46 #define PRINTABLE_START 33
47 #define PRINTABLE_END 126
56 #define BASE64_STR "Base64"
59 #define MAX_LINE_LEN 998
60 #define MAX_ENC_LINE_LEN 76
61 #define MAX_HEADER_NAME 75
62 #define MAX_HEADER_VALUE 2000
63 #define BOUNDARY_BUF 256
64 #define CTNT_TYPE_STR "content-type"
65 #define CTNT_DISP_STR "content-disposition"
66 #define CTNT_TRAN_STR "content-transfer-encoding"
67 #define MSG_ID_STR "message-id"
68 #define MSG_STR "message/"
69 #define MULTIPART_STR "multipart/"
70 #define QP_STR "quoted-printable"
71 #define TXT_STR "text/plain"
72 #define HTML_STR "text/html"
75 #define STACK_FREE_NODES 10
78 #define MAX_IP4_CHARS 15
79 #define MAX_IP6_CHARS 39
85 static const char *StateFlags[] = {
"NONE",
97 static const char *UrlExeExts[] = {
".exe",
".vbs",
".bin",
".cmd",
".bat",
".jar",
".js",
".ps",
98 ".ps1",
".sh",
".run",
".hta",
".bin",
".elf", NULL };
110 static void PrintChars(
int log_level,
const char *label,
const uint8_t *
src, uint32_t
len)
114 printf(
"[%s]\n", label);
128 if (config != NULL) {
129 mime_dec_config = *config;
147 return &mime_dec_config;
162 while(node->
next != NULL)
180 while (entity != NULL)
186 if (entity->
child != NULL)
189 lastSibling = findLastSibling(lastSibling);
196 entity = entity->
next;
221 while (curr != NULL) {
250 while (curr != NULL) {
308 while (curr != NULL) {
310 if (strlen(name) == curr->
name_len) {
334 while (curr != NULL) {
336 if (strlen(name) == curr->
name_len) {
399 if (parent != NULL) {
400 if (parent->
child == NULL) {
401 parent->
child = node;
403 curr = parent->
child;
404 while (curr->
next != NULL) {
427 uint32_t nlen,
const uint8_t *value, uint32_t vlen)
429 if (nlen == 0 && vlen == 0)
440 for (u = 0; u < nlen; u++)
443 field->
name = (uint8_t *)name;
448 field->
value = (uint8_t *)value;
532 while (curr != NULL) {
543 while (curr != NULL) {
572 while (curr->
next != NULL) {
595 while (curr != NULL) {
615 static uint8_t *GetFullValue(
const DataValue *dv, uint32_t *olen)
623 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
632 for (
const DataValue *curr = dv; curr != NULL; curr = curr->
next) {
652 static inline uint8_t *FindBuffer(
653 const uint8_t *
src, uint32_t
len,
const uint8_t *find, uint16_t find_len)
669 static uint8_t * GetLine(uint8_t *buf, uint32_t blen, uint8_t **remainPtr,
687 for (i = 0; i < blen && buf[i] != 0; i++) {
690 if (buf[i] ==
CR || buf[i] ==
LF) {
693 *remainPtr += (i + 1);
694 if ((i + 1 < blen) && buf[i] != buf[i + 1] &&
695 (buf[i + 1] ==
CR || buf[i + 1] ==
LF)) {
703 if (buf == *remainPtr) {
708 *tokLen = (buf + i) - tok;
724 static uint8_t * GetToken(uint8_t *buf, uint32_t blen,
const char *delims,
725 uint8_t **remainPtr, uint32_t *tokenLen)
727 uint32_t i, j, delimFound = 0;
740 for (i = 0; i < blen && buf[i] != 0; i++) {
743 for (j = 0; delims[j] != 0; j++) {
744 if (buf[i] == delims[j]) {
747 (*remainPtr) += (i + 1);
755 if (tok == NULL && !delimFound) {
763 if (buf != *remainPtr) {
770 if (buf == *remainPtr) {
775 *tokenLen = (buf + i) - tok;
796 if (state->
hname != NULL || state->
hvalue != NULL) {
798 val = GetFullValue(state->
hvalue, &vlen);
800 if (state->
hname == NULL) {
801 SCLogDebug(
"Error: Invalid parser state - header value without"
804 }
else if (state->
stack->
top != NULL) {
816 }
else if (state->
hvalue != NULL) {
827 FreeDataValue(state->
hvalue);
845 static int IsExeUrl(
const uint8_t *url, uint32_t
len)
852 for (i = 0; UrlExeExts[i] != NULL; i++) {
853 extLen = strlen(UrlExeExts[i]);
854 ext = FindBuffer(url,
len, (uint8_t *)UrlExeExts[i], (uint16_t)strlen(UrlExeExts[i]));
855 if (ext != NULL && (ext + extLen - url == (
int)
len || ext[extLen] ==
'?')) {
873 static int IsIpv4Host(
const uint8_t *urlhost, uint32_t
len)
875 struct sockaddr_in sa;
880 for ( ; i <
len && urlhost[i] != 0; i++) {
882 if (urlhost[i] ==
'/') {
893 memcpy(tempIp, urlhost, i);
899 return inet_pton(AF_INET, tempIp, &(sa.sin_addr));
911 static int IsIpv6Host(
const uint8_t *urlhost, uint32_t
len)
918 for (i = 0; i <
len && urlhost[i] != 0; i++) {
919 if (urlhost[i] ==
'/') {
930 memcpy(tempIp, urlhost, i);
936 return inet_pton(AF_INET6, tempIp, &in6);
953 while (curr != NULL) {
954 if (url_len == curr->
url_len) {
985 static int FindUrlStrings(
const uint8_t *line, uint32_t
len,
991 uint8_t *fptr, *remptr, *tok = NULL, *tempUrl, *urlHost;
992 uint32_t tokLen = 0, i, tempUrlLen, urlHostLen;
993 uint16_t schemeStrLen = 0;
996 char *schemeStr = NULL;
998 if (mdcfg != NULL && mdcfg->extract_urls_schemes == NULL) {
999 SCLogDebug(
"Error: MIME config extract_urls_schemes was NULL.");
1004 schemeStr = scheme->
val;
1006 schemeStrLen = (uint16_t)strlen(schemeStr);
1008 remptr = (uint8_t *)line;
1010 SCLogDebug(
"Looking for URL String starting with: %s", schemeStr);
1013 fptr = FindBuffer(remptr,
len - (remptr - line), (uint8_t *)schemeStr, schemeStrLen);
1015 if (!mdcfg->log_url_scheme) {
1016 fptr += schemeStrLen;
1018 tok = GetToken(fptr,
len - (fptr - line),
" \"\'<>]\t", &remptr, &tokLen);
1032 for (i = 0; i < tokLen && tok[i] != 0; i++) {
1039 urlHostLen = tempUrlLen;
1040 if (mdcfg->log_url_scheme) {
1046 urlHost += schemeStrLen;
1047 urlHostLen -= schemeStrLen;
1051 if (IsExeUrl(tempUrl, tempUrlLen)) {
1054 PrintChars(
SC_LOG_DEBUG,
"EXE URL", tempUrl, tempUrlLen);
1058 if (tempUrlLen > 0) {
1059 if (!(FindExistingUrl(entity, tempUrl, tempUrlLen))) {
1061 if (IsIpv4Host(urlHost, urlHostLen)) {
1064 PrintChars(
SC_LOG_DEBUG,
"IP URL4", tempUrl, tempUrlLen);
1065 }
else if (IsIpv6Host(urlHost, urlHostLen)) {
1068 PrintChars(
SC_LOG_DEBUG,
"IP URL6", tempUrl, tempUrlLen);
1072 MimeDecAddUrl(entity, tempUrl, tempUrlLen,
flags);
1084 }
while (fptr != NULL);
1100 static int ProcessDecodedDataChunk(
const uint8_t *chunk, uint32_t
len,
1104 uint8_t *remainPtr, *tok;
1107 if ((state->
stack != NULL) && (state->
stack->
top != NULL) &&
1119 remainPtr = (uint8_t *)chunk;
1122 remainPtr,
len - (remainPtr - (uint8_t *)chunk), &remainPtr, &tokLen);
1123 if (tok != remainPtr) {
1127 if (tok + tokLen - (uint8_t *)chunk == (
int)
len) {
1128 PrintChars(
SC_LOG_DEBUG,
"LAST CHUNK LINE - CUTOFF", tok, tokLen);
1129 SCLogDebug(
"\nCHUNK CUTOFF CHARS: %u delim %u\n", tokLen,
1130 len - (uint32_t)(tok + tokLen - (uint8_t *)chunk));
1133 ret = FindUrlStrings(tok, tokLen, state);
1135 SCLogDebug(
"Error: FindUrlStrings() function"
1142 }
while (tok != remainPtr && remainPtr - (uint8_t *)chunk < (
int)
len);
1150 SCLogDebug(
"Error: state->dataChunkProcessor() callback function"
1179 static uint32_t ProcessBase64Remainder(
1182 uint32_t buf_consumed = 0;
1196 for (uint8_t i = 0; i < state->
bvr_len; i++) {
1204 for (uint32_t i = 0; i <
len && cnt <
B64_BLOCK; i++) {
1205 if (buf[i] !=
' ') {
1206 block[cnt++] = buf[i];
1211 memcpy(state->
bvremain, block, cnt);
1214 }
else if (!force && cnt !=
B64_BLOCK) {
1215 SCLogDebug(
"incomplete data and no buffer to backfill");
1233 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1238 uint32_t consumed_bytes = 0;
1239 uint32_t remdec = 0;
1258 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1266 SCLogDebug(
"Error: DecodeBase64() function failed");
1275 return buf_consumed;
1285 for (uint32_t i =
offset; i < buf_len; i++) {
1286 if (buf[i] !=
' ') {
1306 static int ProcessBase64BodyLine(
const uint8_t *buf, uint32_t
len,
1310 uint32_t numDecoded, remaining =
len,
offset = 0;
1320 return ProcessBase64BodyLineCopyRemainder(buf,
len, 0, state);
1328 uint32_t consumed = ProcessBase64Remainder(buf,
len, state, 0);
1333 uint32_t left =
len - consumed;
1336 return ProcessBase64BodyLineCopyRemainder(buf,
len, consumed, state);
1339 remaining -= consumed;
1343 while (remaining > 0 && remaining >=
B64_BLOCK) {
1344 uint32_t consumed_bytes = 0;
1351 if (consumed_bytes > remaining)
1354 uint32_t leftover_bytes = remaining - consumed_bytes;
1370 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
1378 SCLogDebug(
"Error: DecodeBase64() function failed");
1384 if (consumed_bytes == 0 && leftover_bytes >
B64_BLOCK) {
1386 return ProcessBase64BodyLineCopyRemainder(buf,
len,
offset, state);
1387 }
else if (leftover_bytes > 0 && leftover_bytes <=
B64_BLOCK) {
1390 return ProcessBase64BodyLineCopyRemainder(buf,
len,
offset + consumed_bytes, state);
1394 remaining = leftover_bytes;
1395 offset += consumed_bytes;
1408 static int8_t DecodeQPChar(
char h)
1413 if (h >= 48 && h <= 57) {
1415 }
else if (h >= 65 && h <= 70) {
1437 static int ProcessQuotedPrintableBodyLine(
const uint8_t *buf, uint32_t
len,
1441 uint32_t remaining,
offset;
1443 uint8_t c, h1, h2, val;
1450 SCLogDebug(
"Error: Max encoded input line length exceeded %u > %u",
1462 while (remaining > 0) {
1476 }
else if (remaining > 1) {
1481 if (remaining < 3) {
1484 SCLogDebug(
"Error: Quoted-printable decoding failed");
1486 h1 = *(buf +
offset + 1);
1487 res = DecodeQPChar(h1);
1491 SCLogDebug(
"Error: Quoted-printable decoding failed");
1493 val = (uint8_t)(res << 4);
1494 h2 = *(buf +
offset + 2);
1495 res = DecodeQPChar(h2);
1499 SCLogDebug(
"Error: Quoted-printable decoding failed");
1534 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1553 static int ProcessBodyLine(
const uint8_t *buf, uint32_t
len,
1557 uint32_t remaining,
offset, avail, tobuf;
1567 ret = ProcessBase64BodyLine(buf,
len, state);
1569 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
1574 ret = ProcessQuotedPrintableBodyLine(buf,
len, state);
1576 SCLogDebug(
"Error: ProcessQuotedPrintableBodyLine() function "
1583 while (remaining > 0) {
1586 tobuf = avail > remaining ? remaining : avail;
1593 SCLogDebug(
"Error: Invalid Chunk length: %u",
1602 ret = ProcessDecodedDataChunk(state->
data_chunk,
1605 SCLogDebug(
"Error: ProcessDecodedDataChunk() function "
1627 static uint8_t * FindMimeHeaderStart(
const uint8_t *buf, uint32_t blen, uint32_t *hlen)
1629 uint32_t i, valid = 0;
1630 uint8_t *hname = NULL;
1637 for (i = 0; i < blen && buf[i] != 0; i++) {
1643 }
else if (valid > 0 && buf[i] ==
COLON) {
1646 hname = (uint8_t *) buf + i - valid;
1668 static int FindMimeHeader(
const uint8_t *buf, uint32_t blen,
1672 uint8_t *hname, *hval = NULL;
1674 uint32_t hlen, vlen;
1675 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;
1768 ret = ProcessBodyLine(buf, blen, state);
1770 SCLogDebug(
"Error: ProcessBodyLine() function failed");
1776 if (finish_header) {
1778 ret = StoreMimeHeader(state);
1780 SCLogDebug(
"Error: StoreMimeHeader() function failed");
1792 memcpy(state->
hname, hname, hlen);
1795 if (state->
hvalue != NULL) {
1796 SCLogDebug(
"Error: Parser failed due to unexpected header "
1803 vlen = blen - (hval - buf);
1805 SCLogDebug(
"Error: Header value of length (%u) is too long",
1806 state->
hvlen + vlen);
1813 state->
hvalue = AddDataValue(NULL);
1814 if (state->
hvalue == NULL) {
1823 state->
hvlen += vlen;
1841 static int ProcessMimeHeaders(
const uint8_t *buf, uint32_t
len,
1846 uint8_t *rptr = NULL;
1849 uint8_t bptr[RS_MIME_MAX_TOKEN_LEN];
1852 ret = FindMimeHeader(buf,
len, state);
1854 SCLogDebug(
"Error: FindMimeHeader() function failed: %d", ret);
1862 if (field != NULL) {
1869 (uint16_t)strlen(
QP_STR))) {
1871 SCLogDebug(
"quoted-printable encoding found");
1878 if (field != NULL) {
1879 bool truncated_name =
false;
1881 (
const uint8_t *)
"filename", strlen(
"filename"), &bptr, &blen)) {
1882 SCLogDebug(
"File attachment found in disposition");
1885 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1886 blen = RS_MIME_MAX_TOKEN_LEN;
1887 truncated_name =
true;
1895 memcpy(entity->
filename, bptr, blen);
1898 if (truncated_name) {
1907 if (field != NULL) {
1911 (
const uint8_t *)
"boundary", strlen(
"boundary"), &bptr, &blen)) {
1931 bool truncated_name =
false;
1933 (
const uint8_t *)
"name", strlen(
"name"), &bptr, &blen)) {
1937 if (blen > RS_MIME_MAX_TOKEN_LEN) {
1938 blen = RS_MIME_MAX_TOKEN_LEN;
1939 truncated_name =
true;
1947 memcpy(entity->
filename, bptr, blen);
1950 if (truncated_name) {
1964 SCLogDebug(
"Found encapsulated message entity");
1973 PushStack(state->
stack);
2003 if (field != NULL) {
2035 SCLogDebug(
"Found (%u) remaining base64 bytes not processed",
2039 ret = ProcessBase64Remainder(NULL, 0, state, 1);
2041 SCLogDebug(
"Error: ProcessBase64BodyLine() function failed");
2048 SCLogDebug(
"Error: ProcessDecodedDataChunk() function failed");
2068 static int ProcessMimeBoundary(
2075 SCLogDebug(
"PROCESSING BOUNDARY - START: %d",
2083 ret = ProcessBodyComplete(state);
2085 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2095 rptr = (uint8_t *) buf + bdef_len + 2;
2102 SCLogDebug(
"Error: Missing parent entity from stack");
2108 SCLogDebug(
"POPPED ENCAPSULATED CHILD FROM STACK: %p=%p",
2112 PopStack(state->
stack);
2121 if (
len - (rptr - buf) > 1 && rptr[0] ==
DASH && rptr[1] ==
DASH) {
2122 SCLogDebug(
"FOUND END BOUNDARY, POPPING: %p=%p",
2126 PopStack(state->
stack);
2135 SCLogDebug(
"FOUND END BOUNDARY AND ENCAP, POPPING: %p=%p",
2138 PopStack(state->
stack);
2155 PushStack(state->
stack);
2163 SCLogDebug(
"Error: Missing parent entity from stack");
2167 SCLogDebug(
"SIBLING CREATED, POPPING PARENT: %p=%p",
2171 PopStack(state->
stack);
2182 PushStack(state->
stack);
2204 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,
2360 ret = ProcessMimeHeaders(buf,
len, state);
2362 SCLogDebug(
"Error: ProcessMimeHeaders() function failed: %d",
2370 ret = ProcessMimeBody(buf,
len, state);
2372 SCLogDebug(
"Error: ProcessMimeBody() function failed: %d",
2393 int (*DataChunkProcessorFunc)(
const uint8_t *chunk, uint32_t
len,
2422 state->
msg = mimeMsg;
2423 PushStack(state->
stack);
2448 while (state->
stack->
top != NULL) {
2452 PopStack(state->
stack);
2458 SCLogDebug(
"Warning: Stack is not empty upon completion of "
2459 "processing (%u items remaining)", cnt);
2463 FreeDataValue(state->
hvalue);
2464 FreeMimeDecStack(state->
stack);
2487 SCLogDebug(
"parser in error state: PARSE_ERROR");
2492 ret = StoreMimeHeader(state);
2494 SCLogDebug(
"Error: StoreMimeHeader() function failed");
2499 ret = ProcessBodyComplete(state);
2501 SCLogDebug(
"Error: ProcessBodyComplete() function failed");
2506 SCMd5Finalize(state->
md5_ctx, state->
md5,
sizeof(state->
md5));
2519 PopStack(state->
stack);
2530 SCLogDebug(
"Warning: Message has unclosed message part boundary");
2562 ret = ProcessMimeEntity(line,
len, state);
2565 SCLogDebug(
"Error: ProcessMimeEntity() function failed: %d", ret);
2583 int (*dcpfunc)(
const uint8_t *chunk, uint32_t
len,
2587 uint8_t *remainPtr, *tok;
2591 if (state == NULL) {
2592 SCLogDebug(
"Error: MimeDecInitParser() function failed to create "
2600 remainPtr = (uint8_t *) buf;
2601 uint8_t *line = NULL;
2603 tok = GetLine(remainPtr, blen - (remainPtr - buf), &remainPtr, &tokLen);
2604 if (tok != remainPtr) {
2608 if ((remainPtr - tok) - tokLen > UINT8_MAX) {
2609 SCLogDebug(
"Error: MimeDecParseLine() overflow: %ld", (remainPtr - tok) - tokLen);
2617 SCLogDebug(
"Error: MimeDecParseLine() function failed: %d",
2623 }
while (tok != remainPtr && remainPtr - buf < (
int)blen);
2631 SCLogDebug(
"Error: MimeDecParseComplete() function failed");
2649 static int TestDataChunkCallback(
const uint8_t *chunk, uint32_t
len,
2652 uint32_t *line_count = (uint32_t *) state->
data;
2668 remainPtr = (uint8_t *) chunk;
2670 tok = GetLine(remainPtr,
len - (remainPtr - (uint8_t *) chunk),
2671 &remainPtr, &tokLen);
2672 if (tok != NULL && tok != remainPtr) {
2676 }
while (tok != NULL && tok != remainPtr &&
2677 (uint32_t)(remainPtr - (uint8_t *) chunk) <
len);
2690 static int MimeDecParseLineTest01(
void)
2692 uint32_t line_count = 0;
2696 TestDataChunkCallback);
2698 const char *
str =
"From: Sender1\n";
2701 str =
"To: Recipient1\n";
2704 str =
"Content-Type: text/plain\n";
2710 str =
"A simple message line 1\n";
2713 str =
"A simple message line 2\n";
2716 str =
"A simple message line 3\n";
2736 static int MimeDecParseLineTest02(
void)
2738 uint32_t line_count = 0;
2757 TestDataChunkCallback);
2759 const char *
str =
"From: Sender1\r\n";
2762 str =
"To: Recipient1\r\n";
2765 str =
"Content-Type: text/plain\r\n";
2771 str =
"A simple message line 1\r\n";
2774 str =
"A simple message line 2 click on http://www.test.com/malware.exe?"
2775 "hahah hopefully you click this link\r\n";
2797 static int MimeFindUrlStringsTest01(
void)
2800 uint32_t line_count = 0;
2809 const char *
str =
"test";
2810 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2828 static int MimeFindUrlStringsTest02(
void)
2831 uint32_t line_count = 0;
2849 const char *
str =
"A simple message click on "
2850 "http://www.test.com/malware.exe? "
2851 "hahah hopefully you click this link";
2852 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2865 memcmp(
"www.test.com/malware.exe?",
msg->url_list->url,
msg->url_list->url_len) == 0);
2879 static int MimeFindUrlStringsTest03(
void)
2882 uint32_t line_count = 0;
2905 const char *
str =
"A simple message click on "
2906 "http://www.test.com/malware.exe? "
2907 "hahah hopefully you click this link, or "
2908 "you can go to http://www.test.com/test/01.html and "
2909 "https://www.test.com/test/02.php";
2910 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
2943 static int MimeFindUrlStringsTest04(
void)
2946 uint32_t line_count = 0;
2969 const char *
str =
"A simple message click on "
2970 "http://www.test.com/malware.exe? "
2971 "hahah hopefully you click this link, or "
2972 "you can go to http://www.test.com/test/01.html and "
2973 "https://www.test.com/test/02.php";
2974 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3007 static int MimeFindUrlStringsTest05(
void)
3010 uint32_t line_count = 0;
3028 const char *
str =
"A simple message click on "
3029 "http://192.168.1.1/test/01.html "
3030 "hahah hopefully you click this link or this one "
3031 "http://0:0:0:0:0:0:0:0/test/02.php";
3032 ret = FindUrlStrings((uint8_t *)
str, strlen(
str), state);
3063 static int MimeDecParseFullMsgTest01(
void)
3065 uint32_t expected_count = 3;
3066 uint32_t line_count = 0;
3068 char msg[] =
"From: Sender1\r\n"
3069 "To: Recipient1\r\n"
3070 "Content-Type: text/plain\r\n"
3077 TestDataChunkCallback);
3078 if (entity == NULL) {
3079 SCLogInfo(
"Warning: Message failed to parse");
3085 if (expected_count != line_count) {
3086 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d",
3087 expected_count, line_count);
3095 static int MimeDecParseFullMsgTest02(
void)
3097 uint32_t expected_count = 3;
3098 uint32_t line_count = 0;
3100 char msg[] =
"From: Sender2\r\n"
3101 "To: Recipient2\r\n"
3102 "Subject: subject2\r\n"
3103 "Content-Type: text/plain\r\n"
3110 TestDataChunkCallback);
3112 if (entity == NULL) {
3113 SCLogInfo(
"Warning: Message failed to parse");
3118 if (field == NULL) {
3119 SCLogInfo(
"Warning: Message failed to parse");
3123 if (field->
value_len !=
sizeof(
"subject2") - 1) {
3124 SCLogInfo(
"Warning: failed to get subject");
3129 SCLogInfo(
"Warning: failed to get subject");
3136 if (expected_count != line_count) {
3137 SCLogInfo(
"Warning: Line count is invalid: expected - %d actual - %d", expected_count,
3145 static int MimeBase64DecodeTest01(
void)
3148 uint32_t consumed_bytes = 0, num_decoded = 0;
3150 const char *
msg =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@"
3151 "#$%^&*()-=_+,./;'[]<>?:";
3152 const char *base64msg =
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QU"
3153 "VJTVFVWV1hZWjEyMzQ1Njc4OTBAIyQlXiYqKCktPV8rLC4vOydbXTw+Pzo=";
3159 ret =
DecodeBase64(
dst, strlen(
msg) + 1, (
const uint8_t *)base64msg, strlen(base64msg),
3162 if (memcmp(
dst,
msg, strlen(
msg)) == 0) {
3171 static int MimeIsExeURLTest01(
void)
3174 const char *url1 =
"http://www.google.com/";
3175 const char *url2 =
"http://www.google.com/test.exe";
3177 if(IsExeUrl((
const uint8_t *)url1, strlen(url1)) != 0){
3181 if(IsExeUrl((
const uint8_t *)url2, strlen(url2)) != 1){
3192 #define TEST(str, len, expect) { \
3193 SCLogDebug("str %s", (str)); \
3194 int r = IsIpv4Host((const uint8_t *)(str),(len)); \
3195 FAIL_IF_NOT(r == (expect)); \
3197 static int MimeIsIpv4HostTest01(
void)
3199 TEST(
"192.168.1.1", 11, 1);
3200 TEST(
"192.168.1.1.4", 13, 0);
3201 TEST(
"999.168.1.1", 11, 0);
3202 TEST(
"1111.168.1.1", 12, 0);
3203 TEST(
"999.oogle.com", 14, 0);
3204 TEST(
"0:0:0:0:0:0:0:0", 15, 0);
3205 TEST(
"192.168.255.255", 15, 1);
3206 TEST(
"192.168.255.255/testurl.html", 28, 1);
3207 TEST(
"www.google.com", 14, 0);
3212 #define TEST(str, len, expect) { \
3213 SCLogDebug("str %s", (str)); \
3214 int r = IsIpv6Host((const uint8_t *)(str),(len)); \
3215 FAIL_IF_NOT(r == (expect)); \
3217 static int MimeIsIpv6HostTest01(
void)
3219 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3220 TEST(
"0000:0000:0000:0000:0000:0000:0000:0000", 39, 1);
3221 TEST(
"XXXX:0000:0000:0000:0000:0000:0000:0000", 39, 0);
3222 TEST(
"00001:0000:0000:0000:0000:0000:0000:0000", 40, 0);
3223 TEST(
"0:0:0:0:0:0:0:0", 19, 1);
3224 TEST(
"0:0:0:0:0:0:0:0:0", 20, 0);
3225 TEST(
"192:168:1:1:0:0:0:0", 19, 1);
3226 TEST(
"999.oogle.com", 14, 0);
3227 TEST(
"192.168.255.255", 15, 0);
3228 TEST(
"192.168.255.255/testurl.html", 28, 0);
3229 TEST(
"www.google.com", 14, 0);
3234 static int MimeDecParseLongFilename01(
void)
3237 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3238 "12characters12characters12characters12characters"
3239 "12characters12characters12characters12characters"
3240 "12characters12characters12characters12characters"
3241 "12characters12characters12characters12characters"
3242 "12characters12characters12characters12characters"
3243 "12characters12characters12characters.exe\"";
3245 uint32_t line_count = 0;
3253 TestDataChunkCallback);
3255 const char *
str =
"From: Sender1";
3258 str =
"To: Recipient1";
3261 str =
"Content-Type: text/plain";
3270 str =
"A simple message line 1";
3290 static int MimeDecParseSmallRemInp(
void)
3294 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3296 uint32_t line_count = 0;
3306 const char *
str =
"From: Sender1";
3309 str =
"To: Recipient1";
3312 str =
"Content-Type: text/plain";
3315 str =
"Content-Transfer-Encoding: base64";
3343 static int MimeDecParseRemSp(
void)
3346 char mimemsg[] =
"TWltZSBkZWNvZGluZyBpc yBzbyBOT1QgZnVuISBJIGNhbm5vd A";
3348 uint32_t line_count = 0;
3358 const char *
str =
"From: Sender1";
3361 str =
"To: Recipient1";
3364 str =
"Content-Type: text/plain";
3367 str =
"Content-Transfer-Encoding: base64";
3391 static int MimeDecVerySmallInp(
void)
3395 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vA";
3397 uint32_t line_count = 0;
3407 const char *
str =
"From: Sender1";
3410 str =
"To: Recipient1";
3413 str =
"Content-Type: text/plain";
3416 str =
"Content-Transfer-Encoding: base64";
3444 static int MimeDecParseOddLen(
void)
3446 char mimemsg[] =
"TWltZSBkZWNvZGluZyB pcyBzbyBO T1QgZnV uISBJIGNhbm5vdA";
3448 uint32_t line_count = 0;
3458 const char *
str =
"From: Sender1";
3461 str =
"To: Recipient1";
3464 str =
"Content-Type: text/plain";
3467 str =
"Content-Transfer-Encoding: base64";
3491 static int MimeDecParseLongFilename02(
void)
3494 char mimemsg[] =
"Content-Disposition: attachment; filename=\""
3495 "12characters12characters12characters.exe\"; "
3496 "somejunkasfdasfsafasafdsasdasassdssdsd"
3497 "somejunkasfdasfsafasafdsasdasassdssdsd"
3498 "somejunkasfdasfsafasafdsasdasassdssdsd"
3499 "somejunkasfdasfsafasafdsasdasassdssdsd"
3500 "somejunkasfdasfsafasafdsasdasassdssdsd"
3501 "somejunkasfdasfsafasafdsasdasassdssdsd"
3502 "somejunkasfdasfsafasafdsasdasassdssdsd"
3503 "somejunkasfdasfsafasafdsasdasassdssdsd"
3504 "somejunkasfdasfsafasafdsasdasassdssdsd"
3505 "somejunkasfdasfsafasafdsasdasassdssdsd"
3506 "somejunkasfdasfsafasafdsasdasassdssdsd"
3507 "somejunkasfdasfsafasafdsasdasassdssdsd"
3508 "somejunkasfdasfsafasafdsasdasassdssdsd";
3510 uint32_t line_count = 0;
3518 TestDataChunkCallback);
3520 const char *
str =
"From: Sender1";
3523 str =
"To: Recipient1";
3526 str =
"Content-Type: text/plain";
3535 str =
"A simple message line 1";
3560 UtRegisterTest(
"MimeDecParseLineTest01", MimeDecParseLineTest01);
3561 UtRegisterTest(
"MimeDecParseLineTest02", MimeDecParseLineTest02);
3562 UtRegisterTest(
"MimeFindUrlStringsTest01", MimeFindUrlStringsTest01);
3563 UtRegisterTest(
"MimeFindUrlStringsTest02", MimeFindUrlStringsTest02);
3564 UtRegisterTest(
"MimeFindUrlStringsTest03", MimeFindUrlStringsTest03);
3565 UtRegisterTest(
"MimeFindUrlStringsTest04", MimeFindUrlStringsTest04);
3566 UtRegisterTest(
"MimeFindUrlStringsTest05", MimeFindUrlStringsTest05);
3567 UtRegisterTest(
"MimeDecParseFullMsgTest01", MimeDecParseFullMsgTest01);
3568 UtRegisterTest(
"MimeDecParseFullMsgTest02", MimeDecParseFullMsgTest02);
3569 UtRegisterTest(
"MimeBase64DecodeTest01", MimeBase64DecodeTest01);
3573 UtRegisterTest(
"MimeDecParseLongFilename01", MimeDecParseLongFilename01);
3574 UtRegisterTest(
"MimeDecParseLongFilename02", MimeDecParseLongFilename02);
3575 UtRegisterTest(
"MimeDecParseSmallRemInp", MimeDecParseSmallRemInp);