Beispiel #1
0
static int HttpGetHeaders(lua_State *luastate, int dir)
{
    if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
        return LuaCallbackError(luastate, "error: protocol not http");

    htp_tx_t *tx = LuaStateGetTX(luastate);
    if (tx == NULL)
        return LuaCallbackError(luastate, "internal error: no tx");

    htp_table_t *table = tx->request_headers;
    if (dir == 1)
        table = tx->response_headers;
    if (tx->request_headers == NULL)
        return LuaCallbackError(luastate, "no headers");

    lua_newtable(luastate);
    htp_header_t *h = NULL;
    size_t i = 0;
    size_t no_of_headers = htp_table_size(table);
    for (; i < no_of_headers; i++) {
        h = htp_table_get_index(table, i, NULL);
        LuaPushStringBuffer(luastate, bstr_ptr(h->name), bstr_len(h->name));
        LuaPushStringBuffer(luastate, bstr_ptr(h->value), bstr_len(h->value));
        lua_settable(luastate, -3);
    }
    return 1;
}
Beispiel #2
0
static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
{
    MemBufferWriteString(aft->buffer, " [**] ");

    /* referer */
    htp_header_t *h_referer = NULL;
    if (tx->request_headers != NULL) {
        h_referer = table_getc(tx->request_headers, "referer");
    }
    if (h_referer != NULL) {
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                       (uint8_t *)bstr_ptr(h_referer->value),
                       bstr_len(h_referer->value));
    } else {
        MemBufferWriteString(aft->buffer, "<no referer>");
    }
    MemBufferWriteString(aft->buffer, " [**] ");

    /* method */
    if (tx->request_method != NULL) {
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                       (uint8_t *)bstr_ptr(tx->request_method),
                       bstr_len(tx->request_method));
    }
    MemBufferWriteString(aft->buffer, " [**] ");

    /* protocol */
    if (tx->request_protocol != NULL) {
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                       (uint8_t *)bstr_ptr(tx->request_protocol),
                       bstr_len(tx->request_protocol));
    } else {
        MemBufferWriteString(aft->buffer, "<no protocol>");
    }
    MemBufferWriteString(aft->buffer, " [**] ");

    /* response status */
    if (tx->response_status != NULL) {
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                       (uint8_t *)bstr_ptr(tx->response_status),
                       bstr_len(tx->response_status));
        /* Redirect? */
        if ((tx->response_status_number > 300) && ((tx->response_status_number) < 303)) {
            htp_header_t *h_location = table_getc(tx->response_headers, "location");
            if (h_location != NULL) {
                MemBufferWriteString(aft->buffer, " => ");

                PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                               (uint8_t *)bstr_ptr(h_location->value),
                               bstr_len(h_location->value));
            }
        }
    } else {
        MemBufferWriteString(aft->buffer, "<no status>");
    }

    /* length */
    MemBufferWriteString(aft->buffer, " [**] %"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
}
Beispiel #3
0
TEST(BstrTest, DupBin) {
    bstr *src = bstr_dup_mem("ABCDEFGHIJKL\000NOPQRSTUVWXYZ", 20);
    bstr *dst;
    dst = bstr_dup(src);

    EXPECT_EQ(bstr_len(src), bstr_len(dst));
    EXPECT_EQ(0, memcmp(bstr_ptr(src), bstr_ptr(dst), bstr_len(src)));

    bstr_free(src);
    bstr_free(dst);
}
Beispiel #4
0
TEST(BstrTest, DupStr) {
    bstr *p1;
    bstr *p2;
    p1 = bstr_dup_c("s0123456789abcdefghijklmnopqrstuvwxyz");
    p2 = bstr_dup(p1);

    EXPECT_EQ(bstr_len(p1), bstr_len(p2));
    EXPECT_EQ(0, memcmp(bstr_ptr(p1), bstr_ptr(p2), bstr_len(p1)));

    bstr_free(p1);
    bstr_free(p2);
}
Beispiel #5
0
TEST(BstrTest, BeginsWith2) {
    bstr *haystack = bstr_dup_c("ABC");
    bstr *p1 = bstr_dup_c("ABCD");
    bstr *p2 = bstr_dup_c("EDFG");

    EXPECT_EQ(0, bstr_begins_with_mem(haystack, bstr_ptr(p1), bstr_len(p1)));
    EXPECT_EQ(0, bstr_begins_with_mem_nocase(haystack, bstr_ptr(p1), bstr_len(p1)));
    EXPECT_EQ(0, bstr_begins_with_mem_nocase(haystack, bstr_ptr(p2), bstr_len(p2)));

    bstr_free(p1);
    bstr_free(p2);
    bstr_free(haystack);
}
Beispiel #6
0
TEST(BstrBuilder, Append) {
    bstr_builder_t *bb = bstr_builder_create();
    bstr *str1 = bstr_dup_c("0123456789");
    bstr *str2 = bstr_dup_c("abcdefghijklmnopqrstuvwxyz");

    EXPECT_EQ(0, bstr_builder_size(bb));

    bstr_builder_appendn(bb, str1);
    bstr_builder_append_c(bb, "#");
    bstr_builder_appendn(bb, str2);
    bstr_builder_append_c(bb, "#");
    bstr_builder_append_mem(bb, "!@#$%^&*()", 4);

    EXPECT_EQ(5, bstr_builder_size(bb));

    bstr *result = bstr_builder_to_str(bb);
    EXPECT_EQ(42, bstr_len(result));

    EXPECT_EQ(0, memcmp("0123456789#abcdefghijklmnopqrstuvwxyz#!@#$",
                        bstr_ptr(result),42));
    bstr_free(result);

    bstr_builder_clear(bb);
    EXPECT_EQ(0, bstr_builder_size(bb));

    bstr_builder_destroy(bb);
}
Beispiel #7
0
static int HttpGetHeader(lua_State *luastate, int dir)
{
    if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
        return LuaCallbackError(luastate, "error: protocol not http");

    htp_tx_t *tx = LuaStateGetTX(luastate);
    if (tx == NULL)
        return LuaCallbackError(luastate, "internal error: no tx");

    const char *name = LuaGetStringArgument(luastate, 1);
    if (name == NULL)
        return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");

    htp_table_t *headers = tx->request_headers;
    if (dir == 1)
        headers = tx->response_headers;
    if (headers == NULL)
        return LuaCallbackError(luastate, "tx has no headers");

    htp_header_t *h = (htp_header_t *)htp_table_get_c(headers, name);
    if (h == NULL || bstr_len(h->value) == 0)
        return LuaCallbackError(luastate, "header not found");

    return LuaPushStringBuffer(luastate,
            bstr_ptr(h->value), bstr_len(h->value));
}
Beispiel #8
0
TEST(BstrTest, DupMem) {
    bstr *dst;
    dst = bstr_dup_mem("ABCDEFGHIJKL\000NOPQRSTUVWXYZ", 18);
    EXPECT_EQ(0, memcmp("ABCDEFGHIJKL\000NOPQRSTUVWXYZ", bstr_ptr(dst), 18));

    bstr_free(dst);
}
Beispiel #9
0
/**
 * Determines protocol number from a textual representation (i.e., "HTTP/1.1"). This
 * function will only understand a properly formatted protocol information. It does
 * not try to be flexible.
 * 
 * @param[in] protocol
 * @return Protocol version or PROTOCOL_UNKNOWN.
 */
int htp_parse_protocol(bstr *protocol) {
    if (protocol == NULL) {
        return HTP_PROTOCOL_UNKNOWN;
    }
    
    // TODO This function uses a very strict approach to parsing, whereas
    //      browsers will typically be more flexible, allowing whitespace
    //      before and after the forward slash, as well as allowing leading
    //      zeroes in the numbers. We should be able to parse such malformed
    //      content correctly (but emit a warning).
    if (bstr_len(protocol) == 8) {
        unsigned char *ptr = bstr_ptr(protocol);
        if ((ptr[0] == 'H') && (ptr[1] == 'T') && (ptr[2] == 'T') && (ptr[3] == 'P')
            && (ptr[4] == '/') && (ptr[6] == '.')) {
            // Check the version numbers
            if (ptr[5] == '0') {
                if (ptr[7] == '9') {
                    return HTP_PROTOCOL_0_9;
                }
            } else if (ptr[5] == '1') {
                if (ptr[7] == '0') {
                    return HTP_PROTOCOL_1_0;
                } else if (ptr[7] == '1') {
                    return HTP_PROTOCOL_1_1;
                }
            }
        }
    }

    return HTP_PROTOCOL_UNKNOWN;
}
Beispiel #10
0
/**
 * Generic request line parser.
 *
 * @param connp
 * @return HTP_OK or HTP_ERROR
 */
int htp_parse_request_line_generic(htp_connp_t *connp) {
    htp_tx_t *tx = connp->in_tx;
    unsigned char *data = (unsigned char *)bstr_ptr(tx->request_line);
    size_t len = bstr_len(tx->request_line);
    size_t pos = 0;

    // The request method starts at the beginning of the
    // line and ends with the first whitespace character.
    while ((pos < len) && (!htp_is_space(data[pos]))) {
        pos++;
    }

    // No, we don't care if the method is empty.

    tx->request_method = bstr_memdup((char *)data, pos);
    if (tx->request_method == NULL) {
        return HTP_ERROR;
    }
    tx->request_method_number = htp_convert_method_to_number(tx->request_method);

    // Ignore whitespace after request method. The RFC allows
    // for only one SP, but then suggests any number of SP and HT
    // should be permitted.
    while ((pos < len) && (isspace(data[pos]))) {
        pos++;
    }

    size_t start = pos;

    // The URI ends with the first whitespace.
    while ((pos < len) && (!htp_is_space(data[pos]))) {
        pos++;
    }

    tx->request_uri = bstr_memdup((char *)data + start, pos - start);
    if (tx->request_uri == NULL) {
        return HTP_ERROR;
    }

    // Ignore whitespace after URI
    while ((pos < len) && (htp_is_space(data[pos]))) {
        pos++;
    }

    // Is there protocol information available?
    if (pos == len) {
        // No, this looks like a HTTP/0.9 request.
        tx->protocol_is_simple = 1;
        return HTP_OK;
    }

    // The protocol information spreads until the end of the line.
    tx->request_protocol = bstr_memdup((char *)data + pos, len - pos);
    if (tx->request_protocol == NULL) {
        return HTP_ERROR;
    }
    tx->request_protocol_number = htp_parse_protocol(tx->request_protocol);

    return HTP_OK;
}
Beispiel #11
0
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
        const DetectEngineTransforms *transforms, Flow *_f,
        const uint8_t _flow_flags, void *txv, const int list_id)
{
    SCEnter();

    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
    if (buffer->inspect == NULL) {
        htp_tx_t *tx = (htp_tx_t *)txv;
        HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);

        if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) {
            SCLogDebug("no tx_id or uri");
            return NULL;
        }

        const uint32_t data_len = bstr_len(tx_ud->request_uri_normalized);
        const uint8_t *data = bstr_ptr(tx_ud->request_uri_normalized);

        InspectionBufferSetup(buffer, data, data_len);
        InspectionBufferApplyTransforms(buffer, transforms);
    }

    return buffer;
}
Beispiel #12
0
/**
 * Parses Cookie request header in v0 format.
 *
 * @param[in] connp
 * @return HTP_OK on success, HTP_ERROR on error
 */
htp_status_t htp_parse_cookies_v0(htp_connp_t *connp) {
    htp_header_t *cookie_header = htp_table_get_c(connp->in_tx->request_headers, "cookie");
    if (cookie_header == NULL) return HTP_OK;

    // Create a new table to store cookies
    connp->in_tx->request_cookies = htp_table_create(4);
    if (connp->in_tx->request_cookies == NULL) return HTP_ERROR;

    unsigned char *data = bstr_ptr(cookie_header->value);
    size_t len = bstr_len(cookie_header->value);
    size_t pos = 0;

    while (pos < len) {
        // Ignore whitespace at the beginning
        while ((pos < len) && (isspace((int)data[pos]))) pos++;
        if (pos == len) return HTP_OK;

        size_t start = pos;

        // Find the end of the cookie
        while ((pos < len) && (data[pos] != ';')) pos++;

        if (htp_parse_single_cookie_v0(connp, data + start, pos - start) != HTP_OK) {
            return HTP_ERROR;
        }

        // Go over the semicolon
        if (pos != len) pos++;
    }

    return HTP_OK;
}
Beispiel #13
0
/**
 * \brief Do the http_method content inspection for a signature.
 *
 * \param de_ctx  Detection engine context.
 * \param det_ctx Detection engine thread context.
 * \param s       Signature to inspect.
 * \param f       Flow.
 * \param flags   App layer flags.
 * \param state   App layer state.
 *
 * \retval 0 No match.
 * \retval 1 Match.
 */
int DetectEngineInspectHttpMethod(DetectEngineCtx *de_ctx,
                                  DetectEngineThreadCtx *det_ctx,
                                  Signature *s, Flow *f, uint8_t flags,
                                  void *alstate)
{
    SCEnter();
    int r = 0;
    HtpState *htp_state = NULL;
    htp_tx_t *tx = NULL;
    int idx;

    FLOWLOCK_RDLOCK(f);

    htp_state = (HtpState *)alstate;
    if (htp_state == NULL) {
        SCLogDebug("no HTTP state");
        goto end;
    }

    if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
        SCLogDebug("HTP state has no conn(p)");
        goto end;
    }

    idx = AppLayerTransactionGetInspectId(f);
    if (idx == -1) {
        goto end;
    }

    int size = (int)list_size(htp_state->connp->conn->transactions);
    for (; idx < size; idx++) {

        tx = list_get(htp_state->connp->conn->transactions, idx);
        if (tx == NULL || tx->request_method == NULL)
            continue;

        det_ctx->buffer_offset = 0;
        det_ctx->discontinue_matching = 0;
        det_ctx->inspection_recursion_counter = 0;

        r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH],
                                          f,
                                          (uint8_t *)bstr_ptr(tx->request_method),
                                          bstr_len(tx->request_method),
                                          DETECT_ENGINE_CONTENT_INSPECTION_MODE_HMD, NULL);
        //r = DoInspectHttpMethod(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH],
        //(uint8_t *)bstr_ptr(tx->request_method),
        //bstr_len(tx->request_method));
        if (r == 1) {
            break;
        }
    }

