diff options
Diffstat (limited to 'examples/mod_libhtp/mod_libhtp.c')
-rw-r--r-- | examples/mod_libhtp/mod_libhtp.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/examples/mod_libhtp/mod_libhtp.c b/examples/mod_libhtp/mod_libhtp.c new file mode 100644 index 0000000..07a779c --- /dev/null +++ b/examples/mod_libhtp/mod_libhtp.c @@ -0,0 +1,161 @@ +/*************************************************************************** + * 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. + ***************************************************************************/ + +#include "httpd.h" +#include "http_config.h" +#include "http_protocol.h" +#include "ap_config.h" + +#include "htp.h" +#include "htp_transaction.h" + +module AP_MODULE_DECLARE_DATA libhtp_module; + +// XXX Handle all allocation failures + +static int convert_method_number(int method_number) { + // We can cheat here because LibHTP reuses Apache's + // method identifiers. But we really shouldn't. + if ((method_number >= 0)&&(method_number <= 26)) { + return method_number; + } + + // TODO Decouple this functions from Apache's internals. + + return HTP_M_UNKNOWN; +} + +static int convert_protocol_number(int protocol_number) { + // In Apache, 1.1 is stored as 1001. In LibHTP, + // the same protocol number is stored as 101. + return (protocol_number / 1000) * 100 + (protocol_number % 1000); +} + +static apr_status_t transaction_cleanup(htp_tx_t *tx) { + htp_tx_destroy(tx); + return APR_SUCCESS; +} + +static int libhtp_post_read_request(request_rec *r) { + htp_connp_t *connp = ap_get_module_config(r->connection->conn_config, &libhtp_module); + if (connp == NULL) return DECLINED; + + // Create a new LibHTP transaction + htp_tx_t *tx = htp_connp_tx_create(connp); + if (tx == NULL) return DECLINED; + + // Request begins + htp_tx_state_request_start(tx); + + // Populate request line + htp_tx_req_set_method_c(tx, r->method, HTP_ALLOC_REUSE); + htp_tx_req_set_method_number(tx, convert_method_number(r->method_number)); + htp_tx_req_set_uri_c(tx, r->uri, HTP_ALLOC_REUSE); + htp_tx_req_set_query_string_c(tx, r->args, HTP_ALLOC_REUSE); + htp_tx_req_set_protocol_c(tx, r->protocol, HTP_ALLOC_REUSE); + htp_tx_req_set_protocol_number(tx, convert_protocol_number(r->proto_num)); + htp_tx_req_set_protocol_0_9(tx, r->assbackwards); + + // Request line available + htp_tx_state_request_line(tx); + + // Populate request headers + size_t i; + const apr_array_header_t *arr = apr_table_elts(r->headers_in); + const apr_table_entry_t *te = (apr_table_entry_t *) arr->elts; + for (i = 0; i < arr->nelts; i++) { + htp_tx_req_set_header_c(tx, te[i].key, te[i].val, HTP_ALLOC_REUSE); + } + + // Request headers available + htp_tx_state_request_headers(tx); + + // Attach LibHTP's transaction to Apache's request + ap_set_module_config(r->request_config, &libhtp_module, tx); + apr_pool_cleanup_register(r->pool, (void *)tx, + (apr_status_t (*)(void *))transaction_cleanup, apr_pool_cleanup_null); + + return DECLINED; +} + +static apr_status_t connection_cleanup(htp_connp_t *connp) { + htp_config_destroy(connp->cfg); + htp_connp_destroy(connp); + + return APR_SUCCESS; +} + +static int libhtp_pre_connection(conn_rec *c, void *csd) { + // Configuration; normally you'd read the configuration from + // a file, or some other type of storage, but, because this is + // just an example, we have it hard-coded. + htp_cfg_t *cfg = htp_config_create(); + if (cfg == NULL) return OK; + htp_config_set_server_personality(cfg, HTP_SERVER_APACHE_2_2); + htp_config_register_urlencoded_parser(cfg); + htp_config_register_multipart_parser(cfg); + + // Connection parser + htp_connp_t *connp = htp_connp_create(cfg); + if (connp == NULL) { + htp_config_destroy(cfg); + free(connp); + return OK; + } + + // Open connection + htp_connp_open(connp, c->remote_ip, /* XXX remote port */ 0, c->local_ip, /* XXX local port */0, NULL); + + ap_set_module_config(c->conn_config, &libhtp_module, connp); + apr_pool_cleanup_register(c->pool, (void *)connp, + (apr_status_t (*)(void *))connection_cleanup, apr_pool_cleanup_null); + + return OK; +} + +static void libhtp_register_hooks(apr_pool_t *p) { + ap_hook_pre_connection(libhtp_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_read_request(libhtp_post_read_request, NULL, NULL, APR_HOOK_MIDDLE); +} + +/* Dispatch list for API hooks */ +module AP_MODULE_DECLARE_DATA libhtp_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + NULL, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + NULL, /* table of config file commands */ + libhtp_register_hooks /* register hooks */ +}; + |