📄 pp_ftp.c
字号:
} else if (Session->data_chan_state & DATA_CHAN_PASV_CMD_ISSUED) { if (ftp_cmd_pipe_index == Session->data_chan_index) { if (Session->data_xfer_index == -1) ftp_cmd_pipe_index = 0; Session->data_chan_index = -1; if (rsp_code == 227) { snort_ip ip; u_int16_t port=0; const char *ip_begin = req->param_begin; IP_CLEAR(ip); Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED; Session->data_chan_state |= DATA_CHAN_PASV_CMD_ACCEPT; Session->data_chan_index = -1; /* Interpret response message to identify the * Server IP/Port. Server response is inside * a pair of ()s. Find the left (, and use same * means to find IP/Port as is done for the PORT * command. */ while ((*ip_begin != '(') && (ip_begin < req->param_end)) { ip_begin++; } if (ip_begin < req->param_end) { ip_begin++; iRet = getIP(&ip_begin, req->param_end, ')', &ip, &port); if (iRet == FTPP_SUCCESS) {#ifdef SUP_IP6 Session->serverIP = ip;#else Session->serverIP = htonl(ip);#endif Session->serverPort = port; IP_CLEAR(Session->clientIP); Session->clientPort = 0; } } else { iRet = FTPP_MALFORMED_FTP_RESPONSE; } } else { Session->data_chan_index = -1; Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED; } } } else if (Session->data_chan_state & DATA_CHAN_PORT_CMD_ISSUED) { if (ftp_cmd_pipe_index == Session->data_chan_index) { if (Session->data_xfer_index == -1) ftp_cmd_pipe_index = 0; Session->data_chan_index = -1; if (rsp_code == 200) { Session->data_chan_state &= ~DATA_CHAN_PORT_CMD_ISSUED; Session->data_chan_state |= DATA_CHAN_PORT_CMD_ACCEPT; Session->data_chan_index = -1; } else if (ftp_cmd_pipe_index == Session->data_chan_index) { Session->data_chan_index = -1; Session->data_chan_state &= ~DATA_CHAN_PORT_CMD_ISSUED; } } } else if (Session->data_chan_state & DATA_CHAN_XFER_CMD_ISSUED) { if (ftp_cmd_pipe_index == Session->data_xfer_index) { if (Session->data_chan_index == -1) ftp_cmd_pipe_index = 0; Session->data_xfer_index = -1; if ((rsp_code == 150) || (rsp_code == 125)) { Session->data_chan_state &= ~DATA_CHAN_XFER_CMD_ISSUED; Session->data_chan_state = DATA_CHAN_XFER_STARTED; if (!IS_SET(Session->serverIP)) { /* This means we're not in passive mode. */ /* Server is listening/sending from its own IP, * FTP Port -1 */ /* Client IP, Port specified via PORT command */#ifdef SUP_IP6 IP_COPY_VALUE(Session->serverIP, GET_SRC_IP(p));#else Session->serverIP = p->ip4_header->source.s_addr;#endif /* Can't necessarily guarantee this, especially * in the case of a proxy'd connection where the * data channel might not be on port 20 (or server * port-1). Comment it out for now. */ /* Session->serverPort = ntohs(p->tcph->th_sport) -1; */ } if (!IS_SET(Session->clientIP)) { /* This means we're in passive mode. */ /* Server info is known. */ /* Client IP is known from response packet, but * port is unknown */#ifdef SUP_IP6 IP_COPY_VALUE(Session->clientIP, GET_DST_IP(p)); #else Session->clientIP = p->ip4_header->destination.s_addr;#endif } if (Session->server_conf->data_chan) { /* Call into Streams to mark data channel as something * to ignore. */#ifdef SUP_IP6 _dpd.streamAPI->ignore_session(&Session->clientIP, Session->clientPort, &Session->serverIP, Session->serverPort, p->ip4_header->proto, SSN_DIR_BOTH, 0 /* Not permanent */ );#else _dpd.streamAPI->ignore_session(Session->clientIP, Session->clientPort, Session->serverIP, Session->serverPort, p->ip4_header->proto, SSN_DIR_BOTH, 0 /* Not permanent */ );#endif } } /* Clear the session info for next transfer --> * reset host/port */ IP_CLEAR(Session->serverIP); IP_CLEAR(Session->clientIP); Session->serverPort = Session->clientPort = 0; Session->data_chan_state = NO_STATE; } } } /* if (Session->server_conf->data_chan) */ if (Session->global_conf->encrypted.on) { switch(Session->encr_state) { case AUTH_TLS_CMD_ISSUED: if (rsp_code == 234) { /* Could check that response msg includes "TLS" */ Session->encr_state = AUTH_TLS_ENCRYPTED; if (Session->global_conf->encrypted.alert) { /* Alert on encrypted channel */ ftp_eo_event_log(Session, FTP_EO_ENCRYPTED, NULL, NULL); } DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP stream is now TLS encrypted\n");); } break; case AUTH_SSL_CMD_ISSUED: if (rsp_code == 234) { /* Could check that response msg includes "SSL" */ Session->encr_state = AUTH_SSL_ENCRYPTED; if (Session->global_conf->encrypted.alert) { /* Alert on encrypted channel */ ftp_eo_event_log(Session, FTP_EO_ENCRYPTED, NULL, NULL); } DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP stream is now SSL encrypted\n");); } break; case AUTH_UNKNOWN_CMD_ISSUED: if (rsp_code == 234) { Session->encr_state = AUTH_UNKNOWN_ENCRYPTED; if (Session->global_conf->encrypted.alert) { /* Alert on encrypted channel */ ftp_eo_event_log(Session, FTP_EO_ENCRYPTED, NULL, NULL); } DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "FTP stream is now encrypted\n");); } break; } } /* if (Session->global_conf->encrypted.on) */ return iRet;}/* * Function: check_ftp(FTP_SESSION *Session, Packet *p, int iMode) * * Purpose: Handle some trivial validation checks of an FTP packet. Namely, * check argument length and some protocol enforcement. * * Wishful: This results in exposing the FTP command (and looking * at the results) to the rules layer. * * Arguments: Session => Pointer to session info * p => pointer to the current packet struct * iMode => Mode indicating server or client checks * * Returns: int => return code indicating error or success * */#define NUL 0x00#define CR 0x0d#define LF 0x0a#define SP 0x20#define DASH 0x2D#define FTP_CMD_OK 0#define FTP_CMD_INV 1#define FTP_RESPONSE_INV 1#define FTP_RESPONSE 2#define FTP_RESPONSE_2BCONT 2#define FTP_RESPONSE_CONT 3#define FTP_RESPONSE_ENDCONT 4int check_ftp(FTP_SESSION *ftpssn, SFSnortPacket *p, int iMode){ int iRet = FTPP_SUCCESS; int encrypted = 0; int space = 0; long state = FTP_CMD_OK; int rsp_code = 0; FTP_CLIENT_REQ *req; FTP_CMD_CONF *CmdConf = NULL; const unsigned char *read_ptr; const unsigned char *end = p->payload + p->payload_size; if (p->flags & FLAG_ALT_DECODE) end = _dpd.altBuffer + p->normalized_payload_size; if (iMode == FTPP_SI_CLIENT_MODE) { req = &ftpssn->client.request; ftp_cmd_pipe_index = 0; } else if (iMode == FTPP_SI_SERVER_MODE) req = (FTP_CLIENT_REQ *)&ftpssn->server.response; else return FTPP_INVALID_ARG; while (req->pipeline_req) { state = FTP_CMD_OK; /* Starts at the beginning of the buffer/line, * so next up is a command */ read_ptr = (const unsigned char *)req->pipeline_req; /* but first we ignore leading white space */ while ( (read_ptr < end) && (iMode == FTPP_SI_CLIENT_MODE) && isspace(*read_ptr) ) read_ptr++; req->cmd_begin = (const char *)read_ptr; while ((read_ptr < end) && (*read_ptr != SP) && (*read_ptr != CR) && (*read_ptr != LF) && /* Check for LF when there wasn't a CR, * protocol violation, but accepted by * some servers. */ (*read_ptr != DASH)) { /* If the first char is a digit this is a response * in server mode. */ if (iMode == FTPP_SI_SERVER_MODE) { if (isdigit(*read_ptr)) { if (state != FTP_RESPONSE_INV) { state = FTP_RESPONSE; } } else if (!isascii(*read_ptr)) { /* Non-ascii char here? Bad response */ state = FTP_RESPONSE_INV; } } /* Or, if this is not a char, this is garbage in client mode */ else if (!isalpha(*read_ptr) && (iMode == FTPP_SI_CLIENT_MODE)) { state = FTP_CMD_INV; } read_ptr++; } req->cmd_end = (const char *)read_ptr; req->cmd_size = req->cmd_end - req->cmd_begin; if (iMode == FTPP_SI_CLIENT_MODE) { if ( ((req->cmd_size != 4) && (req->cmd_size != 3)) || (state == FTP_CMD_INV) ) { /* Uh, something is very wrong... * nonalpha char seen or cmd is not 3 or 4 chars. * See if this might be encrypted, ie, non-alpha bytes. */ const unsigned char *ptr = (const unsigned char *)req->cmd_begin; while (ptr < (const unsigned char *)req->cmd_end) { if (!isalpha((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 client stream is now encrypted\n");); } break; } else { /* * Check the list of valid FTP commands as * supplied in ftpssn. */ if (req->cmd_size > 4) { /* Alert, cmd not found */ ftp_eo_event_log(ftpssn, FTP_EO_INVALID_CMD, NULL, NULL); state = FTP_CMD_INV; } else { CmdConf = ftp_cmd_lookup_find(ftpssn->server_conf->cmd_lookup, req->cmd_begin, req->cmd_size, &iRet); if ((iRet == FTPP_NOT_FOUND) || (CmdConf == NULL)) { /* Alert, cmd not found */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -