diff --git a/CMakeLists.txt b/CMakeLists.txt index ac156f2..b24b08d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ endif() if (NOT HAVE_SYS_TREE) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compat/sys/tree.h.in - ${CMAKE_CURRENT_BINARY_DIR}/compat/sys/tree.h) + ${PROJECT_BINARY_DIR}/compat/sys/tree.h) include_directories(${PROJECT_BINARY_DIR}/compat) @@ -103,7 +103,9 @@ endif(NOT HAVE_SYS_TREE) if (NOT HAVE_SYS_QUEUE) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compat/sys/queue.h.in - ${CMAKE_CURRENT_BINARY_DIR}/compat/sys/queue.h) + ${PROJECT_BINARY_DIR}/compat/sys/queue.h) + + include_directories(${PROJECT_BINARY_DIR}/compat) endif(NOT HAVE_SYS_QUEUE) if (NOT HAVE_STRNDUP) diff --git a/ChangeLog b/ChangeLog index 43be2b6..2484c21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +v1.3.12-pre3 + o use PROJECT_BINARY_DIR for sys/ compat headers (012341c Nathan French) + o return int for htp__path_new_ (bf59eb1 Nathan French) + o more return normalization (91008a6 Nathan French) + o allocation functions set *out to NULL (0305c10 Nathan French) + o do not return on error from requie_uri (ddc2ce6 Nathan French) + o added user-defined custom memory functions (73b54c6 Nathan French) + o for some reason, htparser_init was being called manually with type_request?? (a153e5f Nathan French) + o Add htp__strndup_ memfn wrapper (763168c Nathan French) + o add a callback member in evhtp_ssl_cfg_t for customized decrypt privfile. fixes #16 (b3a4d42 h00360646) + v1.2.12-pre2 o Internalize some structs / deprecate evhtp_set_hook() (50ab327 Nathan French) o remove cruft (1b1a037 Nathan French) diff --git a/evhtp.c b/evhtp.c index 37a3cd0..ece5ac8 100644 --- a/evhtp.c +++ b/evhtp.c @@ -137,6 +137,111 @@ htp_log_connection(evhtp_connection_t * c) (var) = (tvar)) #endif +#ifndef EVHTP_DISABLE_MEMFUNCTIONS + +static void * (*malloc_)(size_t sz) = malloc; +static void * (* realloc_)(void * d, size_t sz) = realloc; +static void (* free_)(void * d) = free; + +static void * +htp__malloc_(size_t size) +{ + return malloc_(size); +} + +static void * +htp__realloc_(void * ptr, size_t size) +{ + return realloc_(ptr, size); +} + +static void +htp__free_(void * ptr) +{ + return free_(ptr); +} + +static void * +htp__calloc_(size_t nmemb, size_t size) +{ + if (malloc_ != malloc) + { + size_t len = nmemb * size; + void * p; + + if ((p = malloc_(len)) != NULL) + { + memset(p, 0, len); + } + + return p; + } + + return calloc(nmemb, size); +} + +static char * +htp__strdup_(const char * str) +{ + if (malloc_ != malloc) + { + size_t len = strlen(str); + void * p; + + if ((p = malloc_(len + 1)) != NULL) + { + memcpy(p, str, len + 1); + } + + return p; + } + + return strdup(str); +} + +static char * +htp__strndup_(const char * str, size_t len) +{ + if (malloc_ != malloc) + { + char * p; + + if ((p = malloc_(len + 1)) != NULL) + { + memcpy(p, str, len + 1); + } + + p[len] = '\0'; + + return p; + } + + return strndup(str, len); +} + +#else +#define htp__malloc_(sz) malloc(sz) +#define htp__calloc_(n, sz) calloc(n, sz) +#define htp__strdup_(s) strdup(s) +#define htp__strndup_(n, sz) strndup(n, sz) +#define htp__realloc_(p, sz) realloc(p, sz) +#define htp__free_(p) free(p) +#endif + +void +evhtp_set_mem_functions(void *(*mallocfn_)(size_t len), + void *(*reallocfn_)(void * p, size_t sz), + void (* freefn_)(void * p)) +{ +#ifndef EVHTP_DISABLE_MEMFUNCTIONS + malloc_ = mallocfn_; + realloc_ = reallocfn_; + free_ = freefn_; + + return event_set_mem_functions(malloc_, realloc_, free_); +#endif +} + static const char * status_code_to_str(evhtp_res code) { @@ -279,10 +384,10 @@ strndup(const char * s, size_t n) if (len < n) { - return strdup(s); + return htp__strdup_(s); } - ret = malloc(n + 1); + ret = htp__malloc_(n + 1); ret[n] = '\0'; memcpy(ret, s, n); @@ -715,38 +820,42 @@ htp__callback_find_(evhtp_callbacks_t * cbs, * @details if for example the input was "/a/b/c", the parser will * consider "/a/b/" as the path, and "c" as the file. * + * @param the unallocated destination buffer. * @param data raw input data (assumes a /path/[file] structure) * @param len length of the input data * - * @return evhtp_request_t * on success, NULL on error. + * @return 0 on success, -1 on error. */ -static evhtp_path_t * -htp__path_new_(const char * data, size_t len) +static int +htp__path_new_(evhtp_path_t ** out, const char * data, size_t len) { evhtp_path_t * req_path; const char * data_end = (const char *)(data + len); char * path = NULL; char * file = NULL; - req_path = calloc(sizeof(evhtp_path_t), 1); + + req_path = htp__calloc_(1, sizeof(*req_path)); evhtp_alloc_assert(req_path); + *out = NULL; + if (evhtp_unlikely(len == 0)) { /* * odd situation here, no preceding "/", so just assume the path is "/" */ - path = strdup("/"); + path = htp__strdup_("/"); evhtp_alloc_assert(path); } else if (*data != '/') { /* request like GET stupid HTTP/1.0, treat stupid as the file, and * assume the path is "/" */ - path = strdup("/"); - file = strndup(data, len); - + path = htp__strdup_("/"); evhtp_alloc_assert(path); + + file = htp__strndup_(data, len); evhtp_alloc_assert(file); } else { if (data[len - 1] != '/') @@ -774,23 +883,23 @@ htp__path_new_(const char * data, size_t len) /* check for overflow */ if ((const char *)(data + path_len) > data_end) { - evhtp_safe_free(req_path, free); + evhtp_safe_free(req_path, htp__free_); - return NULL; + return -1; } /* check for overflow */ if ((const char *)(&data[i + 1] + file_len) > data_end) { - evhtp_safe_free(req_path, free); + evhtp_safe_free(req_path, htp__free_); - return NULL; + return -1; } - path = strndup(data, path_len); - file = strndup(&data[i + 1], file_len); - + path = htp__strndup_(data, path_len); evhtp_alloc_assert(path); + + file = htp__strndup_(&data[i + 1], file_len); evhtp_alloc_assert(file); break; @@ -800,27 +909,27 @@ htp__path_new_(const char * data, size_t len) if (i == 0 && data[i] == '/' && !file && !path) { /* drops here if the request is something like GET /foo */ - path = strdup("/"); + path = htp__strdup_("/"); evhtp_alloc_assert(path); if (len > 1) { - file = strndup((const char *)(data + 1), len); + file = htp__strndup_((const char *)(data + 1), len); evhtp_alloc_assert(file); } } } else { /* the last character is a "/", thus the request is just a path */ - path = strndup(data, len); + path = htp__strndup_(data, len); evhtp_alloc_assert(path); } } if (len != 0) { - req_path->full = strndup(data, len); + req_path->full = htp__strndup_(data, len); } else { - req_path->full = strdup("/"); + req_path->full = htp__strdup_("/"); } evhtp_alloc_assert(req_path->full); @@ -828,7 +937,9 @@ htp__path_new_(const char * data, size_t len) req_path->path = path; req_path->file = file; - return req_path; + *out = req_path; + + return 0; } /* htp__path_new_ */ static void @@ -839,31 +950,28 @@ htp__path_free_(evhtp_path_t * path) return; } - evhtp_safe_free(path->full, free); - evhtp_safe_free(path->path, free); - evhtp_safe_free(path->file, free); - evhtp_safe_free(path->match_start, free); - evhtp_safe_free(path->match_end, free); + evhtp_safe_free(path->full, htp__free_); + evhtp_safe_free(path->path, htp__free_); + evhtp_safe_free(path->file, htp__free_); + evhtp_safe_free(path->match_start, htp__free_); + evhtp_safe_free(path->match_end, htp__free_); - evhtp_safe_free(path, free); + evhtp_safe_free(path, htp__free_); } /** * @brief create an authority structure * - * @return evhtp_authority_t + * @return 0 on success, -1 on error */ -static evhtp_authority_t * -htp__authority_new_(void) +static int +htp__authority_new_(evhtp_authority_t ** out) { evhtp_authority_t * authority; - if (!(authority = calloc(1, sizeof(*authority)))) - { - return NULL; - } + *out = htp__calloc_(1, sizeof(*authority)); - return authority; + return (*out != NULL) ? 0 : -1; } /** @@ -879,11 +987,11 @@ htp__authority_free_(evhtp_authority_t * authority) return; } - evhtp_safe_free(authority->username, free); - evhtp_safe_free(authority->password, free); - evhtp_safe_free(authority->hostname, free); + evhtp_safe_free(authority->username, htp__free_); + evhtp_safe_free(authority->password, htp__free_); + evhtp_safe_free(authority->hostname, htp__free_); - evhtp_safe_free(authority, free); + evhtp_safe_free(authority, htp__free_); } /** @@ -903,37 +1011,40 @@ htp__uri_free_(evhtp_uri_t * uri) evhtp_safe_free(uri->path, htp__path_free_); evhtp_safe_free(uri->authority, htp__authority_free_); - evhtp_safe_free(uri->fragment, free); - evhtp_safe_free(uri->query_raw, free); + evhtp_safe_free(uri->fragment, htp__free_); + evhtp_safe_free(uri->query_raw, htp__free_); - evhtp_safe_free(uri, free); + evhtp_safe_free(uri, htp__free_); } /** * @brief create an overlay URI structure * - * @return evhtp_uri_t + * @return 0 on success, -1 on error. */ -static evhtp_uri_t * -htp__uri_new_(void) +static int +htp__uri_new_(evhtp_uri_t ** out) { evhtp_uri_t * uri; - if (!(uri = calloc(sizeof(evhtp_uri_t), 1))) + *out = NULL; + + if ((uri = htp__calloc_(1, sizeof(*uri))) == NULL) { - return NULL; + return -1; } - uri->authority = htp__authority_new_(); + uri->authority = NULL; - if (!uri->authority) + if (htp__authority_new_(&uri->authority) == -1) { - htp__uri_free_(uri); - - return NULL; + evhtp_safe_free(uri, htp__uri_free_); + return -1; } - return uri; + *out = uri; + + return 0; } /** @@ -970,8 +1081,8 @@ htp__request_free_(evhtp_request_t * request) evhtp_safe_free(request->buffer_out, evbuffer_free); } - evhtp_safe_free(request->hooks, free); - evhtp_safe_free(request, free); + evhtp_safe_free(request->hooks, htp__free_); + evhtp_safe_free(request, htp__free_); } /** @@ -987,7 +1098,7 @@ htp__request_new_(evhtp_connection_t * c) evhtp_request_t * req; uint8_t error; - if (evhtp_unlikely(!(req = calloc(sizeof(evhtp_request_t), 1)))) + if (evhtp_unlikely(!(req = htp__calloc_(sizeof(evhtp_request_t), 1)))) { return NULL; } @@ -1008,12 +1119,12 @@ htp__request_new_(evhtp_connection_t * c) break; } - if (evhtp_unlikely(!(req->headers_in = malloc(sizeof(evhtp_headers_t))))) + if (evhtp_unlikely(!(req->headers_in = htp__malloc_(sizeof(evhtp_headers_t))))) { break; } - if (evhtp_unlikely(!(req->headers_out = malloc(sizeof(evhtp_headers_t))))) + if (evhtp_unlikely(!(req->headers_out = htp__malloc_(sizeof(evhtp_headers_t))))) { break; } @@ -1112,7 +1223,7 @@ htp__request_parse_args_(htparser * p, const char * data, size_t len) frag_offset += 1; fraglen = len - frag_offset; - uri->fragment = malloc(fraglen + 1); + uri->fragment = htp__malloc_(fraglen + 1); evhtp_alloc_assert(uri->fragment); memcpy(uri->fragment, fragment, fraglen); @@ -1131,7 +1242,7 @@ htp__request_parse_args_(htparser * p, const char * data, size_t len) return -1; } - uri->query_raw = malloc(len + 1); + uri->query_raw = htp__malloc_(len + 1); evhtp_alloc_assert(uri->query_raw); memcpy(uri->query_raw, data, len); @@ -1160,7 +1271,7 @@ htp__request_parse_header_key_(htparser * p, const char * data, size_t len) char * key_s; evhtp_header_t * hdr; - key_s = malloc(len + 1); + key_s = htp__malloc_(len + 1); evhtp_alloc_assert(key_s); key_s[len] = '\0'; @@ -1185,7 +1296,7 @@ htp__request_parse_header_val_(htparser * p, const char * data, size_t len) char * val_s; evhtp_header_t * header; - val_s = malloc(len + 1); + val_s = htp__malloc_(len + 1); evhtp_alloc_assert(val_s); val_s[len] = '\0'; @@ -1193,7 +1304,7 @@ htp__request_parse_header_val_(htparser * p, const char * data, size_t len) if ((header = evhtp_header_val_add(c->request->headers_in, val_s, 0)) == NULL) { - evhtp_safe_free(val_s, free); + evhtp_safe_free(val_s, htp__free_); c->request->status = EVHTP_RES_FATAL; return -1; @@ -1311,13 +1422,13 @@ htp__request_set_callbacks_(evhtp_request_t * request) if (path->match_start == NULL) { - path->match_start = calloc(strlen(path->full) + 1, 1); + path->match_start = htp__calloc_(strlen(path->full) + 1, 1); evhtp_alloc_assert(path->match_start); } if (path->match_end == NULL) { - path->match_end = calloc(strlen(path->full) + 1, 1); + path->match_end = htp__calloc_(strlen(path->full) + 1, 1); evhtp_alloc_assert(path->match_end); } @@ -1341,7 +1452,7 @@ htp__request_set_callbacks_(evhtp_request_t * request) { if (request->hooks == NULL) { - request->hooks = malloc(sizeof(evhtp_hooks_t)); + request->hooks = htp__malloc_(sizeof(evhtp_hooks_t)); evhtp_alloc_assert(request->hooks); } @@ -1414,10 +1525,9 @@ htp__request_parse_hostname_(htparser * p, const char * data, size_t len) static int htp__require_uri_(evhtp_connection_t * c) { - if (c && c->request && !c->request->uri) + if (c != NULL && c->request != NULL && c->request->uri == NULL) { - c->request->uri = htp__uri_new_(); - evhtp_alloc_assert(c->request->uri); + evhtp_assert(htp__uri_new_(&c->request->uri) == 0); } return 0; @@ -1429,15 +1539,15 @@ htp__request_parse_host_(htparser * p, const char * data, size_t len) evhtp_connection_t * c = htparser_get_userdata(p); evhtp_authority_t * authority; - if (htp__require_uri_(c) != 0) + if (htp__require_uri_(c) == -1) { return -1; } authority = c->request->uri->authority; - authority->hostname = malloc(len + 1); + authority->hostname = htp__malloc_(len + 1); - if (!authority->hostname) + if (authority->hostname == NULL) { c->request->status = EVHTP_RES_FATAL; @@ -1458,7 +1568,7 @@ htp__request_parse_port_(htparser * p, const char * data, size_t len) char * endptr; unsigned long port; - if (htp__require_uri_(c) != 0) + if (htp__require_uri_(c) == -1) { return -1; } @@ -1484,12 +1594,12 @@ htp__request_parse_path_(htparser * p, const char * data, size_t len) evhtp_connection_t * c = htparser_get_userdata(p); evhtp_path_t * path; - if (htp__require_uri_(c) != 0) + if (htp__require_uri_(c) == -1) { return -1; } - if (evhtp_unlikely(!(path = htp__path_new_(data, len)))) + if (htp__path_new_(&path, data, len) == -1) { c->request->status = EVHTP_RES_FATAL; @@ -1715,7 +1825,7 @@ htp__request_parse_fini_(htparser * p) body_len = evbuffer_get_length(buf_in); body = (const char *)evbuffer_pullup(buf_in, body_len); - uri->query_raw = calloc(body_len + 1, 1); + uri->query_raw = htp__calloc_(body_len + 1, 1); evhtp_alloc_assert(uri->query_raw); memcpy(uri->query_raw, body, body_len); @@ -2054,7 +2164,7 @@ htp__connection_writecb_(struct bufferevent * bev, void * arg) c->htp = orig_htp; } - htparser_init(c->parser, htp_type_request); + htparser_init(c->parser, c->type); htparser_set_userdata(c->parser, c); return; @@ -2302,7 +2412,7 @@ htp__connection_new_(evhtp_t * htp, evutil_socket_t sock, evhtp_type type) return NULL; } - connection = calloc(sizeof(evhtp_connection_t), 1); + connection = htp__calloc_(sizeof(evhtp_connection_t), 1); evhtp_alloc_assert(connection); connection->scratch_buf = evbuffer_new(); @@ -2398,7 +2508,7 @@ htp__accept_cb_(struct evconnlistener * serv, int fd, struct sockaddr * s, int s htp_log_debug("fd = %d, conn = %p", fd, connection); - connection->saddr = malloc(sl); + connection->saddr = htp__malloc_(sl); evhtp_alloc_assert(connection->saddr); memcpy(connection->saddr, s, sl); @@ -2694,7 +2804,7 @@ evhtp_header_val_add(evhtp_headers_t * headers, const char * val, char valloc) if (valloc == 1) { - header->val = malloc(header->vlen + 1); + header->val = htp__malloc_(header->vlen + 1); header->val[header->vlen] = '\0'; memcpy(header->val, val, header->vlen); } else { @@ -2711,7 +2821,7 @@ evhtp_kvs_new(void) { evhtp_kvs_t * kvs; - kvs = malloc(sizeof(evhtp_kvs_t)); + kvs = htp__malloc_(sizeof(evhtp_kvs_t)); evhtp_alloc_assert(kvs); TAILQ_INIT(kvs); @@ -2724,7 +2834,7 @@ evhtp_kv_new(const char * key, const char * val, char kalloc, char valloc) { evhtp_kv_t * kv; - kv = malloc(sizeof(evhtp_kv_t)); + kv = htp__malloc_(sizeof(evhtp_kv_t)); evhtp_alloc_assert(kv); kv->k_heaped = kalloc; @@ -2742,9 +2852,9 @@ evhtp_kv_new(const char * key, const char * val, char kalloc, char valloc) { char * s; - if (!(s = malloc(kv->klen + 1))) + if (!(s = htp__malloc_(kv->klen + 1))) { - evhtp_safe_free(kv, free); + evhtp_safe_free(kv, htp__free_); return NULL; } @@ -2764,7 +2874,7 @@ evhtp_kv_new(const char * key, const char * val, char kalloc, char valloc) if (valloc == 1) { - char * s = malloc(kv->vlen + 1); + char * s = htp__malloc_(kv->vlen + 1); s[kv->vlen] = '\0'; memcpy(s, val, kv->vlen); @@ -2787,15 +2897,15 @@ evhtp_kv_free(evhtp_kv_t * kv) if (kv->k_heaped) { - evhtp_safe_free(kv->key, free); + evhtp_safe_free(kv->key, htp__free_); } if (kv->v_heaped) { - evhtp_safe_free(kv->val, free); + evhtp_safe_free(kv->val, htp__free_); } - evhtp_safe_free(kv, free); + evhtp_safe_free(kv, htp__free_); } void @@ -2834,7 +2944,7 @@ evhtp_kvs_free(evhtp_kvs_t * kvs) evhtp_safe_free(kv, evhtp_kv_free); } - evhtp_safe_free(kvs, free); + evhtp_safe_free(kvs, htp__free_); } int @@ -2989,15 +3099,11 @@ evhtp_unescape_string(unsigned char ** out, unsigned char * str, size_t str_len) size_t i; enum unscape_state state; - if (out == NULL || *out == NULL) - { - return -1; - } - state = unscape_state_start; optr = *out; sptr = str; d = 0; + *out = NULL; for (i = 0; i < str_len; i++) { @@ -3062,7 +3168,7 @@ evhtp_unescape_string(unsigned char ** out, unsigned char * str, size_t str_len) } /* evhtp_unescape_string */ evhtp_query_t * -evhtp_parse_query_wflags(const char * query, size_t len, int flags) +evhtp_parse_query_wflags(const char * query, const size_t len, const int flags) { evhtp_query_t * query_args; query_parser_state state; @@ -3089,10 +3195,10 @@ evhtp_parse_query_wflags(const char * query, size_t len, int flags) char * key_buf; char * val_buf; - key_buf = malloc(len + 1); + key_buf = htp__malloc_(len + 1); evhtp_alloc_assert(key_buf); - val_buf = malloc(len + 1); + val_buf = htp__malloc_(len + 1); evhtp_alloc_assert(val_buf); #endif @@ -3311,15 +3417,15 @@ evhtp_parse_query_wflags(const char * query, size_t len, int flags) } #ifndef EVHTP_HAS_C99 - evhtp_safe_free(key_buf, free); - evhtp_safe_free(val_buf, free); + evhtp_safe_free(key_buf, htp__free_); + evhtp_safe_free(val_buf, htp__free_); #endif return query_args; error: #ifndef EVHTP_HAS_C99 - evhtp_safe_free(key_buf, free); - evhtp_safe_free(val_buf, free); + evhtp_safe_free(key_buf, htp__free_); + evhtp_safe_free(val_buf, htp__free_); #endif evhtp_query_free(query_args); @@ -3376,7 +3482,7 @@ evhtp_send_reply(evhtp_request_t * request, evhtp_res code) struct evbuffer * reply_buf; struct bufferevent * bev; - c = evhtp_request_get_connection(request); + c = request->conn; HTP_FLAG_ON(request, EVHTP_REQ_FLAG_FINISHED); @@ -3387,7 +3493,7 @@ evhtp_send_reply(evhtp_request_t * request, evhtp_res code) return; } - bev = evhtp_connection_get_bev(c); + bev = c->bev; bufferevent_lock(bev); { @@ -3396,7 +3502,6 @@ evhtp_send_reply(evhtp_request_t * request, evhtp_res code) bufferevent_unlock(bev); evbuffer_drain(reply_buf, -1); - /* evbuffer_free(reply_buf); */ } int @@ -3760,7 +3865,7 @@ evhtp_callbacks_free(evhtp_callbacks_t * callbacks) evhtp_safe_free(callback, evhtp_callback_free); } - evhtp_safe_free(callbacks, free); + evhtp_safe_free(callbacks, htp__free_); } evhtp_callback_t * @@ -3768,7 +3873,7 @@ evhtp_callback_new(const char * path, evhtp_callback_type type, evhtp_callback_c { evhtp_callback_t * hcb; - hcb = calloc(sizeof(evhtp_callback_t), 1); + hcb = htp__calloc_(sizeof(evhtp_callback_t), 1); evhtp_alloc_assert(hcb); hcb->type = type; @@ -3777,26 +3882,26 @@ evhtp_callback_new(const char * path, evhtp_callback_type type, evhtp_callback_c switch (type) { case evhtp_callback_type_hash: - hcb->val.path = strdup(path); + hcb->val.path = htp__strdup_(path); break; #ifndef EVHTP_DISABLE_REGEX case evhtp_callback_type_regex: - hcb->val.regex = malloc(sizeof(regex_t)); + hcb->val.regex = htp__malloc_(sizeof(regex_t)); if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0) { - evhtp_safe_free(hcb->val.regex, free); - evhtp_safe_free(hcb, free); + evhtp_safe_free(hcb->val.regex, htp__free_); + evhtp_safe_free(hcb, htp__free_); return NULL; } break; #endif case evhtp_callback_type_glob: - hcb->val.glob = strdup(path); + hcb->val.glob = htp__strdup_(path); break; default: - evhtp_safe_free(hcb, free); + evhtp_safe_free(hcb, htp__free_); return NULL; } /* switch */ @@ -3814,25 +3919,25 @@ evhtp_callback_free(evhtp_callback_t * callback) switch (callback->type) { case evhtp_callback_type_hash: - evhtp_safe_free(callback->val.path, free); + evhtp_safe_free(callback->val.path, htp__free_); break; case evhtp_callback_type_glob: - evhtp_safe_free(callback->val.glob, free); + evhtp_safe_free(callback->val.glob, htp__free_); break; #ifndef EVHTP_DISABLE_REGEX case evhtp_callback_type_regex: regfree(callback->val.regex); - evhtp_safe_free(callback->val.regex, free); + evhtp_safe_free(callback->val.regex, htp__free_); break; #endif } if (callback->hooks) { - evhtp_safe_free(callback->hooks, free); + evhtp_safe_free(callback->hooks, htp__free_); } - evhtp_safe_free(callback, free); + evhtp_safe_free(callback, htp__free_); return; } @@ -3850,7 +3955,7 @@ htp__set_hook_(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void { if (*hooks == NULL) { - if (!(*hooks = calloc(sizeof(evhtp_hooks_t), 1))) + if (!(*hooks = htp__calloc_(sizeof(evhtp_hooks_t), 1))) { return -1; } @@ -4074,7 +4179,7 @@ evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg) if (htp->callbacks == NULL) { - if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) + if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1))) { htp__unlock_(htp); @@ -4201,7 +4306,7 @@ evhtp_use_callback_locks(evhtp_t * htp) return -1; } - if (!(htp->lock = malloc(sizeof(pthread_mutex_t)))) + if (!(htp->lock = htp__malloc_(sizeof(pthread_mutex_t)))) { return -1; } @@ -4221,7 +4326,7 @@ evhtp_set_regex_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, vo if (htp->callbacks == NULL) { - if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) + if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1))) { htp__unlock_(htp); @@ -4262,7 +4367,7 @@ evhtp_set_glob_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, voi if (htp->callbacks == NULL) { - if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) + if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1))) { htp__unlock_(htp); @@ -4328,8 +4433,8 @@ evhtp_ssl_use_threads(void) ssl_locks_initialized = 1; ssl_num_locks = CRYPTO_num_locks(); - if ((ssl_locks = calloc(ssl_num_locks, - sizeof(evhtp_mutex_t))) == NULL) + if ((ssl_locks = htp__calloc_(ssl_num_locks, + sizeof(evhtp_mutex_t))) == NULL) { return -1; } @@ -4480,8 +4585,25 @@ evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg) } /* switch */ SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM); - SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, - cfg->privfile ? cfg->privfile : cfg->pemfile, SSL_FILETYPE_PEM); + + char * const key = cfg->privfile ? cfg->privfile : cfg->pemfile; + + if (cfg->decrypt_cb != NULL) + { + EVP_PKEY * pkey = cfg->decrypt_cb(key); + + if (pkey == NULL) + { + return -1; + } + + SSL_CTX_use_PrivateKey(htp->ssl_ctx, pkey); + + /*cleanup */ + EVP_PKEY_free(pkey); + } else { + SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, key, SSL_FILETYPE_PEM); + } SSL_CTX_set_session_id_context(htp->ssl_ctx, (void *)&session_id_context, @@ -4635,9 +4757,9 @@ evhtp_connection_free(evhtp_connection_t * connection) htp__hook_connection_fini_(connection); evhtp_safe_free(connection->request, htp__request_free_); - evhtp_safe_free(connection->parser, free); - evhtp_safe_free(connection->hooks, free); - evhtp_safe_free(connection->saddr, free); + evhtp_safe_free(connection->parser, htp__free_); + evhtp_safe_free(connection->hooks, htp__free_); + evhtp_safe_free(connection->saddr, htp__free_); evhtp_safe_free(connection->scratch_buf, evbuffer_free); if (connection->resume_ev) @@ -4661,7 +4783,7 @@ evhtp_connection_free(evhtp_connection_t * connection) #endif } - evhtp_safe_free(connection, free); + evhtp_safe_free(connection, htp__free_); } /* evhtp_connection_free */ void @@ -4756,12 +4878,12 @@ evhtp_add_alias(evhtp_t * evhtp, const char * name) return -1; } - if (!(alias = calloc(sizeof(evhtp_alias_t), 1))) + if (!(alias = htp__calloc_(sizeof(evhtp_alias_t), 1))) { return -1; } - alias->alias = strdup(name); + alias->alias = htp__strdup_(name); evhtp_alloc_assert(alias->alias); TAILQ_INSERT_TAIL(&evhtp->aliases, alias, next); @@ -4799,7 +4921,7 @@ evhtp_add_vhost(evhtp_t * evhtp, const char * name, evhtp_t * vhost) return -1; } - if (!(vhost->server_name = strdup(name))) + if (!(vhost->server_name = htp__strdup_(name))) { return -1; } @@ -4829,21 +4951,20 @@ evhtp__new_(evhtp_t ** out, struct event_base * evbase, void * arg) { evhtp_t * htp; - if (evhtp_unlikely(out == NULL)) - { - return -1; - } if (evhtp_unlikely(evbase == NULL)) { return -1; } - if ((htp = calloc(1, sizeof(evhtp_t))) == NULL) + *out = NULL; + + if ((htp = htp__calloc_(1, sizeof(*htp))) == NULL) { return -1; } + htp->arg = arg; htp->evbase = evbase; htp->flags = EVHTP_FLAG_DEFAULTS; @@ -4907,7 +5028,7 @@ evhtp_free(evhtp_t * evhtp) if (evhtp->server_name) { - evhtp_safe_free(evhtp->server_name, free); + evhtp_safe_free(evhtp->server_name, htp__free_); } if (evhtp->callbacks) @@ -4919,14 +5040,14 @@ evhtp_free(evhtp_t * evhtp) { if (evhtp_alias->alias != NULL) { - evhtp_safe_free(evhtp_alias->alias, free); + evhtp_safe_free(evhtp_alias->alias, htp__free_); } TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next); - evhtp_safe_free(evhtp_alias, free); + evhtp_safe_free(evhtp_alias, htp__free_); } - evhtp_safe_free(evhtp, free); + evhtp_safe_free(evhtp, htp__free_); } /* evhtp_free */ /***************************************************************** @@ -5101,10 +5222,7 @@ evhtp_make_request(evhtp_connection_t * c, evhtp_request_t * r, evbuffer_add_printf(obuf, "%s %s HTTP/%s\r\n", htparser_get_methodstr_m(meth), uri, proto); - evhtp_headers_for_each( - r->headers_out, - htp__create_headers_, obuf); - + evhtp_headers_for_each(r->headers_out, htp__create_headers_, obuf); evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL); if (evbuffer_get_length(r->buffer_out)) diff --git a/evhtp.h b/evhtp.h index 7bae4e2..835164b 100644 --- a/evhtp.h +++ b/evhtp.h @@ -194,6 +194,7 @@ typedef int (* evhtp_headers_iterator)(evhtp_header_t * header, void * arg); #ifndef EVHTP_DISABLE_SSL typedef int (* evhtp_ssl_verify_cb)(int pre_verify, evhtp_x509_store_ctx_t * ctx); typedef int (* evhtp_ssl_chk_issued_cb)(evhtp_x509_store_ctx_t * ctx, evhtp_x509_t * x, evhtp_x509_t * issuer); +typedef EVP_PKEY * (* evhtp_ssl_decrypt_cb)(char * privfile); typedef int (* evhtp_ssl_scache_add)(evhtp_connection_t * connection, unsigned char * sid, int sid_len, evhtp_ssl_sess_t * sess); typedef void (* evhtp_ssl_scache_del)(evhtp_t * htp, unsigned char * sid, int sid_len); @@ -201,10 +202,10 @@ typedef evhtp_ssl_sess_t * (* evhtp_ssl_scache_get)(evhtp_connection_t * connect typedef void * (* evhtp_ssl_scache_init)(evhtp_t *); #endif -#define EVHTP_VERSION "1.2.11" +#define EVHTP_VERSION "1.2.12-pre3" #define EVHTP_VERSION_MAJOR 1 #define EVHTP_VERSION_MINOR 2 -#define EVHTP_VERSION_PATCH 11 +#define EVHTP_VERSION_PATCH 12 #define evhtp_headers_iterator evhtp_kvs_iterator @@ -519,6 +520,7 @@ struct evhtp_ssl_cfg_s { int verify_depth; evhtp_ssl_verify_cb x509_verify_cb; evhtp_ssl_chk_issued_cb x509_chk_issued_cb; + evhtp_ssl_decrypt_cb decrypt_cb; long store_flags; evhtp_ssl_scache_type scache_type; long scache_timeout; @@ -531,6 +533,11 @@ struct evhtp_ssl_cfg_s { }; #endif + +EVHTP_EXPORT void evhtp_set_mem_functions(void *(*malloc_)(size_t), + void *(*realloc_)(void *, size_t), + void (* free_)(void *)); + /** * @defgroup evhtp_core Core evhtp functions * @{