end:
    FLOWLOCK_UNLOCK(f);
    SCReturnInt(r);
}
Beispiel #14
0
/* Another special case callback. This one takes a htp_file_data_t pointer. */
int htpy_request_file_data_callback(htp_file_data_t *file_data) {
	long i;
	PyObject *res;
	PyObject *arglist;
	PyObject *data_key, *data_val;
	PyObject *filename_key, *filename_val;
	PyObject *tmpname_key, *tmpname_val;
	PyObject *dict = PyDict_New();

	if (!dict) {
		PyErr_SetString(htpy_error, "Unable to create dictionary.");
		return HTP_ERROR;
	}

	data_key = Py_BuildValue("s", "data");
	data_val = Py_BuildValue("s#", file_data->data, file_data->len);
	if (!data_key || !data_val) {
		Py_DECREF(dict);
		return HTP_ERROR;
	}
	if (PyDict_SetItem(dict, data_key, data_val) == -1) {
		Py_DECREF(dict);
		return HTP_ERROR;
	}

	if (file_data->file->filename) {
		filename_key = Py_BuildValue("s", "filename");
		filename_val = Py_BuildValue("s#", bstr_ptr(file_data->file->filename), bstr_len(file_data->file->filename));
		if (PyDict_SetItem(dict, filename_key, filename_val) == -1) {
			Py_DECREF(dict);
			return HTP_ERROR;
		}
	}

	if (file_data->file->tmpname) {
		tmpname_key = Py_BuildValue("s", "tmpname");
		tmpname_val = Py_BuildValue("s", file_data->file->tmpname);
		if (PyDict_SetItem(dict, tmpname_key, tmpname_val) == -1) {
			Py_DECREF(dict);
			return HTP_ERROR;
		}
	}

	arglist = Py_BuildValue("(O)", dict);
	if (!arglist)
		return HTP_ERROR;

	res = PyObject_CallObject(request_file_data_callback, arglist);
	Py_DECREF(arglist);
	if (PyErr_Occurred() != NULL) {
		PyErr_PrintEx(0);
		return HTP_ERROR;
	}
	i = PyInt_AsLong(res);
	Py_DECREF(res);
	return((int) i);
}
Beispiel #15
0
TEST(BstrTest, DupC) {
    bstr *p1;
    p1 = bstr_dup_c("arfarf");

    EXPECT_EQ(6, bstr_size(p1));
    EXPECT_EQ(6, bstr_len(p1));
    EXPECT_EQ(0, memcmp("arfarf", bstr_ptr(p1), 6));

    bstr_free(p1);
}
Beispiel #16
0
TEST(BstrTest, DupLower) {
    bstr *p1;
    bstr *p2;
    p1 = bstr_dup_c("0123456789ABCDEFGhIJKL");
    p2 = bstr_dup_lower(p1);

    EXPECT_EQ(0, memcmp("0123456789abcdefghijkl", bstr_ptr(p2), 22));

    bstr_free(p1);
    bstr_free(p2);
}
Beispiel #17
0
TEST(BstrTest, AdjustRealPtr) {
    bstr *b = bstr_dup_c("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    char c[] = "0123456789";

    bstr_adjust_realptr(b, c);
    bstr_adjust_len(b, strlen(c));

    EXPECT_TRUE((char *)bstr_ptr(b) == c);

    bstr_free(b);
}
Beispiel #18
0
static PyObject *htpy_connp_get_response_protocol(PyObject *self, PyObject *args) {
	PyObject *ret;

	if (!((htpy_connp *) self)->connp->out_tx)
		Py_RETURN_NONE;

	if (!((htpy_connp *) self)->connp->out_tx->response_protocol)
		Py_RETURN_NONE;

	ret = Py_BuildValue("s#", bstr_ptr(((htpy_connp *) self)->connp->out_tx->response_protocol), bstr_len(((htpy_connp *) self)->connp->out_tx->response_protocol));
	return ret;
}
Beispiel #19
0
static PyObject *htpy_connp_get_request_line(PyObject *self, PyObject *args) {
	PyObject *ret;

	if (!((htpy_connp *) self)->connp->in_tx)
		Py_RETURN_NONE;

	if (!((htpy_connp *) self)->connp->in_tx->request_line)
		Py_RETURN_NONE;

	ret = Py_BuildValue("s#", bstr_ptr(((htpy_connp *) self)->connp->in_tx->request_line), bstr_len(((htpy_connp *) self)->connp->in_tx->request_line));
	return ret;
}
Beispiel #20
0
static int HttpGetRequestUriNormalized(lua_State *luastate)
{
    if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
        return LuaCallbackError(luastate, "error: protocol not http");

    htp_tx_t *tx = LuaStateGetTX(luastate);
    if (tx == NULL)
        return LuaCallbackError(luastate, "internal error: no tx");

    HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
    if (htud == NULL)
        return LuaCallbackError(luastate, "no htud in tx");

    if (htud->request_uri_normalized == NULL ||
        bstr_ptr(htud->request_uri_normalized) == NULL ||
        bstr_len(htud->request_uri_normalized) == 0)
        return LuaCallbackError(luastate, "no normalized uri");

    return LuaPushStringBuffer(luastate,
            bstr_ptr(htud->request_uri_normalized),
            bstr_len(htud->request_uri_normalized));
}
Beispiel #21
0
TEST(BstrTest, DupEx) {
    bstr *p1;
    bstr *p2;
    p1 = bstr_dup_c("0123456789abcdefghijkl");
    p2 = bstr_dup_ex(p1, 4, 10);

    EXPECT_EQ(10, bstr_size(p2));
    EXPECT_EQ(10, bstr_len(p2));
    EXPECT_EQ(0, memcmp("456789abcd", bstr_ptr(p2),10));

    bstr_free(p1);
    bstr_free(p2);
}
Beispiel #22
0
static void LogFilestoreMetaGetUri(FILE *fp, Packet *p, File *ff) {
    HtpState *htp_state = (HtpState *)p->flow->alstate;
    if (htp_state != NULL) {
        htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, ff->txid);
        if (tx != NULL && tx->request_uri_normalized != NULL) {
            PrintRawUriFp(fp, (uint8_t *)bstr_ptr(tx->request_uri_normalized),
                    bstr_len(tx->request_uri_normalized));
            return;
        }
    }

    fprintf(fp, "<unknown>");
}
Beispiel #23
0
static void LogFileMetaGetHost(FILE *fp, Packet *p, File *ff) {
    HtpState *htp_state = (HtpState *)p->flow->alstate;
    if (htp_state != NULL) {
        htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
        if (tx != NULL && tx->request_hostname != NULL) {
            PrintRawJsonFp(fp, (uint8_t *)bstr_ptr(tx->request_hostname),
                           bstr_len(tx->request_hostname));
            return;
        }
    }

    fprintf(fp, "<unknown>");
}
/**
 * \brief Do the content inspection & validation for a signature
 *
 * \param de_ctx Detection engine context
 * \param det_ctx Detection engine thread context
 * \param s Signature to inspect
 * \param sm SigMatch to inspect
 * \param f Flow
 * \param flags app layer flags
 * \param state App layer state
 *
 * \retval 0 no match.
 * \retval 1 match.
 * \retval 2 Sig can't match.
 */
