static int SIP_MethodAddFastPatterns(void *data, int protocol, int direction, FPContentInfo **info) { char *sip = "SIP"; FPContentInfo *method_fp; SipMethodRuleOptData *sdata = (SipMethodRuleOptData *)data; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Evaluating \"%s\" fast pattern rule option.\n", SIP_ROPT__METHOD)); if ((sdata == NULL) || (info == NULL)) return -1; if ((protocol != IPPROTO_TCP) && (protocol != IPPROTO_UDP)) return -1; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "adding info to \"%s\" fast pattern rule option.\n", SIP_ROPT__METHOD)); method_fp = (FPContentInfo *)calloc(1,sizeof(FPContentInfo)); if (NULL == method_fp) return -1; method_fp->content = (char *)malloc(strlen(sip)); if (NULL == method_fp->content) { free(method_fp); return -1; } memcpy(method_fp->content, sip, strlen(sip)); method_fp->length = strlen(sip); *info = method_fp; return 0; }
/* Add/update a file entry specified by file_id in the file cache*/ void *file_cache_update_entry (FileCache *fileCache, void* p, uint64_t file_id, uint8_t *file_name, uint32_t file_name_size, uint64_t file_size) { FileEntry *fileEntry; fileEntry = file_cache_get(fileCache, p, file_id, true); if (!fileEntry) return NULL; if (file_name) { DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Add file: %s (%p)with file id %d \n", file_name, file_name, file_id)); if (fileEntry->file_name && fileEntry->file_name != file_name) { DEBUG_WRAP(DebugMessage(DEBUG_FILE, "File name: %s released (%p)\n", fileEntry->file_name , fileEntry->file_name )); free(fileEntry->file_name); } fileEntry->file_name = file_name; fileEntry->file_name_size = file_name_size; } if (file_size) { fileEntry->file_size = file_size; } return fileEntry; }
/* Rule option evaluation */ static int SIP_BodyEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; SIPData *sd; SIP_Roptions *ropts; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Evaluating \"%s\" rule option.\n", SIP_ROPT__BODY)); if (!SIP_RoptDoEval(p)) return RULE_NOMATCH; sd = (SIPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_SIP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; if (ropts->body_data != NULL) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Setting cursor to body data: %p.\n", ropts->body_data)); *cursor = ropts->body_data; //Limit the length _dpd.SetAltDetect((uint8_t *)ropts->body_data, ropts->body_len); return RULE_MATCH; } return RULE_NOMATCH; }
/* Rule option evaluation */ static int SIP_MethodEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; SIPData *sd; SIP_Roptions *ropts; SipMethodRuleOptData *sdata = (SipMethodRuleOptData *)data; uint32_t methodFlag; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Evaluating \"%s\" rule option.\n", SIP_ROPT__METHOD)); if (!SIP_RoptDoEval(p)) return RULE_NOMATCH; sd = (SIPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_SIP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Rule Flags: %x Data Flags: %x, Mask: %x \n", sdata->flags, ropts->methodFlag, sdata->mask )); // Not response methodFlag = 1 << (ropts->methodFlag - 1); if (IsRequest(ropts) && ((sdata->flags & methodFlag) ^ sdata->mask)) { return RULE_MATCH; } return RULE_NOMATCH; }
/* Rule option evaluation */ static int GTP_TypeEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; GTPData *sd; GTP_Roptions *ropts; GTP_TypeRuleOptData *sdata = (GTP_TypeRuleOptData *)data; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Evaluating \"%s\" rule option.\n", GTP_ROPT__TYPE)); if (!GTP_RoptDoEval(p)) return RULE_NOMATCH; sd = (GTPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_GTP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "GTP type in packet: %d \n", ropts->gtp_type)); /*Match the GTP type*/ if ((1 << ropts->gtp_version) & sdata->types[ropts->gtp_type]) return RULE_MATCH; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Rule No Match\n")); return RULE_NOMATCH; }
/********************************************************************* * Function: DCE2_PafAbort() * * Purpose: Queries the dcerpc2 session data to see if paf abort * flag is set. * * Arguments: * void * - stream session pointer * uint32_t - flags passed in to callback. * Should have PKT_FROM_CLIENT or PKT_FROM_SERVER set. * * Returns: * bool - true if we should abort PAF, false if not. * *********************************************************************/ static inline bool DCE2_PafAbort(void *ssn, uint32_t flags) { DCE2_SsnData *sd; if (_dpd.sessionAPI->get_session_flags(ssn) & SSNFLAG_MIDSTREAM) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__PAF, "Aborting PAF because of midstream pickup.\n")); return true; } else if (!(_dpd.sessionAPI->get_session_flags(ssn) & SSNFLAG_ESTABLISHED)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__PAF, "Aborting PAF because of unestablished session.\n")); return true; } sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(ssn, PP_DCE2); if ((sd != NULL) && DCE2_SsnNoInspect(sd)) { DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__PAF, "Aborting PAF because of session data check.\n")); return true; } return false; }
/* Display the configuration for the GTP preprocessor. * * PARAMETERS: * * GTPConfig *config: GTP preprocessor configuration. * * RETURNS: Nothing. */ static void DisplayGTPConfig(GTPConfig *config) { int index; int newline; if (config == NULL) return; _dpd.logMsg("GTP config: \n"); /* Traverse list, printing ports, 5 per line */ newline = 1; _dpd.logMsg(" Ports:\n"); for(index = 0; index < MAXPORTS; index++) { if( config->ports[ PORT_INDEX(index) ] & CONV_PORT(index) ) { _dpd.logMsg("\t%d", index); if ( !((newline++)% 5) ) _dpd.logMsg("\n"); } } _dpd.logMsg("\n"); DEBUG_WRAP(DisplayMsgTypes(config)); DEBUG_WRAP(DisplayInfoElements(config)); }
/* Rule option evaluation */ static int GTP_IEEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; GTPData *sd; GTP_Roptions *ropts; GTP_InfoRuleOptData *ie; uint8_t ieType; GTP_IEData *ieData; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Evaluating \"%s\" rule option.\n", GTP_ROPT__IE)); if (!GTP_RoptDoEval(p)) return RULE_NOMATCH; sd = (GTPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_GTP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; if (NULL == ropts->gtp_infoElements) return RULE_NOMATCH; /*Match the status code*/ ie = (GTP_InfoRuleOptData *)data; ieType = ie->types[ropts->gtp_version]; if (!ieType) { return RULE_NOMATCH; } ieData = &ropts->gtp_infoElements[ieType]; /*if the data is up to date*/ if (ieData->msg_id == ropts->msg_id) { *cursor = ieData->shift + (uint8_t *)ropts->gtp_header; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Setting cursor to IE data: %p.\n", *cursor)); /*Limit the length*/ _dpd.SetAltDetect((uint8_t *)*cursor, ieData->length); return RULE_MATCH; } DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Rule No Match\n")); return RULE_NOMATCH; }
/* detection functions */ int rule13897eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const u_int8_t *beg_of_payload, *end_of_payload; u_int32_t atom_size; u_int16_t region_size; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if(checkFlow(p, rule13897options[0]->option_u.flowFlags) > 0 ) { // flowbits:isset "file.quicktime"; if(processFlowbits(p, rule13897options[1]->option_u.flowBit) > 0) { // content:"crgn"; if(contentMatch(p, rule13897options[2]->option_u.content, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if(cursor_normal + 2 >= end_of_payload) return RULE_NOMATCH; region_size = (*cursor_normal++) << 8; region_size |= *cursor_normal++; DEBUG_WRAP(printf("REGION SIZE: %d\n", region_size)); cursor_normal = cursor_normal - 10; if(cursor_normal < beg_of_payload) return RULE_NOMATCH; atom_size = (*cursor_normal++) << 24; atom_size |= (*cursor_normal++) << 16; atom_size |= (*cursor_normal++) << 8; atom_size |= *cursor_normal++; DEBUG_WRAP(printf("ATOM SIZE: %d\n", atom_size)); // Changed from region_size > (atom_size - 8) to avoid // integer underflow from (atom_size - 8) if(((u_int32_t)region_size + 8) > atom_size) return RULE_MATCH; } } } return RULE_NOMATCH; }
/********************************************************************* * Function: * * Purpose: * * Arguments: * * Returns: * *********************************************************************/ void DCE2_Detect(DCE2_SsnData *sd) { SFSnortPacket *top_pkt = (SFSnortPacket *)DCE2_CStackTop(dce2_pkt_stack); PROFILE_VARS; if (top_pkt == NULL) { DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) No packet on top of stack.", __FILE__, __LINE__); return; } DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Detecting ------------------------------------------------\n")); DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, " Rule options:\n")); DCE2_DEBUG_CODE(DCE2_DEBUG__ROPTIONS, DCE2_PrintRoptions(&sd->ropts););
/*gtp type can be numbers*/ static bool GTP_AddTypeByNumer(GTP_TypeRuleOptData *sdata, char *tok) { char *endStr = NULL; unsigned long gtpType; gtpType = _dpd.SnortStrtoul(tok, &endStr, 10); if ( *endStr) { DynamicPreprocessorFatalMessage(" %s(%d) => Bad value specified for %s. " "Please specify an integer between %d and %d, OR a correct name.\n", *(_dpd.config_file), *(_dpd.config_line), GTP_ROPT__TYPE, MIN_GTP_TYPE_CODE, MAX_GTP_TYPE_CODE); } if ((gtpType > MAX_GTP_TYPE_CODE) || (errno == ERANGE)) { DynamicPreprocessorFatalMessage(" %s(%d) => Value specified for %s is out of " "bounds. Please specify an integer between %d and %d, OR a correct name.\n", *(_dpd.config_file), *(_dpd.config_line), GTP_ROPT__TYPE, MIN_GTP_TYPE_CODE, MAX_GTP_TYPE_CODE); } DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Rule GTP type: %d.\n",gtpType)); sdata->types[gtpType] = GTP_VERSION_ALL_FLAG; return true; }
static inline void file_entry_free(FileEntry *file_entry) { if (!file_entry) return; if (file_entry->file_name) { DEBUG_WRAP(DebugMessage(DEBUG_FILE, "File name: %s released (%p)\n", file_entry->file_name, file_entry->file_name)); free(file_entry->file_name); file_entry->file_name = NULL; file_entry->file_name_size = 0; } if (file_entry->context) { file_context_free(file_entry->context); file_entry->context = NULL; } file_entry->file_size = 0; file_segments_free(file_entry); }
/********************************************************************** * Retrieves the GTP data block registered with the stream * session associated w/ the current packet. If none exists, * allocates it and registers it with the stream API. * * Arguments: * * packetp: Pointer to the packet from which/in which to * retrieve/store the GTP data block. * * RETURNS: Pointer to an GTP data block, upon success. * NULL, upon failure. **********************************************************************/ GTPData * GTPGetNewSession(SFSnortPacket *packetp, tSfPolicyId policy_id) { GTPData* datap = NULL; /* Sanity check(s) */ assert( packetp ); if ( !packetp->stream_session_ptr ) { return NULL; } datap = (GTPData *)calloc(1, sizeof(GTPData)); if ( !datap ) return NULL; /*Register the new GTP data block in the stream session. */ _dpd.streamAPI->set_application_data( packetp->stream_session_ptr, PP_GTP, datap, FreeGTPData ); datap->policy_id = policy_id; datap->config = gtp_config; ((GTPConfig *)sfPolicyUserDataGetCurrent(gtp_config))->ref_count++; gtp_stats.sessions++; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Number of sessions created: %u\n", gtp_stats.sessions)); return datap; }
/********************************************************************* * Main entry point for SIP processing. * * Arguments: * SFSnortPacket * - pointer to packet structure * * Returns: * int - SIP_SUCCESS * SIP_FAILURE * *********************************************************************/ static inline int SIP_Process(SFSnortPacket *p, SIPData* sessp) { int status; char* sip_buff = (char*) p->payload; char* end; SIP_Roptions *pRopts; SIPMsg sipMsg; memset(&sipMsg, 0, SIPMSG_ZERO_LEN); /*Input parameters*/ sipMsg.isTcp = IsTCP(p); end = sip_buff + p->payload_size; status = sip_parse(&sipMsg, sip_buff, end); if (SIP_SUCCESS == status) { SIP_overloadURI(p, &sipMsg); /*Update the dialog state*/ SIP_updateDialog(&sipMsg, &(sessp->dialogs), p); } /*Update the session data*/ pRopts = &(sessp->ropts); pRopts->methodFlag = sipMsg.methodFlag; pRopts->header_data = sipMsg.header; pRopts->header_len = sipMsg.headerLen; pRopts->body_len = sipMsg.bodyLen; pRopts->body_data = sipMsg.body_data; pRopts->status_code = sipMsg.status_code; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "SIP message header length: %d\n", sipMsg.headerLen)); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Parsed method: %.*s, Flag: 0x%x\n", sipMsg.methodLen, sipMsg.method, sipMsg.methodFlag)); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Parsed status code: %d\n", sipMsg.status_code)); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Parsed header address: %p.\n", sipMsg.header)); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Parsed body address: %p.\n", sipMsg.body_data)); sip_freeMsg(&sipMsg); return status; }
/******************************************************************** * Function: sip_process_headField() * * Process the header fields (lines). This also deals with folding. * * Arguments: * SIPMsg * - sip message * char* start - start of the header line * char* end - end of the header line * int* - index of last field processed. Used for folding processing * This value will be updated after current field been processed * Returns: * SIP_PARSE_ERROR * SIP_PARSE_SUCCESS ********************************************************************/ static int sip_process_headField(SIPMsg *msg, const char *start, const char *end, int *lastFieldIndex) { int findex =0; int length = end -start; char *colonIndex; char *newStart, *newEnd, newLength; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "process line: %.*s\n", length, start)); // If this is folding if((' ' == start[0]) || ('\t' == start[0])) { if(SIP_PARSE_NOFOLDING != *lastFieldIndex) { SIP_TrimSP(start, end, &newStart, &newEnd); return(headerFields[*lastFieldIndex].setfield(msg, newStart, newEnd)); } } // Otherwise, continue normal processing colonIndex = memchr(start, ':', length); if (!colonIndex || (colonIndex < start + 1)) return SIP_PARSE_ERROR; if (!SIP_TrimSP(start, colonIndex, &newStart, &newEnd)) return SIP_PARSE_ERROR; newLength = newEnd - newStart; /*Find out whether the field name needs to process*/ while (NULL != headerFields[findex].fname) { //Use the full name to check if ((headerFields[findex].fnameLen == newLength)&& (0 == strncasecmp(headerFields[findex].fname, newStart, newLength))) { break; } //Use short name to check else if ((NULL != headerFields[findex].shortName) && ( 1 == newLength)&& (0 == strncasecmp(headerFields[findex].shortName, newStart, newLength))) { break; } findex++; } if (NULL != headerFields[findex].fname) { // Found the field name, evaluate the value SIP_TrimSP(colonIndex + 1, end, &newStart, &newEnd); *lastFieldIndex = findex; return (headerFields[findex].setfield(msg, newStart, newEnd)); } *lastFieldIndex = SIP_PARSE_NOFOLDING; return SIP_PARSE_SUCCESS; }
/* Parsing for the rule option */ static int SIP_StatCodeInit(struct _SnortConfig *sc, char *name, char *params, void **data) { char *end = NULL; char *tok; int i_tok = 0; SipStatCodeRuleOptData *sdata; if (strcasecmp(name, SIP_ROPT__STATUS_CODE) != 0) return 0; /* Must have arguments */ if (SIP_IsEmptyStr(params)) { DynamicPreprocessorFatalMessage("%s(%d) => missing argument to sip_stat_code keyword\n", *(_dpd.config_file), *(_dpd.config_line)); } tok = strtok_r(params, ",", &end); if(!tok) DynamicPreprocessorFatalMessage("%s(%d) => missing argument to sip_stat_code keyword\n", *(_dpd.config_file), *(_dpd.config_line)); sdata = (SipStatCodeRuleOptData *)calloc(1, sizeof(*sdata)); if (sdata == NULL) { DynamicPreprocessorFatalMessage("Could not allocate memory for the " "sip preprocessor rule option.\n"); } while ((NULL != tok) && (i_tok < SIP_NUM_STAT_CODE_MAX)) { unsigned long statCode = _dpd.SnortStrtoul(tok, NULL, 10); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Rule Status code: %d.\n",sdata->stat_codes[i_tok])); if ((statCode > MAX_STAT_CODE) || ((statCode > NUM_OF_RESPONSE_TYPES - 1) && (statCode < MIN_STAT_CODE))) { DynamicPreprocessorFatalMessage("%s(%d) => Status code %u specified is not a 3 digit number or 1 - %d\n ", *(_dpd.config_file), *(_dpd.config_line), statCode, NUM_OF_RESPONSE_TYPES-1); } sdata->stat_codes[i_tok] = (uint16_t)statCode; tok = strtok_r(NULL, ", ", &end); i_tok++; } if (NULL != tok) DynamicPreprocessorFatalMessage("%s(%d) => More than %d argument to sip_stat_code keyword\n", *(_dpd.config_file), *(_dpd.config_line), SIP_NUM_STAT_CODE_MAX); *data = (void *)sdata; return 1; }
/****************************************************************** * Function: DCE2_Alert() * * Potentially generates an alert if an event is triggered. * * Arguments: * DCE2_SsnData * * This is the current session data structure being used * when the event was triggered. It is not a necessary * argument if no session data is currently available, for * example if the event is a memcap event - pass in NULL in * this case. * DCE2_Event * The event type that was triggered. * ... * The arguments to the format for the event. * * Returns: None * ******************************************************************/ void DCE2_Alert(DCE2_SsnData *sd, DCE2_Event e, ...) { va_list ap; #ifdef DEBUG_MSGS // When debugging want to see all of the alerts generated va_start(ap, e); vsnprintf(dce2_event_bufs[e], sizeof(dce2_event_bufs[e]) - 1, dce2_events[e].format, ap); va_end(ap); dce2_event_bufs[e][sizeof(dce2_event_bufs[e]) - 1] = '\0'; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "DCE2 Alert => %s\n", dce2_event_bufs[e])); #endif if (sd != NULL) { // NOTE This check needs to change if the number of preprocessor events // should exceed 63 /* Only log a specific alert once per session */ if (sd->alert_mask & ((uint64_t)1 << e)) return; /* set bit for this alert so we don't alert on again * in this session */ sd->alert_mask |= ((uint64_t)1 << e); } if (!DCE2_GcAlertOnEvent(dce2_events[e].eflag)) return; dce2_stats.events++; #ifndef DEBUG_MSGS va_start(ap, e); vsnprintf(dce2_event_bufs[e], sizeof(dce2_event_bufs[e]) - 1, dce2_events[e].format, ap); va_end(ap); dce2_event_bufs[e][sizeof(dce2_event_bufs[e]) - 1] = '\0'; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ALL, "DCE2 Alert => %s\n", dce2_event_bufs[e])); #endif _dpd.alertAdd(GENERATOR_DCE2, e, 1, 0, 3, dce2_event_bufs[e], 0); }
/* Rule option evaluation */ static int SIP_StatCodeEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; SIPData *sd; SIP_Roptions *ropts; SipStatCodeRuleOptData *sdata = (SipStatCodeRuleOptData *)data; uint16_t short_code; int i_code; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Evaluating \"%s\" rule option.\n", SIP_ROPT__STATUS_CODE)); if (!SIP_RoptDoEval(p)) return RULE_NOMATCH; sd = (SIPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_SIP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Status code in packet: %d \n", ropts->status_code)); if (0 == ropts->status_code) return RULE_NOMATCH; /*Match the status code*/ short_code = ropts->status_code / 100; for(i_code = 0; i_code < SIP_NUM_STAT_CODE_MAX; i_code++) { if ((sdata->stat_codes[i_code] == short_code)|| (sdata->stat_codes[i_code] == ropts->status_code)) return RULE_MATCH; } DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Rule No Match\n")); return RULE_NOMATCH; }
/********************************************************************* * Main entry point for GTP processing. * * Arguments: * SFSnortPacket * - pointer to packet structure * * Returns: * int - GTP_SUCCESS * GTP_FAILURE * *********************************************************************/ static inline int GTP_Process(SFSnortPacket *p, GTPData* sessp) { int status; char* gtp_buff = (char*) p->payload; static uint32_t msgId = 0; GTP_Roptions *pRopts; GTPMsg gtpMsg; pRopts = &(sessp->ropts); memset(>pMsg, 0, GTPMSG_ZERO_LEN); /* msg_id is used to associate message with information elements * If msg_id matches, the information element in the info_elements * belongs to the message * Using msg_id avoids initializing info_elements for every message * Tabled based info_elements improves information element search performance */ /* To avoid id overlap, clean table when msgId resets*/ if ( msgId == 0) gtp_cleanInfoElements(); gtpMsg.msg_id = ++msgId; status = gtp_parse(>pMsg, gtp_buff, p->payload_size); /*Update the session data*/ pRopts->gtp_type = gtpMsg.msg_type; pRopts->gtp_version = gtpMsg.version; pRopts->gtp_infoElements = gtpMsg.info_elements; pRopts->gtp_header = gtpMsg.gtp_header; pRopts->msg_id = gtpMsg.msg_id; DEBUG_WRAP(DebugMessage(DEBUG_GTP, "GTP message version: %d\n", gtpMsg.version)); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "GTP message type: %d\n", gtpMsg.msg_type)); return status; }
static inline int SIP_RoptDoEval(SFSnortPacket *p) { if ((p->payload_size == 0) || (p->stream_session == NULL) || (!IsTCP(p) && !IsUDP(p))) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No payload or no " "session pointer or not TCP or UDP - not evaluating.\n")); return 0; } return 1; }
static int Reputation_Control(uint16_t type, void *new_config, void **old_config) { ReputationConfig *config = (ReputationConfig *) new_config; if (NULL != config) { SwitchToActiveSegment(config->segment_version, &IPtables); DEBUG_WRAP(DebugMessage(DEBUG_REPUTATION,"***Switched to segment %d\n", config->segment_version)); *old_config = config; return 0; } return -1; }
/* Rule option evaluation */ static int GTP_VersionEval(void *pkt, const uint8_t **cursor, void *data) { SFSnortPacket *p = (SFSnortPacket *)pkt; GTPData *sd; GTP_Roptions *ropts; uint8_t version = *((uint8_t *)data); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Evaluating \"%s\" rule option.\n", GTP_ROPT__VERSION)); if (!GTP_RoptDoEval(p)) return RULE_NOMATCH; sd = (GTPData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_GTP); if (sd == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_GTP, "No session data - not evaluating.\n")); return RULE_NOMATCH; } ropts = &sd->ropts; /*Match the status code*/ if (version == ropts->gtp_version) { return RULE_MATCH; } DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Rule No Match\n")); return RULE_NOMATCH; }
/******************************************************************** * Function: DCE2_HttpProcessServer() * * Wrapper arount main processing point for an RPC over HTTP * session. Checks and sets session setup state for a server. * * Arguments: * DCE2_HttpSsnData * * Pointer to an RPC over HTTP session data structure. * * Returns: None * ********************************************************************/ void DCE2_HttpProcessServer(DCE2_HttpSsnData *hsd) { const SFSnortPacket *p = hsd->sd.wire_pkt; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Processing RPC over HTTP server packet.\n")); dce2_stats.http_server_pkts++; if (hsd->state == DCE2_HTTP_STATE__NONE) { if (DCE2_SsnFromServer(p)) hsd->state = DCE2_HTTP_STATE__INIT_SERVER; } DCE2_HttpProcess(hsd); }
/******************************************************************** * Function: DCE2_HttpProcessProxy() * * Wrapper arount main processing point for an RPC over HTTP * session. Checks and sets session setup state for a proxy. * * Arguments: * DCE2_HttpSsnData * * Pointer to an RPC over HTTP session data structure. * * Returns: None * ********************************************************************/ void DCE2_HttpProcessProxy(DCE2_HttpSsnData *hsd) { const SFSnortPacket *p = hsd->sd.wire_pkt; DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Processing RPC over HTTP proxy packet.\n")); dce2_stats.http_proxy_pkts++; if (hsd->state == DCE2_HTTP_STATE__NONE) { if (DCE2_SsnFromClient(p)) hsd->state = DCE2_HTTP_STATE__INIT_CLIENT; } DCE2_HttpProcess(hsd); }
/********************************************************************** * Retrieves the SIP data block registered with the stream * session associated w/ the current packet. If none exists, * allocates it and registers it with the stream API. * * Arguments: * * packetp: Pointer to the packet from which/in which to * retrieve/store the SIP data block. * * RETURNS: Pointer to an SIP data block, upon success. * NULL, upon failure. **********************************************************************/ SIPData * SIPGetNewSession(SFSnortPacket *packetp, tSfPolicyId policy_id) { SIPData* datap = NULL; static int MaxSessionsAlerted = 0; /* Sanity check(s) */ assert( packetp ); if ( !packetp->stream_session ) { return NULL; } if(numSessions > ((SIPConfig *)sfPolicyUserDataGetCurrent(sip_config))->maxNumSessions) { if (!MaxSessionsAlerted) ALERT(SIP_EVENT_MAX_SESSIONS,SIP_EVENT_MAX_SESSIONS_STR); MaxSessionsAlerted = 1; return NULL; } else { MaxSessionsAlerted = 0; } datap = (SIPData *)calloc(1, sizeof(SIPData)); if ( !datap ) return NULL; /*Register the new SIP data block in the stream session. */ _dpd.sessionAPI->set_application_data( packetp->stream_session, PP_SIP, datap, FreeSIPData ); /* We're interested in this session. Turn on stream reassembly. */ if ( !(_dpd.streamAPI->get_reassembly_direction(packetp->stream_session) & SSN_DIR_BOTH )) { _dpd.streamAPI->set_reassembly(packetp->stream_session, STREAM_FLPOLICY_FOOTPRINT, SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE); } datap->policy_id = policy_id; datap->config = sip_config; ((SIPConfig *)sfPolicyUserDataGetCurrent(sip_config))->ref_count++; numSessions++; sip_stats.sessions++; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Number of sessions created: %u\n", numSessions)); return datap; }
/******************************************************************** * Function: sip_headers_parse() * * Parse the SIP header: request and response are the same * * Arguments: * SIPMsg * - sip message * char* buff - start of the header * char* end - end of the buffer * char**lineEnd - output, the found end of header * Returns: * SIP_FAILURE * SIP_SUCCESS ********************************************************************/ static int sip_headers_parse(SIPMsg *msg, const char *buff, char *end, char **headEnd) { char *next; char *start; int length; int numOfLineBreaks; int lastFieldIndex = SIP_PARSE_NOFOLDING ; start = (char *) buff; /* * The end of header is defined by two CRLFs, or CRCR, or LFLF */ numOfLineBreaks = sip_find_linebreak(start, end, &next); while (numOfLineBreaks > 0) { /*Processing this line*/ length = next - start - numOfLineBreaks; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Header line: %.*s\n", length, start)); /*Process headers*/ sip_process_headField(msg, start, start + length, &lastFieldIndex); /*check the end of header*/ if ((1 == numOfLineBreaks) && ( start[0] == start[-1])) { /*Either CRCR or LFLF*/ *headEnd = next ; return SIP_SUCCESS; } else if ( (2 == numOfLineBreaks) && ('\r' == start[0])&&('\n' == start[1])) { *headEnd = next; return SIP_SUCCESS; } start = next; numOfLineBreaks = sip_find_linebreak(start, end, &next); } return SIP_SUCCESS; }
/********************************************************************** * Retrieves the SIP data block registered with the stream * session associated w/ the current packet. If none exists, * allocates it and registers it with the stream API. * * Arguments: * * packetp: Pointer to the packet from which/in which to * retrieve/store the SIP data block. * * RETURNS: Pointer to an SIP data block, upon success. * NULL, upon failure. **********************************************************************/ SIPData * SIPGetNewSession(SFSnortPacket *packetp, tSfPolicyId policy_id) { SIPData* datap = NULL; static int MaxSessionsAlerted = 0; /* Sanity check(s) */ assert( packetp ); if ( !packetp->stream_session_ptr ) { return NULL; } if(numSessions > ((SIPConfig *)sfPolicyUserDataGetCurrent(sip_config))->maxNumSessions) { if (!MaxSessionsAlerted) ALERT(SIP_EVENT_MAX_SESSIONS,SIP_EVENT_MAX_SESSIONS_STR); MaxSessionsAlerted = 1; return NULL; } else { MaxSessionsAlerted = 0; } datap = (SIPData *)calloc(1, sizeof(SIPData)); if ( !datap ) return NULL; /*Register the new SIP data block in the stream session. */ _dpd.streamAPI->set_application_data( packetp->stream_session_ptr, PP_SIP, datap, FreeSIPData ); datap->policy_id = policy_id; datap->config = sip_config; ((SIPConfig *)sfPolicyUserDataGetCurrent(sip_config))->ref_count++; numSessions++; sip_stats.sessions++; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Number of sessions created: %u\n", numSessions)); return datap; }
/*gtp information element can be number*/ static bool GTP_AddInfoElementByNumer(GTP_InfoRuleOptData *sdata, char *tok) { char *end = NULL; unsigned long gtpIE; int i; gtpIE = _dpd.SnortStrtoul(tok, &end, 10); DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Rule GTP information element: %d.\n",gtpIE)); if ( *end) { DynamicPreprocessorFatalMessage(" %s(%d) => Bad value specified for %s. " "Please specify an integer between %d and %d, OR a correct name.\n", *(_dpd.config_file), *(_dpd.config_line), GTP_ROPT__IE, MIN_GTP_IE_CODE, MAX_GTP_IE_CODE); } if ((gtpIE > MAX_GTP_IE_CODE) || (errno == ERANGE)) { DynamicPreprocessorFatalMessage("%s(%d) => Value specified for %s is out of " "bounds. Please specify an integer between %d and %d," "OR a correct name.\n ", *(_dpd.config_file), *(_dpd.config_line), GTP_ROPT__IE, MIN_GTP_IE_CODE, MAX_GTP_IE_CODE); } for( i = 0; i < MAX_GTP_VERSION_CODE + 1; i++) { sdata->types[i] = (uint8_t)gtpIE; } return true; }
/* detection functions */ int ruleLINUXICMPDOSeval(void *p) { #ifdef MISSING_DELETED return RULE_NOMATCH; #else SFSnortPacket *sp = (SFSnortPacket *) p; // stuff we're testing uint8_t length; uint8_t pointer; // cruft int i; if(NULL == sp) return RULE_NOMATCH; DEBUG_WRAP(printf("Beginning of processing\n")); // Leave if not ipopt 0x07 and not ipopt 0x44 if((checkHdrOpt(p, ruleLINUXICMPDOSoptions[0]->option_u.hdrData) <= 0) && (checkHdrOpt(p, ruleLINUXICMPDOSoptions[1]->option_u.hdrData) <= 0)) { DEBUG_WRAP(printf("not ipopt 0x07 or ipopt 0x44\n"););
/********************************************************************* * 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)); }