/** * \brief Returns a cuda_device_pointer against the handle in the argument. * * If a device pointer by the name \"name\" is not registered for the * handle, it is created and associated with this handle and cuda mem is * alloted and the cuda_device_pointer is returned in the argument. * If a device pointer by the name \"name\" is already registered with * the handle, the cuda_device_pointer is returned in the argument. * * \param device_ptr Pointer to the device pointer instance which should be * with the cuda_device_pointer that has to be returned back. * \param name Name of the device pointer by which we have to search * module for its existance. * \param size Size of the cuda device memory to be alloted. * \param host_ptr If any host memory has to be transferred to the cuda device * memory, it can sent using this argument. host_ptr should * hold atleast size bytes in memory. * \param handle A unique handle which identifies a module. Obtained from * a call to SCCudaHlGetUniqueHandle(). * \param cumodule_handle A handle that identifies the CUmodule within the above module. * Obtained from a call to SCCudaHlGetCudaModule() or * SCCudaHlGetCudaModuleFromFile(). * * \retval 0 On success. * \retval -1 On failure. */ int SCCudaHlGetCudaDevicePtr(CUdeviceptr *device_ptr, const char *name, size_t size, void *host_ptr, int handle, int cumodule_handle) { SCCudaHlModuleData *data = NULL; SCCudaHlModuleCUmodule *cumodule = NULL; SCCudaHlModuleDevicePointer *new_module_device_ptr = NULL; SCCudaHlModuleDevicePointer *module_device_ptr = NULL; if (device_ptr == NULL || name == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENTS, "Error invalid arguments" "device_ptr is NULL or name is NULL"); goto error; } /* check if the particular module that wants to allocate device memory is * already registered or not. If it is registered, check if a context has * been associated with the module. If yes, then we can go ahead and * create the device memory or return the reference to the device memory if * we already have the device memory associated with the module. If no, " * log warning and get out of here */ if ( ((data = SCCudaHlGetModuleData(handle)) == NULL) || (data->cuda_context == 0)) { SCLogDebug("Module not registered or no cuda context associated with " "this module. You can't create a CUDA module without" "associating a context with a module first. To use this " "registration facility, first register a module using " "context using SCCudaHlRegisterModule(), and then register " "a cuda context with that module using " "SCCudaHlGetCudaContext(), after which you can call this " "function "); goto error; } if ( (cumodule = SCCudaHlGetModuleCUmodule(data, cumodule_handle)) == NULL ) { SCLogDebug("CUmodule not registered with the module. Before you can request" "a device pointer for a module you need to load the CUmodule into" "the engine module using SCCudaHlGetCudaModule() or" "SCCudaHlGetCudaModuleFromFile()."); goto error; } /* if we already have a device pointer registered by this name return the * cuda device pointer instance */ if ( (module_device_ptr = SCCudaHlCudaDevicePtrAvailable(cumodule, name)) != NULL) { device_ptr[0] = module_device_ptr->d_ptr; return 0; } new_module_device_ptr = SCMalloc(sizeof(SCCudaHlModuleDevicePointer)); if (new_module_device_ptr == NULL) goto error; memset(new_module_device_ptr, 0, sizeof(SCCudaHlModuleDevicePointer)); if ( (new_module_device_ptr->name = SCStrdup(name)) == NULL) { SCLogError(SC_ERR_FATAL, "Fatal error encountered in SCCudaHlGetCudaDevicePtr. Exiting..."); exit(EXIT_FAILURE); } /* allocate the cuda memory */ if (SCCudaMemAlloc(&new_module_device_ptr->d_ptr, size) == -1) goto error; /* if the user has supplied a host buffer, copy contents to the device mem */ if (host_ptr != NULL) { if (SCCudaMemcpyHtoD(new_module_device_ptr->d_ptr, host_ptr, size) == -1) { goto error; } } /* send the newly assigned device pointer back to the caller */ device_ptr[0] = new_module_device_ptr->d_ptr; /* insert it into the device_ptr list for the module instance */ if (cumodule->device_ptrs == NULL) { cumodule->device_ptrs = new_module_device_ptr; return 0; } module_device_ptr = cumodule->device_ptrs; while (module_device_ptr->next != NULL) module_device_ptr = module_device_ptr->next; module_device_ptr->next = new_module_device_ptr; return 0; error: if (new_module_device_ptr != NULL) SCFree(new_module_device_ptr); return -1; }
/** * \brief This function is used to add the parsed isdataatdata into the current * signature. * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param isdataatstr pointer to the user provided isdataat options * * \retval 0 on Success * \retval -1 on Failure */ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatstr) { DetectIsdataatData *idad = NULL; SigMatch *sm = NULL; SigMatch *dm = NULL; SigMatch *pm = NULL; SigMatch *prev_pm = NULL; char *offset = NULL; idad = DetectIsdataatParse(isdataatstr, &offset); if (idad == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_ISDATAAT; sm->ctx = (void *)idad; if (s->alproto == ALPROTO_DCERPC && idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); dm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); if (pm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (dm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (pm->idx > dm->idx) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } prev_pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, sm->prev, DETECT_BYTEJUMP, sm->prev, DETECT_PCRE, sm->prev); if (prev_pm == NULL) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a dce alproto sig."); if (offset != NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s", offset); goto error; } return 0; } } else if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) { if (idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 10, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]); if (pm == NULL) { idad->flags &= ~ISDATAAT_RELATIVE; } s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } else { s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } if (pm == NULL) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a file_data sig."); if (offset != NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s", offset); goto error; } return 0; } prev_pm = pm; } else { if (!(idad->flags & ISDATAAT_RELATIVE)) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); if (offset != NULL) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(offset, s, SigMatchListSMBelongsTo(s, sm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s\n", offset); goto error; } DetectIsdataatData *isdd = sm->ctx; isdd->dataat = ((DetectByteExtractData *)bed_sm->ctx)->local_id; isdd->flags |= ISDATAAT_OFFSET_BE; SCFree(offset); } return 0; } pm = SigMatchGetLastSMFromLists(s, 56, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "isdataat relative seen " "without a previous content uricontent, " "http_client_body, http_header, http_raw_header, " "http_method, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, byte_test, " "byte_extract, byte_jump or http_user_agent keyword"); goto error; } else { int list_type = SigMatchListSMBelongsTo(s, pm); if (list_type == -1) { goto error; } SigMatchAppendSMToList(s, sm, list_type); } /* else - if (pm == NULL) */ prev_pm = pm; } if (offset != NULL) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(offset, s, SigMatchListSMBelongsTo(s, sm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s\n", offset); goto error; } DetectIsdataatData *isdd = sm->ctx; isdd->dataat = ((DetectByteExtractData *)bed_sm->ctx)->local_id; isdd->flags |= ISDATAAT_OFFSET_BE; SCFree(offset); } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (prev_pm->type) { case DETECT_CONTENT: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)prev_pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; case DETECT_PCRE: pe = (DetectPcreData *)prev_pm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: case DETECT_BYTETEST: case DETECT_BYTE_EXTRACT: SCLogDebug("Do nothing for byte_jump, byte_test, byte_extract"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } /* switch */ return 0; error: return -1; }
/** * \brief This function is used to add the parsed isdataatdata into the current * signature. * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param isdataatstr pointer to the user provided isdataat options * * \retval 0 on Success * \retval -1 on Failure */ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatstr) { DetectIsdataatData *idad = NULL; SigMatch *sm = NULL; SigMatch *dm = NULL; SigMatch *pm = NULL; SigMatch *prev_pm = NULL; idad = DetectIsdataatParse(isdataatstr); if (idad == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_ISDATAAT; sm->ctx = (void *)idad; if (s->alproto == ALPROTO_DCERPC && idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); dm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); if (pm == NULL) { SigMatchAppendDcePayload(s, sm); } else if (dm == NULL) { SigMatchAppendDcePayload(s, sm); } else if (pm->idx > dm->idx) { SigMatchAppendPayload(s, sm); } else { SigMatchAppendDcePayload(s, sm); } prev_pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, sm->prev, DETECT_BYTEJUMP, sm->prev, DETECT_PCRE, sm->prev); } else { pm = SigMatchGetLastSMFromLists(s, 30, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (pm == NULL) { if (idad->flags & ISDATAAT_RELATIVE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "isdataat relative seen " "without a previous content uricontent, " "http_client_body, http_header, http_raw_header, " "http_method or http_cookie keyword"); goto error; } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } } else { int list_type; if (pm->type == DETECT_PCRE || pm->type == DETECT_BYTEJUMP) { list_type = SigMatchListSMBelongsTo(s, pm); if (list_type == -1) { goto error; } } else { switch (pm->type) { case DETECT_CONTENT: list_type = DETECT_SM_LIST_PMATCH; break; case DETECT_URICONTENT: list_type = DETECT_SM_LIST_UMATCH; break; case DETECT_AL_HTTP_CLIENT_BODY: list_type = DETECT_SM_LIST_HCBDMATCH; break; case DETECT_AL_HTTP_RAW_HEADER: list_type = DETECT_SM_LIST_HRHDMATCH; break; case DETECT_AL_HTTP_HEADER: list_type = DETECT_SM_LIST_HHDMATCH; break; case DETECT_AL_HTTP_METHOD: list_type = DETECT_SM_LIST_HMDMATCH; break; case DETECT_AL_HTTP_COOKIE: list_type = DETECT_SM_LIST_HCDMATCH; break; } /* switch */ } /* else */ SigMatchAppendSMToList(s, sm, list_type); } /* else - if (pm == NULL) */ prev_pm = pm; } if (!(idad->flags & ISDATAAT_RELATIVE)) { return 0; } if (prev_pm == NULL) { if (s->alproto == ALPROTO_DCERPC) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a dce alproto sig."); return 0; } else { SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content, pcre, " "uricontent, http_client_body, http_header, " "http_raw_header, http_method or http_cookie keyword"); goto error; } } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (prev_pm->type) { case DETECT_CONTENT: case DETECT_URICONTENT: case DETECT_AL_HTTP_CLIENT_BODY: case DETECT_AL_HTTP_HEADER: case DETECT_AL_HTTP_RAW_HEADER: case DETECT_AL_HTTP_METHOD: case DETECT_AL_HTTP_COOKIE: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)prev_pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; case DETECT_PCRE: pe = (DetectPcreData *)prev_pm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: SCLogDebug("Do nothing for bytejump"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } /* switch */ return 0; error: //if (idad != NULL) // DetectIsdataatFree(idad); //if (sm != NULL) // SCFree(sm); return -1; }
/** \test Send a get request in three chunks + more data. */ static int DetectSslVersionTestDetect01(void) { int result = 0; Flow f; uint8_t sslbuf1[] = { 0x16 }; uint32_t ssllen1 = sizeof(sslbuf1); uint8_t sslbuf2[] = { 0x03 }; uint32_t ssllen2 = sizeof(sslbuf2); uint8_t sslbuf3[] = { 0x01 }; uint32_t ssllen3 = sizeof(sslbuf3); uint8_t sslbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x01 }; uint32_t ssllen4 = sizeof(sslbuf4); TcpSession ssn; Packet *p = NULL; Signature *s = NULL; ThreadVars th_v; DetectEngineThreadCtx *det_ctx = NULL; AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); memset(&th_v, 0, sizeof(th_v)); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; f.proto = IPPROTO_TCP; p->flow = &f; p->flowflags |= FLOW_PKT_TOSERVER; p->flowflags |= FLOW_PKT_ESTABLISHED; p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; f.alproto = ALPROTO_TLS; StreamTcpInitConfig(TRUE); DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; } de_ctx->flags |= DE_QUIET; s = de_ctx->sig_list = SigInit(de_ctx,"alert tls any any -> any any (msg:\"TLS\"; ssl_version:tls1.0; sid:1;)"); if (s == NULL) { goto end; } SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); SCMutexLock(&f.m); int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf1, ssllen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); goto end; } r = AppLayerParserParse(alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf2, ssllen2); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); goto end; } r = AppLayerParserParse(alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf3, ssllen3); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); goto end; } r = AppLayerParserParse(alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf4, ssllen4); if (r != 0) { printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); goto end; } SCMutexUnlock(&f.m); SSLState *app_state = f.alstate; if (app_state == NULL) { printf("no ssl state: "); goto end; } if (app_state->client_connp.content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, app_state->client_connp.content_type); goto end; } if (app_state->client_connp.version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, app_state->client_connp.version); goto end; } SCLogDebug("app_state is at %p, app_state->server_connp.version 0x%02X app_state->client_connp.version 0x%02X", app_state, app_state->server_connp.version, app_state->client_connp.version); /* do detect */ SigMatchSignatures(&th_v, de_ctx, det_ctx, p); if (!(PacketAlertCheck(p, 1))) { goto end; } result = 1; end: if (alp_tctx != NULL) AppLayerParserThreadCtxFree(alp_tctx); SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineCtxFree(de_ctx); StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); UTHFreePackets(&p, 1); return result; }
/** * \brief Parses a line from the classification file and adds it to Classtype * hash table in DetectEngineCtx, i.e. DetectEngineCtx->class_conf_ht. * * \param rawstr Pointer to the string to be parsed. * \param index Relative index of the string to be parsed. * \param de_ctx Pointer to the Detection Engine Context. * * \retval 0 On success. * \retval -1 On failure. */ int SCClassConfAddClasstype(char *rawstr, uint8_t index, DetectEngineCtx *de_ctx) { const char *ct_name = NULL; const char *ct_desc = NULL; const char *ct_priority_str = NULL; int ct_priority = 0; uint8_t ct_id = index; SCClassConfClasstype *ct_new = NULL; SCClassConfClasstype *ct_lookup = NULL; #define MAX_SUBSTRINGS 30 int ret = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, 30); if (ret < 0) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid Classtype in " "classification.config file"); goto error; } /* retrieve the classtype name */ ret = pcre_get_substring((char *)rawstr, ov, 30, 1, &ct_name); if (ret < 0) { SCLogInfo("pcre_get_substring() failed"); goto error; } /* retrieve the classtype description */ ret = pcre_get_substring((char *)rawstr, ov, 30, 2, &ct_desc); if (ret < 0) { SCLogInfo("pcre_get_substring() failed"); goto error; } /* retrieve the classtype priority */ ret = pcre_get_substring((char *)rawstr, ov, 30, 3, &ct_priority_str); if (ret < 0) { SCLogInfo("pcre_get_substring() failed"); goto error; } if (ct_priority_str == NULL) { goto error; } ct_priority = atoi(ct_priority_str); /* Create a new instance of the parsed Classtype string */ ct_new = SCClassConfAllocClasstype(ct_id, ct_name, ct_desc, ct_priority); if (ct_new == NULL) goto error; /* Check if the Classtype is present in the HashTable. In case it's present * ignore it, as it is a duplicate. If not present, add it to the table */ ct_lookup = HashTableLookup(de_ctx->class_conf_ht, ct_new, 0); if (ct_lookup == NULL) { if (HashTableAdd(de_ctx->class_conf_ht, ct_new, 0) < 0) SCLogDebug("HashTable Add failed"); } else { SCLogDebug("Duplicate classtype found inside classification.config"); if (ct_new->classtype_desc) SCFree(ct_new->classtype_desc); if (ct_new->classtype) SCFree(ct_new->classtype); SCFree(ct_new); } if (ct_name) SCFree((char *)ct_name); if (ct_desc) SCFree((char *)ct_desc); if (ct_priority_str) SCFree((char *)ct_priority_str); return 0; error: if (ct_name) SCFree((char *)ct_name); if (ct_desc) SCFree((char *)ct_desc); if (ct_priority_str) SCFree((char *)ct_priority_str); return -1; }
/** * \brief Free request body chunks that are already fully parsed. * * \param state htp_state, with reference to our config * \param body the body to prune * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response) * * \retval none */ void HtpBodyPrune(HtpState *state, HtpBody *body, int direction) { SCEnter(); if (body == NULL || body->first == NULL) { SCReturn; } if (body->body_parsed == 0) { SCReturn; } /* get the configured inspect sizes. Default to response values */ uint32_t min_size = state->cfg->response.inspect_min_size; uint32_t window = state->cfg->response.inspect_window; if (direction == STREAM_TOSERVER) { min_size = state->cfg->request.inspect_min_size; window = state->cfg->request.inspect_window; } uint64_t max_window = ((min_size > window) ? min_size : window); uint64_t in_flight = body->content_len_so_far - body->body_inspected; /* Special case. If body_inspected is not being updated, we make sure that * we prune the body. We allow for some extra size/room as we may be called * multiple times on uninspected body chunk additions if a large block of * data was ack'd at once. Want to avoid pruning before inspection. */ if (in_flight > (max_window * 3)) { body->body_inspected = body->content_len_so_far - max_window; } else if (body->body_inspected < max_window) { SCReturn; } uint64_t left_edge = body->body_inspected; if (left_edge <= min_size || left_edge <= window) left_edge = 0; if (left_edge) left_edge -= window; if (left_edge) { SCLogDebug("sliding body to offset %"PRIu64, left_edge); StreamingBufferSlideToOffset(body->sb, left_edge); } SCLogDebug("pruning chunks of body %p", body); HtpBodyChunk *cur = body->first; while (cur != NULL) { HtpBodyChunk *next = cur->next; SCLogDebug("cur %p", cur); if (!StreamingBufferSegmentIsBeforeWindow(body->sb, &cur->sbseg)) { SCLogDebug("not removed"); break; } body->first = next; if (body->last == cur) { body->last = next; } HTPFree(cur, sizeof(HtpBodyChunk)); cur = next; SCLogDebug("removed"); } SCReturn; }
/** * \brief Function to parse the TLS field in packet received from the server * * \param tls_state Pointer the state in which the value to be stored * \param pstate Application layer tarser state for this session * \param input Pointer the received input data * \param input_len Length in bytes of the received data * \param output Pointer to the list of parsed output elements */ static int TLSParseServerRecord(Flow *f, void *tls_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, AppLayerParserResult *output) { SCEnter(); if (input_len >= 7) { if (SSLParseServerRecord(f, tls_state, pstate, input, input_len, output) == 1) { SCLogDebug("it seems the ssl version 2 is detected"); SCReturnInt(1); } } SCLogDebug("tls_state %p, pstate %p, input %p,input_len %" PRIu32 "", tls_state, pstate, input, input_len); //PrintRawDataFp(stdout, input,input_len); uint16_t max_fields = 3; int16_t u = 0; uint32_t offset = 0; if (pstate == NULL) SCReturnInt(-1); for (u = pstate->parse_field; u < max_fields; u++) { SCLogDebug("u %" PRIu32 "", u); switch(u % 3) { case 0: /* TLS CONTENT TYPE */ { uint8_t *data = input + offset; uint32_t data_len = input_len - offset; int r = AlpParseFieldBySize(output, pstate, TLS_FIELD_SERVER_CONTENT_TYPE, /* single byte field */1, data, data_len, &offset); SCLogDebug("r = %" PRId32 "", r); if (r == 0) { pstate->parse_field = 0; SCReturnInt(0); } else if (r == -1) { SCLogError(SC_ERR_ALPARSER, "AlpParseFieldBySize failed, " "r %d", r); SCReturnInt(-1); } break; } case 1: /* TLS VERSION */ { uint8_t *data = input + offset; uint32_t data_len = input_len - offset; int r = AlpParseFieldBySize(output, pstate, TLS_FIELD_SERVER_VERSION,/* 2 byte *field */2, data, data_len, &offset); if (r == 0) { pstate->parse_field = 1; SCReturnInt(0); } else if (r == -1) { SCLogError(SC_ERR_ALPARSER, "AlpParseFieldBySize failed, " "r %d", r); SCReturnInt(-1); } break; } case 2: /* TLS Record Message Length */ { uint8_t *data = input + offset; uint32_t data_len = input_len - offset; int r = AlpParseFieldBySize(output, pstate, TLS_FIELD_LENGTH, /* 2 byte field */2, data, data_len, &offset); if (r == 0) { pstate->parse_field = 2; SCReturnInt(0); } else if (r == -1) { SCLogError(SC_ERR_ALPARSER, "AlpParseFieldBySize failed, " "r %d", r); SCReturnInt(-1); } /* Parsing of the record is done. Since we may have more than * one record, we check here if we still have data left *after* * this record. In that case setup the parser to parse that * record as well. */ uint16_t record_len; int ret = ByteExtractUint16(&record_len, BYTE_BIG_ENDIAN, output->tail->data_len, output->tail->data_ptr); if (ret != 2) { SCReturnInt(-1); } /* calulate the point up to where the current record * is in the data */ uint32_t record_offset = (offset + record_len); SCLogDebug("record offset %"PRIu32" (offset %"PRIu32", record_len" " %"PRIu16")", record_offset, offset, record_len); /* if our input buffer is bigger than the data up to and * including the current record, we instruct the parser to * expect another record of 3 fields */ if (input_len <= record_offset) break; max_fields += 3; offset += record_len; break; } } } pstate->parse_field = 0; SCReturnInt(1); }
void *TmThreadsSlot1NoInOut(void *td) { ThreadVars *tv = (ThreadVars *)td; Tm1Slot *s = (Tm1Slot *)tv->tm_slots; char run = 1; TmEcode r = TM_ECODE_OK; /* Set the thread name */ SCSetThreadName(tv->name); /* Drop the capabilities for this thread */ SCDropCaps(tv); if (tv->thread_setup_flags != 0) TmThreadSetupOptions(tv); SCLogDebug("%s starting", tv->name); if (s->s.SlotThreadInit != NULL) { r = s->s.SlotThreadInit(tv, s->s.slot_initdata, &s->s.slot_data); if (r != TM_ECODE_OK) { EngineKill(); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } memset(&s->s.slot_pre_pq, 0, sizeof(PacketQueue)); memset(&s->s.slot_post_pq, 0, sizeof(PacketQueue)); TmThreadsSetFlag(tv, THV_INIT_DONE); while(run) { TmThreadTestThreadUnPaused(tv); r = s->s.SlotFunc(tv, NULL, s->s.slot_data, /* no outqh, no pq */NULL, NULL); //printf("%s: TmThreadsSlot1NoInNoOut: r %" PRId32 "\n", tv->name, r); /* handle error */ if (r == TM_ECODE_FAILED) { TmThreadsSetFlag(tv, THV_FAILED); break; } if (TmThreadsCheckFlag(tv, THV_KILL)) { //printf("%s: TmThreadsSlot1NoInOut: KILL is set\n", tv->name); SCPerfUpdateCounterArray(tv->sc_perf_pca, &tv->sc_perf_pctx, 0); run = 0; } } if (s->s.SlotThreadExitPrintStats != NULL) { s->s.SlotThreadExitPrintStats(tv, s->s.slot_data); } if (s->s.SlotThreadDeinit != NULL) { r = s->s.SlotThreadDeinit(tv, s->s.slot_data); if (r != TM_ECODE_OK) { TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } //printf("TmThreadsSlot1NoInOut: %s ending\n", tv->name); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) 0); }
void *TmThreadsSlot1(void *td) { ThreadVars *tv = (ThreadVars *)td; Tm1Slot *s = (Tm1Slot *)tv->tm_slots; Packet *p = NULL; char run = 1; TmEcode r = TM_ECODE_OK; /* Set the thread name */ SCSetThreadName(tv->name); /* Drop the capabilities for this thread */ SCDropCaps(tv); if (tv->thread_setup_flags != 0) TmThreadSetupOptions(tv); SCLogDebug("%s starting", tv->name); if (s->s.SlotThreadInit != NULL) { r = s->s.SlotThreadInit(tv, s->s.slot_initdata, &s->s.slot_data); if (r != TM_ECODE_OK) { EngineKill(); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } memset(&s->s.slot_pre_pq, 0, sizeof(PacketQueue)); memset(&s->s.slot_post_pq, 0, sizeof(PacketQueue)); TmThreadsSetFlag(tv, THV_INIT_DONE); while(run) { TmThreadTestThreadUnPaused(tv); /* input a packet */ p = tv->tmqh_in(tv); if (p == NULL) { //printf("%s: TmThreadsSlot1: p == NULL\n", tv->name); } else { r = s->s.SlotFunc(tv, p, s->s.slot_data, &s->s.slot_pre_pq, &s->s.slot_post_pq); /* handle error */ if (r == TM_ECODE_FAILED) { TmqhReleasePacketsToPacketPool(&s->s.slot_pre_pq); TmqhReleasePacketsToPacketPool(&s->s.slot_post_pq); TmqhOutputPacketpool(tv, p); TmThreadsSetFlag(tv, THV_FAILED); break; } while (s->s.slot_pre_pq.top != NULL) { /* handle new packets from this func */ Packet *extra_p = PacketDequeue(&s->s.slot_pre_pq); if (extra_p != NULL) { tv->tmqh_out(tv, extra_p); } } /* output the packet */ tv->tmqh_out(tv, p); while (s->s.slot_post_pq.top != NULL) { /* handle new packets from this func */ Packet *extra_p = PacketDequeue(&s->s.slot_post_pq); if (extra_p != NULL) { tv->tmqh_out(tv, extra_p); } } } if (TmThreadsCheckFlag(tv, THV_KILL)) { //printf("%s: TmThreadsSlot1: KILL is set\n", tv->name); SCPerfUpdateCounterArray(tv->sc_perf_pca, &tv->sc_perf_pctx, 0); run = 0; } } if (s->s.SlotThreadExitPrintStats != NULL) { s->s.SlotThreadExitPrintStats(tv, s->s.slot_data); } if (s->s.SlotThreadDeinit != NULL) { r = s->s.SlotThreadDeinit(tv, s->s.slot_data); if (r != TM_ECODE_OK) { TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } SCLogDebug("%s ending", tv->name); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) 0); }
/** * \internal * \brief this function is used to decode IEEE802.1q packets * * \param tv pointer to the thread vars * \param dtv pointer code thread vars * \param p pointer to the packet struct * \param pkt pointer to the raw packet * \param len packet len * \param pq pointer to the packet queue * */ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { uint32_t proto; if (p->vlan_idx == 0) SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca); else if (p->vlan_idx == 1) SCPerfCounterIncr(dtv->counter_vlan_qinq, tv->sc_perf_pca); if(len < VLAN_HEADER_LEN) { ENGINE_SET_INVALID_EVENT(p, VLAN_HEADER_TOO_SMALL); return TM_ECODE_FAILED; } if (p->vlan_idx >= 2) { ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS); return TM_ECODE_FAILED; } p->vlanh[p->vlan_idx] = (VLANHdr *)pkt; if(p->vlanh[p->vlan_idx] == NULL) return TM_ECODE_FAILED; proto = GET_VLAN_PROTO(p->vlanh[p->vlan_idx]); SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "", p, pkt, proto, GET_VLAN_PRIORITY(p->vlanh[p->vlan_idx]), GET_VLAN_CFI(p->vlanh[p->vlan_idx]), GET_VLAN_ID(p->vlanh[p->vlan_idx]), len); /* only store the id for flow hashing if it's not disabled. */ if (dtv->vlan_disabled == 0) p->vlan_id[p->vlan_idx] = (uint16_t)GET_VLAN_ID(p->vlanh[p->vlan_idx]); p->vlan_idx++; switch (proto) { case ETHERNET_TYPE_IP: DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_IPV6: DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_SESS: DecodePPPOESession(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_DISC: DecodePPPOEDiscovery(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_VLAN: case ETHERNET_TYPE_8021AD: if (p->vlan_idx >= 2) { ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS); return TM_ECODE_OK; } else { DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); } break; default: SCLogDebug("unknown VLAN type: %" PRIx32 "", proto); ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE); return TM_ECODE_OK; } return TM_ECODE_OK; }
void TmThreadKillThreads(void) { ThreadVars *tv = NULL; int i = 0; for (i = 0; i < TVT_MAX; i++) { tv = tv_root[i]; while (tv) { TmThreadsSetFlag(tv, THV_KILL); SCLogDebug("told thread %s to stop", tv->name); if (tv->inq != NULL) { int i; //printf("TmThreadKillThreads: (t->inq->reader_cnt + t->inq->writer_cnt) %" PRIu32 "\n", (t->inq->reader_cnt + t->inq->writer_cnt)); /* make sure our packet pending counter doesn't block */ //SCCondSignal(&cond_pending); /* signal the queue for the number of users */ if (tv->InShutdownHandler != NULL) { tv->InShutdownHandler(tv); } for (i = 0; i < (tv->inq->reader_cnt + tv->inq->writer_cnt); i++) { if (tv->inq->q_type == 0) SCCondSignal(&trans_q[tv->inq->id].cond_q); else SCCondSignal(&data_queues[tv->inq->id].cond_q); } /* to be sure, signal more */ int cnt = 0; while (1) { if (TmThreadsCheckFlag(tv, THV_CLOSED)) { SCLogDebug("signalled the thread %" PRId32 " times", cnt); break; } cnt++; if (tv->InShutdownHandler != NULL) { tv->InShutdownHandler(tv); } for (i = 0; i < (tv->inq->reader_cnt + tv->inq->writer_cnt); i++) { if (tv->inq->q_type == 0) SCCondSignal(&trans_q[tv->inq->id].cond_q); else SCCondSignal(&data_queues[tv->inq->id].cond_q); } usleep(100); } SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id); } if (tv->cond != NULL ) { int cnt = 0; while (1) { if (TmThreadsCheckFlag(tv, THV_CLOSED)) { SCLogDebug("signalled the thread %" PRId32 " times", cnt); break; } cnt++; pthread_cond_broadcast(tv->cond); usleep(100); } } /* join it */ pthread_join(tv->t, NULL); SCLogDebug("thread %s stopped", tv->name); tv = tv->next; } } }
static int DetectSslVersionTestDetect03(void) { DetectEngineCtx *de_ctx = NULL; int result = 0; Flow f; uint8_t sslbuf1[] = { 0x16 }; uint32_t ssllen1 = sizeof(sslbuf1); uint8_t sslbuf2[] = { 0x03 }; uint32_t ssllen2 = sizeof(sslbuf2); uint8_t sslbuf3[] = { 0x01 }; uint32_t ssllen3 = sizeof(sslbuf3); uint8_t sslbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x02 }; uint32_t ssllen4 = sizeof(sslbuf4); TcpSession ssn; Packet *p = NULL; Signature *s = NULL; ThreadVars th_v; DetectEngineThreadCtx *det_ctx = NULL; memset(&th_v, 0, sizeof(th_v)); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); p->tcph->th_seq = htonl(1000); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; p->flow = &f; p->flowflags |= FLOW_PKT_TOSERVER; p->flowflags |= FLOW_PKT_ESTABLISHED; p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; f.alproto = ALPROTO_TLS; f.proto = p->proto; StreamTcpInitConfig(TRUE); FlowL7DataPtrInit(&f); StreamMsg *stream_msg = StreamMsgGetFromPool(); if (stream_msg == NULL) { printf("no stream_msg: "); goto end; } memcpy(stream_msg->data.data, sslbuf4, ssllen4); stream_msg->data.data_len = ssllen4; ssn.toserver_smsg_head = stream_msg; ssn.toserver_smsg_tail = stream_msg; de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; } de_ctx->flags |= DE_QUIET; s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"TLS\"; ssl_version:tls1.0; content:\"|01 00 00 AD|\"; sid:1;)"); if (s == NULL) { goto end; } if (s->flags & SIG_FLAG_PACKET) { SCLogDebug("SIG_FLAG_PACKET flags"); } SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); int r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf1, ssllen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf2, ssllen2); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf3, ssllen3); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, sslbuf4, ssllen4); if (r != 0) { printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); goto end; } TlsState *app_state = f.aldata[AlpGetStateIdx(ALPROTO_TLS)]; if (app_state == NULL) { printf("no ssl state: "); goto end; } if (app_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, app_state->client_content_type); goto end; } if (app_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, app_state->client_version); goto end; } /* do detect */ SigMatchSignatures(&th_v, de_ctx, det_ctx, p); if (!(PacketAlertCheck(p, 1))) { printf("signature 1 didn't match while it should have: "); goto end; } result = 1; end: if (de_ctx != NULL) { SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineCtxFree(de_ctx); } FlowL7DataPtrFree(&f); StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); UTHFreePackets(&p, 1); return result; }
/** * \brief Parses a line from the reference config file and adds it to Reference * Config hash table DetectEngineCtx->reference_conf_ht. * * \param rawstr Pointer to the string to be parsed. * \param de_ctx Pointer to the Detection Engine Context. * * \retval 0 On success. * \retval -1 On failure. */ static int SCRConfAddReference(char *rawstr, DetectEngineCtx *de_ctx) { const char *system = NULL; const char *url = NULL; SCRConfReference *ref_new = NULL; SCRConfReference *ref_lookup = NULL; #define MAX_SUBSTRINGS 30 int ret = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, 30); if (ret < 0) { SCLogError(SC_ERR_REFERENCE_CONFIG, "Invalid Reference Config in " "reference.config file"); goto error; } /* retrieve the reference system */ ret = pcre_get_substring((char *)rawstr, ov, 30, 1, &system); if (ret < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring() failed"); goto error; } /* retrieve the reference url */ ret = pcre_get_substring((char *)rawstr, ov, 30, 2, &url); if (ret < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring() failed"); goto error; } /* Create a new instance of the parsed Reference string */ ref_new = SCRConfAllocSCRConfReference(system, url); /* Check if the Reference is present in the HashTable. In case it's present * ignore it, as it's a duplicate. If not present, add it to the table */ ref_lookup = HashTableLookup(de_ctx->reference_conf_ht, ref_new, 0); if (ref_lookup == NULL) { if (HashTableAdd(de_ctx->reference_conf_ht, ref_new, 0) < 0) { SCLogDebug("HashTable Add failed"); } } else { SCLogDebug("Duplicate reference found inside reference.config"); SCRConfDeAllocSCRConfReference(ref_new); } /* free the substrings */ pcre_free_substring(system); pcre_free_substring(url); return 0; error: if (system) pcre_free_substring(system); if (url) pcre_free_substring(url); return -1; }
/** * \brief Frees a Cuda Device Pointer. * * If a device pointer by the name \"name\" is registered for this * handle, it is freed. * * \param name Name of the device pointer by which we have to search * module for its existance. * \param handle A unique handle which identifies a module. Obtained from * a call to SCCudaHlGetUniqueHandle(). * \param cumodule A handle that identifies the CUmodule within the above module. * Obtained from a call to SCCudaHlGetCudaModule() or * SCCudaHlGetCudaModuleFromFile(). * \retval 0 On success. * \retval -1 On failure. */ int SCCudaHlFreeCudaDevicePtr(const char *name, int handle, int cumodule_handle) { SCCudaHlModuleData *data = NULL; SCCudaHlModuleCUmodule *cumodule = NULL; SCCudaHlModuleDevicePointer *module_device_ptr = NULL; SCCudaHlModuleDevicePointer *temp_module_device_ptr = NULL; if (name == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENTS, "Error invalid arguments" "device_ptr is NULL or name is NULL"); goto error; } /* check if the particular module that wants to free device memory is * already registered or not. If it is registered, check if a context has * been associated with the module. If yes, then we can go ahead and * free the device memory. */ if ( ((data = SCCudaHlGetModuleData(handle)) == NULL) || (data->cuda_context == 0)) { SCLogDebug("Module not registered or no cuda context associated with " "this module. You can't create a CUDA module without" "associating a context with a module first. To use this " "registration facility, first register a module using " "context using SCCudaHlRegisterModule(), and then register " "a cuda context with that module using " "SCCudaHlGetCudaContext(), after which you can call this " "function "); goto error; } if ( (cumodule = SCCudaHlGetModuleCUmodule(data, cumodule_handle)) == NULL ) { SCLogDebug("CUmodule not registered with the module. Before you can request" "a device pointer for a module you need to load the CUmodule into" "the engine module using SCCudaHlGetCudaModule() or" "SCCudaHlGetCudaModuleFromFile()."); goto error; } /* if we do not have a device pointer registered by this name get out */ if ( (module_device_ptr = SCCudaHlCudaDevicePtrAvailable(cumodule, name)) == NULL) { goto error; } SCCudaMemFree(module_device_ptr->d_ptr); module_device_ptr->d_ptr = 0; if (module_device_ptr == cumodule->device_ptrs) { cumodule->device_ptrs = cumodule->device_ptrs->next; } else { temp_module_device_ptr = cumodule->device_ptrs; while (strcmp(temp_module_device_ptr->next->name, name) != 0) { temp_module_device_ptr = temp_module_device_ptr->next; } temp_module_device_ptr->next = temp_module_device_ptr->next->next; } SCFree(module_device_ptr->name); SCFree(module_device_ptr); return 0; error: return -1; }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) { BUG_ON(thread_data == NULL); if (list == NULL) { /* No child loggers registered. */ return TM_ECODE_OK; } OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; const uint8_t ipproto = f->proto; const AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(p->proto, alproto); if (logger_expectation == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER); const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT); const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); uint64_t max_id = tx_id; int logged = 0; int gap = 0; AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto); AppLayerGetTxIterState state; memset(&state, 0, sizeof(state)); while (1) { AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, tx_id, total_txs, &state); if (ires.tx_ptr == NULL) break; void * const tx = ires.tx_ptr; tx_id = ires.tx_id; LoggerId tx_logged = AppLayerParserGetTxLogged(f, alstate, tx); const LoggerId tx_logged_old = tx_logged; SCLogDebug("logger: expect %08x, have %08x", logger_expectation, tx_logged); if (tx_logged == logger_expectation) { /* tx already fully logged */ goto next_tx; } int tx_progress_ts = AppLayerParserGetStateProgress(p->proto, alproto, tx, ts_disrupt_flags); int tx_progress_tc = AppLayerParserGetStateProgress(p->proto, alproto, tx, tc_disrupt_flags); SCLogDebug("tx_progress_ts %d tx_progress_tc %d", tx_progress_ts, tx_progress_tc); const OutputTxLogger *logger = list; const OutputLoggerThreadStore *store = op_thread_data->store; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); #endif while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p, LogCondition %p, ts_log_progress %d " "tc_log_progress %d", logger, logger->LogCondition, logger->ts_log_progress, logger->tc_log_progress); if (logger->alproto == alproto && (tx_logged_old & (1<<logger->logger_id)) == 0) { SCLogDebug("alproto match, logging tx_id %"PRIu64, tx_id); if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { if (logger->LogCondition) { int r = logger->LogCondition(tv, p, alstate, tx, tx_id); if (r == FALSE) { SCLogDebug("conditions not met, not logging"); goto next_logger; } } else { if (tx_progress_tc < logger->tc_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next_logger; } if (tx_progress_ts < logger->ts_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next_logger; } } } SCLogDebug("Logging tx_id %"PRIu64" to logger %d", tx_id, logger->logger_id); PACKET_PROFILING_LOGGER_START(p, logger->logger_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_LOGGER_END(p, logger->logger_id); tx_logged |= (1<<logger->logger_id); } next_logger: logger = logger->next; store = store->next; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); #endif } if (tx_logged != tx_logged_old) { SCLogDebug("logger: storing %08x (was %08x)", tx_logged, tx_logged_old); AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx, tx_logged); } /* If all loggers logged set a flag and update the last tx_id * that was logged. * * If not all loggers were logged we flag that there was a gap * so any subsequent transactions in this loop don't increase * the maximum ID that was logged. */ if (!gap && tx_logged == logger_expectation) { logged = 1; max_id = tx_id; } else { gap = 1; } next_tx: if (!ires.has_next) break; tx_id++; } /* Update the the last ID that has been logged with all * transactions before it. */ if (logged) { SCLogDebug("updating log tx_id %"PRIu64, max_id); AppLayerParserSetTransactionLogId(f->alparser, max_id + 1); } end: return TM_ECODE_OK; }
/** * \todo only the first "slot" currently makes the "post_pq" available * to the thread module. */ void *TmThreadsSlotVar(void *td) { ThreadVars *tv = (ThreadVars *)td; TmVarSlot *s = (TmVarSlot *)tv->tm_slots; Packet *p = NULL; char run = 1; TmEcode r = TM_ECODE_OK; TmSlot *slot = NULL; /* Set the thread name */ SCSetThreadName(tv->name); /* Drop the capabilities for this thread */ SCDropCaps(tv); if (tv->thread_setup_flags != 0) TmThreadSetupOptions(tv); /* check if we are setup properly */ if (s == NULL || s->s == NULL || tv->tmqh_in == NULL || tv->tmqh_out == NULL) { EngineKill(); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } for (slot = s->s; slot != NULL; slot = slot->slot_next) { if (slot->SlotThreadInit != NULL) { r = slot->SlotThreadInit(tv, slot->slot_initdata, &slot->slot_data); if (r != TM_ECODE_OK) { EngineKill(); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } memset(&slot->slot_pre_pq, 0, sizeof(PacketQueue)); memset(&slot->slot_post_pq, 0, sizeof(PacketQueue)); } TmThreadsSetFlag(tv, THV_INIT_DONE); while(run) { TmThreadTestThreadUnPaused(tv); /* input a packet */ p = tv->tmqh_in(tv); if (p != NULL) { /* run the thread module(s) */ r = TmThreadsSlotVarRun(tv, p, s->s); if (r == TM_ECODE_FAILED) { TmqhOutputPacketpool(tv, p); TmThreadsSetFlag(tv, THV_FAILED); break; } /* output the packet */ tv->tmqh_out(tv, p); /* now handle the post_pq packets */ while (s->s->slot_post_pq.top != NULL) { Packet *extra_p = PacketDequeue(&s->s->slot_post_pq); if (extra_p == NULL) continue; if (s->s->slot_next != NULL) { r = TmThreadsSlotVarRun(tv, extra_p, s->s->slot_next); if (r == TM_ECODE_FAILED) { TmqhOutputPacketpool(tv, extra_p); TmThreadsSetFlag(tv, THV_FAILED); break; } } /* output the packet */ tv->tmqh_out(tv, extra_p); } } if (TmThreadsCheckFlag(tv, THV_KILL)) { run = 0; } } SCPerfUpdateCounterArray(tv->sc_perf_pca, &tv->sc_perf_pctx, 0); for (slot = s->s; slot != NULL; slot = slot->slot_next) { if (slot->SlotThreadExitPrintStats != NULL) { slot->SlotThreadExitPrintStats(tv, slot->slot_data); } if (slot->SlotThreadDeinit != NULL) { r = slot->SlotThreadDeinit(tv, slot->slot_data); if (r != TM_ECODE_OK) { TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) -1); } } } SCLogDebug("%s ending", tv->name); TmThreadsSetFlag(tv, THV_CLOSED); pthread_exit((void *) 0); }
int OutputRegisterTxLogger(LoggerId id, const char *name, AppProto alproto, TxLogger LogFunc, OutputCtx *output_ctx, int tc_log_progress, int ts_log_progress, TxLoggerCondition LogCondition, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, void (*ThreadExitPrintStats)(ThreadVars *, void *)) { if (!(AppLayerParserIsTxAware(alproto))) { SCLogNotice("%s logger not enabled: protocol %s is disabled", name, AppProtoToString(alproto)); return -1; } OutputTxLogger *op = SCMalloc(sizeof(*op)); if (op == NULL) return -1; memset(op, 0x00, sizeof(*op)); op->alproto = alproto; op->LogFunc = LogFunc; op->LogCondition = LogCondition; op->output_ctx = output_ctx; op->name = name; op->logger_id = id; op->ThreadInit = ThreadInit; op->ThreadDeinit = ThreadDeinit; op->ThreadExitPrintStats = ThreadExitPrintStats; if (tc_log_progress < 0) { op->tc_log_progress = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT); } else { op->tc_log_progress = tc_log_progress; } if (ts_log_progress < 0) { op->ts_log_progress = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER); } else { op->ts_log_progress = ts_log_progress; } if (list == NULL) { op->id = 1; list = op; } else { OutputTxLogger *t = list; while (t->next) t = t->next; if (t->id * 2 > UINT32_MAX) { SCLogError(SC_ERR_FATAL, "Too many loggers registered."); exit(EXIT_FAILURE); } op->id = t->id * 2; t->next = op; } SCLogDebug("OutputRegisterTxLogger happy"); return 0; }
/** * \brief Creates and returns the TV instance for a new thread. * * \param name Name of this TV instance * \param inq_name Incoming queue name * \param inqh_name Incoming queue handler name as set by TmqhSetup() * \param outq_name Outgoing queue name * \param outqh_name Outgoing queue handler as set by TmqhSetup() * \param slots String representation for the slot function to be used * \param fn_p Pointer to function when \"slots\" is of type \"custom\" * \param mucond Flag to indicate whether to initialize the condition * and the mutex variables for this newly created TV. * * \retval the newly created TV instance, or NULL on error */ ThreadVars *TmThreadCreate(char *name, char *inq_name, char *inqh_name, char *outq_name, char *outqh_name, char *slots, void * (*fn_p)(void *), int mucond) { ThreadVars *tv = NULL; Tmq *tmq = NULL; Tmqh *tmqh = NULL; SCLogDebug("creating thread \"%s\"...", name); /* XXX create separate function for this: allocate a thread container */ tv = SCMalloc(sizeof(ThreadVars)); if (tv == NULL) goto error; memset(tv, 0, sizeof(ThreadVars)); SC_ATOMIC_INIT(tv->flags); SCMutexInit(&tv->sc_perf_pctx.m, NULL); tv->name = name; /* default state for every newly created thread */ TmThreadsSetFlag(tv, THV_PAUSE); TmThreadsSetFlag(tv, THV_USE); /* default aof for every newly created thread */ tv->aof = THV_RESTART_THREAD; /* set the incoming queue */ if (inq_name != NULL && strcmp(inq_name,"packetpool") != 0) { SCLogDebug("inq_name \"%s\"", inq_name); tmq = TmqGetQueueByName(inq_name); if (tmq == NULL) { tmq = TmqCreateQueue(inq_name); if (tmq == NULL) goto error; } SCLogDebug("tmq %p", tmq); tv->inq = tmq; tv->inq->reader_cnt++; SCLogDebug("tv->inq %p", tv->inq); } if (inqh_name != NULL) { SCLogDebug("inqh_name \"%s\"", inqh_name); tmqh = TmqhGetQueueHandlerByName(inqh_name); if (tmqh == NULL) goto error; tv->tmqh_in = tmqh->InHandler; tv->InShutdownHandler = tmqh->InShutdownHandler; SCLogDebug("tv->tmqh_in %p", tv->tmqh_in); } /* set the outgoing queue */ if (outqh_name != NULL) { SCLogDebug("outqh_name \"%s\"", outqh_name); tmqh = TmqhGetQueueHandlerByName(outqh_name); if (tmqh == NULL) goto error; tv->tmqh_out = tmqh->OutHandler; if (outq_name != NULL && strcmp(outq_name,"packetpool") != 0) { SCLogDebug("outq_name \"%s\"", outq_name); if (tmqh->OutHandlerCtxSetup != NULL) { tv->outctx = tmqh->OutHandlerCtxSetup(outq_name); tv->outq = NULL; } else { tmq = TmqGetQueueByName(outq_name); if (tmq == NULL) { tmq = TmqCreateQueue(outq_name); if (tmq == NULL) goto error; } SCLogDebug("tmq %p", tmq); tv->outq = tmq; tv->outctx = NULL; tv->outq->writer_cnt++; } } } if (TmThreadSetSlots(tv, slots, fn_p) != TM_ECODE_OK) { goto error; } if (mucond != 0) TmThreadInitMC(tv); return tv; error: printf("ERROR: failed to setup a thread.\n"); return NULL; }
/** * \brief Decode the nodes/frames located at certain position/level * * \param ac pointer to the ASN1 ctx * \param node_id node index at the asn1 stack of the ctx * * \retval byte of parser status */ uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id) { Asn1Node *node = NULL; uint8_t ret = 0; /* while remaining data, and no fatal error, or end, or max stack frames */ while (ac->iter < ac->end && !(ac->parser_status & ASN1_STATUS_DONE) && ac->cur_frame < asn1_max_frames_config) { /* Prepare a new frame */ if (SCAsn1CtxNewFrame(ac, node_id) == NULL) break; ac->cur_frame = node_id; node = ASN1CTX_GET_NODE(ac, node_id); SCLogDebug("ASN1 Getting ID, cur:%x remaining %"PRIu32, (uint8_t)*ac->iter, (uint32_t)(ac->end - ac->iter)); /* Get identifier/tag */ ret = SCAsn1DecodeIdentifier(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing identifier"); node->flags |= ASN1_BER_EVENT_INVALID_ID; ac->ctx_flags |= node->flags; break; } SCLogDebug("ASN1 Getting LEN"); /* Get length of content */ ret = SCAsn1DecodeLength(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing length"); node->flags |= ASN1_BER_EVENT_INVALID_LEN; ac->ctx_flags |= node->flags; break; } if ( !(node->flags & ASN1_NODE_IS_EOC)) { SCLogDebug("ASN1 Getting CONTENT"); /* Inspect content */ ret = SCAsn1DecodeContent(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing content"); break; } /* Skip to the next record (if any) */ if (node->id.tag_type != ASN1_TAG_TYPE_CONSTRUCTED) /* Is primitive, skip it all (no need to decode it)*/ ac->iter += node->data.len; } /* Check if we are done with data */ ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_DONE; /* There's no more data available */ ret = ASN1_PARSER_OK; break; } #if 0 printf("Tag Num: %"PRIu32", Tag Type: %"PRIu8", Class:%"PRIu8", Length: %"PRIu32"\n", node->id.tag_num, node->id.tag_type, node->id.class_tag, node->len.len); printf("Data: \n"); PrintRawDataFp(stdout, node->data.ptr, node->len.len); printf(" -- EOD --\n"); #endif /* Stack flags/events here, so we have the resume at the ctx flags */ ac->ctx_flags |= node->flags; /* Check if it's not a primitive type, * then we need to decode contents */ if (node->id.tag_type == ASN1_TAG_TYPE_CONSTRUCTED) { ret = SCAsn1Decode(ac, node_id + 1); } /* Else we have reached a primitive type and stop the recursion, * look if we have other branches at the same level */ /* But first check if it's a constructed node, and the sum of child * lengths was more than the length of this frame * this would mean that we have an overflow at the attributes */ if (ac->iter > node->data.ptr + node->data.len + 1) { /* We decoded more length on this frame */ } node_id = ac->cur_frame + 1; } return ret; }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQueue *pq, PacketQueue *postpq) { BUG_ON(thread_data == NULL); BUG_ON(list == NULL); OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; OutputTxLogger *logger = list; OutputLoggerThreadStore *store = op_thread_data->store; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; FLOWLOCK_WRLOCK(f); /* WRITE lock before we updated flow logged id */ AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); int tx_progress_done_value_ts = AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto, STREAM_TOSERVER); int tx_progress_done_value_tc = AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto, STREAM_TOCLIENT); int proto_logged = 0; for (; tx_id < total_txs; tx_id++) { void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id); if (tx == NULL) { SCLogDebug("tx is NULL not logging"); continue; } if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { int tx_progress = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER)); if (tx_progress < tx_progress_done_value_ts) { SCLogDebug("progress not far enough, not logging"); break; } tx_progress = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT)); if (tx_progress < tx_progress_done_value_tc) { SCLogDebug("progress not far enough, not logging"); break; } } // call each logger here (pseudo code) logger = list; store = op_thread_data->store; while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p", logger); if (logger->alproto == alproto) { SCLogDebug("alproto match, logging tx_id %ju", tx_id); PACKET_PROFILING_TMM_START(p, logger->module_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_TMM_END(p, logger->module_id); proto_logged = 1; } logger = logger->next; store = store->next; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); } if (proto_logged) { SCLogDebug("updating log tx_id %ju", tx_id); AppLayerParserSetTransactionLogId(f->alparser); } } end: FLOWLOCK_UNLOCK(f); return TM_ECODE_OK; }
void RegisterNFSUDPParsers(void) { const char *proto_name = "nfs"; /* Check if NFS TCP detection is enabled. If it does not exist in * the configuration file then it will be enabled by default. */ if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) { rs_nfs_init(&sfc); SCLogDebug("NFS UDP protocol detection enabled."); AppLayerProtoDetectRegisterProtocol(ALPROTO_NFS, proto_name); if (RunmodeIsUnittests()) { SCLogDebug("Unittest mode, registering default configuration."); AppLayerProtoDetectPPRegister(IPPROTO_UDP, NFS_DEFAULT_PORT, ALPROTO_NFS, 0, NFS_MIN_FRAME_LEN, STREAM_TOSERVER, NFSProbingParserTS, NFSProbingParserTC); } else { if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP, proto_name, ALPROTO_NFS, 0, NFS_MIN_FRAME_LEN, NFSProbingParserTS, NFSProbingParserTC)) { SCLogDebug("No NFS app-layer configuration, enabling NFS" " detection TCP detection on port %s.", NFS_DEFAULT_PORT); AppLayerProtoDetectPPRegister(IPPROTO_UDP, NFS_DEFAULT_PORT, ALPROTO_NFS, 0, NFS_MIN_FRAME_LEN, STREAM_TOSERVER, NFSProbingParserTS, NFSProbingParserTC); } } } else { SCLogDebug("Protocol detecter and parser disabled for NFS."); return; } if (AppLayerParserConfParserEnabled("udp", proto_name)) { SCLogDebug("Registering NFS protocol parser."); /* Register functions for state allocation and freeing. A * state is allocated for every new NFS flow. */ AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_NFS, NFSStateAlloc, NFSStateFree); /* Register request parser for parsing frame from server to client. */ AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NFS, STREAM_TOSERVER, NFSParseRequest); /* Register response parser for parsing frames from server to client. */ AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NFS, STREAM_TOCLIENT, NFSParseResponse); /* Register a function to be called by the application layer * when a transaction is to be freed. */ AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_NFS, NFSStateTxFree); AppLayerParserRegisterLoggerFuncs(IPPROTO_UDP, ALPROTO_NFS, NFSGetTxLogged, NFSSetTxLogged); /* Register a function to return the current transaction count. */ AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_NFS, NFSGetTxCnt); /* Transaction handling. */ AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_NFS, NFSGetAlstateProgressCompletionStatus); AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP, ALPROTO_NFS, NFSGetStateProgress); AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_NFS, NFSGetTx); AppLayerParserRegisterGetTxIterator(IPPROTO_UDP, ALPROTO_NFS, RustNFSGetTxIterator); AppLayerParserRegisterGetFilesFunc(IPPROTO_UDP, ALPROTO_NFS, NFSGetFiles); /* What is this being registered for? */ AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_NFS, NFSGetTxDetectState, NFSSetTxDetectState); AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_NFS, NFSStateGetEventInfo); AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_NFS, NFSGetEvents); AppLayerParserRegisterDetectFlagsFuncs(IPPROTO_UDP, ALPROTO_NFS, NFSGetDetectFlags, NFSSetDetectFlags); } else { SCLogNotice("NFS protocol parsing disabled."); } #ifdef UNITTESTS AppLayerParserRegisterProtocolUnittests(IPPROTO_UDP, ALPROTO_NFS, NFSUDPParserRegisterTests); #endif }
int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len) { SCEnter(); #ifdef DEBUG_VALIDATION BUG_ON(f->protomap != FlowGetProtoMapping(f->proto)); #endif AppLayerParserState *pstate = NULL; AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto]; void *alstate = NULL; /* we don't have the parser registered for this protocol */ if (p->StateAlloc == NULL) goto end; /* Do this check before calling AppLayerParse */ if (flags & STREAM_GAP) { SCLogDebug("stream gap detected (missing packets), " "this is not yet supported."); if (f->alstate != NULL) AppLayerParserStreamTruncated(f->proto, alproto, f->alstate, flags); goto error; } /* Get the parser state (if any) */ pstate = f->alparser; if (pstate == NULL) { f->alparser = pstate = AppLayerParserStateAlloc(); if (pstate == NULL) goto error; } pstate->version++; SCLogDebug("app layer parser state version incremented to %"PRIu16, pstate->version); if (flags & STREAM_EOF) AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF); alstate = f->alstate; if (alstate == NULL) { f->alstate = alstate = p->StateAlloc(); if (alstate == NULL) goto error; SCLogDebug("alloced new app layer state %p (name %s)", alstate, AppLayerGetProtoName(f->alproto)); } else { SCLogDebug("using existing app layer state %p (name %s))", alstate, AppLayerGetProtoName(f->alproto)); } /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */ if (input_len > 0) { /* invoke the parser */ if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate, input, input_len, alp_tctx->alproto_local_storage[f->protomap][alproto]) < 0) { goto error; } } /* set the packets to no inspection and reassembly if required */ if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) { AppLayerParserSetEOF(pstate); FlowSetNoPayloadInspectionFlag(f); FlowSetSessionNoApplayerInspectionFlag(f); /* Set the no reassembly flag for both the stream in this TcpSession */ if (f->proto == IPPROTO_TCP && pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) { /* Used only if it's TCP */ TcpSession *ssn = f->protoctx; if (ssn != NULL) { StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOCLIENT ? 1 : 0); StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOSERVER ? 1 : 0); } } } /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */ if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) { FlowSetNoPayloadInspectionFlag(f); /* Set the no reassembly flag for both the stream in this TcpSession */ if (f->proto == IPPROTO_TCP) { /* Used only if it's TCP */ TcpSession *ssn = f->protoctx; if (ssn != NULL) { StreamTcpSetDisableRawReassemblyFlag(ssn, 0); StreamTcpSetDisableRawReassemblyFlag(ssn, 1); } } } /* next, see if we can get rid of transactions now */ AppLayerParserTransactionsCleanup(f); /* stream truncated, inform app layer */ if (flags & STREAM_DEPTH) AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags); end: SCReturnInt(0); error: /* Set the no app layer inspection flag for both * the stream in this Flow */ FlowSetSessionNoApplayerInspectionFlag(f); AppLayerParserSetEOF(pstate); SCReturnInt(-1); }
/** * \brief Add a tag entry for a host. If it already exist, update it. * * \param tag_ctx Tag context for hosts * \param tde Tag data * \param p packet * * \retval 0 if it was added, 1 if it was updated */ int TagHashAddTag(DetectTagDataEntry *tde, Packet *p) { SCEnter(); uint8_t updated = 0; uint16_t num_tags = 0; Host *host = NULL; /* Lookup host in the hash. If it doesn't exist yet it's * created. */ if (tde->flags & TAG_ENTRY_FLAG_DIR_SRC) { host = HostGetHostFromHash(&p->src); } else if (tde->flags & TAG_ENTRY_FLAG_DIR_DST) { host = HostGetHostFromHash(&p->dst); } /* no host for us */ if (host == NULL) { return -1; } void *tag = HostGetStorageById(host, host_tag_id); if (tag == NULL) { /* get a new tde as the one we have is on the stack */ DetectTagDataEntry *new_tde = DetectTagDataCopy(tde); if (new_tde != NULL) { HostSetStorageById(host, host_tag_id, new_tde); (void) SC_ATOMIC_ADD(num_tags, 1); } } else { /* Append the tag to the list of this host */ /* First iterate installed entries searching a duplicated sid/gid */ DetectTagDataEntry *iter = NULL; for (iter = tag; iter != NULL; iter = iter->next) { num_tags++; if (iter->sid == tde->sid && iter->gid == tde->gid) { iter->cnt_match++; /* If so, update data, unless the maximum MATCH limit is * reached. This prevents possible DOS attacks */ if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) { /* Reset time and counters */ iter->first_ts = iter->last_ts = tde->first_ts; iter->packets = 0; iter->bytes = 0; } updated = 1; break; } } /* If there was no entry of this rule, append the new tde */ if (updated == 0 && num_tags < DETECT_TAG_MAX_TAGS) { /* get a new tde as the one we have is on the stack */ DetectTagDataEntry *new_tde = DetectTagDataCopy(tde); if (new_tde != NULL) { (void) SC_ATOMIC_ADD(num_tags, 1); new_tde->next = tag; HostSetStorageById(host, host_tag_id, new_tde); } } else if (num_tags == DETECT_TAG_MAX_TAGS) { SCLogDebug("Max tags for sessions reached (%"PRIu16")", num_tags); } } HostRelease(host); SCReturnInt(updated); }
static void DetectHttpStatMsgSetupCallback(Signature *s) { SCLogDebug("callback invoked by %u", s->id); s->mask |= SIG_MASK_REQUIRE_HTTP_STATE; }
/** * \brief Inits the context to be used by the Classification Config parsing API. * * This function initializes the hash table to be used by the Detection * Engine Context to hold the data from the classification.config file, * obtains the file desc to parse the classification.config file, and * inits the regex used to parse the lines from classification.config * file. * * \param de_ctx Pointer to the Detection Engine Context. * * \retval 0 On success. * \retval -1 On failure. */ int SCClassConfInitContextAndLocalResources(DetectEngineCtx *de_ctx) { char *filename = NULL; const char *eb = NULL; int eo; int opts = 0; /* init the hash table to be used by the classification config Classtypes */ de_ctx->class_conf_ht = HashTableInit(4096, SCClassConfClasstypeHashFunc, SCClassConfClasstypeHashCompareFunc, SCClassConfClasstypeHashFree); if (de_ctx->class_conf_ht == NULL) { SCLogError(SC_ERR_HASH_TABLE_INIT, "Error initializing the hash " "table"); goto error; } /* if it is not NULL, use the file descriptor. The hack so that we can * avoid using a dummy classification file for testing purposes and * instead use an input stream against a buffer containing the * classification strings */ if (fd == NULL) { filename = SCClassConfGetConfFilename(); if ( (fd = fopen(filename, "r")) == NULL) { SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); goto error; } } regex = pcre_compile(DETECT_CLASSCONFIG_REGEX, opts, &eb, &eo, NULL); if (regex == NULL) { SCLogDebug("Compile of \"%s\" failed at offset %" PRId32 ": %s", DETECT_CLASSCONFIG_REGEX, eo, eb); goto error; } regex_study = pcre_study(regex, 0, &eb); if (eb != NULL) { SCLogDebug("pcre study failed: %s", eb); goto error; } return 0; error: if (de_ctx->class_conf_ht != NULL) { HashTableFree(de_ctx->class_conf_ht); de_ctx->class_conf_ht = NULL; } if (fd != NULL) { fclose(fd); fd = NULL; } if (regex != NULL) { pcre_free(regex); regex = NULL; } if (regex_study != NULL) { pcre_free(regex_study); regex_study = NULL; } return -1; }
void TimeModeSetLive(void) { live = TRUE; SCLogDebug("live time mode enabled"); }
/** * \internal * \brief Forces reassembly for flows that need it. * * When this function is called we're running in virtually dead engine, * so locking the flows is not strictly required. The reasons it is still * done are: * - code consistency * - silence complaining profilers * - allow us to aggressively check using debug valdation assertions * - be robust in case of future changes * - locking overhead if neglectable when no other thread fights us * * \param q The queue to process flows from. */ static inline void FlowForceReassemblyForHash(void) { Flow *f; TcpSession *ssn; int client_ok; int server_ok; int tcp_needs_inspection; uint32_t idx = 0; /* We use this packet just for reassembly purpose */ Packet *reassemble_p = PacketGetFromAlloc(); if (reassemble_p == NULL) return; for (idx = 0; idx < flow_config.hash_size; idx++) { FlowBucket *fb = &flow_hash[idx]; FBLOCK_LOCK(fb); /* get the topmost flow from the QUEUE */ f = fb->head; /* we need to loop through all the flows in the queue */ while (f != NULL) { PACKET_RECYCLE(reassemble_p); FLOWLOCK_WRLOCK(f); /* Get the tcp session for the flow */ ssn = (TcpSession *)f->protoctx; /* \todo Also skip flows that shouldn't be inspected */ if (ssn == NULL) { FLOWLOCK_UNLOCK(f); f = f->hnext; continue; } /* ah ah! We have some unattended toserver segments */ if ((client_ok = StreamHasUnprocessedSegments(ssn, 0)) == 1) { StreamTcpThread *stt = SC_ATOMIC_GET(stream_pseudo_pkt_stream_tm_slot->slot_data); ssn->client.last_ack = (ssn->client.seg_list_tail->seq + ssn->client.seg_list_tail->payload_len); FlowForceReassemblyPseudoPacketSetup(reassemble_p, 1, f, ssn, 1); StreamTcpReassembleHandleSegment(stream_pseudo_pkt_stream_TV, stt->ra_ctx, ssn, &ssn->server, reassemble_p, NULL); FlowDeReference(&reassemble_p->flow); if (StreamTcpReassembleProcessAppLayer(stt->ra_ctx) < 0) { SCLogDebug("shutdown flow timeout " "StreamTcpReassembleProcessAppLayer() erroring " "over something"); } } /* oh oh! We have some unattended toclient segments */ if ((server_ok = StreamHasUnprocessedSegments(ssn, 1)) == 1) { StreamTcpThread *stt = SC_ATOMIC_GET(stream_pseudo_pkt_stream_tm_slot->slot_data); ssn->server.last_ack = (ssn->server.seg_list_tail->seq + ssn->server.seg_list_tail->payload_len); FlowForceReassemblyPseudoPacketSetup(reassemble_p, 0, f, ssn, 1); StreamTcpReassembleHandleSegment(stream_pseudo_pkt_stream_TV, stt->ra_ctx, ssn, &ssn->client, reassemble_p, NULL); FlowDeReference(&reassemble_p->flow); if (StreamTcpReassembleProcessAppLayer(stt->ra_ctx) < 0) { SCLogDebug("shutdown flow timeout " "StreamTcpReassembleProcessAppLayer() erroring " "over something"); } } if (ssn->state >= TCP_ESTABLISHED && ssn->state != TCP_CLOSED) tcp_needs_inspection = 1; else tcp_needs_inspection = 0; FLOWLOCK_UNLOCK(f); /* insert a pseudo packet in the toserver direction */ if (client_ok || tcp_needs_inspection) { FLOWLOCK_WRLOCK(f); Packet *p = FlowForceReassemblyPseudoPacketGet(0, f, ssn, 1); FLOWLOCK_UNLOCK(f); if (p == NULL) { TmqhOutputPacketpool(NULL, reassemble_p); FBLOCK_UNLOCK(fb); return; } PKT_SET_SRC(p, PKT_SRC_FFR_SHUTDOWN); if (stream_pseudo_pkt_detect_prev_TV != NULL) { stream_pseudo_pkt_detect_prev_TV-> tmqh_out(stream_pseudo_pkt_detect_prev_TV, p); } else { TmSlot *s = stream_pseudo_pkt_detect_tm_slot; while (s != NULL) { TmSlotFunc SlotFunc = SC_ATOMIC_GET(s->SlotFunc); SlotFunc(NULL, p, SC_ATOMIC_GET(s->slot_data), &s->slot_pre_pq, &s->slot_post_pq); s = s->slot_next; } if (stream_pseudo_pkt_detect_TV != NULL) { stream_pseudo_pkt_detect_TV-> tmqh_out(stream_pseudo_pkt_detect_TV, p); } else { TmqhOutputPacketpool(NULL, p); } } } /* if (ssn->client.seg_list != NULL) */ if (server_ok || tcp_needs_inspection) { FLOWLOCK_WRLOCK(f); Packet *p = FlowForceReassemblyPseudoPacketGet(1, f, ssn, 1); FLOWLOCK_UNLOCK(f); if (p == NULL) { TmqhOutputPacketpool(NULL, reassemble_p); FBLOCK_UNLOCK(fb); return; } PKT_SET_SRC(p, PKT_SRC_FFR_SHUTDOWN); if (stream_pseudo_pkt_detect_prev_TV != NULL) { stream_pseudo_pkt_detect_prev_TV-> tmqh_out(stream_pseudo_pkt_detect_prev_TV, p); } else { TmSlot *s = stream_pseudo_pkt_detect_tm_slot; while (s != NULL) { TmSlotFunc SlotFunc = SC_ATOMIC_GET(s->SlotFunc); SlotFunc(NULL, p, SC_ATOMIC_GET(s->slot_data), &s->slot_pre_pq, &s->slot_post_pq); s = s->slot_next; } if (stream_pseudo_pkt_detect_TV != NULL) { stream_pseudo_pkt_detect_TV-> tmqh_out(stream_pseudo_pkt_detect_TV, p); } else { TmqhOutputPacketpool(NULL, p); } } } /* if (ssn->server.seg_list != NULL) */ /* next flow in the queue */ f = f->hnext; } /* while (f != NULL) */ FBLOCK_UNLOCK(fb); } PKT_SET_SRC(reassemble_p, PKT_SRC_FFR_SHUTDOWN); TmqhOutputPacketpool(NULL, reassemble_p); return; }
void TimeModeSetOffline (void) { live = FALSE; SCLogDebug("offline time mode enabled"); }
void RegisterAppLayerGetActiveTxIdFunc(GetActiveTxIdFunc FuncPtr) { //BUG_ON(AppLayerGetActiveTxIdFuncPtr != NULL); AppLayerGetActiveTxIdFuncPtr = FuncPtr; SCLogDebug("AppLayerGetActiveTxIdFuncPtr is now %p", AppLayerGetActiveTxIdFuncPtr); }
/** * \brief Returns a cuda_module against the handle in the argument. * * If a cuda_module is not present for a handle, it is created * and associated with this handle and the cuda_module is returned * in the argument. * * \param p_module The loaded CUmodule that is returned. * \param ptx_image Name of the module source file, w/o the .cu extension * \param handle A unique handle which identifies a module. Obtained from * a call to SCCudaHlGetUniqueHandle(). * * \retval A unique handle within the module that is associated with the * loaded CUmodule. Needed for future API calls. * \retval -1 on failure. */ int SCCudaHlGetCudaModule(CUmodule *p_module, const char *ptx_image, int handle) { SCCudaHlModuleData *data = NULL; SCCudaHlModuleCUmodule *new_module_cumodule = NULL; SCCudaHlModuleCUmodule *module_cumodules = NULL; if (p_module == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENTS, "Error invalid arguments" "p_module NULL"); return -1; } /* check if the particular module that wants a CUDA module is already * registered or not. If it is registered, check if a context has * been associated with the module. If yes, then we can go ahead and * create a cuda module and associate it with the module referenced by * the handle in the functions arguments. If no, log warning and get * out of here */ if ( ((data = SCCudaHlGetModuleData(handle)) == NULL) || (data->cuda_context == 0)) { SCLogDebug("Module not registered or no cuda context associated with " "this module. You can't create a CUDA module without" "associating a context with a module first. To use this " "registration facility, first register a module using " "context using SCCudaHlRegisterModule(), and then register " "a cuda context with that module using " "SCCudaHlGetCudaContext(), after which you can call this " "function "); return -1; } /* Register new CUmodule in the module */ new_module_cumodule = SCMalloc(sizeof(SCCudaHlModuleCUmodule)); if (new_module_cumodule == NULL) { exit(EXIT_FAILURE); } memset(new_module_cumodule, 0, sizeof(SCCudaHlModuleCUmodule)); /* select the ptx image based on the compute capability supported by all * devices (i.e. the lowest) */ char* image = SCMalloc(strlen(ptx_image)+15); memset(image, 0x0, sizeof(image)); int major = INT_MAX; int minor = INT_MAX; SCCudaDevices *devices = SCCudaGetDeviceList(); int i=0; for (; i<devices->count; i++){ if (devices->devices[i]->major_rev < major){ major = devices->devices[i]->major_rev; minor = devices->devices[i]->minor_rev; } if (devices->devices[i]->major_rev == major && devices->devices[i]->minor_rev < minor){ minor = devices->devices[i]->minor_rev; } } snprintf(image, strlen(ptx_image) + 15, "%s_sm_%u%u", ptx_image, major, minor); /* we don't have a cuda module associated with this module. Create a * cuda module, update the module with this cuda module reference and * then return the module refernce back to the calling function using * the argument */ SCLogDebug("Loading kernel module: %s\n",image); if (SCCudaModuleLoadData(p_module, (void *)SCCudaPtxDumpGetModule(image)) == -1) goto error; SCFree(image); new_module_cumodule->cuda_module = p_module[0]; new_module_cumodule->cuda_module_handle = SCCudaHlGetUniqueHandle(); /* insert it into the cuda_modules list for the module instance */ if (data->cuda_modules == NULL) { data->cuda_modules = new_module_cumodule; return new_module_cumodule->cuda_module_handle; } module_cumodules = data->cuda_modules; while (module_cumodules->next != NULL) module_cumodules = module_cumodules->next; module_cumodules->next = new_module_cumodule; return new_module_cumodule->cuda_module_handle; error: SCFree(image); return -1; }