/** * Creates a new hook. * * @return New htp_hook_t structure on success, NULL on failure */ htp_hook_t *hook_create(void) { htp_hook_t *hook = calloc(1, sizeof (htp_hook_t)); if (hook == NULL) return NULL; hook->callbacks = list_array_create(4); if (hook->callbacks == NULL) { free(hook); return NULL; } return hook; }
/** * Creates a new connection structure. * * @param connp * @return A new htp_connp_t structure on success, NULL on memory allocation failure. */ htp_conn_t *htp_conn_create(htp_connp_t *connp) { htp_conn_t *conn = calloc(1, sizeof (htp_conn_t)); if (conn == NULL) return NULL; conn->connp = connp; conn->transactions = list_array_create(16); if (conn->transactions == NULL) { free(conn); return NULL; } conn->messages = list_array_create(8); if (conn->messages == NULL) { list_destroy(conn->transactions); free(conn); return NULL; } return conn; }
/** * Creates a new multipart/form-data parser. * * @param boundary * @return New parser, or NULL on memory allocation failure. */ htp_mpartp_t * htp_mpartp_create(htp_connp_t *connp, char *boundary) { if ((connp == NULL)||(boundary == NULL)) return NULL; htp_mpartp_t *mpartp = calloc(1, sizeof (htp_mpartp_t)); if (mpartp == NULL) return NULL; mpartp->connp = connp; mpartp->boundary_pieces = bstr_builder_create(); if (mpartp->boundary_pieces == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->part_pieces = bstr_builder_create(); if (mpartp->part_pieces == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->parts = list_array_create(64); if (mpartp->parts == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } // Copy the boundary and convert it to lowercase mpartp->boundary_len = strlen(boundary) + 4 + 1; mpartp->boundary = malloc(mpartp->boundary_len + 1); if (mpartp->boundary == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->boundary[0] = CR; mpartp->boundary[1] = LF; mpartp->boundary[2] = '-'; mpartp->boundary[3] = '-'; size_t i = 4; while (i < mpartp->boundary_len) { mpartp->boundary[i] = tolower((int) ((unsigned char) boundary[i - 4])); i++; } mpartp->state = MULTIPART_STATE_BOUNDARY; mpartp->bpos = 2; mpartp->extract_limit = MULTIPART_DEFAULT_FILE_EXTRACT_LIMIT; mpartp->handle_data = htp_mpartp_handle_data; mpartp->handle_boundary = htp_mpartp_handle_boundary; return mpartp; }
/** * Creates a new transaction structure. * * @param cfg * @param is_cfg_shared * @param conn * @return The newly created transaction, or NULL on memory allocation failure. */ htp_tx_t *htp_tx_create(htp_cfg_t *cfg, int is_cfg_shared, htp_conn_t *conn) { htp_tx_t *tx = calloc(1, sizeof (htp_tx_t)); if (tx == NULL) return NULL; tx->conn = conn; tx->cfg = cfg; tx->is_cfg_shared = is_cfg_shared; tx->conn = conn; tx->request_header_lines = list_array_create(32); tx->request_headers = table_create(32); tx->request_line_nul_offset = -1; tx->parsed_uri = calloc(1, sizeof (htp_uri_t)); tx->parsed_uri_incomplete = calloc(1, sizeof (htp_uri_t)); tx->response_header_lines = list_array_create(32); tx->response_headers = table_create(32); tx->request_protocol_number = -1; return tx; }
/** * Called by libnids whenever it has an event we have to handle. * * @param tcp * @param user_data */ void tcp_callback (struct tcp_stream *tcp, void **user_data) { stream_data *sd = *user_data; // New connection if (tcp->nids_state == NIDS_JUST_EST) { tcp->client.collect++; tcp->server.collect++; tcp->server.collect_urg++; tcp->client.collect_urg++; // Allocate custom per-stream data sd = calloc(1, sizeof(stream_data)); sd->id = counter++; sd->direction = -1; sd->fd = -1; sd->log_level = -1; sd->chunks = list_array_create(16); sd->inbound_chunks = list_array_create(16); sd->outbound_chunks = list_array_create(16); sd->req_count = 1; // Init LibHTP parser sd->connp = htp_connp_create(cfg); if (sd->connp == NULL) { fprintf(stderr, "Failed to create LibHTP parser instance.\n"); exit(1); } // Associate TCP stream information with the HTTP connection parser htp_connp_set_user_data(sd->connp, sd); // Associate TCP stream information with the libnids structures *user_data = sd; return; } // Connection close if (tcp->nids_state == NIDS_CLOSE) { if (sd == NULL) return; // Destroy parser htp_connp_destroy_all(sd->connp); // Free custom per-stream data free_stream_data(sd); return; } // Connection close (RST) if (tcp->nids_state == NIDS_RESET) { if (sd == NULL) return; // Destroy parser htp_connp_destroy_all(sd->connp); // Free custom per-stream data free_stream_data(sd); return; } if (tcp->nids_state == NIDS_DATA) { struct half_stream *hlf; int direction; if (tcp->client.count_new) { hlf = &tcp->client; direction = DIRECTION_SERVER; } else { hlf = &tcp->server; direction = DIRECTION_CLIENT; } if (sd == NULL) return; if (sd->direction == -1) { sd->direction = direction; } // Write data to disk or store for later if (sd->fd == -1) { // Store data, as we may need it later chunk_t *chunk = calloc(1, sizeof(chunk_t)); // TODO chunk->direction = direction; chunk->data = malloc(hlf->count_new); // TODO chunk->len = hlf->count_new; memcpy(chunk->data, hlf->data, chunk->len); list_add(sd->chunks, chunk); } else { // No need to store, write directly to file if (sd->chunk_counter != 0) { write(sd->fd, "\r\n", 2); } if (sd->direction == direction) { write(sd->fd, ">>>\r\n", 5); } else { write(sd->fd, "<<<\r\n", 5); } write(sd->fd, hlf->data, hlf->count_new); sd->chunk_counter++; } // Process data process_stream_data(sd, direction, hlf); return; } }