static PAF_Status h2_paf ( void* ssn, void** pv, const uint8_t* data, uint32_t len, uint64_t *flags, uint32_t* fp, uint32_t* fp_eoh) { PAF_Status paf = PAF_IGNORE; PROFILE_VARS; PREPROC_PROFILE_START(hi2PerfStats); if (!stream_api->is_session_http2(ssn)) { if (*flags & PKT_H1_ABORT) paf = PAF_ABORT; else paf = PAF_SEARCH; PREPROC_PROFILE_END(hi2PerfStats); return paf; } #ifdef HAVE_LIBNGHTTP2 int ret = 0; int i = 1; return_data_list_node *current; http2_session_data *sd = (http2_session_data *)session_api->get_application_data(ssn, PP_HTTP2); if(sd == NULL) { bool upg; sd = calloc(1, sizeof(http2_session_data)); if (!sd) { PREPROC_PROFILE_END(hi2PerfStats); return PAF_ABORT; } upg = stream_api->is_session_http2_upg(ssn); PREPROC_PROFILE_START(hi2InitPerfStats); { initialize_nghttp2_session_snort(&(sd->session[0]), sd, 0, upg); initialize_nghttp2_session_snort(&(sd->session[1]), sd, 1, upg); } PREPROC_PROFILE_END(hi2InitPerfStats); session_api->set_application_data(ssn, PP_HTTP2, sd, h2_paf_clear); } sd->first_return_data = NULL; sd->num_of_return_data = 0; DEBUG_WRAP(DebugMessage(DEBUG_STREAM_PAF, "%s: Amount of data passed for Http/2 processing: %u\n", __FUNCTION__, len);)
int mpseSearch( void *pvoid, const unsigned char * T, int n, int ( *action )(void*id, int index, void *data), void * data, int* current_state ) { MPSE * p = (MPSE*)pvoid; int ret; PROFILE_VARS; PREPROC_PROFILE_START(mpsePerfStats); p->bcnt += n; if(p->inc_global_counter) s_bcnt += n; switch( p->method ) { case MPSE_AC_BNFA: /* return is actually the state */ ret = bnfaSearch( (bnfa_struct_t*) p->obj, (unsigned char *)T, n, action, data, 0 /* start-state */, current_state ); PREPROC_PROFILE_END(mpsePerfStats); return ret; case MPSE_AC: ret = acsmSearch( (ACSM_STRUCT*) p->obj, (unsigned char *)T, n, action, data, current_state ); PREPROC_PROFILE_END(mpsePerfStats); return ret; case MPSE_ACF: case MPSE_ACS: case MPSE_ACB: case MPSE_ACSB: ret = acsmSearch2( (ACSM_STRUCT2*) p->obj, (unsigned char *)T, n, action, data, current_state ); PREPROC_PROFILE_END(mpsePerfStats); return ret; case MPSE_LOWMEM: ret = KTrieSearch( (KTRIE_STRUCT *)p->obj, (unsigned char *)T, n, action, data); *current_state = 0; PREPROC_PROFILE_END(mpsePerfStats); return ret; default: PREPROC_PROFILE_START(mpsePerfStats); return 1; } }
/* * Function: SMTPFunction(Packet *) * * Purpose: Perform the preprocessor's intended function. This can be * simple (statistics collection) or complex (IP defragmentation) * as you like. Try not to destroy the performance of the whole * system by trying to do too much.... * * Arguments: p => pointer to the current packet data struct * * Returns: void function * */ static void SMTPDetect(void *pkt, void *context) { SFSnortPacket *p = (SFSnortPacket *)pkt; PROFILE_VARS; if(!IsTCP(p)) { return; } PREPROC_PROFILE_START(smtpPerfStats); SnortSMTP(p); PREPROC_PROFILE_END(smtpPerfStats); #ifdef PERF_PROFILING if (smtpDetectCalled) { smtpPerfStats.ticks -= smtpDetectPerfStats.ticks; /* And Reset ticks to 0 */ smtpDetectPerfStats.ticks = 0; smtpDetectCalled = 0; } #endif /* * if you need to issue an alert from your preprocessor, check out * event_wrapper.h, there are some useful helper functions there */ }
/** ** This function wraps the functionality in the generic HttpInspect ** processing. We get a Packet structure and pass this into the ** HttpInspect module where the first stage in HttpInspect is the ** Session Inspection stage where most of the other Snortisms are ** taken care of. After that, the modules should be fairly generic, ** and that's what we're trying to do here. ** ** @param p a Packet structure that contains Snort info about the ** packet. ** ** @return void */ static void HttpInspect(Packet *p, void *context) { PROFILE_VARS; /* ** IMPORTANT: ** This is where we initialize any variables that can impact other ** aspects of detection/processing. ** ** First thing that we do is reset the p->uri_count to zero, so there ** is no way that we would inspect a buffer that was completely bogus. */ p->uri_count = 0; UriBufs[0].decode_flags = 0; /* ** Check for valid packet ** if neither header or data is good, then we just abort. */ if(!IPH_IS_VALID(p) || !p->tcph || !p->data || !p->dsize) { return; } PREPROC_PROFILE_START(hiPerfStats); /* ** Pass in the configuration and the packet. */ SnortHttpInspect(&GlobalConf, p); p->uri_count = 0; UriBufs[0].decode_flags = 0; /* XXX: * NOTE: this includes the HTTPInspect directly * calling the detection engine - * to get the true HTTPInspect only stats, have another * var inside SnortHttpInspect that tracks the time * spent in Detect(). * Subtract the ticks from this if iCallDetect == 0 */ PREPROC_PROFILE_END(hiPerfStats); #ifdef PERF_PROFILING if (hiDetectCalled) { hiPerfStats.ticks -= hiDetectPerfStats.ticks; /* And Reset ticks to 0 */ hiDetectPerfStats.ticks = 0; hiDetectCalled = 0; } #endif return; }
int mpseSearchAll( void *pvoid, const unsigned char * T, int n, int ( *action )(void* id, void * tree, int index, void *data, void *neg_list), void * data, int* current_state ) { MPSE * p = (MPSE*)pvoid; int ret; PROFILE_VARS; PREPROC_PROFILE_START(mpsePerfStats); p->bcnt += n; if(p->inc_global_counter) s_bcnt += n; switch( p->method ) { case MPSE_ACF: case MPSE_ACF_Q: case MPSE_ACS: case MPSE_ACB: case MPSE_ACSB: ret = acsmSearchAll2( (ACSM_STRUCT2*) p->obj, (unsigned char *)T, n, action, data, current_state ); PREPROC_PROFILE_END(mpsePerfStats); return ret; case MPSE_AC_BNFA: case MPSE_AC_BNFA_Q: case MPSE_AC: case MPSE_LOWMEM: case MPSE_LOWMEM_Q: #ifdef INTEL_SOFT_CPM case MPSE_INTEL_CPM: #endif default: //search all not implemented. PREPROC_PROFILE_END(mpsePerfStats); return 1; } }
static void AppIdProcess(SFSnortPacket *p, void *context) { PROFILE_VARS; PREPROC_PROFILE_START(appMatchPerfStats); /* Trust */ if (p->stream_session && _dpd.sessionAPI->get_ignore_direction(p->stream_session) == SSN_DIR_BOTH) { _dpd.sessionAPI->disable_preproc_for_session( p->stream_session, PP_NETWORK_DISCOVERY ); return; } fwAppIdSearch(p); PREPROC_PROFILE_END(appMatchPerfStats); }
/********************************************************************* * Function: * * Purpose: * * Arguments: * * Returns: * *********************************************************************/ void DCE2_PopPkt(void) { SFSnortPacket *pop_pkt = (SFSnortPacket *)DCE2_CStackPop(dce2_pkt_stack); PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_log); if (pop_pkt == NULL) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) No packet to pop off stack.", __FILE__, __LINE__); PREPROC_PROFILE_END(dce2_pstat_log); return; } _dpd.pushAlerts(); _dpd.logAlerts((void *)pop_pkt); _dpd.resetAlerts(); _dpd.popAlerts(); PREPROC_PROFILE_END(dce2_pstat_log); }
/********************************************************************* * Function: * * Purpose: * * Arguments: * * Returns: * *********************************************************************/ DCE2_Ret DCE2_PushPkt(SFSnortPacket *p) { SFSnortPacket *top_pkt = (SFSnortPacket *)DCE2_CStackTop(dce2_pkt_stack); if (top_pkt != NULL) { PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_log); _dpd.pushAlerts(); _dpd.logAlerts((void *)top_pkt); _dpd.resetAlerts(); _dpd.popAlerts(); PREPROC_PROFILE_END(dce2_pstat_log); } if (DCE2_CStackPush(dce2_pkt_stack, (void *)p) != DCE2_RET__SUCCESS) return DCE2_RET__ERROR; return DCE2_RET__SUCCESS; }
void FTPDataTelnetChecks(void *pkt, void *context) { SFSnortPacket *p = (SFSnortPacket*)pkt; // precondition - what we registered for assert(IsTCP(p)); if ( _dpd.fileAPI->get_max_file_depth() >= 0 ) { if ( _dpd.sessionAPI->get_application_protocol_id(p->stream_session) == ftp_data_app_id ) { PROFILE_VARS; PREPROC_PROFILE_START(ftpdataPerfStats); SnortFTPData(p); PREPROC_PROFILE_END(ftpdataPerfStats); return; } } if ( !p->payload_size || (p->payload == NULL) ) return; SnortFTPTelnet(p); }
/* Main runtime entry point for SSH preprocessor. * Analyzes SSH packets for anomalies/exploits. * * PARAMETERS: * * packetp: Pointer to current packet to process. * contextp: Pointer to context block, not used. * * RETURNS: Nothing. */ static void ProcessSSH( void* ipacketp, void* contextp ) { SSHData* sessp = NULL; uint8_t source = 0; uint8_t dest = 0; uint8_t known_port = 0; uint8_t direction; SFSnortPacket* packetp; #ifdef TARGET_BASED int16_t app_id = SFTARGET_UNKNOWN_PROTOCOL; #endif tSfPolicyId policy_id = _dpd.getRuntimePolicy(); PROFILE_VARS; packetp = (SFSnortPacket*) ipacketp; sfPolicyUserPolicySet (ssh_config, policy_id); /* Make sure this preprocessor should run. */ if (( !packetp ) || ( !packetp->payload ) || ( !packetp->payload_size ) || ( !IPH_IS_VALID(packetp) ) || ( !packetp->tcp_header ) || /* check if we're waiting on stream reassembly */ ( packetp->flags & FLAG_STREAM_INSERT)) { return; } PREPROC_PROFILE_START(sshPerfStats); ssh_eval_config = sfPolicyUserDataGetCurrent(ssh_config); /* Attempt to get a previously allocated SSH block. */ sessp = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_SSH); if (sessp != NULL) { ssh_eval_config = sfPolicyUserDataGet(sessp->config, sessp->policy_id); known_port = 1; } if (sessp == NULL) { /* If not doing autodetection, check the ports to make sure this is * running on an SSH port, otherwise no need to examine the traffic. */ #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(packetp->stream_session_ptr); if (app_id == SFTARGET_UNKNOWN_PROTOCOL) { PREPROC_PROFILE_END(sshPerfStats); return; } if (app_id && (app_id != ssh_app_id)) { PREPROC_PROFILE_END(sshPerfStats); return; } if (app_id == ssh_app_id) { known_port = 1; } if (!app_id) { #endif source = (uint8_t)CheckSSHPort( packetp->src_port ); dest = (uint8_t)CheckSSHPort( packetp->dst_port ); if ( !ssh_eval_config->AutodetectEnabled && !source && !dest ) { /* Not one of the ports we care about. */ PREPROC_PROFILE_END(sshPerfStats); return; } #ifdef TARGET_BASED } #endif /* Check the stream session. If it does not currently * have our SSH data-block attached, create one. */ sessp = SSHGetNewSession(packetp, policy_id); if ( !sessp ) { /* Could not get/create the session data for this packet. */ PREPROC_PROFILE_END(sshPerfStats); return; } /* See if a known server port is involved. */ if (!known_port) { known_port = ( source || dest ? 1 : 0 ); /* If this is a non-SSH port, but autodetect is on, we flag this session to reduce false positives later on. */ if (!known_port && ssh_eval_config->AutodetectEnabled) { sessp->state_flags |= SSH_FLG_AUTODETECTED; } } } /* Don't process if we've missed packets */ if (sessp->state_flags & SSH_FLG_MISSED_PACKETS) return; /* If we picked up mid-stream or missed any packets (midstream pick up * means we've already missed packets) set missed packets flag and make * sure we don't do any more reassembly on this session */ if ((_dpd.streamAPI->get_session_flags(packetp->stream_session_ptr) & SSNFLAG_MIDSTREAM) || _dpd.streamAPI->missed_packets(packetp->stream_session_ptr, SSN_DIR_BOTH)) { /* Don't turn off reassembly if autodetected since another preprocessor * may actually be looking at this session as well and the SSH * autodetect of this session may be wrong. */ if (!(sessp->state_flags & SSH_FLG_AUTODETECTED)) { _dpd.streamAPI->set_reassembly(packetp->stream_session_ptr, STREAM_FLPOLICY_IGNORE, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE); } sessp->state_flags |= SSH_FLG_MISSED_PACKETS; return; } /* We're interested in this session. Turn on stream reassembly. */ if ( !(sessp->state_flags & SSH_FLG_REASSEMBLY_SET )) { _dpd.streamAPI->set_reassembly(packetp->stream_session_ptr, STREAM_FLPOLICY_FOOTPRINT, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_APPEND); sessp->state_flags |= SSH_FLG_REASSEMBLY_SET; } /* Get the direction of the packet. */ direction = ( (packetp->flags & FLAG_FROM_SERVER ) ? SSH_DIR_FROM_SERVER : SSH_DIR_FROM_CLIENT ); if ( !(sessp->state_flags & SSH_FLG_SESS_ENCRYPTED )) { /* If server and client have not performed the protocol * version exchange yet, must look for version strings. */ if ( (sessp->state_flags & SSH_FLG_BOTH_IDSTRING_SEEN) != SSH_FLG_BOTH_IDSTRING_SEEN ) { if ( ProcessSSHProtocolVersionExchange( sessp, packetp, direction, known_port ) == SSH_FAILURE ) { /*Error processing protovers exchange msg */ } PREPROC_PROFILE_END(sshPerfStats); return; } /* Expecting to see the key init exchange at this point * (in SSH2) or the actual key exchange if SSH1 */ if ((( sessp->state_flags & SSH_FLG_V1_KEYEXCH_DONE ) != SSH_FLG_V1_KEYEXCH_DONE ) && ((sessp->state_flags & SSH_FLG_V2_KEXINIT_DONE ) != SSH_FLG_V2_KEXINIT_DONE )) { ProcessSSHKeyInitExchange( sessp, packetp, direction ); PREPROC_PROFILE_END(sshPerfStats); return; } /* If SSH2, need to process the actual key exchange msgs. * The actual key exchange type was negotiated in the * key exchange init msgs. SSH1 won't arrive here. */ ProcessSSHKeyExchange( sessp, packetp, direction ); } else { /* Traffic on this session is currently encrypted. * Two of the major SSH exploits, SSH1 CRC-32 and * the Challenge-Response Overflow attack occur within * the encrypted portion of the SSH session. Therefore, * the only way to detect these attacks is by examining * amounts of data exchanged for anomalies. */ sessp->num_enc_pkts++; if ( sessp->num_enc_pkts <= ssh_eval_config->MaxEncryptedPackets ) { if ( direction == SSH_DIR_FROM_CLIENT ) { sessp->num_client_bytes += packetp->payload_size; if ( sessp->num_client_bytes >= ssh_eval_config->MaxClientBytes ) { /* Probable exploit in progress.*/ if (sessp->version == SSH_VERSION_1) { if ( ssh_eval_config->EnabledAlerts & SSH_ALERT_CRC32 ) { ALERT(SSH_EVENT_CRC32, SSH_EVENT_CRC32_STR); _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } else { if (ssh_eval_config->EnabledAlerts & SSH_ALERT_RESPOVERFLOW ) { ALERT(SSH_EVENT_RESPOVERFLOW, SSH_EVENT_RESPOVERFLOW_STR); _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } } } else { /* * Have seen a server response, so * this appears to be a valid exchange. * Reset suspicious byte count to zero. */ sessp->num_client_bytes = 0; } } else { /* Have already examined more than the limit * of encrypted packets. Both the Gobbles and * the CRC32 attacks occur during authentication * and therefore cannot be used late in an * encrypted session. For performance purposes, * stop examining this session. */ _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } PREPROC_PROFILE_END(sshPerfStats); }
/** * The runtime entry point for the flow module from snort * * 1) Assign each packet a flow * 2) Perform various callbacks based on the parameters for the flow * * @param p packet to process */ static void FlowPreprocessor(Packet *p, void *context) { int flow_class; /**< addressing scheme to use */ int direction; /**< which way does the flow go */ static time_t last_output = 0; FLOWKEY search_key; FLOW *fp; FLOWCACHE *fcache = &s_fcache; FLOWPACKET *pkt = (FLOWPACKET *) p; PROFILE_VARS; if(!FlowPacket(p)) { return; } PREPROC_PROFILE_START(flowPerfStats); /* first find the addressing schema */ if(flow_classifier(pkt, &flow_class) != FLOW_SUCCESS) { //LogMessage("Error classifying packet\n"); return; } switch(flow_class) { case FLOW_IPV4: if(flowkey_make(&search_key, pkt) != FLOW_SUCCESS) { ErrorMessage("Unable to make a search key\n"); PREPROC_PROFILE_END(flowPerfStats); return; } break; default: ErrorMessage("Unknown Flow Type: %d\n", flow_class); PREPROC_PROFILE_END(flowPerfStats); return; } /** this should return a direction too for the key */ //printf("flowkey: "); flowkey_fprint(stdout, &search_key); printf("\n"); if(flowcache_find(fcache, &search_key, &fp, &direction) == FLOW_SUCCESS) { /* ** We set flows for rebuilt pkts if there is one, otherwise ** we just bail. */ if(p->packet_flags & PKT_REBUILT_STREAM) { p->flow = fp; PREPROC_PROFILE_END(flowPerfStats); return; } if(direction == FROM_RESPONDER && fp->stats.packets_recv == 0) { /* this is the first packet back from the guy */ flow_callbacks(FLOW_FIRST_BIDIRECTIONAL, fp, direction, p); } flow_callbacks(FLOW_ADDITIONAL, fp, direction, pkt); } else { /* ** If there's no flow for a rebuilt stream, then we don't ** care because something is screwed up. */ if(p->packet_flags & PKT_REBUILT_STREAM) { PREPROC_PROFILE_END(flowPerfStats); return; } if(flowcache_newflow(fcache, &search_key, &fp) != FLOW_SUCCESS) { flow_printf("***ERROR: "); flowkey_print(&search_key); flow_printf("\n"); } direction = FROM_INITIATOR; flow_callbacks(FLOW_NEW, fp, FROM_INITIATOR, pkt); } fp->stats.direction = direction; /* printout some verbose statistics */ if(s_config.stats_interval && ((last_output + s_config.stats_interval) <= p->pkth->ts.tv_sec)) { last_output = p->pkth->ts.tv_sec; if(!pv.quiet_flag) flowcache_stats(stdout, fcache); } p->flow = fp; PREPROC_PROFILE_END(flowPerfStats); }
/* Main runtime entry point for GTP preprocessor. * Analyzes GTP packets for anomalies/exploits. * * PARAMETERS: * * packetp: Pointer to current packet to process. * contextp: Pointer to context block, not used. * * RETURNS: Nothing. */ static void GTPmain( void* ipacketp, void* contextp ) { GTPData* sessp = NULL; uint8_t source = 0; uint8_t dest = 0; SFSnortPacket* packetp; #ifdef TARGET_BASED int16_t app_id = SFTARGET_UNKNOWN_PROTOCOL; #endif tSfPolicyId policy_id = _dpd.getRuntimePolicy(); PROFILE_VARS; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__START_MSG)); packetp = (SFSnortPacket*) ipacketp; sfPolicyUserPolicySet (gtp_config, policy_id); /* Make sure this preprocessor should run. */ if (( !packetp ) || ( !packetp->payload ) ||( !packetp->payload_size )) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "No payload - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); return; } else if (!IsUDP(packetp)) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Not UDP - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); return; } PREPROC_PROFILE_START(gtpPerfStats); gtp_eval_config = sfPolicyUserDataGetCurrent(gtp_config); /* Attempt to get a previously allocated GTP block. */ sessp = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_GTP); if (sessp != NULL) { gtp_eval_config = sfPolicyUserDataGet(sessp->config, sessp->policy_id); } if (sessp == NULL) { /* If not doing autodetection, check the ports to make sure this is * running on an GTP port, otherwise no need to examine the traffic. */ #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(packetp->stream_session_ptr); if (app_id == SFTARGET_UNKNOWN_PROTOCOL) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Unknown protocol - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); PREPROC_PROFILE_END(gtpPerfStats); return; } else if (app_id && (app_id != gtp_app_id)) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Not GTP - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); PREPROC_PROFILE_END(gtpPerfStats); return; } else if (!app_id) { #endif source = (uint8_t)CheckGTPPort( packetp->src_port ); dest = (uint8_t)CheckGTPPort( packetp->dst_port ); if ( !source && !dest ) { /* Not one of the ports we care about. */ DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Not GTP ports - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); PREPROC_PROFILE_END(gtpPerfStats); return; } #ifdef TARGET_BASED } #endif /* Check the stream session. If it does not currently * have our GTP data-block attached, create one. */ sessp = GTPGetNewSession(packetp, policy_id); if ( !sessp ) { /* Could not get/create the session data for this packet. */ DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Create session error - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); PREPROC_PROFILE_END(gtpPerfStats); return; } } /* We're interested in this session. Turn on stream reassembly. */ if ( !(sessp->state_flags & GTP_FLG_REASSEMBLY_SET )) { _dpd.streamAPI->set_reassembly(packetp->stream_session_ptr, STREAM_FLPOLICY_FOOTPRINT, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE); sessp->state_flags |= GTP_FLG_REASSEMBLY_SET; } /* * Start process PAYLOAD */ GTP_Process(packetp,sessp); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "%s\n", GTP_DEBUG__END_MSG)); PREPROC_PROFILE_END(gtpPerfStats); }
/* Main runtime entry point for SSH preprocessor. * Analyzes SSH packets for anomalies/exploits. * * PARAMETERS: * * packetp: Pointer to current packet to process. * contextp: Pointer to context block, not used. * * RETURNS: Nothing. */ static void ProcessSSH( void* ipacketp, void* contextp ) { SSHData* sessp = NULL; u_int8_t source = 0; u_int8_t dest = 0; u_int8_t known_port = 0; u_int8_t direction; SFSnortPacket* packetp; PROFILE_VARS; packetp = (SFSnortPacket*) ipacketp; /* Make sure this preprocessor should run. */ if (( !packetp ) || ( !packetp->payload ) || ( !packetp->payload_size ) || ( !packetp->ip4_header ) || ( !packetp->tcp_header ) || /* check if we're waiting on stream reassembly */ ( packetp->flags & FLAG_STREAM_INSERT)) { return; } /* If we picked up mid-stream do not process further */ if ( _dpd.streamAPI->get_session_flags( packetp->stream_session_ptr) & SSNFLAG_MIDSTREAM ) { return; } /* If not doing autodetection, check the ports to make sure this is * running on an SSH port, otherwise no need to examine the traffic. */ source = CheckSSHPort( packetp->src_port ); dest = CheckSSHPort( packetp->dst_port ); if ( !ssh_config.AutodetectEnabled && !source && !dest ) { /* Not one of the ports we care about. */ return; } PREPROC_PROFILE_START(sshPerfStats); /* See if a known server port is involved. */ known_port = ( source || dest ? 1 : 0 ); /* Get the direction of the packet. */ direction = ( (packetp->flags & FLAG_FROM_SERVER ) ? SSH_DIR_FROM_SERVER : SSH_DIR_FROM_CLIENT ); /* Check the stream session. If it does not currently * have our SSH data-block attached, create one. */ sessp = GetSSHData( packetp ); if ( !sessp ) { /* Could not get/create the session data for this packet. */ PREPROC_PROFILE_END(sshPerfStats); return; } if ( !(sessp->state_flags & SSH_FLG_SESS_ENCRYPTED )) { /* If server and client have not performed the protocol * version exchange yet, must look for version strings. */ if ( (sessp->state_flags & SSH_FLG_BOTH_IDSTRING_SEEN) != SSH_FLG_BOTH_IDSTRING_SEEN ) { if ( ProcessSSHProtocolVersionExchange( sessp, packetp, direction, known_port ) == SSH_FAILURE ) { /*Error processing protovers exchange msg */ } PREPROC_PROFILE_END(sshPerfStats); return; } /* Expecting to see the key init exchange at this point * (in SSH2) or the actual key exchange if SSH1 */ if ((( sessp->state_flags & SSH_FLG_V1_KEYEXCH_DONE ) != SSH_FLG_V1_KEYEXCH_DONE ) && ((sessp->state_flags & SSH_FLG_V2_KEXINIT_DONE ) != SSH_FLG_V2_KEXINIT_DONE )) { ProcessSSHKeyInitExchange( sessp, packetp, direction ); PREPROC_PROFILE_END(sshPerfStats); return; } /* If SSH2, need to process the actual key exchange msgs. * The actual key exchange type was negotiated in the * key exchange init msgs. SSH1 won't arrive here. */ ProcessSSHKeyExchange( sessp, packetp, direction ); } else { /* Traffic on this session is currently encrypted. * Two of the major SSH exploits, SSH1 CRC-32 and * the GOBBLES attack occur within the encrypted * portion of the SSH session. Therefore, the only * way to detect these attacks is by examining * amounts of data exchanged for anomalies. */ sessp->num_enc_pkts++; if ( sessp->num_enc_pkts <= ssh_config.MaxEncryptedPackets ) { if ( direction == SSH_DIR_FROM_CLIENT ) { sessp->num_client_bytes += packetp->payload_size; if ( sessp->num_client_bytes >= ssh_config.MaxClientBytes ) { /* Probable exploit in progress.*/ if (sessp->version == SSH_VERSION_1) { if ( ssh_config.EnabledAlerts & SSH_ALERT_CRC32 ) { ALERT(SSH_EVENT_CRC32, SSH_EVENT_CRC32_STR); _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } else { if ( ssh_config.EnabledAlerts & SSH_ALERT_GOBBLES ) { ALERT(SSH_EVENT_GOBBLES, SSH_EVENT_GOBBLES_STR); _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } } } else { /* * Have seen a server response, so * this appears to be a valid exchange. * Reset suspicious byte count to zero. */ sessp->num_client_bytes = 0; } } else { /* Have already examined more than the limit * of encrypted packets. Both the Gobbles and * the CRC32 attacks occur during authentication * and therefore cannot be used late in an * encrypted session. For performance purposes, * stop examining this session. */ _dpd.streamAPI->stop_inspection( packetp->stream_session_ptr, packetp, SSN_DIR_BOTH, -1, 0 ); } } PREPROC_PROFILE_END(sshPerfStats); }
/******************************************************************** * Function: DCE2_ClFragReassemble() * * Reassembles fragments into reassembly buffer and copies to * reassembly packet. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClActTracker * * Pointer to the connectionless activity tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * * Returns: None * ********************************************************************/ static void DCE2_ClFragReassemble(DCE2_SsnData *sd, DCE2_ClActTracker *at, const DceRpcClHdr *cl_hdr) { DCE2_ClFragTracker *ft = &at->frag_tracker; DCE2_ClFragNode *fnode; uint8_t *rdata = dce2_cl_rbuf; uint16_t rlen = sizeof(dce2_cl_rbuf); uint32_t stub_len = 0; const uint8_t *stub_data = NULL; SFSnortPacket *rpkt = NULL; PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_cl_reass); for (fnode = (DCE2_ClFragNode *)DCE2_ListFirst(ft->frags); fnode != NULL; fnode = (DCE2_ClFragNode *)DCE2_ListNext(ft->frags)) { if (fnode->frag_len > rlen) { DCE2_Log(DCE2_LOG_TYPE__WARN, "%s(%d) Size of fragments exceeds reassembly buffer size. " "Using as many fragments as will fit.", __FILE__, __LINE__); break; } if (DCE2_Memcpy(rdata, fnode->frag_data, fnode->frag_len, rdata, rdata + rlen) != DCE2_RET__SUCCESS) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Failed to copy data into fragment " "reassembly buffer.", __FILE__, __LINE__); break; } DCE2_MOVE(rdata, rlen, fnode->frag_len); stub_len += fnode->frag_len; } switch (sd->trans) { case DCE2_TRANS_TYPE__UDP: rpkt = DCE2_GetRpkt(sd->wire_pkt, DCE2_RPKT_TYPE__UDP_CL_FRAG, dce2_cl_rbuf, stub_len); if (rpkt == NULL) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Failed to create reassembly packet.", __FILE__, __LINE__); PREPROC_PROFILE_END(dce2_pstat_cl_reass); return; } DCE2_ClSetRdata(at, cl_hdr, (uint8_t *)rpkt->payload, (uint16_t)(rpkt->payload_size - DCE2_MOCK_HDR_LEN__CL)); stub_data = rpkt->payload + DCE2_MOCK_HDR_LEN__CL; break; default: DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid transport type: %d", __FILE__, __LINE__, sd->trans); return; } PREPROC_PROFILE_END(dce2_pstat_cl_reass); if (DCE2_PushPkt(rpkt) != DCE2_RET__SUCCESS) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Failed to push packet onto packet stack.", __FILE__, __LINE__); return; } /* Cache relevant values for rule option processing */ sd->ropts.first_frag = 1; DCE2_CopyUuid(&sd->ropts.iface, &ft->iface, DCERPC_BO_FLAG__NONE); sd->ropts.iface_vers = ft->iface_vers; sd->ropts.hdr_byte_order = DceRpcClByteOrder(cl_hdr); if (ft->data_byte_order != DCE2_SENTINEL) sd->ropts.data_byte_order = ft->data_byte_order; else sd->ropts.data_byte_order = DceRpcClByteOrder(cl_hdr); if (ft->opnum != DCE2_SENTINEL) sd->ropts.opnum = ft->opnum; else sd->ropts.opnum = DceRpcClOpnum(cl_hdr); sd->ropts.stub_data = stub_data; DCE2_Detect(sd); DCE2_PopPkt(); dce2_stats.cl_frag_reassembled++; }
/******************************************************************** * Function: DCE2_ClProcess() * * Main entry point for connectionless DCE/RPC processing. Gets * the activity tracker associated with this session and passes * along to client or server handling. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClTracker * * Pointer to the connectionless tracker structure. * * Returns: None * ********************************************************************/ void DCE2_ClProcess(DCE2_SsnData *sd, DCE2_ClTracker *clt) { DceRpcClHdr *cl_hdr; DCE2_ClActTracker *at; const uint8_t *data_ptr = sd->wire_pkt->payload; uint16_t data_len = sd->wire_pkt->payload_size; PROFILE_VARS; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Cl processing ...\n")); dce2_stats.cl_pkts++; if (data_len < sizeof(DceRpcClHdr)) { if (!DCE2_SsnAutodetected(sd)) DCE2_Alert(sd, DCE2_EVENT__CL_DATA_LT_HDR, data_len, sizeof(DceRpcClHdr)); return; } cl_hdr = (DceRpcClHdr *)data_ptr; DCE2_MOVE(data_ptr, data_len, sizeof(DceRpcClHdr)); if (DCE2_ClHdrChecks(sd, cl_hdr) != DCE2_RET__SUCCESS) return; PREPROC_PROFILE_START(dce2_pstat_cl_acts); at = DCE2_ClGetActTracker(clt, cl_hdr); PREPROC_PROFILE_END(dce2_pstat_cl_acts); if (at == NULL) return; if (DCE2_SsnFromClient(sd->wire_pkt)) { switch (DceRpcClPduType(cl_hdr)) { case DCERPC_PDU_TYPE__REQUEST: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Request\n")); dce2_stats.cl_request++; DCE2_ClRequest(sd, at, cl_hdr, data_ptr, data_len); break; case DCERPC_PDU_TYPE__ACK: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Ack\n")); dce2_stats.cl_ack++; break; case DCERPC_PDU_TYPE__CL_CANCEL: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Cancel\n")); dce2_stats.cl_cancel++; break; case DCERPC_PDU_TYPE__FACK: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Fack\n")); dce2_stats.cl_cli_fack++; break; case DCERPC_PDU_TYPE__PING: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Ping\n")); dce2_stats.cl_ping++; break; case DCERPC_PDU_TYPE__RESPONSE: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Response from client. Changing stream direction.")); _dpd.streamAPI->update_direction(sd->wire_pkt->stream_session, SSN_DIR_FROM_RESPONDER, GET_SRC_IP(((SFSnortPacket *)sd->wire_pkt)), sd->wire_pkt->src_port); break; default: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Other pdu type\n")); dce2_stats.cl_other_req++; break; } } else { switch (DceRpcClPduType(cl_hdr)) { case DCERPC_PDU_TYPE__RESPONSE: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Response\n")); dce2_stats.cl_response++; break; case DCERPC_PDU_TYPE__REJECT: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Reject\n")); dce2_stats.cl_reject++; if (DceRpcClSeqNum(cl_hdr) == at->seq_num) { DCE2_ClResetFragTracker(&at->frag_tracker); at->seq_num_invalid = 1; } break; case DCERPC_PDU_TYPE__CANCEL_ACK: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Cancel Ack\n")); dce2_stats.cl_cancel_ack++; break; case DCERPC_PDU_TYPE__FACK: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Fack\n")); dce2_stats.cl_srv_fack++; break; case DCERPC_PDU_TYPE__FAULT: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Fault\n")); dce2_stats.cl_fault++; break; case DCERPC_PDU_TYPE__NOCALL: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "No call\n")); dce2_stats.cl_nocall++; break; case DCERPC_PDU_TYPE__WORKING: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Working\n")); dce2_stats.cl_working++; break; default: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Other pdu type\n")); dce2_stats.cl_other_resp++; break; } } }
/* Main runtime entry point */ static void ProcessModbus(void *ipacketp, void *contextp) { SFSnortPacket *packetp = (SFSnortPacket *)ipacketp; modbus_session_data_t *sessp; PROFILE_VARS; /* Sanity checks. Should this preprocessor run? */ if (( !packetp ) || ( !packetp->payload ) || ( !packetp->payload_size ) || ( !IPH_IS_VALID(packetp) ) || ( !packetp->tcp_header )) { return; } PREPROC_PROFILE_START(modbusPerfStats); /* Fetch me a preprocessor config to use with this VLAN/subnet/etc.! */ modbus_eval_config = sfPolicyUserDataGetCurrent(modbus_context_id); /* Look for a previously-allocated session data. */ sessp = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_MODBUS); if (sessp == NULL) { /* No existing session. Check those ports. */ if (ModbusPortCheck(modbus_eval_config, packetp) != MODBUS_OK) { PREPROC_PROFILE_END(modbusPerfStats); return; } } if ( !PacketHasFullPDU(packetp) ) { /* If a packet is rebuilt, but not a full PDU, then it's garbage that got flushed at the end of a stream. */ if ( packetp->flags & (FLAG_REBUILT_STREAM|FLAG_PDU_HEAD) ) { _dpd.alertAdd(GENERATOR_SPP_MODBUS, MODBUS_BAD_LENGTH, 1, 0, 3, MODBUS_BAD_LENGTH_STR, 0); } PREPROC_PROFILE_END(modbusPerfStats); return; } if (sessp == NULL) { /* Create session data and attach it to the Stream5 session */ sessp = ModbusCreateSessionData(packetp); if ( !sessp ) { PREPROC_PROFILE_END(modbusPerfStats); return; } } /* When pipelined Modbus PDUs appear in a single TCP segment, the detection engine caches the results of the rule options after evaluating on the first PDU. Setting this flag stops the caching. */ packetp->flags |= FLAG_ALLOW_MULTIPLE_DETECT; /* Do preprocessor-specific detection stuff here */ ModbusDecode(modbus_eval_config, packetp); /* That's the end! */ PREPROC_PROFILE_END(modbusPerfStats); }
/* Main runtime entry point */ static void ProcessDNP3(void *ipacketp, void *contextp) { SFSnortPacket *packetp = (SFSnortPacket *)ipacketp; MemBucket *tmp_bucket = NULL; dnp3_session_data_t *sessp = NULL; PROFILE_VARS; /* Sanity checks. Should this preprocessor run? */ if (( !packetp ) || ( !packetp->payload ) || ( !packetp->payload_size ) || ( !IPH_IS_VALID(packetp) ) || ( !packetp->tcp_header && !packetp->udp_header )) { return; } /* If TCP, require that PAF flushes full PDUs first. */ if (packetp->tcp_header && !PacketHasFullPDU(packetp)) return; PREPROC_PROFILE_START(dnp3PerfStats); /* When pipelined DNP3 PDUs appear in a single TCP segment or UDP packet, the detection engine caches the results of the rule options after evaluating on the first PDU. Setting this flag stops the caching. */ packetp->flags |= FLAG_ALLOW_MULTIPLE_DETECT; /* Fetch me a preprocessor config to use with this VLAN/subnet/etc.! */ dnp3_eval_config = sfPolicyUserDataGetCurrent(dnp3_context_id); /* Look for a previously-allocated session data. */ tmp_bucket = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_DNP3); if (tmp_bucket == NULL) { /* No existing session. Check those ports. */ if (DNP3PortCheck(dnp3_eval_config, packetp) != DNP3_OK) { PREPROC_PROFILE_END(dnp3PerfStats); return; } /* Create session data and attach it to the Stream5 session */ tmp_bucket = DNP3CreateSessionData(packetp); if (tmp_bucket == NULL) { /* Mempool was full, don't process this session. */ static unsigned int times_mempool_alloc_failed = 0; /* Print a message, but only every 1000 times. Don't want to flood the log if there's a lot of DNP3 traffic. */ if (times_mempool_alloc_failed % 1000) { _dpd.logMsg("WARNING: DNP3 memcap exceeded.\n"); } times_mempool_alloc_failed++; PREPROC_PROFILE_END(dnp3PerfStats); return; } } sessp = (dnp3_session_data_t *) tmp_bucket->data; /* Set reassembly direction */ if (packetp->flags & FLAG_FROM_CLIENT) sessp->direction = DNP3_CLIENT; else sessp->direction = DNP3_SERVER; /* Do preprocessor-specific detection stuff here */ if (packetp->tcp_header) { /* Single PDU. PAF already split them up into separate pseudo-packets. */ DNP3FullReassembly(dnp3_eval_config, sessp, packetp, (uint8_t *)packetp->payload, packetp->payload_size); } else if (packetp->udp_header) { DNP3ProcessUDP(dnp3_eval_config, sessp, packetp); } /* That's the end! */ PREPROC_PROFILE_END(dnp3PerfStats); }
/******************************************************************** * Function: DCE2_ClHandleFrag() * * Handles connectionless fragments. Creates a new fragment list * if necessary and inserts fragment into list. Sets rule option * values based on the fragment. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClActTracker * * Pointer to the connectionless activity tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * const uint8_t * * Pointer to current position in the packet payload. * uint16_t * Length of packet payload left from current pointer * position. * * Returns: None * ********************************************************************/ static void DCE2_ClHandleFrag(DCE2_SsnData *sd, DCE2_ClActTracker *at, DceRpcClHdr *cl_hdr, const uint8_t *data_ptr, uint16_t data_len) { DCE2_ClFragTracker *ft = &at->frag_tracker; DCE2_ClFragNode *fn; uint16_t frag_len; int status; PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_cl_frag); /* If the frag length is less than data length there might be authentication * data that we don't want to include, otherwise just set to data len */ if (DceRpcClLen(cl_hdr) < data_len) frag_len = DceRpcClLen(cl_hdr); else frag_len = data_len; if (frag_len == 0) { PREPROC_PROFILE_END(dce2_pstat_cl_frag); return; } if (frag_len > dce2_stats.cl_max_frag_size) dce2_stats.cl_max_frag_size = frag_len; if (DCE2_GcMaxFrag() && (frag_len > DCE2_GcMaxFragLen())) frag_len = DCE2_GcMaxFragLen(); if (ft->frags == NULL) { /* Create new list if we don't have one already */ ft->frags = DCE2_ListNew(DCE2_LIST_TYPE__SORTED, DCE2_ClFragCompare, DCE2_ClFragDataFree, NULL, DCE2_LIST_FLAG__NO_DUPS | DCE2_LIST_FLAG__INS_TAIL, DCE2_MEM_TYPE__CL_FRAG); if (ft->frags == NULL) { PREPROC_PROFILE_END(dce2_pstat_cl_frag); return; } } else { /* If we already have a fragment in the list with the same fragment number, * that fragment will take precedence over this fragment and this fragment * will not be used by the server */ fn = (DCE2_ClFragNode *)DCE2_ListFind(ft->frags, (void *)(uintptr_t)DceRpcClFragNum(cl_hdr)); if (fn != NULL) { PREPROC_PROFILE_END(dce2_pstat_cl_frag); return; } } /* Create a new frag node to insert into the list */ fn = (DCE2_ClFragNode *)DCE2_Alloc(sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); if (fn == NULL) { PREPROC_PROFILE_END(dce2_pstat_cl_frag); DCE2_ClFragReassemble(sd, at, cl_hdr); return; } fn->frag_number = DceRpcClFragNum(cl_hdr); fn->frag_len = frag_len; /* Allocate space for the fragment data */ fn->frag_data = (uint8_t *)DCE2_Alloc(frag_len, DCE2_MEM_TYPE__CL_FRAG); if (fn->frag_data == NULL) { DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); PREPROC_PROFILE_END(dce2_pstat_cl_frag); DCE2_ClFragReassemble(sd, at, cl_hdr); return; } /* Copy the fragment data in the packet to the space just allocated */ status = DCE2_Memcpy(fn->frag_data, data_ptr, frag_len, fn->frag_data, fn->frag_data + frag_len); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)fn->frag_data, frag_len, DCE2_MEM_TYPE__CL_FRAG); DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); PREPROC_PROFILE_END(dce2_pstat_cl_frag); DCE2_ClFragReassemble(sd, at, cl_hdr); return; } if (DCE2_ListIsEmpty(ft->frags)) { /* If this is the first fragment we've received, set interface uuid */ DCE2_CopyUuid(&ft->iface, DceRpcClIface(cl_hdr), DceRpcClByteOrder(cl_hdr)); ft->iface_vers = DceRpcClIfaceVers(cl_hdr); } if (DceRpcClLastFrag(cl_hdr)) { /* Set number of expected frags on last frag */ ft->num_expected_frags = DceRpcClFragNum(cl_hdr) + 1; } else if (DceRpcClFirstFrag(cl_hdr)) { /* Set opum and byte order on first frag */ ft->opnum = DceRpcClOpnum(cl_hdr); ft->data_byte_order = DceRpcClByteOrder(cl_hdr); } /* Insert frag node into the list */ status = DCE2_ListInsert(ft->frags, (void *)(uintptr_t)fn->frag_number, (void *)fn); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)fn->frag_data, frag_len, DCE2_MEM_TYPE__CL_FRAG); DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); PREPROC_PROFILE_END(dce2_pstat_cl_frag); DCE2_ClFragReassemble(sd, at, cl_hdr); return; } /* Fragment number field in header is uint16_t */ if ((ft->num_expected_frags != DCE2_SENTINEL) && (uint16_t)ft->frags->num_nodes == (uint16_t)ft->num_expected_frags) { PREPROC_PROFILE_END(dce2_pstat_cl_frag); /* We got all of the frags - reassemble */ DCE2_ClFragReassemble(sd, at, cl_hdr); at->seq_num_invalid = 1; return; } PREPROC_PROFILE_END(dce2_pstat_cl_frag); /* Cache relevant values for rule option processing */ sd->ropts.first_frag = DceRpcClFirstFrag(cl_hdr); DCE2_CopyUuid(&sd->ropts.iface, &ft->iface, DCERPC_BO_FLAG__NONE); sd->ropts.iface_vers = ft->iface_vers; sd->ropts.hdr_byte_order = DceRpcClByteOrder(cl_hdr); if (ft->data_byte_order != DCE2_SENTINEL) sd->ropts.data_byte_order = ft->data_byte_order; else sd->ropts.data_byte_order = DceRpcClByteOrder(cl_hdr); if (ft->opnum != DCE2_SENTINEL) sd->ropts.opnum = ft->opnum; else sd->ropts.opnum = DceRpcClOpnum(cl_hdr); sd->ropts.stub_data = (uint8_t *)cl_hdr + sizeof(DceRpcClHdr); DCE2_Detect(sd); }
/********************************************************************* * Function: DCE2_Process() * * Purpose: Main entry point for DCE/RPC processing. * * Arguments: * SFSnortPacket * - pointer to packet structure * * Returns: * DCE2_Ret - status * *********************************************************************/ DCE2_Ret DCE2_Process(SFSnortPacket *p) { tSfPolicyId policy_id = _dpd.getNapRuntimePolicy(); DCE2_SsnData *sd = (DCE2_SsnData *)DCE2_SsnGetAppData(p); PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_session); if ((sd != NULL) && DCE2_SsnNoInspect(sd)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Session set to " "not inspect. Returning\n")); PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } dce2_eval_config = (DCE2_Config *)sfPolicyUserDataGet(dce2_config, policy_id); if (sd != NULL) dce2_eval_config = (DCE2_Config *)sfPolicyUserDataGet(sd->config, sd->policy_id); if (dce2_eval_config == NULL) { PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } if (sd == NULL) { sd = DCE2_NewSession(p, policy_id); if (sd == NULL) { PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } } else { sd->wire_pkt = p; if (_dpd.isPafEnabled() && !DCE2_SsnIsPafActive(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "PAF was aborted on " "one or both sides - aborting session inspection\n")); DCE2_SetNoInspect(sd); PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } if (IsTCP(p) && !DCE2_SsnIsRebuilt(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-rebuilt packet " "on session (%p)\n", (void *)sd)); if (DCE2_SsnIsStreamInsert(p)) { if (!_dpd.isPafEnabled()) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Flushing opposite direction.\n")); DCE2_SsnFlush(p); } DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Stream inserted - not inspecting.\n")); } else { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-stream inserted packet " "- not inspecting\n")); } PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } else if (DCE2_SsnAutodetected(sd) && !(p->flags & sd->autodetect_dir)) { /* Try to autodetect in opposite direction */ if ((sd->trans != DCE2_TRANS_TYPE__HTTP_PROXY) && (sd->trans != DCE2_TRANS_TYPE__HTTP_SERVER) && (DCE2_GetAutodetectTransport(p, sd->sconfig) != sd->trans)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Bad autodetect.\n")); DCE2_SetNoInspect(sd); dce2_stats.bad_autodetects++; PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } DCE2_SsnClearAutodetected(sd); } } DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Session pointer: %p\n", (void *)sd)); if (IsTCP(p) && (DCE2_SetSsnState(sd, p) != DCE2_RET__SUCCESS)) { PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } if (DCE2_PushPkt((void *)p) != DCE2_RET__SUCCESS) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Failed to push packet onto packet stack.", __FILE__, __LINE__); PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } p->flags |= FLAG_ALLOW_MULTIPLE_DETECT; dce2_detected = 0; PREPROC_PROFILE_END(dce2_pstat_session); switch (sd->trans) { case DCE2_TRANS_TYPE__SMB: DCE2_SmbProcess((DCE2_SmbSsnData *)sd); break; case DCE2_TRANS_TYPE__TCP: DCE2_TcpProcess((DCE2_TcpSsnData *)sd); break; case DCE2_TRANS_TYPE__UDP: DCE2_UdpProcess((DCE2_UdpSsnData *)sd); break; case DCE2_TRANS_TYPE__HTTP_PROXY: DCE2_HttpProcessProxy((DCE2_HttpSsnData *)sd); break; case DCE2_TRANS_TYPE__HTTP_SERVER: DCE2_HttpProcessServer((DCE2_HttpSsnData *)sd); break; default: DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid transport type: %d", __FILE__, __LINE__, sd->trans); return DCE2_RET__NOT_INSPECTED; } if (sd->flags & DCE2_SSN_FLAG__NO_INSPECT) { DCE2_SetNoInspect(sd); DCE2_PopPkt(); PREPROC_PROFILE_END(dce2_pstat_session); return DCE2_RET__NOT_INSPECTED; } if (!dce2_detected) DCE2_Detect(sd); DCE2_ResetRopts(&sd->ropts); DCE2_PopPkt(); if (dce2_mem_state == DCE2_MEM_STATE__MEMCAP) { DCE2_SetNoInspect(sd); dce2_mem_state = DCE2_MEM_STATE__OKAY; return DCE2_RET__NOT_INSPECTED; } if (DCE2_SsnAutodetected(sd)) return DCE2_RET__NOT_INSPECTED; return DCE2_RET__INSPECTED; }
/* Main runtime entry point for SIP preprocessor. * Analyzes SIP packets for anomalies/exploits. * * PARAMETERS: * * packetp: Pointer to current packet to process. * contextp: Pointer to context block, not used. * * RETURNS: Nothing. */ static void SIPmain( void* ipacketp, void* contextp ) { SIPData* sessp = NULL; uint8_t source = 0; uint8_t dest = 0; SFSnortPacket* packetp; #ifdef TARGET_BASED int16_t app_id = SFTARGET_UNKNOWN_PROTOCOL; #endif tSfPolicyId policy_id = _dpd.getRuntimePolicy(); PROFILE_VARS; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__START_MSG)); packetp = (SFSnortPacket*) ipacketp; sfPolicyUserPolicySet (sip_config, policy_id); /* Make sure this preprocessor should run. */ if (( !packetp ) || ( !packetp->payload ) ||( !packetp->payload_size )) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No payload - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); return; } /* check if we're waiting on stream reassembly */ else if ( packetp->flags & FLAG_STREAM_INSERT) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Stream inserted - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); return; } else if (!IsTCP(packetp) && !IsUDP(packetp)) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Not UDP or TCP - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); return; } PREPROC_PROFILE_START(sipPerfStats); sip_eval_config = sfPolicyUserDataGetCurrent(sip_config); /* Attempt to get a previously allocated SIP block. */ sessp = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_SIP); if (sessp != NULL) { sip_eval_config = sfPolicyUserDataGet(sessp->config, sessp->policy_id); } if (sessp == NULL) { /* If not doing autodetection, check the ports to make sure this is * running on an SIP port, otherwise no need to examine the traffic. */ #ifdef TARGET_BASED app_id = _dpd.streamAPI->get_application_protocol_id(packetp->stream_session_ptr); if (app_id == SFTARGET_UNKNOWN_PROTOCOL) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Unknown protocol - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } else if (app_id && (app_id != sip_app_id)) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Not SIP - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } else if (!app_id) { #endif source = (uint8_t)CheckSIPPort( packetp->src_port ); dest = (uint8_t)CheckSIPPort( packetp->dst_port ); if ( !source && !dest ) { /* Not one of the ports we care about. */ DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Not SIP ports - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } #ifdef TARGET_BASED } #endif /* Check the stream session. If it does not currently * have our SIP data-block attached, create one. */ sessp = SIPGetNewSession(packetp, policy_id); if ( !sessp ) { /* Could not get/create the session data for this packet. */ DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Create session error - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } } /* Don't process if we've missed packets */ if (sessp->state_flags & SIP_FLG_MISSED_PACKETS) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Missed packets - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } /* If we picked up mid-stream or missed any packets (midstream pick up * means we've already missed packets) set missed packets flag and make * sure we don't do any more reassembly on this session */ if (IsTCP(packetp)) { if ((_dpd.streamAPI->get_session_flags(packetp->stream_session_ptr) & SSNFLAG_MIDSTREAM) || _dpd.streamAPI->missed_packets(packetp->stream_session_ptr, SSN_DIR_BOTH)) { _dpd.streamAPI->set_reassembly(packetp->stream_session_ptr, STREAM_FLPOLICY_IGNORE, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE); sessp->state_flags |= SIP_FLG_MISSED_PACKETS; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Missed packets - not inspecting.\n")); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); return; } } /* We're interested in this session. Turn on stream reassembly. */ if ( !(sessp->state_flags & SIP_FLG_REASSEMBLY_SET )) { _dpd.streamAPI->set_reassembly(packetp->stream_session_ptr, STREAM_FLPOLICY_FOOTPRINT, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE); sessp->state_flags |= SIP_FLG_REASSEMBLY_SET; } /* * Start process PAYLOAD */ SIP_Process(packetp,sessp); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "%s\n", SIP_DEBUG__END_MSG)); PREPROC_PROFILE_END(sipPerfStats); }
/******************************************************************** * Function: DCE2_SetSsnState() * * Purpose: * Checks for missing packets and overlapping data on session * * Arguments: * DCE2_SsnData * - session data pointer * SFSnortPacket * - packet structure * * Returns: * DCE2_RET__SUCCESS * DCE2_RET__ERROR * ********************************************************************/ static DCE2_Ret DCE2_SetSsnState(DCE2_SsnData *sd, SFSnortPacket *p) { uint32_t pkt_seq = ntohl(p->tcp_header->sequence); PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_session_state); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Payload size: %u\n", p->payload_size)); if (DCE2_SsnFromClient(p) && !DCE2_SsnSeenClient(sd)) { uint32_t pkt_ack = ntohl(p->tcp_header->acknowledgement); if (DCE2_SsnSeenServer(sd) && SEQ_LT(sd->cli_seq, pkt_seq) && (sd->trans != DCE2_TRANS_TYPE__HTTP_SERVER)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Missing packets on session - aborting session inspection\n")); DCE2_SetNoInspect(sd); PREPROC_PROFILE_END(dce2_pstat_session_state); return DCE2_RET__ERROR; } DCE2_SsnSetSeenClient(sd); sd->cli_seq = pkt_seq; sd->cli_nseq = pkt_seq + p->payload_size; if (!DCE2_SsnSeenServer(sd)) sd->srv_seq = sd->srv_nseq = pkt_ack; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Initial client => seq: %u, " "next seq: %u\n", sd->cli_seq, sd->cli_nseq)); } else if (DCE2_SsnFromServer(p) && !DCE2_SsnSeenServer(sd)) { uint32_t pkt_ack = ntohl(p->tcp_header->acknowledgement); if ((DCE2_SsnSeenClient(sd) && SEQ_LT(sd->srv_seq, pkt_seq)) || (!DCE2_SsnSeenClient(sd) && (sd->trans != DCE2_TRANS_TYPE__HTTP_SERVER))) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Missing packets on session - aborting session inspection\n")); PREPROC_PROFILE_END(dce2_pstat_session_state); DCE2_SetNoInspect(sd); return DCE2_RET__ERROR; } DCE2_SsnSetSeenServer(sd); sd->srv_seq = pkt_seq; sd->srv_nseq = pkt_seq + p->payload_size; if (!DCE2_SsnSeenClient(sd)) sd->cli_seq = sd->cli_nseq = pkt_ack; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Initial server => seq: %u, " "next seq: %u\n", sd->srv_seq, sd->srv_nseq)); } else { uint32_t *ssn_seq; uint32_t *ssn_nseq; if (DCE2_SsnFromClient(p)) { ssn_seq = &sd->cli_seq; ssn_nseq = &sd->cli_nseq; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Client last => seq: %u, " "next seq: %u\n", sd->cli_seq, sd->cli_nseq)); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "This packet => seq: %u, " "next seq: %u\n", pkt_seq, pkt_seq + p->payload_size)); } else { ssn_seq = &sd->srv_seq; ssn_nseq = &sd->srv_nseq; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Server last => seq: %u, " "next seq: %u\n", sd->srv_seq, sd->srv_nseq)); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "This packet => seq: %u, " "next seq: %u\n", pkt_seq, pkt_seq + p->payload_size)); } if (*ssn_nseq != pkt_seq) { if (SEQ_LT(*ssn_nseq, pkt_seq)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Next expected sequence number (%u) is less than " "this sequence number (%u).\n", *ssn_nseq, pkt_seq)); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Missing packets on session - aborting session inspection\n")); DCE2_SetNoInspect(sd); PREPROC_PROFILE_END(dce2_pstat_session_state); return DCE2_RET__ERROR; } else { /* Got some kind of overlap. This shouldn't happen since we're doing * reassembly on both sides and not looking at non-reassembled packets * Actually this can happen if the stream seg list is empty */ DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Overlap => seq: %u, " "next seq: %u - aborting session inspection\n", pkt_seq, pkt_seq + p->payload_size)); DCE2_SetNoInspect(sd); PREPROC_PROFILE_END(dce2_pstat_session_state); return DCE2_RET__ERROR; } } *ssn_seq = pkt_seq; *ssn_nseq = pkt_seq + p->payload_size; } PREPROC_PROFILE_END(dce2_pstat_session_state); return DCE2_RET__SUCCESS; }
/********************************************************************* * Function: DCE2_Main() * * Purpose: Main entry point for DCE/RPC processing. * * Arguments: * void * - pointer to packet structure * void * - pointer to context * * Returns: None * *********************************************************************/ static void DCE2_Main(void *pkt, void *context) { SFSnortPacket *p = (SFSnortPacket *)pkt; PROFILE_VARS; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__START_MSG)); sfPolicyUserPolicySet (dce2_config, _dpd.getRuntimePolicy()); #ifdef DEBUG_MSGS if (DCE2_SsnFromServer(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Packet from Server.\n")); } else { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Packet from Client.\n")); } #endif /* No inspection to do */ if ((p->payload_size == 0) || (p->payload == NULL)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "No payload - not inspecting.\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); return; } else if (p->stream_session_ptr == NULL) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "No session pointer - not inspecting.\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); return; } else if (!IsTCP(p) && !IsUDP(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Not UDP or TCP - not inspecting.\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); return; } if (IsTCP(p)) { if (DCE2_SsnIsMidstream(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Midstream - not inspecting.\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); return; } else if (!DCE2_SsnIsEstablished(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Not established - not inspecting.\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); return; } } PREPROC_PROFILE_START(dce2_pstat_main); if (DCE2_Process(p) == DCE2_RET__INSPECTED) DCE2_DisableDetect(p); PREPROC_PROFILE_END(dce2_pstat_main); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "%s\n", DCE2_DEBUG__END_MSG)); }
/********************************************************************* * Function: * * Purpose: * * Arguments: * * Returns: * *********************************************************************/ static DCE2_SsnData * DCE2_NewSession(SFSnortPacket *p, tSfPolicyId policy_id) { DCE2_SsnData *sd = NULL; DCE2_TransType trans; const DCE2_ServerConfig *sc = DCE2_ScGetConfig(p); int autodetected = 0; PROFILE_VARS; PREPROC_PROFILE_START(dce2_pstat_new_session); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Creating new session: ")); trans = DCE2_GetTransport(p, sc, &autodetected); switch (trans) { case DCE2_TRANS_TYPE__SMB: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "SMB transport ... ")); sd = (DCE2_SsnData *)DCE2_SmbSsnInit(p); break; case DCE2_TRANS_TYPE__TCP: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "TCP transport ... ")); sd = (DCE2_SsnData *)DCE2_TcpSsnInit(); break; case DCE2_TRANS_TYPE__UDP: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "UDP transport ... ")); sd = (DCE2_SsnData *)DCE2_UdpSsnInit(); break; case DCE2_TRANS_TYPE__HTTP_PROXY: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "RPC over HTTP proxy transport ... ")); sd = (DCE2_SsnData *)DCE2_HttpProxySsnInit(); break; case DCE2_TRANS_TYPE__HTTP_SERVER: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "RPC over HTTP server transport ... ")); sd = (DCE2_SsnData *)DCE2_HttpServerSsnInit(); break; case DCE2_TRANS_TYPE__NONE: DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Not configured to " "look at this traffic or unable to autodetect - not inspecting.\n")); PREPROC_PROFILE_END(dce2_pstat_new_session); return NULL; default: DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid transport type: %d", __FILE__, __LINE__, trans); PREPROC_PROFILE_END(dce2_pstat_new_session); return NULL; } if (sd == NULL) { PREPROC_PROFILE_END(dce2_pstat_new_session); return NULL; } DCE2_SsnSetAppData(p, (void *)sd, DCE2_SsnFree); dce2_stats.sessions++; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Created (%p)\n", (void *)sd)); sd->trans = trans; sd->server_policy = DCE2_ScPolicy(sc); sd->client_policy = DCE2_POLICY__WINXP; // Default to Windows XP sd->sconfig = sc; sd->wire_pkt = p; sd->policy_id = policy_id; sd->config = dce2_config; ((DCE2_Config *)sfPolicyUserDataGet(sd->config, policy_id))->ref_count++; if (autodetected) { dce2_stats.sessions_autodetected++; #ifdef DEBUG if (DCE2_SsnFromServer(p)) dce2_stats.autoports[p->src_port][trans]++; else dce2_stats.autoports[p->dst_port][trans]++; #endif DCE2_SsnSetAutodetected(sd, p); } /* If we've determined a transport, make sure we're doing * reassembly on the session */ if (IsTCP(p)) { int rs_dir = DCE2_SsnGetReassembly(p); if (!_dpd.isPafEnabled() && (rs_dir != SSN_DIR_BOTH)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Setting client/server reassembly to FOOTPRINT for this session.\n")); DCE2_SsnSetReassembly(p); } if (!DCE2_SsnIsRebuilt(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-rebuilt packet\n")); if (DCE2_SsnIsStreamInsert(p)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Stream inserted - not inspecting.\n")); PREPROC_PROFILE_END(dce2_pstat_new_session); return NULL; } else if ((DCE2_SsnFromClient(p) && (rs_dir == SSN_DIR_FROM_SERVER)) || (DCE2_SsnFromServer(p) && (rs_dir == SSN_DIR_FROM_CLIENT)) || (rs_dir == SSN_DIR_BOTH)) { /* Reassembly was already set for this session, but stream * decided not to use the packet so it's probably not good */ DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-stream inserted packet - not inspecting\n")); PREPROC_PROFILE_END(dce2_pstat_new_session); return NULL; } } } PREPROC_PROFILE_END(dce2_pstat_new_session); return sd; }