diff --git a/SSH/RPM/buildRublonPamRpm.sh b/SSH/RPM/buildRublonPamRpm.sh deleted file mode 100644 index d786dcd..0000000 --- a/SSH/RPM/buildRublonPamRpm.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -#packages for rpm builder -sudo yum install -y gcc rpm-build rpm-devel rpmlint make python bash coreutils diffutils patch rpmdevtools tree -#packages for rublonPam -sudo yum install -y curl-devel openssl-devel pam-devel policycoreutils-python - -#sudo service sshd restart - -#create rpm package struct -rpmdev-setuptree - -cp -R /home/vagrant/Rublon-Linux/SSH/PAM/src /home/vagrant/Rublon-Linux/SSH/RPM/rublonPam-1.0/ -cp -R /home/vagrant/Rublon-Linux/SSH/PAM/lib /home/vagrant/Rublon-Linux/SSH/RPM/rublonPam-1.0/ -cp /home/vagrant/Rublon-Linux/SSH/PAM/rublonPam.c /home/vagrant/Rublon-Linux/SSH/RPM/rublonPam-1.0/rublonPam.c -cp /home/vagrant/Rublon-Linux/SSH/PAM/.config /home/vagrant/Rublon-Linux/SSH/RPM/rublonPam-1.0/.config - -#zip rublonPam source -tar cvzf rublonPam.tar.gz rublonPam-1.0 -#move source and spec file to default rpm package creator -cp rublonPam.tar.gz /home/vagrant/rpmbuild/SOURCES/ -cp rublonPam.spec /home/vagrant/rpmbuild/SPECS/ - -#build rpm package in /home/vagrant/rpmbuild/RPMS -#rpmbuild -v -bb /home/vagrant/rpmbuild/SPECS/rublonPam.spec -rpmbuild -ba /home/vagrant/rpmbuild/SPECS/rublonPam.spec -cp /home/vagrant/rpmbuild/RPMS/x86_64/rublonPam-1.0-1.x86_64.rpm /home/vagrant/Rublon-Linux/SSH/RPM diff --git a/SSH/RPM/login_rublon.te b/SSH/RPM/login_rublon.te deleted file mode 100644 index 98e5a61..0000000 --- a/SSH/RPM/login_rublon.te +++ /dev/null @@ -1,8 +0,0 @@ -module login_rublon 1.0; -require { -type http_port_t; -type http_cache_port_t; -type sshd_t; -class tcp_socket name_connect; -}; -#allow sshd_t {http_port_t http_cache_port_t}:tcp_socket name_connect; diff --git a/SSH/RPM/rublonPam-1.0-1.x86_64.rpm b/SSH/RPM/rublonPam-1.0-1.x86_64.rpm deleted file mode 100644 index 9decd69..0000000 Binary files a/SSH/RPM/rublonPam-1.0-1.x86_64.rpm and /dev/null differ diff --git a/SSH/RPM/rublonPam-1.0/.config b/SSH/RPM/rublonPam-1.0/.config deleted file mode 100644 index 4ede779..0000000 --- a/SSH/RPM/rublonPam-1.0/.config +++ /dev/null @@ -1,4 +0,0 @@ -systemToken= -secretKey= -userDomain= -rublonApiServer=https://core.rublon.net diff --git a/SSH/RPM/rublonPam-1.0/Makefile b/SSH/RPM/rublonPam-1.0/Makefile deleted file mode 100644 index a660a5c..0000000 --- a/SSH/RPM/rublonPam-1.0/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -rublonPam: - sudo gcc -fPIC -fno-stack-protector -std=c99 -c rublonPam.c src/pamApp.c src/coreHandler.c src/signatureWrapper.c lib/cfg_parse.c lib/cJSON.c lib/qrcodegen.c - sudo ld -x --shared -o rublonPam.so -lcurl rublonPam.o pamApp.o coreHandler.o signatureWrapper.o cfg_parse.o cJSON.o qrcodegen.o -clean: - sudo rm /lib64/security/rublonPam.so -install: - sudo cp .config /lib64/security - sudo ld -x --shared -o /lib64/security/rublonPam.so -lcurl rublonPam.o pamApp.o coreHandler.o signatureWrapper.o cfg_parse.o cJSON.o qrcodegen.o -# sudo rm rublonPam.o pamApp.o coreHandler.o signatureWrapper.o cfg_parse.o cJSON.o qrcodegen.o -# sudo checkmodule -M -m -o login_rublon.mod login_rublon.te -# sudo semodule_package -o login_rublon.pp -m login_rublon.mod -# sudo semodule -i login_rublon.pp - - diff --git a/SSH/RPM/rublonPam-1.0/lib/cJSON.c b/SSH/RPM/rublonPam-1.0/lib/cJSON.c deleted file mode 100644 index 77aea0c..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/cJSON.c +++ /dev/null @@ -1,2933 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning (push) -/* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef ENABLE_LOCALES -#include -#endif - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#include "cJSON.h" - -/* define our own boolean type */ -#define true ((cJSON_bool)1) -#define false ((cJSON_bool)0) - -typedef struct { - const unsigned char *json; - size_t position; -} error; -static error global_error = { NULL, 0 }; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) -{ - return (const char*) (global_error.json + global_error.position); -} - -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { - if (!cJSON_IsString(item)) { - return NULL; - } - - return item->valuestring; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 10) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) -{ - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) -{ - if ((string1 == NULL) || (string2 == NULL)) - { - return 1; - } - - if (string1 == string2) - { - return 0; - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks -{ - void *(CJSON_CDECL *allocate)(size_t size); - void (CJSON_CDECL *deallocate)(void *pointer); - void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ -static void * CJSON_CDECL internal_malloc(size_t size) -{ - return malloc(size); -} -static void CJSON_CDECL internal_free(void *pointer) -{ - free(pointer); -} -static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) -{ - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; - -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) -{ - size_t length = 0; - unsigned char *copy = NULL; - - if (string == NULL) - { - return NULL; - } - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) - { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) -{ - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) -{ - cJSON *next = NULL; - while (item != NULL) - { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { - cJSON_Delete(item->child); - } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { - global_hooks.deallocate(item->valuestring); - } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - global_hooks.deallocate(item->string); - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) -{ -#ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct -{ - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { - return false; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if (number >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) -{ - if (number >= INT_MAX) - { - object->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { - object->valueint = INT_MIN; - } - else - { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -typedef struct -{ - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) -{ - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) - { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) - { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) - { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { - newsize = INT_MAX; - } - else - { - return NULL; - } - } - else - { - newsize = needed * 2; - } - - if (p->hooks.reallocate != NULL) - { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } - else - { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) - { - memcpy(newbuffer, p->buffer, p->offset + 1); - } - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) -{ - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26]; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test; - - if (output_buffer == NULL) - { - return false; - } - - /* This checks for NaN and Infinity */ - if ((d * 0) != 0) - { - length = sprintf((char*)number_buffer, "null"); - } - else - { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); - - /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) - { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); - } - } - - /* sprintf failed or buffer overrun occured */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) -{ - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) - { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ - { - return 0; - } - - if (i < 3) - { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) -{ - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { - /* invalid second half of the surrogate pair */ - goto fail; - } - - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } - else if (codepoint < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } - else - { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) - { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) -{ - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else - { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { - goto fail; - } - - switch (input_pointer[1]) - { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - input_buffer->offset = (size_t) (input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if (output != NULL) - { - input_buffer->hooks.deallocate(output); - } - - if (input_pointer != NULL) - { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) -{ - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) - { - return false; - } - - /* empty string */ - if (input == NULL) - { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) - { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { - /* normal character, copy */ - *output_pointer = *input_pointer; - } - else - { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) - { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) -{ - return print_string_ptr((unsigned char*)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL)) - { - return NULL; - } - - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; - } - - if (buffer->offset == buffer->length) - { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { - return NULL; - } - - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { - buffer->offset += 3; - } - - return buffer; -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - cJSON *item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if (value == NULL) - { - goto fail; - } - - buffer.content = (const unsigned char*)value; - buffer.length = strlen((const char*)value) + sizeof(""); - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ - { - goto fail; - } - - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { - goto fail; - } - } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); - } - - return item; - -fail: - if (item != NULL) - { - cJSON_Delete(item); - } - - if (value != NULL) - { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; - - if (buffer.offset < buffer.length) - { - local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { - local_error.position = buffer.length - 1; - } - - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -#define cjson_min(a, b) ((a < b) ? a : b) - -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) -{ - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { - goto fail; - } - - /* print the value */ - if (!print_value(item, buffer)) - { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); - if (printed == NULL) { - goto fail; - } - buffer->buffer = NULL; - } - else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { - goto fail; - } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - } - - return printed; - -fail: - if (buffer->buffer != NULL) - { - hooks->deallocate(buffer->buffer); - } - - if (printed != NULL) - { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) -{ - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) -{ - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if (prebuffer < 0) - { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if (!print_value(item, &p)) - { - global_hooks.deallocate(p.buffer); - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if ((len < 0) || (buf == NULL)) - { - return false; - } - - p.buffer = (unsigned char*)buf; - p.length = (size_t)len; - p.offset = 0; - p.noalloc = true; - p.format = fmt; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) -{ - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { - return parse_string(item, input_buffer); - } - /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { - return parse_number(item, input_buffer); - } - /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { - return parse_array(item, input_buffer); - } - /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) - { - return false; - } - - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (buffer_at_offset(input_buffer)[0] != '[') - { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { - return false; - } - update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ','; - if(output_buffer->format) - { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { - goto fail; /* faile to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) - { - if (output_buffer->format) - { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { - return false; - } - for (i = 0; i < output_buffer->depth; i++) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ':'; - if (output_buffer->format) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - if (current_item->next) - { - *output_pointer++ = ','; - } - - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { - return false; - } - if (output_buffer->format) - { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) -{ - cJSON *child = NULL; - size_t size = 0; - - if (array == NULL) - { - return 0; - } - - child = array->child; - - while(child != NULL) - { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON* get_array_item(const cJSON *array, size_t index) -{ - cJSON *current_child = NULL; - - if (array == NULL) - { - return NULL; - } - - current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) -{ - if (index < 0) - { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) -{ - cJSON *current_element = NULL; - - if ((object == NULL) || (name == NULL)) - { - return NULL; - } - - current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) - { - current_element = current_element->next; - } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { - current_element = current_element->next; - } - } - - if ((current_element == NULL) || (current_element->string == NULL)) { - return NULL; - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) -{ - cJSON *reference = NULL; - if (item == NULL) - { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if (reference == NULL) - { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) -{ - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL)) - { - return false; - } - - child = array->child; - - if (child == NULL) - { - /* list is empty, start new one */ - array->child = item; - } - else - { - /* append to the end */ - while (child->next) - { - child = child->next; - } - suffix_object(child, item); - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - add_item_to_array(array, item); -} - -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void* cast_away_const(const void* string) -{ - return (void*)string; -} -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop -#endif - - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) -{ - char *new_key = NULL; - int new_type = cJSON_Invalid; - - if ((object == NULL) || (string == NULL) || (item == NULL)) - { - return false; - } - - if (constant_key) - { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - if (array == NULL) - { - return; - } - - add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - if ((object == NULL) || (string == NULL)) - { - return; - } - - add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) -{ - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) -{ - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) -{ - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) -{ - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) -{ - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) -{ - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) -{ - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) -{ - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) -{ - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) -{ - if ((parent == NULL) || (item == NULL)) - { - return NULL; - } - - if (item->prev != NULL) - { - /* not the first element */ - item->prev->next = item->next; - } - if (item->next != NULL) - { - /* not the last element */ - item->next->prev = item->prev; - } - - if (item == parent->child) - { - /* first element */ - parent->child = item->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) -{ - if (which < 0) - { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *after_inserted = NULL; - - if (which < 0) - { - return; - } - - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { - add_item_to_array(array, newitem); - return; - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) -{ - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) - { - return false; - } - - if (replacement == item) - { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if (replacement->next != NULL) - { - replacement->next->prev = replacement; - } - if (replacement->prev != NULL) - { - replacement->prev->next = replacement; - } - if (parent->child == item) - { - parent->child = replacement; - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - if (which < 0) - { - return; - } - - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) -{ - if ((replacement == NULL) || (string == NULL)) - { - return false; - } - - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { - cJSON_free(replacement->string); - } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - replacement->type &= ~cJSON_StringIsConst; - - cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = b ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (num <= (double)INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0;a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (strings == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) -{ - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { - goto fail; - } - } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) - { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - goto fail; - } - if (next != NULL) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - - return newitem; - -fail: - if (newitem != NULL) - { - cJSON_Delete(newitem); - } - - return NULL; -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) -{ - unsigned char *into = (unsigned char*)json; - - if (json == NULL) - { - return; - } - - while (*json) - { - if (*json == ' ') - { - json++; - } - else if (*json == '\t') - { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') - { - json++; - } - else if (*json=='\n') - { - json++; - } - else if ((*json == '/') && (json[1] == '/')) - { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) - { - json++; - } - } - else if ((*json == '/') && (json[1] == '*')) - { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) - { - json++; - } - json += 2; - } - else if (*json == '\"') - { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) - { - if (*json == '\\') - { - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else - { - /* All other characters. */ - *into++ = (unsigned char)*json++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) -{ - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) - { - return false; - } - - /* check if type is valid */ - switch (a->type & 0xFF) - { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if (a == b) - { - return true; - } - - switch (a->type & 0xFF) - { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if (a->valuedouble == b->valuedouble) - { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { - return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) - { - return true; - } - - return false; - - case cJSON_Array: - { - cJSON *a_element = a->child; - cJSON *b_element = b->child; - - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: - { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) - { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) - { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) -{ - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void *object) -{ - global_hooks.deallocate(object); -} diff --git a/SSH/RPM/rublonPam-1.0/lib/cJSON.h b/SSH/RPM/rublonPam-1.0/lib/cJSON.h deleted file mode 100644 index 0b05217..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/cJSON.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif - -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol -For *nix builds that support visibility attribute, you can define similar behavior by -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does -*/ - -#define CJSON_CDECL __cdecl -#define CJSON_STDCALL __stdcall - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL -#endif -#else /* !__WINDOWS__ */ -#define CJSON_CDECL -#define CJSON_STDCALL - -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 10 - -#include - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks -{ - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void (CJSON_CDECL *free_fn)(void *ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ -#ifndef CJSON_NESTING_LIMIT -#define CJSON_NESTING_LIMIT 1000 -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* Check if the item is a string and return its valuestring */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); - -/* These utilities create an Array of count items. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); - - -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) - -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ -CJSON_PUBLIC(void *) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void *object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/SSH/RPM/rublonPam-1.0/lib/cfg_parse.c b/SSH/RPM/rublonPam-1.0/lib/cfg_parse.c deleted file mode 100644 index c1738bf..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/cfg_parse.c +++ /dev/null @@ -1,568 +0,0 @@ -#include "cfg_parse.h" - -/* for malloc, EXIT_SUCCESS and _FAILURE, exit */ -#include -/* for FILE*, fgets, fputs */ -#include -/* for memset, strlen, strchr etc */ -#include -/* for tolower, isspace */ -#include - -/* SIZE_MAX */ -#if __STDC_VERSION__ >= 199901L - #include -#elif !defined(SIZE_MAX) - #define SIZE_MAX ((size_t)-1) -#endif - -/* ************************************************************************* */ -/* implementation details of (opaque) config structures */ -/* ************************************************************************* */ - -struct cfg_node -{ - char* key; - char* value; - - struct cfg_node* next; -}; - -struct cfg_struct -{ - struct cfg_node* head; -}; - -/* ************************************************************************* */ -/* Helper functions */ -/* ************************************************************************* */ - -/* A malloc() wrapper which handles null return values */ -static void* cfg_malloc(const size_t size) -{ - void* ptr = - malloc(size); - - if (ptr == NULL) - { - perror("cfg_parse: ERROR: malloc() returned NULL"); - exit(EXIT_FAILURE); - } - - return ptr; -} - -/* Returns a duplicate of input str, without leading / trailing whitespace - Input str *MUST* be null-terminated, or disaster will result */ -static char* cfg_trim(const char* str) -{ - size_t tlen; - char* tstr; - - /* advance start pointer to first non-whitespace char */ - while (isspace(*str)) - str ++; - - /* roll back length until we run out of whitespace */ - tlen = strlen(str); - while (tlen > 0 && isspace(str[tlen - 1])) - tlen --; - - /* copy portion of string to new string */ - tstr = cfg_malloc(tlen + 1); - tstr[tlen] = '\0'; - if (tlen > 0) memcpy(tstr, str, tlen); - - return tstr; -} - -/* Returns a duplicate of input str, without leading / trailing whitespace - Also lowercases the string, AND returns NULL instead of empty str */ -static char* cfg_norm_key(const char* key) -{ - size_t i, tlen; - char* tkey; - - /* advance start pointer to first non-whitespace char */ - while (isspace(*key)) - key ++; - - /* roll back length until we run out of whitespace */ - tlen = strlen(key); - while (tlen > 0 && isspace(key[tlen - 1])) - tlen --; - - /* Exclude empty key */ - if (tlen == 0) return NULL; - - /* copy portion of string to new string */ - tkey = cfg_malloc(tlen + 1); - tkey[tlen] = '\0'; - /* Lowercase key and copy */ - for (i = 0; i < tlen; i++) - tkey[i] = tolower(key[i]); - - return tkey; -} - -/* Creates a node struct with key and value, and returns it */ -static struct cfg_node* cfg_create_node(char* key, char* value) -{ - struct cfg_node* cur = - cfg_malloc(sizeof(struct cfg_node)); - - /* assign key, value */ - cur->key = key; - cur->value = value; - cur->next = NULL; - - return cur; -} - -/* ************************************************************************* */ -/* Public functions */ -/* ************************************************************************* */ - -/** - * This function initializes a cfg_struct, and must be called before - * performing any further operations. - * @return Pointer to newly initialized cfg_struct object. - */ -struct cfg_struct* cfg_init() -{ - struct cfg_struct* cfg = - cfg_malloc(sizeof(struct cfg_struct)); - cfg->head = NULL; - - return cfg; -} - -/** - * This function deletes an entire cfg_struct, clearing any memory - * previously held by the structure. - * @param cfg Pointer to cfg_struct to delete. - */ -void cfg_free(struct cfg_struct* cfg) -{ - struct cfg_node* temp; - - if (cfg == NULL) return; - - while ((temp = cfg->head) != NULL) - { - cfg->head = temp->next; - - free(temp->key); - free(temp->value); - free(temp); - } - - free(cfg); -} - -/** - * This function loads data from a file, and inserts / updates the specified - * cfg_struct. New keys will be inserted. Existing keys will have values - * overwritten by those read from the file. - * The format of config-files is "key=value", with any amount of whitespace. - * Comments can be added, beginning with a # character until end-of-line. - * The maximum line size is CFG_MAX_LINE bytes (see cfg_parse.h) - * @param cfg Pointer to cfg_struct to update. - * @param filename String containing filename to open and parse. - * @return EXIT_SUCCESS (0) on success, or EXIT_FAILURE if file could not be - * opened. - */ -int cfg_load(struct cfg_struct* cfg, const char* filename) -{ - FILE* fp; - char* delim; - char buffer[CFG_MAX_LINE + 1]; - - /* safety check: null input */ - if (cfg == NULL || filename == NULL) return EXIT_FAILURE; - - /* open file for reading */ - fp = fopen(filename, "r"); - if (fp == NULL) return EXIT_FAILURE; - - while (!feof(fp)) - { - if (fgets(buffer, CFG_MAX_LINE + 1, fp) != NULL) - { - /* locate first # sign and terminate string there (comment) */ - delim = strchr(buffer, '#'); - if (delim != NULL) *delim = '\0'; - - /* locate first = sign and prepare to split */ - delim = strchr(buffer, '='); - if (delim != NULL) - { - *delim = '\0'; - delim ++; - - cfg_set(cfg, buffer, delim); - } - /* else: seems to be an invalid line */ - } - /* else: read error */ - } - - fclose(fp); - return EXIT_SUCCESS; -} - -/** - * This function saves a complete cfg_struct to a file. - * Comments are not preserved. - * @param cfg Pointer to cfg_struct to save. - * @param filename String containing filename to open and parse. - * @return EXIT_SUCCESS (0) on success, or EXIT_FAILURE if file could not be - * opened or a write error occurred. - */ -int cfg_save(const struct cfg_struct* cfg, const char* filename) -{ - FILE* fp; - struct cfg_node* cur; - - /* safety check: null input */ - if (cfg == NULL || filename == NULL) return EXIT_FAILURE; - - /* open output file for writing */ - fp = fopen(filename, "w"); - if (fp == NULL) return EXIT_FAILURE; - - /* point at first item in list */ - cur = cfg->head; - /* step through the list, dumping each key-value pair to disk */ - while (cur != NULL) - { - if (fputs(cur->key, fp) == EOF || - fputc('=', fp) == EOF || - fputs(cur->value, fp) == EOF || - fputc('\n', fp) == EOF) - { - fclose(fp); - return EXIT_FAILURE; - } - - cur = cur->next; - } - - fclose(fp); - return EXIT_SUCCESS; -} - -/** - * This function performs a key-lookup on a cfg_struct, and returns the - * associated value. - * @param cfg Pointer to cfg_struct to search. - * @param key String containing key to search for. - * @return String containing associated value, or NULL if key was not found. - */ -const char* cfg_get(const struct cfg_struct* cfg, const char* key) -{ - char* tkey; - struct cfg_node* cur; - - /* safety check: null input */ - if (cfg == NULL || cfg->head == NULL || key == NULL) return NULL; - - /* Trim input search key */ - tkey = cfg_norm_key(key); - /* Exclude empty key */ - if (tkey == NULL) return NULL; - - /* set up pointer to start of list */ - cur = cfg->head; - /* loop through linked list looking for match on key - if found, free search key, return the value */ - do - { - if (strcmp(tkey, cur->key) == 0) - { - free(tkey); - return cur->value; - } - } while ((cur = cur->next) != NULL); - - free(tkey); - return NULL; -} - -/** - * Returns an array of strings, one for each key in the config struct. - * This array and its contents are dynamically allocated: the caller - * should free them when done. - * @param cfg Pointer to cfg_struct to retrieve keys from. - * @param count Output parameter: number of keys in the returned array. - * @return Array of (count) strings, one for each key in the struct, or NULL - * in case of error or empty struct. - */ -char** cfg_get_keys(const struct cfg_struct* cfg, size_t* count) -{ - size_t i; - char** keys; - struct cfg_node* cur; - - /* safety check: null input */ - if (cfg == NULL || cfg->head == NULL) return NULL; - - /* walk the list to count how many keys we have available */ - i = 0; - for (cur = cfg->head; cur != NULL; cur = cur->next) - i ++; - - /* now create the array to hold them all */ - if (SIZE_MAX / sizeof(char*) < i) return NULL; - keys = cfg_malloc(i * sizeof(char*)); - - /* walk the list again, this time allocating and copying each key */ - cur = cfg->head; - for (*count = 0; *count < i; (*count) ++) - { - /* create space to hold the key, and copy it over */ - keys[*count] = cfg_malloc(strlen(cur->key) + 1); - strcpy(keys[*count], cur->key); - cur = cur->next; - } - - return keys; -} - -/** - * This function sets a single key-value pair in a cfg_struct. - * If the key already exists, its value will be updated. - * If not, a new item is added to the cfg_struct list. - * For convenience, a NULL value is treated as a call to cfg_delete(). - * @param cfg Pointer to cfg_struct to search. - * @param key String containing key to search for. - * @param value String containing new value to assign to key. - */ -void cfg_set(struct cfg_struct* cfg, const char* key, const char* value) -{ - char* tkey; - char* tvalue; - - struct cfg_node* cur; - - /* Treat NULL value as a "delete" operation */ - if (value == NULL) - { - cfg_delete(cfg, key); - return; - } - - /* safety check: null input */ - if (cfg == NULL || key == NULL) return; - - /* Trim input search key */ - tkey = cfg_norm_key(key); - /* Exclude empty key */ - if (tkey == NULL) return; - - /* Trim value. */ - tvalue = cfg_trim(value); - - if (cfg->head == NULL) - { - /* list was empty to begin with */ - cfg->head = cfg_create_node(tkey, tvalue); - } else { - struct cfg_node* prev; - - /* search list for existing key */ - cur = cfg->head; - do - { - if (strcmp(tkey, cur->key) == 0) - { - /* found a match: no longer need cur key */ - free(tkey); - - /* update value */ - free(cur->value); - cur->value = tvalue; - return; - } - prev = cur; - } while ((cur = cur->next) != NULL); - - /* not found: create new element and append it */ - prev->next = cfg_create_node(tkey, tvalue); - } -} - -/** - * This function sets multiple key-value pairs in a cfg_struct. - * @param cfg Pointer to cfg_struct to search. - * @param keys Array of strings containing key to search for. - * @param values Array of strings containing new value to assign to key. - * @param count Length of keys / values arrays - */ -void cfg_set_array(struct cfg_struct* cfg, const char* keys[], const char* values[], const size_t count) -{ - size_t i; - - /* safety check: null input */ - if (cfg == NULL || keys == NULL || values == NULL || count == 0) return; - - /* Call cfg_set on every item in the lists */ - for (i = 0; i < count; i ++) - cfg_set(cfg, keys[i], values[i]); -} - -/** - * This function deletes a key-value pair from a cfg_struct. - * If the key does not exist, the function does nothing. - * @param cfg Pointer to cfg_struct to search. - * @param key String containing key to search for. - */ -void cfg_delete(struct cfg_struct* cfg, const char* key) -{ - char* tkey; - struct cfg_node* cur; - struct cfg_node* prev; - - /* safety check: null input */ - if (cfg == NULL || cfg->head == NULL || key == NULL) return; - - /* Trim input search key */ - tkey = cfg_norm_key(key); - /* Exclude empty key */ - if (tkey == NULL) return; - - /* search list for existing key */ - cur = cfg->head; - do - { - if (strcmp(tkey, cur->key) == 0) - { - /* found it - cleanup trimmed key */ - free(tkey); - - if (cur == cfg->head) - { - /* first element */ - cfg->head = cur->next; - } else { - /* splice out element */ - prev->next = cur->next; - } - - /* delete element */ - free(cur->value); - free(cur->key); - free(cur); - - return; - } - - prev = cur; - } while ((cur = cur->next) != NULL); - /* not found */ - - /* cleanup trimmed key */ - free(tkey); -} - -/** - * This function deletes multiple key-value pairs from a cfg_struct. - * @param cfg Pointer to cfg_struct to search. - * @param keys Array of strings containing key to search for. - * @param count Length of keys array - */ -void cfg_delete_array(struct cfg_struct* cfg, const char* keys[], const size_t count) -{ - size_t i; - - /* safety check: null input */ - if (cfg == NULL || cfg->head == NULL || keys == NULL || count == 0) return; - - /* Call cfg_delete on every item in the list */ - for (i = 0; i < count; i ++) - cfg_delete(cfg, keys[i]); -} - -/** - * This function performs the inverse of cfg_delete_array(). - * Instead of deleting entries from cfg which match keys[], - * this will KEEP only those entries that match keys[]. - * It can be used to keep a config file tidy between versions or - * after user edits. - * @param cfg Pointer to cfg_struct to search. - * @param keys Array of strings containing keys to keep - * @param count Length of keys array - */ -void cfg_prune(struct cfg_struct* cfg, const char* keys[], const size_t count) -{ - char** tkeys; - size_t i, j; - - struct cfg_node* cur; - struct cfg_node* prev; - - /* safety check: null input */ - if (cfg == NULL || cfg->head == NULL || keys == NULL || count == 0 || - SIZE_MAX / sizeof(char*) < count) return; - - /* First we must prep every key in keys[] using the normalize function. */ - tkeys = cfg_malloc(count * sizeof(char*)); - - j = 0; - for (i = 0; i < count; i ++) - { - char *tkey; - - if (keys[i] == NULL) continue; - tkey = cfg_norm_key(keys[i]); - if (tkey == NULL) continue; - - tkeys[j] = tkey; - j ++; - } - - if (j == 0) - { - free(tkeys); - return; - } - - /* Now iterate through the cfg struct and test every entry */ - cur = cfg->head; - do - { - for (i = 0; i < j; i ++) - if (strcmp(tkeys[i], cur->key) == 0) - break; - - if (i == j) - { - /* Didn't find a key match - delete this */ - free(cur->value); - free(cur->key); - - if (cur == cfg->head) - { - /* first element */ - cfg->head = cur->next; - free(cur); - cur = cfg->head; - } else { - /* splice out element */ - prev->next = cur->next; - free(cur); - cur = prev->next; - } - } else { - /* matched, advance list element */ - prev = cur; - cur = cur->next; - } - } while (cur != NULL); - - /* Cleanup all our trimmed keys */ - for (i = 0; i < j; i ++) - free(tkeys[i]); - free(tkeys); -} - diff --git a/SSH/RPM/rublonPam-1.0/lib/cfg_parse.h b/SSH/RPM/rublonPam-1.0/lib/cfg_parse.h deleted file mode 100644 index 2d175aa..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/cfg_parse.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @file - * @brief Header file for cfg_parse. - * - * This file should be included to use any features of cfg_parse. Typically, a - * user should create a pointer to a cfg_struct, initialize it with cfg_init(), - * and then perform actions on that object (lookup, add, delete) by passing the - * pointer to the functions here. - * At end of use, call cfg_delete to clean up the object. - */ -#ifndef CFG_PARSE_H_ -#define CFG_PARSE_H_ - -#include - -/** - * @brief Sets the maximum size of a line in a configuration file. - * - * cfg_load uses this definition to limit the size of its read buffer. - * Lines which exceed the length do not crash outright, but probably won't - * load correctly. - */ -#define CFG_MAX_LINE 256 - -/* Opaque data structure holding config in memory */ -struct cfg_struct; - -/* Declare C-style name mangling, - this makes mixing with c++ compilers possible */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Creates a cfg_struct. - */ -struct cfg_struct* cfg_init(); - -/** - * @brief Frees a cfg_struct. - */ -void cfg_free(struct cfg_struct* cfg); - -/** - * @brief Loads key=value pairs from a file into cfg_struct. - */ -int cfg_load(struct cfg_struct* cfg, const char* filename); - -/** - * @brief Saves a cfg_struct to a file as key=value pairs. - */ -int cfg_save(const struct cfg_struct* cfg, const char* filename); - -/** - * @brief Retrieves a value from a cfg_struct for a specified key. - */ -const char* cfg_get(const struct cfg_struct* cfg, const char* key); - -/** - * @brief Retrieves a list of all keys in a cfg_struct. - */ -char** cfg_get_keys(const struct cfg_struct* cfg, size_t* count); - -/** - * @brief Sets a key, value pair in a cfg_struct. - */ -void cfg_set(struct cfg_struct* cfg, const char* key, const char* value); - -/** - * @brief Sets multiple key, value pairs in a cfg_struct. - */ -void cfg_set_array(struct cfg_struct* cfg, const char* keys[], const char* values[], size_t count); - -/** - * @brief Deletes a key (and associated value) from a cfg_struct. - */ -void cfg_delete(struct cfg_struct* cfg, const char* key); - -/** - * @brief Deletes multiple keys (and associated values) from a cfg_struct. - */ -void cfg_delete_array(struct cfg_struct* cfg, const char* keys[], size_t count); - -/** - * @brief Deletes all entries not found in keys[] from a cfg_struct. - */ -void cfg_prune(struct cfg_struct* cfg, const char* keys[], size_t count); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/SSH/RPM/rublonPam-1.0/lib/qrcodegen.c b/SSH/RPM/rublonPam-1.0/lib/qrcodegen.c deleted file mode 100644 index d239c31..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/qrcodegen.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * QR Code generator library (C) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#include -#include -#include -#include -#include "qrcodegen.h" - -#ifndef QRCODEGEN_TEST - #define testable static // Keep functions private -#else - #define testable // Expose private functions -#endif - - -/*---- Forward declarations for private functions ----*/ - -// Regarding all public and private functions defined in this source file: -// - They require all pointer/array arguments to be not null unless the array length is zero. -// - They only read input scalar/array arguments, write to output pointer/array -// arguments, and return scalar values; they are "pure" functions. -// - They don't read mutable global variables or write to any global variables. -// - They don't perform I/O, read the clock, print to console, etc. -// - They allocate a small and constant amount of stack memory. -// - They don't allocate or free any memory on the heap. -// - They don't recurse or mutually recurse. All the code -// could be inlined into the top-level public functions. -// - They run in at most quadratic time with respect to input arguments. -// Most functions run in linear time, and some in constant time. -// There are no unbounded loops or non-obvious termination conditions. -// - They are completely thread-safe if the caller does not give the -// same writable buffer to concurrent calls to these functions. - -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); - -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); -testable int getNumRawDataModules(int ver); - -testable void calcReedSolomonGenerator(int degree, uint8_t result[]); -testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]); -testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y); - -testable void initializeFunctionModules(int version, uint8_t qrcode[]); -static void drawWhiteFunctionModules(uint8_t qrcode[], int version); -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); -testable int getAlignmentPatternPositions(int version, uint8_t result[7]); -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); - -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); -static long getPenaltyScore(const uint8_t qrcode[]); -static void addRunToHistory(unsigned char run, unsigned char history[7]); -static bool hasFinderLikePattern(const unsigned char runHistory[7]); - -testable bool getModule(const uint8_t qrcode[], int x, int y); -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); -static bool getBit(int x, int i); - -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); -static int numCharCountBits(enum qrcodegen_Mode mode, int version); - - - -/*---- Private tables of constants ----*/ - -// The set of all legal characters in alphanumeric mode, where each character -// value maps to the index in the string. For checking text and encoding segments. -static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; - -// For generating error correction codes. -testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High -}; - -#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above - -// For generating error correction codes. -testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High -}; - -// For automatic mask pattern selection. -static const int PENALTY_N1 = 3; -static const int PENALTY_N2 = 3; -static const int PENALTY_N3 = 40; -static const int PENALTY_N4 = 10; - - - -/*---- High-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - size_t i; - size_t textLen = strlen(text); - if (textLen == 0) - return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); - - struct qrcodegen_Segment seg; - if (qrcodegen_isNumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeNumeric(text, tempBuffer); - } else if (qrcodegen_isAlphanumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeAlphanumeric(text, tempBuffer); - } else { - if (textLen > bufLen) - goto fail; - for (i = 0; i < textLen; i++) - tempBuffer[i] = (uint8_t)text[i]; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, textLen); - if (seg.bitLength == -1) - goto fail; - seg.numChars = (int)textLen; - seg.data = tempBuffer; - } - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - -fail: - qrcode[0] = 0; // Set size to invalid value for safety - return false; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - struct qrcodegen_Segment seg; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); - if (seg.bitLength == -1) { - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - seg.numChars = (int)dataLen; - seg.data = dataAndTemp; - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); -} - - -// Appends the given number of low-order bits of the given value to the given byte-based -// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { - int i; - assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); - for (i = numBits - 1; i >= 0; i--, (*bitLen)++) - buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); -} - - - -/*---- Low-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { - return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, - qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { - - int i,j; - uint8_t padByte; - size_t k; - assert(segs != NULL || len == 0); - assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); - assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); - - // Find the minimal version number to use - int version, dataUsedBits; - for (version = minVersion; ; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = getTotalBits(segs, len, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - break; // This version number is found to be suitable - if (version >= maxVersion) { // All versions in the range could not fit the given data - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - } - assert(dataUsedBits != -1); - - // Increase the error correction level while the data still fits in the current version number - for (i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) - ecl = (enum qrcodegen_Ecc)i; - } - - // Concatenate all segments to create the data bit string - memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); - int bitLen = 0; - for (k = 0; k < len; k++) { - const struct qrcodegen_Segment *seg = &segs[k]; - appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen); - appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); - for (j = 0; j < seg->bitLength; j++) - appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen); - } - assert(bitLen == dataUsedBits); - - // Add terminator and pad up to a byte if applicable - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; - assert(bitLen <= dataCapacityBits); - int terminatorBits = dataCapacityBits - bitLen; - if (terminatorBits > 4) - terminatorBits = 4; - appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); - appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); - assert(bitLen % 8 == 0); - - // Pad with alternating bytes until data capacity is reached - for (padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) - appendBitsToBuffer(padByte, 8, qrcode, &bitLen); - - // Draw function and data codeword modules - addEccAndInterleave(qrcode, version, ecl, tempBuffer); - initializeFunctionModules(version, qrcode); - drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); - drawWhiteFunctionModules(qrcode, version); - initializeFunctionModules(version, tempBuffer); - - // Handle masking - if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask - long minPenalty = LONG_MAX; - for (i = 0; i < 8; i++) { - enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; - applyMask(tempBuffer, qrcode, msk); - drawFormatBits(ecl, msk, qrcode); - long penalty = getPenaltyScore(qrcode); - if (penalty < minPenalty) { - mask = msk; - minPenalty = penalty; - } - applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR - } - } - assert(0 <= (int)mask && (int)mask <= 7); - applyMask(tempBuffer, qrcode, mask); - drawFormatBits(ecl, mask, qrcode); - return true; -} - - - -/*---- Error correction code generation functions ----*/ - -// Appends error correction bytes to each block of the given data array, then interleaves -// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains -// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will -// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { - int i,j,k; - // Calculate parameter numbers - assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; - int rawCodewords = getNumRawDataModules(version) / 8; - int dataLen = getNumDataCodewords(version, ecl); - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; - - // Split data into blocks, calculate ECC, and interleave - // (not concatenate) the bytes into a single sequence - uint8_t generator[qrcodegen_REED_SOLOMON_DEGREE_MAX]; - calcReedSolomonGenerator(blockEccLen, generator); - const uint8_t *dat = data; - for (i = 0; i < numBlocks; i++) { - int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); - uint8_t *ecc = &data[dataLen]; // Temporary storage - calcReedSolomonRemainder(dat, datLen, generator, blockEccLen, ecc); - for (j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data - if (j == shortBlockDataLen) - k -= numShortBlocks; - result[k] = dat[j]; - } - for (j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC - result[k] = ecc[j]; - dat += datLen; - } -} - - -// Returns the number of 8-bit codewords that can be used for storing data (not ECC), -// for the given version number and error correction level. The result is in the range [9, 2956]. -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { - int v = version, e = (int)ecl; - assert(0 <= e && e < 4); - return getNumRawDataModules(v) / 8 - - ECC_CODEWORDS_PER_BLOCK [e][v] - * NUM_ERROR_CORRECTION_BLOCKS[e][v]; -} - - -// Returns the number of data bits that can be stored in a QR Code of the given version number, after -// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. -// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. -testable int getNumRawDataModules(int ver) { - assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); - int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - int numAlign = ver / 7 + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - return result; -} - - - -/*---- Reed-Solomon ECC generator functions ----*/ - -// Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree]. -testable void calcReedSolomonGenerator(int degree, uint8_t result[]) { - int i,j; - // Start with the monomial x^0 - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, degree * sizeof(result[0])); - result[degree - 1] = 1; - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // drop the highest term, and store the rest of the coefficients in order of descending powers. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint8_t root = 1; - for (i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (j = 0; j < degree; j++) { - result[j] = finiteFieldMultiply(result[j], root); - if (j + 1 < degree) - result[j] ^= result[j + 1]; - } - root = finiteFieldMultiply(root, 0x02); - } -} - - -// Calculates the remainder of the polynomial data[0 : dataLen] when divided by the generator[0 : degree], where all -// polynomials are in big endian and the generator has an implicit leading 1 term, storing the result in result[0 : degree]. -testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]) { - int i,j; - // Perform polynomial division - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, degree * sizeof(result[0])); - for (i = 0; i < dataLen; i++) { - uint8_t factor = data[i] ^ result[0]; - memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0])); - result[degree - 1] = 0; - for (j = 0; j < degree; j++) - result[j] ^= finiteFieldMultiply(generator[j], factor); - } -} - -#undef qrcodegen_REED_SOLOMON_DEGREE_MAX - - -// Returns the product of the two given field elements modulo GF(2^8/0x11D). -// All inputs are valid. This could be implemented as a 256*256 lookup table. -testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y) { - int i; - // Russian peasant multiplication - uint8_t z = 0; - for (i = 7; i >= 0; i--) { - z = (z << 1) ^ ((z >> 7) * 0x11D); - z ^= ((y >> i) & 1) * x; - } - return z; -} - - - -/*---- Drawing function modules ----*/ - -// Clears the given QR Code grid with white modules for the given -// version's size, then marks every function module as black. -testable void initializeFunctionModules(int version, uint8_t qrcode[]) { - int i,j; - // Initialize QR Code - int qrsize = version * 4 + 17; - memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); - qrcode[0] = (uint8_t)qrsize; - - // Fill horizontal and vertical timing patterns - fillRectangle(6, 0, 1, qrsize, qrcode); - fillRectangle(0, 6, qrsize, 1, qrcode); - - // Fill 3 finder patterns (all corners except bottom right) and format bits - fillRectangle(0, 0, 9, 9, qrcode); - fillRectangle(qrsize - 8, 0, 8, 9, qrcode); - fillRectangle(0, qrsize - 8, 9, 8, qrcode); - - // Fill numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (i = 0; i < numAlign; i++) { - for (j = 0; j < numAlign; j++) { - // Don't draw on the three finder corners - if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) - fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); - } - } - - // Fill version blocks - if (version >= 7) { - fillRectangle(qrsize - 11, 0, 3, 6, qrcode); - fillRectangle(0, qrsize - 11, 6, 3, qrcode); - } -} - - -// Draws white function modules and possibly some black modules onto the given QR Code, without changing -// non-function modules. This does not draw the format bits. This requires all function modules to be previously -// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. -static void drawWhiteFunctionModules(uint8_t qrcode[], int version) { - int i,j,dx,dy; - // Draw horizontal and vertical timing patterns - int qrsize = qrcodegen_getSize(qrcode); - for (i = 7; i < qrsize - 7; i += 2) { - setModule(qrcode, 6, i, false); - setModule(qrcode, i, 6, false); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - for (dy = -4; dy <= 4; dy++) { - for (dx = -4; dx <= 4; dx++) { - int dist = abs(dx); - if (abs(dy) > dist) - dist = abs(dy); - if (dist == 2 || dist == 4) { - setModuleBounded(qrcode, 3 + dx, 3 + dy, false); - setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); - setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); - } - } - } - - // Draw numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (i = 0; i < numAlign; i++) { - for (j = 0; j < numAlign; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) - continue; // Don't draw on the three finder corners - for (dy = -1; dy <= 1; dy++) { - for (dx = -1; dx <= 1; dx++) - setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); - } - } - } - - // Draw version blocks - if (version >= 7) { - // Calculate error correction code and pack bits - int rem = version; // version is uint6, in the range [7, 40] - for (i = 0; i < 12; i++) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - long bits = (long)version << 12 | rem; // uint18 - assert(bits >> 18 == 0); - - // Draw two copies - for (i = 0; i < 6; i++) { - for (j = 0; j < 3; j++) { - int k = qrsize - 11 + j; - setModule(qrcode, k, i, (bits & 1) != 0); - setModule(qrcode, i, k, (bits & 1) != 0); - bits >>= 1; - } - } - } -} - - -// Draws two copies of the format bits (with its own error correction code) based -// on the given mask and error correction level. This always draws all modules of -// the format bits, unlike drawWhiteFunctionModules() which might skip black modules. -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { - int i; - // Calculate error correction code and pack bits - assert(0 <= (int)mask && (int)mask <= 7); - static const int table[] = {1, 0, 3, 2}; - int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 - int rem = data; - for (i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - int bits = (data << 10 | rem) ^ 0x5412; // uint15 - assert(bits >> 15 == 0); - - // Draw first copy - for (i = 0; i <= 5; i++) - setModule(qrcode, 8, i, getBit(bits, i)); - setModule(qrcode, 8, 7, getBit(bits, 6)); - setModule(qrcode, 8, 8, getBit(bits, 7)); - setModule(qrcode, 7, 8, getBit(bits, 8)); - for (i = 9; i < 15; i++) - setModule(qrcode, 14 - i, 8, getBit(bits, i)); - - // Draw second copy - int qrsize = qrcodegen_getSize(qrcode); - for (i = 0; i < 8; i++) - setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); - for (i = 8; i < 15; i++) - setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); - setModule(qrcode, 8, qrsize - 8, true); // Always black -} - - -// Calculates and stores an ascending list of positions of alignment patterns -// for this version number, returning the length of the list (in the range [0,7]). -// Each position is in the range [0,177), and are used on both the x and y axes. -// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. -testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { - int i, pos; - if (version == 1) - return 0; - int numAlign = version / 7 + 2; - int step = (version == 32) ? 26 : - (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; - for (i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) - result[i] = pos; - result[0] = 6; - return numAlign; -} - - -// Sets every pixel in the range [left : left + width] * [top : top + height] to black. -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { - int dx,dy; - for (dy = 0; dy < height; dy++) { - for (dx = 0; dx < width; dx++) - setModule(qrcode, left + dx, top + dy, true); - } -} - - - -/*---- Drawing data modules and masking ----*/ - -// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of -// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { - int right,vert,j; - int qrsize = qrcodegen_getSize(qrcode); - int i = 0; // Bit index into the data - // Do the funny zigzag scan - for (right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) - right = 5; - for (vert = 0; vert < qrsize; vert++) { // Vertical counter - for (j = 0; j < 2; j++) { - int x = right - j; // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate - if (!getModule(qrcode, x, y) && i < dataLen * 8) { - bool black = getBit(data[i >> 3], 7 - (i & 7)); - setModule(qrcode, x, y, black); - i++; - } - // If this QR Code has any remainder bits (0 to 7), they were assigned as - // 0/false/white by the constructor and are left unchanged by this method - } - } - } - assert(i == dataLen * 8); -} - - -// XORs the codeword modules in this QR Code with the given mask pattern. -// The function modules must be marked and the codeword bits must be drawn -// before masking. Due to the arithmetic of XOR, calling applyMask() with -// the same mask value a second time will undo the mask. A final well-formed -// QR Code needs exactly one (not zero, two, etc.) mask applied. -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { - int x,y; - assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO - int qrsize = qrcodegen_getSize(qrcode); - for (y = 0; y < qrsize; y++) { - for (x = 0; x < qrsize; x++) { - if (getModule(functionModules, x, y)) - continue; - bool invert; - switch ((int)mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: assert(false); return; - } - bool val = getModule(qrcode, x, y); - setModule(qrcode, x, y, val ^ invert); - } - } -} - - -// Calculates and returns the penalty score based on state of the given QR Code's current modules. -// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. -static long getPenaltyScore(const uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - long result = 0; - int x,y; - // Adjacent modules in row having same color, and finder-like patterns - for (y = 0; y < qrsize; y++) { - unsigned char runHistory[7] = {0}; - bool color = false; - unsigned char runX = 0; - for (x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y) == color) { - runX++; - if (runX == 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - addRunToHistory(runX, runHistory); - if (!color && hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - color = getModule(qrcode, x, y); - runX = 1; - } - } - addRunToHistory(runX, runHistory); - if (color) - addRunToHistory(0, runHistory); // Dummy run of white - if (hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - } - // Adjacent modules in column having same color, and finder-like patterns - for (x = 0; x < qrsize; x++) { - unsigned char runHistory[7] = {0}; - bool color = false; - unsigned char runY = 0; - for (y = 0; y < qrsize; y++) { - if (getModule(qrcode, x, y) == color) { - runY++; - if (runY == 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - addRunToHistory(runY, runHistory); - if (!color && hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - color = getModule(qrcode, x, y); - runY = 1; - } - } - addRunToHistory(runY, runHistory); - if (color) - addRunToHistory(0, runHistory); // Dummy run of white - if (hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - } - - // 2*2 blocks of modules having same color - for (y = 0; y < qrsize - 1; y++) { - for (x = 0; x < qrsize - 1; x++) { - bool color = getModule(qrcode, x, y); - if ( color == getModule(qrcode, x + 1, y) && - color == getModule(qrcode, x, y + 1) && - color == getModule(qrcode, x + 1, y + 1)) - result += PENALTY_N2; - } - } - - // Balance of black and white modules - int black = 0; - for (y = 0; y < qrsize; y++) { - for (x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y)) - black++; - } - } - int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 - // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% - int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; - result += k * PENALTY_N4; - return result; -} - - -// Inserts the given value to the front of the given array, which shifts over the -// existing values and deletes the last value. A helper function for getPenaltyScore(). -static void addRunToHistory(unsigned char run, unsigned char history[7]) { - memmove(&history[1], &history[0], 6 * sizeof(history[0])); - history[0] = run; -} - - -// Tests whether the given run history has the pattern of ratio 1:1:3:1:1 in the middle, and -// surrounded by at least 4 on either or both ends. A helper function for getPenaltyScore(). -// Must only be called immediately after a run of white modules has ended. -static bool hasFinderLikePattern(const unsigned char runHistory[7]) { - unsigned char n = runHistory[1]; - // The maximum QR Code size is 177, hence the run length n <= 177. - // Arithmetic is promoted to int, so n*4 will not overflow. - return n > 0 && runHistory[2] == n && runHistory[4] == n && runHistory[5] == n - && runHistory[3] == n * 3 && (runHistory[0] >= n * 4 || runHistory[6] >= n * 4); -} - - - -/*---- Basic QR Code information ----*/ - -// Public function - see documentation comment in header file. -int qrcodegen_getSize(const uint8_t qrcode[]) { - assert(qrcode != NULL); - int result = qrcode[0]; - assert((qrcodegen_VERSION_MIN * 4 + 17) <= result - && result <= (qrcodegen_VERSION_MAX * 4 + 17)); - return result; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { - assert(qrcode != NULL); - int qrsize = qrcode[0]; - return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); -} - - -// Gets the module at the given coordinates, which must be in bounds. -testable bool getModule(const uint8_t qrcode[], int x, int y) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - return getBit(qrcode[(index >> 3) + 1], index & 7); -} - - -// Sets the module at the given coordinates, which must be in bounds. -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - int bitIndex = index & 7; - int byteIndex = (index >> 3) + 1; - if (isBlack) - qrcode[byteIndex] |= 1 << bitIndex; - else - qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; -} - - -// Sets the module at the given coordinates, doing nothing if out of bounds. -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - if (0 <= x && x < qrsize && 0 <= y && y < qrsize) - setModule(qrcode, x, y, isBlack); -} - - -// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. -static bool getBit(int x, int i) { - return ((x >> i) & 1) != 0; -} - - - -/*---- Segment handling ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_isAlphanumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_isNumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (*text < '0' || *text > '9') - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { - int temp = calcSegmentBitLength(mode, numChars); - if (temp == -1) - return SIZE_MAX; - assert(0 <= temp && temp <= INT16_MAX); - return ((size_t)temp + 7) / 8; -} - - -// Returns the number of data bits needed to represent a segment -// containing the given number of characters using the given mode. Notes: -// - Returns -1 on failure, i.e. numChars > INT16_MAX or -// the number of needed bits exceeds INT16_MAX (i.e. 32767). -// - Otherwise, all valid results are in the range [0, INT16_MAX]. -// - For byte mode, numChars measures the number of bytes, not Unicode code points. -// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. -// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { - // All calculations are designed to avoid overflow on all platforms - if (numChars > (unsigned int)INT16_MAX) - return -1; - long result = (long)numChars; - if (mode == qrcodegen_Mode_NUMERIC) - result = (result * 10 + 2) / 3; // ceil(10/3 * n) - else if (mode == qrcodegen_Mode_ALPHANUMERIC) - result = (result * 11 + 1) / 2; // ceil(11/2 * n) - else if (mode == qrcodegen_Mode_BYTE) - result *= 8; - else if (mode == qrcodegen_Mode_KANJI) - result *= 13; - else if (mode == qrcodegen_Mode_ECI && numChars == 0) - result = 3 * 8; - else { // Invalid argument - assert(false); - return -1; - } - assert(result >= 0); - if (result > INT16_MAX) - return -1; - return (int)result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { - assert(data != NULL || len == 0); - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_BYTE; - result.bitLength = calcSegmentBitLength(result.mode, len); - assert(result.bitLength != -1); - result.numChars = (int)len; - if (len > 0) - memcpy(buf, data, len * sizeof(buf[0])); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { - assert(digits != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(digits); - result.mode = qrcodegen_Mode_NUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *digits != '\0'; digits++) { - char c = *digits; - assert('0' <= c && c <= '9'); - accumData = accumData * 10 + (unsigned int)(c - '0'); - accumCount++; - if (accumCount == 3) { - appendBitsToBuffer(accumData, 10, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 or 2 digits remaining - appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { - assert(text != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(text); - result.mode = qrcodegen_Mode_ALPHANUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *text != '\0'; text++) { - const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); - assert(temp != NULL); - accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); - accumCount++; - if (accumCount == 2) { - appendBitsToBuffer(accumData, 11, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 character remaining - appendBitsToBuffer(accumData, 6, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_ECI; - result.numChars = 0; - result.bitLength = 0; - if (assignVal < 0) - assert(false); - else if (assignVal < (1 << 7)) { - memset(buf, 0, 1 * sizeof(buf[0])); - appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); - } else if (assignVal < (1 << 14)) { - memset(buf, 0, 2 * sizeof(buf[0])); - appendBitsToBuffer(2, 2, buf, &result.bitLength); - appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); - } else if (assignVal < 1000000L) { - memset(buf, 0, 3 * sizeof(buf[0])); - appendBitsToBuffer(6, 3, buf, &result.bitLength); - appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); - appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); - } else - assert(false); - result.data = buf; - return result; -} - - -// Calculates the number of bits needed to encode the given segments at the given version. -// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too -// many characters to fit its length field, or the total bits exceeds INT16_MAX. -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { - size_t i; - assert(segs != NULL || len == 0); - long result = 0; - for (i = 0; i < len; i++) { - int numChars = segs[i].numChars; - int bitLength = segs[i].bitLength; - assert(0 <= numChars && numChars <= INT16_MAX); - assert(0 <= bitLength && bitLength <= INT16_MAX); - int ccbits = numCharCountBits(segs[i].mode, version); - assert(0 <= ccbits && ccbits <= 16); - if (numChars >= (1L << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + bitLength; - if (result > INT16_MAX) - return -1; // The sum might overflow an int type - } - assert(0 <= result && result <= INT16_MAX); - return (int)result; -} - - -// Returns the bit width of the character count field for a segment in the given mode -// in a QR Code at the given version number. The result is in the range [0, 16]. -static int numCharCountBits(enum qrcodegen_Mode mode, int version) { - assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int i = (version + 7) / 17; - switch (mode) { - case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } - case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } - case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } - case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } - case qrcodegen_Mode_ECI : return 0; - default: assert(false); return -1; // Dummy value - } -} diff --git a/SSH/RPM/rublonPam-1.0/lib/qrcodegen.h b/SSH/RPM/rublonPam-1.0/lib/qrcodegen.h deleted file mode 100644 index e419ff6..0000000 --- a/SSH/RPM/rublonPam-1.0/lib/qrcodegen.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * QR Code generator library (C) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#pragma once - -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * This library creates QR Code symbols, which is a type of two-dimension barcode. - * Invented by Denso Wave and described in the ISO/IEC 18004 standard. - * A QR Code structure is an immutable square grid of black and white cells. - * The library provides functions to create a QR Code from text or binary data. - * The library covers the QR Code Model 2 specification, supporting all versions (sizes) - * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. - * - * Ways to create a QR Code object: - * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). - * - Low level: Custom-make the list of segments and call - * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). - * (Note that all ways require supplying the desired error correction level and various byte buffers.) - */ - - -/*---- Enum and struct types----*/ - -/* - * The error correction level in a QR Code symbol. - */ -enum qrcodegen_Ecc { - // Must be declared in ascending order of error protection - // so that an internal qrcodegen function works properly - qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords - qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords - qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords - qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords -}; - - -/* - * The mask pattern used in a QR Code symbol. - */ -enum qrcodegen_Mask { - // A special value to tell the QR Code encoder to - // automatically select an appropriate mask pattern - qrcodegen_Mask_AUTO = -1, - // The eight actual mask patterns - qrcodegen_Mask_0 = 0, - qrcodegen_Mask_1, - qrcodegen_Mask_2, - qrcodegen_Mask_3, - qrcodegen_Mask_4, - qrcodegen_Mask_5, - qrcodegen_Mask_6, - qrcodegen_Mask_7, -}; - - -/* - * Describes how a segment's data bits are interpreted. - */ -enum qrcodegen_Mode { - qrcodegen_Mode_NUMERIC = 0x1, - qrcodegen_Mode_ALPHANUMERIC = 0x2, - qrcodegen_Mode_BYTE = 0x4, - qrcodegen_Mode_KANJI = 0x8, - qrcodegen_Mode_ECI = 0x7, -}; - - -/* - * A segment of character/binary/control data in a QR Code symbol. - * The mid-level way to create a segment is to take the payload data - * and call a factory function such as qrcodegen_makeNumeric(). - * The low-level way to create a segment is to custom-make the bit buffer - * and initialize a qrcodegen_Segment struct with appropriate values. - * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. - * Any segment longer than this is meaningless for the purpose of generating QR Codes. - * Moreover, the maximum allowed bit length is 32767 because - * the largest QR Code (version 40) has 31329 modules. - */ -struct qrcodegen_Segment { - // The mode indicator of this segment. - enum qrcodegen_Mode mode; - - // The length of this segment's unencoded data. Measured in characters for - // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. - // Always zero or positive. Not the same as the data's bit length. - int numChars; - - // The data bits of this segment, packed in bitwise big endian. - // Can be null if the bit length is zero. - uint8_t *data; - - // The number of valid data bits used in the buffer. Requires - // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. - // The character count (numChars) must agree with the mode and the bit buffer length. - int bitLength; -}; - - - -/*---- Macro constants and functions ----*/ - -#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard -#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard - -// Calculates the number of bytes needed to store any QR Code up to and including the given version number, -// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' -// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). -// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. -#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) - -// The worst-case number of bytes needed to store one QR Code, up to and including -// version 40. This value equals 3918, which is just under 4 kilobytes. -// Use this more convenient value to avoid calculating tighter memory bounds for buffers. -#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) - - - -/*---- Functions (high level) to generate QR Codes ----*/ - -/* - * Encodes the given text string to a QR Code, returning true if encoding succeeded. - * If the data is too long to fit in any version in the given range - * at the given ECC level, then false is returned. - * - The input text must be encoded in UTF-8 and contain no NULs. - * - The variables ecl and mask must correspond to enum constant values. - * - Requires 1 <= minVersion <= maxVersion <= 40. - * - The arrays tempBuffer and qrcode must each have a length - * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). - * - After the function returns, tempBuffer contains no useful data. - * - If successful, the resulting QR Code may use numeric, - * alphanumeric, or byte mode to encode the text. - * - In the most optimistic case, a QR Code at version 40 with low ECC - * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string - * up to 4296 characters, or any digit string up to 7089 characters. - * These numbers represent the hard upper limit of the QR Code standard. - * - Please consult the QR Code specification for information on - * data capacities per version, ECC level, and text encoding mode. - */ -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - - -/* - * Encodes the given binary data to a QR Code, returning true if encoding succeeded. - * If the data is too long to fit in any version in the given range - * at the given ECC level, then false is returned. - * - The input array range dataAndTemp[0 : dataLen] should normally be - * valid UTF-8 text, but is not required by the QR Code standard. - * - The variables ecl and mask must correspond to enum constant values. - * - Requires 1 <= minVersion <= maxVersion <= 40. - * - The arrays dataAndTemp and qrcode must each have a length - * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). - * - After the function returns, the contents of dataAndTemp may have changed, - * and does not represent useful data anymore. - * - If successful, the resulting QR Code will use byte mode to encode the data. - * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte - * sequence up to length 2953. This is the hard upper limit of the QR Code standard. - * - Please consult the QR Code specification for information on - * data capacities per version, ECC level, and text encoding mode. - */ -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - - -/*---- Functions (low level) to generate QR Codes ----*/ - -/* - * Renders a QR Code representing the given segments at the given error correction level. - * The smallest possible QR Code version is automatically chosen for the output. Returns true if - * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level - * of the result may be higher than the ecl argument if it can be done without increasing the version. - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. - */ -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); - - -/* - * Renders a QR Code representing the given segments with the given encoding parameters. - * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. - * The smallest possible QR Code version within the given range is automatically - * chosen for the output. Iff boostEcl is true, then the ECC level of the result - * may be higher than the ecl argument if it can be done without increasing the - * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or - * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. - */ -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); - - -/* - * Tests whether the given string can be encoded as a segment in alphanumeric mode. - * A string is encodable iff each character is in the following set: 0 to 9, A to Z - * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ -bool qrcodegen_isAlphanumeric(const char *text); - - -/* - * Tests whether the given string can be encoded as a segment in numeric mode. - * A string is encodable iff each character is in the range 0 to 9. - */ -bool qrcodegen_isNumeric(const char *text); - - -/* - * Returns the number of bytes (uint8_t) needed for the data buffer of a segment - * containing the given number of characters using the given mode. Notes: - * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or - * the number of needed bits exceeds INT16_MAX (i.e. 32767). - * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. - * - It is okay for the user to allocate more bytes for the buffer than needed. - * - For byte mode, numChars measures the number of bytes, not Unicode code points. - * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. - * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. - */ -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); - - -/* - * Returns a segment representing the given binary data encoded in - * byte mode. All input byte arrays are acceptable. Any text string - * can be converted to UTF-8 bytes and encoded as a byte mode segment. - */ -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); - - -/* - * Returns a segment representing the given string of decimal digits encoded in numeric mode. - */ -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); - - -/* - * Returns a segment representing the given text string encoded in alphanumeric mode. - * The characters allowed are: 0 to 9, A to Z (uppercase only), space, - * dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); - - -/* - * Returns a segment representing an Extended Channel Interpretation - * (ECI) designator with the given assignment value. - */ -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); - - -/*---- Functions to extract raw data from QR Codes ----*/ - -/* - * Returns the side length of the given QR Code, assuming that encoding succeeded. - * The result is in the range [21, 177]. Note that the length of the array buffer - * is related to the side length - every 'uint8_t qrcode[]' must have length at least - * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). - */ -int qrcodegen_getSize(const uint8_t qrcode[]); - - -/* - * Returns the color of the module (pixel) at the given coordinates, which is false - * for white or true for black. The top left corner has the coordinates (x=0, y=0). - * If the given coordinates are out of bounds, then false (white) is returned. - */ -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); - - -#ifdef __cplusplus -} -#endif diff --git a/SSH/RPM/rublonPam-1.0/login_rublon.te b/SSH/RPM/rublonPam-1.0/login_rublon.te deleted file mode 100644 index de46001..0000000 --- a/SSH/RPM/rublonPam-1.0/login_rublon.te +++ /dev/null @@ -1,10 +0,0 @@ -module login_rublon 1.0; - -require { -type http_port_t; -type http_cache_port_t; -type sshd_t; -class tcp_socket name_connect; -}; - -allow sshd_t {http_port_t http_cache_port_t}:tcp_socket name_connect; diff --git a/SSH/RPM/rublonPam-1.0/rublonPam.c b/SSH/RPM/rublonPam-1.0/rublonPam.c deleted file mode 100644 index 2a85cde..0000000 --- a/SSH/RPM/rublonPam-1.0/rublonPam.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "src/misc.h" -#include -#include -#include -#include -#include -#include -#include - -void displayHeader(pam_handle_t *pamh) { - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++. `;+++++++++++++++: ++++++++` `+++++++++++++++++++++++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` ++++++++++++++: ++++++++` `+++++++++++++++++++++++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` +++++++++++++: ++++++++` `+++++++++++++++++++++++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` ''` ++';;'++;;;++: +:,+++++` `++++++.`.+++++;;;'+..++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` +++ ++ `++ ++: +++` `++++ `+++ ` .++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` ++: ++ `++ ++: ++` `+++ `++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` `++ `++ ++: `' ++` `+++ `' ++ +: ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` +++ `++ ++: +++ ;+` `++, +++ '+ .++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` ` .+++ `++ ++: +++ ;+` `++, +++ '+ .++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` +. +++` ,` ++: `; ++` +++ `; ++ .++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` ++ +++ ++: ++, ++ .++ .++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++` +++ `++, +++: ++++ +++ .+++ .++ ++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "++++++++++++++++++++;.,++++++++++;:+++++++;.,+++++.`,++++++++++++++++++++"); - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); -} - -PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags, int argc, const char **argv ) { - return PAM_SUCCESS; -} - -PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { - return PAM_SUCCESS; -} - -PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) { - displayHeader(pamh); - - int access = startRublon(pamh); - - if(access == STATUS_BYPASS){ - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "User bypassed"); - return PAM_SUCCESS; - } - if(access == STATUS_DENIED){ - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Access denied!"); - return PAM_MAXTRIES; - } - if(access == STATUS_PENDING){ - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Status pending...!"); - return PAM_SUCCESS; - } - if(access == CONNECTION_ERROR){ - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Connection error"); - return PAM_MAXTRIES; - } - if(access == STATUS_UNKNOWN){ - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Connection error : status unknown"); - return PAM_MAXTRIES; - } - if(access == STATUS_CONFIRMED) { - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Access confirmed by Rublon 2FA!"); - return PAM_SUCCESS; - } - - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "End PAM module"); - - return PAM_MAXTRIES; -} \ No newline at end of file diff --git a/SSH/RPM/rublonPam-1.0/src/coreHandler.c b/SSH/RPM/rublonPam-1.0/src/coreHandler.c deleted file mode 100644 index 3a945cd..0000000 --- a/SSH/RPM/rublonPam-1.0/src/coreHandler.c +++ /dev/null @@ -1,398 +0,0 @@ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#include "../lib/cJSON.h" -#include "../lib/qrcodegen.h" -#include "misc.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -struct MemoryStruct { - char *memory; - size_t size; -}; - -static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { - size_t realsize = size * nmemb; - struct MemoryStruct *mem = (struct MemoryStruct *)userp; - mem->memory = realloc(mem->memory, mem->size + realsize + 1); - if(mem->memory == NULL) - return 0; - memcpy(&(mem->memory[mem->size]), contents, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - return realsize; -} - -char *parseNestedJson(char source[], char name[], char indexName[]) { - const cJSON *value = NULL; - const cJSON *nestedValue = NULL; - cJSON *monitor_json = cJSON_Parse(source); - value = cJSON_GetObjectItemCaseSensitive(monitor_json, name); - nestedValue = cJSON_GetObjectItemCaseSensitive(value,indexName); - if(nestedValue) - return nestedValue->valuestring; - else - return NULL; -} - -int parseNestedJsonInt(char source[], char name[], char indexName[]) { - const cJSON *value = NULL; - const cJSON *nestedValue = NULL; - cJSON *monitor_json = cJSON_Parse(source); - value = cJSON_GetObjectItemCaseSensitive(monitor_json, name); - nestedValue = cJSON_GetObjectItemCaseSensitive(value,indexName); - if(nestedValue) - return nestedValue->valueint; - else - return 0; -} - -char *parseJson(char source[], char name[] ) { - const cJSON *value = NULL; - cJSON *monitor_json = cJSON_Parse(source); - value = cJSON_GetObjectItemCaseSensitive(monitor_json, name); - if(value) - return value->valuestring; - else - return NULL; -} - -void printQr(const uint8_t qrcode[],pam_handle_t *pamh) { - char *qrCodeString = ""; - int size = qrcodegen_getSize(qrcode); - int border = 1; - int y; - for(y = -border; y < size + border; y++) { - int x; - for(x = -border; x < size + border; x++) - asprintf(&qrCodeString,"%s%s",qrCodeString,qrcodegen_getModule(qrcode, x, y) ? " " : "\u2588\u2588"); - asprintf(&qrCodeString,"%s%s",qrCodeString,"\n"); - } - asprintf(&qrCodeString,"%s%s",qrCodeString,"\n"); - - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%s",qrCodeString); -} - -void displayQrCode(pam_handle_t *pamh, char *qrToken) { - enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW; - uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; - uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - bool ok = qrcodegen_encodeText(qrToken, tempBuffer, qrcode, errCorLvl, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); - if(ok) - printQr(qrcode, pamh); -} - -void displayAvailableAuthenticationMethods(cJSON *methods, pam_handle_t *pamh) { - - if(cJSON_GetArraySize(methods)) { - int i; - for (i = 0; i < cJSON_GetArraySize(methods); i++) { - if (strcmp(cJSON_GetArrayItem(methods, i)->valuestring,"email") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%d: Email verification link",i+1); - if (strcmp(cJSON_GetArrayItem(methods, i)->valuestring,"qrcode") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%d: QR code (Rublon app required)",i+1); - if (strcmp(cJSON_GetArrayItem(methods, i)->valuestring,"push") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%d: Push notification (Rublon app required)",i+1); - if (strcmp(cJSON_GetArrayItem(methods, i)->valuestring,"totp") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%d: TOTP code (Rublon app required)",i+1); - if (strcmp(cJSON_GetArrayItem(methods, i)->valuestring,"sms") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "%d: SMS code",i+1); - } - } -} - -void selectMethodModule(pam_handle_t *pamh, cJSON *methods, char **selectedMethod) { - char *authentication = 0; - int idx = 0; - if(cJSON_GetArraySize(methods)) { - displayAvailableAuthenticationMethods(methods, pamh); - do{ - if(cJSON_GetArraySize(methods) == 1) { - idx=1; - break; - } - pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &authentication, "Select method [1-%d]: ",cJSON_GetArraySize(methods)); - idx = atoi(authentication); - }while(idx < 1 || idx > cJSON_GetArraySize(methods)); - *selectedMethod=cJSON_GetArrayItem(methods, idx-1)->valuestring; - } -} - -void displaySelectedMethodMsg(pam_handle_t *pamh, char *selectedMethod) { - if(strcmp(selectedMethod,"email") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "\nWe have sent a verification link.\nUse this link to sing in to your account."); - else if(strcmp(selectedMethod,"qrcode") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "\nSign in by scanning QR code (Rublon app required)"); - else if(strcmp(selectedMethod,"push") == 0) - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "\nSign in using Push notification (Rublon app required)"); -} - -bool transactionErrorException(pam_handle_t *pamh, char *curlResponse) { - char *exception = NULL; - exception = parseNestedJson(curlResponse,"result","exception"); - if(exception != NULL) { - pam_prompt(pamh, PAM_PROMPT_ECHO_OFF,NULL, "Rublon exception: %s",exception); - return true; - } - return false; -} - -char *curlHandler(pam_handle_t *pamh, char *jsonObj, char *url, char *secretKey) { - CURL *curl; - CURLcode res, headerLength; - struct MemoryStruct chunks; - chunks.memory = malloc(1); - chunks.size = 0; - curl = curl_easy_init(); - char *curlResponse, *responseXRublon; - char *xRublon; - - asprintf(&xRublon,"X-Rublon-Signature: %s",signData(pamh,jsonObj, secretKey)); - - if(curl) { - struct curl_slist *chunk = NULL; - curl_easy_setopt(curl, CURLOPT_URL, url); - chunk = curl_slist_append(chunk, "Content-Type: application/json"); - chunk = curl_slist_append(chunk, "Accept: application/json"); - chunk = curl_slist_append(chunk, xRublon); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj); - curl_easy_setopt(curl, CURLOPT_HEADER, 1); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunks); - res = curl_easy_perform(curl); - if(res != CURLE_OK) - return NULL; - long size; - curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size); - curlResponse = curlResponseJsonParser(pamh, size, chunks.memory); - responseXRublon = curlResponseSignatureParser(pamh, size, chunks.memory); - if(!verifyData(pamh, curlResponse, secretKey, responseXRublon)) { - pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Invalid Signature Exception"); - return NULL; - } - curl_easy_cleanup(curl); - if(chunks.memory) - free(chunks.memory); - return curlResponse; - } - else - return NULL; -} - -void curlHandlerThread(pam_handle_t *pamh, char *jsonObj, char *url, char *secretKey, char **accessToken, char **status, char **exception) { - char *curlResponse = curlHandler(pamh, jsonObj, url, secretKey); - if(curlResponse != NULL) { - *status = parseJson(curlResponse,"status"); - *exception = parseNestedJson(curlResponse,"result","exception"); - *accessToken = parseNestedJson(curlResponse,"result","token"); - } - else - *status = "ERROR"; -} - -bool checkResult(char *curlResponse) { - cJSON *json = cJSON_Parse(curlResponse); - cJSON *result_json = cJSON_GetObjectItemCaseSensitive(json, "result"); - cJSON_Delete(json); - if (cJSON_IsTrue(result_json) == 1) - return true; - return false; -} - -bool isDigit(char *code) { - int i; - for (i=0;i -#include "../lib/cJSON.h" -#include -#include -#include -#include -#include - -#include - -#define STATUS_PENDING 0 -#define STATUS_WAITING 1 -#define STATUS_DENIED 2 -#define STATUS_BYPASS 3 -#define STATUS_UNKNOWN 4 -#define STATUS_CONFIRMED 5 -#define CONNECTION_ERROR 6 -#define CHANGE_METHOD 7 - -#define TOTP_SMS_INPUT_CODE_SIZE 6 -#define SIGNATURE_SIZE 64 -bool isOneOfSelectedMethods(char *selectedMethod, char *methods[], int methodsSize); -int startRublon(pam_handle_t *pamh); -void curlHandlerThread(pam_handle_t *pamh, char *jsonObj, char *url, char *secretKey, char **accessToken, char **status, char **exception); -int postInit(pam_handle_t *pamh, cJSON **availableMethods, char **transactionId, char *systemToken, char *secretKey, const char *appUserId, char *userEmail, char *rublonApiServer); -int postMethod(pam_handle_t *pamh, char *secretKey, char *tId, char *selectedMethod, char *rublonApiServer, char *systemToken, bool onlyOneMethod); -int postConfirmCode(pam_handle_t *pamh, char *secretKey, char *systemToken, char *transactionId, char *selectedMethod, char *rublonApiServer, bool onlyOneMethod); - -void selectMethodModule(pam_handle_t *pamh, cJSON *methods, char **selectedMethod); -void substring(char s[], char sub[], int p, int l); -char *curlResponseJsonParser(pam_handle_t *pamh, long headerLength, char *resp); -char *curlResponseSignatureParser(pam_handle_t *pamh, long headerLength, char *resp); -char *signData(pam_handle_t *pamh, char *data, char *secretKey); -int verifyData(pam_handle_t *pamh, char *data, char *secretKey, char *sign); -int postCredentials(pam_handle_t *pamh, char *systemToken, char *accessToken, char *rublonApiServer, char *secretKey); \ No newline at end of file diff --git a/SSH/RPM/rublonPam-1.0/src/pamApp.c b/SSH/RPM/rublonPam-1.0/src/pamApp.c deleted file mode 100644 index 708de2d..0000000 --- a/SSH/RPM/rublonPam-1.0/src/pamApp.c +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#include "misc.h" -#include "../lib/cfg_parse.h" -#include "../lib/cJSON.h" -#include -#include -#include -#include -#include -#include -#include - -struct args { - int listenerStatus; - char *transactionId; - char *systemToken; - char *secretKey; - char *rublonApiServer; - char *accessToken; - char *status; - char *exception; - pam_handle_t *pamh; -}; - -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -void* listenerThread(void* input) { - char *jsonObj; - char *url; - char *status; - char *accessToken; - char *exception; - - do { - pthread_mutex_lock(&mutex); - asprintf(&jsonObj,"{\"tid\":\"%s\",\"systemToken\":\"%s\"}",((struct args*)input)->transactionId, ((struct args*)input)->systemToken); - asprintf(&url,"%s/api/transaction/listener",((struct args*)input)->rublonApiServer); - status = ((struct args*)input)->status; - accessToken = ((struct args*)input)->accessToken; - exception = ((struct args*)input)->exception; - curlHandlerThread(((struct args*)input)->pamh, jsonObj, url, ((struct args*)input)->secretKey, &accessToken, &status, &exception); - ((struct args*)input)->status = status; - ((struct args*)input)->accessToken = accessToken; - ((struct args*)input)->exception = exception; - if(strcmp(status,"ERROR") == 0 || exception != NULL) { - ((struct args*)input)->accessToken = ""; - ((struct args*)input)->listenerStatus = STATUS_DENIED; - } - else - ((struct args*)input)->listenerStatus = STATUS_PENDING; - pthread_mutex_unlock(&mutex); - sleep(5); - } while (((struct args*)input)->accessToken == NULL); - pthread_exit(0); -} - -char *getConfigValue(const char * value) { - struct cfg_struct* cfg; - cfg = cfg_init(); - if (cfg_load(cfg,"/lib64/security/.config") < 0) - return NULL; - else - return (char*)cfg_get(cfg,value); -} - -int startRublon(pam_handle_t *pamh) { - char *systemToken; - char *secretKey; - const char *appUserId; - char *userEmail; - char *userDomain; - char *rublonApiServer; - char *transactionId; - const char *pamUser; - char *selectedMethod = NULL; - char *accessToken = NULL; - cJSON *availableMethods; - bool codeRequired = false; - - struct args *threadArgs = (struct args *)malloc(sizeof(struct args)); - pam_get_user(pamh, &pamUser, NULL); - - systemToken = getConfigValue("systemToken"); - secretKey = getConfigValue("secretKey"); - appUserId = pamUser; - userEmail = getConfigValue("userEmail"); - userDomain = getConfigValue("userDomain"); - rublonApiServer = getConfigValue("rublonApiServer"); - asprintf(&userEmail, "%s%s%s", pamUser,"@",userDomain); - transactionId = NULL; - - int initStatus = postInit(pamh, &availableMethods, &transactionId , systemToken, secretKey, appUserId, userEmail, rublonApiServer); - if(initStatus != STATUS_PENDING) - return initStatus; - - threadArgs->pamh = pamh; - threadArgs->transactionId = transactionId; - threadArgs->systemToken = systemToken; - threadArgs->secretKey = secretKey; - threadArgs->rublonApiServer = rublonApiServer; - threadArgs->accessToken = accessToken; - threadArgs->status = NULL; - threadArgs->exception = NULL; - threadArgs->listenerStatus = STATUS_PENDING; - - pthread_t listener; - pthread_create(&listener,NULL,listenerThread, threadArgs); - - bool changeMethod; - do { - bool onlyOneMethod = false; - selectMethodModule(pamh, availableMethods, &selectedMethod); - if(cJSON_GetArraySize(availableMethods) == 1) - onlyOneMethod = true; - changeMethod = false; - int methodStatus = postMethod(pamh, secretKey, transactionId, selectedMethod, rublonApiServer, systemToken, onlyOneMethod); - if(methodStatus == CHANGE_METHOD) { - changeMethod = true; - continue; - } - else if(methodStatus != STATUS_PENDING) - return methodStatus; - - char *methodsToCompare[] = {"totp","sms"}; - - if(isOneOfSelectedMethods(selectedMethod, methodsToCompare, 2)) { - int confirmCodeStatus = postConfirmCode(pamh, secretKey, systemToken, transactionId, selectedMethod, rublonApiServer, onlyOneMethod); - if(confirmCodeStatus == CHANGE_METHOD) { - changeMethod = true; - continue; - } - else if(confirmCodeStatus != STATUS_PENDING) - return confirmCodeStatus; - continue; - } - - }while(changeMethod == true); - do { - sleep(1); - }while(threadArgs->accessToken == NULL); - - pthread_mutex_destroy(&mutex); - - if(threadArgs->listenerStatus != STATUS_PENDING) - return threadArgs->listenerStatus; - - int credentialsStatus = postCredentials(pamh, systemToken, threadArgs->accessToken, rublonApiServer, secretKey); - return credentialsStatus; -} \ No newline at end of file diff --git a/SSH/RPM/rublonPam-1.0/src/signatureWrapper.c b/SSH/RPM/rublonPam-1.0/src/signatureWrapper.c deleted file mode 100644 index a0fc6d7..0000000 --- a/SSH/RPM/rublonPam-1.0/src/signatureWrapper.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "misc.h" -#include -#include -#include -#include -#include -#include -#include -#include - -void substring(char s[], char sub[], int p, int l) { - int c = 0; - - while (c < l) { - sub[c] = s[p+c-1]; - c++; - } - sub[c] = '\0'; -} - -char *curlResponseJsonParser(pam_handle_t *pamh, long headerLength, char *resp) { - char *response = malloc (sizeof (char) * strlen(resp)); - substring(resp, response, headerLength+1, strlen(resp)-headerLength+1); - return response; -} - -char *curlResponseSignatureParser(pam_handle_t *pamh, long headerLength, char *resp) { - char *rublonHeader = "X-Rublon-Signature: "; - char *headers = malloc (sizeof (char) * headerLength); - - substring(resp, headers, 1, headerLength); - const char * curLine = headers; - while(curLine) { - const char * nextLine = strchr(curLine, '\n'); - int curLineLen = nextLine ? (nextLine-curLine) : strlen(curLine); - char * tempStr = (char *) malloc(curLineLen+1); - if (tempStr) { - memcpy(tempStr, curLine, curLineLen); - tempStr[curLineLen] = '\0'; - char *signatureExist = strstr(tempStr, rublonHeader); - if(signatureExist != NULL) - substring(tempStr, headers, strlen(rublonHeader) +1, SIGNATURE_SIZE); - free(tempStr); - } - curLine = nextLine ? (nextLine+1) : NULL; - } - return headers; -} - -char *signData(pam_handle_t *pamh, char *data, char *secretKey) { - unsigned char *hmac = HMAC(EVP_sha256(), (unsigned char*)secretKey, strlen(secretKey), (unsigned char*)data, strlen(data), NULL, NULL); - char *xRublon = malloc (sizeof (char) * 64); - int i; - for(i = 0; i < 32; i++) - sprintf(&xRublon[i*2], "%02x", (unsigned int)hmac[i]); - return xRublon; -} - -int verifyData(pam_handle_t *pamh, char *data, char *secretKey, char *sign) { - char *dataSign = signData(pamh, data, secretKey); - return (strcmp(dataSign,sign) == 0); -} \ No newline at end of file diff --git a/SSH/RPM/rublonPam.spec b/SSH/RPM/rublonPam.spec deleted file mode 100644 index 108e4e6..0000000 --- a/SSH/RPM/rublonPam.spec +++ /dev/null @@ -1,43 +0,0 @@ -Summary: Rublon 2FA for Linux SSH -Name: rublonPam -Version: 1.0 -Release: 1 -License: - -Group: 2FA -Source: rublonPam.tar.gz -URL: https://rublon.net -Distribution: CENTOS Linux -Packager: KRI - -Requires: gcc -Requires: make -Requires: curl-devel -Requires: openssl-devel -Requires: pam-devel -Requires: policycoreutils-python - -%description -Rublon 2FA - -%prep - -%setup -q - -%install -rm -rf $RPM_BUILD_ROOT -make -install -d $RPM_BUILD_ROOT/lib64/security -install rublonPam.so $RPM_BUILD_ROOT/lib64/security/rublonPam.so -install .config $RPM_BUILD_ROOT/lib64/security/.config -install login_rublon.te $RPM_BUILD_ROOT/lib64/security/login_rublon.te - -%files -/lib64/security/.config -/lib64/security/rublonPam.so -/lib64/security/login_rublon.te - -%post -sudo checkmodule -M -m -o /lib64/security/login_rublon.mod /lib64/security/login_rublon.te -sudo semodule_package -o /lib64/security/login_rublon.pp -m /lib64/security/login_rublon.mod -sudo semodule -i /lib64/security/login_rublon.pp -service sshd restart diff --git a/SSH/RPM/rublonPam.tar.gz b/SSH/RPM/rublonPam.tar.gz deleted file mode 100644 index 852e77c..0000000 Binary files a/SSH/RPM/rublonPam.tar.gz and /dev/null differ