📄 pp_ftp.c
字号:
iRet = validate_date_format(ThisFmt->format.date_fmt, &tmp_ch); if (iRet != FTPP_SUCCESS) { /* Alert invalid date */ return FTPP_INVALID_PARAM; } if (!isspace(*tmp_ch)) { /* Alert invalid date -- didn't make it to end of parameter. Overflow attempt? */ return FTPP_INVALID_PARAM; } this_param = tmp_ch; } break; case e_host_port: /* check that this_param is #,#,#,#,#,# */ { u_int32_t ip; u_int16_t port=0; int iRet; iRet = getIP(&this_param, end, ' ', &ip, &port); switch (iRet) { case FTPP_NON_DIGIT: /* Alert on non-digit */ return FTPP_INVALID_PARAM; break; case FTPP_INVALID_ARG: /* Alert on number > 255 */ return FTPP_INVALID_PARAM; break; case FTPP_MALFORMED_IP_PORT: /* Alert on malformed host-port */ return FTPP_INVALID_PARAM; break; } if ((Session->client_conf->bounce.on) && (Session->client_conf->bounce.alert)) { if (ip != ntohl(p->ip4_header->source.s_addr)) { int alert = 1; char *ipPtr = (char *)&ip; FTP_BOUNCE_TO *BounceTo = ftp_bounce_lookup_find( Session->client_conf->bounce_lookup, ipPtr, 4, &iRet); if (BounceTo) { if (BounceTo->portlo) { if (BounceTo->porthi) { if ((port >= BounceTo->portlo) && (port <= BounceTo->porthi)) alert = 0; } else { if (port == BounceTo->portlo) alert = 0; } } } /* Alert on invalid IP address for PORT */ if (alert) { ftp_eo_event_log(Session, FTP_EO_BOUNCE, NULL, NULL); /* Return here -- because we will likely want to * inspect the data traffic over a bounced data * connection */ return FTPP_PORT_ATTACK; } } } Session->clientIP = htonl(ip); Session->clientPort = port; Session->data_chan_state |= DATA_CHAN_PORT_CMD_ISSUED; if (Session->data_chan_state & DATA_CHAN_PASV_CMD_ISSUED) { /* * If there was a PORT command previously in * a series of pipelined requests, this * cancels it. */ Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED; } Session->serverIP = 0; Session->serverPort = 0; } break; } ThisFmt->next_param = this_param; return FTPP_SUCCESS;}/* * Function: check_ftp_param_validity( * Packet *p, * char *params_begin, * char *params_end, * FTP_PARAM_FMT *param_format, * FTP_SESSION *Session) * * Purpose: Recursively determines whether each of the parameters for * an FTP command are valid. * * Arguments: p => Pointer to the current packet * params_begin => Pointer to beginning of parameters * params_end => End of params buffer * param_format => Parameter format specifier for this command * Session => Pointer to the session info * * Returns: int => return code indicating error or success * */int check_ftp_param_validity(SFSnortPacket *p, char *params_begin, char *params_end, FTP_PARAM_FMT *param_format, FTP_SESSION *Session){ int iRet = FTPP_ALERT; FTP_PARAM_FMT *ThisFmt = param_format; FTP_PARAM_FMT *NextFmt; char *this_param = params_begin; if (!param_format) return FTPP_INVALID_ARG; if (!params_begin) return FTPP_INVALID_ARG; if ((!ThisFmt->next_param_fmt) && (params_begin >= params_end)) return FTPP_SUCCESS; ThisFmt->next_param = params_begin; if (ThisFmt->optional_fmt) { /* Check against optional */ iRet = validate_param(p, this_param, params_end, ThisFmt->optional_fmt, Session); if (iRet == FTPP_SUCCESS) { char *next_param; NextFmt = ThisFmt->optional_fmt; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; } } } if ((iRet != FTPP_SUCCESS) && (ThisFmt->choices)) { /* Check against choices -- one of many */ int i; int valid = 0; for (i=0;i<ThisFmt->numChoices && !valid;i++) { /* Try choice [i] */ iRet = validate_param(p, this_param, params_end, ThisFmt->choices[i], Session); if (iRet == FTPP_SUCCESS) { char *next_param; NextFmt = ThisFmt->choices[i]; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; valid = 1; break; } } } } else if ((iRet != FTPP_SUCCESS) && (ThisFmt->next_param_fmt)) { /* Check against next param */ iRet = validate_param(p, this_param, params_end, ThisFmt->next_param_fmt, Session); if (iRet == FTPP_SUCCESS) { char *next_param; NextFmt = ThisFmt->next_param_fmt; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; } } } if (iRet == FTPP_SUCCESS) { ThisFmt->next_param = this_param; } return iRet;}/* * Function: initialize_ftp(FTP_SESSION *Session, Packet *p, int iMode) * * Purpose: Initializes the state machine for checking an FTP packet. * Does normalization checks. * * 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 * */int initialize_ftp(FTP_SESSION *Session, SFSnortPacket *p, int iMode){ int iRet; unsigned char *read_ptr = p->payload; FTP_CLIENT_REQ *req; /* Normalize this packet ala telnet */ iRet = normalize_telnet(Session->global_conf, NULL, p, iMode); if (iRet != FTPP_SUCCESS && iRet != FTPP_NORMALIZED) { if (iRet == FTPP_ALERT) { if (Session->global_conf->global_telnet.detect_anomalies) { ftp_eo_event_log(Session, FTP_EO_EVASIVE_TELNET_CMD, NULL, NULL); } } return iRet; } if (p->flags & FLAG_ALT_DECODE) { /* Normalized data will always be in decode buffer */ if ( ((Session->client_conf->telnet_cmds.alert) && (iMode == FTPP_SI_CLIENT_MODE)) || ((Session->server_conf->telnet_cmds.alert) && (iMode == FTPP_SI_SERVER_MODE)) ) { /* alert -- FTP channel with telnet commands */ ftp_eo_event_log(Session, FTP_EO_TELNET_CMD, NULL, NULL); return FTPP_ALERT; /* Nothing else to do since we alerted */ } read_ptr = _dpd.altBuffer; } if (iMode == FTPP_SI_CLIENT_MODE) req = &Session->client.request; else if (iMode == FTPP_SI_SERVER_MODE) req = (FTP_CLIENT_REQ *)&Session->server.response; else return FTPP_INVALID_ARG; /* Set the beginning of the pipeline to the start of the * (normalized) buffer */ req->pipeline_req = read_ptr; return FTPP_SUCCESS;}#ifdef MAINTAIN_DIR_STATE/* * Function: adjust_dir(FTP_SESSION *Session, int cmd, * char *result, int resultLen) * * Purpose: Updates the state information that tracks the FTP * directory. * * Arguments: Session => Pointer to session info * cmd => CDUP, CWD, or PWD * result => Pointer to response for PWD * resultLen => Length of above * * Returns: void => None * */void adjust_dir(FTP_SESSION *Session, int cmd, char *result, int resultLen){ char *dirPtr; int iLen; switch (cmd) { case CDUP_CMD_ISSUED: if (Session->curr_directory) { FTP_DIR_NODE *old = Session->curr_directory; Session->curr_directory = Session->curr_directory->parent; FTPFreeDirectory(old); if (Session->curr_directory) Session->curr_directory->next = NULL; else Session->head_directory = NULL; } else { /* CD beyond root... problem */ /* TODO: set an alert here... ? */ Session->dir_state = LOST_STATE; } break; case CWD_CMD_ISSUED: if (Session->dir_adjust[0] == '/') { FTPFreeDirectory(Session->head_directory); Session->head_directory = Session->curr_directory = NULL; } else if (Session->dir_adjust[0] == '~') { /* Can't really guess at the home dir for user x... */ Session->dir_state = LOST_STATE; } dirPtr = strtok(Session->dir_adjust, "/"); while (dirPtr) { FTP_DIR_NODE *thisNode; /* Trying to include . as a directory. * Nothing to do... */ if (!strcmp(dirPtr, ".")) { dirPtr = strtok(NULL, "/"); continue; } /* Trying to include .. as a directory. * Go up one */ if (!strcmp(dirPtr, "..")) { if (Session->curr_directory) { FTP_DIR_NODE *old = Session->curr_directory; Session->curr_directory = Session->curr_directory->parent; FTPFreeDirectory(old); if (Session->curr_directory) Session->curr_directory->next = NULL; else Session->head_directory = NULL; } else { /* CD beyond root... problem */ /* TODO: set an alert here... ? */ Session->dir_state = LOST_STATE; } dirPtr = strtok(NULL, "/"); continue; } iLen = strlen(dirPtr); thisNode = malloc(sizeof(FTP_DIR_NODE)); thisNode->name = calloc(sizeof(char), iLen + 1); memcpy(thisNode->name, dirPtr, iLen); if (!Session->curr_directory) { Session->curr_directory = thisNode; Session->head_directory = thisNode; thisNode->parent = NULL; thisNode->next = NULL; } else { thisNode->parent = Session->curr_directory; thisNode->next = NULL; Session->curr_directory->next = thisNode; Session->curr_directory = thisNode; } dirPtr = strtok(NULL, "/"); } break; case PWD_CMD_ISSUED: /* This is a special case -- we can check state and/or * reset, as necessary. Start at head, check. If * we find a mismatch, update current dir. :) */ { char normalizedDir[1024]; int i = 0 ,j = 0; int quotes_seen = 0; FTP_DIR_NODE *thisNode = Session->head_directory; int reset = 0; memset(&normalizedDir[0], 0, 1024); /* First normalize the directory name from the response * to eliminate the escaped " -- noted by a "". The * directory name is encapsulated in quotes. */ for (i=0;i<resultLen && quotes_seen < 2 && j < 1024; ) { if (result[i] == '\"') { if ((i < resultLen -1) && (result[i+1] == '\"')) { normalizedDir[j++] = result[i++]; i++; /* Skip the 2nd " */ } else { quotes_seen++; i++; } } else { normalizedDir[j++] = result[i++]; } } /* Now search for each dir component in turn */ dirPtr = strtok(normalizedDir, "/"); while (dirPtr && !reset) { if (!thisNode) { reset = 1; break; } if (strcmp(thisNode->name, dirPtr)) { /* Uh, lost state, kill everything below here */ FTPFreeDirectory(thisNode->next); free(thisNode->name); iLen = strlen(dirPtr); thisNode->name = calloc(sizeof(char), iLen + 1); memcpy(thisNode->name, dirPtr, iLen); reset = 1; } thisNode = thisNode->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -