Beispiel #1
0
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);)
Beispiel #2
0
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;
   }

}
Beispiel #3
0
/*
 * 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
     */
}
Beispiel #4
0
/**
**  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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
   }

}
Beispiel #7
0
/*********************************************************************
 * 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;
}
Beispiel #8
0
/*********************************************************************
 * 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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
/* 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);
}
Beispiel #12
0
/* 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);

}
Beispiel #13
0
/* 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);
}
Beispiel #14
0
/* 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);
}
Beispiel #15
0
/********************************************************************
 * 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++;
}
Beispiel #16
0
/********************************************************************
 * 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;
        }
    }
}
Beispiel #17
0
/* 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);
}
Beispiel #18
0
/********************************************************************
 * 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);
}
Beispiel #19
0
/*********************************************************************
 * 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;
}
Beispiel #20
0
/* 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);

}
Beispiel #21
0
/********************************************************************
 * 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;
}
Beispiel #22
0
/*********************************************************************
 * 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));
}
Beispiel #23
0
/*********************************************************************
 * 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;
}