summaryrefslogtreecommitdiffstats
path: root/htp/htp_connection_parser.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--htp/htp_connection_parser.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/htp/htp_connection_parser.c b/htp/htp_connection_parser.c
new file mode 100644
index 0000000..8fd4ed6
--- /dev/null
+++ b/htp/htp_connection_parser.c
@@ -0,0 +1,260 @@
+/***************************************************************************
+ * Copyright (c) 2009-2010 Open Information Security Foundation
+ * Copyright (c) 2010-2013 Qualys, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+
+ * - Neither the name of the Qualys, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ***************************************************************************/
+
+/**
+ * @file
+ * @author Ivan Ristic <ivanr@webkreator.com>
+ */
+
+#include "htp_config_auto.h"
+
+#include "htp_private.h"
+
+void htp_connp_clear_error(htp_connp_t *connp) {
+ connp->last_error = NULL;
+}
+
+void htp_connp_req_close(htp_connp_t *connp, const htp_time_t *timestamp) {
+ if (connp == NULL) return;
+
+ // Update internal flags
+ if (connp->in_status != HTP_STREAM_ERROR)
+ connp->in_status = HTP_STREAM_CLOSED;
+
+ // Call the parsers one last time, which will allow them
+ // to process the events that depend on stream closure
+ htp_connp_req_data(connp, timestamp, NULL, 0);
+}
+
+void htp_connp_close(htp_connp_t *connp, const htp_time_t *timestamp) {
+ if (connp == NULL) return;
+
+ // Close the underlying connection.
+ htp_conn_close(connp->conn, timestamp);
+
+ // Update internal flags
+ if (connp->in_status != HTP_STREAM_ERROR)
+ connp->in_status = HTP_STREAM_CLOSED;
+ if (connp->out_status != HTP_STREAM_ERROR)
+ connp->out_status = HTP_STREAM_CLOSED;
+
+ // Call the parsers one last time, which will allow them
+ // to process the events that depend on stream closure
+ htp_connp_req_data(connp, timestamp, NULL, 0);
+ htp_connp_res_data(connp, timestamp, NULL, 0);
+}
+
+htp_connp_t *htp_connp_create(htp_cfg_t *cfg) {
+ htp_connp_t *connp = calloc(1, sizeof (htp_connp_t));
+ if (connp == NULL) return NULL;
+
+ // Use the supplied configuration structure
+ connp->cfg = cfg;
+
+ // Create a new connection.
+ connp->conn = htp_conn_create();
+ if (connp->conn == NULL) {
+ free(connp);
+ return NULL;
+ }
+
+ // Request parsing
+ connp->in_state = htp_connp_REQ_IDLE;
+ connp->in_status = HTP_STREAM_NEW;
+
+ // Response parsing
+ connp->out_state = htp_connp_RES_IDLE;
+ connp->out_status = HTP_STREAM_NEW;
+
+ return connp;
+}
+
+void htp_connp_destroy(htp_connp_t *connp) {
+ if (connp == NULL) return;
+
+ if (connp->in_buf != NULL) {
+ free(connp->in_buf);
+ }
+
+ if (connp->out_buf != NULL) {
+ free(connp->out_buf);
+ }
+
+ htp_connp_destroy_decompressors(connp);
+
+ if (connp->put_file != NULL) {
+ bstr_free(connp->put_file->filename);
+ free(connp->put_file);
+ }
+
+ if (connp->in_header) {
+ bstr_free(connp->in_header);
+ connp->in_header = NULL;
+ }
+ if (connp->out_header) {
+ bstr_free(connp->out_header);
+ connp->out_header = NULL;
+ }
+ free(connp);
+}
+
+void htp_connp_destroy_all(htp_connp_t *connp) {
+ if (connp == NULL) return;
+
+ // Destroy connection
+ htp_conn_destroy(connp->conn);
+ connp->conn = NULL;
+
+ // Destroy everything else
+ htp_connp_destroy(connp);
+}
+
+htp_conn_t *htp_connp_get_connection(const htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+ return connp->conn;
+}
+
+htp_tx_t *htp_connp_get_in_tx(const htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+ return connp->in_tx;
+}
+
+htp_log_t *htp_connp_get_last_error(const htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+ return connp->last_error;
+}
+
+htp_tx_t *htp_connp_get_out_tx(const htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+ return connp->out_tx;
+}
+
+void *htp_connp_get_user_data(const htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+ return (void *)connp->user_data;
+}
+
+void htp_connp_in_reset(htp_connp_t *connp) {
+ if (connp == NULL) return;
+ connp->in_content_length = -1;
+ connp->in_body_data_left = -1;
+ connp->in_chunk_request_index = connp->in_chunk_count;
+}
+
+void htp_connp_open(htp_connp_t *connp, const char *client_addr, int client_port, const char *server_addr,
+ int server_port, htp_time_t *timestamp)
+{
+ if (connp == NULL) return;
+
+ // Check connection parser state first.
+ if ((connp->in_status != HTP_STREAM_NEW) || (connp->out_status != HTP_STREAM_NEW)) {
+ htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Connection is already open");
+ return;
+ }
+
+ if (htp_conn_open(connp->conn, client_addr, client_port, server_addr, server_port, timestamp) != HTP_OK) {
+ return;
+ }
+
+ connp->in_status = HTP_STREAM_OPEN;
+ connp->out_status = HTP_STREAM_OPEN;
+}
+
+void htp_connp_set_user_data(htp_connp_t *connp, const void *user_data) {
+ if (connp == NULL) return;
+ connp->user_data = user_data;
+}
+
+htp_tx_t *htp_connp_tx_create(htp_connp_t *connp) {
+ if (connp == NULL) return NULL;
+
+ // Detect pipelining.
+ if (htp_list_size(connp->conn->transactions) > connp->out_next_tx_index) {
+ connp->conn->flags |= HTP_CONN_PIPELINED;
+ }
+ if (connp->cfg->max_tx > 0 &&
+ htp_list_size(connp->conn->transactions) > connp->cfg->max_tx) {
+ return NULL;
+ }
+
+ htp_tx_t *tx = htp_tx_create(connp);
+ if (tx == NULL) return NULL;
+
+ connp->in_tx = tx;
+
+ htp_connp_in_reset(connp);
+
+ return tx;
+}
+
+/**
+ * Removes references to the supplied transaction.
+ *
+ * @param[in] connp
+ * @param[in] tx
+ */
+void htp_connp_tx_remove(htp_connp_t *connp, htp_tx_t *tx) {
+ if (connp == NULL) return;
+
+ if (connp->in_tx == tx) {
+ connp->in_tx = NULL;
+ }
+
+ if (connp->out_tx == tx) {
+ connp->out_tx = NULL;
+ }
+}
+
+/**
+ * Removes all front NULL-ed transactions
+ *
+ * @param[in] connp
+ * @return numbers of removed NULL transactions
+ */
+size_t htp_connp_tx_freed(htp_connp_t *connp) {
+ // Transactions first got freed and NULLed
+ // Now, we can recycle the space that hold them by shifting the list
+ size_t r = 0;
+ size_t nb = htp_list_size(connp->conn->transactions);
+ for (size_t i = 0; i < nb; i++) {
+ // 0 and not i because at next iteration, we have removed the first
+ void * tx = htp_list_get(connp->conn->transactions, 0);
+ if (tx != NULL) {
+ break;
+ }
+ htp_list_shift(connp->conn->transactions);
+ r++;
+ connp->out_next_tx_index--;
+ }
+ return r;
+}