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  /* connection is in a paused state, no further processing yet */
2377  if ((conn->flags & EVHTP_CONN_FLAG_PAUSED))
2378  {
2379  return;
2380  }
2381 
2382  /* run user-hook for on_write callback before further analysis */
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);
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  if (errno != EOPNOTSUPP) {
3968  break;
3969  }
3970 
3971  log_warn("SO_REUSEPORT not supported for this socket.. Skipping");
3972  }
3973  }
3974 #endif
3975 
3976 #if defined TCP_NODELAY
3977  if (htp->flags & EVHTP_FLAG_ENABLE_NODELAY)
3978  {
3979  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) == -1)
3980  {
3981  if (errno != EOPNOTSUPP) {
3982  break;
3983  }
3984 
3985  log_warn("TCP_NODELAY not supported for this socket.. Skipping");
3986  }
3987  }
3988 #endif
3989 
3990 #if defined TCP_DEFER_ACCEPT
3991  if (htp->flags & EVHTP_FLAG_ENABLE_DEFER_ACCEPT)
3992  {
3993  if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void *)&on, sizeof(on)) == -1)
3994  {
3995  if (errno != EOPNOTSUPP) {
3996  break;
3997  }
3998 
3999  log_warn("TCP_DEFER_ACCEPT not supported for this socket.. Skipping");
4000  }
4001  }
4002 #endif
4003 
4004  htp->server = evconnlistener_new(htp->evbase, htp__accept_cb_, htp,
4005  LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
4006  backlog, sock);
4007 
4008  if (htp->server == NULL)
4009  {
4010  break;
4011  }
4012 
4013 #ifndef EVHTP_DISABLE_SSL
4014  if (htp->ssl_ctx != NULL)
4015  {
4016  /* if ssl is enabled and we have virtual hosts, set our servername
4017  * callback. We do this here because we want to make sure that this gets
4018  * set after all potential virtualhosts have been set, not just after
4019  * ssl_init.
4020  */
4021  if (TAILQ_FIRST(&htp->vhosts) != NULL)
4022  {
4023  SSL_CTX_set_tlsext_servername_callback(htp->ssl_ctx,
4025  }
4026  }
4027 #endif
4028  err = 0;
4029  } while (0);
4030 
4031  if (err == 1)
4032  {
4033  if (htp->server != NULL)
4034  {
4035  evhtp_safe_free(htp->server, evconnlistener_free);
4036  }
4037 
4038  return -1;
4039  }
4040 
4041  return 0;
4042 } /* evhtp_accept_socket */
4043 
4044 int
4045 evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int backlog)
4046 {
4047  evutil_socket_t fd = -1;
4048  int on = 1;
4049  int error = 1;
4050 
4051  if (htp == NULL)
4052  {
4053  return -1;
4054  }
4055 
4056  /* XXX: API's should not set signals */
4057 #ifndef WIN32
4058  signal(SIGPIPE, SIG_IGN);
4059 #endif
4060 
4061  do {
4062  if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1)
4063  {
4064  return -1;
4065  }
4066 
4067 
4068  evutil_make_socket_closeonexec(fd);
4069  evutil_make_socket_nonblocking(fd);
4070 
4071  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1)
4072  {
4073  break;
4074  }
4075 
4076  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == -1)
4077  {
4078  break;
4079  }
4080 
4081  if (sa->sa_family == AF_INET6)
4082  {
4083  if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
4084  {
4085  break;
4086  }
4087  }
4088 
4089  if (bind(fd, sa, sin_len) == -1)
4090  {
4091  break;
4092  }
4093 
4094  error = 0;
4095  } while (0);
4096 
4097 
4098  if (error == 1)
4099  {
4100  if (fd != -1)
4101  {
4102  evutil_closesocket(fd);
4103  }
4104 
4105  return -1;
4106  }
4107 
4108  if (evhtp_accept_socket(htp, fd, backlog) == -1)
4109  {
4110  /* accept_socket() does not close the descriptor
4111  * on error, but this function does.
4112  */
4113  evutil_closesocket(fd);
4114 
4115  return -1;
4116  }
4117 
4118  return 0;
4119 } /* evhtp_bind_sockaddr */
4120 
4121 int
4122 evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog)
4123 {
4124 #ifndef NO_SYS_UN
4125  struct sockaddr_un sockun = { 0 };
4126 #endif
4127  struct sockaddr * sa;
4128  struct sockaddr_in6 sin6 = { 0 };
4129  struct sockaddr_in sin = { 0 };
4130  size_t sin_len;
4131 
4132  if (!strncmp(baddr, "ipv6:", 5))
4133  {
4134  baddr += 5;
4135  sin_len = sizeof(struct sockaddr_in6);
4136  sin6.sin6_port = htons(port);
4137  sin6.sin6_family = AF_INET6;
4138 
4139  evutil_inet_pton(AF_INET6, baddr, &sin6.sin6_addr);
4140  sa = (struct sockaddr *)&sin6;
4141  } else if (!strncmp(baddr, "unix:", 5))
4142  {
4143 #ifndef NO_SYS_UN
4144  baddr += 5;
4145 
4146  if (strlen(baddr) >= sizeof(sockun.sun_path))
4147  {
4148  return -1;
4149  }
4150 
4151  sin_len = sizeof(struct sockaddr_un);
4152  sockun.sun_family = AF_UNIX;
4153 
4154  strncpy(sockun.sun_path, baddr, strlen(baddr));
4155 
4156  sa = (struct sockaddr *)&sockun;
4157 #else
4158 
4159  return -1;
4160 #endif
4161  } else {
4162  if (!strncmp(baddr, "ipv4:", 5))
4163  {
4164  baddr += 5;
4165  }
4166 
4167  sin_len = sizeof(struct sockaddr_in);
4168  sin.sin_family = AF_INET;
4169  sin.sin_port = htons(port);
4170  sin.sin_addr.s_addr = inet_addr(baddr);
4171 
4172  sa = (struct sockaddr *)&sin;
4173  }
4174 
4175  return evhtp_bind_sockaddr(htp, sa, sin_len, backlog);
4176 } /* evhtp_bind_socket */
4177 
4178 void
4180 {
4181  evhtp_callback_t * callback;
4182  evhtp_callback_t * tmp;
4183 
4184  if (callbacks == NULL)
4185  {
4186  return;
4187  }
4188 
4189  TAILQ_FOREACH_SAFE(callback, callbacks, next, tmp) {
4190  TAILQ_REMOVE(callbacks, callback, next);
4191 
4193  }
4194 
4195  evhtp_safe_free(callbacks, htp__free_);
4196 }
4197 
4198 evhtp_callback_t *
4200 {
4201  evhtp_callback_t * hcb;
4202 
4203  hcb = htp__calloc_(sizeof(evhtp_callback_t), 1);
4204  evhtp_alloc_assert(hcb);
4205 
4206  hcb->type = type;
4207  hcb->cb = cb;
4208  hcb->cbarg = arg;
4209  hcb->len = strlen(path);
4210 
4211  switch (type) {
4213  hcb->val.path = htp__strdup_(path);
4214  evhtp_alloc_assert(hcb->val.path);
4215  break;
4216 #ifndef EVHTP_DISABLE_REGEX
4218  hcb->val.regex = htp__malloc_(sizeof(regex_t));
4219  evhtp_alloc_assert(hcb->val.regex);
4220 
4221  if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0)
4222  {
4223  evhtp_safe_free(hcb->val.regex, htp__free_);
4225 
4226  return NULL;
4227  }
4228  break;
4229 #endif
4231  hcb->val.glob = htp__strdup_(path);
4232  evhtp_alloc_assert(hcb->val.glob);
4233  break;
4234  default:
4236 
4237  return NULL;
4238  } /* switch */
4239 
4240  return hcb;
4241 } /* evhtp_callback_new */
4242 
4243 void
4244 evhtp_callback_free(evhtp_callback_t * callback)
4245 {
4246  if (callback == NULL)
4247  {
4248  return;
4249  }
4250 
4251  switch (callback->type) {
4253  evhtp_safe_free(callback->val.path, htp__free_);
4254  break;
4256  evhtp_safe_free(callback->val.glob, htp__free_);
4257  break;
4258 #ifndef EVHTP_DISABLE_REGEX
4260  regfree(callback->val.regex);
4261  evhtp_safe_free(callback->val.regex, htp__free_);
4262  break;
4263 #endif
4264  }
4265 
4266  if (callback->hooks)
4267  {
4268  evhtp_safe_free(callback->hooks, htp__free_);
4269  }
4270 
4271  evhtp_safe_free(callback, htp__free_);
4272 
4273  return;
4274 }
4275 
4276 int
4278 {
4279  TAILQ_INSERT_TAIL(cbs, cb, next);
4280 
4281  return 0;
4282 }
4283 
4284 static int
4285 htp__set_hook_(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
4286 {
4287  if (*hooks == NULL)
4288  {
4289  if (!(*hooks = htp__calloc_(sizeof(evhtp_hooks_t), 1)))
4290  {
4291  return -1;
4292  }
4293  }
4294 
4295  switch (type) {
4297  (*hooks)->on_headers_start = (evhtp_hook_headers_start_cb)cb;
4298  (*hooks)->on_headers_start_arg = arg;
4299  break;
4300  case evhtp_hook_on_header:
4301  (*hooks)->on_header = (evhtp_hook_header_cb)cb;
4302  (*hooks)->on_header_arg = arg;
4303  break;
4304  case evhtp_hook_on_headers:
4305  (*hooks)->on_headers = (evhtp_hook_headers_cb)cb;
4306  (*hooks)->on_headers_arg = arg;
4307  break;
4308  case evhtp_hook_on_path:
4309  (*hooks)->on_path = (evhtp_hook_path_cb)cb;
4310  (*hooks)->on_path_arg = arg;
4311  break;
4312  case evhtp_hook_on_read:
4313  (*hooks)->on_read = (evhtp_hook_read_cb)cb;
4314  (*hooks)->on_read_arg = arg;
4315  break;
4317  (*hooks)->on_request_fini = (evhtp_hook_request_fini_cb)cb;
4318  (*hooks)->on_request_fini_arg = arg;
4319  break;
4321  (*hooks)->on_connection_fini = (evhtp_hook_connection_fini_cb)cb;
4322  (*hooks)->on_connection_fini_arg = arg;
4323  break;
4325  (*hooks)->on_connection_error = (evhtp_hook_conn_err_cb)cb;
4326  (*hooks)->on_connection_error_arg = arg;
4327  break;
4328  case evhtp_hook_on_error:
4329  (*hooks)->on_error = (evhtp_hook_err_cb)cb;
4330  (*hooks)->on_error_arg = arg;
4331  break;
4333  (*hooks)->on_new_chunk = (evhtp_hook_chunk_new_cb)cb;
4334  (*hooks)->on_new_chunk_arg = arg;
4335  break;
4337  (*hooks)->on_chunk_fini = (evhtp_hook_chunk_fini_cb)cb;
4338  (*hooks)->on_chunk_fini_arg = arg;
4339  break;
4341  (*hooks)->on_chunks_fini = (evhtp_hook_chunks_fini_cb)cb;
4342  (*hooks)->on_chunks_fini_arg = arg;
4343  break;
4345  (*hooks)->on_hostname = (evhtp_hook_hostname_cb)cb;
4346  (*hooks)->on_hostname_arg = arg;
4347  break;
4348  case evhtp_hook_on_write:
4349  (*hooks)->on_write = (evhtp_hook_write_cb)cb;
4350  (*hooks)->on_write_arg = arg;
4351  break;
4352  case evhtp_hook_on_event:
4353  (*hooks)->on_event = (evhtp_hook_event_cb)cb;
4354  (*hooks)->on_event_arg = arg;
4355  break;
4356  default:
4357  return -1;
4358  } /* switch */
4359 
4360  return 0;
4361 } /* htp__set_hook_ */
4362 
4363 static int
4365  return htp__set_hook_(hooks, type, NULL, NULL);
4366 }
4367 
4368 int
4369 evhtp_callback_unset_hook(evhtp_callback_t * callback, evhtp_hook_type type)
4370 {
4371  return htp__unset_hook_(&callback->hooks, type);
4372 }
4373 
4374 int
4376 {
4377  return htp__unset_hook_(&req->hooks, type);
4378 }
4379 
4380 int
4382 {
4383  return htp__unset_hook_(&conn->hooks, type);
4384 }
4385 
4386 int
4387 evhtp_callback_set_hook(evhtp_callback_t * callback, evhtp_hook_type type, evhtp_hook cb, void * arg)
4388 {
4389  return htp__set_hook_(&callback->hooks, type, cb, arg);
4390 }
4391 
4392 int
4393 evhtp_request_set_hook(evhtp_request_t * req, evhtp_hook_type type, evhtp_hook cb, void * arg)
4394 {
4395  return htp__set_hook_(&req->hooks, type, cb, arg);
4396 }
4397 
4398 int
4399 evhtp_connection_set_hook(evhtp_connection_t * conn, evhtp_hook_type type, evhtp_hook cb, void * arg)
4400 {
4401  return htp__set_hook_(&conn->hooks, type, cb, arg);
4402 }
4403 
4404 int
4405 evhtp_unset_all_hooks(evhtp_hooks_t ** hooks)
4406 {
4407  int i;
4408 
4409  struct {
4410  enum evhtp_hook_type type;
4411  } hooklist_[] = {
4414  { evhtp_hook_on_path },
4415  { evhtp_hook_on_read },
4422  { evhtp_hook_on_error },
4424  { evhtp_hook_on_write },
4425  { evhtp_hook_on_event },
4427  { -1 }
4428  };
4429 
4430  if (hooks == NULL) {
4431  return -1;
4432  }
4433 
4434  for (i = 0; hooklist_[i].type != -1; i++) {
4435  if (htp__unset_hook_(hooks, hooklist_[i].type) == -1) {
4436  return -1;
4437  }
4438  }
4439 
4440  return 0;
4441 }
4442 
4443 evhtp_hooks_t *
4444 evhtp_connection_get_hooks(evhtp_connection_t * c)
4445 {
4446  if (evhtp_unlikely(c == NULL))
4447  {
4448  return NULL;
4449  }
4450 
4451  return c->hooks;
4452 }
4453 
4460 evhtp_hooks_t *
4461 evhtp_request_get_hooks(evhtp_request_t * r)
4462 {
4463  if (evhtp_unlikely(r == NULL))
4464  {
4465  return NULL;
4466  }
4467 
4468  return r->hooks;
4469 }
4470 
4477 evhtp_hooks_t *
4478 evhtp_callback_get_hooks(evhtp_callback_t * cb)
4479 {
4480  return cb->hooks;
4481 }
4482 
4483 evhtp_callback_t *
4484 evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg)
4485 {
4486  evhtp_callback_t * hcb;
4487 
4488  htp__lock_(htp);
4489 
4490  if (htp->callbacks == NULL)
4491  {
4492  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4493  {
4494  htp__unlock_(htp);
4495 
4496  return NULL;
4497  }
4498 
4499  TAILQ_INIT(htp->callbacks);
4500  }
4501 
4502  if (!(hcb = evhtp_callback_new(path, evhtp_callback_type_hash, cb, arg)))
4503  {
4504  htp__unlock_(htp);
4505 
4506  return NULL;
4507  }
4508 
4509  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4510  {
4512  htp__unlock_(htp);
4513 
4514  return NULL;
4515  }
4516 
4517  htp__unlock_(htp);
4518 
4519  return hcb;
4520 }
4521 
4522 evhtp_callback_t *
4523 evhtp_get_cb(evhtp_t * htp, const char * path)
4524 {
4525  evhtp_callback_t * callback;
4526 
4527  evhtp_assert(htp != NULL);
4528 
4529  if (evhtp_unlikely(htp->callbacks == NULL))
4530  {
4531  return NULL;
4532  }
4533 
4534  TAILQ_FOREACH(callback, htp->callbacks, next) {
4535  if (strcmp(callback->val.path, path) == 0)
4536  {
4537  return callback;
4538  }
4539  }
4540 
4541  return NULL;
4542 }
4543 
4544 #ifndef EVHTP_DISABLE_EVTHR
4545 static void
4546 htp__thread_init_(evthr_t * thr, void * arg)
4547 {
4548  evhtp_t * htp = (evhtp_t *)arg;
4549 
4550  if (htp->thread_init_cb)
4551  {
4552  htp->thread_init_cb(htp, thr, htp->thread_cbarg);
4553  }
4554 }
4555 
4556 static void
4557 htp__thread_exit_(evthr_t * thr, void * arg)
4558 {
4559  evhtp_t * htp = (evhtp_t *)arg;
4560 
4561  if (htp->thread_exit_cb)
4562  {
4563  htp->thread_exit_cb(htp, thr, htp->thread_cbarg);
4564  }
4565 }
4566 
4567 static int
4568 htp__use_threads_(evhtp_t * htp,
4569  evhtp_thread_init_cb init_cb,
4570  evhtp_thread_exit_cb exit_cb,
4571  int nthreads, void * arg)
4572 {
4573  if (htp == NULL)
4574  {
4575  return -1;
4576  }
4577 
4578  htp->thread_cbarg = arg;
4579  htp->thread_init_cb = init_cb;
4580  htp->thread_exit_cb = exit_cb;
4581 
4582 #ifndef EVHTP_DISABLE_SSL
4584 #endif
4585 
4586  if (!(htp->thr_pool = evthr_pool_wexit_new(nthreads,
4588  htp__thread_exit_, htp)))
4589  {
4590  return -1;
4591  }
4592 
4593  evthr_pool_start(htp->thr_pool);
4594 
4595  return 0;
4596 }
4597 
4598 int
4600  int nthreads, void * arg)
4601 {
4602  return htp__use_threads_(htp, init_cb, NULL, nthreads, arg);
4603 }
4604 
4605 int
4607  evhtp_thread_init_cb init_cb,
4608  evhtp_thread_exit_cb exit_cb,
4609  int nthreads, void * arg)
4610 {
4611  return htp__use_threads_(htp, init_cb, exit_cb, nthreads, arg);
4612 }
4613 
4614 #endif
4615 
4616 #ifndef EVHTP_DISABLE_EVTHR
4617 int
4619 {
4620  if (htp == NULL)
4621  {
4622  return -1;
4623  }
4624 
4625  if (!(htp->lock = htp__malloc_(sizeof(pthread_mutex_t))))
4626  {
4627  return -1;
4628  }
4629 
4630  return pthread_mutex_init(htp->lock, NULL);
4631 }
4632 
4633 #endif
4634 
4635 #ifndef EVHTP_DISABLE_REGEX
4636 evhtp_callback_t *
4637 evhtp_set_regex_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg)
4638 {
4639  evhtp_callback_t * hcb;
4640 
4641  htp__lock_(htp);
4642 
4643  if (htp->callbacks == NULL)
4644  {
4645  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4646  {
4647  htp__unlock_(htp);
4648 
4649  return NULL;
4650  }
4651 
4652  TAILQ_INIT(htp->callbacks);
4653  }
4654 
4655  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_regex, cb, arg)))
4656  {
4657  htp__unlock_(htp);
4658 
4659  return NULL;
4660  }
4661 
4662  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4663  {
4665  htp__unlock_(htp);
4666 
4667  return NULL;
4668  }
4669 
4670  htp__unlock_(htp);
4671 
4672  return hcb;
4673 }
4674 
4675 #endif
4676 
4677 evhtp_callback_t *
4678 evhtp_set_glob_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg)
4679 {
4680  evhtp_callback_t * hcb;
4681 
4682  htp__lock_(htp);
4683 
4684  if (htp->callbacks == NULL)
4685  {
4686  if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
4687  {
4688  htp__unlock_(htp);
4689 
4690  return NULL;
4691  }
4692 
4693  TAILQ_INIT(htp->callbacks);
4694  }
4695 
4696  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_glob, cb, arg)))
4697  {
4698  htp__unlock_(htp);
4699 
4700  return NULL;
4701  }
4702 
4703  if (evhtp_callbacks_add_callback(htp->callbacks, hcb))
4704  {
4706  htp__unlock_(htp);
4707 
4708  return NULL;
4709  }
4710 
4711  htp__unlock_(htp);
4712 
4713  return hcb;
4714 }
4715 
4716 void
4717 evhtp_set_gencb(evhtp_t * htp, evhtp_callback_cb cb, void * arg)
4718 {
4719  htp->defaults.cb = cb;
4720  htp->defaults.cbarg = arg;
4721 }
4722 
4723 void
4725 {
4726  htp->defaults.pre_accept = cb;
4727  htp->defaults.pre_accept_cbarg = arg;
4728 }
4729 
4730 void
4732 {
4733  htp->defaults.post_accept = cb;
4734  htp->defaults.post_accept_cbarg = arg;
4735 }
4736 
4737 #ifndef EVHTP_DISABLE_SSL
4738 #ifndef EVHTP_DISABLE_EVTHR
4739 int
4741 {
4742  int i;
4743 
4744  if (ssl_locks_initialized == 1)
4745  {
4746  return 0;
4747  }
4748 
4749  ssl_locks_initialized = 1;
4750  ssl_num_locks = CRYPTO_num_locks();
4751 
4752  if ((ssl_locks = htp__calloc_(ssl_num_locks,
4753  sizeof(evhtp_mutex_t))) == NULL)
4754  {
4755  return -1;
4756  }
4757 
4758  for (i = 0; i < ssl_num_locks; i++)
4759  {
4760  pthread_mutex_init(&(ssl_locks[i]), NULL);
4761  }
4762 
4763  CRYPTO_set_id_callback(htp__ssl_get_thread_id_);
4764  CRYPTO_set_locking_callback(htp__ssl_thread_lock_);
4765 
4766  return 0;
4767 }
4768 
4769 #endif
4770 
4771 int
4772 evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg)
4773 {
4774  long cache_mode;
4775  unsigned char c;
4776 
4777  if (cfg == NULL || htp == NULL || cfg->pemfile == NULL)
4778  {
4779  return -1;
4780  }
4781 
4782 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4783  SSL_library_init();
4784  ERR_load_crypto_strings();
4785  SSL_load_error_strings();
4786  OpenSSL_add_all_algorithms();
4787 #else
4788  /* unnecessary in OpenSSL 1.1.0 */
4789  /*
4790  * if (OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL) == 0) {
4791  * log_error("OPENSSL_init_ssl");
4792  * return -1;
4793  * }
4794  *
4795  * if (OPENSSL_init_crypto(
4796  * OPENSSL_INIT_ADD_ALL_CIPHERS |
4797  * OPENSSL_INIT_ADD_ALL_DIGESTS |
4798  * OPENSSL_INIT_LOAD_CONFIG, NULL) == 0) {
4799  * log_error("OPENSSL_init_crypto");
4800  * return -1;
4801  * }
4802  */
4803 #endif
4804  if (RAND_poll() != 1) {
4805  log_error("RAND_poll");
4806  return -1;
4807  }
4808 
4809  if (RAND_bytes(&c, 1) != 1) {
4810  log_error("RAND_bytes");
4811  return -1;
4812  }
4813 
4814 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4815  STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
4816  sk_SSL_COMP_zero(comp_methods);
4817 #endif
4818 
4819  htp->ssl_cfg = cfg;
4820 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4821  htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
4822 #else
4823  htp->ssl_ctx = SSL_CTX_new(TLS_server_method());
4824 #endif
4825 
4826  evhtp_alloc_assert(htp->ssl_ctx);
4827 
4828 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
4829  SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS | SSL_OP_NO_COMPRESSION);
4830  SSL_CTX_set_timeout(htp->ssl_ctx, cfg->ssl_ctx_timeout);
4831 #endif
4832 
4833  SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);
4834 
4835 #ifndef OPENSSL_NO_ECDH
4836  if (cfg->named_curve != NULL) {
4837  EC_KEY * ecdh = NULL;
4838  int nid = 0;
4839 
4840  nid = OBJ_sn2nid(cfg->named_curve);
4841 
4842  if (nid == 0) {
4843  log_error("ECDH initialization failed: unknown curve %s", cfg->named_curve);
4844  }
4845 
4846  ecdh = EC_KEY_new_by_curve_name(nid);
4847 
4848  if (ecdh == NULL) {
4849  log_error("ECDH initialization failed for curve %s", cfg->named_curve);
4850  }
4851 
4852  SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh);
4853  EC_KEY_free(ecdh);
4854  }
4855 #endif /* OPENSSL_NO_ECDH */
4856 #ifndef OPENSSL_NO_DH
4857  if (cfg->dhparams != NULL)
4858  {
4859  FILE * fh;
4860  DH * dh;
4861 
4862  fh = fopen(cfg->dhparams, "r");
4863 
4864  if (fh != NULL)
4865  {
4866  dh = PEM_read_DHparams(fh, NULL, NULL, NULL);
4867  if (dh != NULL)
4868  {
4869  SSL_CTX_set_tmp_dh(htp->ssl_ctx, dh);
4870  DH_free(dh);
4871  } else {
4872  log_error("DH initialization failed: unable to parse file %s", cfg->dhparams);
4873  }
4874 
4875  fclose(fh);
4876  } else {
4877  log_error("DH initialization failed: unable to open file %s", cfg->dhparams);
4878  }
4879  }
4880 #endif /* OPENSSL_NO_DH */
4881 
4882  if (cfg->ciphers != NULL) {
4883  if (SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers) == 0) {
4884  log_error("set_cipher_list");
4885  return -1;
4886  }
4887  }
4888 
4889  SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
4890  X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
4891  SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);
4892 
4893  if (cfg->x509_chk_issued_cb != NULL) {
4894 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4895  htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
4896 #else
4897  X509_STORE_set_check_issued(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->x509_chk_issued_cb);
4898 #endif
4899  }
4900 
4901  if (cfg->verify_depth) {
4902  SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
4903  }
4904 
4905  switch (cfg->scache_type) {
4907  cache_mode = SSL_SESS_CACHE_OFF;
4908  break;
4909  default:
4910  cache_mode = SSL_SESS_CACHE_SERVER;
4911  break;
4912  } /* switch */
4913 
4914  SSL_CTX_use_certificate_chain_file(htp->ssl_ctx, cfg->pemfile);
4915 
4916  char * const key = cfg->privfile ? cfg->privfile : cfg->pemfile;
4917 
4918  if (cfg->decrypt_cb != NULL)
4919  {
4920  EVP_PKEY * pkey = cfg->decrypt_cb(key);
4921 
4922  if (pkey == NULL)
4923  {
4924  return -1;
4925  }
4926 
4927  SSL_CTX_use_PrivateKey(htp->ssl_ctx, pkey);
4928 
4929  /*cleanup */
4930  EVP_PKEY_free(pkey);
4931  } else {
4932  SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, key, SSL_FILETYPE_PEM);
4933  }
4934 
4935  SSL_CTX_set_session_id_context(htp->ssl_ctx,
4936  (void *)&session_id_context,
4937  sizeof(session_id_context));
4938 
4939  SSL_CTX_set_app_data(htp->ssl_ctx, htp);
4940  SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);
4941 
4942  if (cache_mode != SSL_SESS_CACHE_OFF)
4943  {
4944  SSL_CTX_sess_set_cache_size(htp->ssl_ctx,
4945  cfg->scache_size ? cfg->scache_size : 1024);
4946 
4947  if (cfg->scache_type == evhtp_ssl_scache_type_builtin ||
4948  cfg->scache_type == evhtp_ssl_scache_type_user)
4949  {
4950  SSL_CTX_sess_set_new_cb(htp->ssl_ctx, htp__ssl_add_scache_ent_);
4951  SSL_CTX_sess_set_get_cb(htp->ssl_ctx, htp__ssl_get_scache_ent_);
4952  SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, htp__ssl_delete_scache_ent_);
4953 
4954  if (cfg->scache_init)
4955  {
4956  cfg->args = (cfg->scache_init)(htp);
4957  }
4958  }
4959  }
4960 
4961  return 0;
4962 } /* evhtp_use_ssl */
4963 
4964 #endif
4965 
4966 struct bufferevent *
4967 evhtp_connection_get_bev(evhtp_connection_t * connection) {
4968  return connection->bev;
4969 }
4970 
4971 struct bufferevent *
4972 evhtp_connection_take_ownership(evhtp_connection_t * connection) {
4973  struct bufferevent * bev = evhtp_connection_get_bev(connection);
4974 
4975  if (connection->hooks)
4976  {
4977  evhtp_unset_all_hooks(&connection->hooks);
4978  }
4979 
4980  if (connection->request && connection->request->hooks)
4981  {
4982  evhtp_unset_all_hooks(&connection->request->hooks);
4983  }
4984 
4985  evhtp_connection_set_bev(connection, NULL);
4986 
4987  /* relinquish ownership of this connection, unset
4988  * the ownership flag.
4989  */
4990  HTP_FLAG_OFF(connection, EVHTP_CONN_FLAG_OWNER);
4991 
4992  bufferevent_disable(bev, EV_READ);
4993  bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
4994 
4995  return bev;
4996 }
4997 
4998 struct bufferevent *
4999 evhtp_request_get_bev(evhtp_request_t * request) {
5000  return evhtp_connection_get_bev(request->conn);
5001 }
5002 
5003 struct bufferevent *
5004 evhtp_request_take_ownership(evhtp_request_t * request) {
5005  return evhtp_connection_take_ownership(request->conn);
5006 }
5007 
5008 void
5009 evhtp_connection_set_bev(evhtp_connection_t * conn, struct bufferevent * bev)
5010 {
5011  conn->bev = bev;
5012 }
5013 
5014 void
5015 evhtp_request_set_bev(evhtp_request_t * request, struct bufferevent * bev)
5016 {
5017  evhtp_connection_set_bev(request->conn, bev);
5018 }
5019 
5020 void
5021 evhtp_request_set_keepalive(evhtp_request_t * request, int val)
5022 {
5023  if (val)
5024  {
5026  }
5027 }
5028 
5029 evhtp_connection_t *
5030 evhtp_request_get_connection(evhtp_request_t * request)
5031 {
5032  return request->conn;
5033 }
5034 
5036 evhtp_request_get_proto(evhtp_request_t * request)
5037 {
5038  return request->proto;
5039 }
5040 
5041 inline void
5042 evhtp_connection_set_timeouts(evhtp_connection_t * c,
5043  const struct timeval * rtimeo,
5044  const struct timeval * wtimeo)
5045 {
5046  if (evhtp_unlikely(c == NULL))
5047  {
5048  return;
5049  }
5050 
5051 
5052  bufferevent_set_timeouts(c->bev, rtimeo, wtimeo);
5053 }
5054 
5055 void
5056 evhtp_connection_set_max_body_size(evhtp_connection_t * c, uint64_t len)
5057 {
5058  if (len == 0)
5059  {
5060  c->max_body_size = c->htp->max_body_size;
5061  } else {
5062  c->max_body_size = len;
5063  }
5064 }
5065 
5066 void
5067 evhtp_request_set_max_body_size(evhtp_request_t * req, uint64_t len)
5068 {
5069  evhtp_connection_set_max_body_size(req->conn, len);
5070 }
5071 
5072 void
5073 evhtp_connection_free(evhtp_connection_t * connection)
5074 {
5075  if (evhtp_unlikely(connection == NULL))
5076  {
5077  return;
5078  }
5079 
5080  htp__hook_connection_fini_(connection);
5081 
5082  evhtp_safe_free(connection->request, htp__request_free_);
5083  evhtp_safe_free(connection->parser, htp__free_);
5084  evhtp_safe_free(connection->hooks, htp__free_);
5085  evhtp_safe_free(connection->saddr, htp__free_);
5086  evhtp_safe_free(connection->scratch_buf, evbuffer_free);
5087 
5088  if (connection->resume_ev)
5089  {
5090  evhtp_safe_free(connection->resume_ev, event_free);
5091  }
5092 
5093  if (connection->bev)
5094  {
5095 #ifdef LIBEVENT_HAS_SHUTDOWN
5096  bufferevent_shutdown(connection->bev, htp__shutdown_eventcb_);
5097 #else
5098 #ifndef EVHTP_DISABLE_SSL
5099  if (connection->ssl != NULL)
5100  {
5101  SSL_set_shutdown(connection->ssl, SSL_RECEIVED_SHUTDOWN);
5102  SSL_shutdown(connection->ssl);
5103  }
5104 #endif
5105  bufferevent_free(connection->bev);
5106 #endif
5107  }
5108 
5109  evhtp_safe_free(connection, htp__free_);
5110 } /* evhtp_connection_free */
5111 
5112 void
5113 evhtp_request_free(evhtp_request_t * request)
5114 {
5115  htp__request_free_(request);
5116 }
5117 
5118 void
5119 evhtp_set_timeouts(evhtp_t * htp, const struct timeval * r_timeo, const struct timeval * w_timeo)
5120 {
5121  if (r_timeo != NULL)
5122  {
5123  htp->recv_timeo = *r_timeo;
5124  }
5125 
5126  if (w_timeo != NULL)
5127  {
5128  htp->send_timeo = *w_timeo;
5129  }
5130 }
5131 
5132 void
5133 evhtp_set_max_keepalive_requests(evhtp_t * htp, uint64_t num)
5134 {
5135  htp->max_keepalive_requests = num;
5136 }
5137 
5138 void
5139 evhtp_set_bev_flags(evhtp_t * htp, int flags)
5140 {
5141  htp->bev_flags = flags;
5142 }
5143 
5144 void
5145 evhtp_set_max_body_size(evhtp_t * htp, uint64_t len)
5146 {
5147  htp->max_body_size = len;
5148 }
5149 
5150 void
5152 {
5154 }
5155 
5156 void
5157 evhtp_set_parser_flags(evhtp_t * htp, int flags)
5158 {
5159  htp->parser_flags = flags;
5160 }
5161 
5162 #define HTP_FLAG_FNGEN(NAME, TYPE) void \
5163  evhtp ## NAME ## _enable_flag(TYPE v, int flag) { \
5164  HTP_FLAG_ON(v, flag); \
5165  } \
5166  \
5167  void \
5168  evhtp ## NAME ## _disable_flag(TYPE v, int flag) { \
5169  HTP_FLAG_OFF(v, flag); \
5170  } \
5171  \
5172  int \
5173  evhtp ## NAME ## _get_flags(TYPE v) { \
5174  if (v) \
5175  { \
5176  return v->flags; \
5177  } \
5178  return -1; \
5179  }
5180 
5181 HTP_FLAG_FNGEN(, evhtp_t *);
5182 HTP_FLAG_FNGEN(_connection, evhtp_connection_t *);
5183 HTP_FLAG_FNGEN(_request, evhtp_request_t *);
5184 
5185 int
5186 evhtp_add_alias(evhtp_t * evhtp, const char * name)
5187 {
5188  evhtp_alias_t * alias;
5189 
5190  if (evhtp_unlikely(evhtp == NULL || name == NULL))
5191  {
5192  return -1;
5193  }
5194 
5195  if (!(alias = htp__calloc_(sizeof(evhtp_alias_t), 1)))
5196  {
5197  return -1;
5198  }
5199 
5200  log_debug("Adding %s to aliases", name);
5201 
5202  alias->alias = htp__strdup_(name);
5203  evhtp_alloc_assert(alias->alias);
5204 
5205  TAILQ_INSERT_TAIL(&evhtp->aliases, alias, next);
5206 
5207  return 0;
5208 }
5209 
5210 int
5211 evhtp_add_aliases(evhtp_t * htp, const char * name, ...) {
5212  va_list argp;
5213  size_t len;
5214 
5215  if (evhtp_add_alias(htp, name) == -1) {
5216  return -1;
5217  }
5218 
5219  va_start(argp, name);
5220  {
5221  const char * p;
5222 
5223  while ((p = va_arg(argp, const char *)) != NULL) {
5224  if (evhtp_add_alias(htp, p) == -1) {
5225  log_error("Unable to add %s alias", p);
5226  return -1;
5227  }
5228  }
5229  }
5230  va_end(argp);
5231 
5232  return 0;
5233 }
5234 
5235 int
5236 evhtp_add_vhost(evhtp_t * evhtp, const char * name, evhtp_t * vhost)
5237 {
5238  if (evhtp == NULL || name == NULL || vhost == NULL)
5239  {
5240  return -1;
5241  }
5242 
5243  if (TAILQ_FIRST(&vhost->vhosts) != NULL)
5244  {
5245  /* vhosts cannot have secondary vhosts defined */
5246  return -1;
5247  }
5248 
5249  if (!(vhost->server_name = htp__strdup_(name)))
5250  {
5251  return -1;
5252  }
5253 
5254  /* set the parent of this vhost so when the request has been completely
5255  * serviced, the vhost can be reset to the original evhtp structure.
5256  *
5257  * This allows for a keep-alive connection to make multiple requests with
5258  * different Host: values.
5259  */
5260  vhost->parent = evhtp;
5261 
5262  /* inherit various flags from the parent evhtp structure */
5263  vhost->bev_flags = evhtp->bev_flags;
5264  vhost->max_body_size = evhtp->max_body_size;
5265  vhost->max_keepalive_requests = evhtp->max_keepalive_requests;
5266  vhost->recv_timeo = evhtp->recv_timeo;
5267  vhost->send_timeo = evhtp->send_timeo;
5268 
5269  TAILQ_INSERT_TAIL(&evhtp->vhosts, vhost, next_vhost);
5270 
5271  return 0;
5272 }
5273 
5283 static int
5284 evhtp__new_(evhtp_t ** out, struct event_base * evbase, void * arg)
5285 {
5286  evhtp_t * htp;
5287 
5288 
5289  if (evhtp_unlikely(evbase == NULL))
5290  {
5291  return -1;
5292  }
5293 
5294  *out = NULL;
5295 
5296  if ((htp = htp__calloc_(1, sizeof(*htp))) == NULL)
5297  {
5298  return -1;
5299  }
5300 
5301 
5302  htp->arg = arg;
5303  htp->evbase = evbase;
5304  htp->flags = EVHTP_FLAG_DEFAULTS;
5305  htp->bev_flags = BEV_OPT_CLOSE_ON_FREE;
5306 
5307  /* default to lenient argument parsing */
5308  htp->parser_flags = EVHTP_PARSE_QUERY_FLAG_DEFAULT;
5309 
5310 
5311  TAILQ_INIT(&htp->vhosts);
5312  TAILQ_INIT(&htp->aliases);
5313 
5314  /* note that we pass the htp context to the callback,
5315  * not the user supplied arguments. That is stored
5316  * within the context itself.
5317  */
5318  evhtp_set_gencb(htp, htp__default_request_cb_, (void *)htp);
5319 
5320  *out = htp;
5321 
5322  return 0;
5323 }
5324 
5325 evhtp_t *
5326 evhtp_new(struct event_base * evbase, void * arg)
5327 {
5328  evhtp_t * htp;
5329 
5330  if (evhtp__new_(&htp, evbase, arg) == -1)
5331  {
5332  return NULL;
5333  }
5334 
5335  return htp;
5336 }
5337 
5338 void
5339 evhtp_free(evhtp_t * evhtp)
5340 {
5341  evhtp_alias_t * evhtp_alias, * tmp;
5342 
5343  if (evhtp == NULL)
5344  {
5345  return;
5346  }
5347 
5348 #ifndef EVHTP_DISABLE_EVTHR
5349  if (evhtp->thr_pool)
5350  {
5351  evthr_pool_stop(evhtp->thr_pool);
5352  evthr_pool_free(evhtp->thr_pool);
5353  }
5354 #endif
5355 
5356 #ifndef EVHTP_DISABLE_SSL
5357  if (evhtp->ssl_ctx)
5358  {
5359  evhtp_safe_free(evhtp->ssl_ctx, SSL_CTX_free);
5360  }
5361 #endif
5362 
5363  if (evhtp->server_name)
5364  {
5365  evhtp_safe_free(evhtp->server_name, htp__free_);
5366  }
5367 
5368  if (evhtp->callbacks)
5369  {
5370  evhtp_safe_free(evhtp->callbacks, evhtp_callbacks_free);
5371  }
5372 
5373  TAILQ_FOREACH_SAFE(evhtp_alias, &evhtp->aliases, next, tmp) {
5374  if (evhtp_alias->alias != NULL)
5375  {
5376  evhtp_safe_free(evhtp_alias->alias, htp__free_);
5377  }
5378 
5379  TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next);
5380  evhtp_safe_free(evhtp_alias, htp__free_);
5381  }
5382 
5383  evhtp_safe_free(evhtp, htp__free_);
5384 } /* evhtp_free */
5385 
5386 /*****************************************************************
5387 * client request functions *
5388 *****************************************************************/
5389 
5390 evhtp_connection_t *
5391 evhtp_connection_new(struct event_base * evbase, const char * addr, uint16_t port)
5392 {
5393  return evhtp_connection_new_dns(evbase, NULL, addr, port);
5394 }
5395 
5396 evhtp_connection_t *
5397 evhtp_connection_new_dns(struct event_base * evbase, struct evdns_base * dns_base,
5398  const char * addr, uint16_t port)
5399 {
5400  evhtp_connection_t * conn;
5401  int err;
5402 
5403  log_debug("Enter");
5404  evhtp_assert(evbase != NULL);
5405 
5406  if (!(conn = htp__connection_new_(NULL, -1, evhtp_type_client)))
5407  {
5408  return NULL;
5409  }
5410 
5411  conn->evbase = evbase;
5412  conn->bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
5413 
5414  if (conn->bev == NULL)
5415  {
5416  evhtp_connection_free(conn);
5417 
5418  return NULL;
5419  }
5420 
5421  bufferevent_enable(conn->bev, EV_READ);
5422  bufferevent_setcb(conn->bev, NULL, NULL,
5423  htp__connection_eventcb_, conn);
5424 
5425  if (dns_base != NULL)
5426  {
5427  err = bufferevent_socket_connect_hostname(conn->bev, dns_base,
5428  AF_UNSPEC, addr, port);
5429  } else {
5430  struct sockaddr_in sin4;
5431  struct sockaddr_in6 sin6;
5432  struct sockaddr * sin;
5433  int salen;
5434 
5435  if (inet_pton(AF_INET, addr, &sin4.sin_addr))
5436  {
5437  sin4.sin_family = AF_INET;
5438  sin4.sin_port = htons(port);
5439  sin = (struct sockaddr *)&sin4;
5440  salen = sizeof(sin4);
5441  } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr))
5442  {
5443  sin6.sin6_family = AF_INET6;
5444  sin6.sin6_port = htons(port);
5445  sin = (struct sockaddr *)&sin6;
5446  salen = sizeof(sin6);
5447  } else {
5448  /* Not a valid IP. */
5449  evhtp_connection_free(conn);
5450 
5451  return NULL;
5452  }
5453 
5454  err = bufferevent_socket_connect(conn->bev, sin, salen);
5455  }
5456 
5457  /* not needed since any of the bufferevent errors will go straight to
5458  * the eventcb
5459  */
5460  if (err)
5461  {
5462  return NULL;
5463  }
5464 
5465  return conn;
5466 } /* evhtp_connection_new_dns */
5467 
5468 #ifndef EVHTP_DISABLE_SSL
5469 
5470 #define ssl_sk_new_ bufferevent_openssl_socket_new
5471 #define ssl_sk_connect_ bufferevent_socket_connect
5472 
5473 evhtp_connection_t *
5474 evhtp_connection_ssl_new(struct event_base * evbase,
5475  const char * addr,
5476  uint16_t port,
5477  evhtp_ssl_ctx_t * ctx)
5478 {
5479  evhtp_connection_t * conn;
5480  struct sockaddr_in sin;
5481  const char * errstr;
5482 
5483  if (evbase == NULL)
5484  {
5485  return NULL;
5486  }
5487 
5488  if (!(conn = htp__connection_new_(NULL, -1, evhtp_type_client))) {
5489  return NULL;
5490  }
5491 
5492  conn->evbase = evbase;
5493  errstr = NULL;
5494 
5495  do {
5496  if ((conn->ssl = SSL_new(ctx)) == NULL) {
5497  errstr = "unable to allocate SSL context";
5498 
5499  break;
5500  }
5501 
5502  if ((conn->bev = ssl_sk_new_(evbase, -1, conn->ssl,
5503  BUFFEREVENT_SSL_CONNECTING,
5504  BEV_OPT_CLOSE_ON_FREE)) == NULL) {
5505  errstr = "unable to allocate bev context";
5506  break;
5507  }
5508 
5509  if (bufferevent_enable(conn->bev, EV_READ) == -1) {
5510  errstr = "unable to enable reading";
5511  break;
5512  }
5513 
5514 
5515  bufferevent_setcb(conn->bev, NULL, NULL,
5516  htp__connection_eventcb_, conn);
5517 
5518 
5519  sin.sin_family = AF_INET;
5520  sin.sin_addr.s_addr = inet_addr(addr);
5521  sin.sin_port = htons(port);
5522 
5523  if (ssl_sk_connect_(conn->bev,
5524  (struct sockaddr *)&sin,
5525  sizeof(sin)) == -1) {
5526  errstr = "sk_connect_ failure";
5527  break;
5528  }
5529  } while (0);
5530 
5531 
5532  if (errstr != NULL) {
5533  log_error("%s", errstr);
5534 
5536 
5537  return NULL;
5538  }
5539 
5540  return conn;
5541 } /* evhtp_connection_ssl_new */
5542 
5543 #endif
5544 
5545 
5546 evhtp_request_t *
5548 {
5549  evhtp_request_t * r;
5550 
5551  r = htp__request_new_(NULL);
5552  evhtp_alloc_assert(r);
5553 
5554  r->cb = cb;
5555  r->cbarg = arg;
5556  r->proto = EVHTP_PROTO_11;
5557 
5558  return r;
5559 }
5560 
5561 int
5562 evhtp_make_request(evhtp_connection_t * c, evhtp_request_t * r,
5563  htp_method meth, const char * uri)
5564 {
5565  struct evbuffer * obuf;
5566  char * proto;
5567 
5568  obuf = bufferevent_get_output(c->bev);
5569  r->conn = c;
5570  c->request = r;
5571 
5572  switch (r->proto) {
5573  case EVHTP_PROTO_10:
5574  proto = "1.0";
5575  break;
5576  case EVHTP_PROTO_11:
5577  default:
5578  proto = "1.1";
5579  break;
5580  }
5581 
5582  evbuffer_add_printf(obuf, "%s %s HTTP/%s\r\n",
5583  htparser_get_methodstr_m(meth), uri, proto);
5584 
5585  evhtp_headers_for_each(r->headers_out, htp__create_headers_, obuf);
5586  evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL);
5587 
5588  if (evbuffer_get_length(r->buffer_out))
5589  {
5590  evbuffer_add_buffer(obuf, r->buffer_out);
5591  }
5592 
5593  return 0;
5594 }
5595 
5596 unsigned int
5597 evhtp_request_status(evhtp_request_t * r)
5598 {
5599  return htparser_get_status(r->conn->parser);
5600 }
void evhtp_request_set_keepalive(evhtp_request_t *request, int val)
Definition: evhtp.c:5021
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:4277
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:4122
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:469
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:4381
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:4599
#define EVHTP_PARSE_QUERY_FLAG_DEFAULT
Definition: evhtp/evhtp.h:1125
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:5133
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:5236
#define evhtp_headers_find_header
Definition: evhtp/evhtp.h:1223
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:4999
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:5151
#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:418
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:1224
evhtp_hooks_t * evhtp_request_get_hooks(evhtp_request_t *r)
returns request hooks
Definition: evhtp.c:4461
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:4618
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:4637
#define EVHTP_PARSE_QUERY_FLAG_ALLOW_EMPTY_VALS
Definition: evhtp/evhtp.h:1115
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:1232
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:4967
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:5119
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:5036
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:481
unsigned char htparser_get_multipart(htparser *p)
Definition: parser.c:522
evhtp_hooks_t * evhtp_connection_get_hooks(evhtp_connection_t *c)
Definition: evhtp.c:4444
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:1117
int evhtp_ssl_init(evhtp_t *htp, evhtp_ssl_cfg_t *cfg)
Definition: evhtp.c:4772
#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:5030
struct bufferevent * evhtp_request_take_ownership(evhtp_request_t *request)
Definition: evhtp.c:5004
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:428
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:5211
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:5474
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:5009
#define EVHTP_PARSE_QUERY_FLAG_IGNORE_HEX
Definition: evhtp/evhtp.h:1114
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:504
void evhtp_request_free(evhtp_request_t *request)
Definition: evhtp.c:5113
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:454
#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:4478
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:5157
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:1116
unsigned int evhtp_request_status(evhtp_request_t *r)
Definition: evhtp.c:5597
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:4399
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:475
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:4045
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:4568
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:4244
#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:718
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:5547
#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:4717
void evhtp_callbacks_free(evhtp_callbacks_t *callbacks)
Definition: evhtp.c:4179
#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:4387
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:5145
int evhtp_request_unset_hook(evhtp_request_t *req, evhtp_hook_type type)
Definition: evhtp.c:4375
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:4724
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:35
void evhtp_request_set_bev(evhtp_request_t *request, struct bufferevent *bev)
sets the underlying bufferevent for a evhtp_request
Definition: evhtp.c:5015
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:5042
#define EVHTP_CONN_FLAG_ERROR
Definition: evhtp/evhtp.h:452
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:5397
#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:5326
#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:5139
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:564
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:510
#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:419
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:4484
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:4364
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:4606
#define EVHTP_REQ_FLAG_KEEPALIVE
Definition: evhtp/evhtp.h:416
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:4546
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:4285
int evhtp_add_alias(evhtp_t *evhtp, const char *name)
Add an alias hostname for a virtual-host specific evhtp_t.
Definition: evhtp.c:5186
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:4731
#define EVHTP_PARSE_QUERY_FLAG_STRICT
Definition: evhtp/evhtp.h:1113
#define EVHTP_CONN_FLAG_FREE_CONN
Definition: evhtp/evhtp.h:458
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:5067
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:5391
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:457
static void htp__connection_writecb_(struct bufferevent *bev, void *arg)
Definition: evhtp.c:2322
#define ssl_sk_new_
Definition: evhtp.c:5470
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:4972
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:5056
#define EVHTP_PARSE_QUERY_FLAG_IGNORE_FRAGMENTS
Definition: evhtp/evhtp.h:1118
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:534
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:4523
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:4199
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:528
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:4740
static int ssl_num_locks
Definition: evhtp.c:447
htpparse_error htparser_get_error(htparser *p)
Definition: parser.c:421
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:5284
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:453
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:456
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:5073
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:4557
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:4405
htparser * htparser_new(void)
Definition: parser.c:576
unsigned int htparser_get_status(htparser *p)
Definition: parser.c:440
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:546
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:516
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:4678
#define evhtp_query_free
Definition: evhtp/evhtp.h:1233
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:5471
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:5562
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:459
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:25
#define EVHTP_REQ_FLAG_FINISHED
Definition: evhtp/evhtp.h:417
int evhtp_callback_unset_hook(evhtp_callback_t *callback, evhtp_hook_type type)
Definition: evhtp.c:4369
#define EVHTP_CONN_FLAG_PAUSED
this connection has been marked as paused
Definition: evhtp/evhtp.h:455
#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:446
#define log_warn(M,...)
Definition: log.h:45
int evhtp_request_set_hook(evhtp_request_t *req, evhtp_hook_type type, evhtp_hook cb, void *arg)
Definition: evhtp.c:4393
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:5339
#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:498
#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:5162