aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/ndpiReader.c55
-rw-r--r--src/include/ndpi_api.h21
-rw-r--r--src/lib/ndpi_main.c47
-rw-r--r--src/lib/protocols/mail_imap.c183
-rw-r--r--src/lib/protocols/mail_pop.c62
-rw-r--r--src/lib/protocols/mail_smtp.c66
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;
}
}