📄 snort_smtp.c
字号:
*mime_boundary_len = 2 + boundary_len; mime_boundary[*mime_boundary_len] = '\0'; return 0;}/* * Handle COMMAND state * * @param p standard Packet structure * @param ptr pointer into p->payload buffer to start looking at data * @param end points to end of p->payload buffer * * @return pointer into p->payload where we stopped looking at data * will be end of line or end of packet */static const u_int8_t * SMTP_HandleCommand(SFSnortPacket *p, const u_int8_t *ptr, const u_int8_t *end){ const u_int8_t *eol; /* end of line */ const u_int8_t *eolm; /* end of line marker */ int cmd_line_len; int ret; int cmd_found; char alert_long_command_line = 0; /* get end of line and end of line marker */ SMTP_GetEOL(ptr, end, &eol, &eolm); /* calculate length of command line */ cmd_line_len = eol - ptr; /* check for command line exceeding maximum * do this before checking for a command since this could overflow * some server's buffers without the presence of a known command */ if ((_smtp_config.max_command_line_len != 0) && (cmd_line_len > _smtp_config.max_command_line_len)) { alert_long_command_line = 1; } /* TODO If the end of line marker coincides with the end of payload we can't be * sure that we got a command and not a substring which we could tell through * inpsection of the next packet. Maybe a command pending state where the first * char in the next packet is checked for a space and end of line marker */ /* do not confine since there could be space chars before command */ _smtp_current_search = &_smtp_cmd_search[0]; cmd_found = _dpd.searchAPI->search_find(SEARCH_CMD, (const char *)ptr, eolm - ptr, 0, SMTP_SearchStrFound); /* see if we actually found a command and not a substring */ if (cmd_found > 0) { const u_int8_t *tmp = ptr; const u_int8_t *cmd_start = ptr + _smtp_search_info.index; const u_int8_t *cmd_end = cmd_start + _smtp_search_info.length; /* move past spaces up until start of command */ while ((tmp < cmd_start) && isspace((int)*tmp)) tmp++; /* if not all spaces before command, we found a * substring */ if (tmp != cmd_start) cmd_found = 0; /* if we're before the end of line marker and the next * character is not whitespace, we found a substring */ if ((cmd_end < eolm) && !isspace((int)*cmd_end)) cmd_found = 0; /* there is a chance that end of command coincides with the end of payload * in which case, it could be a substring, but for now, we will treat it as found */ } /* if command not found, alert and move on */ if (!cmd_found) { /* If we missed one or more packets we might not actually be in the command * state. Check to see if we're encrypted */ if (_smtp->state == STATE_UNKNOWN) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Command not found, but state is " "unknown - checking for SSL\n");); /* check for encrypted */ if ((_smtp->session_flags & SMTP_FLAG_CHECK_SSL) && (SMTP_IsSSL(ptr, end - ptr, p->flags))) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Packet is SSL encrypted\n");); _smtp->state = STATE_TLS_DATA; /* Ignore data */ if (_smtp_config.ignore_tls_data) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Ignoring encrypted data\n");); p->normalized_payload_size = 0; p->flags |= FLAG_ALT_DECODE; } return end; } else { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Not SSL - try data state\n");); /* don't check for ssl again in this packet */ if (_smtp->session_flags & SMTP_FLAG_CHECK_SSL) _smtp->session_flags &= ~SMTP_FLAG_CHECK_SSL; _smtp->state = STATE_DATA; _smtp->data_state = STATE_DATA_UNKNOWN; return ptr; } } else { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "No known command found\n");); if (_smtp_config.alert_unknown_cmds) { SMTP_GenerateAlert(SMTP_UNKNOWN_CMD, "%s", SMTP_UNKNOWN_CMD_STR); } if (alert_long_command_line) { SMTP_GenerateAlert(SMTP_COMMAND_OVERFLOW, "%s: more than %d chars", SMTP_COMMAND_OVERFLOW_STR, _smtp_config.max_command_line_len); } /* if normalizing, copy line to alt buffer */ if (_smtp_normalizing) { ret = SMTP_CopyToAltBuffer(p, ptr, eol - ptr); if (ret == -1) return NULL; } return eol; } } /* At this point we have definitely found a legitimate command */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "%s\n", _smtp_cmds[_smtp_search_info.id].name);); /* check if max command line length for a specific command is exceeded */ if (_smtp_cmd_config[_smtp_search_info.id].max_line_len != 0) { if (cmd_line_len > _smtp_cmd_config[_smtp_search_info.id].max_line_len) { SMTP_GenerateAlert(SMTP_SPECIFIC_CMD_OVERFLOW, "%s: %s, %d chars", SMTP_SPECIFIC_CMD_OVERFLOW_STR, _smtp_cmd_search[_smtp_search_info.id].name, cmd_line_len); } } else if (alert_long_command_line) { SMTP_GenerateAlert(SMTP_COMMAND_OVERFLOW, "%s: more than %d chars", SMTP_COMMAND_OVERFLOW_STR, _smtp_config.max_command_line_len); } /* Are we alerting on this command? */ if (_smtp_cmd_config[_smtp_search_info.id].alert) { SMTP_GenerateAlert(SMTP_ILLEGAL_CMD, "%s: %s", SMTP_ILLEGAL_CMD_STR, _smtp_cmds[_smtp_search_info.id].name); } switch (_smtp_search_info.id) { /* unless we do our own parsing of MAIL and RCTP commands we have to assume they * are ok unless we got a server error in which case we flush and if this is a * reassembled packet, the last command in this packet will be the command that * caused the error */ case CMD_MAIL: _smtp->state_flags |= SMTP_FLAG_GOT_MAIL_CMD; break; case CMD_RCPT: if ((_smtp->state_flags & SMTP_FLAG_GOT_MAIL_CMD) || _smtp->state == STATE_UNKNOWN) { _smtp->state_flags |= SMTP_FLAG_GOT_RCPT_CMD; } break; case CMD_RSET: case CMD_HELO: case CMD_EHLO: case CMD_QUIT: _smtp->state_flags &= ~(SMTP_FLAG_GOT_MAIL_CMD | SMTP_FLAG_GOT_RCPT_CMD); break;#if 0 case CMD_BDAT: { const u_int8_t *begin_chunk; const u_int8_t *end_chunk; const u_int8_t *last; const u_int8_t *tmp; int num_digits; int ten_power; u_int32_t bdat_chunk; begin_chunk = ptr + _smtp_search_info.index + _smtp_search_info.length; while ((begin_chunk < eolm) && isspace((int)*begin_chunk)) begin_chunk++; /* bad BDAT command - needs chunk argument */ if (begin_chunk == eolm) break; end_chunk = begin_chunk; while ((end_chunk < eolm) && isdigit((int)*end_chunk)) end_chunk++; /* didn't get all digits */ if ((end_chunk < eolm) && !isspace((int)*end_chunk)) break; /* get chunk size */ num_digits = end_chunk - begin_chunk; /* more than 9 digits could potentially overflow a 32 bit integer * this allows for one less than a billion bytes which most servers * won't accept */ if (num_digits > 9) break; tmp = end_chunk; for (ten_power = 1, tmp--; tmp >= begin_chunk; ten_power *= 10, tmp--) { 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_BDAT: case CMD_DATA: if ((_smtp->state_flags & SMTP_FLAG_GOT_RCPT_CMD) || _smtp->state == STATE_UNKNOWN) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Set to data state.\n");); _smtp->state = STATE_DATA; _smtp->state_flags &= ~(SMTP_FLAG_GOT_MAIL_CMD | SMTP_FLAG_GOT_RCPT_CMD); } else { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Didn't get MAIL -> RCPT command sequence - " "stay in command state.\n");); } 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; } /* Since we found a command, if state is still unknown, * set to command state */ if (_smtp->state == STATE_UNKNOWN) _smtp->state = STATE_COMMAND; /* 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) || (_smtp->data_state == STATE_DATA_UNKNOWN)) { 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; } } if (_smtp->data_state == STATE_DATA_INIT) _smtp->data_state = STATE_DATA_HEADER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -