/* Parsing for the rule option */ static int SIP_MethodInit(struct _SnortConfig *sc, char *name, char *params, void **data) { int flags = 0, mask = 0; char *end = NULL; char *tok; int negated = 0; int numTokens = 0; SipMethodRuleOptData *sdata; SIPMethodNode *method; SIPConfig * sip_parsing_config; if (strcasecmp(name, SIP_ROPT__METHOD) != 0) return 0; /*Evaluate whether all the methods are in the PP configurations */ sip_parsing_config = getParsingSIPConfig(sc); if (NULL == sip_parsing_config) DynamicPreprocessorFatalMessage("%s(%d) => Configuration error!\n", *(_dpd.config_file), *(_dpd.config_line)); /* Must have arguments */ if (SIP_IsEmptyStr(params)) { DynamicPreprocessorFatalMessage("%s(%d) => missing argument to sip_method keyword\n", *(_dpd.config_file), *(_dpd.config_line)); } tok = strtok_r(params, ",", &end); if(!tok) DynamicPreprocessorFatalMessage("%s(%d) => missing argument to sip_method keyword\n", *(_dpd.config_file), *(_dpd.config_line)); while (NULL != tok) { numTokens++; if (tok[0] == '!') { negated = 1; tok++; } /*Only one method is allowed with !*/ if (negated && (numTokens > 1)) { DynamicPreprocessorFatalMessage("%s(%d) => %s, only one method is allowed with ! for %s.\n", *(_dpd.config_file), *(_dpd.config_line), tok, name); } method = SIP_FindMethod (sip_parsing_config->methods, tok, strlen (tok)); /*if method is not found, add it as a user defined method*/ if (NULL == method) { method = SIP_AddUserDefinedMethod(tok, &sip_parsing_config->methodsConfig, &sip_parsing_config->methods ); if (NULL == method) DynamicPreprocessorFatalMessage("%s(%d) => %s can't add new method to %s.\n", *(_dpd.config_file), *(_dpd.config_line), tok, name); _dpd.logMsg("%s(%d) => Add user defined method: %s to SIP preprocessor through rule.\n", *(_dpd.config_file), *(_dpd.config_line), method->methodName); } flags |= 1 << (method->methodFlag - 1); if (negated) mask |= 1 << (method->methodFlag - 1); tok = strtok_r(NULL, ", ", &end); } sdata = (SipMethodRuleOptData *)calloc(1, sizeof(*sdata)); if (sdata == NULL) { DynamicPreprocessorFatalMessage("Could not allocate memory for the " "sip preprocessor rule option.\n"); } sdata->flags = flags; sdata->mask = mask; *data = (void *)sdata; return 1; }
static int sip_startline_parse(SIPMsg *msg, const char *buff, char *end, char **lineEnd) { char *next; char *start; int length; int numOfLineBreaks; start = (char *) buff; numOfLineBreaks = sip_find_linebreak(start, end, &next); if (numOfLineBreaks < 1) { /*No CRLF */ DEBUG_WRAP(DebugMessage(DEBUG_SIP, "No CRLF, check failed\n")); return SIP_FAILURE; } /*Exclude CRLF from start line*/ length = next - start - numOfLineBreaks; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Start line: %.*s \n", length, start)); DEBUG_WRAP(DebugMessage(DEBUG_SIP, "End of Start line \n")); /*Should at least have SIP/2.0 */ if (length < SIP_MIN_MSG_LEN) { DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Message too short, check failed\n")); return SIP_FAILURE; } *lineEnd = next; // This is a response if (0 == strncmp((const char *) buff, (const char *) SIP_KEYWORD, SIP_KEYWORD_LEN)) { char *space; unsigned long statusCode; /*Process response*/ msg->method = NULL; msg->uri = NULL; /*Check SIP version number, end with SP*/ if (!(sip_is_valid_version(buff + SIP_KEYWORD_LEN) && (*(buff + SIP_VERSION_LEN) == ' '))) { ALERT(SIP_EVENT_INVALID_VERSION,SIP_EVENT_INVALID_VERSION_STR); } space = strchr(buff, ' '); if (space == NULL) return SIP_FAILURE; statusCode = _dpd.SnortStrtoul(space + 1, NULL, 10); if (( statusCode > MAX_STAT_CODE) || (statusCode < MIN_STAT_CODE )) { ALERT(SIP_EVENT_BAD_STATUS_CODE,SIP_EVENT_BAD_STATUS_CODE_STR) msg->status_code = MAX_STAT_CODE + 1; } else msg->status_code = (uint16_t)statusCode; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Status code: %d \n", msg->status_code)); } else /* This might be a request*/ { char *space; char *version; int length; SIPMethodNode *method; /*Process request*/ if (NULL ==sip_eval_config) return SIP_FAILURE; msg->status_code = 0; // Parse the method space = memchr(buff, ' ', end - buff); if (space == NULL) return SIP_FAILURE; length = space - buff; msg->method = (char*)buff; msg->methodLen = length; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "method: %.*s\n", msg->methodLen, msg->method)); method = SIP_FindMethod (sip_eval_config->methods, msg->method, msg->methodLen); if (method) { msg->methodFlag = method->methodFlag; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "Found the method: %s, Flag: 0x%x\n", method->methodName, method->methodFlag)); } // parse the uri if (space + 1 > end) return SIP_FAILURE; msg->uri = space + 1; space = memchr(space + 1, ' ', end - msg->uri); if (space == NULL) return SIP_FAILURE; msg->uriLen = space - msg->uri; DEBUG_WRAP(DebugMessage(DEBUG_SIP, "uri: %.*s, length: %u\n", msg->uriLen, msg->uri, msg->uriLen)); if(0 == msg->uriLen) ALERT(SIP_EVENT_EMPTY_REQUEST_URI,SIP_EVENT_EMPTY_REQUEST_URI_STR) else if (sip_eval_config->maxUriLen && (msg->uriLen > sip_eval_config->maxUriLen)) ALERT(SIP_EVENT_BAD_URI,SIP_EVENT_BAD_URI_STR); version = space + 1; if (version + SIP_VERSION_LEN > end) return SIP_FAILURE; if (0 != strncmp((const char *) version, (const char *) SIP_KEYWORD, SIP_KEYWORD_LEN)) return SIP_FAILURE; /*Check SIP version number, end with CRLF*/ if (!sip_is_valid_version(*lineEnd - SIP_VERSION_NUM_LEN - numOfLineBreaks)) { ALERT(SIP_EVENT_INVALID_VERSION,SIP_EVENT_INVALID_VERSION_STR); } if (NULL == method) { ALERT(SIP_EVENT_UNKOWN_METHOD, SIP_EVENT_UNKOWN_METHOD_STR); return SIP_FAILURE; } } return SIP_SUCCESS; }