int DetectEngineInspectHttpResponseLine(ThreadVars *tv,
                                  DetectEngineCtx *de_ctx,
                                  DetectEngineThreadCtx *det_ctx,
                                  Signature *s, Flow *f, uint8_t flags,
                                  void *alstate,
                                  void *txv, uint64_t tx_id)
{
    htp_tx_t *tx = (htp_tx_t *)txv;

    if (tx->response_line == NULL) {
        if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_RESPONSE_LINE)
            return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
        else
            return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
    }

    det_ctx->discontinue_matching = 0;
    det_ctx->buffer_offset = 0;
    det_ctx->inspection_recursion_counter = 0;

#if 0
    PrintRawDataFp(stdout, (uint8_t *)bstr_ptr(tx->response_line),
            bstr_len(tx->response_line));
#endif

    /* run the inspection against the buffer */
    int r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HTTP_RESLINEMATCH],
                                          f,
                                          bstr_ptr(tx->response_line),
                                          bstr_len(tx->response_line),
                                          0,
                                          DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
    if (r == 1) {
        return DETECT_ENGINE_INSPECT_SIG_MATCH;
    } else {
        return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
    }
}
Beispiel #25
0
/**
 * Parses request query string, if present.
 *
 * @param[in] connp
 * @param[in] raw_data
 * @param[in] raw_len
 * @return HTP_OK if query string was parsed, HTP_DECLINED if there was no query
 *         string, and HTP_ERROR on failure.
 */
