📄 snort_smtp.c
字号:
{ bdat_chunk += (*tmp - '0') * ten_power; } /* bad bdat chunk size */ if (bdat_chunk == 0) break; /* got a valid chunk size - check to see if this is the last chunk */ last = end_chunk; while ((last < eolm) && isspace((int)*last)) last++; /* TODO need an ESMTP argument search */ if (last < eolm) { /* must have at least 4 chars for 'last' */ if ((eolm - last) >= 4) { if (*last == 'l' || *last == 'L') { last++; if (*last == 'a' || *last == 'A') { last++; if (*last == 's' || *last == 'S') { last++; if (*last == 't' || *last == 'T') { last++; while ((last < eolm) && isspace((int)*last)) last++; if (last != eolm) { break; } _smtp->bdat_last = 1; } } } } } } _smtp->state = STATE_BDAT; _smtp->bdat_chunk = bdat_chunk; } break;#endif case CMD_DATA: if (_smtp->state_flags & SMTP_FLAG_GOT_DATA_RESP) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Already got 354 data ready response - set " "to data state.\n");); _smtp->state = STATE_DATA; _smtp->state_flags &= ~(SMTP_FLAG_GOT_DATA_RESP | SMTP_FLAG_GOT_DATA_CMD); } else if (!(_smtp->state_flags & SMTP_FLAG_GOT_RCPT_CMD)) { /* if this flag is set, then this is a reassembled packet with the last * command being the one that caused the error. In this case it was the * DATA command that caused the error, so we shouldn't accept it and stay * in the command state */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Didn't get MAIL -> RCPT command sequence or " "got server error on DATA command - " "stay in command state.\n");); } else { /* Since we're not keeping a more granular state (such as mail state, rcpt state) * we have no way of knowing whether the data command will be accepted. Now, we * assume that it will be, but if the next server response is not 354 we will * revert back to command state */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Got DATA command but no server response yet " "set to data response pending state.\n");); _smtp->state = STATE_DATA_PEND; _smtp->state_flags |= SMTP_FLAG_GOT_DATA_CMD; } break; case CMD_STARTTLS: /* if reassembled we flush after seeing a 220 so this should be the last * command in reassembled packet and if not reassembled it should be the * last line in the packet as you can't pipeline the tls hello */ if (eol == end) { _smtp->state = STATE_TLS_CLIENT_PEND; } break; case CMD_X_LINK2STATE: if (_smtp_config.alert_xlink2state) { ParseXLink2State(p, ptr + _smtp_search_info.index); } break; default: break; } /* normalize command line */ if (_smtp_config.normalize == NORMALIZE_ALL || _smtp_cmd_config[_smtp_search_info.id].normalize) { ret = SMTP_NormalizeCmd(p, ptr, eolm, eol); if (ret == -1) return NULL; } else if (_smtp_normalizing) /* Already normalizing */ { ret = SMTP_CopyToAltBuffer(p, ptr, eol - ptr); if (ret == -1) return NULL; } return eol;}static const u_int8_t * SMTP_HandleData(SFSnortPacket *p, const u_int8_t *ptr, const u_int8_t *end){ const u_int8_t *data_end_marker = NULL; const u_int8_t *data_end = NULL; int data_end_found; int ret; /* if we've just entered the data state, check for a dot + end of line * if found, no data */ if (_smtp->data_state == STATE_DATA_INIT) { if ((ptr < end) && (*ptr == '.')) { const u_int8_t *eol = NULL; const u_int8_t *eolm = NULL; SMTP_GetEOL(ptr, end, &eol, &eolm); /* this means we got a real end of line and not just end of payload * and that the dot is only char on line */ if ((eolm != end) && (eolm == (ptr + 1))) { /* if we're normalizing and not ignoring data copy data end marker * and dot to alt buffer */ if (!_smtp_config.ignore_data && _smtp_normalizing) { ret = SMTP_CopyToAltBuffer(p, ptr, eol - ptr); if (ret == -1) return NULL; } SMTP_ResetState(); return eol; } } _smtp->data_state = STATE_DATA_HEADER; /* XXX A line starting with a '.' that isn't followed by a '.' is * deleted (RFC 821 - 4.5.2. TRANSPARENCY). If data starts with * '. text', i.e a dot followed by white space then text, some * servers consider it data header and some data body. * Postfix and Qmail will consider the start of data: * . text\r\n * . text\r\n * to be part of the header and the effect will be that of a * folded line with the '.' deleted. Exchange will put the same * in the body which seems more reasonable. */ } /* get end of data body * TODO check last bytes of previous packet to see if we had a partial * end of data */ _smtp_current_search = &_smtp_data_end_search[0]; data_end_found = _dpd.searchAPI->search_find(SEARCH_DATA_END, (const char *)ptr, end - ptr, 0, SMTP_SearchStrFound); if (data_end_found > 0) { data_end_marker = ptr + _smtp_search_info.index; data_end = data_end_marker + _smtp_search_info.length; } else { data_end_marker = data_end = end; } if (_smtp->data_state == STATE_DATA_HEADER) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "DATA HEADER STATE ~~~~~~~~~~~~~~~~~~~~~~\n");); ptr = SMTP_HandleHeader(p, ptr, data_end_marker); if (ptr == NULL) return NULL; } /* if we're ignoring data and not already normalizing, copy everything * up to here into alt buffer so detection engine doesn't have * to look at the data; otherwise, if we're normalizing and not * ignoring data, copy all of the data into the alt buffer */ if (_smtp_config.ignore_data && !_smtp_normalizing) { ret = SMTP_CopyToAltBuffer(p, p->payload, ptr - p->payload); if (ret == -1) return NULL; } else if (!_smtp_config.ignore_data && _smtp_normalizing) { ret = SMTP_CopyToAltBuffer(p, ptr, data_end - ptr); if (ret == -1) return NULL; } /* now we shouldn't have to worry about copying any data to the alt buffer * only mime headers if we find them and only if we're ignoring data */ while ((ptr != NULL) && (ptr < data_end_marker)) { switch (_smtp->data_state) { case STATE_MIME_HEADER: DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "MIME HEADER STATE ~~~~~~~~~~~~~~~~~~~~~~\n");); ptr = SMTP_HandleHeader(p, ptr, data_end_marker); break; case STATE_DATA_BODY: DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "DATA BODY STATE ~~~~~~~~~~~~~~~~~~~~~~~~\n");); ptr = SMTP_HandleDataBody(p, ptr, data_end_marker); break; } } /* if we got the data end reset state, otherwise we're probably still in the data * to expect more data in next packet */ if (data_end_marker != end) { SMTP_ResetState(); } return data_end;}/* * Handle Headers - Data or Mime * * @param packet standard Packet structure * * @param i index into p->payload buffer to start looking at data * * @return i index into p->payload where we stopped looking at data */static const u_int8_t * SMTP_HandleHeader(SFSnortPacket *p, const u_int8_t *ptr, const u_int8_t *data_end_marker){ const u_int8_t *eol; const u_int8_t *eolm; const u_int8_t *colon; const u_int8_t *content_type_ptr = NULL; int header_line_len; int header_found; int ret; const u_int8_t *start_hdr; int header_name_len; start_hdr = ptr; /* if we got a content-type in a previous packet and are * folding, the boundary still needs to be checked for */ if (_smtp->state_flags & SMTP_FLAG_IN_CONTENT_TYPE) content_type_ptr = ptr; while (ptr < data_end_marker) { SMTP_GetEOL(ptr, data_end_marker, &eol, &eolm); /* got a line with only end of line marker should signify end of header */ if (eolm == ptr) { /* reset global header state values */ _smtp->state_flags &= ~(SMTP_FLAG_FOLDING | SMTP_FLAG_IN_CONTENT_TYPE); _smtp->data_state = STATE_DATA_BODY; /* if no headers, treat as data */ if (ptr == start_hdr) return eolm; else return eol; } /* if we're not folding, see if we should interpret line as a data line * instead of a header line */ if (!(_smtp->state_flags & SMTP_FLAG_FOLDING)) { char got_space_in_header_name = 0; /* if we're not folding and the first char is a space or * colon, it's not a header */ if (isspace((int)*ptr) || *ptr == ':') { _smtp->data_state = STATE_DATA_BODY; return ptr; } /* look for header field colon - if we're not folding then we need * to find a header which will be all printables (except colon) * followed by a colon */ colon = ptr; while ((colon < eolm) && (*colon != ':')) { if (isspace((int)*colon)) got_space_in_header_name = 1; colon++; } /* Check for Exim 4.32 exploit where number of chars before colon is greater than 64 */ header_name_len = colon - ptr; if ((colon < eolm) && (header_name_len > MAX_HEADER_NAME_LEN)) { SMTP_GenerateAlert(SMTP_HEADER_NAME_OVERFLOW, "%s: %d chars before colon", SMTP_HEADER_NAME_OVERFLOW_STR, header_name_len); } if ((colon == eolm) || got_space_in_header_name) { /* no colon or spaces in header name (won't be interpreted as a header) * assume we're in the body */ _smtp->data_state = STATE_DATA_BODY; return ptr; } _smtp_current_search = &_smtp_hdr_search[0]; header_found = _dpd.searchAPI->search_find(SEARCH_HDR, (const char *)ptr, eolm - ptr, 1, SMTP_SearchStrFound); /* Headers must start at beginning of line */ if ((header_found > 0) && (_smtp_search_info.index == 0)) { switch (_smtp_search_info.id) { case HDR_CONTENT_TYPE: /* for now we're just looking for the boundary in the data * header section */ if (_smtp->data_state == STATE_DATA_HEADER) { content_type_ptr = ptr + _smtp_search_info.length; _smtp->state_flags |= SMTP_FLAG_IN_CONTENT_TYPE; } break; default: break; } } } /* get length of header line */ header_line_len = eol - ptr; if ((_smtp_config.max_header_line_len != 0) && (header_line_len > _smtp_config.max_header_line_len)) { SMTP_GenerateAlert(SMTP_DATA_HDR_OVERFLOW, "%s: %d chars", SMTP_DATA_HDR_OVERFLOW_STR, header_line_len); } /* XXX Does VRT want data headers normalized? * currently the code does not normalize headers */ if (_smtp_normalizing) { ret = SMTP_CopyToAltBuffer(p, ptr, eol - ptr); if (ret == -1) return NULL; } /* check for folding * if char on next line is a space and not \n or \r\n, we are folding */ if ((eol < data_end_marker) && isspace((int)eol[0]) && (eol[0] != '\n')) { if ((eol < (data_end_marker - 1)) && (eol[0] != '\r') && (eol[1] != '\n')) { _smtp->state_flags |= SMTP_FLAG_FOLDING; } else { _smtp->state_flags &= ~SMTP_FLAG_FOLDING; } } else { _smtp->state_flags &= ~SMTP_FLAG_FOLDING; } /* check if we're in a content-type header and not folding. if so we have the whole * header line/lines for content-type - see if we got a multipart with boundary * we don't check each folded line, but wait until we have the complete header * because boundary=BOUNDARY can be split across mulitple folded lines before * or after the '=' */ if ((_smtp->state_flags & (SMTP_FLAG_IN_CONTENT_TYPE | SMTP_FLAG_FOLDING)) == SMTP_FLAG_IN_CONTENT_TYPE) { /* we got the full content-type header - look for boundary string */ ret = SMTP_GetBoundary((const char *)content_type_ptr, eolm - content_type_ptr); if (ret != -1) { ret = SMTP_BoundarySearchInit(); if (ret != -1) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Got mime boundary: %s\n", _smtp->mime_boundary.boundary);); _smtp->state_flags |= SMTP_FLAG_GOT_BOUNDARY; } } _smtp->state_flags &= ~SMTP_FLAG_IN_CONTENT_TYPE; content_type_ptr = NULL; } ptr = eol; } return ptr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -