diff options
-rw-r--r-- | example/ndpiReader.c | 55 | ||||
-rw-r--r-- | src/include/ndpi_api.h | 21 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 47 | ||||
-rw-r--r-- | src/lib/protocols/mail_imap.c | 183 | ||||
-rw-r--r-- | src/lib/protocols/mail_pop.c | 62 | ||||
-rw-r--r-- | src/lib/protocols/mail_smtp.c | 66 |
6 files changed, 194 insertions, 240 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index dbb6b04df..d26505062 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -6168,6 +6168,60 @@ void memmemUnitTest(void) { /* *********************************************** */ +void memcasecmpUnitTest(void) +{ + /* Test 1: NULL pointers */ + assert(ndpi_memcasecmp(NULL, NULL, 5) == 0); + assert(ndpi_memcasecmp(NULL, "string", 6) == -1); + assert(ndpi_memcasecmp("string", NULL, 6) == 1); + + /* Test 2: Zero length */ + assert(ndpi_memcasecmp("string", "different", 0) == 0); + + /* Test 3: Single byte comparison */ + assert(ndpi_memcasecmp("a", "a", 1) == 0); + assert(ndpi_memcasecmp("a", "A", 1) == 0); + assert(ndpi_memcasecmp("a", "b", 1) < 0); + assert(ndpi_memcasecmp("b", "a", 1) > 0); + + /* Test 4: Case insensitivity */ + assert(ndpi_memcasecmp("STRING", "string", 6) == 0); + assert(ndpi_memcasecmp("String", "sTrInG", 6) == 0); + + /* Test 5: Various string comparisons */ + assert(ndpi_memcasecmp("string", "string", 6) == 0); + assert(ndpi_memcasecmp("string", "strong", 6) < 0); + assert(ndpi_memcasecmp("strong", "string", 6) > 0); + assert(ndpi_memcasecmp("abc", "abcd", 3) == 0); + assert(ndpi_memcasecmp("abcd", "abc", 3) == 0); + + /* Test 6: Optimization for checking first and last bytes */ + assert(ndpi_memcasecmp("aBc", "abc", 3) == 0); + assert(ndpi_memcasecmp("abc", "abC", 3) == 0); + assert(ndpi_memcasecmp("abc", "def", 3) < 0); + assert(ndpi_memcasecmp("abz", "abx", 3) > 0); + assert(ndpi_memcasecmp("axc", "ayc", 3) < 0); + + /* Test 7: Edge cases with non-printable characters and embedded zeros */ + const char str1[] = {0, 'a', 'b', 'c'}; + const char str2[] = {0, 'a', 'b', 'c'}; + assert(ndpi_memcasecmp(str1, str2, 4) == 0); + + const char str3[] = {0, 'a', 'b', 'c'}; + const char str4[] = {1, 'a', 'b', 'c'}; + assert(ndpi_memcasecmp(str3, str4, 4) < 0); + + const char str5[] = {'a', 'b', 'c', 0}; + const char str6[] = {'a', 'b', 'c', 1}; + assert(ndpi_memcasecmp(str5, str6, 4) < 0); + + const char str7[] = {'a', 'b', 0, 'd'}; + const char str8[] = {'a', 'b', 1, 'd'}; + assert(ndpi_memcasecmp(str7, str8, 4) < 0); +} + +/* *********************************************** */ + void mahalanobisUnitTest() { /* Example based on: https://supplychenmanagement.com/2019/03/06/calculating-mahalanobis-distance/ */ @@ -6721,6 +6775,7 @@ int main(int argc, char **argv) { strnstrUnitTest(); strncasestrUnitTest(); memmemUnitTest(); + memcasecmpUnitTest(); mahalanobisUnitTest(); #endif } diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index ac0e11d39..9cb064d14 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -2446,8 +2446,25 @@ extern "C" { * @return The destination string buffer */ u_char* ndpi_str_to_utf8(u_char *in, u_int in_len, u_char *out, u_int out_len); - - + + /** + * Performs a case-insensitive comparison of two memory regions + * + * @par s1 Pointer to the first memory region + * @par s2 Pointer to the second memory region + * @par n Number of bytes to compare + * @return < 0 if s1 is less than s2 in a case-insensitive comparison + * = 0 if s1 matches s2 in a case-insensitive comparison + * > 0 if s1 is greater than s2 in a case-insensitive comparison + * If s1 is NULL and s2 is not, returns -1 + * If s2 is NULL and s1 is not, returns 1 + * If both are NULL, returns 0 + * + * This function works similarly to memcmp() but performs case-insensitive + * comparison. + */ + int ndpi_memcasecmp(const void *s1, const void *s2, size_t n); + #ifdef __cplusplus } #endif diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index bd4d530f9..bb287d2d6 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -12372,3 +12372,50 @@ size_t ndpi_strlcpy(char *dst, const char* src, size_t dst_len, size_t src_len) return src_len; } + +int ndpi_memcasecmp(const void *s1, const void *s2, size_t n) { + if (s1 == NULL && s2 == NULL) { + return 0; + } + + if (s1 == NULL) { + return -1; + } + + if (s2 == NULL) { + return 1; + } + + if (n == 0) { + return 0; + } + + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + + if (n == 1) { + return tolower(*p1) - tolower(*p2); + } + + /* Early exit optimization - check first and last bytes */ + + int first_cmp = tolower(p1[0]) - tolower(p2[0]); + if (first_cmp != 0) { + return first_cmp; + } + + int last_cmp = tolower(p1[n-1]) - tolower(p2[n-1]); + if (last_cmp != 0) { + return last_cmp; + } + + size_t i; + for (i = 1; i < n-1; i++) { + int cmp = tolower(p1[i]) - tolower(p2[i]); + if (cmp != 0) { + return cmp; + } + } + + return 0; +} diff --git a/src/lib/protocols/mail_imap.c b/src/lib/protocols/mail_imap.c index 0dec662c5..3bb858f9c 100644 --- a/src/lib/protocols/mail_imap.c +++ b/src/lib/protocols/mail_imap.c @@ -29,6 +29,15 @@ #include "ndpi_api.h" #include "ndpi_private.h" +/* Safely increments IMAP stage counter preventing 3-bit mail_imap_stage overflow. + * Even though current tests don't trigger overflow, better safe than sorry. */ +#define SAFE_INC_IMAP_STAGE(flow) \ + do { \ + if ((flow)->l4.tcp.mail_imap_stage < 7) { \ + (flow)->l4.tcp.mail_imap_stage += 1; \ + } \ + } while(0) + /* #define IMAP_DEBUG 1*/ static void ndpi_int_mail_imap_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, @@ -53,11 +62,8 @@ static void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_ if(packet->payload_packet_len >= 4 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) { // the DONE command appears without a tag - if(packet->payload_packet_len == 6 && ((packet->payload[0] == 'D' || packet->payload[0] == 'd') - && (packet->payload[1] == 'O' || packet->payload[1] == 'o') - && (packet->payload[2] == 'N' || packet->payload[2] == 'n') - && (packet->payload[3] == 'E' || packet->payload[3] == 'e'))) { - flow->l4.tcp.mail_imap_stage += 1; + if(packet->payload_packet_len == 6 && ndpi_memcasecmp(packet->payload, "DONE", 4) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } else { if(flow->l4.tcp.mail_imap_stage < 5) { @@ -102,10 +108,8 @@ static void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_ } if((command_start + 3) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'O' || packet->payload[command_start] == 'o') - && (packet->payload[command_start + 1] == 'K' || packet->payload[command_start + 1] == 'k') - && packet->payload[command_start + 2] == ' ') { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "OK ", 3) == 0) { + SAFE_INC_IMAP_STAGE(flow); if(flow->l4.tcp.mail_imap_starttls == 1) { NDPI_LOG_DBG2(ndpi_struct, "starttls detected\n"); ndpi_int_mail_imap_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAPS); @@ -118,62 +122,37 @@ static void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_ } } saw_command = 1; - } else if((packet->payload[command_start] == 'U' || packet->payload[command_start] == 'u') - && (packet->payload[command_start + 1] == 'I' || packet->payload[command_start + 1] == 'i') - && (packet->payload[command_start + 2] == 'D' || packet->payload[command_start + 2] == 'd')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "UID", 3) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'N' || packet->payload[command_start] == 'n') - && (packet->payload[command_start + 1] == 'O' || packet->payload[command_start + 1] == 'o') - && packet->payload[command_start + 2] == ' ') { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "NO ", 3) == 0) { + SAFE_INC_IMAP_STAGE(flow); if(flow->l4.tcp.mail_imap_starttls == 1) flow->l4.tcp.mail_imap_starttls = 0; saw_command = 1; } } if((command_start + 10) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'C' || packet->payload[command_start] == 'c') - && (packet->payload[command_start + 1] == 'A' || packet->payload[command_start + 1] == 'a') - && (packet->payload[command_start + 2] == 'P' || packet->payload[command_start + 2] == 'p') - && (packet->payload[command_start + 3] == 'A' || packet->payload[command_start + 3] == 'a') - && (packet->payload[command_start + 4] == 'B' || packet->payload[command_start + 4] == 'b') - && (packet->payload[command_start + 5] == 'I' || packet->payload[command_start + 5] == 'i') - && (packet->payload[command_start + 6] == 'L' || packet->payload[command_start + 6] == 'l') - && (packet->payload[command_start + 7] == 'I' || packet->payload[command_start + 7] == 'i') - && (packet->payload[command_start + 8] == 'T' || packet->payload[command_start + 8] == 't') - && (packet->payload[command_start + 9] == 'Y' || packet->payload[command_start + 9] == 'y')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "CAPABILITY", 10) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } } if((command_start + 8) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's') - && (packet->payload[command_start + 1] == 'T' || packet->payload[command_start + 1] == 't') - && (packet->payload[command_start + 2] == 'A' || packet->payload[command_start + 2] == 'a') - && (packet->payload[command_start + 3] == 'R' || packet->payload[command_start + 3] == 'r') - && (packet->payload[command_start + 4] == 'T' || packet->payload[command_start + 4] == 't') - && (packet->payload[command_start + 5] == 'T' || packet->payload[command_start + 5] == 't') - && (packet->payload[command_start + 6] == 'L' || packet->payload[command_start + 6] == 'l') - && (packet->payload[command_start + 7] == 'S' || packet->payload[command_start + 7] == 's')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "STARTTLS", 8) == 0) { + SAFE_INC_IMAP_STAGE(flow); flow->l4.tcp.mail_imap_starttls = 1; saw_command = 1; } } if((command_start + 5) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l') - && (packet->payload[command_start + 1] == 'O' || packet->payload[command_start + 1] == 'o') - && (packet->payload[command_start + 2] == 'G' || packet->payload[command_start + 2] == 'g') - && (packet->payload[command_start + 3] == 'I' || packet->payload[command_start + 3] == 'i') - && (packet->payload[command_start + 4] == 'N' || packet->payload[command_start + 4] == 'n')) { + if(ndpi_memcasecmp(packet->payload + command_start, "LOGIN", 5) == 0) { /* xxxx LOGIN "username" "password" xxxx LOGIN username password */ char str[256], *user, *saveptr; u_int len = ndpi_min(packet->payload_packet_len - (command_start + 5), (int)sizeof(str) - 1); - strncpy(str, (const char*)packet->payload + command_start + 5, len); - str[len] = '\0'; + ndpi_strlcpy(str, (const char*)packet->payload + command_start + 5, sizeof(str), len); user = strtok_r(str, " \"\r\n", &saveptr); if(user) { @@ -195,52 +174,25 @@ static void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_ } } - flow->l4.tcp.mail_imap_stage += 1; + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'F' || packet->payload[command_start] == 'f') - && (packet->payload[command_start + 1] == 'E' || packet->payload[command_start + 1] == 'e') - && (packet->payload[command_start + 2] == 'T' || packet->payload[command_start + 2] == 't') - && (packet->payload[command_start + 3] == 'C' || packet->payload[command_start + 3] == 'c') - && (packet->payload[command_start + 4] == 'H' || packet->payload[command_start + 4] == 'h')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "FETCH", 5) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'F' || packet->payload[command_start] == 'f') - && (packet->payload[command_start + 1] == 'L' || packet->payload[command_start + 1] == 'l') - && (packet->payload[command_start + 2] == 'A' || packet->payload[command_start + 2] == 'a') - && (packet->payload[command_start + 3] == 'G' || packet->payload[command_start + 3] == 'g') - && (packet->payload[command_start + 4] == 'S' || packet->payload[command_start + 4] == 's')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "FLAGS", 5) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'C' || packet->payload[command_start] == 'c') - && (packet->payload[command_start + 1] == 'H' || packet->payload[command_start + 1] == 'h') - && (packet->payload[command_start + 2] == 'E' || packet->payload[command_start + 2] == 'e') - && (packet->payload[command_start + 3] == 'C' || packet->payload[command_start + 3] == 'c') - && (packet->payload[command_start + 4] == 'K' || packet->payload[command_start + 4] == 'k')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "CHECK", 5) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's') - && (packet->payload[command_start + 1] == 'T' || packet->payload[command_start + 1] == 't') - && (packet->payload[command_start + 2] == 'O' || packet->payload[command_start + 2] == 'o') - && (packet->payload[command_start + 3] == 'R' || packet->payload[command_start + 3] == 'r') - && (packet->payload[command_start + 4] == 'E' || packet->payload[command_start + 4] == 'e')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "STORE", 5) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } } if((command_start + 12) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'A' || packet->payload[command_start] == 'a') - && (packet->payload[command_start + 1] == 'U' || packet->payload[command_start + 1] == 'u') - && (packet->payload[command_start + 2] == 'T' || packet->payload[command_start + 2] == 't') - && (packet->payload[command_start + 3] == 'H' || packet->payload[command_start + 3] == 'h') - && (packet->payload[command_start + 4] == 'E' || packet->payload[command_start + 4] == 'e') - && (packet->payload[command_start + 5] == 'N' || packet->payload[command_start + 5] == 'n') - && (packet->payload[command_start + 6] == 'T' || packet->payload[command_start + 6] == 't') - && (packet->payload[command_start + 7] == 'I' || packet->payload[command_start + 7] == 'i') - && (packet->payload[command_start + 8] == 'C' || packet->payload[command_start + 8] == 'c') - && (packet->payload[command_start + 9] == 'A' || packet->payload[command_start + 9] == 'a') - && (packet->payload[command_start + 10] == 'T' || packet->payload[command_start + 10] == 't') - && (packet->payload[command_start + 11] == 'E' || packet->payload[command_start + 11] == 'e')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "AUTHENTICATE", 12) == 0) { + SAFE_INC_IMAP_STAGE(flow); /* Authenticate phase may have multiple messages. Ignore them since they are somehow encrypted anyway. */ ndpi_int_mail_imap_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAPS); @@ -248,70 +200,35 @@ static void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_ } } if((command_start + 9) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'N' || packet->payload[command_start] == 'n') - && (packet->payload[command_start + 1] == 'A' || packet->payload[command_start + 1] == 'a') - && (packet->payload[command_start + 2] == 'M' || packet->payload[command_start + 2] == 'm') - && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e') - && (packet->payload[command_start + 4] == 'S' || packet->payload[command_start + 4] == 's') - && (packet->payload[command_start + 5] == 'P' || packet->payload[command_start + 5] == 'p') - && (packet->payload[command_start + 6] == 'A' || packet->payload[command_start + 6] == 'a') - && (packet->payload[command_start + 7] == 'C' || packet->payload[command_start + 7] == 'c') - && (packet->payload[command_start + 8] == 'E' || packet->payload[command_start + 8] == 'e')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "NAMESPACE", 9) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } } if((command_start + 4) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l') - && (packet->payload[command_start + 1] == 'S' || packet->payload[command_start + 1] == 's') - && (packet->payload[command_start + 2] == 'U' || packet->payload[command_start + 2] == 'u') - && (packet->payload[command_start + 3] == 'B' || packet->payload[command_start + 3] == 'b')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "LSUB", 4) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l') - && (packet->payload[command_start + 1] == 'I' || packet->payload[command_start + 1] == 'i') - && (packet->payload[command_start + 2] == 'S' || packet->payload[command_start + 2] == 's') - && (packet->payload[command_start + 3] == 'T' || packet->payload[command_start + 3] == 't')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "LIST", 4) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'N' || packet->payload[command_start] == 'n') - && (packet->payload[command_start + 1] == 'O' || packet->payload[command_start + 1] == 'o') - && (packet->payload[command_start + 2] == 'O' || packet->payload[command_start + 2] == 'o') - && (packet->payload[command_start + 3] == 'P' || packet->payload[command_start + 3] == 'p')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "NOOP", 4) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'I' || packet->payload[command_start] == 'i') - && (packet->payload[command_start + 1] == 'D' || packet->payload[command_start + 1] == 'd') - && (packet->payload[command_start + 2] == 'L' || packet->payload[command_start + 2] == 'l') - && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "IDLE", 4) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } } if((command_start + 6) < packet->payload_packet_len) { - if((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's') - && (packet->payload[command_start + 1] == 'E' || packet->payload[command_start + 1] == 'e') - && (packet->payload[command_start + 2] == 'L' || packet->payload[command_start + 2] == 'l') - && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e') - && (packet->payload[command_start + 4] == 'C' || packet->payload[command_start + 4] == 'c') - && (packet->payload[command_start + 5] == 'T' || packet->payload[command_start + 5] == 't')) { - flow->l4.tcp.mail_imap_stage += 1; + if(ndpi_memcasecmp(packet->payload + command_start, "SELECT", 6) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'E' || packet->payload[command_start] == 'e') - && (packet->payload[command_start + 1] == 'X' || packet->payload[command_start + 1] == 'x') - && (packet->payload[command_start + 2] == 'I' || packet->payload[command_start + 2] == 'i') - && (packet->payload[command_start + 3] == 'S' || packet->payload[command_start + 3] == 's') - && (packet->payload[command_start + 4] == 'T' || packet->payload[command_start + 4] == 't') - && (packet->payload[command_start + 5] == 'S' || packet->payload[command_start + 5] == 's')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "EXISTS", 6) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; - } else if((packet->payload[command_start] == 'A' || packet->payload[command_start] == 'a') - && (packet->payload[command_start + 1] == 'P' || packet->payload[command_start + 1] == 'p') - && (packet->payload[command_start + 2] == 'P' || packet->payload[command_start + 2] == 'p') - && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e') - && (packet->payload[command_start + 4] == 'N' || packet->payload[command_start + 4] == 'n') - && (packet->payload[command_start + 5] == 'D' || packet->payload[command_start + 5] == 'd')) { - flow->l4.tcp.mail_imap_stage += 1; + } else if(ndpi_memcasecmp(packet->payload + command_start, "APPEND", 6) == 0) { + SAFE_INC_IMAP_STAGE(flow); saw_command = 1; } } diff --git a/src/lib/protocols/mail_pop.c b/src/lib/protocols/mail_pop.c index 88497a22a..2ba8b8d5e 100644 --- a/src/lib/protocols/mail_pop.c +++ b/src/lib/protocols/mail_pop.c @@ -63,22 +63,13 @@ static int ndpi_int_mail_pop_check_for_client_commands(struct ndpi_detection_mod struct ndpi_packet_struct *packet = &ndpi_struct->packet; if(packet->payload_packet_len > 4) { - if((packet->payload[0] == 'A' || packet->payload[0] == 'a') - && (packet->payload[1] == 'U' || packet->payload[1] == 'u') - && (packet->payload[2] == 'T' || packet->payload[2] == 't') - && (packet->payload[3] == 'H' || packet->payload[3] == 'h')) { + if(ndpi_memcasecmp(packet->payload, "AUTH", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_AUTH; return 1; - } else if((packet->payload[0] == 'A' || packet->payload[0] == 'a') - && (packet->payload[1] == 'P' || packet->payload[1] == 'p') - && (packet->payload[2] == 'O' || packet->payload[2] == 'o') - && (packet->payload[3] == 'P' || packet->payload[3] == 'p')) { + } else if(ndpi_memcasecmp(packet->payload, "APOP", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_APOP; return 1; - } else if((packet->payload[0] == 'U' || packet->payload[0] == 'u') - && (packet->payload[1] == 'S' || packet->payload[1] == 's') - && (packet->payload[2] == 'E' || packet->payload[2] == 'e') - && (packet->payload[3] == 'R' || packet->payload[3] == 'r')) { + } else if(ndpi_memcasecmp(packet->payload, "USER", 4) == 0) { char buf[64]; ndpi_user_pwd_payload_copy((u_int8_t*)flow->l4.tcp.ftp_imap_pop_smtp.username, @@ -91,10 +82,7 @@ static int ndpi_int_mail_pop_check_for_client_commands(struct ndpi_detection_mod flow->l4.tcp.pop_command_bitmask |= POP_BIT_USER; return 1; - } else if((packet->payload[0] == 'P' || packet->payload[0] == 'p') - && (packet->payload[1] == 'A' || packet->payload[1] == 'a') - && (packet->payload[2] == 'S' || packet->payload[2] == 's') - && (packet->payload[3] == 'S' || packet->payload[3] == 's')) { + } else if(ndpi_memcasecmp(packet->payload, "PASS", 4) == 0) { ndpi_user_pwd_payload_copy((u_int8_t*)flow->l4.tcp.ftp_imap_pop_smtp.password, sizeof(flow->l4.tcp.ftp_imap_pop_smtp.password), 5, packet->payload, packet->payload_packet_len); @@ -102,46 +90,25 @@ static int ndpi_int_mail_pop_check_for_client_commands(struct ndpi_detection_mod ndpi_set_risk(ndpi_struct, flow, NDPI_CLEAR_TEXT_CREDENTIALS, "Found password"); flow->l4.tcp.pop_command_bitmask |= POP_BIT_PASS; return 1; - } else if((packet->payload[0] == 'C' || packet->payload[0] == 'c') - && (packet->payload[1] == 'A' || packet->payload[1] == 'a') - && (packet->payload[2] == 'P' || packet->payload[2] == 'p') - && (packet->payload[3] == 'A' || packet->payload[3] == 'a')) { + } else if(ndpi_memcasecmp(packet->payload, "CAPA", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_CAPA; return 1; - } else if((packet->payload[0] == 'L' || packet->payload[0] == 'l') - && (packet->payload[1] == 'I' || packet->payload[1] == 'i') - && (packet->payload[2] == 'S' || packet->payload[2] == 's') - && (packet->payload[3] == 'T' || packet->payload[3] == 't')) { + } else if(ndpi_memcasecmp(packet->payload, "LIST", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_LIST; return 1; - } else if((packet->payload[0] == 'S' || packet->payload[0] == 's') - && (packet->payload[1] == 'T' || packet->payload[1] == 't') - && (packet->payload[2] == 'A' || packet->payload[2] == 'a') - && (packet->payload[3] == 'T' || packet->payload[3] == 't')) { + } else if(ndpi_memcasecmp(packet->payload, "STAT", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_STAT; return 1; - } else if((packet->payload[0] == 'U' || packet->payload[0] == 'u') - && (packet->payload[1] == 'I' || packet->payload[1] == 'i') - && (packet->payload[2] == 'D' || packet->payload[2] == 'd') - && (packet->payload[3] == 'L' || packet->payload[3] == 'l')) { + } else if(ndpi_memcasecmp(packet->payload, "UIDL", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_UIDL; return 1; - } else if((packet->payload[0] == 'R' || packet->payload[0] == 'r') - && (packet->payload[1] == 'E' || packet->payload[1] == 'e') - && (packet->payload[2] == 'T' || packet->payload[2] == 't') - && (packet->payload[3] == 'R' || packet->payload[3] == 'r')) { + } else if(ndpi_memcasecmp(packet->payload, "RETR", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_RETR; return 1; - } else if((packet->payload[0] == 'D' || packet->payload[0] == 'd') - && (packet->payload[1] == 'E' || packet->payload[1] == 'e') - && (packet->payload[2] == 'L' || packet->payload[2] == 'l') - && (packet->payload[3] == 'E' || packet->payload[3] == 'e')) { + } else if(ndpi_memcasecmp(packet->payload, "DELE", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_DELE; return 1; - } else if((packet->payload[0] == 'S' || packet->payload[0] == 's') - && (packet->payload[1] == 'T' || packet->payload[1] == 't') - && (packet->payload[2] == 'L' || packet->payload[2] == 'l') - && (packet->payload[3] == 'S' || packet->payload[3] == 's')) { + } else if(ndpi_memcasecmp(packet->payload, "STLS", 4) == 0) { flow->l4.tcp.pop_command_bitmask |= POP_BIT_STLS; flow->l4.tcp.mail_imap_starttls = 1; return 1; @@ -162,12 +129,9 @@ static void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct NDPI_LOG_DBG(ndpi_struct, "search mail_pop\n"); if((packet->payload_packet_len > 3 - && (packet->payload[0] == '+' && (packet->payload[1] == 'O' || packet->payload[1] == 'o') - && (packet->payload[2] == 'K' || packet->payload[2] == 'k'))) + && ndpi_memcasecmp(packet->payload, "+OK", 3) == 0) || (packet->payload_packet_len > 4 - && (packet->payload[0] == '-' && (packet->payload[1] == 'E' || packet->payload[1] == 'e') - && (packet->payload[2] == 'R' || packet->payload[2] == 'r') - && (packet->payload[3] == 'R' || packet->payload[3] == 'r')))) { + && ndpi_memcasecmp(packet->payload, "-ERR", 4) == 0)) { // +OK or -ERR seen flow->l4.tcp.mail_pop_stage += 1; if(packet->payload[0] == '+' && flow->l4.tcp.mail_imap_starttls == 1) { diff --git a/src/lib/protocols/mail_smtp.c b/src/lib/protocols/mail_smtp.c index 13da69117..9a968f622 100644 --- a/src/lib/protocols/mail_smtp.c +++ b/src/lib/protocols/mail_smtp.c @@ -179,38 +179,21 @@ static void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_ // expected client requests if(packet->line[a].len >= 5) { - if((((packet->line[a].ptr[0] == 'H' || packet->line[a].ptr[0] == 'h') - && (packet->line[a].ptr[1] == 'E' || packet->line[a].ptr[1] == 'e')) - || ((packet->line[a].ptr[0] == 'E' || packet->line[a].ptr[0] == 'e') - && (packet->line[a].ptr[1] == 'H' || packet->line[a].ptr[1] == 'h'))) - && (packet->line[a].ptr[2] == 'L' || packet->line[a].ptr[2] == 'l') - && (packet->line[a].ptr[3] == 'O' || packet->line[a].ptr[3] == 'o') - && packet->line[a].ptr[4] == ' ') { + if(ndpi_memcasecmp(packet->line[a].ptr, "HELO ", 5) == 0 || + ndpi_memcasecmp(packet->line[a].ptr, "EHLO ", 5) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_HELO_EHLO; flow->l4.tcp.ftp_imap_pop_smtp.auth_found = 0; - } else if((packet->line[a].ptr[0] == 'M' || packet->line[a].ptr[0] == 'm') - && (packet->line[a].ptr[1] == 'A' || packet->line[a].ptr[1] == 'a') - && (packet->line[a].ptr[2] == 'I' || packet->line[a].ptr[2] == 'i') - && (packet->line[a].ptr[3] == 'L' || packet->line[a].ptr[3] == 'l') - && packet->line[a].ptr[4] == ' ') { + } else if(ndpi_memcasecmp(packet->line[a].ptr, "MAIL ", 5) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_MAIL; flow->l4.tcp.ftp_imap_pop_smtp.auth_found = 0; /* We shouldn't be here if there are credentials */ flow->l4.tcp.ftp_imap_pop_smtp.auth_done = 1; - } else if((packet->line[a].ptr[0] == 'R' || packet->line[a].ptr[0] == 'r') - && (packet->line[a].ptr[1] == 'C' || packet->line[a].ptr[1] == 'c') - && (packet->line[a].ptr[2] == 'P' || packet->line[a].ptr[2] == 'p') - && (packet->line[a].ptr[3] == 'T' || packet->line[a].ptr[3] == 't') - && packet->line[a].ptr[4] == ' ') { + } else if(ndpi_memcasecmp(packet->line[a].ptr, "RCPT ", 5) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_RCPT; flow->l4.tcp.ftp_imap_pop_smtp.auth_found = 0; /* We shouldn't be here if there are credentials */ flow->l4.tcp.ftp_imap_pop_smtp.auth_done = 1; - } else if((packet->line[a].ptr[0] == 'A' || packet->line[a].ptr[0] == 'a') - && (packet->line[a].ptr[1] == 'U' || packet->line[a].ptr[1] == 'u') - && (packet->line[a].ptr[2] == 'T' || packet->line[a].ptr[2] == 't') - && (packet->line[a].ptr[3] == 'H' || packet->line[a].ptr[3] == 'h') - && packet->line[a].ptr[4] == ' ') { + } else if(ndpi_memcasecmp(packet->line[a].ptr, "AUTH ", 5) == 0) { #ifdef SMTP_DEBUG printf("%s() AUTH [%.*s]\n", __FUNCTION__, packet->line[a].len, packet->line[a].ptr); #endif @@ -301,14 +284,7 @@ static void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_ } if(packet->line[a].len >= 8) { - if((packet->line[a].ptr[0] == 'S' || packet->line[a].ptr[0] == 's') - && (packet->line[a].ptr[1] == 'T' || packet->line[a].ptr[1] == 't') - && (packet->line[a].ptr[2] == 'A' || packet->line[a].ptr[2] == 'a') - && (packet->line[a].ptr[3] == 'R' || packet->line[a].ptr[3] == 'r') - && (packet->line[a].ptr[4] == 'T' || packet->line[a].ptr[4] == 't') - && (packet->line[a].ptr[5] == 'T' || packet->line[a].ptr[5] == 't') - && (packet->line[a].ptr[6] == 'L' || packet->line[a].ptr[6] == 'l') - && (packet->line[a].ptr[7] == 'S' || packet->line[a].ptr[7] == 's')) { + if(ndpi_memcasecmp(packet->line[a].ptr, "STARTTLS", 8) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_STARTTLS; flow->l4.tcp.ftp_imap_pop_smtp.auth_tls = 1; flow->l4.tcp.ftp_imap_pop_smtp.auth_done = 0; @@ -316,20 +292,7 @@ static void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_ } if(packet->line[a].len >= 14) { - if((packet->line[a].ptr[0] == 'X' || packet->line[a].ptr[0] == 'x') - && (packet->line[a].ptr[1] == '-' || packet->line[a].ptr[1] == '-') - && (packet->line[a].ptr[2] == 'A' || packet->line[a].ptr[2] == 'a') - && (packet->line[a].ptr[3] == 'N' || packet->line[a].ptr[3] == 'n') - && (packet->line[a].ptr[4] == 'O' || packet->line[a].ptr[4] == 'o') - && (packet->line[a].ptr[5] == 'N' || packet->line[a].ptr[5] == 'n') - && (packet->line[a].ptr[6] == 'Y' || packet->line[a].ptr[6] == 'y') - && (packet->line[a].ptr[7] == 'M' || packet->line[a].ptr[6] == 'm') - && (packet->line[a].ptr[8] == 'O' || packet->line[a].ptr[6] == 'o') - && (packet->line[a].ptr[9] == 'U' || packet->line[a].ptr[6] == 'u') - && (packet->line[a].ptr[10] == 'S' || packet->line[a].ptr[6] == 's') - && (packet->line[a].ptr[11] == 'T' || packet->line[a].ptr[6] == 't') - && (packet->line[a].ptr[12] == 'L' || packet->line[a].ptr[6] == 'l') - && (packet->line[a].ptr[13] == 'S' || packet->line[a].ptr[7] == 's')) { + if(ndpi_memcasecmp(packet->line[a].ptr, "X-AnonymousTLS", 14) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_STARTTLS; flow->l4.tcp.ftp_imap_pop_smtp.auth_tls = 1; flow->l4.tcp.ftp_imap_pop_smtp.auth_done = 0; @@ -337,20 +300,11 @@ static void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_ } if(packet->line[a].len >= 4) { - if((packet->line[a].ptr[0] == 'D' || packet->line[a].ptr[0] == 'd') - && (packet->line[a].ptr[1] == 'A' || packet->line[a].ptr[1] == 'a') - && (packet->line[a].ptr[2] == 'T' || packet->line[a].ptr[2] == 't') - && (packet->line[a].ptr[3] == 'A' || packet->line[a].ptr[3] == 'a')) { + if(ndpi_memcasecmp(packet->line[a].ptr, "DATA", 4) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_DATA; - } else if((packet->line[a].ptr[0] == 'N' || packet->line[a].ptr[0] == 'n') - && (packet->line[a].ptr[1] == 'O' || packet->line[a].ptr[1] == 'o') - && (packet->line[a].ptr[2] == 'O' || packet->line[a].ptr[2] == 'o') - && (packet->line[a].ptr[3] == 'P' || packet->line[a].ptr[3] == 'p')) { + } else if(ndpi_memcasecmp(packet->line[a].ptr, "NOOP", 4) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_NOOP; - } else if((packet->line[a].ptr[0] == 'R' || packet->line[a].ptr[0] == 'r') - && (packet->line[a].ptr[1] == 'S' || packet->line[a].ptr[1] == 's') - && (packet->line[a].ptr[2] == 'E' || packet->line[a].ptr[2] == 'e') - && (packet->line[a].ptr[3] == 'T' || packet->line[a].ptr[3] == 't')) { + } else if(ndpi_memcasecmp(packet->line[a].ptr, "RSET", 4) == 0) { flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_RSET; } } |