htp_status_t htp_ch_urlencoded_callback_request_line(htp_tx_t *tx) {
    // Proceed only if there's something for us to parse.
    if ((tx->parsed_uri->query == NULL) || (bstr_len(tx->parsed_uri->query) == 0)) {
        return HTP_DECLINED;
    }

    // We have a non-zero length query string.

    tx->request_urlenp_query = htp_urlenp_create(tx);
    if (tx->request_urlenp_query == NULL) return HTP_ERROR;

    if (htp_urlenp_parse_complete(tx->request_urlenp_query, bstr_ptr(tx->parsed_uri->query),
            bstr_len(tx->parsed_uri->query)) != HTP_OK) {
        htp_urlenp_destroy(tx->request_urlenp_query);
        return HTP_ERROR;
    }

    // Add all parameters to the transaction.

    bstr *name = NULL;
    bstr *value = NULL;
    for (size_t i = 0, n = htp_table_size(tx->request_urlenp_query->params); i < n; i++) {
        value = htp_table_get_index(tx->request_urlenp_query->params, i, &name);

        htp_param_t *param = calloc(1, sizeof (htp_param_t));
        if (param == NULL) return HTP_ERROR;
        
        param->name = name;
        param->value = value;
        param->source = HTP_SOURCE_QUERY_STRING;
        param->parser_id = HTP_PARSER_URLENCODED;
        param->parser_data = NULL;

        if (htp_tx_req_add_param(tx, param) != HTP_OK) {
            free(param);
            return HTP_ERROR;
        }
    }

    // All the parameter data is now owned by the transaction, and
    // the parser table used to store it is no longer needed. The
    // line below will destroy just the table, leaving keys intact.
    htp_table_destroy_ex(tx->request_urlenp_query->params);
    tx->request_urlenp_query->params = NULL;

    htp_urlenp_destroy(tx->request_urlenp_query);
    tx->request_urlenp_query = NULL;

    return HTP_OK;
}
Beispiel #26
0
/*
 * XXX: Not sure I like mucking around in the transaction to get the status,
 * but I'm not sure of a better way.
 */
static PyObject *htpy_connp_get_response_status_string(PyObject *self, PyObject *args) {
	PyObject *ret;
	htp_tx_t *tx = NULL;

	tx = htp_list_get(((htpy_connp *) self)->connp->conn->transactions, htp_list_size(((htpy_connp *) self)->connp->conn->transactions) - 1);
	if (!tx) {
		PyErr_SetString(htpy_error, "Missing transaction.");
		return NULL;
	}

	ret = Py_BuildValue("s#", bstr_ptr(tx->response_status), bstr_len(tx->response_status));

	return ret;
}
Beispiel #27
0
static void LogFilestoreMetaGetReferer(FILE *fp, Packet *p, File *ff) {
    HtpState *htp_state = (HtpState *)p->flow->alstate;
    if (htp_state != NULL) {
        htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, ff->txid);
        if (tx != NULL) {
            table_t *headers;
            headers = tx->request_headers;
            htp_header_t *h = NULL;

            table_iterator_reset(headers);
            while (table_iterator_next(headers, (void **)&h) != NULL) {
                if (bstr_len(h->name) >= 7 &&
                        SCMemcmpLowercase((uint8_t *)"referer", (uint8_t *)bstr_ptr(h->name), bstr_len(h->name)) == 0) {
                    PrintRawUriFp(fp, (uint8_t *)bstr_ptr(h->value),
                        bstr_len(h->value));
                    return;
                }
            }
        }
    }

    fprintf(fp, "<unknown>");
}
Beispiel #28
0
/**
 * Parse query string, if available. This method is invoked after the
 * request line has been processed.
 *
 * @param connp
 */
