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) {
302 while (curr != NULL) {
304 if (strlen(name) == curr->
name_len) {
328 while (curr != NULL) {
330 if (strlen(name) == curr->
name_len) {
391 if (parent != NULL) {
392 if (parent->
child == NULL) {
393 parent->
child = node;
421 MimeDecEntity *entity, uint8_t **name, uint32_t nlen, uint8_t **value, uint32_t vlen)
423 if (nlen == 0 && vlen == 0)
435 for (uint32_t u = 0; u < nlen; u++)
438 field->
name = (uint8_t *)n;
444 field->
value = (uint8_t *)*value;
529 while (curr != NULL) {
540 while (curr != NULL) {
568 while (curr->
next != NULL) {
591 while (curr != NULL) {
611 static uint8_t *GetFullValue(
const DataValue *dv, uint32_t *olen)
619 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
628 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
648 static inline uint8_t *FindBuffer(
649 const uint8_t *
src, uint32_t
len,
const uint8_t *find, uint16_t find_len)
665 static uint8_t * GetLine(uint8_t *buf, uint32_t blen, uint8_t **remainPtr,
683 for (i = 0; i < blen && buf[i] != 0; i++) {
686 if (buf[i] ==
CR || buf[i] ==
LF) {
689 *remainPtr += (i + 1);
690 if ((i + 1 < blen) && buf[i] != buf[i + 1] &&
691 (buf[i + 1] ==
CR || buf[i + 1] ==
LF)) {
699 if (buf == *remainPtr) {
704 *tokLen = (buf + i) - tok;
720 static uint8_t * GetToken(uint8_t *buf, uint32_t blen,
const char *delims,
721 uint8_t **remainPtr, uint32_t *tokenLen)
723 uint32_t i, j, delimFound = 0;
736 for (i = 0; i < blen && buf[i] != 0; i++) {
739 for (j = 0; delims[j] != 0; j++) {
740 if (buf[i] == delims[j]) {
743 (*remainPtr) += (i + 1);
751 if (tok == NULL && !delimFound) {
759 if (buf != *remainPtr) {
766 if (buf == *remainPtr) {
771 *tokenLen = (buf + i) - tok;
790 if (state->
hname != NULL || state->
hvalue != NULL) {
793 uint8_t *val = GetFullValue(state->
hvalue, &vlen);
795 if (state->
hname == NULL) {
796 SCLogDebug(
"Error: Invalid parser state - header value without"
800 }
else if (state->
stack->
top != NULL) {
811 if (state->
hvalue != NULL) {
820 FreeDataValue(state->
hvalue);
838 static int IsExeUrl(
const uint8_t *url, uint32_t
len)
845 for (i = 0; UrlExeExts[i] != NULL; i++) {
846 extLen = strlen(UrlExeExts[i]);
847 ext = FindBuffer(url,
len, (uint8_t *)UrlExeExts[i], (uint16_t)strlen(UrlExeExts[i]));
848 if (ext != NULL && (ext + extLen - url == (
int)
len || ext[extLen] ==
'?')) {
866 static int IsIpv4Host(
const uint8_t *urlhost, uint32_t
len)
868 struct sockaddr_in sa;
873 for ( ; i <
len && urlhost[i] != 0; i++) {
875 if (urlhost[i] ==
'/') {
886 memcpy(tempIp, urlhost, i);
892 return inet_pton(AF_INET, tempIp, &(sa.sin_addr));
904 static int IsIpv6Host(
const uint8_t *urlhost, uint32_t
len)
911 for (i = 0; i <
len && urlhost[i] != 0; i++) {
912 if (urlhost[i] ==
'/') {
923 memcpy(tempIp, urlhost, i);
929 return inet_pton(AF_INET6, tempIp, &in6);
946 while (curr != NULL) {
947 if (url_len == curr->
url_len) {
978 static int FindUrlStrings(
const uint8_t *line, uint32_t
len,
984 uint8_t *fptr, *remptr, *tok = NULL, *tempUrl, *urlHost;
985 uint32_t tokLen = 0, i, tempUrlLen, urlHostLen;
986 uint16_t schemeStrLen = 0;
989 char *schemeStr = NULL;
991 if (mdcfg != NULL && mdcfg->extract_urls_schemes == NULL) {
992 SCLogDebug(
"Error: MIME config extract_urls_schemes was NULL.");
997 schemeStr = scheme->
val;
999 schemeStrLen = (uint16_t)strlen(schemeStr);
1001 remptr = (uint8_t *)line;
1003 SCLogDebug(
"Looking for URL String starting with: %s", schemeStr);
1006 fptr = FindBuffer(remptr,
len - (remptr - line), (uint8_t *)schemeStr, schemeStrLen);
1008 if (!mdcfg->log_url_scheme) {
1009 fptr += schemeStrLen;
1011 tok = GetToken(fptr,
len - (fptr - line),
" \"\'<>]\t", &remptr, &tokLen);
1025 for (i = 0; i < tokLen && tok[i] != 0; i++) {
1032 urlHostLen = tempUrlLen;
1033 if (mdcfg->log_url_scheme) {
1039 urlHost += schemeStrLen;
1040 urlHostLen -= schemeStrLen;
1044 if (IsExeUrl(tempUrl, tempUrlLen)) {
1047 PrintChars(
SC_LOG_DEBUG,
"EXE URL", tempUrl, tempUrlLen);
1051 if (tempUrlLen > 0) {
1052 if (!(FindExistingUrl(entity, tempUrl, tempUrlLen))) {
1054 if (IsIpv4Host(urlHost, urlHostLen)) {
1057 PrintChars(
SC_LOG_DEBUG,
"IP URL4", tempUrl, tempUrlLen);
1058 }
else if (IsIpv6Host(urlHost, urlHostLen)) {
1061 PrintChars(
SC_LOG_DEBUG,
"IP URL6", tempUrl, tempUrlLen);
1065 MimeDecAddUrl(entity, tempUrl, tempUrlLen,
flags);
1077 }
while (fptr != NULL);
1093 static int ProcessDecodedDataChunk(
const uint8_t *chunk, uint32_t
len,
1097 uint8_t *remainPtr, *tok;
1100 if ((state->
stack != NULL) && (state->
stack->
top != NULL) &&
1112 remainPtr = (uint8_t *)chunk;
1115 remainPtr,
len - (remainPtr - (uint8_t *)chunk), &remainPtr, &tokLen);
1116 if (tok != remainPtr) {
1118 ret = FindUrlStrings(tok, tokLen, state);
1120 SCLogDebug(
"Error: FindUrlStrings() function"
1126 }
while (tok != remainPtr && remainPtr - (uint8_t *)chunk < (
int)
len);
1134 SCLogDebug(
"Error: state->dataChunkProcessor() callback function"
1163 static uint32_t ProcessBase64Remainder(
1166 uint32_t buf_consumed = 0;
1180 for (uint8_t i = 0; i < state->
bvr_len; i++) {
1190 block[
cnt++] = buf[i];
1195 for (uint32_t i = 0; i <
cnt; i++) {
1200 SCLogDebug(
"incomplete data and no buffer to backfill");
1218 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1223 uint32_t consumed_bytes = 0;
1224 uint32_t remdec = 0;
1243 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1251 SCLogDebug(
"Error: DecodeBase64() function failed");
1260 return buf_consumed;
1270 for (uint32_t i =
offset; i < buf_len; i++) {
1292 static int ProcessBase64BodyLine(
const uint8_t *buf, uint32_t
len,
1296 uint32_t numDecoded, remaining =
len,
offset = 0;
1306 return ProcessBase64BodyLineCopyRemainder(buf,
len, 0, state);
1314 uint32_t consumed = ProcessBase64Remainder(buf,
len, state, 0);
1319 uint32_t left =
len - consumed;
1322 return ProcessBase64BodyLineCopyRemainder(buf,
len, consumed, state);
1325 remaining -= consumed;
1329 while (remaining > 0 && remaining >=
B64_BLOCK) {
1330 uint32_t consumed_bytes = 0;
1337 if (consumed_bytes > remaining)
1340 uint32_t leftover_bytes = remaining - consumed_bytes;
1356 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1364 SCLogDebug(
"Error: DecodeBase64() function failed");
1370 if (consumed_bytes == 0 && leftover_bytes >
B64_BLOCK) {
1372 ret = ProcessBase64BodyLineCopyRemainder(buf,
len,
offset, state);
1374 }
else if (leftover_bytes > 0 && leftover_bytes <=
B64_BLOCK) {
1377 ret = ProcessBase64BodyLineCopyRemainder(buf,
len,
offset + consumed_bytes, state);
1382 remaining = leftover_bytes;
1383 offset += consumed_bytes;
1399 static int8_t DecodeQPChar(
char h)
1404 if (h >= 48 && h <= 57) {
1406 }
else if (h >= 65 && h <= 70) {
1428 static int ProcessQuotedPrintableBodyLine(
const uint8_t *buf, uint32_t
len,
1432 uint32_t remaining,
offset;
1434 uint8_t c, h1, h2, val;
1441 SCLogDebug(
"Error: Max encoded input line length exceeded %u > %u",
1453 while (remaining > 0) {
1467 }
else if (remaining > 1) {
1472 if (remaining < 3) {
1475 SCLogDebug(
"Error: Quoted-printable decoding failed");
1477 h1 = *(buf +
offset + 1);
1478 res = DecodeQPChar(h1);
1482 SCLogDebug(
"Error: Quoted-printable decoding failed");
1484 val = (uint8_t)(res << 4);
1485 h2 = *(buf +
offset + 2);
1486 res = DecodeQPChar(h2);
1490 SCLogDebug(
"Error: Quoted-printable decoding failed");
1525 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1544 static int ProcessBodyLine(
const uint8_t *buf, uint32_t
len,
1548 uint32_t remaining,
offset, avail, tobuf;
1558 ret = ProcessBase64BodyLine(buf,
len, state);
1560 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
1565 ret = ProcessQuotedPrintableBodyLine(buf,
len, state);
1567 SCLogDebug(
"Error: ProcessQuotedPrintableBodyLine() function "
1574 while (remaining > 0) {
1577 tobuf = avail > remaining ? remaining : avail;
1584 SCLogDebug(
"Error: Invalid Chunk length: %u",
1593 ret = ProcessDecodedDataChunk(state->
data_chunk,
1596 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1607 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1628 static uint8_t * FindMimeHeaderStart(
const uint8_t *buf, uint32_t blen, uint32_t *hlen)
1630 uint32_t i, valid = 0;
1631 uint8_t *hname = NULL;
1638 for (i = 0; i < blen && buf[i] != 0; i++) {
1644 }
else if (valid > 0 && buf[i] ==
COLON) {
1647 hname = (uint8_t *) buf + i - valid;
1669 static int FindMimeHeader(
const uint8_t *buf, uint32_t blen,
1673 uint8_t *hname, *hval = NULL;
1675 uint32_t hlen, vlen;
1676 int finish_header = 0, new_header = 0;
1682 hname = FindMimeHeaderStart(buf, blen, &hlen);
1683 if (hname != NULL) {
1689 SCLogDebug(
"Error: Header name exceeds limit (%u > %u)",
1694 hval = hname + hlen + 1;
1695 if (hval - buf >= (
int)blen) {
1699 while (hval[0] ==
' ') {
1702 if (hval - buf >= (
int)blen - 1) {
1722 }
else if (blen == 0) {
1729 SCLogDebug(
"All Header processing finished");
1735 SCLogDebug(
"Error: Header value of length (%u) is too long",
1736 state->
hvlen + vlen);
1742 dv = AddDataValue(state->
hvalue);
1746 if (state->
hvalue == NULL) {
1754 memcpy(dv->
value, buf, vlen);
1756 state->
hvlen += vlen;
1774 ret = ProcessBodyLine(buf, blen, state);
1776 SCLogDebug(
"Error: ProcessBodyLine() function failed");
1782 if (finish_header) {
1784 ret = StoreMimeHeader(state);
1786 SCLogDebug(
"Error: StoreMimeHeader() function failed");
1798 memcpy(state->
hname, hname, hlen);
1801 if (state->
hvalue != NULL) {
1802 SCLogDebug(
"Error: Parser failed due to unexpected header "
1809 vlen = blen - (hval - buf);
1811 SCLogDebug(
"Error: Header value of length (%u) is too long",
1812 state->
hvlen + vlen);
1819 state->
hvalue = AddDataValue(NULL);
1820 if (state->
hvalue == NULL) {
1829 state->
hvlen += vlen;
1847 static int ProcessMimeHeaders(
const uint8_t *buf, uint32_t
len,
1852 uint8_t *rptr = NULL;
1855 uint8_t bptr[RS_MIME_MAX_TOKEN_LEN];
1858 ret = FindMimeHeader(buf,
len, state);
1860 SCLogDebug(
"Error: FindMimeHeader() function failed: %d", ret);
1868 if (field != NULL) {
1875 (uint16_t)strlen(
QP_STR))) {
1877 SCLogDebug(
"quoted-printable encoding found");
1884 if (field != NULL) {
1885 bool truncated_name =
false;
1887 (
const uint8_t *)
"filename", strlen(
"filename"), &bptr, &blen)) {
1888 SCLogDebug(
"File attachment found in disposition");
1891 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1892 blen = RS_MIME_MAX_TOKEN_LEN;
1893 truncated_name =
true;
1901 memcpy(entity->
filename, bptr, blen);
1904 if (truncated_name) {
1913 if (field != NULL) {
1917 (
const uint8_t *)
"boundary", strlen(
"boundary"), &bptr, &blen)) {
1937 bool truncated_name =
false;
1939 (
const uint8_t *)
"name", strlen(
"name"), &bptr, &blen)) {
1943 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1944 blen = RS_MIME_MAX_TOKEN_LEN;
1945 truncated_name =
true;
1953 memcpy(entity->
filename, bptr, blen);
1956 if (truncated_name) {
1970 SCLogDebug(
"Found encapsulated message entity");
1979 PushStack(state->
stack);
2009 if (field != NULL) {
2041 SCLogDebug(
"Found (%u) remaining base64 bytes not processed",
2045 ret = ProcessBase64Remainder(NULL, 0, state, 1);
2047 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
2059 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
2079 static int ProcessMimeBoundary(
2086 SCLogDebug(
"PROCESSING BOUNDARY - START: %d",
2094 ret = ProcessBodyComplete(state);
2096 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2106 rptr = (uint8_t *) buf + bdef_len + 2;
2113 SCLogDebug(
"Error: Missing parent entity from stack");
2119 SCLogDebug(
"POPPED ENCAPSULATED CHILD FROM STACK: %p=%p",
2123 PopStack(state->
stack);
2132 if (
len - (rptr - buf) > 1 && rptr[0] ==
DASH && rptr[1] ==
DASH) {
2133 SCLogDebug(
"FOUND END BOUNDARY, POPPING: %p=%p",
2137 PopStack(state->
stack);
2146 SCLogDebug(
"FOUND END BOUNDARY AND ENCAP, POPPING: %p=%p",
2149 PopStack(state->
stack);
2166 PushStack(state->
stack);
2174 SCLogDebug(
"Error: Missing parent entity from stack");
2178 SCLogDebug(
"SIBLING CREATED, POPPING PARENT: %p=%p",
2182 PopStack(state->
stack);
2193 PushStack(state->
stack);
2215 static int ProcessMimeBody(
const uint8_t *buf, uint32_t
len,
2232 SCLogDebug(
"empty line, lets see if we skip it. We're in state %s",
2236 if (entity != NULL && mdcfg != NULL) {
2260 while (node != NULL && node->
bdef == NULL) {
2261 SCLogDebug(
"Traversing through stack for node with boundary");
2272 if (
len > 1 && buf[0] ==
'-' && buf[1] ==
'-') {
2278 SCLogDebug(
"Error: Long boundary: tlen %u > %d. Set ANOM_LONG_BOUNDARY", tlen,
2283 memcpy(temp,
"--", 2);
2287 bstart = FindBuffer(buf,
len, temp, tlen);
2288 if (bstart != NULL) {
2289 ret = ProcessMimeBoundary(buf,
len, node->
bdef_len, state);
2291 SCLogDebug(
"Error: ProcessMimeBoundary() function "
2309 ret = ProcessBodyLine(buf,
len, state);
2311 SCLogDebug(
"Error: ProcessBodyLine() function failed");
2333 static int ProcessMimeEntity(
const uint8_t *buf, uint32_t
len,
2349 SCLogDebug(
"Error: Max input line length exceeded %u > %u",
len,
2372 ret = ProcessMimeHeaders(buf,
len, state);
2374 SCLogDebug(
"Error: ProcessMimeHeaders() function failed: %d",
2382 ret = ProcessMimeBody(buf,
len, state);
2384 SCLogDebug(
"Error: ProcessMimeBody() function failed: %d",
2405 int (*DataChunkProcessorFunc)(
const uint8_t *chunk, uint32_t
len,
2431 state->
msg = mimeMsg;
2432 PushStack(state->
stack);
2458 while (state->
stack->
top != NULL) {
2462 PopStack(state->
stack);
2468 SCLogDebug(
"Warning: Stack is not empty upon completion of "
2469 "processing (%u items remaining)",
cnt);
2473 FreeDataValue(state->
hvalue);
2474 FreeMimeDecStack(state->
stack);
2497 SCLogDebug(
"parser in error state: PARSE_ERROR");
2502 ret = StoreMimeHeader(state);
2504 SCLogDebug(
"Error: StoreMimeHeader() function failed");
2509 ret = ProcessBodyComplete(state);
2511 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2516 SCMd5Finalize(state->
md5_ctx, state->
md5,
sizeof(state->
md5));
2529 PopStack(state->
stack);
2540 SCLogDebug(
"Warning: Message has unclosed message part boundary");
2572 ret = ProcessMimeEntity(line,
len, state);
2575 SCLogDebug(
"Error: ProcessMimeEntity() function failed: %d", ret);
2593 int (*dcpfunc)(
const uint8_t *chunk, uint32_t
len,
2597 uint8_t *remainPtr, *tok;
2601 if (state == NULL) {
2602 SCLogDebug(
"Error: MimeDecInitParser() function failed to create "
2610 remainPtr = (uint8_t *) buf;
2611 uint8_t *line = NULL;
2613 tok = GetLine(remainPtr, blen - (remainPtr - buf), &remainPtr, &tokLen);
2614 if (tok != remainPtr) {
2618 if ((remainPtr - tok) - tokLen > UINT8_MAX) {
2619 SCLogDebug(
"Error: MimeDecParseLine() overflow: %ld", (remainPtr - tok) - tokLen);
2627 SCLogDebug(
"Error: MimeDecParseLine() function failed: %d",
2633 }
while (tok != remainPtr && remainPtr - buf < (
int)blen);
2641 SCLogDebug(
"Error: MimeDecParseComplete() function failed");
2659 static int TestDataChunkCallback(
const uint8_t *chunk, uint32_t
len,
2662 uint32_t *line_count = (uint32_t *) state->
data;
2670 if ((*line_count) == 0) {
2674 for (uint32_t i = 0; i <
len; i++) {
2675 if (chunk[i] ==
CR || chunk[i] ==
LF) {
2676 if (i + 1 <
len && chunk[i] != chunk[i + 1] &&
2677 (chunk[i + 1] ==
CR || chunk[i + 1] ==
LF)) {
2695 static int MimeDecParseLineTest01(
void)
2697 uint32_t line_count = 0;
2701 TestDataChunkCallback);
2703 const char *
str =
"From: Sender1\n";
2706 str =
"To: Recipient1\n";
2709 str =
"Content-Type: text/plain\n";
2715 str =
"A simple message line 1\n";
2718 str =
"A simple message line 2\n";
2721 str =
"A simple message line 3\n";
2741 static int MimeDecParseLineTest02(
void)
2743 uint32_t line_count = 0;
2762 TestDataChunkCallback);
2764 const char *
str =
"From: Sender1\r\n";
2767 str =
"To: Recipient1\r\n";
2770 str =
"Content-Type: text/plain\r\n";
2776 str =
"A simple message line 1\r\n";
2779 str =
"A simple message line 2 click on http://www.test.com/malware.exe?"
2780 "hahah hopefully you click this link\r\n";
2802 static int MimeFindUrlStringsTest01(
void)
2805 uint32_t line_count = 0;
2814 const char *
str =
"test";
2815 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2833 static int MimeFindUrlStringsTest02(
void)
2836 uint32_t line_count = 0;
2854 const char *
str =
"A simple message click on "
2855 "http://www.test.com/malware.exe? "
2856 "hahah hopefully you click this link";
2857 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2870 memcmp(
"www.test.com/malware.exe?",
msg->url_list->url,
msg->url_list->url_len) == 0);
2884 static int MimeFindUrlStringsTest03(
void)
2887 uint32_t line_count = 0;
2910 const char *
str =
"A simple message click on "
2911 "http://www.test.com/malware.exe? "
2912 "hahah hopefully you click this link, or "
2913 "you can go to http://www.test.com/test/01.html and "
2914 "https://www.test.com/test/02.php";
2915 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2948 static int MimeFindUrlStringsTest04(
void)
2951 uint32_t line_count = 0;
2974 const char *
str =
"A simple message click on "
2975 "http://www.test.com/malware.exe? "
2976 "hahah hopefully you click this link, or "
2977 "you can go to http://www.test.com/test/01.html and "
2978 "https://www.test.com/test/02.php";
2979 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3012 static int MimeFindUrlStringsTest05(
void)
3015 uint32_t line_count = 0;
3033 const char *
str =
"A simple message click on "
3034 "http://192.168.1.1/test/01.html "
3035 "hahah hopefully you click this link or this one "
3036 "http://0:0:0:0:0:0:0:0/test/02.php";
3037 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3068 static int MimeDecParseFullMsgTest01(
void)
3070 uint32_t expected_count = 3;
3071 uint32_t line_count = 0;
3073 char msg[] =
"From: Sender1\r\n"
3074 "To: Recipient1\r\n"
3075 "Content-Type: text/plain\r\n"
3082 TestDataChunkCallback);
3083 if (entity == NULL) {
3084 SCLogInfo(
"Warning: Message failed to parse");
3090 if (expected_count != line_count) {
3091 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d",
3092 expected_count, line_count);
3100 static int MimeDecParseFullMsgTest02(
void)
3102 uint32_t expected_count = 3;
3103 uint32_t line_count = 0;
3105 char msg[] =
"From: Sender2\r\n"
3106 "To: Recipient2\r\n"
3107 "Subject: subject2\r\n"
3108 "Content-Type: text/plain\r\n"
3115 TestDataChunkCallback);
3117 if (entity == NULL) {
3118 SCLogInfo(
"Warning: Message failed to parse");
3123 if (field == NULL) {
3124 SCLogInfo(
"Warning: Message failed to parse");
3128 if (field->
value_len !=
sizeof(
"subject2") - 1) {
3129 SCLogInfo(
"Warning: failed to get subject");
3134 SCLogInfo(
"Warning: failed to get subject");
3141 if (expected_count != line_count) {
3142 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d", expected_count,
3150 static int MimeBase64DecodeTest01(
void)
3153 uint32_t consumed_bytes = 0, num_decoded = 0;
3155 const char *
msg =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@"
3156 "#$%^&*()-=_+,./;'[]<>?:";
3157 const char *base64msg =
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QU"
3158 "VJTVFVWV1hZWjEyMzQ1Njc4OTBAIyQlXiYqKCktPV8rLC4vOydbXTw+Pzo=";
3164 ret =
DecodeBase64(
dst, strlen(
msg) + 1, (
const uint8_t *)base64msg, strlen(base64msg),
3167 if (memcmp(
dst,
msg, strlen(
msg)) == 0) {
3176 static int MimeIsExeURLTest01(
void)
3179 const char *url1 =
"http://www.google.com/";
3180 const char *url2 =
"http://www.google.com/test.exe";
3182 if(IsExeUrl((
const uint8_t *)url1, strlen(url1)) != 0){
3186 if(IsExeUrl((
const uint8_t *)url2, strlen(url2)) != 1){
3197 #define TEST(str, len, expect) { \
3198 SCLogDebug("str %s", (str)); \
3199 int r = IsIpv4Host((const uint8_t *)(str),(len)); \
3200 FAIL_IF_NOT(r == (expect)); \
3202 static int MimeIsIpv4HostTest01(
void)
3204 TEST(
"192.168.1.1", 11, 1);
3205 TEST(
"192.168.1.1.4", 13, 0);
3206 TEST(
"999.168.1.1", 11, 0);
3207 TEST(
"1111.168.1.1", 12, 0);
3208 TEST(
"999.oogle.com", 14, 0);
3209 TEST(
"0:0:0:0:0:0:0:0", 15, 0);
3210 TEST(
"192.168.255.255", 15, 1);
3211 TEST(
"192.168.255.255/testurl.html", 28, 1);
3212 TEST(
"www.google.com", 14, 0);
3217 #define TEST(str, len, expect) { \
3218 SCLogDebug("str %s", (str)); \
3219 int r = IsIpv6Host((const uint8_t *)(str),(len)); \
3220 FAIL_IF_NOT(r == (expect)); \
3222 static int MimeIsIpv6HostTest01(
void)
3224 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3225 TEST(
"0000:0000:0000:0000:0000:0000:0000:0000", 39, 1);
3226 TEST(
"XXXX:0000:0000:0000:0000:0000:0000:0000", 39, 0);
3227 TEST(
"00001:0000:0000:0000:0000:0000:0000:0000", 40, 0);
3228 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3229 TEST(
"0:0:0:0:0:0:0:0:0", 20, 0);
3230 TEST(
"192:168:1:1:0:0:0:0", 19, 1);
3231 TEST(
"999.oogle.com", 14, 0);
3232 TEST(
"192.168.255.255", 15, 0);
3233 TEST(
"192.168.255.255/testurl.html", 28, 0);
3234 TEST(
"www.google.com", 14, 0);
3239 static int MimeDecParseLongFilename01(
void)
3242 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3243 "12characters12characters12characters12characters"
3244 "12characters12characters12characters12characters"
3245 "12characters12characters12characters12characters"
3246 "12characters12characters12characters12characters"
3247 "12characters12characters12characters12characters"
3248 "12characters12characters12characters.exe\"";
3250 uint32_t line_count = 0;
3258 TestDataChunkCallback);
3260 const char *
str =
"From: Sender1";
3263 str =
"To: Recipient1";
3266 str =
"Content-Type: text/plain";
3275 str =
"A simple message line 1";
3295 static int MimeDecParseSmallRemInp(
void)
3299 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3301 uint32_t line_count = 0;
3311 const char *
str =
"From: Sender1";
3314 str =
"To: Recipient1";
3317 str =
"Content-Type: text/plain";
3320 str =
"Content-Transfer-Encoding: base64";
3348 static int MimeDecParseRemSp(
void)
3351 char mimemsg[] =
"TWltZSBkZWNvZGluZyBpc yBzbyBOT1QgZnVuISBJIGNhbm5vd A";
3353 uint32_t line_count = 0;
3363 const char *
str =
"From: Sender1";
3366 str =
"To: Recipient1";
3369 str =
"Content-Type: text/plain";
3372 str =
"Content-Transfer-Encoding: base64";
3396 static int MimeDecVerySmallInp(
void)
3400 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vA";
3402 uint32_t line_count = 0;
3412 const char *
str =
"From: Sender1";
3415 str =
"To: Recipient1";
3418 str =
"Content-Type: text/plain";
3421 str =
"Content-Transfer-Encoding: base64";
3449 static int MimeDecParseOddLen(
void)
3451 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3453 uint32_t line_count = 0;
3463 const char *
str =
"From: Sender1";
3466 str =
"To: Recipient1";
3469 str =
"Content-Type: text/plain";
3472 str =
"Content-Transfer-Encoding: base64";
3496 static int MimeDecParseLongFilename02(
void)
3499 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3500 "12characters12characters12characters.exe\"; "
3501 "somejunkasfdasfsafasafdsasdasassdssdsd"
3502 "somejunkasfdasfsafasafdsasdasassdssdsd"
3503 "somejunkasfdasfsafasafdsasdasassdssdsd"
3504 "somejunkasfdasfsafasafdsasdasassdssdsd"
3505 "somejunkasfdasfsafasafdsasdasassdssdsd"
3506 "somejunkasfdasfsafasafdsasdasassdssdsd"
3507 "somejunkasfdasfsafasafdsasdasassdssdsd"
3508 "somejunkasfdasfsafasafdsasdasassdssdsd"
3509 "somejunkasfdasfsafasafdsasdasassdssdsd"
3510 "somejunkasfdasfsafasafdsasdasassdssdsd"
3511 "somejunkasfdasfsafasafdsasdasassdssdsd"
3512 "somejunkasfdasfsafasafdsasdasassdssdsd"
3513 "somejunkasfdasfsafasafdsasdasassdssdsd";
3515 uint32_t line_count = 0;
3523 TestDataChunkCallback);
3525 const char *
str =
"From: Sender1";
3528 str =
"To: Recipient1";
3531 str =
"Content-Type: text/plain";
3540 str =
"A simple message line 1";
3565 UtRegisterTest(
"MimeDecParseLineTest01", MimeDecParseLineTest01);
3566 UtRegisterTest(
"MimeDecParseLineTest02", MimeDecParseLineTest02);
3567 UtRegisterTest(
"MimeFindUrlStringsTest01", MimeFindUrlStringsTest01);
3568 UtRegisterTest(
"MimeFindUrlStringsTest02", MimeFindUrlStringsTest02);
3569 UtRegisterTest(
"MimeFindUrlStringsTest03", MimeFindUrlStringsTest03);
3570 UtRegisterTest(
"MimeFindUrlStringsTest04", MimeFindUrlStringsTest04);
3571 UtRegisterTest(
"MimeFindUrlStringsTest05", MimeFindUrlStringsTest05);
3572 UtRegisterTest(
"MimeDecParseFullMsgTest01", MimeDecParseFullMsgTest01);
3573 UtRegisterTest(
"MimeDecParseFullMsgTest02", MimeDecParseFullMsgTest02);
3574 UtRegisterTest(
"MimeBase64DecodeTest01", MimeBase64DecodeTest01);
3578 UtRegisterTest(
"MimeDecParseLongFilename01", MimeDecParseLongFilename01);
3579 UtRegisterTest(
"MimeDecParseLongFilename02", MimeDecParseLongFilename02);
3580 UtRegisterTest(
"MimeDecParseSmallRemInp", MimeDecParseSmallRemInp);