📄 pp_ftp.c
字号:
ftp_eo_event_log(ftpssn, FTP_EO_INVALID_CMD, NULL, NULL); state = FTP_CMD_INV; } else { /* In case we were encrypted, but aren't now */ ftpssn->encr_state = 0; } } } } else if (iMode == FTPP_SI_SERVER_MODE) { if (state == FTP_CMD_INV) state = FTP_RESPONSE_INV; if ( (req->cmd_size != 3) || (state == FTP_RESPONSE_INV) ) { /* Uh, something is very wrong... * nondigit char seen or resp code is not 3 chars. * See if this might be encrypted, ie, non-alpha bytes. */ const char *ptr = req->cmd_begin; while (ptr < req->cmd_end) { if (!isdigit((int)(*ptr))) { if (!isascii((int)(*ptr))) { encrypted = 1; } break; } ptr++; } } if (encrypted) { /* If the session wasn't already marked as encrypted... * Don't want to double-alert if we've already * determined the session is encrypted and we're * checking encrypted sessions. */ if (ftpssn->encr_state == 0) { ftpssn->encr_state = AUTH_UNKNOWN_ENCRYPTED; if (ftpssn->global_conf->encrypted.alert) { /* Alert on encrypted channel */ ftp_eo_event_log(ftpssn, FTP_EO_ENCRYPTED, NULL, NULL); } if (!ftpssn->global_conf->check_encrypted_data) { /* Mark this session & packet as one to ignore */ _dpd.streamAPI->stop_inspection(p->stream_session_ptr, p, SSN_DIR_BOTH, -1, 0); } DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP server stream is now encrypted\n");); } break; } else { /* In case we were encrypted, but aren't now */ ftpssn->encr_state = 0; } if (read_ptr < end) { if (*read_ptr != DASH) { const unsigned char *resp_begin = (const unsigned char *)req->cmd_begin; const unsigned char *resp_end = (const unsigned char *)req->cmd_end; if (resp_end - resp_begin >= 3) { if (isdigit(*(resp_begin)) && isdigit(*(resp_begin+1)) && isdigit(*(resp_begin+2)) ) { rsp_code = ( (*(resp_begin) - '0') * 100 + (*(resp_begin+1) - '0') * 10 + (*(resp_begin+2) - '0') ); if (rsp_code == ftpssn->server.response.state) { /* End of continued response */ state = FTP_RESPONSE_ENDCONT; ftpssn->server.response.state = 0; } else { /* Single line response */ state = FTP_RESPONSE; } } } if (ftpssn->server.response.state != 0) { req->cmd_begin = NULL; req->cmd_end = NULL; if (*read_ptr != SP) read_ptr--; state = FTP_RESPONSE_CONT; } } else if ((state == FTP_RESPONSE) && (*read_ptr == DASH)) { const unsigned char *resp_begin = (const unsigned char *)req->cmd_begin; if (isdigit(*(resp_begin)) && isdigit(*(resp_begin+1)) && isdigit(*(resp_begin+2)) ) { int resp_code = ( (*(resp_begin) - '0') * 100 + (*(resp_begin+1) - '0') * 10 + (*(resp_begin+2) - '0') ); if (resp_code == ftpssn->server.response.state) { /* Continuation of previous response */ state = FTP_RESPONSE_CONT; } else { /* Start of response, state stays as -2 */ state = FTP_RESPONSE_2BCONT; ftpssn->server.response.state = resp_code; rsp_code = resp_code; } } else { DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "invalid FTP response code.");); ftpssn->server.response.state = FTP_RESPONSE_INV; } } } } if (read_ptr < end) { if (*read_ptr == SP) { space = 1; } read_ptr++; /* Move past the space, dash, or CR */ } /* If there is anything left... */ if (read_ptr < end) { /* Look for an LF --> implies no parameters/message */ if (*read_ptr == LF) { read_ptr++; req->param_begin = NULL; req->param_end = NULL; } else if (!space && ftpssn->server.response.state == 0) { DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Missing LF from end of FTP command\n");); } else { /* Now grab the command parameters/response message */ if (read_ptr < end) { req->param_begin = (const char *)read_ptr; while ((read_ptr < end) && (*read_ptr != CR)) { read_ptr++; } req->param_end = (const char *)read_ptr; read_ptr++; } if (read_ptr < end) { /* Cool, got the end of the parameters, move past * the LF, so we can process the next one in * the pipeline. */ if (*read_ptr == LF) { read_ptr++; } else { DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Missing LF from end of FTP command with params\n");); } } } } else { /* Nothing left --> no parameters/message. Not even an LF */ req->param_begin = NULL; req->param_end = NULL; DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Missing LF from end of FTP command sans params\n");); } /* Set the pointer for the next request/response * in the pipeline. */ if (read_ptr < end) req->pipeline_req = (const char *)read_ptr; else req->pipeline_req = NULL; req->param_size = req->param_end - req->param_begin; switch (state) { case FTP_CMD_INV: DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Illegal FTP command found: %.*s\n", req->cmd_size, req->cmd_begin)); iRet = FTPP_ALERT; break; case FTP_RESPONSE: /* Response */ DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP response: code: %.*s : M len %d : M %.*s\n", req->cmd_size, req->cmd_begin, req->param_size, req->param_size, req->param_begin)); if ((ftpssn->client_conf->max_resp_len > 0) && (req->param_size > ftpssn->client_conf->max_resp_len)) { /* Alert on response message overflow */ ftp_eo_event_log(ftpssn, FTP_EO_RESPONSE_LENGTH_OVERFLOW, NULL, NULL); iRet = FTPP_ALERT; } if (ftpssn->global_conf->inspection_type == FTPP_UI_CONFIG_STATEFUL) { int newRet = do_stateful_checks(ftpssn, p, req, rsp_code); if (newRet != FTPP_SUCCESS) iRet = newRet; } break; case FTP_RESPONSE_CONT: /* Response continued */ DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP response: continuation of code: %d : M len %d : M %.*s\n", ftpssn->server.response.state, req->param_size, req->param_size, req->param_begin)); if ((ftpssn->client_conf->max_resp_len > 0) && (req->param_size > ftpssn->client_conf->max_resp_len)) { /* Alert on response message overflow */ ftp_eo_event_log(ftpssn, FTP_EO_RESPONSE_LENGTH_OVERFLOW, NULL, NULL); iRet = FTPP_ALERT; } break; case FTP_RESPONSE_ENDCONT: /* Continued response end */ DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP response: final continue of code: %.*s : M len %d : " "M %.*s\n", req->cmd_size, req->cmd_begin, req->param_size, req->param_size, req->param_begin)); if ((ftpssn->client_conf->max_resp_len > 0) && (req->param_size > ftpssn->client_conf->max_resp_len)) { /* Alert on response message overflow */ ftp_eo_event_log(ftpssn, FTP_EO_RESPONSE_LENGTH_OVERFLOW, NULL, NULL); iRet = FTPP_ALERT; } break; default: DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP command: CMD: %.*s : " "P len %d : P %.*s\n", req->cmd_size, req->cmd_begin, req->param_size, req->param_size, req->param_begin)); if (CmdConf) { if ((CmdConf->max_param_len >= 0) && (req->param_size > CmdConf->max_param_len)) { /* Alert on param length overrun */ ftp_eo_event_log(ftpssn, FTP_EO_PARAMETER_LENGTH_OVERFLOW, NULL, NULL); DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP command: %.*s" "parameter length overrun %d > %d \n", req->cmd_size, req->cmd_begin, req->param_size, CmdConf->max_param_len)); iRet = FTPP_ALERT; break; } if (CmdConf->data_chan_cmd) { ftpssn->data_chan_state |= DATA_CHAN_PASV_CMD_ISSUED; ftpssn->data_chan_index = ftp_cmd_pipe_index; if (ftpssn->data_chan_state & DATA_CHAN_PORT_CMD_ISSUED) { /* * If there was a PORT command previously in * a series of pipelined requests, this * cancels it. */ ftpssn->data_chan_state &= ~DATA_CHAN_PORT_CMD_ISSUED; } } else if (CmdConf->data_xfer_cmd) { ftpssn->data_chan_state |= DATA_CHAN_XFER_CMD_ISSUED; ftpssn->data_xfer_index = ftp_cmd_pipe_index; } else if (CmdConf->encr_cmd) { if (req->param_begin && (req->param_size > 0) && ((req->param_begin[0] == 'T') || (req->param_begin[0] == 't'))) { ftpssn->encr_state = AUTH_TLS_CMD_ISSUED; } else if (req->param_begin && (req->param_size > 0) && ((req->param_begin[0] == 'S') || (req->param_begin[0] == 's'))) { ftpssn->encr_state = AUTH_SSL_CMD_ISSUED; } else { ftpssn->encr_state = AUTH_UNKNOWN_CMD_ISSUED; } } if (CmdConf->check_validity) { iRet = check_ftp_param_validity(p, req->param_begin, req->param_end, CmdConf->param_format, ftpssn); /* If negative, haven't already alerted on violation */ if (iRet < 0) { /* Set Alert on malformatted parameter */ ftp_eo_event_log(ftpssn, FTP_EO_MALFORMED_PARAMETER, NULL, NULL); iRet = FTPP_ALERT; break; } else if (iRet > 0) { /* Already alerted -- ie, string format attack. */ break; } } } break; } if (iMode == FTPP_SI_CLIENT_MODE) ftp_cmd_pipe_index++; else if ((rsp_code != 226) && (rsp_code != 426)) { /* * In terms of counting responses, ignore * 226 response saying transfer complete * 426 response saying transfer aborted * The 226 may or may not be sent by the server. * Both are 2nd response to a transfer command. */ ftp_cmd_pipe_index++; } } if (iMode == FTPP_SI_CLIENT_MODE) { ftp_cmd_pipe_index = 0; } if (encrypted) return FTPP_ALERT; return iRet;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -