/* * Function: FTPInitConf(Packet *p, FTPTELNET_GLOBAL_CONF *GlobalConf, * FTP_CLIENT_PROTO_CONF **ClientConf, * FTP_SERVER_PROTO_CONF **ServerConf, * FTPP_SI_INPUT *SiInput, int *piInspectMode) * * Purpose: When a session is initialized, we must select the appropriate * server configuration and select the type of inspection based * on the source and destination ports. * * IMPORTANT NOTE: * We should check to make sure that there are some unique configurations, * otherwise we can just default to the global default and work some magic * that way. * * Arguments: p => pointer to the Packet/Session * GlobalConf => pointer to the global configuration * ClientConf => pointer to the address of the client * config so we can set it. * ServerConf => pointer to the address of the server * config so we can set it. * SiInput => pointer to the packet info * piInspectMode => pointer so we can set the inspection mode * * Returns: int => return code indicating error or success * */ static int FTPInitConf(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf, FTP_CLIENT_PROTO_CONF **ClientConf, FTP_SERVER_PROTO_CONF **ServerConf, FTPP_SI_INPUT *SiInput, int *piInspectMode) { FTP_CLIENT_PROTO_CONF *ClientConfSip; FTP_CLIENT_PROTO_CONF *ClientConfDip; FTP_SERVER_PROTO_CONF *ServerConfSip; FTP_SERVER_PROTO_CONF *ServerConfDip; int iServerSip; int iServerDip; int iErr = 0; int iRet = FTPP_SUCCESS; #ifdef TARGET_BASED int16_t app_id = 0; #endif snort_ip sip; snort_ip dip; //structure copy sip = SiInput->sip; dip = SiInput->dip; if (sip.family == AF_INET) { sip.ip.u6_addr32[0] = ntohl(sip.ip.u6_addr32[0]); } if (dip.family == AF_INET) { dip.ip.u6_addr32[0] = ntohl(dip.ip.u6_addr32[0]); } /* * We find the client configurations for both the source and dest IPs. * There should be a check on the global configuration to see if there * is at least one unique client configuration. If there isn't then we * assume the global client configuration. */ ClientConfDip = ftpp_ui_client_lookup_find(GlobalConf->client_lookup, &dip, &iErr); if(!ClientConfDip) { ClientConfDip = GlobalConf->default_ftp_client; } ClientConfSip = ftpp_ui_client_lookup_find(GlobalConf->client_lookup, &sip, &iErr); if(!ClientConfSip) { ClientConfSip = GlobalConf->default_ftp_client; } /* * Now, we find the server configurations for both the source and dest IPs. * There should be a check on the global configuration to see if there * is at least one unique client configuration. If there isn't then we * assume the global client configuration. */ ServerConfDip = ftpp_ui_server_lookup_find(GlobalConf->server_lookup, &dip, &iErr); if(!ServerConfDip) { ServerConfDip = GlobalConf->default_ftp_server; } ServerConfSip = ftpp_ui_server_lookup_find(GlobalConf->server_lookup, &sip, &iErr); if(!ServerConfSip) { ServerConfSip = GlobalConf->default_ftp_server; } /* * We check the IP and the port to see if the FTP client is talking in * the session. This should tell us whether it is client communication * or server configuration. If both IPs and ports are servers, then there * is a sort of problem. We don't know which side is the client and which * side is the server so we have to assume one. * * In stateful processing, we only do this stage on the startup of a * session, so we can still assume that the initial packet is the client * talking. */ iServerDip = PortMatch((PROTO_CONF*)ServerConfDip, SiInput->dport); iServerSip = PortMatch((PROTO_CONF*)ServerConfSip, SiInput->sport); /* * We default to the no FTP traffic case */ *piInspectMode = FTPP_SI_NO_MODE; *ClientConf = NULL; *ServerConf = NULL; /* * Depending on the type of packet direction we get from the * state machine, we evaluate client/server differently. */ switch(SiInput->pdir) { case FTPP_SI_NO_MODE: #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(p->stream_session_ptr); if (app_id == ftp_app_id || app_id == 0) { #endif /* * We check for the case where both SIP and DIP * appear to be servers. In this case, we assume server * and process that way. */ if(iServerSip && iServerDip) { /* * We check for the case where both SIP and DIP * appear to be servers. In this case, we look at * the first few bytes of the packet to try to * determine direction -- 3 digits indicate server * response. */ /* look at the first few bytes of the packet. We might * be wrong if this is a reassembled packet and we catch * a server response mid-stream. */ *piInspectMode = FTPGetPacketDir(p); if (*piInspectMode == FTPP_SI_SERVER_MODE) { /* Packet is from server --> src is Server */ *ClientConf = ClientConfDip; *ServerConf = ServerConfSip; } else /* Assume client */ { /* Packet is from client --> dest is Server */ *piInspectMode = FTPP_SI_CLIENT_MODE; *ClientConf = ClientConfSip; *ServerConf = ServerConfDip; } SiInput->pproto = FTPP_SI_PROTO_FTP; } else if(iServerDip) { /* Packet is from client --> dest is Server */ *piInspectMode = FTPP_SI_CLIENT_MODE; *ClientConf = ClientConfSip; *ServerConf = ServerConfDip; SiInput->pproto = FTPP_SI_PROTO_FTP; } else if(iServerSip) { /* Packet is from server --> src is Server */ *piInspectMode = FTPP_SI_SERVER_MODE; *ClientConf = ClientConfDip; *ServerConf = ServerConfSip; SiInput->pproto = FTPP_SI_PROTO_FTP; } break; #ifdef TARGET_BASED } #endif case FTPP_SI_CLIENT_MODE: /* Packet is from client --> dest is Server */ #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(p->stream_session_ptr); if ((app_id == ftp_app_id) || (!app_id && iServerDip)) #else if(iServerDip) #endif { *piInspectMode = FTPP_SI_CLIENT_MODE; *ClientConf = ClientConfSip; *ServerConf = ServerConfDip; SiInput->pproto = FTPP_SI_PROTO_FTP; } else { *piInspectMode = FTPP_SI_NO_MODE; iRet = FTPP_NONFATAL_ERR; } break; case FTPP_SI_SERVER_MODE: /* Packet is from server --> src is Server */ #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(p->stream_session_ptr); if ((app_id == ftp_app_id) || (!app_id && iServerSip)) #else if(iServerSip) #endif { *piInspectMode = FTPP_SI_SERVER_MODE; *ClientConf = ClientConfDip; *ServerConf = ServerConfSip; SiInput->pproto = FTPP_SI_PROTO_FTP; } else { *piInspectMode = FTPP_SI_NO_MODE; iRet = FTPP_NONFATAL_ERR; } break; default: *piInspectMode = FTPP_SI_NO_MODE; *ClientConf = NULL; *ServerConf = NULL; break; } return iRet; }
/* * Function: FTPStatefulSessionInspection(Packet *p, * FTPTELNET_GLOBAL_CONF *GlobalConf, * FTP_SESSION **FtpSession, * FTPP_SI_INPUT *SiInput, int *piInspectMode) * * Purpose: Initialize the session and server configurations for this * packet/stream. In this function, we set the Session pointer * (which includes the correct server configuration). The actual * processing to find which IP is the server and which is the * client, is done in the InitServerConf() function. * * Arguments: p => pointer to the Packet/Session * GlobalConf => pointer to the global configuration * Session => double pointer to the Session structure * SiInput => pointer to the session information * piInspectMode => pointer so the inspection mode can be set * * Returns: int => return code indicating error or success * */ static int FTPStatefulSessionInspection(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf, FTP_SESSION **FtpSession, FTPP_SI_INPUT *SiInput, int *piInspectMode) { FTP_CLIENT_PROTO_CONF *ClientConf; FTP_SERVER_PROTO_CONF *ServerConf; int iRet; FTP_SESSION *NewSession; /* * First, check if there is already a session pointer. */ if (p->stream_session_ptr) { *FtpSession = _dpd.streamAPI->get_application_data(p->stream_session_ptr, PP_FTPTELNET); if (*FtpSession) { if (SiInput->pdir != FTPP_SI_NO_MODE) { *piInspectMode = SiInput->pdir; } else { FTP_SESSION *tmp = *FtpSession; /* check session pointer server conf port */ if (tmp->server_conf && tmp->server_conf->proto_ports.ports[SiInput->sport]) *piInspectMode = FTPP_SI_SERVER_MODE; else if (tmp->server_conf && tmp->server_conf->proto_ports.ports[SiInput->dport]) *piInspectMode = FTPP_SI_CLIENT_MODE; else *piInspectMode = FTPGetPacketDir(p); } return FTPP_SUCCESS; } } /* * If not, create a new one, and initialize it. */ iRet = FTPInitConf(p, GlobalConf, &ClientConf, &ServerConf, SiInput, piInspectMode); if (iRet) { return iRet; } if (*piInspectMode) { NewSession = (FTP_SESSION *)calloc(1, sizeof(FTP_SESSION)); if (NewSession == NULL) { DynamicPreprocessorFatalMessage("%s(%d) => Failed to allocate memory for new FTP session\n", *(_dpd.config_file), *(_dpd.config_line)); } FTPResetSession(NewSession, 1); NewSession->client_conf = ClientConf; NewSession->server_conf = ServerConf; NewSession->global_conf = GlobalConf; *FtpSession = NewSession; return FTPP_SUCCESS; } return FTPP_INVALID_PROTO; }