Libevhtp  1.2.13
evhtp.c
Go to the documentation of this file.
1 
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdint.h>
10 #include <errno.h>
11 #include <signal.h>
12 #include <strings.h>
13 #include <inttypes.h>
14 #ifndef WIN32
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <netinet/tcp.h>
18 #include <arpa/inet.h>
19 #else
20 #define WINVER 0x0501
21 #include <winsock2.h>
22 #include <ws2tcpip.h>
23 #endif
24 #ifndef NO_SYS_UN
25 #include <sys/un.h>
26 #endif
27 
28 #include <limits.h>
29 #include <event2/dns.h>
30 
31 #include "internal.h"
32 #include "numtoa.h"
33 #include "evhtp/evhtp.h"
34 
35 #include "log.h"
36 
54  void * cbarg;
55  evhtp_hooks_t * hooks;
56  size_t len;
57 
58  union {
59  char * path;
60  char * glob;
61 #ifndef EVHTP_DISABLE_REGEX
62  regex_t * regex;
63 #endif
64  } val;
65 
66  TAILQ_ENTRY(evhtp_callback_s) next;
67 };
68 
69 TAILQ_HEAD(evhtp_callbacks_s, evhtp_callback_s);
70 
71 #define SET_BIT(VAR, FLAG) VAR |= FLAG
72 #define UNSET_BIT(VAR, FLAG) VAR &= ~FLAG
73 
74 #define HTP_FLAG_ON(PRE, FLAG) SET_BIT(PRE->flags, FLAG)
75 #define HTP_FLAG_OFF(PRE, FLAG) UNSET_BIT(PRE->flags, FLAG)
76 
77 #define HOOK_AVAIL(var, hook_name) (var->hooks && var->hooks->hook_name)
78 #define HOOK_FUNC(var, hook_name) (var->hooks->hook_name)
79 #define HOOK_ARGS(var, hook_name) var->hooks->hook_name ## _arg
80 
81 #define HOOK_REQUEST_RUN(request, hook_name, ...) do { \
82  if (HOOK_AVAIL(request, hook_name)) \
83  { \
84  return HOOK_FUNC(request, hook_name) (request, __VA_ARGS__, \
85  HOOK_ARGS(request, hook_name)); \
86  } \
87  \
88  if (request->conn && HOOK_AVAIL(request->conn, hook_name)) \
89  { \
90  return HOOK_FUNC(request->conn, hook_name) (request, __VA_ARGS__, \
91  HOOK_ARGS(request->conn, hook_name)); \
92  } \
93 } while (0)
94 
95 #define HOOK_REQUEST_RUN_NARGS(__request, hook_name) do { \
96  if (HOOK_AVAIL(__request, hook_name)) \
97  { \
98  return HOOK_FUNC(__request, hook_name) (__request, \
99  HOOK_ARGS(__request, hook_name)); \
100  } \
101  \
102  if (__request->conn && HOOK_AVAIL(__request->conn, hook_name)) \
103  { \
104  return HOOK_FUNC(__request->conn, hook_name) (request, \
105  HOOK_ARGS(__request->conn, hook_name)); \
106  } \
107 } while (0);
108 
109 #ifndef EVHTP_DISABLE_EVTHR
110 
115 #define htp__lock_(h) do { \
116  if (h->lock) \
117  { \
118  pthread_mutex_lock(h->lock); \
119  } \
120 } while (0)
121 
127 #define htp__unlock_(h) do { \
128  if (h->lock) \
129  { \
130  pthread_mutex_unlock(h->lock); \
131  } \
132 } while (0)
133 #else
134 #define htp__lock_(h) do { \
135 } while (0)
136 #define htp__unlock_(h) do { \
137 } while (0)
138 #endif
139 
140 #ifndef TAILQ_FOREACH_SAFE
141 #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
142  for ((var) = TAILQ_FIRST((head)); \
143  (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
144  (var) = (tvar))
145 #endif
146 
147 /* rc == request->conn. Just little things to make life easier */
148 #define rc_scratch conn->scratch_buf
149 #define rc_parser conn->parser
150 
151 /* ch_ == conn->hooks->on_... */
152 #define ch_fini_arg hooks->on_connection_fini_arg
153 #define ch_fini hooks->on_connection_fini
154 
155 /* cr_ == conn->request */
156 #define cr_status request->status
157 
158 /* rh_ == request->hooks->on_ */
159 #define rh_err hooks->on_error
160 #define rh_err_arg hooks->on_error_arg
161 
162 #ifndef EVHTP_DISABLE_MEMFUNCTIONS
163 
164 static void * (*malloc_)(size_t sz) = malloc;
165 static void * (* realloc_)(void * d, size_t sz) = realloc;
166 static void (* free_)(void * d) = free;
167 
178 static void *
179 htp__malloc_(size_t size)
180 {
181  return malloc_(size);
182 }
183 
195 static void *
196 htp__realloc_(void * ptr, size_t size)
197 {
198  return realloc_(ptr, size);
199 }
200 
210 static void
211 htp__free_(void * ptr)
212 {
213  return free_(ptr);
214 }
215 
227 static void *
228 htp__calloc_(size_t nmemb, size_t size)
229 {
230  if (malloc_ != malloc)
231  {
232  size_t len = nmemb * size;
233  void * p;
234 
235  if ((p = malloc_(len)) == NULL)
236  {
237  return NULL;
238  }
239 
240  memset(p, 0, len);
241 
242  return p;
243  }
244 
245  return calloc(nmemb, size);
246 }
247 
256 static char *
257 htp__strdup_(const char * str)
258 {
259  if (malloc_ != malloc)
260  {
261  size_t len;
262  void * p;
263 
264  len = strlen(str);
265 
266  if ((p = malloc_(len + 1)) == NULL)
267  {
268  return NULL;
269  }
270 
271  memcpy(p, str, len + 1);
272 
273  return p;
274  }
275 
276  return strdup(str);
277 }
278 
288 static char *
289 htp__strndup_(const char * str, size_t len)
290 {
291  if (malloc_ != malloc)
292  {
293  char * p;
294 
295  if ((p = malloc_(len + 1)) != NULL)
296  {
297  memcpy(p, str, len + 1);
298  } else {
299  return NULL;
300  }
301 
302  p[len] = '\0';
303 
304  return p;
305  }
306 
307  return strndup(str, len);
308 }
309 
310 #else
311 #define htp__malloc_(sz) malloc(sz)
312 #define htp__calloc_(n, sz) calloc(n, sz)
313 #define htp__strdup_(s) strdup(s)
314 #define htp__strndup_(n, sz) strndup(n, sz)
315 #define htp__realloc_(p, sz) realloc(p, sz)
316 #define htp__free_(p) free(p)
317 #endif
318 
319 
320 void
321 evhtp_set_mem_functions(void *(*mallocfn_)(size_t len),
322  void *(*reallocfn_)(void * p, size_t sz),
323  void (* freefn_)(void * p))
324 {
325 #ifndef EVHTP_DISABLE_MEMFUNCTIONS
326  malloc_ = mallocfn_;
327  realloc_ = reallocfn_;
328  free_ = freefn_;
329 
330  return event_set_mem_functions(malloc_, realloc_, free_);
331 #endif
332 }
333 
341 static const char *
343 {
344  switch (code) {
345  case EVHTP_RES_200:
346  return "OK";
347  case EVHTP_RES_300:
348  return "Redirect";
349  case EVHTP_RES_400:
350  return "Bad Request";
351  case EVHTP_RES_NOTFOUND:
352  return "Not Found";
353  case EVHTP_RES_SERVERR:
354  return "Internal Server Error";
355  case EVHTP_RES_CONTINUE:
356  return "Continue";
357  case EVHTP_RES_FORBIDDEN:
358  return "Forbidden";
359  case EVHTP_RES_SWITCH_PROTO:
360  return "Switching Protocols";
361  case EVHTP_RES_MOVEDPERM:
362  return "Moved Permanently";
363  case EVHTP_RES_PROCESSING:
364  return "Processing";
365  case EVHTP_RES_URI_TOOLONG:
366  return "URI Too Long";
367  case EVHTP_RES_CREATED:
368  return "Created";
369  case EVHTP_RES_ACCEPTED:
370  return "Accepted";
371  case EVHTP_RES_NAUTHINFO:
372  return "No Auth Info";
373  case EVHTP_RES_NOCONTENT:
374  return "No Content";
375  case EVHTP_RES_RSTCONTENT:
376  return "Reset Content";
377  case EVHTP_RES_PARTIAL:
378  return "Partial Content";
379  case EVHTP_RES_MSTATUS:
380  return "Multi-Status";
381  case EVHTP_RES_IMUSED:
382  return "IM Used";
383  case EVHTP_RES_FOUND:
384  return "Found";
385  case EVHTP_RES_SEEOTHER:
386  return "See Other";
387  case EVHTP_RES_NOTMOD:
388  return "Not Modified";
389  case EVHTP_RES_USEPROXY:
390  return "Use Proxy";
391  case EVHTP_RES_SWITCHPROXY:
392  return "Switch Proxy";
393  case EVHTP_RES_TMPREDIR:
394  return "Temporary Redirect";
395  case EVHTP_RES_UNAUTH:
396  return "Unauthorized";
397  case EVHTP_RES_PAYREQ:
398  return "Payment Required";
399  case EVHTP_RES_METHNALLOWED:
400  return "Not Allowed";
401  case EVHTP_RES_NACCEPTABLE:
402  return "Not Acceptable";
403  case EVHTP_RES_PROXYAUTHREQ:
404  return "Proxy Authentication Required";
405  case EVHTP_RES_TIMEOUT:
406  return "Request Timeout";
407  case EVHTP_RES_CONFLICT:
408  return "Conflict";
409  case EVHTP_RES_GONE:
410  return "Gone";
411  case EVHTP_RES_LENREQ:
412  return "Length Required";
413  case EVHTP_RES_PRECONDFAIL:
414  return "Precondition Failed";
415  case EVHTP_RES_ENTOOLARGE:
416  return "Entity Too Large";
417  case EVHTP_RES_URITOOLARGE:
418  return "Request-URI Too Long";
419  case EVHTP_RES_UNSUPPORTED:
420  return "Unsupported Media Type";
421  case EVHTP_RES_RANGENOTSC:
422  return "Requested Range Not Satisfiable";
423  case EVHTP_RES_EXPECTFAIL:
424  return "Expectation Failed";
425  case EVHTP_RES_IAMATEAPOT:
426  return "I'm a teapot";
427  case EVHTP_RES_NOTIMPL:
428  return "Not Implemented";
429  case EVHTP_RES_BADGATEWAY:
430  return "Bad Gateway";
431  case EVHTP_RES_SERVUNAVAIL:
432  return "Service Unavailable";
433  case EVHTP_RES_GWTIMEOUT:
434  return "Gateway Timeout";
435  case EVHTP_RES_VERNSUPPORT:
436  return "HTTP Version Not Supported";
437  case EVHTP_RES_BWEXEED:
438  return "Bandwidth Limit Exceeded";
439  } /* switch */
440 
441  return "UNKNOWN";
442 } /* status_code_to_str */
443 
444 #ifndef EVHTP_DISABLE_SSL
445 static int session_id_context = 1;
446 #ifndef EVHTP_DISABLE_EVTHR
447 static int ssl_num_locks;
449 static int ssl_locks_initialized = 0;
450 #endif
451 #endif
452 
453 /*
454  * COMPAT FUNCTIONS
455  */
456 
457 #ifdef NO_STRNLEN
458 
467 static size_t
468 strnlen(const char * s, size_t maxlen)
469 {
470  const char * e;
471  size_t n;
472 
473  for (e = s, n = 0; *e && n < maxlen; e++, n++)
474  {
475  ;
476  }
477 
478  return n;
479 }
480 
481 #endif
482 
483 #ifdef NO_STRNDUP
484 
493 static char *
494 strndup(const char * s, size_t n)
495 {
496  size_t len = strnlen(s, n);
497  char * ret;
498 
499  if (len < n)
500  {
501  return htp__strdup_(s);
502  }
503 
504  if ((ret = htp__malloc_(n + 1)) == NULL)
505  {
506  return NULL;
507  }
508 
509  ret[n] = '\0';
510 
511  memcpy(ret, s, n);
512 
513  return ret;
514 }
515 
516 #endif
517 
518 /*
519  * PRIVATE FUNCTIONS
520  */
521 
532 #define htp__is_http_11_(_major, _minor) \
533  (_major >= 1 && _minor >= 1)
534 
544 #define htp__is_http_10_(_major, _minor) \
545  (_major >= 1 && _minor <= 0)
546 
547 
557 static inline evhtp_proto
558 htp__protocol_(const char major, const char minor)
559 {
560  if (htp__is_http_10_(major, minor))
561  {
562  return EVHTP_PROTO_10;
563  }
564 
565  if (htp__is_http_11_(major, minor))
566  {
567  return EVHTP_PROTO_11;
568  }
569 
570  return EVHTP_PROTO_INVALID;
571 }
572 
581 static inline evhtp_res
582 htp__hook_path_(evhtp_request_t * request, evhtp_path_t * path)
583 {
584  HOOK_REQUEST_RUN(request, on_path, path);
585 
586  return EVHTP_RES_OK;
587 }
588 
599 static inline evhtp_res
600 htp__hook_header_(evhtp_request_t * request, evhtp_header_t * header)
601 {
602  HOOK_REQUEST_RUN(request, on_header, header);
603 
604  return EVHTP_RES_OK;
605 }
606 
616 static inline evhtp_res
617 htp__hook_headers_(evhtp_request_t * request, evhtp_headers_t * headers)
618 {
619  HOOK_REQUEST_RUN(request, on_headers, headers);
620 
621  return EVHTP_RES_OK;
622 }
623 
634 static inline evhtp_res
635 htp__hook_body_(evhtp_request_t * request, struct evbuffer * buf)
636 {
637  if (request == NULL)
638  {
639  return 500;
640  }
641 
642  HOOK_REQUEST_RUN(request, on_read, buf);
643 
644  return EVHTP_RES_OK;
645 }
646 
655 static inline evhtp_res
656 htp__hook_request_fini_(evhtp_request_t * request)
657 {
658  if (request == NULL)
659  {
660  return 500;
661  }
662 
663  HOOK_REQUEST_RUN_NARGS(request, on_request_fini);
664 
665  return EVHTP_RES_OK;
666 }
667 
675 static inline evhtp_res
676 htp__hook_chunk_new_(evhtp_request_t * request, uint64_t len)
677 {
678  HOOK_REQUEST_RUN(request, on_new_chunk, len);
679 
680  return EVHTP_RES_OK;
681 }
682 
689 static inline evhtp_res
690 htp__hook_chunk_fini_(evhtp_request_t * request)
691 {
692  HOOK_REQUEST_RUN_NARGS(request, on_chunk_fini);
693 
694  return EVHTP_RES_OK;
695 }
696 
703 static inline evhtp_res
704 htp__hook_chunks_fini_(evhtp_request_t * request)
705 {
706  HOOK_REQUEST_RUN_NARGS(request, on_chunks_fini);
707 
708  return EVHTP_RES_OK;
709 }
710 
717 static inline evhtp_res
718 htp__hook_headers_start_(evhtp_request_t * request)
719 {
720  HOOK_REQUEST_RUN_NARGS(request, on_headers_start);
721 
722  return EVHTP_RES_OK;
723 }
724 
733 static inline evhtp_res
734 htp__hook_connection_fini_(evhtp_connection_t * connection)
735 {
736  if (evhtp_unlikely(connection == NULL))
737  {
738  return 500;
739  }
740 
741  if (connection->hooks != NULL && connection->ch_fini != NULL)
742  {
743  return (connection->ch_fini)(connection, connection->ch_fini_arg);
744  }
745 
746  return EVHTP_RES_OK;
747 }
748 
755 static inline void
756 htp__hook_error_(evhtp_request_t * request, evhtp_error_flags errtype)
757 {
758  if (request && request->hooks && request->rh_err)
759  {
760  (*request->rh_err)(request, errtype, request->rh_err_arg);
761  }
762 }
763 
770 static inline evhtp_res
771 htp__hook_connection_error_(evhtp_connection_t * connection, evhtp_error_flags errtype)
772 {
773  if (connection == NULL)
774  {
775  return EVHTP_RES_FATAL;
776  }
777 
778  if (connection->request != NULL)
779  {
780  htp__hook_error_(connection->request, errtype);
781  }
782 
783  return EVHTP_RES_OK;
784 }
785 
793 static inline evhtp_res
794 htp__hook_hostname_(evhtp_request_t * r, const char * hostname)
795 {
796  HOOK_REQUEST_RUN(r, on_hostname, hostname);
797 
798  return EVHTP_RES_OK;
799 }
800 
807 static inline evhtp_res
808 htp__hook_connection_write_(evhtp_connection_t * connection)
809 {
810  if (connection->hooks && connection->hooks->on_write)
811  {
812  return (connection->hooks->on_write)(connection,
813  connection->hooks->on_write_arg);
814  }
815 
816  return EVHTP_RES_OK;
817 }
818 
829 static int
830 htp__glob_match_(const char * pattern, size_t plen,
831  const char * string, size_t str_len)
832 {
833  while (plen)
834  {
835  switch (pattern[0]) {
836  case '*':
837  while (pattern[1] == '*')
838  {
839  pattern++;
840  plen--;
841  }
842 
843  if (plen == 1)
844  {
845  return 1; /* match */
846  }
847 
848  while (str_len)
849  {
850  if (htp__glob_match_(pattern + 1, plen - 1,
851  string, str_len))
852  {
853  return 1; /* match */
854  }
855 
856  string++;
857  str_len--;
858  }
859 
860  return 0; /* no match */
861  default:
862  if (pattern[0] != string[0])
863  {
864  return 0; /* no match */
865  }
866 
867  string++;
868  str_len--;
869  break;
870  } /* switch */
871 
872  pattern++;
873  plen--;
874 
875  if (str_len == 0)
876  {
877  while (*pattern == '*')
878  {
879  pattern++;
880  plen--;
881  }
882 
883  break;
884  }
885  }
886 
887  if (plen == 0 && str_len == 0)
888  {
889  return 1;
890  }
891 
892  return 0;
893 } /* htp__glob_match_ */
894 
904 static evhtp_callback_t *
906  const char * path,
907  unsigned int * start_offset,
908  unsigned int * end_offset)
909 {
910  size_t path_len;
911 
912 #ifndef EVHTP_DISABLE_REGEX
913  regmatch_t pmatch[28];
914 #endif
915  evhtp_callback_t * callback;
916 
917  if (evhtp_unlikely(cbs == NULL))
918  {
919  return NULL;
920  }
921 
922  path_len = strlen(path);
923 
924  TAILQ_FOREACH(callback, cbs, next) {
925  switch (callback->type) {
927  if (strncmp(path, callback->val.path, callback->len) == 0)
928  {
929  *start_offset = 0;
930  *end_offset = path_len;
931 
932  return callback;
933  }
934  break;
935 #ifndef EVHTP_DISABLE_REGEX
937  if (regexec(callback->val.regex,
938  path,
939  callback->val.regex->re_nsub + 1,
940  pmatch, 0) == 0)
941  {
942  *start_offset = pmatch[callback->val.regex->re_nsub].rm_so;
943  *end_offset = pmatch[callback->val.regex->re_nsub].rm_eo;
944 
945  return callback;
946  }
947 
948  break;
949 #endif
951  {
952  size_t glob_len = strlen(callback->val.glob);
953 
954  if (htp__glob_match_(callback->val.glob,
955  glob_len,
956  path,
957  path_len) == 1)
958  {
959  *start_offset = 0;
960  *end_offset = path_len;
961 
962  return callback;
963  }
964  }
965  default:
966  break;
967  } /* switch */
968  }
969 
970  return NULL;
971 } /* htp__callback_find_ */
972 
989 static int
990 htp__path_new_(evhtp_path_t ** out, const char * data, size_t len)
991 {
992  evhtp_path_t * req_path;
993  const char * data_end = (const char *)(data + len);
994  char * path = NULL;
995  char * file = NULL;
996 
997 
998  req_path = htp__calloc_(1, sizeof(*req_path));
999  evhtp_alloc_assert(req_path);
1000 
1001  *out = NULL;
1002 
1003  if (evhtp_unlikely(len == 0))
1004  {
1005  /*
1006  * odd situation here, no preceding "/", so just assume the path is "/"
1007  */
1008  path = htp__strdup_("/");
1009  evhtp_alloc_assert(path);
1010  } else if (*data != '/')
1011  {
1012  /* request like GET stupid HTTP/1.0, treat stupid as the file, and
1013  * assume the path is "/"
1014  */
1015  path = htp__strdup_("/");
1016  evhtp_alloc_assert(path);
1017 
1018  file = htp__strndup_(data, len);
1019  evhtp_alloc_assert(file);
1020  } else {
1021  if (data[len - 1] != '/')
1022  {
1023  /*
1024  * the last character in data is assumed to be a file, not the end of path
1025  * loop through the input data backwards until we find a "/"
1026  */
1027  size_t i;
1028 
1029  for (i = (len - 1); i != 0; i--)
1030  {
1031  if (data[i] == '/')
1032  {
1033  /*
1034  * we have found a "/" representing the start of the file,
1035  * and the end of the path
1036  */
1037  size_t path_len;
1038  size_t file_len;
1039 
1040  path_len = (size_t)(&data[i] - data) + 1;
1041  file_len = (size_t)(data_end - &data[i + 1]);
1042 
1043  /* check for overflow */
1044  if ((const char *)(data + path_len) > data_end)
1045  {
1046  evhtp_safe_free(req_path, htp__free_);
1047 
1048  return -1;
1049  }
1050 
1051  /* check for overflow */
1052  if ((const char *)(&data[i + 1] + file_len) > data_end)
1053  {
1054  evhtp_safe_free(req_path, htp__free_);
1055 
1056  return -1;
1057  }
1058 
1059  path = htp__strndup_(data, path_len);
1060  evhtp_alloc_assert(path);
1061 
1062  file = htp__strndup_(&data[i + 1], file_len);
1063  evhtp_alloc_assert(file);
1064 
1065  break;
1066  }
1067  }
1068 
1069  if (i == 0 && data[i] == '/' && !file && !path)
1070  {
1071  /* drops here if the request is something like GET /foo */
1072  path = htp__strdup_("/");
1073  evhtp_alloc_assert(path);
1074 
1075  if (len > 1)
1076  {
1077  file = htp__strndup_((const char *)(data + 1), len);
1078  evhtp_alloc_assert(file);
1079  }
1080  }
1081  } else {
1082  /* the last character is a "/", thus the request is just a path */
1083  path = htp__strndup_(data, len);
1084  evhtp_alloc_assert(path);
1085  }
1086  }
1087 
1088  if (len != 0)
1089  {
1090  req_path->full = htp__strndup_(data, len);
1091  } else {
1092  req_path->full = htp__strdup_("/");
1093  }
1094 
1095  evhtp_alloc_assert(req_path->full);
1096 
1097  req_path->path = path;
1098  req_path->file = file;
1099 
1100  *out = req_path;
1101 
1102  return 0;
1103 } /* htp__path_new_ */
1104 
1109 static void
1110 htp__path_free_(evhtp_path_t * path)
1111 {
1112  if (evhtp_unlikely(path == NULL))
1113  {
1114  return;
1115  }
1116 
1117  evhtp_safe_free(path->full, htp__free_);
1118  evhtp_safe_free(path->path, htp__free_);
1119  evhtp_safe_free(path->file, htp__free_);
1120  evhtp_safe_free(path->match_start, htp__free_);
1121  evhtp_safe_free(path->match_end, htp__free_);
1122 
1123  evhtp_safe_free(path, htp__free_);
1124 }
1125 
1131 static int
1132 htp__authority_new_(evhtp_authority_t ** out)
1133 {
1134  evhtp_authority_t * authority;
1135 
1136  if (evhtp_unlikely(out == NULL))
1137  {
1138  return -1;
1139  }
1140 
1141  *out = htp__calloc_(1, sizeof(*authority));
1142 
1143  return (*out != NULL) ? 0 : -1;
1144 }
1145 
1151 static void
1152 htp__authority_free_(evhtp_authority_t * authority)
1153 {
1154  if (authority == NULL)
1155  {
1156  return;
1157  }
1158 
1159  evhtp_safe_free(authority->username, htp__free_);
1160  evhtp_safe_free(authority->password, htp__free_);
1161  evhtp_safe_free(authority->hostname, htp__free_);
1162 
1163  evhtp_safe_free(authority, htp__free_);
1164 }
1165 
1171 static void
1172 htp__uri_free_(evhtp_uri_t * uri)
1173 {
1174  if (evhtp_unlikely(uri == NULL))
1175  {
1176  return;
1177  }
1178 
1179  evhtp_safe_free(uri->query, evhtp_query_free);
1180  evhtp_safe_free(uri->path, htp__path_free_);
1181  evhtp_safe_free(uri->authority, htp__authority_free_);
1182 
1183  evhtp_safe_free(uri->fragment, htp__free_);
1184  evhtp_safe_free(uri->query_raw, htp__free_);
1185 
1187 }
1188 
1194 static int
1195 htp__uri_new_(evhtp_uri_t ** out)
1196 {
1197  evhtp_uri_t * uri;
1198 
1199  *out = NULL;
1200 
1201  if ((uri = htp__calloc_(1, sizeof(*uri))) == NULL)
1202  {
1203  return -1;
1204  }
1205 
1206  uri->authority = NULL;
1207 
1208  if (htp__authority_new_(&uri->authority) == -1)
1209  {
1211  return -1;
1212  }
1213 
1214  *out = uri;
1215 
1216  return 0;
1217 }
1218 
1224 static void
1225 htp__request_free_(evhtp_request_t * request)
1226 {
1227  if (evhtp_unlikely(request == NULL))
1228  {
1229  return;
1230  }
1231 
1232  htp__hook_request_fini_(request);
1233 
1234  evhtp_safe_free(request->uri, htp__uri_free_);
1235  evhtp_safe_free(request->headers_in, evhtp_kvs_free);
1236  evhtp_safe_free(request->headers_out, evhtp_kvs_free);
1237 
1238  if (request->conn && request->conn->request == request)
1239  {
1240  request->conn->request = NULL;
1241  }
1242 
1243  if (request->buffer_in != NULL)
1244  {
1245  evhtp_safe_free(request->buffer_in, evbuffer_free);
1246  }
1247 
1248  if (request->buffer_out != NULL)
1249  {
1250  evhtp_safe_free(request->buffer_out, evbuffer_free);
1251  }
1252 
1253  evhtp_safe_free(request->hooks, htp__free_);
1254  evhtp_safe_free(request, htp__free_);
1255 }
1256 
1264 static evhtp_request_t *
1265 htp__request_new_(evhtp_connection_t * c)
1266 {
1267  evhtp_request_t * req;
1268  uint8_t error;
1269 
1270  if (evhtp_unlikely(!(req = htp__calloc_(sizeof(*req), 1))))
1271  {
1272  return NULL;
1273  }
1274 
1275  error = 1;
1276  req->conn = c;
1277  req->htp = c ? c->htp : NULL;
1278  req->status = EVHTP_RES_OK;
1279 
1280  do {
1281  if (evhtp_unlikely(!(req->buffer_in = evbuffer_new())))
1282  {
1283  break;
1284  }
1285 
1286  if (evhtp_unlikely(!(req->buffer_out = evbuffer_new())))
1287  {
1288  break;
1289  }
1290 
1291  if (evhtp_unlikely(!(req->headers_in = htp__malloc_(sizeof(evhtp_headers_t)))))
1292  {
1293  break;
1294  }
1295 
1296  if (evhtp_unlikely(!(req->headers_out = htp__malloc_(sizeof(evhtp_headers_t)))))
1297  {
1298  break;
1299  }
1300 
1301  TAILQ_INIT(req->headers_in);
1302  TAILQ_INIT(req->headers_out);
1303 
1304  error = 0;
1305  } while (0);
1306 
1307  if (error == 0)
1308  {
1309  return req;
1310  }
1311 
1313 
1314  return req;
1315 } /* htp__request_new_ */
1316 
1323 static int
1325 {
1326  evhtp_connection_t * c = htparser_get_userdata(p);
1327 
1328  if (evhtp_unlikely(c->type == evhtp_type_client))
1329  {
1330  return 0;
1331  }
1332 
1333  if (c->flags & EVHTP_CONN_FLAG_PAUSED)
1334  {
1335  return -1;
1336  }
1337 
1338  if (c->request)
1339  {
1340  if (c->request->flags & EVHTP_REQ_FLAG_FINISHED)
1341  {
1342  htp__request_free_(c->request);
1343  } else {
1344  return -1;
1345  }
1346  }
1347 
1348  if (((c->request = htp__request_new_(c))) == NULL)
1349  {
1350  return -1;
1351  }
1352 
1353  return 0;
1354 }
1355 
1366 static int
1367 htp__request_parse_args_(htparser * p, const char * data, size_t len)
1368 {
1369  evhtp_connection_t * c = htparser_get_userdata(p);
1370  evhtp_uri_t * uri = c->request->uri;
1371  const char * fragment;
1372  int ignore_fragment;
1373 
1374  if (c->type == evhtp_type_client)
1375  {
1376  /* as a client, technically we should never get here, but just in case
1377  * we return a 0 to the parser to continue.
1378  */
1379  return 0;
1380  }
1381 
1382 
1383  /* if the parser flags has the IGNORE_FRAGMENTS bit set, skip
1384  * the fragment parsing
1385  */
1386  ignore_fragment = (c->htp->parser_flags &
1388 
1389 
1390  if (!ignore_fragment && (fragment = memchr(data, '#', len)))
1391  {
1392  /* Separate fragment from query according to RFC 3986.
1393  *
1394  * XXX: not happy about using strchr stuff, maybe this functionality
1395  * is more apt as part of evhtp_parse_query()
1396  */
1397 
1398  ptrdiff_t frag_offset;
1399 
1400  frag_offset = fragment - data;
1401 
1402  if (frag_offset < len)
1403  {
1404  size_t fraglen;
1405 
1406  /* Skip '#'. */
1407  fragment += 1;
1408  frag_offset += 1;
1409  fraglen = len - frag_offset;
1410 
1411  uri->fragment = htp__malloc_(fraglen + 1);
1412  evhtp_alloc_assert(uri->fragment);
1413 
1414  memcpy(uri->fragment, fragment, fraglen);
1415 
1416  uri->fragment[fraglen] = '\0';
1417  len -= fraglen + 1; /* Skip '#' + fragment string. */
1418  }
1419  }
1420 
1421  uri->query = evhtp_parse_query_wflags(data, len, c->htp->parser_flags);
1422 
1423  if (evhtp_unlikely(!uri->query))
1424  {
1425  c->cr_status = EVHTP_RES_ERROR;
1426 
1427  return -1;
1428  }
1429 
1430  uri->query_raw = htp__malloc_(len + 1);
1431  evhtp_alloc_assert(uri->query_raw);
1432 
1433  memcpy(uri->query_raw, data, len);
1434  uri->query_raw[len] = '\0';
1435 
1436  return 0;
1437 } /* htp__request_parse_args_ */
1438 
1439 static int
1441 {
1442  evhtp_connection_t * c = htparser_get_userdata(p);
1443 
1444  if ((c->cr_status = htp__hook_headers_start_(c->request)) != EVHTP_RES_OK)
1445  {
1446  return -1;
1447  }
1448 
1449  return 0;
1450 }
1451 
1452 static int
1453 htp__request_parse_header_key_(htparser * p, const char * data, size_t len)
1454 {
1455  evhtp_connection_t * c = htparser_get_userdata(p);
1456  char * key_s;
1457  evhtp_header_t * hdr;
1458 
1459  key_s = htp__malloc_(len + 1);
1460  evhtp_alloc_assert(key_s);
1461 
1462  key_s[len] = '\0';
1463  memcpy(key_s, data, len);
1464 
1465  if ((hdr = evhtp_header_key_add(c->request->headers_in, key_s, 0)) == NULL)
1466  {
1467  c->cr_status = EVHTP_RES_FATAL;
1468 
1469  return -1;
1470  }
1471 
1472  hdr->k_heaped = 1;
1473 
1474  return 0;
1475 }
1476 
1477 static int
1478 htp__request_parse_header_val_(htparser * p, const char * data, size_t len)
1479 {
1480  evhtp_connection_t * c = htparser_get_userdata(p);
1481  char * val_s;
1482  evhtp_header_t * header;
1483 
1484  val_s = htp__malloc_(len + 1);
1485  evhtp_alloc_assert(val_s);
1486 
1487  val_s[len] = '\0';
1488  memcpy(val_s, data, len);
1489 
1490  if ((header = evhtp_header_val_add(c->request->headers_in, val_s, 0)) == NULL)
1491  {
1492  evhtp_safe_free(val_s, htp__free_);
1493  c->cr_status = EVHTP_RES_FATAL;
1494 
1495  return -1;
1496  }
1497 
1498  header->v_heaped = 1;
1499 
1500  if ((c->cr_status = htp__hook_header_(c->request, header)) != EVHTP_RES_OK)
1501  {
1502  return -1;
1503  }
1504 
1505  return 0;
1506 }
1507 
1508 static inline evhtp_t *
1509 htp__request_find_vhost_(evhtp_t * evhtp, const char * name)
1510 {
1511  evhtp_t * evhtp_vhost;
1512  evhtp_alias_t * evhtp_alias;
1513 
1514  TAILQ_FOREACH(evhtp_vhost, &evhtp->vhosts, next_vhost) {
1515  if (evhtp_unlikely(evhtp_vhost->server_name == NULL))
1516  {
1517  continue;
1518  }
1519 
1520  if (htp__glob_match_(evhtp_vhost->server_name,
1521  strlen(evhtp_vhost->server_name), name,
1522  strlen(name)) == 1)
1523  {
1524  return evhtp_vhost;
1525  }
1526 
1527  TAILQ_FOREACH(evhtp_alias, &evhtp_vhost->aliases, next) {
1528  if (evhtp_alias->alias == NULL)
1529  {
1530  continue;
1531  }
1532 
1533  if (htp__glob_match_(evhtp_alias->alias,
1534  strlen(evhtp_alias->alias), name,
1535  strlen(name)) == 1)
1536  {
1537  return evhtp_vhost;
1538  }
1539  }
1540  }
1541 
1542  return NULL;
1543 }
1544 
1545 static inline int
1546 htp__request_set_callbacks_(evhtp_request_t * request)
1547 {
1548  evhtp_t * evhtp;
1549  evhtp_connection_t * conn;
1550  evhtp_uri_t * uri;
1551  evhtp_path_t * path;
1552  evhtp_hooks_t * hooks;
1553  evhtp_callback_t * callback;
1555  void * cbarg;
1556 
1557  if (request == NULL)
1558  {
1559  return -1;
1560  }
1561 
1562  if ((evhtp = request->htp) == NULL)
1563  {
1564  return -1;
1565  }
1566 
1567  if ((conn = request->conn) == NULL)
1568  {
1569  return -1;
1570  }
1571 
1572  if ((uri = request->uri) == NULL)
1573  {
1574  return -1;
1575  }
1576 
1577  if ((path = uri->path) == NULL)
1578  {
1579  return -1;
1580  }
1581 
1582  hooks = NULL;
1583  callback = NULL;
1584  cb = NULL;
1585  cbarg = NULL;
1586 
1587  if ((callback = htp__callback_find_(evhtp->callbacks, path->full,
1588  &path->matched_soff, &path->matched_eoff)))
1589  {
1590  /* matched a callback using both path and file (/a/b/c/d) */
1591  cb = callback->cb;
1592  cbarg = callback->cbarg;
1593  hooks = callback->hooks;
1594  } else if ((callback = htp__callback_find_(evhtp->callbacks, path->path,
1595  &path->matched_soff, &path->matched_eoff)))
1596  {
1597  /* matched a callback using *just* the path (/a/b/c/) */
1598  cb = callback->cb;
1599  cbarg = callback->cbarg;
1600  hooks = callback->hooks;
1601  } else {
1602  /* no callbacks found for either case, use defaults */
1603  cb = evhtp->defaults.cb;
1604  cbarg = evhtp->defaults.cbarg;
1605 
1606  path->matched_soff = 0;
1607  path->matched_eoff = (unsigned int)strlen(path->full);
1608  }
1609 
1610  if (path->match_start == NULL)
1611  {
1612  path->match_start = htp__calloc_(strlen(path->full) + 1, 1);
1613  evhtp_alloc_assert(path->match_start);
1614  }
1615 
1616  if (path->match_end == NULL)
1617  {
1618  path->match_end = htp__calloc_(strlen(path->full) + 1, 1);
1619  evhtp_alloc_assert(path->match_end);
1620  }
1621 
1622  if (path->matched_soff != UINT_MAX /*ONIG_REGION_NOTPOS*/)
1623  {
1624  if (path->matched_eoff - path->matched_soff)
1625  {
1626  memcpy(path->match_start, (void *)(path->full + path->matched_soff),
1627  path->matched_eoff - path->matched_soff);
1628  } else {
1629  memcpy(path->match_start, (void *)(path->full + path->matched_soff),
1630  strlen((const char *)(path->full + path->matched_soff)));
1631  }
1632 
1633  memcpy(path->match_end,
1634  (void *)(path->full + path->matched_eoff),
1635  strlen(path->full) - path->matched_eoff);
1636  }
1637 
1638  if (hooks != NULL)
1639  {
1640  if (request->hooks == NULL)
1641  {
1642  request->hooks = htp__malloc_(sizeof(evhtp_hooks_t));
1643  evhtp_alloc_assert(request->hooks);
1644  }
1645 
1646  memcpy(request->hooks, hooks, sizeof(evhtp_hooks_t));
1647  }
1648 
1649  request->cb = cb;
1650  request->cbarg = cbarg;
1651 
1652  return 0;
1653 } /* htp__request_set_callbacks_ */
1654 
1655 static int
1656 htp__request_parse_hostname_(htparser * p, const char * data, size_t len)
1657 {
1658  evhtp_connection_t * c = htparser_get_userdata(p);
1659  evhtp_t * evhtp;
1660  evhtp_t * evhtp_vhost;
1661 
1662 #ifndef EVHTP_DISABLE_SSL
1663  if ((c->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI) && c->ssl != NULL)
1664  {
1665  /* use the SNI set hostname instead of the header hostname */
1666  const char * host;
1667 
1668  host = SSL_get_servername(c->ssl, TLSEXT_NAMETYPE_host_name);
1669 
1670  if ((c->cr_status = htp__hook_hostname_(c->request, host)) != EVHTP_RES_OK)
1671  {
1672  return -1;
1673  }
1674 
1675  return 0;
1676  }
1677 #endif
1678 
1679  evhtp = c->htp;
1680 
1681  /* since this is called after htp__request_parse_path_(), which already
1682  * setup callbacks for the URI, we must now attempt to find callbacks which
1683  * are specific to this host.
1684  */
1685  htp__lock_(evhtp);
1686  {
1687  if ((evhtp_vhost = htp__request_find_vhost_(evhtp, data)))
1688  {
1689  htp__lock_(evhtp_vhost);
1690  {
1691  /* if we found a match for the host, we must set the htp
1692  * variables for both the connection and the request.
1693  */
1694  c->htp = evhtp_vhost;
1695  c->request->htp = evhtp_vhost;
1696 
1697  htp__request_set_callbacks_(c->request);
1698  }
1699  htp__unlock_(evhtp_vhost);
1700  }
1701  }
1702  htp__unlock_(evhtp);
1703 
1704  if ((c->cr_status = htp__hook_hostname_(c->request, data)) != EVHTP_RES_OK)
1705  {
1706  return -1;
1707  }
1708 
1709  return 0;
1710 } /* htp__request_parse_hostname_ */
1711 
1712 static int
1713 htp__require_uri_(evhtp_connection_t * c)
1714 {
1715  if (c != NULL && c->request != NULL)
1716  {
1717  if (c->request->uri == NULL)
1718  {
1719  return htp__uri_new_(&c->request->uri);
1720  }
1721 
1722  return 0;
1723  }
1724 
1725  return -1;
1726 }
1727 
1728 static int
1729 htp__request_parse_host_(htparser * p, const char * data, size_t len)
1730 {
1731  evhtp_connection_t * c;
1732  evhtp_authority_t * authority;
1733 
1734  if (evhtp_unlikely(p == NULL))
1735  {
1736  return -1;
1737  }
1738 
1739  c = htparser_get_userdata(p);
1740 
1741  /* all null checks are done in require_uri_,
1742  * no need to check twice
1743  */
1744  if (htp__require_uri_(c) == -1)
1745  {
1746  return -1;
1747  }
1748 
1749  authority = c->request->uri->authority;
1750  authority->hostname = htp__malloc_(len + 1);
1751  evhtp_alloc_assert(authority->hostname);
1752 
1753  if (authority->hostname == NULL)
1754  {
1755  c->cr_status = EVHTP_RES_FATAL;
1756 
1757  return -1;
1758  }
1759 
1760  memcpy(authority->hostname, data, len);
1761  authority->hostname[len] = '\0';
1762 
1763  return 0;
1764 }
1765 
1766 static int
1767 htp__request_parse_port_(htparser * p, const char * data, size_t len)
1768 {
1769  evhtp_connection_t * c = htparser_get_userdata(p);
1770  evhtp_authority_t * authority;
1771  char * endptr;
1772  unsigned long port;
1773 
1774  if (htp__require_uri_(c) == -1)
1775  {
1776  return -1;
1777  }
1778 
1779  authority = c->request->uri->authority;
1780  port = strtoul(data, &endptr, 10);
1781 
1782  if (endptr - data != len || port > 65535)
1783  {
1784  c->cr_status = EVHTP_RES_FATAL;
1785 
1786  return -1;
1787  }
1788 
1789  authority->port = port;
1790 
1791  return 0;
1792 }
1793 
1794 static int
1795 htp__request_parse_path_(htparser * p, const char * data, size_t len)
1796 {
1797  evhtp_connection_t * c = htparser_get_userdata(p);
1798  evhtp_path_t * path;
1799 
1800  if (evhtp_unlikely(p == NULL || c == NULL))
1801  {
1802  return -1;
1803  }
1804 
1805  if (htp__require_uri_(c) == -1)
1806  {
1807  return -1;
1808  }
1809 
1810  if (htp__path_new_(&path, data, len) == -1)
1811  {
1812  c->cr_status = EVHTP_RES_FATAL;
1813 
1814  return -1;
1815  }
1816 
1817  c->request->uri->path = path;
1818  c->request->uri->scheme = htparser_get_scheme(p);
1819  c->request->method = htparser_get_method(p);
1820 
1821  htp__lock_(c->htp);
1822  {
1823  htp__request_set_callbacks_(c->request);
1824  }
1825  htp__unlock_(c->htp);
1826 
1827  if ((c->cr_status = htp__hook_path_(c->request, path)) != EVHTP_RES_OK)
1828  {
1829  return -1;
1830  }
1831 
1832  return 0;
1833 } /* htp__request_parse_path_ */
1834 
1835 static int
1837 {
1838  evhtp_connection_t * c;
1839 
1840  if ((c = htparser_get_userdata(p)) == NULL)
1841  {
1842  return -1;
1843  }
1844 
1845  /* XXX proto should be set with htparsers on_hdrs_begin hook */
1846 
1847  if (htparser_should_keep_alive(p) == 1)
1848  {
1849  c->request->flags |= EVHTP_REQ_FLAG_KEEPALIVE;
1850  }
1851 
1852  c->request->proto = htp__protocol_(htparser_get_major(p), htparser_get_minor(p));
1853  c->cr_status = htp__hook_headers_(c->request, c->request->headers_in);
1854 
1855  if (c->cr_status != EVHTP_RES_OK)
1856  {
1857  return -1;
1858  }
1859 
1860  if (c->type == evhtp_type_server
1861  && c->htp->flags & EVHTP_FLAG_ENABLE_100_CONT)
1862  {
1863  /* only send a 100 continue response if it hasn't been disabled via
1864  * evhtp_disable_100_continue.
1865  */
1866  if (!evhtp_header_find(c->request->headers_in, "Expect"))
1867  {
1868  return 0;
1869  }
1870 
1871  evbuffer_add_printf(bufferevent_get_output(c->bev),
1872  "HTTP/%c.%c 100 Continue\r\n\r\n",
1875  }
1876 
1877  return 0;
1878 }
1879 
1880 static int
1881 htp__request_parse_body_(htparser * p, const char * data, size_t len)
1882 {
1883  evhtp_connection_t * c = htparser_get_userdata(p);
1884  struct evbuffer * buf;
1885  int res = 0;
1886 
1887  if (c->max_body_size > 0 && c->body_bytes_read + len >= c->max_body_size)
1888  {
1889  c->flags |= EVHTP_CONN_FLAG_ERROR;
1890  c->cr_status = EVHTP_RES_DATA_TOO_LONG;
1891 
1892  return -1;
1893  }
1894 
1895  if ((buf = c->scratch_buf) == NULL)
1896  {
1897  return -1;
1898  }
1899 
1900  evbuffer_add(buf, data, len);
1901 
1902  if ((c->cr_status = htp__hook_body_(c->request, buf)) != EVHTP_RES_OK)
1903  {
1904  res = -1;
1905  }
1906 
1907  if (evbuffer_get_length(buf))
1908  {
1909  evbuffer_add_buffer(c->request->buffer_in, buf);
1910  }
1911 
1912  evbuffer_drain(buf, -1);
1913 
1914  c->body_bytes_read += len;
1915 
1916  return res;
1917 }
1918 
1919 static int
1921 {
1922  evhtp_connection_t * c = htparser_get_userdata(p);
1923 
1924  if ((c->cr_status = htp__hook_chunk_new_(c->request,
1926  {
1927  return -1;
1928  }
1929 
1930  return 0;
1931 }
1932 
1933 static int
1935 {
1936  evhtp_connection_t * c = htparser_get_userdata(p);
1937 
1938  if ((c->cr_status = htp__hook_chunk_fini_(c->request)) != EVHTP_RES_OK)
1939  {
1940  return -1;
1941  }
1942 
1943  return 0;
1944 }
1945 
1946 static int
1948 {
1949  evhtp_connection_t * c = htparser_get_userdata(p);
1950 
1951  if ((c->cr_status = htp__hook_chunks_fini_(c->request)) != EVHTP_RES_OK)
1952  {
1953  return -1;
1954  }
1955 
1956  return 0;
1957 }
1958 
1969 static int
1970 htp__should_parse_query_body_(evhtp_request_t * req)
1971 {
1972  const char * content_type;
1973 
1974  if (req == NULL)
1975  {
1976  return 0;
1977  }
1978 
1979  if (req->uri == NULL || req->uri->query != NULL)
1980  {
1981  return 0;
1982  }
1983 
1984  if (evhtp_request_content_len(req) == 0)
1985  {
1986  return 0;
1987  }
1988 
1989  if (evhtp_request_content_len(req) !=
1990  evbuffer_get_length(req->buffer_in))
1991  {
1992  return 0;
1993  }
1994 
1995  content_type = evhtp_kv_find(req->headers_in, "content-type");
1996 
1997  if (content_type == NULL)
1998  {
1999  return 0;
2000  }
2001 
2002  if (strncasecmp(content_type, "application/x-www-form-urlencoded", 33))
2003  {
2004  return 0;
2005  }
2006 
2007  return 1;
2008 }
2009 
2010 static int
2012 {
2013  evhtp_connection_t * c = htparser_get_userdata(p);
2014 
2015  if (c->flags & EVHTP_CONN_FLAG_PAUSED)
2016  {
2017  return -1;
2018  }
2019 
2020  /* check to see if we should use the body of the request as the query
2021  * arguments.
2022  *
2023  * htp__should_parse_query_body_ does all the proper null checks.
2024  */
2025  if (htp__should_parse_query_body_(c->request) == 1)
2026  {
2027  const char * body;
2028  size_t body_len;
2029  evhtp_uri_t * uri;
2030  struct evbuffer * buf_in;
2031 
2032  uri = c->request->uri;
2033  buf_in = c->request->buffer_in;
2034 
2035  body_len = evbuffer_get_length(buf_in);
2036  body = (const char *)evbuffer_pullup(buf_in, body_len);
2037 
2038  uri->query_raw = htp__calloc_(body_len + 1, 1);
2039  evhtp_alloc_assert(uri->query_raw);
2040 
2041  memcpy(uri->query_raw, body, body_len);
2042 
2043  uri->query = evhtp_parse_query(body, body_len);
2044  }
2045 
2046 
2047  /*
2048  * XXX c->request should never be NULL, but we have found some path of
2049  * execution where this actually happens. We will check for now, but the bug
2050  * path needs to be tracked down.
2051  *
2052  */
2053  if (c->request && c->request->cb)
2054  {
2055  (c->request->cb)(c->request, c->request->cbarg);
2056  }
2057 
2058  if (c->flags & EVHTP_CONN_FLAG_PAUSED)
2059  {
2060  return -1;
2061  }
2062 
2063  return 0;
2064 } /* htp__request_parse_fini_ */
2065 
2066 static int
2068 {
2069  struct evbuffer * buf = arg;
2070 
2071  evbuffer_expand(buf, header->klen + 2 + header->vlen + 2);
2072  evbuffer_add(buf, header->key, header->klen);
2073  evbuffer_add(buf, ": ", 2);
2074  evbuffer_add(buf, header->val, header->vlen);
2075  evbuffer_add(buf, "\r\n", 2);
2076 
2077  return 0;
2078 }
2079 
2080 static struct evbuffer *
2081 htp__create_reply_(evhtp_request_t * request, evhtp_res code) {
2082  struct evbuffer * buf;
2083  const char * content_type;
2084  char res_buf[2048];
2085  int sres;
2086  size_t out_len;
2087  unsigned char major;
2088  unsigned char minor;
2089  char out_buf[64];
2090 
2091  evhtp_assert(request
2092  && request->headers_out
2093  && request->buffer_out
2094  && request->conn
2095  && request->rc_parser);
2096 
2097  content_type = evhtp_header_find(request->headers_out, "Content-Type");
2098  out_len = evbuffer_get_length(request->buffer_out);
2099 
2100  if ((buf = request->rc_scratch) == NULL)
2101  {
2102  request->rc_scratch = evbuffer_new();
2103  evhtp_alloc_assert(request->rc_scratch);
2104  }
2105 
2106  evbuffer_drain(buf, -1);
2107 
2108  if (htparser_get_multipart(request->rc_parser) == 1)
2109  {
2110  goto check_proto;
2111  }
2112 
2113  if (out_len && !(request->flags & EVHTP_REQ_FLAG_CHUNKED))
2114  {
2115  /* add extra headers (like content-length/type) if not already present */
2116 
2117  if (!evhtp_header_find(request->headers_out, "Content-Length"))
2118  {
2119  /* convert the buffer_out length to a string and set
2120  * and add the new Content-Length header.
2121  */
2122  evhtp_modp_sizetoa(out_len, out_buf);
2123 
2124  evhtp_headers_add_header(request->headers_out,
2125  evhtp_header_new("Content-Length", out_buf, 0, 1));
2126  }
2127  }
2128 check_proto:
2129  /* add the proper keep-alive type headers based on http version */
2130  switch (request->proto) {
2131  case EVHTP_PROTO_11:
2132  if (!(request->flags & EVHTP_REQ_FLAG_KEEPALIVE))
2133  {
2134  /* protocol is HTTP/1.1 but client wanted to close */
2135  evhtp_headers_add_header(request->headers_out,
2136  evhtp_header_new("Connection", "close", 0, 0));
2137  }
2138 
2139  if (!evhtp_header_find(request->headers_out, "Content-Length"))
2140  {
2141  evhtp_headers_add_header(request->headers_out,
2142  evhtp_header_new("Content-Length", "0", 0, 0));
2143  }
2144 
2145  break;
2146  case EVHTP_PROTO_10:
2147  if (request->flags & EVHTP_REQ_FLAG_KEEPALIVE)
2148  {
2149  /* protocol is HTTP/1.0 and clients wants to keep established */
2150  evhtp_headers_add_header(request->headers_out,
2151  evhtp_header_new("Connection", "keep-alive", 0, 0));
2152  }
2153  break;
2154  default:
2155  /* this sometimes happens when a response is made but paused before
2156  * the method has been parsed */
2157  htparser_set_major(request->rc_parser, 1);
2158  htparser_set_minor(request->rc_parser, 0);
2159  break;
2160  } /* switch */
2161 
2162 
2163  if (!content_type)
2164  {
2165  evhtp_headers_add_header(request->headers_out,
2166  evhtp_header_new("Content-Type", "text/plain", 0, 0));
2167  }
2168 
2169  /* attempt to add the status line into a temporary buffer and then use
2170  * evbuffer_add(). Using plain old snprintf() will be faster than
2171  * evbuffer_add_printf(). If the snprintf() fails, which it rarely should,
2172  * we fallback to using evbuffer_add_printf().
2173  */
2174 
2175  major = evhtp_modp_uchartoa(htparser_get_major(request->rc_parser));
2176  minor = evhtp_modp_uchartoa(htparser_get_minor(request->rc_parser));
2177 
2178  evhtp_modp_u32toa((uint32_t)code, out_buf);
2179 
2180  sres = snprintf(res_buf, sizeof(res_buf), "HTTP/%c.%c %s %s\r\n",
2181  major, minor, out_buf, status_code_to_str(code));
2182 
2183  if (sres >= sizeof(res_buf) || sres < 0)
2184  {
2185  /* failed to fit the whole thing in the res_buf, so just fallback to
2186  * using evbuffer_add_printf().
2187  */
2188  evbuffer_add_printf(buf, "HTTP/%c.%c %d %s\r\n",
2189  major, minor,
2190  code, status_code_to_str(code));
2191  } else {
2192  /* copy the res_buf using evbuffer_add() instead of add_printf() */
2193  evbuffer_add(buf, res_buf, sres);
2194  }
2195 
2196 
2197  evhtp_headers_for_each(request->headers_out, htp__create_headers_, buf);
2198  evbuffer_add(buf, "\r\n", 2);
2199 
2200  if (evbuffer_get_length(request->buffer_out))
2201  {
2202  evbuffer_add_buffer(buf, request->buffer_out);
2203  }
2204 
2205  return buf;
2206 } /* htp__create_reply_ */
2207 
2211 static htparse_hooks request_psets = {
2212  .on_msg_begin = htp__request_parse_start_,
2213  .method = NULL,
2214  .scheme = NULL,
2215  .host = htp__request_parse_host_,
2216  .port = htp__request_parse_port_,
2217  .path = htp__request_parse_path_,
2218  .args = htp__request_parse_args_,
2219  .uri = NULL,
2220  .on_hdrs_begin = htp__request_parse_headers_start_,
2221  .hdr_key = htp__request_parse_header_key_,
2222  .hdr_val = htp__request_parse_header_val_,
2223  .hostname = htp__request_parse_hostname_,
2224  .on_hdrs_complete = htp__request_parse_headers_,
2225  .on_new_chunk = htp__request_parse_chunk_new_,
2226  .on_chunk_complete = htp__request_parse_chunk_fini_,
2227  .on_chunks_complete = htp__request_parse_chunks_fini_,
2228  .body = htp__request_parse_body_,
2229  .on_msg_complete = htp__request_parse_fini_
2230 };
2231 
2232 static void
2233 htp__connection_readcb_(struct bufferevent * bev, void * arg)
2234 {
2235  evhtp_connection_t * c = arg;
2236  void * buf;
2237  size_t nread;
2238  size_t avail;
2239 
2240  if (evhtp_unlikely(bev == NULL))
2241  {
2242  return;
2243  }
2244 
2245  avail = evbuffer_get_length(bufferevent_get_input(bev));
2246 
2247  if (evhtp_unlikely(avail == 0))
2248  {
2249  return;
2250  }
2251 
2252  if (c->request)
2253  {
2254  c->cr_status = EVHTP_RES_OK;
2255  }
2256 
2257  if (c->flags & EVHTP_CONN_FLAG_PAUSED)
2258  {
2259  return;
2260  }
2261 
2262  buf = evbuffer_pullup(bufferevent_get_input(bev), avail);
2263 
2264  evhtp_assert(buf != NULL);
2265  evhtp_assert(c->parser != NULL);
2266 
2267  nread = htparser_run(c->parser, &request_psets, (const char *)buf, avail);
2268 
2269  log_debug("nread = %zu", nread);
2270 
2271  if (!(c->flags & EVHTP_CONN_FLAG_OWNER))
2272  {
2273  /*
2274  * someone has taken the ownership of this connection, we still need to
2275  * drain the input buffer that had been read up to this point.
2276  */
2277 
2278  log_debug("EVHTP_CONN_FLAG_OWNER set, removing contexts");
2279 
2280  evbuffer_drain(bufferevent_get_input(bev), nread);
2282 
2283  return;
2284  }
2285 
2286  if (c->request)
2287  {
2288  switch (c->cr_status) {
2292 
2293  return;
2294  default:
2295  break;
2296  }
2297  }
2298 
2299  evbuffer_drain(bufferevent_get_input(bev), nread);
2300 
2301  if (c->request && c->cr_status == EVHTP_RES_PAUSE)
2302  {
2303  log_debug("Pausing connection");
2304 
2305  evhtp_request_pause(c->request);
2306  } else if (htparser_get_error(c->parser) != htparse_error_none)
2307  {
2308  log_debug("error %d, freeing connection",
2309  htparser_get_error(c->parser));
2310 
2312  } else if (nread < avail)
2313  {
2314  /* we still have more data to read (piped request probably) */
2315  log_debug("Reading more data via resumption");
2316 
2318  }
2319 } /* htp__connection_readcb_ */
2320 
2321 static void
2322 htp__connection_writecb_(struct bufferevent * bev, void * arg)
2323 {
2324  evhtp_connection_t * conn;
2325  uint64_t keepalive_max;
2326  const char * errstr;
2327 
2328  evhtp_assert(bev != NULL);
2329 
2330  if (evhtp_unlikely(arg == NULL))
2331  {
2332  log_error("No data associated with the bufferevent %p", bev);
2333 
2334  bufferevent_free(bev);
2335  return;
2336  }
2337 
2338  errstr = NULL;
2339  conn = (evhtp_connection_t *)arg;
2340 
2341  do {
2342  if (evhtp_unlikely(conn->request == NULL))
2343  {
2344  errstr = "no request associated with connection";
2345  break;
2346  }
2347 
2348  if (evhtp_unlikely(conn->parser == NULL))
2349  {
2350  errstr = "no parser registered with connection";
2351  break;
2352  }
2353 
2354  if (evhtp_likely(conn->type == evhtp_type_server))
2355  {
2356  if (evhtp_unlikely(conn->htp == NULL))
2357  {
2358  errstr = "no context associated with the server-connection";
2359  break;
2360  }
2361 
2362  keepalive_max = conn->htp->max_keepalive_requests;
2363  } else {
2364  keepalive_max = 0;
2365  }
2366  } while (0);
2367 
2368  if (evhtp_unlikely(errstr != NULL))
2369  {
2370  log_error("shutting down connection: %s", errstr);
2371 
2373  return;
2374  }
2375 
2376  /* run user-hook for on_write callback before further analysis */
2378 
2379  /* connection is in a paused state, no further processing yet */
2380  if ((conn->flags & EVHTP_CONN_FLAG_PAUSED))
2381  {
2382  return;
2383  }
2384 
2385  if (conn->flags & EVHTP_CONN_FLAG_WAITING)
2386  {
2388 
2389  bufferevent_enable(bev, EV_READ);
2390 
2391  if (evbuffer_get_length(bufferevent_get_input(bev)))
2392  {
2393  htp__connection_readcb_(bev, arg);
2394  }
2395 
2396  return;
2397  }
2398 
2399  /* if the connection is not finished, OR there is data ready to output
2400  * (can only happen if a user-defined connection_write hook added data
2401  * manually, since this is called only when all data has been flushed)
2402  * just return and wait.
2403  */
2404  if (!(conn->request->flags & EVHTP_REQ_FLAG_FINISHED)
2405  || evbuffer_get_length(bufferevent_get_output(bev)))
2406  {
2407  return;
2408  }
2409 
2410  /*
2411  * if there is a set maximum number of keepalive requests configured, check
2412  * to make sure we are not over it. If we have gone over the max we set the
2413  * keepalive bit to 0, thus closing the connection.
2414  */
2415  if (keepalive_max > 0)
2416  {
2417  conn->num_requests += 1;
2418 
2419  if (conn->num_requests >= keepalive_max)
2420  {
2421  HTP_FLAG_OFF(conn->request, EVHTP_REQ_FLAG_KEEPALIVE);
2422  }
2423  }
2424 
2425  if (conn->request->flags & EVHTP_REQ_FLAG_KEEPALIVE)
2426  {
2427  htp_type type;
2428 
2429  /* free up the current request, set it to NULL, making
2430  * way for the next request.
2431  */
2432  evhtp_safe_free(conn->request, htp__request_free_);
2433 
2434  /* since the request is keep-alive, assure that the connection
2435  * is aware of the same.
2436  */
2438 
2439  conn->body_bytes_read = 0;
2440 
2441  if (conn->type == evhtp_type_server)
2442  {
2443  if (conn->htp->parent != NULL
2444  && !(conn->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI))
2445  {
2446  /* this request was served by a virtual host evhtp_t structure
2447  * which was *NOT* found via SSL SNI lookup. In this case we want to
2448  * reset our connections evhtp_t structure back to the original so
2449  * that subsequent requests can have a different 'Host' header.
2450  */
2451  conn->htp = conn->htp->parent;
2452  }
2453  }
2454 
2455  switch (conn->type) {
2456  case evhtp_type_client:
2457  type = htp_type_response;
2458  break;
2459  case evhtp_type_server:
2460  type = htp_type_request;
2461  break;
2462  default:
2463  log_error("Unknown connection type");
2464 
2466  return;
2467  }
2468 
2469  htparser_init(conn->parser, type);
2470  htparser_set_userdata(conn->parser, conn);
2471 
2472  return;
2473  } else {
2475 
2476  return;
2477  }
2478 
2479  return;
2480 } /* htp__connection_writecb_ */
2481 
2482 static void
2483 htp__connection_eventcb_(struct bufferevent * bev, short events, void * arg)
2484 {
2485  evhtp_connection_t * c = arg;
2486 
2487  log_debug("%p %p eventcb %s%s%s%s", arg, (void *)bev,
2488  events & BEV_EVENT_CONNECTED ? "connected" : "",
2489  events & BEV_EVENT_ERROR ? "error" : "",
2490  events & BEV_EVENT_TIMEOUT ? "timeout" : "",
2491  events & BEV_EVENT_EOF ? "eof" : "");
2492 
2493  if (c->hooks && c->hooks->on_event)
2494  {
2495  (c->hooks->on_event)(c, events, c->hooks->on_event_arg);
2496  }
2497 
2498  if ((events & BEV_EVENT_CONNECTED))
2499  {
2500  log_debug("CONNECTED");
2501 
2502  if (evhtp_likely(c->type == evhtp_type_client))
2503  {
2505 
2506  bufferevent_setcb(bev,
2510  }
2511 
2512  return;
2513  }
2514 
2515 #ifndef EVHTP_DISABLE_SSL
2516  if (c->ssl && !(events & BEV_EVENT_EOF))
2517  {
2518 #ifdef EVHTP_DEBUG
2519  unsigned long sslerr;
2520 
2521  while ((sslerr = bufferevent_get_openssl_error(bev))) {
2522  log_error("SSL ERROR %lu:%i:%s:%i:%s:%i:%s",
2523  sslerr,
2524  ERR_GET_REASON(sslerr),
2525  ERR_reason_error_string(sslerr),
2526  ERR_GET_LIB(sslerr),
2527  ERR_lib_error_string(sslerr),
2528  ERR_GET_FUNC(sslerr),
2529  ERR_func_error_string(sslerr));
2530  }
2531 #endif
2532 
2533  /* XXX need to do better error handling for SSL specific errors */
2535 
2536  if (c->request)
2537  {
2538  HTP_FLAG_ON(c->request, EVHTP_REQ_FLAG_ERROR);
2539  }
2540  }
2541 #endif
2542 
2543  if (events == (BEV_EVENT_EOF | BEV_EVENT_READING))
2544  {
2545  if (errno == EAGAIN)
2546  {
2547  /* libevent will sometimes recv again when it's not actually ready,
2548  * this results in a 0 return value, and errno will be set to EAGAIN
2549  * (try again). This does not mean there is a hard socket error, but
2550  * simply needs to be read again.
2551  *
2552  * but libevent will disable the read side of the bufferevent
2553  * anyway, so we must re-enable it.
2554  */
2555  bufferevent_enable(bev, EV_READ);
2556  errno = 0;
2557 
2558  return;
2559  }
2560  }
2561 
2562  /* set the error mask */
2564 
2565  /* unset connected flag */
2567 
2568  htp__hook_connection_error_(c, events);
2569 
2570  if (c->flags & EVHTP_CONN_FLAG_PAUSED)
2571  {
2572  /* we are currently paused, so we don't want to free just yet, let's
2573  * wait till the next loop.
2574  */
2576  } else {
2577  evhtp_connection_free((evhtp_connection_t *)arg);
2578  }
2579 } /* htp__connection_eventcb_ */
2580 
2581 static void
2582 htp__connection_resumecb_(int fd, short events, void * arg)
2583 {
2584  evhtp_connection_t * c = arg;
2585 
2586  /* unset the pause flag */
2588 
2589  if (c->request)
2590  {
2591  c->cr_status = EVHTP_RES_OK;
2592  }
2593 
2594  if (c->flags & EVHTP_CONN_FLAG_FREE_CONN)
2595  {
2597 
2598  return;
2599  }
2600 
2601  /* XXX this is a hack to show a potential fix for issues/86, the main indea
2602  * is that you call resume AFTER you have sent the reply (not BEFORE).
2603  *
2604  * When it has been decided this is a proper fix, the pause bit should be
2605  * changed to a state-type flag.
2606  */
2607 
2608  if (evbuffer_get_length(bufferevent_get_output(c->bev)))
2609  {
2611 
2612  bufferevent_enable(c->bev, EV_WRITE);
2613  } else {
2614  bufferevent_enable(c->bev, EV_READ | EV_WRITE);
2615  htp__connection_readcb_(c->bev, c);
2616  }
2617 }
2618 
2619 static int
2620 htp__run_pre_accept_(evhtp_t * htp, evhtp_connection_t * conn)
2621 {
2622  void * args;
2623  evhtp_res res;
2624 
2625  if (evhtp_likely(htp->defaults.pre_accept == NULL))
2626  {
2627  return 0;
2628  }
2629 
2630  args = htp->defaults.pre_accept_cbarg;
2631  res = htp->defaults.pre_accept(conn, args);
2632 
2633  if (res != EVHTP_RES_OK)
2634  {
2635  return -1;
2636  }
2637 
2638  return 0;
2639 }
2640 
2641 static int
2642 htp__connection_accept_(struct event_base * evbase, evhtp_connection_t * connection)
2643 {
2644  struct timeval * c_recv_timeo;
2645  struct timeval * c_send_timeo;
2646 
2647  if (htp__run_pre_accept_(connection->htp, connection) < 0)
2648  {
2649  evutil_closesocket(connection->sock);
2650 
2651  return -1;
2652  }
2653 
2654 #ifndef EVHTP_DISABLE_SSL
2655  if (connection->htp->ssl_ctx != NULL)
2656  {
2657  connection->ssl = SSL_new(connection->htp->ssl_ctx);
2658  connection->bev = bufferevent_openssl_socket_new(evbase,
2659  connection->sock,
2660  connection->ssl,
2661  BUFFEREVENT_SSL_ACCEPTING,
2662  connection->htp->bev_flags);
2663  SSL_set_app_data(connection->ssl, connection);
2664  goto end;
2665  }
2666 #endif
2667 
2668  connection->bev = bufferevent_socket_new(evbase,
2669  connection->sock,
2670  connection->htp->bev_flags);
2671 
2672  log_debug("enter sock=%d\n", connection->sock);
2673 
2674 #ifndef EVHTP_DISABLE_SSL
2675 end:
2676 #endif
2677 
2678  if (connection->recv_timeo.tv_sec || connection->recv_timeo.tv_usec)
2679  {
2680  c_recv_timeo = &connection->recv_timeo;
2681  } else if (connection->htp->recv_timeo.tv_sec ||
2682  connection->htp->recv_timeo.tv_usec)
2683  {
2684  c_recv_timeo = &connection->htp->recv_timeo;
2685  } else {
2686  c_recv_timeo = NULL;
2687  }
2688 
2689  if (connection->send_timeo.tv_sec || connection->send_timeo.tv_usec)
2690  {
2691  c_send_timeo = &connection->send_timeo;
2692  } else if (connection->htp->send_timeo.tv_sec ||
2693  connection->htp->send_timeo.tv_usec)
2694  {
2695  c_send_timeo = &connection->htp->send_timeo;
2696  } else {
2697  c_send_timeo = NULL;
2698  }
2699 
2700  evhtp_connection_set_timeouts(connection, c_recv_timeo, c_send_timeo);
2701 
2702  connection->resume_ev = event_new(evbase, -1, EV_READ | EV_PERSIST,
2703  htp__connection_resumecb_, connection);
2704  event_add(connection->resume_ev, NULL);
2705 
2706  bufferevent_enable(connection->bev, EV_READ);
2707  bufferevent_setcb(connection->bev,
2710  htp__connection_eventcb_, connection);
2711 
2712  return 0;
2713 } /* htp__connection_accept_ */
2714 
2715 static void
2716 htp__default_request_cb_(evhtp_request_t * request, void * arg)
2717 {
2718  evhtp_headers_add_header(request->headers_out,
2719  evhtp_header_new("Content-Length", "0", 0, 0));
2720  evhtp_send_reply(request, EVHTP_RES_NOTFOUND);
2721 }
2722 
2723 static evhtp_connection_t *
2724 htp__connection_new_(evhtp_t * htp, evutil_socket_t sock, evhtp_type type)
2725 {
2726  evhtp_connection_t * connection;
2727  htp_type ptype;
2728 
2729  switch (type) {
2730  case evhtp_type_client:
2731  ptype = htp_type_response;
2732  break;
2733  case evhtp_type_server:
2734  ptype = htp_type_request;
2735  break;
2736  default:
2737  return NULL;
2738  }
2739 
2740  connection = htp__calloc_(sizeof(evhtp_connection_t), 1);
2741  evhtp_alloc_assert(connection);
2742 
2743  connection->scratch_buf = evbuffer_new();
2744  evhtp_alloc_assert(connection->scratch_buf);
2745 
2746  connection->flags = EVHTP_CONN_FLAG_OWNER;
2747  connection->sock = sock;
2748  connection->htp = htp;
2749  connection->type = type;
2750  connection->parser = htparser_new();
2751 
2752  evhtp_alloc_assert(connection->parser);
2753 
2754  htparser_init(connection->parser, ptype);
2755  htparser_set_userdata(connection->parser, connection);
2756 
2757  return connection;
2758 } /* htp__connection_new_ */
2759 
2760 #ifdef LIBEVENT_HAS_SHUTDOWN
2761 #ifndef EVHTP_DISABLE_SSL
2762 static void
2763 htp__shutdown_eventcb_(struct bufferevent * bev, short events, void * arg)
2764 {
2765 }
2766 
2767 #endif
2768 #endif
2769 
2770 static int
2771 htp__run_post_accept_(evhtp_t * htp, evhtp_connection_t * connection)
2772 {
2773  void * args;
2774  evhtp_res res;
2775 
2776  if (evhtp_likely(htp->defaults.post_accept == NULL))
2777  {
2778  return 0;
2779  }
2780 
2781  args = htp->defaults.post_accept_cbarg;
2782  res = htp->defaults.post_accept(connection, args);
2783 
2784  if (res != EVHTP_RES_OK)
2785  {
2786  return -1;
2787  }
2788 
2789  return 0;
2790 }
2791 
2792 #ifndef EVHTP_DISABLE_EVTHR
2793 static void
2794 htp__run_in_thread_(evthr_t * thr, void * arg, void * shared)
2795 {
2796  evhtp_t * htp = shared;
2797  evhtp_connection_t * connection = arg;
2798 
2799  connection->evbase = evthr_get_base(thr);
2800  connection->thread = thr;
2801 
2802  if (htp__connection_accept_(connection->evbase, connection) < 0)
2803  {
2804  evhtp_connection_free(connection);
2805 
2806  return;
2807  }
2808 
2809  if (htp__run_post_accept_(htp, connection) < 0)
2810  {
2811  evhtp_connection_free(connection);
2812 
2813  return;
2814  }
2815 }
2816 
2817 #endif
2818 
2819 static void
2820 htp__accept_cb_(struct evconnlistener * serv, int fd, struct sockaddr * s, int sl, void * arg)
2821 {
2822  evhtp_t * htp = arg;
2823  evhtp_connection_t * connection;
2824 
2825  evhtp_assert(htp && serv && serv && s);
2826 
2827  connection = htp__connection_new_(htp, fd, evhtp_type_server);
2828 
2829  if (evhtp_unlikely(connection == NULL))
2830  {
2831  return;
2832  }
2833 
2834  log_debug("fd = %d, conn = %p", fd, connection);
2835 
2836  connection->saddr = htp__malloc_(sl);
2837  evhtp_alloc_assert(connection->saddr);
2838 
2839  memcpy(connection->saddr, s, sl);
2840 
2841 #ifndef EVHTP_DISABLE_EVTHR
2842  if (htp->thr_pool != NULL)
2843  {
2844  if (evthr_pool_defer(htp->thr_pool,
2845  htp__run_in_thread_, connection) != EVTHR_RES_OK)
2846  {
2847  evutil_closesocket(connection->sock);
2848  evhtp_connection_free(connection);
2849 
2850  return;
2851  }
2852 
2853  return;
2854  }
2855 #endif
2856  connection->evbase = htp->evbase;
2857 
2858  if (htp__connection_accept_(htp->evbase, connection) == -1)
2859  {
2860  evhtp_connection_free(connection);
2861  return;
2862  }
2863 
2864  if (htp__run_post_accept_(htp, connection) == -1)
2865  {
2866  evhtp_connection_free(connection);
2867  return;
2868  }
2869 } /* htp__accept_cb_ */
2870 
2871 #ifndef EVHTP_DISABLE_SSL
2872 #ifndef EVHTP_DISABLE_EVTHR
2873 static unsigned long
2875 {
2876 #ifndef WIN32
2877 
2878  return (unsigned long)pthread_self();
2879 #else
2880 
2881  return (unsigned long)(pthread_self().p);
2882 #endif
2883 }
2884 
2885 static void
2886 htp__ssl_thread_lock_(int mode, int type, const char * file, int line)
2887 {
2888  if (type < ssl_num_locks)
2889  {
2890  if (mode & CRYPTO_LOCK)
2891  {
2892  pthread_mutex_lock(&(ssl_locks[type]));
2893  } else {
2894  pthread_mutex_unlock(&(ssl_locks[type]));
2895  }
2896  }
2897 }
2898 
2899 #endif
2900 static void
2902 {
2903  evhtp_t * htp;
2904  evhtp_ssl_cfg_t * cfg;
2905  evhtp_ssl_data_t * sid;
2906  unsigned int slen;
2907 
2908  htp = (evhtp_t *)SSL_CTX_get_app_data(ctx);
2909  cfg = htp->ssl_cfg;
2910  sid = (evhtp_ssl_data_t *)SSL_SESSION_get_id(sess, &slen);
2911 
2912  if (cfg->scache_del)
2913  {
2914  (cfg->scache_del)(htp, sid, slen);
2915  }
2916 }
2917 
2918 static int
2920 {
2921  evhtp_connection_t * connection;
2922  evhtp_ssl_cfg_t * cfg;
2923  evhtp_ssl_data_t * sid;
2924  int slen;
2925 
2926  connection = (evhtp_connection_t *)SSL_get_app_data(ssl);
2927  if (connection->htp == NULL)
2928  {
2929  return 0; /* We cannot get the ssl_cfg */
2930  }
2931 
2932  cfg = connection->htp->ssl_cfg;
2933  sid = (evhtp_ssl_data_t *)SSL_SESSION_get_id(sess, &slen);
2934 
2935  SSL_set_timeout(sess, cfg->scache_timeout);
2936 
2937  if (cfg->scache_add)
2938  {
2939  return (cfg->scache_add)(connection, sid, slen, sess);
2940  }
2941 
2942  return 0;
2943 }
2944 
2945 static evhtp_ssl_sess_t *
2946 htp__ssl_get_scache_ent_(evhtp_ssl_t * ssl, evhtp_ssl_data_t * sid, int sid_len, int * copy)
2947 {
2948  evhtp_connection_t * connection;
2949  evhtp_ssl_cfg_t * cfg;
2950  evhtp_ssl_sess_t * sess;
2951 
2952  connection = (evhtp_connection_t * )SSL_get_app_data(ssl);
2953 
2954  if (connection->htp == NULL)
2955  {
2956  return NULL; /* We have no way of getting ssl_cfg */
2957  }
2958  cfg = connection->htp->ssl_cfg;
2959  sess = NULL;
2960 
2961  if (cfg->scache_get)
2962  {
2963  sess = (cfg->scache_get)(connection, sid, sid_len);
2964  }
2965 
2966  *copy = 0;
2967 
2968  return sess;
2969 }
2970 
2971 static int
2972 htp__ssl_servername_(evhtp_ssl_t * ssl, int * unused, void * arg)
2973 {
2974  const char * sname;
2975  evhtp_connection_t * connection;
2976  evhtp_t * evhtp;
2977  evhtp_t * evhtp_vhost;
2978 
2979  if (evhtp_unlikely(ssl == NULL))
2980  {
2981  return SSL_TLSEXT_ERR_NOACK;
2982  }
2983 
2984  if (!(sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)))
2985  {
2986  return SSL_TLSEXT_ERR_NOACK;
2987  }
2988 
2989  if (!(connection = SSL_get_app_data(ssl)))
2990  {
2991  return SSL_TLSEXT_ERR_NOACK;
2992  }
2993 
2994  if (!(evhtp = connection->htp))
2995  {
2996  return SSL_TLSEXT_ERR_NOACK;
2997  }
2998 
2999  if ((evhtp_vhost = htp__request_find_vhost_(evhtp, sname)))
3000  {
3001  SSL_CTX * ctx = SSL_get_SSL_CTX(ssl);
3002 
3003  connection->htp = evhtp_vhost;
3004 
3006 
3007  SSL_set_SSL_CTX(ssl, evhtp_vhost->ssl_ctx);
3008  SSL_set_options(ssl, SSL_CTX_get_options(ctx));
3009 
3010  if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
3011  (SSL_num_renegotiations(ssl) == 0))
3012  {
3013  SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx),
3014  SSL_CTX_get_verify_callback(ctx));
3015  }
3016 
3017  return SSL_TLSEXT_ERR_OK;
3018  }
3019 
3020  return SSL_TLSEXT_ERR_NOACK;
3021 } /* htp__ssl_servername_ */
3022 
3023 #endif
3024 
3025 /*
3026  * PUBLIC FUNCTIONS
3027  */
3028 
3029 htp_method
3030 evhtp_request_get_method(evhtp_request_t * r)
3031 {
3032  evhtp_assert(r != NULL);
3033  evhtp_assert(r->conn != NULL);
3034  evhtp_assert(r->conn->parser != NULL);
3035 
3036  return htparser_get_method(r->conn->parser);
3037 }
3038 
3039 void
3040 evhtp_connection_pause(evhtp_connection_t * c)
3041 {
3042  evhtp_assert(c != NULL);
3043 
3045 
3046  bufferevent_disable(c->bev, EV_READ | EV_WRITE);
3047 
3048  return;
3049 }
3050 
3051 void
3052 evhtp_connection_resume(evhtp_connection_t * c)
3053 {
3054  evhtp_assert(c != NULL);
3055 
3057 
3058  event_active(c->resume_ev, EV_WRITE, 1);
3059 
3060  return;
3061 }
3062 
3063 void
3064 evhtp_request_pause(evhtp_request_t * request)
3065 {
3066  evhtp_assert(request != NULL);
3067 
3068  request->status = EVHTP_RES_PAUSE;
3069  evhtp_connection_pause(request->conn);
3070 }
3071 
3072 void
3073 evhtp_request_resume(evhtp_request_t * request)
3074 {
3075  evhtp_assert(request != NULL);
3076 
3077  evhtp_connection_resume(request->conn);
3078 }
3079 
3081 evhtp_header_key_add(evhtp_headers_t * headers, const char * key, char key_alloc)
3082 {
3083  evhtp_header_t * header;
3084 
3085  if (!(header = evhtp_header_new(key, NULL, key_alloc, 0)))
3086  {
3087  return NULL;
3088  }
3089 
3090  evhtp_headers_add_header(headers, header);
3091 
3092  return header;
3093 }
3094 
3096 evhtp_header_val_add(evhtp_headers_t * headers, const char * val, char val_alloc)
3097 {
3098  evhtp_header_t * header;
3099 
3100  if (!headers || !val)
3101  {
3102  return NULL;
3103  }
3104 
3105  if (!(header = TAILQ_LAST(headers, evhtp_headers_s)))
3106  {
3107  return NULL;
3108  }
3109 
3110  if (header->val != NULL)
3111  {
3112  return NULL;
3113  }
3114 
3115  header->vlen = strlen(val);
3116 
3117  if (val_alloc == 1)
3118  {
3119  header->val = htp__malloc_(header->vlen + 1);
3120  evhtp_alloc_assert(header->val);
3121 
3122  header->val[header->vlen] = '\0';
3123  memcpy(header->val, val, header->vlen);
3124  } else {
3125  header->val = (char *)val;
3126  }
3127 
3128  header->v_heaped = val_alloc;
3129 
3130  return header;
3131 }
3132 
3133 evhtp_kvs_t *
3135 {
3136  evhtp_kvs_t * kvs;
3137 
3138  kvs = htp__malloc_(sizeof(evhtp_kvs_t));
3139  evhtp_alloc_assert(kvs);
3140 
3141  TAILQ_INIT(kvs);
3142 
3143  return kvs;
3144 }
3145 
3146 evhtp_kv_t *
3147 evhtp_kv_new(const char * key, const char * val,
3148  char key_alloc, char val_alloc)
3149 {
3150  evhtp_kv_t * kv;
3151 
3152  kv = htp__malloc_(sizeof(evhtp_kv_t));
3153  evhtp_alloc_assert(kv);
3154 
3155  kv->k_heaped = key_alloc;
3156  kv->v_heaped = val_alloc;
3157  kv->klen = 0;
3158  kv->vlen = 0;
3159  kv->key = NULL;
3160  kv->val = NULL;
3161 
3162  if (key != NULL)
3163  {
3164  kv->klen = strlen(key);
3165 
3166  if (key_alloc == 1)
3167  {
3168  char * s;
3169 
3170  if (!(s = htp__malloc_(kv->klen + 1)))
3171  {
3173 
3174  return NULL;
3175  }
3176 
3177  memcpy(s, key, kv->klen);
3178 
3179  s[kv->klen] = '\0';
3180  kv->key = s;
3181  } else {
3182  kv->key = (char *)key;
3183  }
3184  }
3185 
3186  if (val != NULL)
3187  {
3188  kv->vlen = strlen(val);
3189 
3190  if (val_alloc == 1)
3191  {
3192  char * s = htp__malloc_(kv->vlen + 1);
3193 
3194  s[kv->vlen] = '\0';
3195  memcpy(s, val, kv->vlen);
3196  kv->val = s;
3197  } else {
3198  kv->val = (char *)val;
3199  }
3200  }
3201 
3202  return kv;
3203 } /* evhtp_kv_new */
3204 
3205 void
3206 evhtp_kv_free(evhtp_kv_t * kv)
3207 {
3208  if (evhtp_unlikely(kv == NULL))
3209  {
3210  return;
3211  }
3212 
3213  if (kv->k_heaped)
3214  {
3215  evhtp_safe_free(kv->key, htp__free_);
3216  }
3217 
3218  if (kv->v_heaped)
3219  {
3220  evhtp_safe_free(kv->val, htp__free_);
3221  }
3222 
3224 }
3225 
3226 void
3227 evhtp_kv_rm_and_free(evhtp_kvs_t * kvs, evhtp_kv_t * kv)
3228 {
3229  if (evhtp_unlikely(kvs == NULL || kv == NULL))
3230  {
3231  return;
3232  }
3233 
3234  TAILQ_REMOVE(kvs, kv, next);
3235 
3236  evhtp_kv_free(kv);
3237 }
3238 
3239 void
3241 {
3242  evhtp_kv_t * kv;
3243  evhtp_kv_t * save;
3244 
3245  if (evhtp_unlikely(kvs == NULL))
3246  {
3247  return;
3248  }
3249 
3250  kv = NULL;
3251  save = NULL;
3252 
3253  for (kv = TAILQ_FIRST(kvs); kv != NULL; kv = save)
3254  {
3255  save = TAILQ_NEXT(kv, next);
3256 
3257  TAILQ_REMOVE(kvs, kv, next);
3258 
3260  }
3261 
3263 }
3264 
3265 int
3267 {
3268  evhtp_kv_t * kv;
3269 
3270  if (kvs == NULL || cb == NULL)
3271  {
3272  return -1;
3273  }
3274 
3275  TAILQ_FOREACH(kv, kvs, next) {
3276  int res;
3277 
3278  if ((res = cb(kv, arg)))
3279  {
3280  return res;
3281  }
3282  }
3283 
3284  return 0;
3285 }
3286 
3287 const char *
3288 evhtp_kv_find(evhtp_kvs_t * kvs, const char * key)
3289 {
3290  evhtp_kv_t * kv;
3291 
3292  if (evhtp_unlikely(kvs == NULL || key == NULL))
3293  {
3294  return NULL;
3295  }
3296 
3297  TAILQ_FOREACH(kv, kvs, next) {
3298  if (strcasecmp(kv->key, key) == 0)
3299  {
3300  return kv->val;
3301  }
3302  }
3303 
3304  return NULL;
3305 }
3306 
3307 evhtp_kv_t *
3308 evhtp_kvs_find_kv(evhtp_kvs_t * kvs, const char * key)
3309 {
3310  evhtp_kv_t * kv;
3311 
3312  if (evhtp_unlikely(kvs == NULL || key == NULL))
3313  {
3314  return NULL;
3315  }
3316 
3317  TAILQ_FOREACH(kv, kvs, next) {
3318  if (strcasecmp(kv->key, key) == 0)
3319  {
3320  return kv;
3321  }
3322  }
3323 
3324  return NULL;
3325 }
3326 
3327 void
3328 evhtp_kvs_add_kv(evhtp_kvs_t * kvs, evhtp_kv_t * kv)
3329 {
3330  if (evhtp_unlikely(kvs == NULL || kv == NULL))
3331  {
3332  return;
3333  }
3334 
3335  TAILQ_INSERT_TAIL(kvs, kv, next);
3336 }
3337 
3338 void
3340 {
3341  if (dst == NULL || src == NULL)
3342  {
3343  return;
3344  }
3345 
3346  evhtp_kv_t * kv;
3347 
3348  TAILQ_FOREACH(kv, src, next) {
3349  evhtp_kvs_add_kv(dst, evhtp_kv_new(kv->key,
3350  kv->val,
3351  kv->k_heaped,
3352  kv->v_heaped));
3353  }
3354 }
3355 
3356 typedef enum {
3367 
3368 static inline int
3369 evhtp_is_hex_query_char(unsigned char ch)
3370 {
3371  switch (ch) {
3372  case 'a': case 'A':
3373  case 'b': case 'B':
3374  case 'c': case 'C':
3375  case 'd': case 'D':
3376  case 'e': case 'E':
3377  case 'f': case 'F':
3378  case '0':
3379  case '1':
3380  case '2':
3381  case '3':
3382  case '4':
3383  case '5':
3384  case '6':
3385  case '7':
3386  case '8':
3387  case '9':
3388 
3389  return 1;
3390  default:
3391 
3392  return 0;
3393  } /* switch */
3394 }
3395 
3400 };
3401 
3402 int
3403 evhtp_unescape_string(unsigned char ** out, unsigned char * str, size_t str_len)
3404 {
3405  unsigned char * optr;
3406  unsigned char * sptr;
3407  unsigned char d;
3408  unsigned char ch;
3409  unsigned char c;
3410  size_t i;
3411  enum unscape_state state;
3412 
3413  state = unscape_state_start;
3414  optr = *out;
3415  sptr = str;
3416  d = 0;
3417  *out = NULL;
3418 
3419  for (i = 0; i < str_len; i++)
3420  {
3421  ch = *sptr++;
3422 
3423  switch (state) {
3424  case unscape_state_start:
3425  if (ch == '%')
3426  {
3427  state = unscape_state_hex1;
3428  break;
3429  }
3430 
3431  *optr++ = ch;
3432 
3433  break;
3434  case unscape_state_hex1:
3435  if (ch >= '0' && ch <= '9')
3436  {
3437  d = (unsigned char)(ch - '0');
3438  state = unscape_state_hex2;
3439  break;
3440  }
3441 
3442  c = (unsigned char)(ch | 0x20);
3443 
3444  if (c >= 'a' && c <= 'f')
3445  {
3446  d = (unsigned char)(c - 'a' + 10);
3447  state = unscape_state_hex2;
3448  break;
3449  }
3450 
3451  state = unscape_state_start;
3452  *optr++ = ch;
3453  break;
3454  case unscape_state_hex2:
3455  state = unscape_state_start;
3456 
3457  if (ch >= '0' && ch <= '9')
3458  {
3459  ch = (unsigned char)((d << 4) + ch - '0');
3460 
3461  *optr++ = ch;
3462  break;
3463  }
3464 
3465  c = (unsigned char)(ch | 0x20);
3466 
3467  if (c >= 'a' && c <= 'f')
3468  {
3469  ch = (unsigned char)((d << 4) + c - 'a' + 10);
3470  *optr++ = ch;
3471  break;
3472  }
3473 
3474  break;
3475  } /* switch */
3476  }
3477 
3478  return 0;
3479 } /* evhtp_unescape_string */
3480 
3481 evhtp_query_t *
3482 evhtp_parse_query_wflags(const char * query, const size_t len, const int flags)
3483 {
3484  evhtp_query_t * query_args;
3485  query_parser_state state;
3486  size_t key_idx;
3487  size_t val_idx;
3488  unsigned char ch;
3489  size_t i;
3490 
3491  if (len > (SIZE_MAX - (len + 2)))
3492  {
3493  return NULL;
3494  }
3495 
3496  query_args = evhtp_query_new();
3497 
3498  state = s_query_start;
3499  key_idx = 0;
3500  val_idx = 0;
3501 
3502 #ifdef EVHTP_HAS_C99
3503  char key_buf[len + 1];
3504  char val_buf[len + 1];
3505 #else
3506  char * key_buf;
3507  char * val_buf;
3508 
3509  key_buf = htp__malloc_(len + 1);
3510  evhtp_alloc_assert(key_buf);
3511 
3512  val_buf = htp__malloc_(len + 1);
3513  evhtp_alloc_assert(val_buf);
3514 #endif
3515 
3516  for (i = 0; i < len; i++)
3517  {
3518  ch = query[i];
3519 
3520  if (key_idx >= len || val_idx >= len)
3521  {
3522  goto error;
3523  }
3524 
3525  switch (state) {
3526  case s_query_start:
3527  key_idx = 0;
3528  val_idx = 0;
3529 
3530  key_buf[0] = '\0';
3531  val_buf[0] = '\0';
3532 
3533  state = s_query_key;
3534  /* Fall through. */
3535  case s_query_key:
3536  switch (ch) {
3537  case '=':
3538  state = s_query_val;
3539  break;
3540  case '%':
3541  key_buf[key_idx++] = ch;
3542  key_buf[key_idx] = '\0';
3543 
3544  if (!(flags & EVHTP_PARSE_QUERY_FLAG_IGNORE_HEX))
3545  {
3546  state = s_query_key_hex_1;
3547  }
3548 
3549  break;
3550  case ';':
3552  {
3553  key_buf[key_idx++] = ch;
3554  key_buf[key_idx] = '\0';
3555  break;
3556  }
3557 
3558  /* otherwise we fallthrough */
3559  case '&':
3560  /* in this state, we have a NULL value */
3562  {
3563  goto error;
3564  }
3565 
3566  /* insert the key with value of NULL and set the
3567  * state back to parsing s_query_key.
3568  */
3569  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, NULL, 1, 1));
3570 
3571  key_idx = 0;
3572  val_idx = 0;
3573 
3574  key_buf[0] = '\0';
3575  val_buf[0] = '\0';
3576 
3577  state = s_query_key;
3578  break;
3579  default:
3580  key_buf[key_idx++] = ch;
3581  key_buf[key_idx] = '\0';
3582  break;
3583  } /* switch */
3584  break;
3585  case s_query_key_hex_1:
3586  if (!evhtp_is_hex_query_char(ch))
3587  {
3588  /* not hex, so we treat as a normal key */
3589  if ((key_idx + 2) >= len)
3590  {
3591  /* we need to insert \%<ch>, but not enough space */
3592  goto error;
3593  }
3594 
3595  key_buf[key_idx - 1] = '%';
3596  key_buf[key_idx++] = ch;
3597  key_buf[key_idx] = '\0';
3598 
3599  state = s_query_key;
3600  break;
3601  }
3602 
3603  key_buf[key_idx++] = ch;
3604  key_buf[key_idx] = '\0';
3605 
3606  state = s_query_key_hex_2;
3607  break;
3608  case s_query_key_hex_2:
3609  if (!evhtp_is_hex_query_char(ch))
3610  {
3611  goto error;
3612  }
3613 
3614  key_buf[key_idx++] = ch;
3615  key_buf[key_idx] = '\0';
3616 
3617  state = s_query_key;
3618  break;
3619  case s_query_val:
3620  switch (ch) {
3621  case ';':
3623  {
3624  val_buf[val_idx++] = ch;
3625  val_buf[val_idx] = '\0';
3626  break;
3627  }
3628  case '&':
3629  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, val_buf, 1, 1));
3630 
3631  key_idx = 0;
3632  val_idx = 0;
3633 
3634  key_buf[0] = '\0';
3635  val_buf[0] = '\0';
3636  state = s_query_key;
3637 
3638  break;
3639  case '%':
3640  val_buf[val_idx++] = ch;
3641  val_buf[val_idx] = '\0';
3642 
3643  if (!(flags & EVHTP_PARSE_QUERY_FLAG_IGNORE_HEX))
3644  {
3645  state = s_query_val_hex_1;
3646  }
3647 
3648  break;
3649  default:
3650  val_buf[val_idx++] = ch;
3651  val_buf[val_idx] = '\0';
3652 
3653  break;
3654  } /* switch */
3655  break;
3656  case s_query_val_hex_1:
3657  if (!evhtp_is_hex_query_char(ch))
3658  {
3659  /* not really a hex val */
3660  if ((val_idx + 2) >= len)
3661  {
3662  /* we need to insert \%<ch>, but not enough space */
3663  goto error;
3664  }
3665 
3666  if (val_idx == 0)
3667  {
3668  goto error;
3669  }
3670 
3671  val_buf[val_idx - 1] = '%';
3672  val_buf[val_idx++] = ch;
3673  val_buf[val_idx] = '\0';
3674 
3675  state = s_query_val;
3676  break;
3677  }
3678 
3679  val_buf[val_idx++] = ch;
3680  val_buf[val_idx] = '\0';
3681 
3682  state = s_query_val_hex_2;
3683  break;
3684  case s_query_val_hex_2:
3685  if (!evhtp_is_hex_query_char(ch))
3686  {
3687  goto error;
3688  }
3689 
3690  val_buf[val_idx++] = ch;
3691  val_buf[val_idx] = '\0';
3692 
3693  state = s_query_val;
3694  break;
3695  default:
3696  /* bad state */
3697  goto error;
3698  } /* switch */
3699  }
3700 
3701  if (key_idx)
3702  {
3703  do {
3704  if (val_idx)
3705  {
3706  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, val_buf, 1, 1));
3707  break;
3708  }
3709 
3710  if (state >= s_query_val)
3711  {
3713  {
3714  goto error;
3715  }
3716 
3717  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, "", 1, 1));
3718  break;
3719  }
3720 
3722  {
3723  goto error;
3724  }
3725 
3726  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, NULL, 1, 0));
3727  } while (0);
3728  }
3729 
3730 #ifndef EVHTP_HAS_C99
3731  evhtp_safe_free(key_buf, htp__free_);
3732  evhtp_safe_free(val_buf, htp__free_);
3733 #endif
3734 
3735  return query_args;
3736 error:
3737 #ifndef EVHTP_HAS_C99
3738  evhtp_safe_free(key_buf, htp__free_);
3739  evhtp_safe_free(val_buf, htp__free_);
3740 #endif
3741 
3742  evhtp_query_free(query_args);
3743 
3744  return NULL;
3745 } /* evhtp_parse_query */
3746 
3747 evhtp_query_t *
3748 evhtp_parse_query(const char * query, size_t len)
3749 {
3750  return evhtp_parse_query_wflags(query, len,
3752 }
3753 
3754 void
3755 evhtp_send_reply_start(evhtp_request_t * request, evhtp_res code)
3756 {
3757  evhtp_connection_t * c;
3758  struct evbuffer * reply_buf;
3759 
3760  c = evhtp_request_get_connection(request);
3761 
3762  if (!(reply_buf = htp__create_reply_(request, code)))
3763  {
3765 
3766  return;
3767  }
3768 
3769  bufferevent_write_buffer(c->bev, reply_buf);
3770  evbuffer_drain(reply_buf, -1);
3771 }
3772 
3773 void
3774 evhtp_send_reply_body(evhtp_request_t * request, struct evbuffer * buf)
3775 {
3776  evhtp_connection_t * c;
3777 
3778  c = request->conn;
3779 
3780  bufferevent_write_buffer(c->bev, buf);
3781 }
3782 
3783 void
3784 evhtp_send_reply_end(evhtp_request_t * request)
3785 {
3787 }
3788 
3789 void
3790 evhtp_send_reply(evhtp_request_t * request, evhtp_res code)
3791 {
3792  evhtp_connection_t * c;
3793  struct evbuffer * reply_buf;
3794  struct bufferevent * bev;
3795 
3796  c = request->conn;
3797 
3799 
3800  if (!(reply_buf = htp__create_reply_(request, code)))
3801  {
3802  evhtp_connection_free(request->conn);
3803 
3804  return;
3805  }
3806 
3807  bev = c->bev;
3808 
3809  bufferevent_lock(bev);
3810  {
3811  bufferevent_write_buffer(bev, reply_buf);
3812  }
3813  bufferevent_unlock(bev);
3814 
3815  evbuffer_drain(reply_buf, -1);
3816 }
3817 
3818 int
3819 evhtp_response_needs_body(const evhtp_res code, const htp_method method)
3820 {
3821  return code != EVHTP_RES_NOCONTENT &&
3822  code != EVHTP_RES_NOTMOD &&
3823  (code < 100 || code >= 200) &&
3824  method != htp_method_HEAD;
3825 }
3826 
3827 void
3828 evhtp_send_reply_chunk_start(evhtp_request_t * request, evhtp_res code)
3829 {
3830  evhtp_header_t * content_len;
3831 
3832  if (evhtp_response_needs_body(code, request->method))
3833  {
3834  content_len = evhtp_headers_find_header(request->headers_out, "Content-Length");
3835 
3836  switch (request->proto) {
3837  case EVHTP_PROTO_11:
3838 
3839  /*
3840  * prefer HTTP/1.1 chunked encoding to closing the connection;
3841  * note RFC 2616 section 4.4 forbids it with Content-Length:
3842  * and it's not necessary then anyway.
3843  */
3844 
3845  evhtp_kv_rm_and_free(request->headers_out, content_len);
3846 
3848  break;
3849  case EVHTP_PROTO_10:
3850  /*
3851  * HTTP/1.0 can be chunked as long as the Content-Length header
3852  * is set to 0
3853  */
3854  evhtp_kv_rm_and_free(request->headers_out, content_len);
3855 
3857  break;
3858  default:
3860  break;
3861  } /* switch */
3862  } else {
3864  }
3865 
3866  if (request->flags & EVHTP_REQ_FLAG_CHUNKED)
3867  {
3868  evhtp_headers_add_header(request->headers_out,
3869  evhtp_header_new("Transfer-Encoding", "chunked", 0, 0));
3870 
3871  /*
3872  * if data already exists on the output buffer, we automagically convert
3873  * it to the first chunk.
3874  */
3875  if (evbuffer_get_length(request->buffer_out) > 0)
3876  {
3877  char lstr[128];
3878  int sres;
3879 
3880  sres = snprintf(lstr, sizeof(lstr), "%x\r\n",
3881  (unsigned)evbuffer_get_length(request->buffer_out));
3882 
3883  if (sres >= sizeof(lstr) || sres < 0)
3884  {
3885  /* overflow condition, shouldn't ever get here, but lets
3886  * terminate the connection asap */
3887  goto end;
3888  }
3889 
3890  evbuffer_prepend(request->buffer_out, lstr, strlen(lstr));
3891  evbuffer_add(request->buffer_out, "\r\n", 2);
3892  }
3893  }
3894 
3895 end:
3896  evhtp_send_reply_start(request, code);
3897 } /* evhtp_send_reply_chunk_start */
3898 
3899 void
3900 evhtp_send_reply_chunk(evhtp_request_t * request, struct evbuffer * buf)
3901 {
3902  struct evbuffer * output;
3903 
3904  if (evbuffer_get_length(buf) == 0)
3905  {
3906  return;
3907  }
3908 
3909  output = bufferevent_get_output(request->conn->bev);
3910 
3911  if (request->flags & EVHTP_REQ_FLAG_CHUNKED)
3912  {
3913  evbuffer_add_printf(output, "%x\r\n",
3914  (unsigned)evbuffer_get_length(buf));
3915  }
3916 
3917  evhtp_send_reply_body(request, buf);
3918 
3919  if (request->flags & EVHTP_REQ_FLAG_CHUNKED)
3920  {
3921  evbuffer_add(output, "\r\n", 2);
3922  }
3923 
3924  bufferevent_flush(request->conn->bev, EV_WRITE, BEV_FLUSH);
3925 }
3926 
3927 void
3928 evhtp_send_reply_chunk_end(evhtp_request_t * request)
3929 {
3930  if (request->flags & EVHTP_REQ_FLAG_CHUNKED)
3931  {
3932  evbuffer_add(bufferevent_get_output(evhtp_request_get_bev(request)),
3933  "0\r\n\r\n", 5);
3934  }
3935 
3936  evhtp_send_reply_end(request);
3937 }
3938 
3939 void
3940 evhtp_unbind_socket(evhtp_t * htp)
3941 {
3942  if (htp == NULL || htp->server == NULL)
3943  {
3944  return;
3945  }
3946 
3947  evhtp_safe_free(htp->server, evconnlistener_free);
3948 }
3949 
3950 int
3951 evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
3952 {
3953  int on = 1;
3954  int err = 1;
3955 
3956  if (htp == NULL || sock == -1)
3957  {
3958  return -1;
3959  }
3960 
3961  do {
3962 #if defined SO_REUSEPORT
3963  if (htp->flags & EVHTP_FLAG_ENABLE_REUSEPORT)
3964  {
3965  if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) == -1)
3966  {
3967  break;
3968  }
3969  }
3970 #endif
3971 
3972 #if defined TCP_NODELAY
3973  if (htp->flags & EVHTP_FLAG_ENABLE_NODELAY)
3974  {
3975  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) == -1)
3976  {
3977  break;
3978  }
3979  }
3980 #endif
3981 
3982 #if defined TCP_DEFER_ACCEPT
3983  if (htp->flags & EVHTP_FLAG_ENABLE_DEFER_ACCEPT)
3984  {
3985  if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void *)&on, sizeof(on)) == -1)
3986  {
3987  break;
3988  }
3989  }
3990 #endif
3991 
3992  htp->server = evconnlistener_new(htp->evbase, htp__accept_cb_, htp,
3993  LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
3994  backlog, sock);
3995 
3996  if (htp->server == NULL)
3997  {
3998  break;
3999  }
4000 
4001 #ifndef EVHTP_DISABLE_SSL
4002  if (htp->ssl_ctx != NULL)
4003  {
4004  /* if ssl is enabled and we have virtual hosts, set our servername
4005  * callback. We do this here because we want to make sure that this gets
4006  * set after all potential virtualhosts have been set, not just after
4007  * ssl_init.
4008  */
4009  if (TAILQ_FIRST(&htp->vhosts) != NULL)
4010  {
4011  SSL_CTX_set_tlsext_servername_callback(htp->ssl_ctx,
4013  }
4014  }
4015 #endif
4016  err = 0;
4017  } while (0);
4018 
4019  if (err == 1)
4020  {
4021  if (htp->server != NULL)
4022  {
4023  evhtp_safe_free(htp->server, evconnlistener_free);
4024  }
4025 
4026  return -1;
4027  }
4028 
4029  return 0;
4030 } /* evhtp_accept_socket */
4031 
4032 int
4033 evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int backlog)
4034 {
4035  evutil_socket_t fd = -1;
4036  int on = 1;
4037  int error = 1;
4038 
4039  if (htp == NULL)
4040  {
4041  return -1;
4042  }
4043 
4044  /* XXX: API's should not set signals */
4045 #ifndef WIN32
4046  signal(SIGPIPE, SIG_IGN);
4047 #endif
4048 
4049  do {
4050  if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1)
4051  {
4052  return -1;
4053  }
4054 
4055 
4056  evutil_make_socket_closeonexec(fd);
4057  evutil_make_socket_nonblocking(fd);
4058 
4059  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1)
4060  {
4061  break;
4062  }
4063 
4064  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == -1)
4065  {
4066  break;
4067  }
4068 
4069  if (sa->sa_family == AF_INET6)
4070  {
4071  if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
4072  {
4073  break;
4074  }
4075  }
4076 
4077  if (bind(fd, sa, sin_len) == -1)
4078  {
4079  break;
4080  }
4081 
4082  error = 0;
4083  } while (0);
4084 
4085 
4086  if (error == 1)
4087  {
4088  if (fd != -1)
4089  {
4090  evutil_closesocket(fd);
4091  }
4092 
4093  return -1;
4094  }
4095 
4096  if (evhtp_accept_socket(htp, fd, backlog) == -1)
4097  {
4098  /* accept_socket() does not close the descriptor
4099  * on error, but this function does.
4100  */
4101  evutil_closesocket(fd);
4102 
4103  return -1;
4104  }
4105 
4106  return 0;
4107 } /* evhtp_bind_sockaddr */
4108 
4109 int
4110 evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog)
4111 {
4112 #ifndef NO_SYS_UN
4113  struct sockaddr_un sockun = { 0 };
4114 #endif
4115  struct sockaddr * sa;
4116  struct sockaddr_in6 sin6 = { 0 };
4117  struct sockaddr_in sin = { 0 };
4118  size_t sin_len;
4119 
4120  if (!strncmp(baddr, "ipv6:", 5))
4121  {
4122  baddr += 5;
4123  sin_len = sizeof(struct sockaddr_in6);
4124  sin6.sin6_port = htons(port);
4125  sin6.sin6_family = AF_INET6;
4126 
4127  evutil_inet_pton(AF_INET6, baddr, &sin6.sin6_addr);
4128  sa = (struct sockaddr *)&sin6;
4129  } else if (!strncmp(baddr, "unix:", 5))
4130  {
4131 #ifndef NO_SYS_UN
4132  baddr += 5;
4133 
4134  if (strlen(baddr) >= sizeof(sockun.sun_path))
4135  {
4136  return -1;
4137  }
4138 
4139  sin_len = sizeof(struct sockaddr_un);
4140  sockun.sun_family = AF_UNIX;
4141 
4142  strncpy(sockun.sun_path, baddr, strlen(baddr));
4143 
4144  sa = (struct sockaddr *)&sockun;
4145 #else
4146 
4147  return -1;
4148 #endif
4149  } else {
4150  if (!strncmp(baddr, "ipv4:", 5))
4151  {
4152  baddr += 5;
4153  }
4154 
4155  sin_len = sizeof(struct sockaddr_in);
4156  sin.sin_family = AF_INET;
4157  sin.sin_port = htons(port);
4158  sin.sin_addr.s_addr = inet_addr(baddr);
4159 
4160  sa = (struct sockaddr *)&sin;
4161  }
4162 
4163  return evhtp_bind_sockaddr(htp, sa, sin_len, backlog);
4164 } /* evhtp_bind_socket */
4165 
4166 void
4168 {
4169  evhtp_callback_t * callback;
4170  evhtp_callback_t * tmp;
4171 
4172  if (callbacks == NULL)
4173  {
4174  return;
4175  }
4176 
4177  TAILQ_FOREACH_SAFE(callback, callbacks, next, tmp) {
4178  TAILQ_REMOVE(callbacks, callback, next);
4179 
4181  }
4182 
4183  evhtp_safe_free(callbacks, htp__free_);
4184 }
4185 
4186 evhtp_callback_t *
4188 {
4189  evhtp_callback_t * hcb;
4190 
4191  hcb = htp__calloc_(sizeof(evhtp_callback_t), 1);
4192  evhtp_alloc_assert(hcb);
4193 
4194  hcb->type = type;
4195  hcb->cb = cb;
4196  hcb->cbarg = arg;
4197  hcb->len = strlen(path);
4198 
4199  switch (type) {
4201  hcb->val.path = htp__strdup_(path);
4202  evhtp_alloc_assert(hcb->val.path);
4203  break;
4204 #ifndef EVHTP_DISABLE_REGEX
4206  hcb->val.regex = htp__malloc_(sizeof(regex_t));
4207  evhtp_alloc_assert(hcb->val.regex);
4208 
4209  if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0)
4210  {
4211  evhtp_safe_free(hcb->val.regex, htp__free_);
4213 
4214  return NULL;
4215  }
4216  break;
4217 #endif
4219  hcb->val.glob = htp__strdup_(path);
4220  evhtp_alloc_assert(hcb->val.glob);
4221  break;
4222  default:
4224 
4225  return NULL;
4226  } /* switch */
4227 
4228  return hcb;
4229 } /* evhtp_callback_new */
4230 
4231 void
4232 evhtp_callback_free(evhtp_callback_t * callback)
4233 {
4234  if (callback == NULL)
4235  {
4236  return;
4237  }
4238 
4239  switch (callback->type) {
4241  evhtp_safe_free(callback->val.path, htp__free_);
4242  break;
4244  evhtp_safe_free(callback->val.glob, htp__free_);
4245  break;
4246 #ifndef EVHTP_DISABLE_REGEX
4248  regfree(callback->val.regex);
4249  evhtp_safe_free(callback->val.regex, htp__free_);
4250  break;
4251 #endif
4252  }
4253 
4254  if (callback->hooks)
4255  {
4256  evhtp_safe_free(callback->hooks, htp__free_);
4257  }
4258 
4259  evhtp_safe_free(callback, htp__free_);
4260 
4261  return;
4262 }
4263 
4264 int
4266 {
4267  TAILQ_INSERT_TAIL(cbs, cb, next);
4268 
4269  return 0;
4270 }
4271 
4272 static int
4273 htp__set_hook_(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
4274 {
4275  if (*hooks == NULL)
4276  {
4277  if (!(*hooks = htp__calloc_(sizeof(evhtp_hooks_t), 1)))
4278  {
4279  return -1;
4280  }
4281  }
4282 
4283  switch (type) {
4285  (*hooks)->on_headers_start = (evhtp_hook_headers_start_cb)cb;
4286  (*hooks)->on_headers_start_arg = arg;
4287  break;
4288  case evhtp_hook_on_header:
4289  (*hooks)->on_header = (evhtp_hook_header_cb)cb;
4290  (*hooks)->on_header_arg = arg;
4291  break;
4292  case evhtp_hook_on_headers:
4293  (*hooks)->on_headers = (evhtp_hook_headers_cb)cb;
4294  (*hooks)->on_headers_arg = arg;
4295  break;
4296  case evhtp_hook_on_path:
4297  (*hooks)->on_path = (evhtp_hook_path_cb)cb;
4298  (*hooks)->on_path_arg = arg;
4299  break;
4300  case evhtp_hook_on_read:
4301  (*hooks)->on_read = (evhtp_hook_read_cb)cb;
4302  (*hooks)->on_read_arg = arg;
4303  break;
4305  (*hooks)->on_request_fini = (evhtp_hook_request_fini_cb)cb;
4306  (*hooks)->on_request_fini_arg = arg;
4307  break;
4309  (*hooks)->on_connection_fini = (evhtp_hook_connection_fini_cb)cb;
4310  (*hooks)->on_connection_fini_arg = arg;
4311  break;
4313  (*hooks)->on_connection_error = (evhtp_hook_conn_err_cb)cb;
4314  (*hooks)->on_connection_error_arg = arg;
4315  break;
4316  case evhtp_hook_on_error:
4317  (*hooks)->on_error = (evhtp_hook_err_cb)cb;
4318  (*hooks)->on_error_arg = arg;
4319  break;
4321  (*hooks)->on_new_chunk = (evhtp_hook_chunk_new_cb)cb;
4322  (*hooks)->on_new_chunk_arg = arg;
4323  break;
4325  (*hooks)->on_chunk_fini = (evhtp_hook_chunk_fini_cb)cb;
4326  (*hooks)->on_chunk_fini_arg = arg;
4327  break;
4329  (*hooks)->on_chunks_fini = (evhtp_hook_chunks_fini_cb)cb;
4330  (*hooks)->on_chunks_fini_arg = arg;
4331  break;
4333  (*hooks)->on_hostname = (evhtp_hook_hostname_cb)cb;
4334  (*hooks)->on_hostname_arg = arg;
4335  break;
4336  case evhtp_hook_on_write:
4337  (*hooks)->on_write = (evhtp_hook_write_cb)cb;
4338  (*hooks)->on_write_arg = arg;
4339  break;
4340  case evhtp_hook_on_event:
4341  (*hooks)->on_event = (evhtp_hook_event_cb)cb;
4342  (*hooks)->on_event_arg = arg;
4343  break;
4344  default:
4345  return -1;
4346  } /* switch */
4347 
4348  return 0;
4349 } /* htp__set_hook_ */
4350 
4351 static int
4353  return htp__set_hook_(hooks, type, NULL, NULL);
4354 }
4355 
4356 int
4357 evhtp_callback_unset_hook(evhtp_callback_t * callback, evhtp_hook_type type)
4358 {
4359  return htp__unset_hook_(&callback->hooks, type);
4360 }
4361 
4362 int
4364 {
4365  return htp__unset_hook_(&req->hooks, type);
4366 }
4367 
4368 int
4370 {
4371  return htp__unset_hook_(&conn->hooks, type);
4372 }
4373 
4374 int
4375 evhtp_callback_set_hook(evhtp_callback_t * callback, evhtp_hook_type type, evhtp_hook cb, void * arg)
4376 {
4377  return htp__set_hook_(&callback->hooks, type, cb, arg);
4378 }
4379 
4380 int
4381 evhtp_request_set_hook(evhtp_request_t * req, evhtp_hook_type type, evhtp_hook cb, void * arg)
4382 {
4383  return htp__set_hook_(&req->hooks, type, cb, arg);
4384 }
4385 
4386 int
4387 evhtp_connection_set_hook(evhtp_connection_t * conn, evhtp_hook_type type, evhtp_hook cb, void * arg)
4388 {
4389  return htp__set_hook_(&conn->hooks, type, cb, arg);
4390 }
4391 
4392 int
4393 evhtp_unset_all_hooks(evhtp_hooks_t ** hooks)
4394 {
4395  int i;
4396 
4397  struct {
4398  enum evhtp_hook_type type;
4399  } hooklist_[] = {
4402  { evhtp_hook_on_path },
4403  { evhtp_hook_on_read },
4410  { evhtp_hook_on_error },
4412  { evhtp_hook_on_write },
4413  { evhtp_hook_on_event },
4415  { -1 }
4416  };
4417 
4418  if (hooks == NULL) {
4419  return -1;
4420  }
4421 
4422  for (i = 0; hooklist_[i].type != -1; i++) {
4423  if (htp__unset_hook_(hooks, hooklist_[i].type) == -1) {
4424  return -1;
4425  }
4426  }
4427 
4428  return 0;
4429 }
4430 
4431 evhtp_hooks_t *
4432 evhtp_connection_get_hooks(evhtp_connection_t * c)
4433 {
4434  if (evhtp_unlikely(c == NULL))
4435  {
4436  return NULL;
4437  }
4438 
4439  return c->hooks;
4440 }
4441 
4448 evhtp_hooks_t *
4449 evhtp_request_get_hooks(evhtp_request_t * r)
4450 {
4451  if (evhtp_unlikely(r == NULL))
4452  {
4453  return NULL;
4454  }
4455 
4456  return r->hooks;
4457 }
4458 
4465 evhtp_hooks_t *
4466 evhtp_callback_get_hooks(evhtp_callback_t * cb)
4467 {
4468  return cb->hooks;
4469 }
4470 
4471 evhtp_callback_t *
4472 evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg)
4473 {
4474  evhtp_callback_t * hcb;
4475 
4476  htp__lock_(htp);
4477 
4478  if (htp->callbacks == NULL)
4479  {
4480  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4481  {
4482  htp__unlock_(htp);
4483 
4484  return NULL;
4485  }
4486 
4487  TAILQ_INIT(htp->callbacks);
4488  }
4489 
4490  if (!(hcb = evhtp_callback_new(path, evhtp_callback_type_hash, cb, arg)))
4491  {
4492  htp__unlock_(htp);
4493 
4494  return NULL;
4495  }
4496 
4497  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4498  {
4500  htp__unlock_(htp);
4501 
4502  return NULL;
4503  }
4504 
4505  htp__unlock_(htp);
4506 
4507  return hcb;
4508 }
4509 
4510 evhtp_callback_t *
4511 evhtp_get_cb(evhtp_t * htp, const char * path)
4512 {
4513  evhtp_callback_t * callback;
4514 
4515  evhtp_assert(htp != NULL);
4516 
4517  if (evhtp_unlikely(htp->callbacks == NULL))
4518  {
4519  return NULL;
4520  }
4521 
4522  TAILQ_FOREACH(callback, htp->callbacks, next) {
4523  if (strcmp(callback->val.path, path) == 0)
4524  {
4525  return callback;
4526  }
4527  }
4528 
4529  return NULL;
4530 }
4531 
4532 #ifndef EVHTP_DISABLE_EVTHR
4533 static void
4534 htp__thread_init_(evthr_t * thr, void * arg)
4535 {
4536  evhtp_t * htp = (evhtp_t *)arg;
4537 
4538  if (htp->thread_init_cb)
4539  {
4540  htp->thread_init_cb(htp, thr, htp->thread_cbarg);
4541  }
4542 }
4543 
4544 static void
4545 htp__thread_exit_(evthr_t * thr, void * arg)
4546 {
4547  evhtp_t * htp = (evhtp_t *)arg;
4548 
4549  if (htp->thread_exit_cb)
4550  {
4551  htp->thread_exit_cb(htp, thr, htp->thread_cbarg);
4552  }
4553 }
4554 
4555 static int
4556 htp__use_threads_(evhtp_t * htp,
4557  evhtp_thread_init_cb init_cb,
4558  evhtp_thread_exit_cb exit_cb,
4559  int nthreads, void * arg)
4560 {
4561  if (htp == NULL)
4562  {
4563  return -1;
4564  }
4565 
4566  htp->thread_cbarg = arg;
4567  htp->thread_init_cb = init_cb;
4568  htp->thread_exit_cb = exit_cb;
4569 
4570 #ifndef EVHTP_DISABLE_SSL
4572 #endif
4573 
4574  if (!(htp->thr_pool = evthr_pool_wexit_new(nthreads,
4576  htp__thread_exit_, htp)))
4577  {
4578  return -1;
4579  }
4580 
4581  evthr_pool_start(htp->thr_pool);
4582 
4583  return 0;
4584 }
4585 
4586 int
4588  int nthreads, void * arg)
4589 {
4590  return htp__use_threads_(htp, init_cb, NULL, nthreads, arg);
4591 }
4592 
4593 int
4595  evhtp_thread_init_cb init_cb,
4596  evhtp_thread_exit_cb exit_cb,
4597  int nthreads, void * arg)
4598 {
4599  return htp__use_threads_(htp, init_cb, exit_cb, nthreads, arg);
4600 }
4601 
4602 #endif
4603 
4604 #ifndef EVHTP_DISABLE_EVTHR
4605 int
4607 {
4608  if (htp == NULL)
4609  {
4610  return -1;
4611  }
4612 
4613  if (!(htp->lock = htp__malloc_(sizeof(pthread_mutex_t))))
4614  {
4615  return -1;
4616  }
4617 
4618  return pthread_mutex_init(htp->lock, NULL);
4619 }
4620 
4621 #endif
4622 
4623 #ifndef EVHTP_DISABLE_REGEX
4624 evhtp_callback_t *
4625 evhtp_set_regex_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg)
4626 {
4627  evhtp_callback_t * hcb;
4628 
4629  htp__lock_(htp);
4630 
4631  if (htp->callbacks == NULL)
4632  {
4633  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4634  {
4635  htp__unlock_(htp);
4636 
4637  return NULL;
4638  }
4639 
4640  TAILQ_INIT(htp->callbacks);
4641  }
4642 
4643  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_regex, cb, arg)))
4644  {
4645  htp__unlock_(htp);
4646 
4647  return NULL;
4648  }
4649 
4650  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4651  {
4653  htp__unlock_(htp);
4654 
4655  return NULL;
4656  }
4657 
4658  htp__unlock_(htp);
4659 
4660  return hcb;
4661 }
4662 
4663 #endif
4664 
4665 evhtp_callback_t *
4666 evhtp_set_glob_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg)
4667 {
4668  evhtp_callback_t * hcb;
4669 
4670  htp__lock_(htp);
4671 
4672  if (htp->callbacks == NULL)
4673  {
4674  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4675  {
4676  htp__unlock_(htp);
4677 
4678  return NULL;
4679  }
4680 
4681  TAILQ_INIT(htp->callbacks);
4682  }
4683 
4684  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_glob, cb, arg)))
4685  {
4686  htp__unlock_(htp);
4687 
4688  return NULL;
4689  }
4690 
4691  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4692  {
4694  htp__unlock_(htp);
4695 
4696  return NULL;
4697  }
4698 
4699  htp__unlock_(htp);
4700 
4701  return hcb;
4702 }
4703 
4704 void
4705 evhtp_set_gencb(evhtp_t * htp, evhtp_callback_cb cb, void * arg)
4706 {
4707  htp->defaults.cb = cb;
4708  htp->defaults.cbarg = arg;
4709 }
4710 
4711 void
4713 {
4714  htp->defaults.pre_accept = cb;
4715  htp->defaults.pre_accept_cbarg = arg;
4716 }
4717 
4718 void
4720 {
4721  htp->defaults.post_accept = cb;
4722  htp->defaults.post_accept_cbarg = arg;
4723 }
4724 
4725 #ifndef EVHTP_DISABLE_SSL
4726 #ifndef EVHTP_DISABLE_EVTHR
4727 int
4729 {
4730  int i;
4731 
4732  if (ssl_locks_initialized == 1)
4733  {
4734  return 0;
4735  }
4736 
4737  ssl_locks_initialized = 1;
4738  ssl_num_locks = CRYPTO_num_locks();
4739 
4740  if ((ssl_locks = htp__calloc_(ssl_num_locks,
4741  sizeof(evhtp_mutex_t))) == NULL)
4742  {
4743  return -1;
4744  }
4745 
4746  for (i = 0; i < ssl_num_locks; i++)
4747  {
4748  pthread_mutex_init(&(ssl_locks[i]), NULL);
4749  }
4750 
4751  CRYPTO_set_id_callback(htp__ssl_get_thread_id_);
4752  CRYPTO_set_locking_callback(htp__ssl_thread_lock_);
4753 
4754  return 0;
4755 }
4756 
4757 #endif
4758 
4759 int
4760 evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg)
4761 {
4762  long cache_mode;
4763  unsigned char c;
4764 
4765  if (cfg == NULL || htp == NULL || cfg->pemfile == NULL)
4766  {
4767  return -1;
4768  }
4769 
4770  SSL_library_init();
4771  ERR_load_crypto_strings();
4772  SSL_load_error_strings();
4773  OpenSSL_add_all_algorithms();
4774 
4775  if (RAND_poll() != 1) {
4776  log_error("RAND_poll");
4777  return -1;
4778  }
4779 
4780  if (RAND_bytes(&c, 1) != 1) {
4781  log_error("RAND_bytes");
4782  return -1;
4783  }
4784 
4785 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4786  STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
4787  sk_SSL_COMP_zero(comp_methods);
4788 #endif
4789 
4790  htp->ssl_cfg = cfg;
4791  htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
4792 
4793  evhtp_alloc_assert(htp->ssl_ctx);
4794 
4795 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
4796  SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS | SSL_OP_NO_COMPRESSION);
4797  SSL_CTX_set_timeout(htp->ssl_ctx, cfg->ssl_ctx_timeout);
4798 #endif
4799 
4800  SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);
4801 
4802 #ifndef OPENSSL_NO_ECDH
4803  if (cfg->named_curve != NULL) {
4804  EC_KEY * ecdh = NULL;
4805  int nid = 0;
4806 
4807  nid = OBJ_sn2nid(cfg->named_curve);
4808 
4809  if (nid == 0) {
4810  log_error("ECDH initialization failed: unknown curve %s", cfg->named_curve);
4811  }
4812 
4813  ecdh = EC_KEY_new_by_curve_name(nid);
4814 
4815  if (ecdh == NULL) {
4816  log_error("ECDH initialization failed for curve %s", cfg->named_curve);
4817  }
4818 
4819  SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh);
4820  EC_KEY_free(ecdh);
4821  }
4822 #endif /* OPENSSL_NO_ECDH */
4823 #ifndef OPENSSL_NO_DH
4824  if (cfg->dhparams != NULL)
4825  {
4826  FILE * fh;
4827  DH * dh;
4828 
4829  fh = fopen(cfg->dhparams, "r");
4830 
4831  if (fh != NULL)
4832  {
4833  dh = PEM_read_DHparams(fh, NULL, NULL, NULL);
4834  if (dh != NULL)
4835  {
4836  SSL_CTX_set_tmp_dh(htp->ssl_ctx, dh);
4837  DH_free(dh);
4838  } else {
4839  log_error("DH initialization failed: unable to parse file %s", cfg->dhparams);
4840  }
4841 
4842  fclose(fh);
4843  } else {
4844  log_error("DH initialization failed: unable to open file %s", cfg->dhparams);
4845  }
4846  }
4847 #endif /* OPENSSL_NO_DH */
4848 
4849  if (cfg->ciphers != NULL) {
4850  if (SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers) == 0) {
4851  log_error("set_cipher_list");
4852  return -1;
4853  }
4854  }
4855 
4856  SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
4857  X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
4858  SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);
4859 
4860  if (cfg->x509_chk_issued_cb != NULL) {
4861 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4862  htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
4863 #else
4864  X509_STORE_set_check_issued(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->x509_chk_issued_cb);
4865 #endif
4866  }
4867 
4868  if (cfg->verify_depth) {
4869  SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
4870  }
4871 
4872  switch (cfg->scache_type) {
4874  cache_mode = SSL_SESS_CACHE_OFF;
4875  break;
4876  default:
4877  cache_mode = SSL_SESS_CACHE_SERVER;
4878  break;
4879  } /* switch */
4880 
4881  SSL_CTX_use_certificate_chain_file(htp->ssl_ctx, cfg->pemfile);
4882 
4883  char * const key = cfg->privfile ? cfg->privfile : cfg->pemfile;
4884 
4885  if (cfg->decrypt_cb != NULL)
4886  {
4887  EVP_PKEY * pkey = cfg->decrypt_cb(key);
4888 
4889  if (pkey == NULL)
4890  {
4891  return -1;
4892  }
4893 
4894  SSL_CTX_use_PrivateKey(htp->ssl_ctx, pkey);
4895 
4896  /*cleanup */
4897  EVP_PKEY_free(pkey);
4898  } else {
4899  SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, key, SSL_FILETYPE_PEM);
4900  }
4901 
4902  SSL_CTX_set_session_id_context(htp->ssl_ctx,
4903  (void *)&session_id_context,
4904  sizeof(session_id_context));
4905 
4906  SSL_CTX_set_app_data(htp->ssl_ctx, htp);
4907  SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);
4908 
4909  if (cache_mode != SSL_SESS_CACHE_OFF)
4910  {
4911  SSL_CTX_sess_set_cache_size(htp->ssl_ctx,
4912  cfg->scache_size ? cfg->scache_size : 1024);
4913 
4914  if (cfg->scache_type == evhtp_ssl_scache_type_builtin ||
4915  cfg->scache_type == evhtp_ssl_scache_type_user)
4916  {
4917  SSL_CTX_sess_set_new_cb(htp->ssl_ctx, htp__ssl_add_scache_ent_);
4918  SSL_CTX_sess_set_get_cb(htp->ssl_ctx, htp__ssl_get_scache_ent_);
4919  SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, htp__ssl_delete_scache_ent_);
4920 
4921  if (cfg->scache_init)
4922  {
4923  cfg->args = (cfg->scache_init)(htp);
4924  }
4925  }
4926  }
4927 
4928  return 0;
4929 } /* evhtp_use_ssl */
4930 
4931 #endif
4932 
4933 struct bufferevent *
4934 evhtp_connection_get_bev(evhtp_connection_t * connection) {
4935  return connection->bev;
4936 }
4937 
4938 struct bufferevent *
4939 evhtp_connection_take_ownership(evhtp_connection_t * connection) {
4940  struct bufferevent * bev = evhtp_connection_get_bev(connection);
4941 
4942  if (connection->hooks)
4943  {
4944  evhtp_unset_all_hooks(&connection->hooks);
4945  }
4946 
4947  if (connection->request && connection->request->hooks)
4948  {
4949  evhtp_unset_all_hooks(&connection->request->hooks);
4950  }
4951 
4952  evhtp_connection_set_bev(connection, NULL);
4953 
4954  /* relinquish ownership of this connection, unset
4955  * the ownership flag.
4956  */
4957  HTP_FLAG_OFF(connection, EVHTP_CONN_FLAG_OWNER);
4958 
4959  bufferevent_disable(bev, EV_READ);
4960  bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
4961 
4962  return bev;
4963 }
4964 
4965 struct bufferevent *
4966 evhtp_request_get_bev(evhtp_request_t * request) {
4967  return evhtp_connection_get_bev(request->conn);
4968 }
4969 
4970 struct bufferevent *
4971 evhtp_request_take_ownership(evhtp_request_t * request) {
4972  return evhtp_connection_take_ownership(request->conn);
4973 }
4974 
4975 void
4976 evhtp_connection_set_bev(evhtp_connection_t * conn, struct bufferevent * bev)
4977 {
4978  conn->bev = bev;
4979 }
4980 
4981 void
4982 evhtp_request_set_bev(evhtp_request_t * request, struct bufferevent * bev)
4983 {
4984  evhtp_connection_set_bev(request->conn, bev);
4985 }
4986 
4987 void
4988 evhtp_request_set_keepalive(evhtp_request_t * request, int val)
4989 {
4990  if (val)
4991  {
4993  }
4994 }
4995 
4996 evhtp_connection_t *
4997 evhtp_request_get_connection(evhtp_request_t * request)
4998 {
4999  return request->conn;
5000 }
5001 
5003 evhtp_request_get_proto(evhtp_request_t * request)
5004 {
5005  return request->proto;
5006 }
5007 
5008 inline void
5009 evhtp_connection_set_timeouts(evhtp_connection_t * c,
5010  const struct timeval * rtimeo,
5011  const struct timeval * wtimeo)
5012 {
5013  if (evhtp_unlikely(c == NULL))
5014  {
5015  return;
5016  }
5017 
5018 
5019  bufferevent_set_timeouts(c->bev, rtimeo, wtimeo);
5020 }
5021 
5022 void
5023 evhtp_connection_set_max_body_size(evhtp_connection_t * c, uint64_t len)
5024 {
5025  if (len == 0)
5026  {
5027  c->max_body_size = c->htp->max_body_size;
5028  } else {
5029  c->max_body_size = len;
5030  }
5031 }
5032 
5033 void
5034 evhtp_request_set_max_body_size(evhtp_request_t * req, uint64_t len)
5035 {
5036  evhtp_connection_set_max_body_size(req->conn, len);
5037 }
5038 
5039 void
5040 evhtp_connection_free(evhtp_connection_t * connection)
5041 {
5042  if (evhtp_unlikely(connection == NULL))
5043  {
5044  return;
5045  }
5046 
5047  htp__hook_connection_fini_(connection);
5048 
5049  evhtp_safe_free(connection->request, htp__request_free_);
5050  evhtp_safe_free(connection->parser, htp__free_);
5051  evhtp_safe_free(connection->hooks, htp__free_);
5052  evhtp_safe_free(connection->saddr, htp__free_);
5053  evhtp_safe_free(connection->scratch_buf, evbuffer_free);
5054 
5055  if (connection->resume_ev)
5056  {
5057  evhtp_safe_free(connection->resume_ev, event_free);
5058  }
5059 
5060  if (connection->bev)
5061  {
5062 #ifdef LIBEVENT_HAS_SHUTDOWN
5063  bufferevent_shutdown(connection->bev, htp__shutdown_eventcb_);
5064 #else
5065 #ifndef EVHTP_DISABLE_SSL
5066  if (connection->ssl != NULL)
5067  {
5068  SSL_set_shutdown(connection->ssl, SSL_RECEIVED_SHUTDOWN);
5069  SSL_shutdown(connection->ssl);
5070  }
5071 #endif
5072  bufferevent_free(connection->bev);
5073 #endif
5074  }
5075 
5076  evhtp_safe_free(connection, htp__free_);
5077 } /* evhtp_connection_free */
5078 
5079 void
5080 evhtp_request_free(evhtp_request_t * request)
5081 {
5082  htp__request_free_(request);
5083 }
5084 
5085 void
5086 evhtp_set_timeouts(evhtp_t * htp, const struct timeval * r_timeo, const struct timeval * w_timeo)
5087 {
5088  if (r_timeo != NULL)
5089  {
5090  htp->recv_timeo = *r_timeo;
5091  }
5092 
5093  if (w_timeo != NULL)
5094  {
5095  htp->send_timeo = *w_timeo;
5096  }
5097 }
5098 
5099 void
5100 evhtp_set_max_keepalive_requests(evhtp_t * htp, uint64_t num)
5101 {
5102  htp->max_keepalive_requests = num;
5103 }
5104 
5105 void
5106 evhtp_set_bev_flags(evhtp_t * htp, int flags)
5107 {
5108  htp->bev_flags = flags;
5109 }
5110 
5111 void
5112 evhtp_set_max_body_size(evhtp_t * htp, uint64_t len)
5113 {
5114  htp->max_body_size = len;
5115 }
5116 
5117 void
5119 {
5121 }
5122 
5123 void
5124 evhtp_set_parser_flags(evhtp_t * htp, int flags)
5125 {
5126  htp->parser_flags = flags;
5127 }
5128 
5129 #define HTP_FLAG_FNGEN(NAME, TYPE) void \
5130  evhtp ## NAME ## _enable_flag(TYPE v, int flag) { \
5131  HTP_FLAG_ON(v, flag); \
5132  } \
5133  \
5134  void \
5135  evhtp ## NAME ## _disable_flag(TYPE v, int flag) { \
5136  HTP_FLAG_OFF(v, flag); \
5137  } \
5138  \
5139  int \
5140  evhtp ## NAME ## _get_flags(TYPE v) { \
5141  if (v) \
5142  { \
5143  return v->flags; \
5144  } \
5145  return -1; \
5146  }
5147 
5148 HTP_FLAG_FNGEN(, evhtp_t *);
5149 HTP_FLAG_FNGEN(_connection, evhtp_connection_t *);
5150 HTP_FLAG_FNGEN(_request, evhtp_request_t *);
5151 
5152 int
5153 evhtp_add_alias(evhtp_t * evhtp, const char * name)
5154 {
5155  evhtp_alias_t * alias;
5156 
5157  if (evhtp_unlikely(evhtp == NULL || name == NULL))
5158  {
5159  return -1;
5160  }
5161 
5162  if (!(alias = htp__calloc_(sizeof(evhtp_alias_t), 1)))
5163  {
5164  return -1;
5165  }
5166 
5167  log_debug("Adding %s to aliases", name);
5168 
5169  alias->alias = htp__strdup_(name);
5170  evhtp_alloc_assert(alias->alias);
5171 
5172  TAILQ_INSERT_TAIL(&evhtp->aliases, alias, next);
5173 
5174  return 0;
5175 }
5176 
5177 int
5178 evhtp_add_aliases(evhtp_t * htp, const char * name, ...) {
5179  va_list argp;
5180  size_t len;
5181 
5182  if (evhtp_add_alias(htp, name) == -1) {
5183  return -1;
5184  }
5185 
5186  va_start(argp, name);
5187  {
5188  const char * p;
5189 
5190  while ((p = va_arg(argp, const char *)) != NULL) {
5191  if (evhtp_add_alias(htp, p) == -1) {
5192  log_error("Unable to add %s alias", p);
5193  return -1;
5194  }
5195  }
5196  }
5197  va_end(argp);
5198 
5199  return 0;
5200 }
5201 
5202 int
5203 evhtp_add_vhost(evhtp_t * evhtp, const char * name, evhtp_t * vhost)
5204 {
5205  if (evhtp == NULL || name == NULL || vhost == NULL)
5206  {
5207  return -1;
5208  }
5209 
5210  if (TAILQ_FIRST(&vhost->vhosts) != NULL)
5211  {
5212  /* vhosts cannot have secondary vhosts defined */
5213  return -1;
5214  }
5215 
5216  if (!(vhost->server_name = htp__strdup_(name)))
5217  {
5218  return -1;
5219  }
5220 
5221  /* set the parent of this vhost so when the request has been completely
5222  * serviced, the vhost can be reset to the original evhtp structure.
5223  *
5224  * This allows for a keep-alive connection to make multiple requests with
5225  * different Host: values.
5226  */
5227  vhost->parent = evhtp;
5228 
5229  /* inherit various flags from the parent evhtp structure */
5230  vhost->bev_flags = evhtp->bev_flags;
5231  vhost->max_body_size = evhtp->max_body_size;
5232  vhost->max_keepalive_requests = evhtp->max_keepalive_requests;
5233  vhost->recv_timeo = evhtp->recv_timeo;
5234  vhost->send_timeo = evhtp->send_timeo;
5235 
5236  TAILQ_INSERT_TAIL(&evhtp->vhosts, vhost, next_vhost);
5237 
5238  return 0;
5239 }
5240 
5250 static int
5251 evhtp__new_(evhtp_t ** out, struct event_base * evbase, void * arg)
5252 {
5253  evhtp_t * htp;
5254 
5255 
5256  if (evhtp_unlikely(evbase == NULL))
5257  {
5258  return -1;
5259  }
5260 
5261  *out = NULL;
5262 
5263  if ((htp = htp__calloc_(1, sizeof(*htp))) == NULL)
5264  {
5265  return -1;
5266  }
5267 
5268 
5269  htp->arg = arg;
5270  htp->evbase = evbase;
5271  htp->flags = EVHTP_FLAG_DEFAULTS;
5272  htp->bev_flags = BEV_OPT_CLOSE_ON_FREE;
5273 
5274  /* default to lenient argument parsing */
5275  htp->parser_flags = EVHTP_PARSE_QUERY_FLAG_DEFAULT;
5276 
5277 
5278  TAILQ_INIT(&htp->vhosts);
5279  TAILQ_INIT(&htp->aliases);
5280 
5281  /* note that we pass the htp context to the callback,
5282  * not the user supplied arguments. That is stored
5283  * within the context itself.
5284  */
5285  evhtp_set_gencb(htp, htp__default_request_cb_, (void *)htp);
5286 
5287  *out = htp;
5288 
5289  return 0;
5290 }
5291 
5292 evhtp_t *
5293 evhtp_new(struct event_base * evbase, void * arg)
5294 {
5295  evhtp_t * htp;
5296 
5297  if (evhtp__new_(&htp, evbase, arg) == -1)
5298  {
5299  return NULL;
5300  }
5301 
5302  return htp;
5303 }
5304 
5305 void
5306 evhtp_free(evhtp_t * evhtp)
5307 {
5308  evhtp_alias_t * evhtp_alias, * tmp;
5309 
5310  if (evhtp == NULL)
5311  {
5312  return;
5313  }
5314 
5315 #ifndef EVHTP_DISABLE_EVTHR
5316  if (evhtp->thr_pool)
5317  {
5318  evthr_pool_stop(evhtp->thr_pool);
5319  evthr_pool_free(evhtp->thr_pool);
5320  }
5321 #endif
5322 
5323 #ifndef EVHTP_DISABLE_SSL
5324  if (evhtp->ssl_ctx)
5325  {
5326  evhtp_safe_free(evhtp->ssl_ctx, SSL_CTX_free);
5327  }
5328 #endif
5329 
5330  if (evhtp->server_name)
5331  {
5332  evhtp_safe_free(evhtp->server_name, htp__free_);
5333  }
5334 
5335  if (evhtp->callbacks)
5336  {
5337  evhtp_safe_free(evhtp->callbacks, evhtp_callbacks_free);
5338  }
5339 
5340  TAILQ_FOREACH_SAFE(evhtp_alias, &evhtp->aliases, next, tmp) {
5341  if (evhtp_alias->alias != NULL)
5342  {
5343  evhtp_safe_free(evhtp_alias->alias, htp__free_);
5344  }
5345 
5346  TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next);
5347  evhtp_safe_free(evhtp_alias, htp__free_);
5348  }
5349 
5350  evhtp_safe_free(evhtp, htp__free_);
5351 } /* evhtp_free */
5352 
5353 /*****************************************************************
5354 * client request functions *
5355 *****************************************************************/
5356 
5357 evhtp_connection_t *
5358 evhtp_connection_new(struct event_base * evbase, const char * addr, uint16_t port)
5359 {
5360  return evhtp_connection_new_dns(evbase, NULL, addr, port);
5361 }
5362 
5363 evhtp_connection_t *
5364 evhtp_connection_new_dns(struct event_base * evbase, struct evdns_base * dns_base,
5365  const char * addr, uint16_t port)
5366 {
5367  evhtp_connection_t * conn;
5368  int err;
5369 
5370  log_debug("Enter");
5371  evhtp_assert(evbase != NULL);
5372 
5373  if (!(conn = htp__connection_new_(NULL, -1, evhtp_type_client)))
5374  {
5375  return NULL;
5376  }
5377 
5378  conn->evbase = evbase;
5379  conn->bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
5380 
5381  if (conn->bev == NULL)
5382  {
5383  evhtp_connection_free(conn);
5384 
5385  return NULL;
5386  }
5387 
5388  bufferevent_enable(conn->bev, EV_READ);
5389  bufferevent_setcb(conn->bev, NULL, NULL,
5390  htp__connection_eventcb_, conn);
5391 
5392  if (dns_base != NULL)
5393  {
5394  err = bufferevent_socket_connect_hostname(conn->bev, dns_base,
5395  AF_UNSPEC, addr, port);
5396  } else {
5397  struct sockaddr_in sin4;
5398  struct sockaddr_in6 sin6;
5399  struct sockaddr * sin;
5400  int salen;
5401 
5402  if (inet_pton(AF_INET, addr, &sin4.sin_addr))
5403  {
5404  sin4.sin_family = AF_INET;
5405  sin4.sin_port = htons(port);
5406  sin = (struct sockaddr *)&sin4;
5407  salen = sizeof(sin4);
5408  } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr))
5409  {
5410  sin6.sin6_family = AF_INET6;
5411  sin6.sin6_port = htons(port);
5412  sin = (struct sockaddr *)&sin6;
5413  salen = sizeof(sin6);
5414  } else {
5415  /* Not a valid IP. */
5416  evhtp_connection_free(conn);
5417 
5418  return NULL;
5419  }
5420 
5421  err = bufferevent_socket_connect(conn->bev, sin, salen);
5422  }
5423 
5424  /* not needed since any of the bufferevent errors will go straight to
5425  * the eventcb
5426  */
5427  if (err)
5428  {
5429  return NULL;
5430  }
5431 
5432  return conn;
5433 } /* evhtp_connection_new_dns */
5434 
5435 #ifndef EVHTP_DISABLE_SSL
5436 
5437 #define ssl_sk_new_ bufferevent_openssl_socket_new
5438 #define ssl_sk_connect_ bufferevent_socket_connect
5439 
5440 evhtp_connection_t *
5441 evhtp_connection_ssl_new(struct event_base * evbase,
5442  const char * addr,
5443  uint16_t port,
5444  evhtp_ssl_ctx_t * ctx)
5445 {
5446  evhtp_connection_t * conn;
5447  struct sockaddr_in sin;
5448  const char * errstr;
5449 
5450  if (evbase == NULL)
5451  {
5452  return NULL;
5453  }
5454 
5455  if (!(conn = htp__connection_new_(NULL, -1, evhtp_type_client))) {
5456  return NULL;
5457  }
5458 
5459  conn->evbase = evbase;
5460  errstr = NULL;
5461 
5462  do {
5463  if ((conn->ssl = SSL_new(ctx)) == NULL) {
5464  errstr = "unable to allocate SSL context";
5465 
5466  break;
5467  }
5468 
5469  if ((conn->bev = ssl_sk_new_(evbase, -1, conn->ssl,
5470  BUFFEREVENT_SSL_CONNECTING,
5471  BEV_OPT_CLOSE_ON_FREE)) == NULL) {
5472  errstr = "unable to allocate bev context";
5473  break;
5474  }
5475 
5476  if (bufferevent_enable(conn->bev, EV_READ) == -1) {
5477  errstr = "unable to enable reading";
5478  break;
5479  }
5480 
5481 
5482  bufferevent_setcb(conn->bev, NULL, NULL,
5483  htp__connection_eventcb_, conn);
5484 
5485 
5486  sin.sin_family = AF_INET;
5487  sin.sin_addr.s_addr = inet_addr(addr);
5488  sin.sin_port = htons(port);
5489 
5490  if (ssl_sk_connect_(conn->bev,
5491  (struct sockaddr *)&sin,
5492  sizeof(sin)) == -1) {
5493  errstr = "sk_connect_ failure";
5494  break;
5495  }
5496  } while (0);
5497 
5498 
5499  if (errstr != NULL) {
5500  log_error("%s", errstr);
5501 
5503 
5504  return NULL;
5505  }
5506 
5507  return conn;
5508 } /* evhtp_connection_ssl_new */
5509 
5510 #endif
5511 
5512 
5513 evhtp_request_t *
5515 {
5516  evhtp_request_t * r;
5517 
5518  r = htp__request_new_(NULL);
5519  evhtp_alloc_assert(r);
5520 
5521  r->cb = cb;
5522  r->cbarg = arg;
5523  r->proto = EVHTP_PROTO_11;
5524 
5525  return r;
5526 }
5527 
5528 int
5529 evhtp_make_request(evhtp_connection_t * c, evhtp_request_t * r,
5530  htp_method meth, const char * uri)
5531 {
5532  struct evbuffer * obuf;
5533  char * proto;
5534 
5535  obuf = bufferevent_get_output(c->bev);
5536  r->conn = c;
5537  c->request = r;
5538 
5539  switch (r->proto) {
5540  case EVHTP_PROTO_10:
5541  proto = "1.0";
5542  break;
5543  case EVHTP_PROTO_11:
5544  default:
5545  proto = "1.1";
5546  break;
5547  }
5548 
5549  evbuffer_add_printf(obuf, "%s %s HTTP/%s\r\n",
5550  htparser_get_methodstr_m(meth), uri, proto);
5551 
5552  evhtp_headers_for_each(r->headers_out, htp__create_headers_, obuf);
5553  evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL);
5554 
5555  if (evbuffer_get_length(r->buffer_out))
5556  {
5557  evbuffer_add_buffer(obuf, r->buffer_out);
5558  }
5559 
5560  return 0;
5561 }
5562 
5563 unsigned int
5564 evhtp_request_status(evhtp_request_t * r)
5565 {
5566  return htparser_get_status(r->conn->parser);
5567 }
void evhtp_request_set_keepalive(evhtp_request_t *request, int val)
Definition: evhtp.c:4988
int evhtp_callbacks_add_callback(evhtp_callbacks_t *cbs, evhtp_callback_t *cb)
Adds a evhtp_callback_t to the evhtp_callbacks_t list.
Definition: evhtp.c:4265
void(* evhtp_thread_init_cb)(evhtp_t *htp, evthr_t *thr, void *arg)
Definition: evhtp/evhtp.h:155
evhtp_res(* evhtp_hook_write_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp/evhtp.h:178
static evhtp_t * htp__request_find_vhost_(evhtp_t *evhtp, const char *name)
Definition: evhtp.c:1509
int evhtp_bind_socket(evhtp_t *htp, const char *baddr, uint16_t port, int backlog)
bind to a socket, optionally with specific protocol support formatting.
Definition: evhtp.c:4110
evhtp_type
Definition: evhtp/evhtp.h:144
int evthr_pool_start(evthr_pool_t *pool)
Definition: thread.c:425
evthr_pool_t * evthr_pool_wexit_new(int nthreads, evthr_init_cb init_cb, evthr_exit_cb exit_cb, void *shared)
Definition: thread.c:418
htp_scheme htparser_get_scheme(htparser *p)
Definition: parser.c:471
size_t len
Definition: evhtp.c:56
static evhtp_res htp__hook_headers_start_(evhtp_request_t *request)
Runs the user defined on_headers_start hook.
Definition: evhtp.c:718
int evhtp_connection_unset_hook(evhtp_connection_t *conn, evhtp_hook_type type)
Definition: evhtp.c:4369
type which defines to hook whenever an error occurs
Definition: evhtp/evhtp.h:123
static int htp__request_parse_fini_(htparser *p)
Definition: evhtp.c:2011
void * args
Definition: thread.c:119
static htparse_hooks request_psets
callback definitions for request processing from libhtparse
Definition: evhtp.c:2211
int evhtp_use_threads(evhtp_t *htp, evhtp_thread_init_cb init_cb, int nthreads, void *arg)
Enable thread-pool support for an evhtp_t context.
Definition: evhtp.c:4587
#define EVHTP_PARSE_QUERY_FLAG_DEFAULT
Definition: evhtp/evhtp.h:1111
evhtp_res(* evhtp_hook_hostname_cb)(evhtp_request_t *r, const char *hostname, void *arg)
Definition: evhtp/evhtp.h:177
static int htp__uri_new_(evhtp_uri_t **out)
create an overlay URI structure
Definition: evhtp.c:1195
void evhtp_set_max_keepalive_requests(evhtp_t *htp, uint64_t num)
sets a maximum number of requests that a single connection can make.
Definition: evhtp.c:5100
unsigned char evhtp_ssl_data_t
Definition: evhtp/evhtp.h:48
static void htp__connection_readcb_(struct bufferevent *bev, void *arg)
Definition: evhtp.c:2233
int evhtp_add_vhost(evhtp_t *evhtp, const char *name, evhtp_t *vhost)
add an evhtp_t structure (with its own callbacks) to a base evhtp_t structure for virtual hosts...
Definition: evhtp.c:5203
#define evhtp_headers_find_header
Definition: evhtp/evhtp.h:1209
static void htp__ssl_delete_scache_ent_(evhtp_ssl_ctx_t *ctx, evhtp_ssl_sess_t *sess)
Definition: evhtp.c:2901
static evhtp_res htp__hook_chunks_fini_(evhtp_request_t *request)
Runs the user defined on chunk_finis hook.
Definition: evhtp.c:704
#define EVHTP_FLAG_ENABLE_100_CONT
Definition: evhtp/evhtp.h:296
struct bufferevent * evhtp_request_get_bev(evhtp_request_t *request)
returns the underlying requests bufferevent
Definition: evhtp.c:4966
void evhtp_set_mem_functions(void *(*mallocfn_)(size_t len), void *(*reallocfn_)(void *p, size_t sz), void(*freefn_)(void *p))
Definition: evhtp.c:321
void evhtp_send_reply_chunk_end(evhtp_request_t *request)
call when all chunks have been sent and you wish to send the last bits.
Definition: evhtp.c:3928
void evhtp_disable_100_continue(evhtp_t *htp)
Definition: evhtp.c:5118
#define evhtp_header_t
Definition: evhtp/evhtp.h:97
static void htp__connection_eventcb_(struct bufferevent *bev, short events, void *arg)
Definition: evhtp.c:2483
struct evhtp_callbacks_s evhtp_callbacks_t
Definition: evhtp/evhtp.h:76
#define EVHTP_REQ_FLAG_CHUNKED
Definition: evhtp/evhtp.h:413
SSL evhtp_ssl_t
Definition: evhtp/evhtp.h:43
static int htp__run_pre_accept_(evhtp_t *htp, evhtp_connection_t *conn)
Definition: evhtp.c:2620
#define evhtp_headers_for_each
Definition: evhtp/evhtp.h:1210
evhtp_hooks_t * evhtp_request_get_hooks(evhtp_request_t *r)
returns request hooks
Definition: evhtp.c:4449
int evhtp_use_callback_locks(evhtp_t *htp)
creates a lock around callbacks and hooks, allowing for threaded applications to add/remove/modify ho...
Definition: evhtp.c:4606
static char * htp__strndup_(const char *str, size_t len)
implementation of strndup function.
Definition: evhtp.c:289
#define EVHTP_FLAG_ENABLE_REUSEPORT
Definition: evhtp/evhtp.h:297
static int htp__request_set_callbacks_(evhtp_request_t *request)
Definition: evhtp.c:1546
union evhtp_callback_s::@0 val
EVHTP_EXPORT const char * evhtp_header_find(evhtp_headers_t *headers, const char *key)
finds the value of a key in a evhtp_headers_t structure
void evhtp_send_reply_end(evhtp_request_t *request)
Definition: evhtp.c:3784
evhtp_callback_t * evhtp_set_regex_cb(evhtp_t *htp, const char *pattern, evhtp_callback_cb cb, void *arg)
sets a callback to be executed based on a regex pattern
Definition: evhtp.c:4625
#define EVHTP_PARSE_QUERY_FLAG_ALLOW_EMPTY_VALS
Definition: evhtp/evhtp.h:1101
htp_method evhtp_request_get_method(evhtp_request_t *r)
returns the htp_method enum version of the request method.
Definition: evhtp.c:3030
#define evhtp_query_new
Definition: evhtp/evhtp.h:1218
type which defines to hook once a path has been parsed
Definition: evhtp/evhtp.h:115
static int evhtp_is_hex_query_char(unsigned char ch)
Definition: evhtp.c:3369
int evhtp_accept_socket(evhtp_t *htp, evutil_socket_t sock, int backlog)
create the listener plus setup various options with an already-bound socket.
Definition: evhtp.c:3951
static void * htp__calloc_(size_t nmemb, size_t size)
Wrapper for calloc so that a different calloc can be used if desired.
Definition: evhtp.c:228
struct bufferevent * evhtp_connection_get_bev(evhtp_connection_t *connection)
returns the underlying connections bufferevent
Definition: evhtp.c:4934
evhtp_header_t * evhtp_header_val_add(evhtp_headers_t *headers, const char *val, char val_alloc)
finds the last header in the headers tailq and adds the value
Definition: evhtp.c:3096
static evhtp_connection_t * htp__connection_new_(evhtp_t *htp, evutil_socket_t sock, evhtp_type type)
Definition: evhtp.c:2724
static void htp__hook_error_(evhtp_request_t *request, evhtp_error_flags errtype)
runs the user-defined hook when a connection error occurs
Definition: evhtp.c:756
evhtp_query_t * evhtp_parse_query_wflags(const char *query, const size_t len, const int flags)
Parses the query portion of the uri into a set of key/values.
Definition: evhtp.c:3482
void evhtp_send_reply(evhtp_request_t *request, evhtp_res code)
generates all the right information for a reply to be sent to the client
Definition: evhtp.c:3790
void evhtp_set_timeouts(evhtp_t *htp, const struct timeval *r_timeo, const struct timeval *w_timeo)
set a read/write timeout on all things evhtp_t.
Definition: evhtp.c:5086
static evhtp_res htp__hook_hostname_(evhtp_request_t *r, const char *hostname)
Runs the user defined hostname processing hook.
Definition: evhtp.c:794
evhtp_proto evhtp_request_get_proto(evhtp_request_t *request)
Definition: evhtp.c:5003
evhtp_res(* evhtp_hook_conn_err_cb)(evhtp_connection_t *connection, evhtp_error_flags errtype, void *arg)
Definition: evhtp/evhtp.h:164
#define HOOK_REQUEST_RUN(request, hook_name,...)
Definition: evhtp.c:81
evbase_t * evthr_get_base(evthr_t *thr)
Definition: thread.c:168
static evhtp_res htp__hook_header_(evhtp_request_t *request, evhtp_header_t *header)
runs the user-defined on_header hook for a request
Definition: evhtp.c:600
const char * htparser_get_methodstr_m(htp_method meth)
Definition: parser.c:483
unsigned char htparser_get_multipart(htparser *p)
Definition: parser.c:524
evhtp_hooks_t * evhtp_connection_get_hooks(evhtp_connection_t *c)
Definition: evhtp.c:4432
void evhtp_request_pause(evhtp_request_t *request)
Wrapper around evhtp_connection_pause.
Definition: evhtp.c:3064
SSL_CTX evhtp_ssl_ctx_t
Definition: evhtp/evhtp.h:44
#define HOOK_REQUEST_RUN_NARGS(__request, hook_name)
Definition: evhtp.c:95
#define EVHTP_PARSE_QUERY_FLAG_TREAT_SEMICOLON_AS_SEP
Definition: evhtp/evhtp.h:1103
int evhtp_ssl_init(evhtp_t *htp, evhtp_ssl_cfg_t *cfg)
Definition: evhtp.c:4760
#define evhtp_query_t
Definition: evhtp/evhtp.h:99
static evhtp_res htp__hook_connection_error_(evhtp_connection_t *connection, evhtp_error_flags errtype)
runs the user-defined hook when a connection error occurs
Definition: evhtp.c:771
evhtp_connection_t * evhtp_request_get_connection(evhtp_request_t *request)
returns the underlying evhtp_connection_t structure from a request
Definition: evhtp.c:4997
struct bufferevent * evhtp_request_take_ownership(evhtp_request_t *request)
Definition: evhtp.c:4971
evhtp_callback_type
Definition: evhtp/evhtp.h:130
pthread_mutex_t evhtp_mutex_t
Definition: evhtp/evhtp.h:71
evhtp_hooks_t * hooks
per-callback hooks
Definition: evhtp.c:55
#define evhtp_headers_s
Definition: evhtp/evhtp.h:94
#define evhtp_request_content_len(r)
Definition: evhtp/evhtp.h:423
int evhtp_add_aliases(evhtp_t *htp, const char *name,...)
set a variable number of aliases in one call evhtp_add_alias
Definition: evhtp.c:5178
evhtp_hook_type
types associated with where a developer can hook into during the request processing cycle...
Definition: evhtp/evhtp.h:112
evhtp_res(* evhtp_hook_path_cb)(evhtp_request_t *req, evhtp_path_t *path, void *arg)
Definition: evhtp/evhtp.h:169
evhtp_connection_t * evhtp_connection_ssl_new(struct event_base *evbase, const char *addr, uint16_t port, evhtp_ssl_ctx_t *ctx)
Definition: evhtp.c:5441
static void htp__default_request_cb_(evhtp_request_t *request, void *arg)
Definition: evhtp.c:2716
void evhtp_connection_set_bev(evhtp_connection_t *conn, struct bufferevent *bev)
Sets the connections underlying bufferevent.
Definition: evhtp.c:4976
#define EVHTP_PARSE_QUERY_FLAG_IGNORE_HEX
Definition: evhtp/evhtp.h:1100
static void(* free_)(void *d)
Definition: evhtp.c:166
int evhtp_kvs_for_each(evhtp_kvs_t *kvs, evhtp_kvs_iterator cb, void *arg)
callback iterator which executes &#39;cb&#39; for every entry in &#39;kvs&#39;
Definition: evhtp.c:3266
static evhtp_res htp__hook_path_(evhtp_request_t *request, evhtp_path_t *path)
runs the user-defined on_path hook for a request
Definition: evhtp.c:582
evhtp_res(* evhtp_hook_request_fini_cb)(evhtp_request_t *req, void *arg)
Definition: evhtp/evhtp.h:171
static int htp__request_parse_body_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1881
static int htp__request_parse_args_(htparser *p, const char *data, size_t len)
parses http request arguments
Definition: evhtp.c:1367
void htparser_set_minor(htparser *p, unsigned char minor)
Definition: parser.c:506
void evhtp_request_free(evhtp_request_t *request)
Definition: evhtp.c:5080
void evhtp_kv_free(evhtp_kv_t *kv)
frees resources allocated for a single key/value
Definition: evhtp.c:3206
#define EVHTP_CONN_FLAG_VHOST_VIA_SNI
set to 1 if the vhost was found via SSL SNI
Definition: evhtp/evhtp.h:449
#define evhtp_assert(x)
Definition: internal.h:34
static int htp__connection_accept_(struct event_base *evbase, evhtp_connection_t *connection)
Definition: evhtp.c:2642
evhtp_hooks_t * evhtp_callback_get_hooks(evhtp_callback_t *cb)
returns callback hooks
Definition: evhtp.c:4466
evthr_res evthr_pool_stop(evthr_pool_t *pool)
Definition: thread.c:309
static evhtp_request_t * htp__request_new_(evhtp_connection_t *c)
Creates a new evhtp_request_t.
Definition: evhtp.c:1265
void evhtp_set_parser_flags(evhtp_t *htp, int flags)
during the request processing cycle, these flags will be used to for query argument parsing...
Definition: evhtp.c:5124
static void htp__run_in_thread_(evthr_t *thr, void *arg, void *shared)
Definition: evhtp.c:2794
#define EVHTP_PARSE_QUERY_FLAG_ALLOW_NULL_VALS
Definition: evhtp/evhtp.h:1102
unsigned int evhtp_request_status(evhtp_request_t *r)
Definition: evhtp.c:5564
type which defines to hook before the request is free&#39;d
Definition: evhtp/evhtp.h:117
static int htp__glob_match_(const char *pattern, size_t plen, const char *string, size_t str_len)
glob/wildcard type pattern matching.
Definition: evhtp.c:830
uint16_t evhtp_res
Definition: evhtp/evhtp.h:89
int evhtp_connection_set_hook(evhtp_connection_t *conn, evhtp_hook_type type, evhtp_hook cb, void *arg)
sets a callback hook for either a connection or a path/regex .
Definition: evhtp.c:4387
void evthr_pool_free(evthr_pool_t *pool)
Definition: thread.c:291
evhtp_res(* evhtp_hook_chunk_fini_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp/evhtp.h:174
void evhtp_unbind_socket(evhtp_t *htp)
stops the listening socket.
Definition: evhtp.c:3940
static evhtp_mutex_t * ssl_locks
Definition: evhtp.c:448
void(* evhtp_hook_err_cb)(evhtp_request_t *req, evhtp_error_flags errtype, void *arg)
Definition: evhtp/evhtp.h:158
evhtp_res(* evhtp_hook_header_cb)(evhtp_request_t *req, evhtp_header_t *hdr, void *arg)
Definition: evhtp/evhtp.h:167
void(* evhtp_thread_exit_cb)(evhtp_t *htp, evthr_t *thr, void *arg)
Definition: evhtp/evhtp.h:156
#define htp__is_http_11_(_major, _minor)
helper macro to determine if http version is HTTP/1.0
Definition: evhtp.c:532
uint8_t evhtp_error_flags
Definition: evhtp/evhtp.h:90
htp_method htparser_get_method(htparser *p)
Definition: parser.c:477
int evhtp_bind_sockaddr(evhtp_t *htp, struct sockaddr *sa, size_t sin_len, int backlog)
bind to an already allocated sockaddr.
Definition: evhtp.c:4033
evhtp_res(* evhtp_hook)()
Definition: evhtp/evhtp.h:162
static int htp__use_threads_(evhtp_t *htp, evhtp_thread_init_cb init_cb, evhtp_thread_exit_cb exit_cb, int nthreads, void *arg)
Definition: evhtp.c:4556
evhtp_res(* evhtp_hook_headers_cb)(evhtp_request_t *req, evhtp_headers_t *hdr, void *arg)
Definition: evhtp/evhtp.h:168
int evhtp_unescape_string(unsigned char **out, unsigned char *str, size_t str_len)
Unescapes strings like &#39;%7B1,%202,%203%7D&#39; would become &#39;{1, 2, 3}&#39;.
Definition: evhtp.c:3403
void evhtp_callback_free(evhtp_callback_t *callback)
safely frees callback structure memory and internals
Definition: evhtp.c:4232
#define EVHTP_RES_DATA_TOO_LONG
Definition: evhtp/evhtp.h:206
static int htp__request_parse_chunks_fini_(htparser *p)
Definition: evhtp.c:1947
static void htp__path_free_(evhtp_path_t *path)
Correctly frees the evhtp_path_t ptr that is passed in.
Definition: evhtp.c:1110
static int session_id_context
Definition: evhtp.c:445
size_t htparser_run(htparser *p, htparse_hooks *hooks, const char *data, size_t len)
Definition: parser.c:709
EVHTP_EXPORT void evhtp_headers_add_header(evhtp_headers_t *headers, evhtp_header_t *header)
adds an evhtp_header_t to the end of the evhtp_headers_t tailq
evhtp_request_t * evhtp_request_new(evhtp_callback_cb cb, void *arg)
allocate a new request
Definition: evhtp.c:5514
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: internal.h:22
void evhtp_request_resume(evhtp_request_t *request)
Wrapper around evhtp_connection_resume.
Definition: evhtp.c:3073
void evhtp_set_gencb(evhtp_t *htp, evhtp_callback_cb cb, void *arg)
sets a callback which is called if no other callbacks are matched
Definition: evhtp.c:4705
void evhtp_callbacks_free(evhtp_callbacks_t *callbacks)
Definition: evhtp.c:4167
#define htp__unlock_(h)
Helper macro to unlock htp lock.
Definition: evhtp.c:127
unscape_state
Definition: evhtp.c:3396
evthr_res evthr_pool_defer(evthr_pool_t *pool, evthr_cb cb, void *arg)
Definition: thread.c:325
#define evhtp_headers_t
Definition: evhtp/evhtp.h:98
int evhtp_callback_set_hook(evhtp_callback_t *callback, evhtp_hook_type type, evhtp_hook cb, void *arg)
Definition: evhtp.c:4375
evhtp_callback_type type
the type of callback (regex|path)
Definition: evhtp.c:52
void evhtp_set_max_body_size(evhtp_t *htp, uint64_t len)
set a max body size to accept for an incoming request, this will default to unlimited.
Definition: evhtp.c:5112
int evhtp_request_unset_hook(evhtp_request_t *req, evhtp_hook_type type)
Definition: evhtp.c:4363
static evhtp_callback_t * htp__callback_find_(evhtp_callbacks_t *cbs, const char *path, unsigned int *start_offset, unsigned int *end_offset)
Locates a given callback offsets performs a regex pattern match.
Definition: evhtp.c:905
void evhtp_set_pre_accept_cb(evhtp_t *htp, evhtp_pre_accept_cb cb, void *arg)
call a user-defined function before the connection is accepted.
Definition: evhtp.c:4712
structure containing a single callback and configuration
Definition: evhtp.c:51
static int htp__request_parse_headers_start_(htparser *p)
Definition: evhtp.c:1440
static evhtp_res htp__hook_body_(evhtp_request_t *request, struct evbuffer *buf)
runs the user-defined on_body hook for requests containing a body.
Definition: evhtp.c:635
#define log_error(M,...)
Definition: log.h:28
void evhtp_request_set_bev(evhtp_request_t *request, struct bufferevent *bev)
sets the underlying bufferevent for a evhtp_request
Definition: evhtp.c:4982
static int htp__require_uri_(evhtp_connection_t *c)
Definition: evhtp.c:1713
static int htp__path_new_(evhtp_path_t **out, const char *data, size_t len)
parses the path and file from an input buffer
Definition: evhtp.c:990
void evhtp_connection_set_timeouts(evhtp_connection_t *c, const struct timeval *rtimeo, const struct timeval *wtimeo)
sets a connection-specific read/write timeout which overrides the global read/write settings...
Definition: evhtp.c:5009
#define EVHTP_CONN_FLAG_ERROR
Definition: evhtp/evhtp.h:447
static int htp__request_parse_path_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1795
evhtp_res(* evhtp_hook_connection_fini_cb)(evhtp_connection_t *connection, void *arg)
Definition: evhtp/evhtp.h:172
static void htp__free_(void *ptr)
Wrapper for free so that a different free can be used if desired.
Definition: evhtp.c:211
static void htp__connection_resumecb_(int fd, short events, void *arg)
Definition: evhtp.c:2582
void evhtp_send_reply_start(evhtp_request_t *request, evhtp_res code)
Definition: evhtp.c:3755
type which defines to hook after all headers have been parsed
Definition: evhtp/evhtp.h:114
static evhtp_res htp__hook_connection_fini_(evhtp_connection_t *connection)
runs the user-definedhook called just prior to a connection being closed
Definition: evhtp.c:734
static evhtp_res htp__hook_chunk_new_(evhtp_request_t *request, uint64_t len)
Runs the user defined request hook.
Definition: evhtp.c:676
evhtp_connection_t * evhtp_connection_new_dns(struct event_base *evbase, struct evdns_base *dns_base, const char *addr, uint16_t port)
allocate a new connection
Definition: evhtp.c:5364
#define EVHTP_RES_FATAL
Definition: evhtp/evhtp.h:204
query_parser_state
Definition: evhtp.c:3356
static int htp__request_parse_hostname_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1656
void evhtp_connection_resume(evhtp_connection_t *c)
resumes a connection (enables reading) and activates resume event.
Definition: evhtp.c:3052
evhtp_t * evhtp_new(struct event_base *evbase, void *arg)
creates a new evhtp_t instance
Definition: evhtp.c:5293
#define evhtp_safe_free(_var, _freefn)
Definition: internal.h:28
struct evhtp_kvs_s evhtp_kvs_t
Definition: evhtp/evhtp.h:80
evhtp_header_t * evhtp_header_key_add(evhtp_headers_t *headers, const char *key, char key_alloc)
creates a new evhtp_header_t, sets only the key, and adds to the evhtp_headers TAILQ ...
Definition: evhtp.c:3081
void evhtp_send_reply_body(evhtp_request_t *request, struct evbuffer *buf)
Definition: evhtp.c:3774
#define EVHTP_RES_ERROR
Definition: evhtp/evhtp.h:202
static void * htp__realloc_(void *ptr, size_t size)
Wrapper for realloc so that a different realloc can be used if desired.
Definition: evhtp.c:196
static void htp__uri_free_(evhtp_uri_t *uri)
frees an overlay URI structure
Definition: evhtp.c:1172
static int htp__request_parse_chunk_new_(htparser *p)
Definition: evhtp.c:1920
EVHTP_EXPORT evhtp_header_t * evhtp_header_new(const char *key, const char *val, char kalloc, char valloc)
creates a new evhtp_header_t key/val structure
static int htp__request_parse_header_key_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1453
void evhtp_set_bev_flags(evhtp_t *htp, int flags)
bufferevent flags which will be used for bev sockets.
Definition: evhtp.c:5106
static int ssl_locks_initialized
Definition: evhtp.c:449
void * cbarg
user-defind arguments passed to the cb
Definition: evhtp.c:54
regex_t * regex
Definition: evhtp.c:62
static int htp__request_parse_port_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1767
#define htp__lock_(h)
Helper macro to lock htp structure.
Definition: evhtp.c:115
#define EVHTP_RES_PAUSE
Definition: evhtp/evhtp.h:203
evhtp_callback_cb cb
the actual callback function
Definition: evhtp.c:53
evhtp_res(* evhtp_pre_accept_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp/evhtp.h:165
void htparser_init(htparser *p, htp_type type)
Definition: parser.c:566
evhtp_proto
Definition: evhtp/evhtp.h:138
#define htp__is_http_10_(_major, _minor)
helper function to determine if http version is HTTP/1.1
Definition: evhtp.c:544
EVHTP_EXPORT size_t evhtp_modp_sizetoa(size_t value, char *str)
based on the system architecture, convert a size_t number to a string.
unsigned char htparser_get_major(htparser *p)
Definition: parser.c:512
#define EVHTP_FLAG_ENABLE_NODELAY
Definition: evhtp/evhtp.h:298
int(* evhtp_kvs_iterator)(evhtp_kv_t *kv, void *arg)
Definition: evhtp/evhtp.h:180
#define EVHTP_REQ_FLAG_ERROR
Definition: evhtp/evhtp.h:414
evhtp_callback_t * evhtp_set_cb(evhtp_t *htp, const char *path, evhtp_callback_cb cb, void *arg)
sets a callback to be executed on a specific path
Definition: evhtp.c:4472
void evhtp_kvs_free(evhtp_kvs_t *kvs)
frees a the list of key/values, and all underlying entries
Definition: evhtp.c:3240
static int htp__unset_hook_(evhtp_hooks_t **hooks, evhtp_hook_type type)
Definition: evhtp.c:4352
int evhtp_use_threads_wexit(evhtp_t *htp, evhtp_thread_init_cb init_cb, evhtp_thread_exit_cb exit_cb, int nthreads, void *arg)
Temporary function which will be renamed evhtp_use_threads in the future.
Definition: evhtp.c:4594
#define EVHTP_REQ_FLAG_KEEPALIVE
Definition: evhtp/evhtp.h:411
void evhtp_kvs_add_kv(evhtp_kvs_t *kvs, evhtp_kv_t *kv)
appends a key/val structure to a evhtp_kvs_t tailq
Definition: evhtp.c:3328
#define evhtp_modp_uchartoa(_val)
Definition: numtoa.h:42
static void htp__thread_init_(evthr_t *thr, void *arg)
Definition: evhtp.c:4534
char * glob
Definition: evhtp.c:60
static int htp__set_hook_(evhtp_hooks_t **hooks, evhtp_hook_type type, evhtp_hook cb, void *arg)
Definition: evhtp.c:4273
int evhtp_add_alias(evhtp_t *evhtp, const char *name)
Add an alias hostname for a virtual-host specific evhtp_t.
Definition: evhtp.c:5153
type which defines to hook whenever the parser recieves data in a body
Definition: evhtp/evhtp.h:116
type which defines to hook whenever a connection error occurs
Definition: evhtp/evhtp.h:127
void evhtp_send_reply_chunk(evhtp_request_t *request, struct evbuffer *buf)
send a chunk reply.
Definition: evhtp.c:3900
static unsigned long htp__ssl_get_thread_id_(void)
Definition: evhtp.c:2874
evhtp_res(* evhtp_hook_headers_start_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp/evhtp.h:176
void evhtp_set_post_accept_cb(evhtp_t *htp, evhtp_post_accept_cb cb, void *arg)
call a user-defined function right after a connection is accepted.
Definition: evhtp.c:4719
#define EVHTP_PARSE_QUERY_FLAG_STRICT
Definition: evhtp/evhtp.h:1099
#define EVHTP_CONN_FLAG_FREE_CONN
Definition: evhtp/evhtp.h:453
void evhtp_request_set_max_body_size(evhtp_request_t *req, uint64_t len)
just calls evhtp_connection_set_max_body_size for the request.
Definition: evhtp.c:5034
static int htp__request_parse_host_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1729
evhtp_connection_t * evhtp_connection_new(struct event_base *evbase, const char *addr, uint16_t port)
allocate a new connection
Definition: evhtp.c:5358
SSL_SESSION evhtp_ssl_sess_t
Definition: evhtp/evhtp.h:39
static int htp__request_parse_chunk_fini_(htparser *p)
Definition: evhtp.c:1934
static void htp__authority_free_(evhtp_authority_t *authority)
frees an authority structure
Definition: evhtp.c:1152
void evhtp_send_reply_chunk_start(evhtp_request_t *request, evhtp_res code)
start a chunked response.
Definition: evhtp.c:3828
evhtp_res(* evhtp_post_accept_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp/evhtp.h:166
static void htp__request_free_(evhtp_request_t *request)
frees all data in an evhtp_request_t along with calling finished hooks
Definition: evhtp.c:1225
#define EVHTP_CONN_FLAG_WAITING
used to make sure resuming happens AFTER sending a reply
Definition: evhtp/evhtp.h:452
static void htp__connection_writecb_(struct bufferevent *bev, void *arg)
Definition: evhtp.c:2322
#define ssl_sk_new_
Definition: evhtp.c:5437
static int htp__request_parse_headers_(htparser *p)
Definition: evhtp.c:1836
static void * htp__malloc_(size_t size)
Wrapper for malloc so that a different malloc can be used if desired.
Definition: evhtp.c:179
#define HTP_FLAG_OFF(PRE, FLAG)
Definition: evhtp.c:75
static int htp__run_post_accept_(evhtp_t *htp, evhtp_connection_t *connection)
Definition: evhtp.c:2771
EVHTP_EXPORT size_t evhtp_modp_u32toa(uint32_t value, char *str)
converts uint32_t value to string
struct bufferevent * evhtp_connection_take_ownership(evhtp_connection_t *connection)
let a user take ownership of the underlying bufferevent and free all other underlying resources...
Definition: evhtp.c:4939
void evhtp_connection_set_max_body_size(evhtp_connection_t *c, uint64_t len)
set a max body size for a specific connection, this will default to the size set by evhtp_set_max_bod...
Definition: evhtp.c:5023
#define EVHTP_PARSE_QUERY_FLAG_IGNORE_FRAGMENTS
Definition: evhtp/evhtp.h:1104
static struct evbuffer * htp__create_reply_(evhtp_request_t *request, evhtp_res code)
Definition: evhtp.c:2081
void htparser_set_userdata(htparser *p, void *ud)
Definition: parser.c:536
static int htp__ssl_servername_(evhtp_ssl_t *ssl, int *unused, void *arg)
Definition: evhtp.c:2972
evhtp_callback_t * evhtp_get_cb(evhtp_t *htp, const char *path)
attempts to find the callback matching the exact string &#39;needle&#39;.
Definition: evhtp.c:4511
evhtp_callback_t * evhtp_callback_new(const char *path, evhtp_callback_type type, evhtp_callback_cb cb, void *arg)
creates a new evhtp_callback_t structure.
Definition: evhtp.c:4187
void(* evhtp_hook_event_cb)(evhtp_connection_t *conn, short events, void *arg)
Definition: evhtp/evhtp.h:159
static evhtp_res htp__hook_chunk_fini_(evhtp_request_t *request)
Runs the user defined on_chunk_fini hook.
Definition: evhtp.c:690
void * htparser_get_userdata(htparser *p)
Definition: parser.c:530
static evhtp_res htp__hook_request_fini_(evhtp_request_t *request)
runs the user-defined hook called just prior to a request been free()&#39;d
Definition: evhtp.c:656
int evhtp_ssl_use_threads(void)
Definition: evhtp.c:4728
static int ssl_num_locks
Definition: evhtp.c:447
htpparse_error htparser_get_error(htparser *p)
Definition: parser.c:423
void evhtp_connection_pause(evhtp_connection_t *c)
pauses a connection (disables reading)
Definition: evhtp.c:3040
static int evhtp__new_(evhtp_t **out, struct event_base *evbase, void *arg)
Allocates new evhtp_t structure.
Definition: evhtp.c:5251
static void htp__accept_cb_(struct evconnlistener *serv, int fd, struct sockaddr *s, int sl, void *arg)
Definition: evhtp.c:2820
static evhtp_res htp__hook_connection_write_(evhtp_connection_t *connection)
Runs the user defined on_write hook.
Definition: evhtp.c:808
char * path
Definition: evhtp.c:59
void evhtp_kv_rm_and_free(evhtp_kvs_t *kvs, evhtp_kv_t *kv)
free&#39;s resources associated with &#39;kv&#39; if ONLY found within the key/value list
Definition: evhtp.c:3227
static evhtp_ssl_sess_t * htp__ssl_get_scache_ent_(evhtp_ssl_t *ssl, evhtp_ssl_data_t *sid, int sid_len, int *copy)
Definition: evhtp.c:2946
static int htp__ssl_add_scache_ent_(evhtp_ssl_t *ssl, evhtp_ssl_sess_t *sess)
Definition: evhtp.c:2919
#define EVHTP_CONN_FLAG_OWNER
set to 1 if this structure owns the bufferevent
Definition: evhtp/evhtp.h:448
static void htp__ssl_thread_lock_(int mode, int type, const char *file, int line)
Definition: evhtp.c:2886
evhtp_res(* evhtp_hook_read_cb)(evhtp_request_t *req, struct evbuffer *buf, void *arg)
Definition: evhtp/evhtp.h:170
#define EVHTP_CONN_FLAG_CONNECTED
client specific - set after successful connection
Definition: evhtp/evhtp.h:451
void evhtp_connection_free(evhtp_connection_t *connection)
free&#39;s all connection related resources, this will also call your request fini hook and request fini ...
Definition: evhtp.c:5040
evhtp_kv_t * evhtp_kvs_find_kv(evhtp_kvs_t *kvs, const char *key)
find the evhtp_kv_t reference &#39;key&#39; from the k/val list &#39;kvs&#39;
Definition: evhtp.c:3308
static void htp__thread_exit_(evthr_t *thr, void *arg)
Definition: evhtp.c:4545
static void *(* malloc_)(size_t sz)
Definition: evhtp.c:164
int evhtp_unset_all_hooks(evhtp_hooks_t **hooks)
removes all hooks.
Definition: evhtp.c:4393
htparser * htparser_new(void)
Definition: parser.c:578
unsigned int htparser_get_status(htparser *p)
Definition: parser.c:442
const char * evhtp_kv_find(evhtp_kvs_t *kvs, const char *key)
find the string value of &#39;key&#39; from the key/value list &#39;kvs&#39;
Definition: evhtp.c:3288
uint64_t htparser_get_content_length(htparser *p)
Definition: parser.c:548
void(* evhtp_callback_cb)(evhtp_request_t *req, void *arg)
Definition: evhtp/evhtp.h:157
static int htp__authority_new_(evhtp_authority_t **out)
create an authority structure
Definition: evhtp.c:1132
unsigned char htparser_get_minor(htparser *p)
Definition: parser.c:518
evhtp_callback_t * evhtp_set_glob_cb(evhtp_t *htp, const char *pattern, evhtp_callback_cb cb, void *arg)
sets a callback to to be executed on simple glob/wildcard patterns this is useful if the app does not...
Definition: evhtp.c:4666
#define evhtp_query_free
Definition: evhtp/evhtp.h:1219
evhtp_res(* evhtp_hook_chunk_new_cb)(evhtp_request_t *r, uint64_t len, void *arg)
Definition: evhtp/evhtp.h:173
#define ssl_sk_connect_
Definition: evhtp.c:5438
static int htp__create_headers_(evhtp_header_t *header, void *arg)
Definition: evhtp.c:2067
int evhtp_make_request(evhtp_connection_t *c, evhtp_request_t *r, htp_method meth, const char *uri)
make a client request
Definition: evhtp.c:5529
int evhtp_response_needs_body(const evhtp_res code, const htp_method method)
Determine if a response should have a body.
Definition: evhtp.c:3819
#define EVHTP_FLAG_ENABLE_DEFER_ACCEPT
Definition: evhtp/evhtp.h:299
evhtp_query_t * evhtp_parse_query(const char *query, size_t len)
Parses the query portion of the uri into a set of key/values in a strict manner.
Definition: evhtp.c:3748
static char * htp__strdup_(const char *str)
implementation of strdup function.
Definition: evhtp.c:257
evhtp_res(* evhtp_hook_chunks_fini_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp/evhtp.h:175
#define EVHTP_FLAG_DEFAULTS
Definition: evhtp/evhtp.h:300
static int htp__should_parse_query_body_(evhtp_request_t *req)
determines if the request body contains the query arguments.
Definition: evhtp.c:1970
#define EVHTP_CONN_FLAG_KEEPALIVE
set to 1 after the first request has been processed and the connection is kept open ...
Definition: evhtp/evhtp.h:454
evhtp_kv_t * evhtp_kv_new(const char *key, const char *val, char key_alloc, char val_alloc)
Allocates a new key/value structure.
Definition: evhtp.c:3147
TAILQ_HEAD(evhtp_callbacks_s, evhtp_callback_s)
#define log_debug(M,...)
Definition: log.h:17
#define EVHTP_REQ_FLAG_FINISHED
Definition: evhtp/evhtp.h:412
int evhtp_callback_unset_hook(evhtp_callback_t *callback, evhtp_hook_type type)
Definition: evhtp.c:4357
#define EVHTP_CONN_FLAG_PAUSED
this connection has been marked as paused
Definition: evhtp/evhtp.h:450
#define evhtp_unlikely(x)
Definition: internal.h:18
evhtp_kvs_t * evhtp_kvs_new(void)
creates an empty list of key/values
Definition: evhtp.c:3134
static const char * status_code_to_str(evhtp_res code)
returns string status code from enum code
Definition: evhtp.c:342
static void *(* realloc_)(void *d, size_t sz)
Definition: evhtp.c:165
static int htp__request_parse_start_(htparser *p)
Starts the parser for the connection associated with the parser struct.
Definition: evhtp.c:1324
type which defines to hook after one header has been parsed
Definition: evhtp/evhtp.h:113
#define EVHTP_RES_OK
Definition: evhtp/evhtp.h:207
static int htp__request_parse_header_val_(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1478
int htparser_should_keep_alive(htparser *p)
Definition: parser.c:448
int evhtp_request_set_hook(evhtp_request_t *req, evhtp_hook_type type, evhtp_hook cb, void *arg)
Definition: evhtp.c:4381
static evhtp_res htp__hook_headers_(evhtp_request_t *request, evhtp_headers_t *headers)
runs the user-defined on_Headers hook for a request after all headers have been parsed.
Definition: evhtp.c:617
void evhtp_free(evhtp_t *evhtp)
Frees evhtp_t structure; will stop and free threads associated with the structure, and free the ssl context as well (if applicable).
Definition: evhtp.c:5306
#define HTP_FLAG_ON(PRE, FLAG)
Definition: evhtp.c:74
void evhtp_kvs_add_kvs(evhtp_kvs_t *dst, evhtp_kvs_t *src)
appends all key/val structures from src tailq onto dst tailq
Definition: evhtp.c:3339
void htparser_set_major(htparser *p, unsigned char major)
Definition: parser.c:500
#define evhtp_likely(x)
Definition: internal.h:17
#define evhtp_alloc_assert(x)
Definition: internal.h:44
static evhtp_proto htp__protocol_(const char major, const char minor)
returns the HTTP protocol version
Definition: evhtp.c:558
#define HTP_FLAG_FNGEN(NAME, TYPE)
Definition: evhtp.c:5129