Exemplo n.º 1
0
/**
 * The callback for the flow-portscan module
 *
 * This function's purpose is to do about the same thing as a
 * traditional snort preprocessor.  The only difference is that this
 * occurs only on a specific FLOW position.
 *
 * This individual callback position is only valid in the "NEW" flow
 * position.
 *
 * The operations are pretty much the same as laid out by
 *
 * Chris Green, Marc Norton, Dan Roelker
 *
 * Basic code flow:
 *
 * 1) Get the score and flag type
 * 2) return if the score is 0
 * 3) Get the score entry node
 * 4) Perform time window maintence 
 *    - includes flushing the "scan data" out of the subsys
 * 5) Process the score data
 * 6) Generate alerts if necessary
 *
 * @param position where in the flow module this is being called from
 * @param flow the flow that the stats are kept for
 * @param direction the direction of the flow
 * @param cur the current time
 * @param p the current packet (may be NULL)
 *
 * @return TBD
 */
int flowps_newflow_callback(FLOW_POSITION position, FLOW *flowp,
                            int direction, time_t cur, FLOWPACKET *p)
{
    TRACKER_POSITION tr_pos = TRACKER_ACTIVE; /* where new nodes get inserted */
    PS_TRACKER *pstp = &s_tracker;
    SCORE_ENTRY *current_entry = NULL;
    int ret, score;    
    u_int32_t alert_flags;
    u_int8_t cflags;
    u_int32_t *address = &flowp->key.init_address;

    if(!flowps_enabled())
        return 0;

    if(s_debug > 5)
    {
        printf("DEBUG: callback %s:%d -> %s:%d\n",
               inet_ntoax(p->iph->ip_src.s_addr), p->sp,
               inet_ntoax(p->iph->ip_dst.s_addr), p->dp);
    }

    if(position != FLOW_NEW)        
    {
#ifndef WIN32
        flow_printf("Wrong callback position for %s\n", __func__);
#else
        flow_printf("Wrong callback position for %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    if(flowps_is_ignored_ipv4(pstp,
                              &flowp->key.init_address,
                              &flowp->key.resp_address) == FLOW_SUCCESS)
    {
        return 0;
    }

    if(IsTcpPacket(p))
    {
        /* allow radically different flags from SYN help score
         * differently */
        cflags = GetTcpFlags(p);
    }
    else
    {
        cflags = 0;
    }

    /*
     * if we can't find the score for whatever reason, or the
     * resultant score is 0 (indicating that this a "normal" event),
     * just go ahead and return 
     */
    if(flowps_get_score(pstp, flowp, cur,
                        cflags, &score, &tr_pos) != FLOW_SUCCESS)
    {
        return -1;
    }

    if(score == 0)
    {
        return 0;
    }
    else if(s_debug > 5)
    {
        flow_printf("new unique flow!\n");
        flowkey_print(&flowp->key);
        flow_printf("\n");
    }
    
    /* run the "score entry finder" or create a new node */    
    ret = flowps_find_entry(pstp, address, &current_entry);

    if(ret == FLOW_NOTFOUND)
    {
        ret = flowps_add_entry(pstp,  tr_pos, address, &current_entry);

        if(ret != FLOW_SUCCESS)            
        {
            /* tracker failed horribly */
#ifndef WIN32
            flow_printf("flowps_add_entry check failed in %s\n", __func__);
#else
            flow_printf("flowps_add_entry check failed in %s(%d)\n", __FILE__, __LINE__);
#endif
            return 0;
        }
    }
    else if(ret != FLOW_SUCCESS)
    {
#ifndef WIN32
        flow_printf("bad return for finding the entry %s\n", __func__);
#else
        flow_printf("bad return for finding the entry %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    flowps_sliding_winadj(&current_entry->sliding_talker,
                          cur,
                          &pstp->config.limit_talker);

    flowps_fixed_winadj(&current_entry->fixed_talker,
                        cur,
                        &pstp->config.limit_talker);

    flowps_sliding_winadj(&current_entry->sliding_scanner,
                          cur,
                          &pstp->config.limit_scanner);

    flowps_fixed_winadj(&current_entry->fixed_scanner,
                        cur,
                        &pstp->config.limit_scanner);

    /* maintain the list of recent connections */
    flowps_set_last_address(current_entry, flowp, cflags);

    /* windows adjusted, lets get us some alerts */
    if(s_debug > 5 && score > 1)
    {
        flow_printf("XXXX **** got a big old score(%d) because of [%s] -> %s\n",
               score,  mktcpflag_str(cflags),
               inet_ntoa(*(struct in_addr *) (&flowp->key.resp_address)));
        flowps_entry_print(current_entry, address);
        flow_printf("\nXXXX ****\n");
    }

    if(flowps_score_entry(pstp, current_entry, score, tr_pos, 
                          pstp->config.alert_once,
                          &alert_flags) != FLOW_SUCCESS)
    {
#ifndef WIN32
        flow_printf("bad return for finding the entry %s\n", __func__);
#else
        flow_printf("bad return for finding the entry %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    /* If someone generates an event 
     * 
     *
     */
    if(current_entry->position == TRACKER_ACTIVE && tr_pos == TRACKER_SCANNER)
    {
        //flow_printf("moving this one! (cur %d) -> (new %d) %s\n",
        //current_entry->position, tr_pos, inet_ntoa(*(struct in_addr *) address));

        /* move address TO scanner FROM active */
        ret = scoreboard_move(&pstp->table_scanner, &pstp->table_active, address);
        
        if(ret != FLOW_SUCCESS)
        {
            flow_printf("Unable to move %s\n",inet_ntoa(*(struct in_addr *) address));
            return -1;
        }
        else
        {
            /* @todo - move this into the scoreboard mv call */
            current_entry->position = TRACKER_SCANNER;
        }
       
    }

    if(s_debug > 5)
    {
        if(tr_pos == TRACKER_SCANNER)
        {
            flow_printf("Found a tracker scanner!\n");
            flowps_entry_print(current_entry, address);
        }
    }
    
    if(s_debug > 10)
    {
        flowps_entry_print(current_entry, address);
    }
    
    if(alert_flags)        
    {
        /*
        **  We OR the alert_flags here because we only want to add
        **  new alerts and reset alerts that might not be set in
        **  alert_flags.  This is for the case of alert_once being
        **  set.
        */
        current_entry->flags |= alert_flags;
            
        /* push things through the output system */
        
        flowps_generate_flow_event(current_entry, p, address,
                                   pstp->config.output_mode, cur);
    }

    return 0;
}
int flowps_entry_print(SCORE_ENTRY *entry, u_int32_t *address)
{
    char *c_position = "TRACKER_ACTIVE";
    u_int32_t i;
    if(entry->position == TRACKER_SCANNER)
        c_position = "TRACKER_SCANNER";

    flow_printf(",-----------------------------------------------------\n");
    flow_printf("| Score entry for %s@%p Flags: %x\n",
            inet_ntoa(*(struct in_addr *) address), entry, entry->flags);


    flow_printf("|   Alerts: FT: %u ST: %u FS: %u SS: %u",
            (entry->flags & ALERT_FIXED_TALKER),
            (entry->flags & ALERT_SLIDING_TALKER),
            (entry->flags & ALERT_FIXED_SCANNER),
            (entry->flags & ALERT_SLIDING_SCANNER));
    
    flowps_score_print(&entry->fixed_talker);
    
    flow_printf("\n| Position: %s\n", c_position);
    flow_printf("|   Fixed Talker:");
    flowps_score_print(&entry->fixed_talker);
    
    flow_printf("\n| Sliding Talker:");
    flowps_score_print(&entry->sliding_talker);
    
    flow_printf("\n|   Fixed Scanner:");
    flowps_score_print(&entry->fixed_scanner);

    flow_printf("\n| Sliding Scanner:");
    flowps_score_print(&entry->sliding_scanner);

    flow_printf("\n| Connections Seen: %u", entry->connections_seen);

    /* as long as we have a postive # of connections, pump out the info */
    for(i=0; i < entry->connections_seen && i < FLOWPS_HOSTS_SIZE; i++)
    {
        CONN_ENTRY *cp = &entry->last_hosts[i];
        if(cp->protocol == 6)
        {
            flow_printf("\n|        proto: %d %s:%d th_flags: %s",
                        cp->protocol,
                        inet_ntoa(*(struct in_addr*) &cp->ip),
                        cp->port,
                        mktcpflag_str(cp->cflags));
        }
        else
        {
            flow_printf("\n|        proto: %d %s:%d cflags: %d",
                        cp->protocol,
                        inet_ntoa(*(struct in_addr*) &cp->ip),
                        cp->port,
                        cp->cflags);

        }
    }
    flow_printf("\n`----------------------------------------------------\n");

    return 0;
}