int htp_ch_urlencoded_callback_request_line(htp_connp_t *connp) {
    // Parse query string, when available
    if ((connp->in_tx->parsed_uri->query != NULL) && (bstr_len(connp->in_tx->parsed_uri->query) > 0)) {
        connp->in_tx->request_urlenp_query = htp_urlenp_create(connp->in_tx);
        if (connp->in_tx->request_urlenp_query == NULL) {
            return HOOK_ERROR;
        }

        htp_urlenp_parse_complete(connp->in_tx->request_urlenp_query,
            (unsigned char *) bstr_ptr(connp->in_tx->parsed_uri->query),
            bstr_len(connp->in_tx->parsed_uri->query));

        // Is there a parameter processor?
        if (connp->cfg->parameter_processor == NULL) {
            // There's no parameter processor

            if (connp->cfg->internal_encoding == NULL) {
                // No transcoding; use the parser table directly
                connp->in_tx->request_params_query = connp->in_tx->request_urlenp_query->params;
                connp->in_tx->request_params_query_reused = 1;
            } else {
                // Transcode values
                connp->in_tx->request_params_query = connp->in_tx->request_urlenp_query->params;
                htp_transcode_params(connp, &connp->in_tx->request_params_query, 0);
            }
        } else {
            // We have a parameter processor defined, which
            // means we'll need to create a new table

            connp->in_tx->request_params_query =
                connp->cfg->create_table(table_size(connp->in_tx->request_urlenp_query->params));

            // Use the parameter processor on each parameter, storing
            // the results in the newly created table
            bstr *name;
            void *tvalue;
            table_iterator_reset(connp->in_tx->request_urlenp_query->params);
            while ((name = table_iterator_next(connp->in_tx->request_urlenp_query->params, & tvalue)) != NULL) {
                connp->cfg->parameter_processor(connp->in_tx->request_params_query, name, (bstr *)tvalue);
                // TODO Check return code
            }

            // Transcode as necessary
            htp_transcode_params(connp, &connp->in_tx->request_params_query, 1);
        }
    }

    return HOOK_OK;
}
Beispiel #29
0
int DetectEngineRunHttpUAMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
                             HtpState *htp_state, uint8_t flags)
{
    htp_tx_t *tx = NULL;
    uint32_t cnt = 0;
    int idx;

    /* we need to lock because the buffers are not actually true buffers
     * but are ones that point to a buffer given by libhtp */
    FLOWLOCK_RDLOCK(f);

    if (htp_state == NULL) {
        SCLogDebug("no HTTP state");
        goto end;
    }

    if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
        SCLogDebug("HTP state has no conn(p)");
        goto end;
    }

    idx = AppLayerTransactionGetInspectId(f);
    if (idx == -1) {
        goto end;
    }

    int size = (int)list_size(htp_state->connp->conn->transactions);
    for (; idx < size; idx++) {

        tx = list_get(htp_state->connp->conn->transactions, idx);
        if (tx == NULL)
            continue;

        htp_header_t *h = (htp_header_t *)table_getc(tx->request_headers,
                                                     "User-Agent");
        if (h == NULL) {
            SCLogDebug("HTTP user agent header not present in this request");
            continue;
        }

        cnt += HttpUAPatternSearch(det_ctx,
                                   (uint8_t *)bstr_ptr(h->value),
                                   bstr_len(h->value), flags);
    }

 end:
    FLOWLOCK_UNLOCK(f);
    return cnt;
}
Beispiel #30
0
TEST(BstrTest, ExpandPtr) {
    bstr *b;
    b = (bstr*) malloc(sizeof(bstr));
    ASSERT_NE((bstr*)NULL, b);
    b->realptr = (unsigned char*) malloc(10);
    b->len = 0;
    b->size = 10;
    ASSERT_NE((unsigned char*)NULL, bstr_ptr(b));

    bstr *p2 = bstr_expand(b, 100);
    EXPECT_TRUE(p2 == NULL);

    free(b->realptr);
    bstr_free(b);
}