47 #define PRINTABLE_START 33
48 #define PRINTABLE_END 126
57 #define BASE64_STR "Base64"
60 #define MAX_LINE_LEN 998
61 #define MAX_ENC_LINE_LEN 76
62 #define MAX_HEADER_NAME 75
63 #define MAX_HEADER_VALUE 2000
64 #define BOUNDARY_BUF 256
65 #define CTNT_TYPE_STR "content-type"
66 #define CTNT_DISP_STR "content-disposition"
67 #define CTNT_TRAN_STR "content-transfer-encoding"
68 #define MSG_ID_STR "message-id"
69 #define MSG_STR "message/"
70 #define MULTIPART_STR "multipart/"
71 #define QP_STR "quoted-printable"
72 #define TXT_STR "text/plain"
73 #define HTML_STR "text/html"
76 #define STACK_FREE_NODES 10
79 #define MAX_IP4_CHARS 15
80 #define MAX_IP6_CHARS 39
86 static const char *StateFlags[] = {
"NONE",
98 static const char *UrlExeExts[] = {
".exe",
".vbs",
".bin",
".cmd",
".bat",
".jar",
".js",
".ps",
99 ".ps1",
".sh",
".run",
".hta",
".bin",
".elf", NULL };
111 static void PrintChars(
int log_level,
const char *label,
const uint8_t *
src, uint32_t
len)
115 printf(
"[%s]\n", label);
129 if (config != NULL) {
130 mime_dec_config = *config;
148 return &mime_dec_config;
163 while(node->
next != NULL)
181 while (entity != NULL)
184 if (entity->
child != NULL) {
186 entity->
child = NULL;
187 lastSibling = findLastSibling(lastSibling);
192 (
next != NULL && entity == lastSibling) || (
next == NULL && entity != lastSibling));
216 while (curr != NULL) {
245 while (curr != NULL) {
303 while (curr != NULL) {
305 if (strlen(name) == curr->
name_len) {
329 while (curr != NULL) {
331 if (strlen(name) == curr->
name_len) {
394 if (parent != NULL) {
395 if (parent->
child == NULL) {
396 parent->
child = node;
398 curr = parent->
child;
399 while (curr->
next != NULL) {
426 MimeDecEntity *entity, uint8_t **name, uint32_t nlen, uint8_t **value, uint32_t vlen)
428 if (nlen == 0 && vlen == 0)
440 for (uint32_t u = 0; u < nlen; u++)
443 field->
name = (uint8_t *)n;
449 field->
value = (uint8_t *)*value;
534 while (curr != NULL) {
545 while (curr != NULL) {
574 while (curr->
next != NULL) {
597 while (curr != NULL) {
617 static uint8_t *GetFullValue(
const DataValue *dv, uint32_t *olen)
625 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
634 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
654 static inline uint8_t *FindBuffer(
655 const uint8_t *
src, uint32_t
len,
const uint8_t *find, uint16_t find_len)
671 static uint8_t * GetLine(uint8_t *buf, uint32_t blen, uint8_t **remainPtr,
689 for (i = 0; i < blen && buf[i] != 0; i++) {
692 if (buf[i] ==
CR || buf[i] ==
LF) {
695 *remainPtr += (i + 1);
696 if ((i + 1 < blen) && buf[i] != buf[i + 1] &&
697 (buf[i + 1] ==
CR || buf[i + 1] ==
LF)) {
705 if (buf == *remainPtr) {
710 *tokLen = (buf + i) - tok;
726 static uint8_t * GetToken(uint8_t *buf, uint32_t blen,
const char *delims,
727 uint8_t **remainPtr, uint32_t *tokenLen)
729 uint32_t i, j, delimFound = 0;
742 for (i = 0; i < blen && buf[i] != 0; i++) {
745 for (j = 0; delims[j] != 0; j++) {
746 if (buf[i] == delims[j]) {
749 (*remainPtr) += (i + 1);
757 if (tok == NULL && !delimFound) {
765 if (buf != *remainPtr) {
772 if (buf == *remainPtr) {
777 *tokenLen = (buf + i) - tok;
796 if (state->
hname != NULL || state->
hvalue != NULL) {
799 uint8_t *val = GetFullValue(state->
hvalue, &vlen);
801 if (state->
hname == NULL) {
802 SCLogDebug(
"Error: Invalid parser state - header value without"
806 }
else if (state->
stack->
top != NULL) {
817 if (state->
hvalue != NULL) {
826 FreeDataValue(state->
hvalue);
844 static int IsExeUrl(
const uint8_t *url, uint32_t
len)
851 for (i = 0; UrlExeExts[i] != NULL; i++) {
852 extLen = strlen(UrlExeExts[i]);
853 ext = FindBuffer(url,
len, (uint8_t *)UrlExeExts[i], (uint16_t)strlen(UrlExeExts[i]));
854 if (ext != NULL && (ext + extLen - url == (
int)
len || ext[extLen] ==
'?')) {
872 static int IsIpv4Host(
const uint8_t *urlhost, uint32_t
len)
874 struct sockaddr_in sa;
879 for ( ; i <
len && urlhost[i] != 0; i++) {
881 if (urlhost[i] ==
'/') {
892 memcpy(tempIp, urlhost, i);
898 return inet_pton(AF_INET, tempIp, &(sa.sin_addr));
910 static int IsIpv6Host(
const uint8_t *urlhost, uint32_t
len)
917 for (i = 0; i <
len && urlhost[i] != 0; i++) {
918 if (urlhost[i] ==
'/') {
929 memcpy(tempIp, urlhost, i);
935 return inet_pton(AF_INET6, tempIp, &in6);
952 while (curr != NULL) {
953 if (url_len == curr->
url_len) {
984 static int FindUrlStrings(
const uint8_t *line, uint32_t
len,
990 uint8_t *fptr, *remptr, *tok = NULL, *tempUrl, *urlHost;
991 uint32_t tokLen = 0, i, tempUrlLen, urlHostLen;
992 uint16_t schemeStrLen = 0;
995 char *schemeStr = NULL;
997 if (mdcfg != NULL && mdcfg->extract_urls_schemes == NULL) {
998 SCLogDebug(
"Error: MIME config extract_urls_schemes was NULL.");
1003 schemeStr = scheme->
val;
1005 schemeStrLen = (uint16_t)strlen(schemeStr);
1007 remptr = (uint8_t *)line;
1009 SCLogDebug(
"Looking for URL String starting with: %s", schemeStr);
1012 fptr = FindBuffer(remptr,
len - (remptr - line), (uint8_t *)schemeStr, schemeStrLen);
1014 if (!mdcfg->log_url_scheme) {
1015 fptr += schemeStrLen;
1017 tok = GetToken(fptr,
len - (fptr - line),
" \"\'<>]\t", &remptr, &tokLen);
1031 for (i = 0; i < tokLen && tok[i] != 0; i++) {
1038 urlHostLen = tempUrlLen;
1039 if (mdcfg->log_url_scheme) {
1045 urlHost += schemeStrLen;
1046 urlHostLen -= schemeStrLen;
1050 if (IsExeUrl(tempUrl, tempUrlLen)) {
1053 PrintChars(
SC_LOG_DEBUG,
"EXE URL", tempUrl, tempUrlLen);
1057 if (tempUrlLen > 0) {
1058 if (!(FindExistingUrl(entity, tempUrl, tempUrlLen))) {
1060 if (IsIpv4Host(urlHost, urlHostLen)) {
1063 PrintChars(
SC_LOG_DEBUG,
"IP URL4", tempUrl, tempUrlLen);
1064 }
else if (IsIpv6Host(urlHost, urlHostLen)) {
1067 PrintChars(
SC_LOG_DEBUG,
"IP URL6", tempUrl, tempUrlLen);
1071 MimeDecAddUrl(entity, tempUrl, tempUrlLen,
flags);
1083 }
while (fptr != NULL);
1099 static int ProcessDecodedDataChunk(
const uint8_t *chunk, uint32_t
len,
1103 uint8_t *remainPtr, *tok;
1106 if ((state->
stack != NULL) && (state->
stack->
top != NULL) &&
1118 remainPtr = (uint8_t *)chunk;
1121 remainPtr,
len - (remainPtr - (uint8_t *)chunk), &remainPtr, &tokLen);
1122 if (tok != remainPtr) {
1124 ret = FindUrlStrings(tok, tokLen, state);
1126 SCLogDebug(
"Error: FindUrlStrings() function"
1132 }
while (tok != remainPtr && remainPtr - (uint8_t *)chunk < (
int)
len);
1140 SCLogDebug(
"Error: state->dataChunkProcessor() callback function"
1169 static uint32_t ProcessBase64Remainder(
1172 uint32_t buf_consumed = 0;
1186 for (uint8_t i = 0; i < state->
bvr_len; i++) {
1194 for (uint32_t i = 0; i <
len && cnt <
B64_BLOCK; i++) {
1196 block[cnt++] = buf[i];
1201 for (uint32_t i = 0; i < cnt; i++) {
1205 }
else if (!force && cnt !=
B64_BLOCK) {
1206 SCLogDebug(
"incomplete data and no buffer to backfill");
1224 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1229 uint32_t consumed_bytes = 0;
1230 uint32_t remdec = 0;
1249 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1257 SCLogDebug(
"Error: DecodeBase64() function failed");
1266 return buf_consumed;
1276 for (uint32_t i =
offset; i < buf_len; i++) {
1298 static int ProcessBase64BodyLine(
const uint8_t *buf, uint32_t
len,
1302 uint32_t numDecoded, remaining =
len,
offset = 0;
1312 return ProcessBase64BodyLineCopyRemainder(buf,
len, 0, state);
1320 uint32_t consumed = ProcessBase64Remainder(buf,
len, state, 0);
1325 uint32_t left =
len - consumed;
1328 return ProcessBase64BodyLineCopyRemainder(buf,
len, consumed, state);
1331 remaining -= consumed;
1335 while (remaining > 0 && remaining >=
B64_BLOCK) {
1336 uint32_t consumed_bytes = 0;
1343 if (consumed_bytes > remaining)
1346 uint32_t leftover_bytes = remaining - consumed_bytes;
1362 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1370 SCLogDebug(
"Error: DecodeBase64() function failed");
1376 if (consumed_bytes == 0 && leftover_bytes >
B64_BLOCK) {
1378 ret = ProcessBase64BodyLineCopyRemainder(buf,
len,
offset, state);
1380 }
else if (leftover_bytes > 0 && leftover_bytes <=
B64_BLOCK) {
1383 ret = ProcessBase64BodyLineCopyRemainder(buf,
len,
offset + consumed_bytes, state);
1388 remaining = leftover_bytes;
1389 offset += consumed_bytes;
1405 static int8_t DecodeQPChar(
char h)
1410 if (h >= 48 && h <= 57) {
1412 }
else if (h >= 65 && h <= 70) {
1434 static int ProcessQuotedPrintableBodyLine(
const uint8_t *buf, uint32_t
len,
1438 uint32_t remaining,
offset;
1440 uint8_t c, h1, h2, val;
1447 SCLogDebug(
"Error: Max encoded input line length exceeded %u > %u",
1459 while (remaining > 0) {
1473 }
else if (remaining > 1) {
1478 if (remaining < 3) {
1481 SCLogDebug(
"Error: Quoted-printable decoding failed");
1483 h1 = *(buf +
offset + 1);
1484 res = DecodeQPChar(h1);
1488 SCLogDebug(
"Error: Quoted-printable decoding failed");
1490 val = (uint8_t)(res << 4);
1491 h2 = *(buf +
offset + 2);
1492 res = DecodeQPChar(h2);
1496 SCLogDebug(
"Error: Quoted-printable decoding failed");
1531 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1550 static int ProcessBodyLine(
const uint8_t *buf, uint32_t
len,
1554 uint32_t remaining,
offset, avail, tobuf;
1564 ret = ProcessBase64BodyLine(buf,
len, state);
1566 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
1571 ret = ProcessQuotedPrintableBodyLine(buf,
len, state);
1573 SCLogDebug(
"Error: ProcessQuotedPrintableBodyLine() function "
1580 while (remaining > 0) {
1583 tobuf = avail > remaining ? remaining : avail;
1590 SCLogDebug(
"Error: Invalid Chunk length: %u",
1599 ret = ProcessDecodedDataChunk(state->
data_chunk,
1602 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1613 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1634 static uint8_t * FindMimeHeaderStart(
const uint8_t *buf, uint32_t blen, uint32_t *hlen)
1636 uint32_t i, valid = 0;
1637 uint8_t *hname = NULL;
1644 for (i = 0; i < blen && buf[i] != 0; i++) {
1650 }
else if (valid > 0 && buf[i] ==
COLON) {
1653 hname = (uint8_t *) buf + i - valid;
1675 static int FindMimeHeader(
const uint8_t *buf, uint32_t blen,
1679 uint8_t *hname, *hval = NULL;
1681 uint32_t hlen, vlen;
1682 int finish_header = 0, new_header = 0;
1688 hname = FindMimeHeaderStart(buf, blen, &hlen);
1689 if (hname != NULL) {
1695 SCLogDebug(
"Error: Header name exceeds limit (%u > %u)",
1700 hval = hname + hlen + 1;
1701 if (hval - buf >= (
int)blen) {
1705 while (hval[0] ==
' ') {
1708 if (hval - buf >= (
int)blen - 1) {
1728 }
else if (blen == 0) {
1735 SCLogDebug(
"All Header processing finished");
1741 SCLogDebug(
"Error: Header value of length (%u) is too long",
1742 state->
hvlen + vlen);
1748 dv = AddDataValue(state->
hvalue);
1752 if (state->
hvalue == NULL) {
1760 memcpy(dv->
value, buf, vlen);
1762 state->
hvlen += vlen;
1780 ret = ProcessBodyLine(buf, blen, state);
1782 SCLogDebug(
"Error: ProcessBodyLine() function failed");
1788 if (finish_header) {
1790 ret = StoreMimeHeader(state);
1792 SCLogDebug(
"Error: StoreMimeHeader() function failed");
1804 memcpy(state->
hname, hname, hlen);
1807 if (state->
hvalue != NULL) {
1808 SCLogDebug(
"Error: Parser failed due to unexpected header "
1815 vlen = blen - (hval - buf);
1817 SCLogDebug(
"Error: Header value of length (%u) is too long",
1818 state->
hvlen + vlen);
1825 state->
hvalue = AddDataValue(NULL);
1826 if (state->
hvalue == NULL) {
1835 state->
hvlen += vlen;
1853 static int ProcessMimeHeaders(
const uint8_t *buf, uint32_t
len,
1858 uint8_t *rptr = NULL;
1861 uint8_t bptr[RS_MIME_MAX_TOKEN_LEN];
1864 ret = FindMimeHeader(buf,
len, state);
1866 SCLogDebug(
"Error: FindMimeHeader() function failed: %d", ret);
1874 if (field != NULL) {
1881 (uint16_t)strlen(
QP_STR))) {
1883 SCLogDebug(
"quoted-printable encoding found");
1890 if (field != NULL) {
1891 bool truncated_name =
false;
1893 (
const uint8_t *)
"filename", strlen(
"filename"), &bptr, &blen)) {
1894 SCLogDebug(
"File attachment found in disposition");
1897 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1898 blen = RS_MIME_MAX_TOKEN_LEN;
1899 truncated_name =
true;
1907 memcpy(entity->
filename, bptr, blen);
1910 if (truncated_name) {
1919 if (field != NULL) {
1923 (
const uint8_t *)
"boundary", strlen(
"boundary"), &bptr, &blen)) {
1943 bool truncated_name =
false;
1945 (
const uint8_t *)
"name", strlen(
"name"), &bptr, &blen)) {
1949 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1950 blen = RS_MIME_MAX_TOKEN_LEN;
1951 truncated_name =
true;
1959 memcpy(entity->
filename, bptr, blen);
1962 if (truncated_name) {
1976 SCLogDebug(
"Found encapsulated message entity");
1985 PushStack(state->
stack);
2015 if (field != NULL) {
2047 SCLogDebug(
"Found (%u) remaining base64 bytes not processed",
2051 ret = ProcessBase64Remainder(NULL, 0, state, 1);
2053 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
2065 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
2085 static int ProcessMimeBoundary(
2092 SCLogDebug(
"PROCESSING BOUNDARY - START: %d",
2100 ret = ProcessBodyComplete(state);
2102 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2112 rptr = (uint8_t *) buf + bdef_len + 2;
2119 SCLogDebug(
"Error: Missing parent entity from stack");
2125 SCLogDebug(
"POPPED ENCAPSULATED CHILD FROM STACK: %p=%p",
2129 PopStack(state->
stack);
2138 if (
len - (rptr - buf) > 1 && rptr[0] ==
DASH && rptr[1] ==
DASH) {
2139 SCLogDebug(
"FOUND END BOUNDARY, POPPING: %p=%p",
2143 PopStack(state->
stack);
2152 SCLogDebug(
"FOUND END BOUNDARY AND ENCAP, POPPING: %p=%p",
2155 PopStack(state->
stack);
2172 PushStack(state->
stack);
2180 SCLogDebug(
"Error: Missing parent entity from stack");
2184 SCLogDebug(
"SIBLING CREATED, POPPING PARENT: %p=%p",
2188 PopStack(state->
stack);
2199 PushStack(state->
stack);
2221 static int ProcessMimeBody(
const uint8_t *buf, uint32_t
len,
2238 SCLogDebug(
"empty line, lets see if we skip it. We're in state %s",
2242 if (entity != NULL && mdcfg != NULL) {
2266 while (node != NULL && node->
bdef == NULL) {
2267 SCLogDebug(
"Traversing through stack for node with boundary");
2278 if (
len > 1 && buf[0] ==
'-' && buf[1] ==
'-') {
2284 SCLogDebug(
"Error: Long boundary: tlen %u > %d. Set ANOM_LONG_BOUNDARY", tlen,
2289 memcpy(temp,
"--", 2);
2293 bstart = FindBuffer(buf,
len, temp, tlen);
2294 if (bstart != NULL) {
2295 ret = ProcessMimeBoundary(buf,
len, node->
bdef_len, state);
2297 SCLogDebug(
"Error: ProcessMimeBoundary() function "
2315 ret = ProcessBodyLine(buf,
len, state);
2317 SCLogDebug(
"Error: ProcessBodyLine() function failed");
2339 static int ProcessMimeEntity(
const uint8_t *buf, uint32_t
len,
2355 SCLogDebug(
"Error: Max input line length exceeded %u > %u",
len,
2378 ret = ProcessMimeHeaders(buf,
len, state);
2380 SCLogDebug(
"Error: ProcessMimeHeaders() function failed: %d",
2388 ret = ProcessMimeBody(buf,
len, state);
2390 SCLogDebug(
"Error: ProcessMimeBody() function failed: %d",
2411 int (*DataChunkProcessorFunc)(
const uint8_t *chunk, uint32_t
len,
2440 state->
msg = mimeMsg;
2441 PushStack(state->
stack);
2466 while (state->
stack->
top != NULL) {
2470 PopStack(state->
stack);
2476 SCLogDebug(
"Warning: Stack is not empty upon completion of "
2477 "processing (%u items remaining)", cnt);
2481 FreeDataValue(state->
hvalue);
2482 FreeMimeDecStack(state->
stack);
2505 SCLogDebug(
"parser in error state: PARSE_ERROR");
2510 ret = StoreMimeHeader(state);
2512 SCLogDebug(
"Error: StoreMimeHeader() function failed");
2517 ret = ProcessBodyComplete(state);
2519 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2524 SCMd5Finalize(state->
md5_ctx, state->
md5,
sizeof(state->
md5));
2537 PopStack(state->
stack);
2548 SCLogDebug(
"Warning: Message has unclosed message part boundary");
2580 ret = ProcessMimeEntity(line,
len, state);
2583 SCLogDebug(
"Error: ProcessMimeEntity() function failed: %d", ret);
2601 int (*dcpfunc)(
const uint8_t *chunk, uint32_t
len,
2605 uint8_t *remainPtr, *tok;
2609 if (state == NULL) {
2610 SCLogDebug(
"Error: MimeDecInitParser() function failed to create "
2618 remainPtr = (uint8_t *) buf;
2619 uint8_t *line = NULL;
2621 tok = GetLine(remainPtr, blen - (remainPtr - buf), &remainPtr, &tokLen);
2622 if (tok != remainPtr) {
2626 if ((remainPtr - tok) - tokLen > UINT8_MAX) {
2627 SCLogDebug(
"Error: MimeDecParseLine() overflow: %ld", (remainPtr - tok) - tokLen);
2635 SCLogDebug(
"Error: MimeDecParseLine() function failed: %d",
2641 }
while (tok != remainPtr && remainPtr - buf < (
int)blen);
2649 SCLogDebug(
"Error: MimeDecParseComplete() function failed");
2667 static int TestDataChunkCallback(
const uint8_t *chunk, uint32_t
len,
2670 uint32_t *line_count = (uint32_t *) state->
data;
2678 if ((*line_count) == 0) {
2682 for (uint32_t i = 0; i <
len; i++) {
2683 if (chunk[i] ==
CR || chunk[i] ==
LF) {
2684 if (i + 1 <
len && chunk[i] != chunk[i + 1] &&
2685 (chunk[i + 1] ==
CR || chunk[i + 1] ==
LF)) {
2703 static int MimeDecParseLineTest01(
void)
2705 uint32_t line_count = 0;
2709 TestDataChunkCallback);
2711 const char *
str =
"From: Sender1\n";
2714 str =
"To: Recipient1\n";
2717 str =
"Content-Type: text/plain\n";
2723 str =
"A simple message line 1\n";
2726 str =
"A simple message line 2\n";
2729 str =
"A simple message line 3\n";
2749 static int MimeDecParseLineTest02(
void)
2751 uint32_t line_count = 0;
2770 TestDataChunkCallback);
2772 const char *
str =
"From: Sender1\r\n";
2775 str =
"To: Recipient1\r\n";
2778 str =
"Content-Type: text/plain\r\n";
2784 str =
"A simple message line 1\r\n";
2787 str =
"A simple message line 2 click on http://www.test.com/malware.exe?"
2788 "hahah hopefully you click this link\r\n";
2810 static int MimeFindUrlStringsTest01(
void)
2813 uint32_t line_count = 0;
2822 const char *
str =
"test";
2823 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2841 static int MimeFindUrlStringsTest02(
void)
2844 uint32_t line_count = 0;
2862 const char *
str =
"A simple message click on "
2863 "http://www.test.com/malware.exe? "
2864 "hahah hopefully you click this link";
2865 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2878 memcmp(
"www.test.com/malware.exe?",
msg->url_list->url,
msg->url_list->url_len) == 0);
2892 static int MimeFindUrlStringsTest03(
void)
2895 uint32_t line_count = 0;
2918 const char *
str =
"A simple message click on "
2919 "http://www.test.com/malware.exe? "
2920 "hahah hopefully you click this link, or "
2921 "you can go to http://www.test.com/test/01.html and "
2922 "https://www.test.com/test/02.php";
2923 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2956 static int MimeFindUrlStringsTest04(
void)
2959 uint32_t line_count = 0;
2982 const char *
str =
"A simple message click on "
2983 "http://www.test.com/malware.exe? "
2984 "hahah hopefully you click this link, or "
2985 "you can go to http://www.test.com/test/01.html and "
2986 "https://www.test.com/test/02.php";
2987 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3020 static int MimeFindUrlStringsTest05(
void)
3023 uint32_t line_count = 0;
3041 const char *
str =
"A simple message click on "
3042 "http://192.168.1.1/test/01.html "
3043 "hahah hopefully you click this link or this one "
3044 "http://0:0:0:0:0:0:0:0/test/02.php";
3045 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3076 static int MimeDecParseFullMsgTest01(
void)
3078 uint32_t expected_count = 3;
3079 uint32_t line_count = 0;
3081 char msg[] =
"From: Sender1\r\n"
3082 "To: Recipient1\r\n"
3083 "Content-Type: text/plain\r\n"
3090 TestDataChunkCallback);
3091 if (entity == NULL) {
3092 SCLogInfo(
"Warning: Message failed to parse");
3098 if (expected_count != line_count) {
3099 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d",
3100 expected_count, line_count);
3108 static int MimeDecParseFullMsgTest02(
void)
3110 uint32_t expected_count = 3;
3111 uint32_t line_count = 0;
3113 char msg[] =
"From: Sender2\r\n"
3114 "To: Recipient2\r\n"
3115 "Subject: subject2\r\n"
3116 "Content-Type: text/plain\r\n"
3123 TestDataChunkCallback);
3125 if (entity == NULL) {
3126 SCLogInfo(
"Warning: Message failed to parse");
3131 if (field == NULL) {
3132 SCLogInfo(
"Warning: Message failed to parse");
3136 if (field->
value_len !=
sizeof(
"subject2") - 1) {
3137 SCLogInfo(
"Warning: failed to get subject");
3142 SCLogInfo(
"Warning: failed to get subject");
3149 if (expected_count != line_count) {
3150 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d", expected_count,
3158 static int MimeBase64DecodeTest01(
void)
3161 uint32_t consumed_bytes = 0, num_decoded = 0;
3163 const char *
msg =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@"
3164 "#$%^&*()-=_+,./;'[]<>?:";
3165 const char *base64msg =
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QU"
3166 "VJTVFVWV1hZWjEyMzQ1Njc4OTBAIyQlXiYqKCktPV8rLC4vOydbXTw+Pzo=";
3172 ret =
DecodeBase64(
dst, strlen(
msg) + 1, (
const uint8_t *)base64msg, strlen(base64msg),
3175 if (memcmp(
dst,
msg, strlen(
msg)) == 0) {
3184 static int MimeIsExeURLTest01(
void)
3187 const char *url1 =
"http://www.google.com/";
3188 const char *url2 =
"http://www.google.com/test.exe";
3190 if(IsExeUrl((
const uint8_t *)url1, strlen(url1)) != 0){
3194 if(IsExeUrl((
const uint8_t *)url2, strlen(url2)) != 1){
3205 #define TEST(str, len, expect) { \
3206 SCLogDebug("str %s", (str)); \
3207 int r = IsIpv4Host((const uint8_t *)(str),(len)); \
3208 FAIL_IF_NOT(r == (expect)); \
3210 static int MimeIsIpv4HostTest01(
void)
3212 TEST(
"192.168.1.1", 11, 1);
3213 TEST(
"192.168.1.1.4", 13, 0);
3214 TEST(
"999.168.1.1", 11, 0);
3215 TEST(
"1111.168.1.1", 12, 0);
3216 TEST(
"999.oogle.com", 14, 0);
3217 TEST(
"0:0:0:0:0:0:0:0", 15, 0);
3218 TEST(
"192.168.255.255", 15, 1);
3219 TEST(
"192.168.255.255/testurl.html", 28, 1);
3220 TEST(
"www.google.com", 14, 0);
3225 #define TEST(str, len, expect) { \
3226 SCLogDebug("str %s", (str)); \
3227 int r = IsIpv6Host((const uint8_t *)(str),(len)); \
3228 FAIL_IF_NOT(r == (expect)); \
3230 static int MimeIsIpv6HostTest01(
void)
3232 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3233 TEST(
"0000:0000:0000:0000:0000:0000:0000:0000", 39, 1);
3234 TEST(
"XXXX:0000:0000:0000:0000:0000:0000:0000", 39, 0);
3235 TEST(
"00001:0000:0000:0000:0000:0000:0000:0000", 40, 0);
3236 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3237 TEST(
"0:0:0:0:0:0:0:0:0", 20, 0);
3238 TEST(
"192:168:1:1:0:0:0:0", 19, 1);
3239 TEST(
"999.oogle.com", 14, 0);
3240 TEST(
"192.168.255.255", 15, 0);
3241 TEST(
"192.168.255.255/testurl.html", 28, 0);
3242 TEST(
"www.google.com", 14, 0);
3247 static int MimeDecParseLongFilename01(
void)
3250 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3251 "12characters12characters12characters12characters"
3252 "12characters12characters12characters12characters"
3253 "12characters12characters12characters12characters"
3254 "12characters12characters12characters12characters"
3255 "12characters12characters12characters12characters"
3256 "12characters12characters12characters.exe\"";
3258 uint32_t line_count = 0;
3266 TestDataChunkCallback);
3268 const char *
str =
"From: Sender1";
3271 str =
"To: Recipient1";
3274 str =
"Content-Type: text/plain";
3283 str =
"A simple message line 1";
3303 static int MimeDecParseSmallRemInp(
void)
3307 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3309 uint32_t line_count = 0;
3319 const char *
str =
"From: Sender1";
3322 str =
"To: Recipient1";
3325 str =
"Content-Type: text/plain";
3328 str =
"Content-Transfer-Encoding: base64";
3356 static int MimeDecParseRemSp(
void)
3359 char mimemsg[] =
"TWltZSBkZWNvZGluZyBpc yBzbyBOT1QgZnVuISBJIGNhbm5vd A";
3361 uint32_t line_count = 0;
3371 const char *
str =
"From: Sender1";
3374 str =
"To: Recipient1";
3377 str =
"Content-Type: text/plain";
3380 str =
"Content-Transfer-Encoding: base64";
3404 static int MimeDecVerySmallInp(
void)
3408 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vA";
3410 uint32_t line_count = 0;
3420 const char *
str =
"From: Sender1";
3423 str =
"To: Recipient1";
3426 str =
"Content-Type: text/plain";
3429 str =
"Content-Transfer-Encoding: base64";
3457 static int MimeDecParseOddLen(
void)
3459 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3461 uint32_t line_count = 0;
3471 const char *
str =
"From: Sender1";
3474 str =
"To: Recipient1";
3477 str =
"Content-Type: text/plain";
3480 str =
"Content-Transfer-Encoding: base64";
3504 static int MimeDecParseLongFilename02(
void)
3507 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3508 "12characters12characters12characters.exe\"; "
3509 "somejunkasfdasfsafasafdsasdasassdssdsd"
3510 "somejunkasfdasfsafasafdsasdasassdssdsd"
3511 "somejunkasfdasfsafasafdsasdasassdssdsd"
3512 "somejunkasfdasfsafasafdsasdasassdssdsd"
3513 "somejunkasfdasfsafasafdsasdasassdssdsd"
3514 "somejunkasfdasfsafasafdsasdasassdssdsd"
3515 "somejunkasfdasfsafasafdsasdasassdssdsd"
3516 "somejunkasfdasfsafasafdsasdasassdssdsd"
3517 "somejunkasfdasfsafasafdsasdasassdssdsd"
3518 "somejunkasfdasfsafasafdsasdasassdssdsd"
3519 "somejunkasfdasfsafasafdsasdasassdssdsd"
3520 "somejunkasfdasfsafasafdsasdasassdssdsd"
3521 "somejunkasfdasfsafasafdsasdasassdssdsd";
3523 uint32_t line_count = 0;
3531 TestDataChunkCallback);
3533 const char *
str =
"From: Sender1";
3536 str =
"To: Recipient1";
3539 str =
"Content-Type: text/plain";
3548 str =
"A simple message line 1";
3573 UtRegisterTest(
"MimeDecParseLineTest01", MimeDecParseLineTest01);
3574 UtRegisterTest(
"MimeDecParseLineTest02", MimeDecParseLineTest02);
3575 UtRegisterTest(
"MimeFindUrlStringsTest01", MimeFindUrlStringsTest01);
3576 UtRegisterTest(
"MimeFindUrlStringsTest02", MimeFindUrlStringsTest02);
3577 UtRegisterTest(
"MimeFindUrlStringsTest03", MimeFindUrlStringsTest03);
3578 UtRegisterTest(
"MimeFindUrlStringsTest04", MimeFindUrlStringsTest04);
3579 UtRegisterTest(
"MimeFindUrlStringsTest05", MimeFindUrlStringsTest05);
3580 UtRegisterTest(
"MimeDecParseFullMsgTest01", MimeDecParseFullMsgTest01);
3581 UtRegisterTest(
"MimeDecParseFullMsgTest02", MimeDecParseFullMsgTest02);
3582 UtRegisterTest(
"MimeBase64DecodeTest01", MimeBase64DecodeTest01);
3586 UtRegisterTest(
"MimeDecParseLongFilename01", MimeDecParseLongFilename01);
3587 UtRegisterTest(
"MimeDecParseLongFilename02", MimeDecParseLongFilename02);
3588 UtRegisterTest(
"MimeDecParseSmallRemInp", MimeDecParseSmallRemInp);