diff options
Diffstat (limited to 'nDPId.c')
-rw-r--r-- | nDPId.c | 140 |
1 files changed, 91 insertions, 49 deletions
@@ -1123,69 +1123,109 @@ static void serialize_and_send(struct nDPId_reader_thread * const reader_thread) ndpi_reset_serializer(&reader_thread->workflow->ndpi_serializer); } -static size_t base64_out_len(size_t in_len) +/* Slightly modified code from: https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 */ +static int base64encode(uint8_t const * const data_buf, + size_t dataLength, + char * const result, + size_t * const resultSize) { - return ((in_len + 2) / 3) * 4; -} - -static char * base64_encode(uint8_t const * in, size_t in_len, char * const out, size_t const out_len) -{ - static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - size_t len = 0, ret_size; - int i = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; + const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const uint8_t * data = (const uint8_t *)data_buf; + size_t resultIndex = 0; + size_t x; + uint32_t n = 0; + int padCount = dataLength % 3; + uint8_t n0, n1, n2, n3; - ret_size = base64_out_len(in_len); - if (out_len < ret_size) + /* increment over the length of the string, three characters at a time */ + for (x = 0; x < dataLength; x += 3) { - return NULL; - } + /* these three 8-bit (ASCII) characters become one 24-bit number */ + n = ((uint32_t)data[x]) << 16; // parenthesis needed, compiler depending on flags can do the shifting before + // conversion to uint32_t, resulting to 0 - while (in_len-- != 0) - { - char_array_3[i++] = *(in++); - if (i == 3) + if ((x + 1) < dataLength) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (i = 0; i < 4; i++) - { - out[len++] = base64_table[char_array_4[i]]; - } - i = 0; + n += ((uint32_t)data[x + 1]) << 8; // parenthesis needed, compiler depending on flags can do the shifting + // before conversion to uint32_t, resulting to 0 } - } - if (i != 0) - { - for (int j = i; j < 3; j++) + if ((x + 2) < dataLength) { - char_array_3[j] = '\0'; + n += data[x + 2]; } - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; + /* this 24-bit number gets separated into four 6-bit numbers */ + n0 = (uint8_t)(n >> 18) & 63; + n1 = (uint8_t)(n >> 12) & 63; + n2 = (uint8_t)(n >> 6) & 63; + n3 = (uint8_t)n & 63; - for (int j = 0; (j < i + 1); j++) + /* + * if we have one byte available, then its encoding is spread + * out over two characters + */ + if (resultIndex >= *resultSize) + { + return 1; /* indicate failure: buffer too small */ + } + result[resultIndex++] = base64chars[n0]; + if (resultIndex >= *resultSize) { - out[len++] = base64_table[char_array_4[j]]; + return 1; /* indicate failure: buffer too small */ } + result[resultIndex++] = base64chars[n1]; - while ((i++ < 3)) + /* + * if we have only two bytes available, then their encoding is + * spread out over three chars + */ + if ((x + 1) < dataLength) { - out[len++] = '='; + if (resultIndex >= *resultSize) + { + return 1; /* indicate failure: buffer too small */ + } + result[resultIndex++] = base64chars[n2]; + } + + /* + * if we have all three bytes available, then their encoding is spread + * out over four characters + */ + if ((x + 2) < dataLength) + { + if (resultIndex >= *resultSize) + { + return 1; /* indicate failure: buffer too small */ + } + result[resultIndex++] = base64chars[n3]; } } - out[len++] = '\0'; + /* + * create and add padding that is required if we did not have a multiple of 3 + * number of characters available + */ + if (padCount > 0) + { + for (; padCount < 3; padCount++) + { + if (resultIndex >= *resultSize) + { + return 1; /* indicate failure: buffer too small */ + } + result[resultIndex++] = '='; + } + } + if (resultIndex >= *resultSize) + { + return 1; /* indicate failure: buffer too small */ + } - return out; + result[resultIndex] = 0; + *resultSize = resultIndex; + return 0; /* indicate success */ } static void jsonize_packet_event(struct nDPId_reader_thread * const reader_thread, @@ -1230,16 +1270,17 @@ static void jsonize_packet_event(struct nDPId_reader_thread * const reader_threa jsonize_basic(reader_thread); - size_t base64_data_len = base64_out_len(header->caplen); char base64_data[NETWORK_BUFFER_MAX_SIZE]; + size_t base64_data_len = sizeof(base64_data); + int base64_retval = base64encode(packet, header->caplen, base64_data, &base64_data_len); + if (ndpi_serialize_string_boolean(&workflow->ndpi_serializer, "pkt_oversize", base64_data_len > sizeof(base64_data)) != 0 || ndpi_serialize_string_uint64(&workflow->ndpi_serializer, "pkt_ts", header->ts.tv_sec) != 0 || ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "pkt_len", header->len) != 0 || - ndpi_serialize_string_string(&workflow->ndpi_serializer, - "pkt", - base64_encode(packet, header->caplen, base64_data, sizeof(base64_data))) != 0 || + (base64_retval == 0 && base64_data_len > 0 && + ndpi_serialize_string_binary(&workflow->ndpi_serializer, "pkt", base64_data, base64_data_len) != 0) || ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "pkt_caplen", header->caplen) != 0 || ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "pkt_type", pkt_type) != 0 || ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "pkt_ipoffset", pkt_ipoffset) != 0 || @@ -2708,7 +2749,8 @@ static int validate_options(char const * const arg0) if (process_internal_initial_direction != 0 || process_external_initial_direction != 0) { fprintf(stderr, - "%s: Internal and External packet processing may lead to incorrect results for flows that were active before the daemon started.\n", + "%s: Internal and External packet processing may lead to incorrect results for flows that were active " + "before the daemon started.\n", arg0); } |