Blame


1 fe3fcc3a 2026-06-03 kirill /* $OpenBSD: relay_http.c,v 1.100 2026/06/03 20:00:34 kirill Exp $ */
2 8bf959a5 2012-09-20 reyk
3 8bf959a5 2012-09-20 reyk /*
4 4a9b7b24 2016-07-29 reyk * Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
5 8bf959a5 2012-09-20 reyk *
6 8bf959a5 2012-09-20 reyk * Permission to use, copy, modify, and distribute this software for any
7 8bf959a5 2012-09-20 reyk * purpose with or without fee is hereby granted, provided that the above
8 8bf959a5 2012-09-20 reyk * copyright notice and this permission notice appear in all copies.
9 8bf959a5 2012-09-20 reyk *
10 8bf959a5 2012-09-20 reyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 8bf959a5 2012-09-20 reyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 8bf959a5 2012-09-20 reyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 8bf959a5 2012-09-20 reyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 8bf959a5 2012-09-20 reyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 8bf959a5 2012-09-20 reyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 8bf959a5 2012-09-20 reyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 8bf959a5 2012-09-20 reyk */
18 8bf959a5 2012-09-20 reyk
19 8bf959a5 2012-09-20 reyk #include <sys/types.h>
20 8bf959a5 2012-09-20 reyk #include <sys/queue.h>
21 8bf959a5 2012-09-20 reyk #include <sys/time.h>
22 8bf959a5 2012-09-20 reyk #include <sys/socket.h>
23 8bf959a5 2012-09-20 reyk #include <sys/tree.h>
24 8bf959a5 2012-09-20 reyk
25 8bf959a5 2012-09-20 reyk #include <netinet/in.h>
26 d93c36af 2015-01-22 reyk #include <arpa/inet.h>
27 8bf959a5 2012-09-20 reyk
28 d93c36af 2015-01-22 reyk #include <limits.h>
29 d93c36af 2015-01-22 reyk #include <stdio.h>
30 8bf959a5 2012-09-20 reyk #include <stdlib.h>
31 d93c36af 2015-01-22 reyk #include <errno.h>
32 8bf959a5 2012-09-20 reyk #include <string.h>
33 d93c36af 2015-01-22 reyk #include <time.h>
34 8bf959a5 2012-09-20 reyk #include <event.h>
35 8bf959a5 2012-09-20 reyk #include <fnmatch.h>
36 d93c36af 2015-01-22 reyk #include <siphash.h>
37 d93c36af 2015-01-22 reyk #include <imsg.h>
38 66088222 2015-04-29 bluhm #include <unistd.h>
39 8bf959a5 2012-09-20 reyk
40 8bf959a5 2012-09-20 reyk #include "relayd.h"
41 69fde657 2014-07-09 reyk #include "http.h"
42 6b5c4000 2026-03-02 rsadowski #include "log.h"
43 8bf959a5 2012-09-20 reyk
44 8bf959a5 2012-09-20 reyk static int _relay_lookup_url(struct ctl_relay_event *, char *, char *,
45 69fde657 2014-07-09 reyk char *, struct kv *);
46 8bf959a5 2012-09-20 reyk int relay_lookup_url(struct ctl_relay_event *,
47 69fde657 2014-07-09 reyk const char *, struct kv *);
48 69fde657 2014-07-09 reyk int relay_lookup_query(struct ctl_relay_event *, struct kv *);
49 69fde657 2014-07-09 reyk int relay_lookup_cookie(struct ctl_relay_event *, const char *,
50 69fde657 2014-07-09 reyk struct kv *);
51 8bf959a5 2012-09-20 reyk void relay_read_httpcontent(struct bufferevent *, void *);
52 8bf959a5 2012-09-20 reyk void relay_read_httpchunks(struct bufferevent *, void *);
53 8bf959a5 2012-09-20 reyk char *relay_expand_http(struct ctl_relay_event *, char *,
54 8bf959a5 2012-09-20 reyk char *, size_t);
55 2d9632ee 2014-07-11 reyk int relay_writeheader_kv(struct ctl_relay_event *, struct kv *);
56 69fde657 2014-07-09 reyk int relay_writeheader_http(struct ctl_relay_event *,
57 69fde657 2014-07-09 reyk struct ctl_relay_event *);
58 69fde657 2014-07-09 reyk int relay_writerequest_http(struct ctl_relay_event *,
59 69fde657 2014-07-09 reyk struct ctl_relay_event *);
60 69fde657 2014-07-09 reyk int relay_writeresponse_http(struct ctl_relay_event *,
61 69fde657 2014-07-09 reyk struct ctl_relay_event *);
62 69fde657 2014-07-09 reyk void relay_reset_http(struct ctl_relay_event *);
63 69fde657 2014-07-09 reyk static int relay_httpmethod_cmp(const void *, const void *);
64 fa847717 2014-07-12 reyk static int relay_httperror_cmp(const void *, const void *);
65 69fde657 2014-07-09 reyk int relay_httpquery_test(struct ctl_relay_event *,
66 69fde657 2014-07-09 reyk struct relay_rule *, struct kvlist *);
67 69fde657 2014-07-09 reyk int relay_httpheader_test(struct ctl_relay_event *,
68 69fde657 2014-07-09 reyk struct relay_rule *, struct kvlist *);
69 69fde657 2014-07-09 reyk int relay_httppath_test(struct ctl_relay_event *,
70 69fde657 2014-07-09 reyk struct relay_rule *, struct kvlist *);
71 69fde657 2014-07-09 reyk int relay_httpurl_test(struct ctl_relay_event *,
72 69fde657 2014-07-09 reyk struct relay_rule *, struct kvlist *);
73 69fde657 2014-07-09 reyk int relay_httpcookie_test(struct ctl_relay_event *,
74 69fde657 2014-07-09 reyk struct relay_rule *, struct kvlist *);
75 b8764354 2019-05-13 reyk int relay_apply_actions(struct ctl_relay_event *, struct kvlist *,
76 b8764354 2019-05-13 reyk struct relay_table *);
77 69fde657 2014-07-09 reyk int relay_match_actions(struct ctl_relay_event *,
78 b8764354 2019-05-13 reyk struct relay_rule *, struct kvlist *, struct kvlist *,
79 b8764354 2019-05-13 reyk struct relay_table **);
80 69fde657 2014-07-09 reyk void relay_httpdesc_free(struct http_descriptor *);
81 d498e80a 2021-01-09 denis char * server_root_strip(char *, int);
82 192c004f 2026-03-08 rsadowski int relay_http_parse_startline(struct ctl_relay_event *, char *,
83 192c004f 2026-03-08 rsadowski enum httpmethod *);
84 8bf959a5 2012-09-20 reyk
85 69fde657 2014-07-09 reyk static struct relayd *env = NULL;
86 69fde657 2014-07-09 reyk
87 69fde657 2014-07-09 reyk static struct http_method http_methods[] = HTTP_METHODS;
88 fa847717 2014-07-12 reyk static struct http_error http_errors[] = HTTP_ERRORS;
89 69fde657 2014-07-09 reyk
90 8bf959a5 2012-09-20 reyk void
91 69fde657 2014-07-09 reyk relay_http(struct relayd *x_env)
92 69fde657 2014-07-09 reyk {
93 69fde657 2014-07-09 reyk if (x_env != NULL)
94 69fde657 2014-07-09 reyk env = x_env;
95 69fde657 2014-07-09 reyk
96 69fde657 2014-07-09 reyk DPRINTF("%s: sorting lookup tables, pid %d", __func__, getpid());
97 69fde657 2014-07-09 reyk
98 69fde657 2014-07-09 reyk /* Sort the HTTP lookup arrays */
99 69fde657 2014-07-09 reyk qsort(http_methods, sizeof(http_methods) /
100 69fde657 2014-07-09 reyk sizeof(http_methods[0]) - 1,
101 69fde657 2014-07-09 reyk sizeof(http_methods[0]), relay_httpmethod_cmp);
102 fa847717 2014-07-12 reyk qsort(http_errors, sizeof(http_errors) /
103 fa847717 2014-07-12 reyk sizeof(http_errors[0]) - 1,
104 fa847717 2014-07-12 reyk sizeof(http_errors[0]), relay_httperror_cmp);
105 69fde657 2014-07-09 reyk }
106 69fde657 2014-07-09 reyk
107 69fde657 2014-07-09 reyk void
108 69fde657 2014-07-09 reyk relay_http_init(struct relay *rlay)
109 69fde657 2014-07-09 reyk {
110 69fde657 2014-07-09 reyk rlay->rl_proto->close = relay_close_http;
111 69fde657 2014-07-09 reyk
112 69fde657 2014-07-09 reyk relay_http(NULL);
113 69fde657 2014-07-09 reyk
114 69fde657 2014-07-09 reyk /* Calculate skip step for the filter rules (may take a while) */
115 69fde657 2014-07-09 reyk relay_calc_skip_steps(&rlay->rl_proto->rules);
116 69fde657 2014-07-09 reyk }
117 69fde657 2014-07-09 reyk
118 69fde657 2014-07-09 reyk int
119 94c8a65e 2021-03-24 benno relay_http_priv_init(struct rsession *con)
120 94c8a65e 2021-03-24 benno {
121 94c8a65e 2021-03-24 benno
122 94c8a65e 2021-03-24 benno struct http_session *hs;
123 94c8a65e 2021-03-24 benno
124 94c8a65e 2021-03-24 benno if ((hs = calloc(1, sizeof(*hs))) == NULL)
125 94c8a65e 2021-03-24 benno return (-1);
126 94c8a65e 2021-03-24 benno SIMPLEQ_INIT(&hs->hs_methods);
127 94c8a65e 2021-03-24 benno DPRINTF("%s: session %d http_session %p", __func__,
128 94c8a65e 2021-03-24 benno con->se_id, hs);
129 94c8a65e 2021-03-24 benno con->se_priv = hs;
130 94c8a65e 2021-03-24 benno return (relay_httpdesc_init(&con->se_in));
131 94c8a65e 2021-03-24 benno }
132 94c8a65e 2021-03-24 benno
133 94c8a65e 2021-03-24 benno int
134 69fde657 2014-07-09 reyk relay_httpdesc_init(struct ctl_relay_event *cre)
135 69fde657 2014-07-09 reyk {
136 69fde657 2014-07-09 reyk struct http_descriptor *desc;
137 69fde657 2014-07-09 reyk
138 69fde657 2014-07-09 reyk if ((desc = calloc(1, sizeof(*desc))) == NULL)
139 69fde657 2014-07-09 reyk return (-1);
140 2d9632ee 2014-07-11 reyk
141 2d9632ee 2014-07-11 reyk RB_INIT(&desc->http_headers);
142 69fde657 2014-07-09 reyk cre->desc = desc;
143 69fde657 2014-07-09 reyk
144 69fde657 2014-07-09 reyk return (0);
145 69fde657 2014-07-09 reyk }
146 69fde657 2014-07-09 reyk
147 69fde657 2014-07-09 reyk void
148 69fde657 2014-07-09 reyk relay_httpdesc_free(struct http_descriptor *desc)
149 69fde657 2014-07-09 reyk {
150 f4fc50a1 2017-11-27 claudio if (desc == NULL)
151 f4fc50a1 2017-11-27 claudio return;
152 f4fc50a1 2017-11-27 claudio
153 ba24b6a0 2015-12-07 mmcc free(desc->http_path);
154 ba24b6a0 2015-12-07 mmcc desc->http_path = NULL;
155 ba24b6a0 2015-12-07 mmcc free(desc->http_query);
156 ba24b6a0 2015-12-07 mmcc desc->http_query = NULL;
157 ba24b6a0 2015-12-07 mmcc free(desc->http_version);
158 ba24b6a0 2015-12-07 mmcc desc->http_version = NULL;
159 ba24b6a0 2015-12-07 mmcc free(desc->query_key);
160 ba24b6a0 2015-12-07 mmcc desc->query_key = NULL;
161 ba24b6a0 2015-12-07 mmcc free(desc->query_val);
162 ba24b6a0 2015-12-07 mmcc desc->query_val = NULL;
163 69fde657 2014-07-09 reyk kv_purge(&desc->http_headers);
164 c363b8d4 2015-05-18 bluhm desc->http_lastheader = NULL;
165 fe3fcc3a 2026-06-03 kirill desc->http_cl = NULL;
166 69fde657 2014-07-09 reyk }
167 69fde657 2014-07-09 reyk
168 d335681c 2023-11-28 millert static int
169 d335681c 2023-11-28 millert relay_http_header_name_valid(const char *name)
170 d335681c 2023-11-28 millert {
171 d335681c 2023-11-28 millert /*
172 d335681c 2023-11-28 millert * RFC 9110 specifies that only the following characters are
173 d335681c 2023-11-28 millert * permitted within HTTP header field names.
174 d335681c 2023-11-28 millert */
175 d335681c 2023-11-28 millert const char token_chars[] = "!#$%&'*+-.^_`|~0123456789"
176 d335681c 2023-11-28 millert "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
177 d335681c 2023-11-28 millert const size_t len = strspn(name, token_chars);
178 d335681c 2023-11-28 millert
179 d335681c 2023-11-28 millert return (name[len] == '\0');
180 d335681c 2023-11-28 millert }
181 d335681c 2023-11-28 millert
182 69fde657 2014-07-09 reyk void
183 8bf959a5 2012-09-20 reyk relay_read_http(struct bufferevent *bev, void *arg)
184 8bf959a5 2012-09-20 reyk {
185 6e65a975 2013-01-17 bluhm struct ctl_relay_event *cre = arg;
186 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
187 8bf959a5 2012-09-20 reyk struct rsession *con = cre->con;
188 6e65a975 2013-01-17 bluhm struct relay *rlay = con->se_relay;
189 8bf959a5 2012-09-20 reyk struct protocol *proto = rlay->rl_proto;
190 8bf959a5 2012-09-20 reyk struct evbuffer *src = EVBUFFER_INPUT(bev);
191 69fde657 2014-07-09 reyk char *line = NULL, *key, *value;
192 4e975be3 2016-07-27 reyk char *urlproto, *host, *path;
193 4e975be3 2016-07-27 reyk int action, unique, ret;
194 8bf959a5 2012-09-20 reyk const char *errstr;
195 dc0cba89 2014-07-11 reyk size_t size, linelen;
196 69fde657 2014-07-09 reyk struct kv *hdr = NULL;
197 62ee3f1b 2019-05-08 reyk struct kv *upgrade = NULL, *upgrade_ws = NULL;
198 7e7eb993 2021-10-23 benno struct kv *connection_close = NULL;
199 7e7eb993 2021-10-23 benno int ws_response = 0;
200 05a099a8 2026-05-16 kirill int headers_only = 0;
201 158279cc 2026-01-01 rsadowski enum httpmethod request_method = HTTP_METHOD_NONE;
202 8bf959a5 2012-09-20 reyk
203 b7f7a948 2013-03-10 reyk getmonotime(&con->se_tv_last);
204 e442b42f 2014-07-14 bluhm cre->timedout = 0;
205 b7f7a948 2013-03-10 reyk
206 8bf959a5 2012-09-20 reyk size = EVBUFFER_LENGTH(src);
207 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: size %lu, to read %lld",
208 69fde657 2014-07-09 reyk __func__, con->se_id, size, cre->toread);
209 f4fc50a1 2017-11-27 claudio if (size == 0) {
210 8bf959a5 2012-09-20 reyk if (cre->dir == RELAY_DIR_RESPONSE)
211 8bf959a5 2012-09-20 reyk return;
212 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_HEADER;
213 8bf959a5 2012-09-20 reyk goto done;
214 8bf959a5 2012-09-20 reyk }
215 8bf959a5 2012-09-20 reyk
216 0e047fe7 2023-11-29 millert for (;;) {
217 ce0360b4 2017-09-23 bluhm line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
218 0e047fe7 2023-11-29 millert if (line == NULL) {
219 0e047fe7 2023-11-29 millert /*
220 0e047fe7 2023-11-29 millert * We do not process the last header on premature
221 0e047fe7 2023-11-29 millert * EOF as it may not be complete.
222 0e047fe7 2023-11-29 millert */
223 ce0360b4 2017-09-23 bluhm break;
224 0e047fe7 2023-11-29 millert }
225 dc0cba89 2014-07-11 reyk
226 8bf959a5 2012-09-20 reyk /*
227 8bf959a5 2012-09-20 reyk * An empty line indicates the end of the request.
228 8bf959a5 2012-09-20 reyk * libevent already stripped the \r\n for us.
229 8bf959a5 2012-09-20 reyk */
230 ce0360b4 2017-09-23 bluhm if (linelen == 0) {
231 8bf959a5 2012-09-20 reyk cre->done = 1;
232 8bf959a5 2012-09-20 reyk free(line);
233 0e047fe7 2023-11-29 millert line = NULL;
234 0e047fe7 2023-11-29 millert if (cre->line > 1) {
235 0e047fe7 2023-11-29 millert /* Process last (complete) header line. */
236 0e047fe7 2023-11-29 millert goto last_header;
237 0e047fe7 2023-11-29 millert }
238 8bf959a5 2012-09-20 reyk break;
239 8bf959a5 2012-09-20 reyk }
240 8bf959a5 2012-09-20 reyk
241 dc0cba89 2014-07-11 reyk /* Limit the total header length minus \r\n */
242 dc0cba89 2014-07-11 reyk cre->headerlen += linelen;
243 b688796e 2017-11-15 benno if (cre->headerlen > proto->httpheaderlen) {
244 b688796e 2017-11-15 benno relay_abort_http(con, 413,
245 b688796e 2017-11-15 benno "request headers too large", 0);
246 d335681c 2023-11-28 millert goto abort;
247 dc0cba89 2014-07-11 reyk }
248 dc0cba89 2014-07-11 reyk
249 d335681c 2023-11-28 millert /* Reject requests with an embedded NUL byte. */
250 d335681c 2023-11-28 millert if (memchr(line, '\0', linelen) != NULL) {
251 d335681c 2023-11-28 millert relay_abort_http(con, 400, "malformed", 0);
252 d335681c 2023-11-28 millert goto abort;
253 d335681c 2023-11-28 millert }
254 192c004f 2026-03-08 rsadowski /* Process the HTTP start-line (request or response status) */
255 d335681c 2023-11-28 millert if (++cre->line == 1) {
256 192c004f 2026-03-08 rsadowski if (relay_http_parse_startline(cre, line,
257 192c004f 2026-03-08 rsadowski &request_method) == -1) {
258 192c004f 2026-03-08 rsadowski free(line);
259 192c004f 2026-03-08 rsadowski return;
260 d335681c 2023-11-28 millert }
261 0e047fe7 2023-11-29 millert free(line);
262 0e047fe7 2023-11-29 millert continue;
263 d335681c 2023-11-28 millert }
264 0e047fe7 2023-11-29 millert
265 b62a1edf 2026-06-03 rsadowski /*
266 b62a1edf 2026-06-03 rsadowski * RFC 9112 section 5.2 permits unconditional rejection.
267 b62a1edf 2026-06-03 rsadowski * Obs-fold creates parser differentials between intermediaries
268 b62a1edf 2026-06-03 rsadowski * and backends.
269 b62a1edf 2026-06-03 rsadowski */
270 0e047fe7 2023-11-29 millert if (*line == ' ' || *line == '\t') {
271 b62a1edf 2026-06-03 rsadowski if (cre->dir == RELAY_DIR_RESPONSE)
272 b62a1edf 2026-06-03 rsadowski relay_abort_http(con, 502, "Bad Gateway", 0);
273 b62a1edf 2026-06-03 rsadowski else
274 8bf959a5 2012-09-20 reyk relay_abort_http(con, 400, "malformed", 0);
275 b62a1edf 2026-06-03 rsadowski goto abort;
276 8bf959a5 2012-09-20 reyk }
277 d335681c 2023-11-28 millert
278 0e047fe7 2023-11-29 millert /* Process the last complete header line. */
279 0e047fe7 2023-11-29 millert last_header:
280 0e047fe7 2023-11-29 millert if (desc->http_lastheader != NULL) {
281 0e047fe7 2023-11-29 millert key = desc->http_lastheader->kv_key;
282 0e047fe7 2023-11-29 millert value = desc->http_lastheader->kv_value;
283 8bf959a5 2012-09-20 reyk
284 0e047fe7 2023-11-29 millert DPRINTF("%s: session %d: header '%s: %s'", __func__,
285 0e047fe7 2023-11-29 millert con->se_id, key, value);
286 8bf959a5 2012-09-20 reyk
287 0e047fe7 2023-11-29 millert if (desc->http_method != HTTP_METHOD_NONE &&
288 0e047fe7 2023-11-29 millert strcasecmp("Content-Length", key) == 0) {
289 3e59c1b6 2023-12-01 millert switch (desc->http_method) {
290 3e59c1b6 2023-12-01 millert case HTTP_METHOD_TRACE:
291 3e59c1b6 2023-12-01 millert case HTTP_METHOD_CONNECT:
292 3e59c1b6 2023-12-01 millert /*
293 3e59c1b6 2023-12-01 millert * These methods should not have a body
294 3e59c1b6 2023-12-01 millert * and thus no Content-Length header.
295 3e59c1b6 2023-12-01 millert */
296 0e047fe7 2023-11-29 millert relay_abort_http(con, 400, "malformed",
297 0e047fe7 2023-11-29 millert 0);
298 0e047fe7 2023-11-29 millert goto abort;
299 3e59c1b6 2023-12-01 millert case HTTP_METHOD_GET:
300 3e59c1b6 2023-12-01 millert case HTTP_METHOD_HEAD:
301 3e59c1b6 2023-12-01 millert case HTTP_METHOD_COPY:
302 3e59c1b6 2023-12-01 millert case HTTP_METHOD_MOVE:
303 0e047fe7 2023-11-29 millert /*
304 3e59c1b6 2023-12-01 millert * We strip the body (if present) from
305 3e59c1b6 2023-12-01 millert * the GET, HEAD, COPY and MOVE methods
306 3e59c1b6 2023-12-01 millert * so strip Content-Length too.
307 3e59c1b6 2023-12-01 millert */
308 3e59c1b6 2023-12-01 millert kv_delete(&desc->http_headers,
309 3e59c1b6 2023-12-01 millert desc->http_lastheader);
310 3e59c1b6 2023-12-01 millert break;
311 a4d9f842 2024-07-20 anton case HTTP_METHOD_RESPONSE:
312 a4d9f842 2024-07-20 anton if (request_method == HTTP_METHOD_HEAD)
313 a4d9f842 2024-07-20 anton break;
314 a4d9f842 2024-07-20 anton /* FALLTHROUGH */
315 3e59c1b6 2023-12-01 millert default:
316 3e59c1b6 2023-12-01 millert /*
317 0e047fe7 2023-11-29 millert * Need to read data from the client
318 0e047fe7 2023-11-29 millert * after the HTTP header.
319 0e047fe7 2023-11-29 millert * XXX What about non-standard clients
320 0e047fe7 2023-11-29 millert * not using the carriage return? And
321 0e047fe7 2023-11-29 millert * some browsers seem to include the
322 0e047fe7 2023-11-29 millert * line length in the content-length.
323 0e047fe7 2023-11-29 millert */
324 0e047fe7 2023-11-29 millert if (*value == '+' || *value == '-') {
325 0e047fe7 2023-11-29 millert errstr = "invalid";
326 0e047fe7 2023-11-29 millert } else {
327 0e047fe7 2023-11-29 millert cre->toread = strtonum(value, 0,
328 0e047fe7 2023-11-29 millert LLONG_MAX, &errstr);
329 0e047fe7 2023-11-29 millert }
330 0e047fe7 2023-11-29 millert if (errstr) {
331 0e047fe7 2023-11-29 millert relay_abort_http(con, 500,
332 0e047fe7 2023-11-29 millert errstr, 0);
333 0e047fe7 2023-11-29 millert goto abort;
334 0e047fe7 2023-11-29 millert }
335 fe3fcc3a 2026-06-03 kirill desc->http_cl = desc->http_lastheader;
336 fe3fcc3a 2026-06-03 kirill if (desc->http_cl->kv_parent != NULL)
337 fe3fcc3a 2026-06-03 kirill desc->http_cl =
338 fe3fcc3a 2026-06-03 kirill desc->http_cl->kv_parent;
339 3e59c1b6 2023-12-01 millert break;
340 0e047fe7 2023-11-29 millert }
341 0e047fe7 2023-11-29 millert /*
342 0e047fe7 2023-11-29 millert * Response with a status code of 1xx
343 0e047fe7 2023-11-29 millert * (Informational) or 204 (No Content) MUST
344 0e047fe7 2023-11-29 millert * not have a Content-Length (rfc 7230 3.3.3)
345 0e047fe7 2023-11-29 millert * Instead we check for value != 0 because there
346 0e047fe7 2023-11-29 millert * are servers that do not follow the rfc and
347 0e047fe7 2023-11-29 millert * send Content-Length: 0.
348 0e047fe7 2023-11-29 millert */
349 0e047fe7 2023-11-29 millert if (desc->http_method == HTTP_METHOD_RESPONSE &&
350 0e047fe7 2023-11-29 millert (((desc->http_status >= 100 &&
351 0e047fe7 2023-11-29 millert desc->http_status < 200) ||
352 0e047fe7 2023-11-29 millert desc->http_status == 204)) &&
353 0e047fe7 2023-11-29 millert cre->toread != 0) {
354 0e047fe7 2023-11-29 millert relay_abort_http(con, 502,
355 0e047fe7 2023-11-29 millert "Bad Gateway", 0);
356 94c8a65e 2021-03-24 benno goto abort;
357 94c8a65e 2021-03-24 benno }
358 8bf959a5 2012-09-20 reyk }
359 0e047fe7 2023-11-29 millert if (strcasecmp("Transfer-Encoding", key) == 0) {
360 0e047fe7 2023-11-29 millert /* We don't support other encodings. */
361 0e047fe7 2023-11-29 millert if (strcasecmp("chunked", value) != 0) {
362 4e975be3 2016-07-27 reyk relay_abort_http(con, 400,
363 0e047fe7 2023-11-29 millert "malformed", 0);
364 4e975be3 2016-07-27 reyk goto abort;
365 4e975be3 2016-07-27 reyk }
366 0e047fe7 2023-11-29 millert desc->http_chunked = 1;
367 4e975be3 2016-07-27 reyk }
368 4e975be3 2016-07-27 reyk
369 0e047fe7 2023-11-29 millert if (strcasecmp("Host", key) == 0) {
370 0e047fe7 2023-11-29 millert /*
371 0e047fe7 2023-11-29 millert * The path may contain a URL. The host in the
372 0e047fe7 2023-11-29 millert * URL has to match the Host: value.
373 0e047fe7 2023-11-29 millert */
374 0e047fe7 2023-11-29 millert if (parse_url(desc->http_path,
375 0e047fe7 2023-11-29 millert &urlproto, &host, &path) == 0) {
376 0e047fe7 2023-11-29 millert ret = strcasecmp(host, value);
377 0e047fe7 2023-11-29 millert free(urlproto);
378 0e047fe7 2023-11-29 millert free(host);
379 0e047fe7 2023-11-29 millert free(path);
380 0e047fe7 2023-11-29 millert if (ret != 0) {
381 0e047fe7 2023-11-29 millert relay_abort_http(con, 400,
382 0e047fe7 2023-11-29 millert "malformed host", 0);
383 0e047fe7 2023-11-29 millert goto abort;
384 0e047fe7 2023-11-29 millert }
385 0e047fe7 2023-11-29 millert }
386 8bf959a5 2012-09-20 reyk }
387 8bf959a5 2012-09-20 reyk }
388 8bf959a5 2012-09-20 reyk
389 0e047fe7 2023-11-29 millert if (cre->done)
390 0e047fe7 2023-11-29 millert break;
391 0e047fe7 2023-11-29 millert
392 0e047fe7 2023-11-29 millert /* Validate header field name and check for missing value. */
393 0e047fe7 2023-11-29 millert key = line;
394 0e047fe7 2023-11-29 millert if ((value = strchr(line, ':')) == NULL) {
395 0e047fe7 2023-11-29 millert relay_abort_http(con, 400, "malformed", 0);
396 0e047fe7 2023-11-29 millert goto abort;
397 0e047fe7 2023-11-29 millert }
398 0e047fe7 2023-11-29 millert *value++ = '\0';
399 0e047fe7 2023-11-29 millert value += strspn(value, " \t\r\n");
400 0e047fe7 2023-11-29 millert
401 0e047fe7 2023-11-29 millert if (!relay_http_header_name_valid(key)) {
402 0e047fe7 2023-11-29 millert relay_abort_http(con, 400, "malformed", 0);
403 0e047fe7 2023-11-29 millert goto abort;
404 0e047fe7 2023-11-29 millert }
405 0e047fe7 2023-11-29 millert
406 0e047fe7 2023-11-29 millert /* The "Host" header must only occur once. */
407 0e047fe7 2023-11-29 millert unique = strcasecmp("Host", key) == 0;
408 0e047fe7 2023-11-29 millert
409 0e047fe7 2023-11-29 millert if ((hdr = kv_add(&desc->http_headers, key,
410 0e047fe7 2023-11-29 millert value, unique)) == NULL) {
411 0e047fe7 2023-11-29 millert relay_abort_http(con, 400, "malformed header", 0);
412 0e047fe7 2023-11-29 millert goto abort;
413 0e047fe7 2023-11-29 millert }
414 0e047fe7 2023-11-29 millert desc->http_lastheader = hdr;
415 0e047fe7 2023-11-29 millert
416 69fde657 2014-07-09 reyk free(line);
417 69fde657 2014-07-09 reyk }
418 0e047fe7 2023-11-29 millert
419 69fde657 2014-07-09 reyk if (cre->done) {
420 69fde657 2014-07-09 reyk if (desc->http_method == HTTP_METHOD_NONE) {
421 8bf959a5 2012-09-20 reyk relay_abort_http(con, 406, "no method", 0);
422 8bf959a5 2012-09-20 reyk return;
423 69fde657 2014-07-09 reyk }
424 69fde657 2014-07-09 reyk
425 69fde657 2014-07-09 reyk action = relay_test(proto, cre);
426 265f5a08 2016-07-22 benno switch (action) {
427 265f5a08 2016-07-22 benno case RES_FAIL:
428 37ed6014 2018-08-06 benno relay_close(con, "filter rule failed", 1);
429 69fde657 2014-07-09 reyk return;
430 265f5a08 2016-07-22 benno case RES_BAD:
431 265f5a08 2016-07-22 benno relay_abort_http(con, 400, "Bad Request",
432 265f5a08 2016-07-22 benno con->se_label);
433 265f5a08 2016-07-22 benno return;
434 265f5a08 2016-07-22 benno case RES_INTERNAL:
435 265f5a08 2016-07-22 benno relay_abort_http(con, 500, "Internal Server Error",
436 265f5a08 2016-07-22 benno con->se_label);
437 265f5a08 2016-07-22 benno return;
438 265f5a08 2016-07-22 benno }
439 265f5a08 2016-07-22 benno if (action != RES_PASS) {
440 69fde657 2014-07-09 reyk relay_abort_http(con, 403, "Forbidden", con->se_label);
441 69fde657 2014-07-09 reyk return;
442 69fde657 2014-07-09 reyk }
443 69fde657 2014-07-09 reyk
444 62ee3f1b 2019-05-08 reyk /*
445 fe3fcc3a 2026-06-03 kirill * RFC 9112 section 6.1 requires an intermediary that
446 fe3fcc3a 2026-06-03 kirill * forwards a message with Transfer-Encoding to first
447 fe3fcc3a 2026-06-03 kirill * remove Content-Length. relayd keeps chunked framing,
448 fe3fcc3a 2026-06-03 kirill * so strip Content-Length before header emission.
449 fe3fcc3a 2026-06-03 kirill */
450 fe3fcc3a 2026-06-03 kirill if (desc->http_chunked && desc->http_cl != NULL) {
451 fe3fcc3a 2026-06-03 kirill kv_delete(&desc->http_headers, desc->http_cl);
452 fe3fcc3a 2026-06-03 kirill desc->http_cl = NULL;
453 fe3fcc3a 2026-06-03 kirill desc->http_lastheader = NULL;
454 fe3fcc3a 2026-06-03 kirill }
455 fe3fcc3a 2026-06-03 kirill
456 fe3fcc3a 2026-06-03 kirill /*
457 62ee3f1b 2019-05-08 reyk * HTTP 101 Switching Protocols
458 62ee3f1b 2019-05-08 reyk */
459 7e7eb993 2021-10-23 benno
460 62ee3f1b 2019-05-08 reyk upgrade = kv_find_value(&desc->http_headers,
461 62ee3f1b 2019-05-08 reyk "Connection", "upgrade", ",");
462 62ee3f1b 2019-05-08 reyk upgrade_ws = kv_find_value(&desc->http_headers,
463 62ee3f1b 2019-05-08 reyk "Upgrade", "websocket", ",");
464 7e7eb993 2021-10-23 benno ws_response = 0;
465 62ee3f1b 2019-05-08 reyk if (cre->dir == RELAY_DIR_REQUEST && upgrade_ws != NULL) {
466 62ee3f1b 2019-05-08 reyk if ((proto->httpflags & HTTPFLAG_WEBSOCKETS) == 0) {
467 c0f9bf60 2019-03-04 benno relay_abort_http(con, 403,
468 c0f9bf60 2019-03-04 benno "Websocket Forbidden", 0);
469 c0f9bf60 2019-03-04 benno return;
470 62ee3f1b 2019-05-08 reyk } else if (upgrade == NULL) {
471 c0f9bf60 2019-03-04 benno relay_abort_http(con, 400,
472 c0f9bf60 2019-03-04 benno "Bad Websocket Request", 0);
473 c0f9bf60 2019-03-04 benno return;
474 62ee3f1b 2019-05-08 reyk } else if (desc->http_method != HTTP_METHOD_GET) {
475 c0f9bf60 2019-03-04 benno relay_abort_http(con, 405,
476 c0f9bf60 2019-03-04 benno "Websocket Method Not Allowed", 0);
477 c0f9bf60 2019-03-04 benno return;
478 c0f9bf60 2019-03-04 benno }
479 c0f9bf60 2019-03-04 benno } else if (cre->dir == RELAY_DIR_RESPONSE &&
480 c0f9bf60 2019-03-04 benno desc->http_status == 101) {
481 62ee3f1b 2019-05-08 reyk if (upgrade_ws != NULL && upgrade != NULL &&
482 62ee3f1b 2019-05-08 reyk (proto->httpflags & HTTPFLAG_WEBSOCKETS)) {
483 7e7eb993 2021-10-23 benno ws_response = 1;
484 c0f9bf60 2019-03-04 benno cre->dst->toread = TOREAD_UNLIMITED;
485 c0f9bf60 2019-03-04 benno cre->dst->bev->readcb = relay_read;
486 62ee3f1b 2019-05-08 reyk } else {
487 c0f9bf60 2019-03-04 benno relay_abort_http(con, 502,
488 c0f9bf60 2019-03-04 benno "Bad Websocket Gateway", 0);
489 c0f9bf60 2019-03-04 benno return;
490 c0f9bf60 2019-03-04 benno }
491 c0f9bf60 2019-03-04 benno }
492 c0f9bf60 2019-03-04 benno
493 7e7eb993 2021-10-23 benno connection_close = kv_find_value(&desc->http_headers,
494 7e7eb993 2021-10-23 benno "Connection", "close", ",");
495 05a099a8 2026-05-16 kirill /*
496 05a099a8 2026-05-16 kirill * RFC 9112 section 6.3: these responses end at the empty
497 05a099a8 2026-05-16 kirill * line after the header section. 101 upgrades become streams.
498 05a099a8 2026-05-16 kirill */
499 05a099a8 2026-05-16 kirill headers_only = cre->dir == RELAY_DIR_RESPONSE && !ws_response &&
500 05a099a8 2026-05-16 kirill (request_method == HTTP_METHOD_HEAD ||
501 05a099a8 2026-05-16 kirill (desc->http_status >= 100 && desc->http_status < 200) ||
502 05a099a8 2026-05-16 kirill desc->http_status == 204 || desc->http_status == 304);
503 05a099a8 2026-05-16 kirill if (headers_only)
504 05a099a8 2026-05-16 kirill cre->toread = 0;
505 7e7eb993 2021-10-23 benno
506 69fde657 2014-07-09 reyk switch (desc->http_method) {
507 8bf959a5 2012-09-20 reyk case HTTP_METHOD_CONNECT:
508 8bf959a5 2012-09-20 reyk /* Data stream */
509 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_UNLIMITED;
510 8bf959a5 2012-09-20 reyk bev->readcb = relay_read;
511 8bf959a5 2012-09-20 reyk break;
512 8bf959a5 2012-09-20 reyk case HTTP_METHOD_GET:
513 8bf959a5 2012-09-20 reyk case HTTP_METHOD_HEAD:
514 7088e981 2016-07-29 reyk /* WebDAV methods */
515 7088e981 2016-07-29 reyk case HTTP_METHOD_COPY:
516 7088e981 2016-07-29 reyk case HTTP_METHOD_MOVE:
517 d3d69475 2016-07-27 reyk cre->toread = 0;
518 d3d69475 2016-07-27 reyk break;
519 633bc164 2017-03-10 reyk case HTTP_METHOD_DELETE:
520 8bf959a5 2012-09-20 reyk case HTTP_METHOD_OPTIONS:
521 8bf959a5 2012-09-20 reyk case HTTP_METHOD_POST:
522 8bf959a5 2012-09-20 reyk case HTTP_METHOD_PUT:
523 8bf959a5 2012-09-20 reyk case HTTP_METHOD_RESPONSE:
524 7088e981 2016-07-29 reyk /* WebDAV methods */
525 7088e981 2016-07-29 reyk case HTTP_METHOD_PROPFIND:
526 7088e981 2016-07-29 reyk case HTTP_METHOD_PROPPATCH:
527 7088e981 2016-07-29 reyk case HTTP_METHOD_MKCOL:
528 7088e981 2016-07-29 reyk case HTTP_METHOD_LOCK:
529 7088e981 2016-07-29 reyk case HTTP_METHOD_UNLOCK:
530 7088e981 2016-07-29 reyk case HTTP_METHOD_VERSION_CONTROL:
531 7088e981 2016-07-29 reyk case HTTP_METHOD_REPORT:
532 7088e981 2016-07-29 reyk case HTTP_METHOD_CHECKOUT:
533 7088e981 2016-07-29 reyk case HTTP_METHOD_CHECKIN:
534 7088e981 2016-07-29 reyk case HTTP_METHOD_UNCHECKOUT:
535 7088e981 2016-07-29 reyk case HTTP_METHOD_MKWORKSPACE:
536 7088e981 2016-07-29 reyk case HTTP_METHOD_UPDATE:
537 7088e981 2016-07-29 reyk case HTTP_METHOD_LABEL:
538 7088e981 2016-07-29 reyk case HTTP_METHOD_MERGE:
539 7088e981 2016-07-29 reyk case HTTP_METHOD_BASELINE_CONTROL:
540 7088e981 2016-07-29 reyk case HTTP_METHOD_MKACTIVITY:
541 7088e981 2016-07-29 reyk case HTTP_METHOD_ORDERPATCH:
542 7088e981 2016-07-29 reyk case HTTP_METHOD_ACL:
543 7088e981 2016-07-29 reyk case HTTP_METHOD_MKREDIRECTREF:
544 7088e981 2016-07-29 reyk case HTTP_METHOD_UPDATEREDIRECTREF:
545 7088e981 2016-07-29 reyk case HTTP_METHOD_SEARCH:
546 ee259709 2026-05-19 rsadowski case HTTP_METHOD_MKCALENDAR:
547 7088e981 2016-07-29 reyk case HTTP_METHOD_PATCH:
548 8bf959a5 2012-09-20 reyk /* HTTP request payload */
549 94c8a65e 2021-03-24 benno if (cre->toread > 0) {
550 8bf959a5 2012-09-20 reyk bev->readcb = relay_read_httpcontent;
551 94c8a65e 2021-03-24 benno }
552 8bf959a5 2012-09-20 reyk
553 95b5700d 2013-09-04 bluhm /* Single-pass HTTP body */
554 95b5700d 2013-09-04 bluhm if (cre->toread < 0) {
555 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_UNLIMITED;
556 268a5dac 2013-02-05 bluhm bev->readcb = relay_read;
557 268a5dac 2013-02-05 bluhm }
558 8bf959a5 2012-09-20 reyk break;
559 8bf959a5 2012-09-20 reyk default:
560 8bf959a5 2012-09-20 reyk /* HTTP handler */
561 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_HEADER;
562 8bf959a5 2012-09-20 reyk bev->readcb = relay_read_http;
563 8bf959a5 2012-09-20 reyk break;
564 8bf959a5 2012-09-20 reyk }
565 05a099a8 2026-05-16 kirill if (desc->http_chunked && !headers_only) {
566 8bf959a5 2012-09-20 reyk /* Chunked transfer encoding */
567 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_CHUNK_LENGTH;
568 8bf959a5 2012-09-20 reyk bev->readcb = relay_read_httpchunks;
569 8bf959a5 2012-09-20 reyk }
570 8bf959a5 2012-09-20 reyk
571 41f2ab1c 2019-05-13 reyk /*
572 41f2ab1c 2019-05-13 reyk * Ask the server to close the connection after this request
573 7e7eb993 2021-10-23 benno * since we don't read any further request headers. Only add
574 7e7eb993 2021-10-23 benno * this header if it does not already exist or if this is a
575 7e7eb993 2021-10-23 benno * outbound websocket upgrade response.
576 41f2ab1c 2019-05-13 reyk */
577 7e7eb993 2021-10-23 benno if (cre->toread == TOREAD_UNLIMITED &&
578 7e7eb993 2021-10-23 benno connection_close == NULL && !ws_response)
579 41f2ab1c 2019-05-13 reyk if (kv_add(&desc->http_headers, "Connection",
580 41f2ab1c 2019-05-13 reyk "close", 0) == NULL)
581 41f2ab1c 2019-05-13 reyk goto fail;
582 41f2ab1c 2019-05-13 reyk
583 69fde657 2014-07-09 reyk if (cre->dir == RELAY_DIR_REQUEST) {
584 69fde657 2014-07-09 reyk if (relay_writerequest_http(cre->dst, cre) == -1)
585 69fde657 2014-07-09 reyk goto fail;
586 69fde657 2014-07-09 reyk } else {
587 69fde657 2014-07-09 reyk if (relay_writeresponse_http(cre->dst, cre) == -1)
588 69fde657 2014-07-09 reyk goto fail;
589 69fde657 2014-07-09 reyk }
590 69fde657 2014-07-09 reyk if (relay_bufferevent_print(cre->dst, "\r\n") == -1 ||
591 69fde657 2014-07-09 reyk relay_writeheader_http(cre->dst, cre) == -1 ||
592 69fde657 2014-07-09 reyk relay_bufferevent_print(cre->dst, "\r\n") == -1)
593 8bf959a5 2012-09-20 reyk goto fail;
594 8bf959a5 2012-09-20 reyk
595 69fde657 2014-07-09 reyk relay_reset_http(cre);
596 8bf959a5 2012-09-20 reyk done:
597 1465da0c 2013-02-15 bluhm if (cre->dir == RELAY_DIR_REQUEST && cre->toread <= 0 &&
598 6b2aabbf 2015-06-12 reyk cre->dst->state != STATE_CONNECTED) {
599 8bf959a5 2012-09-20 reyk if (rlay->rl_conf.fwdmode == FWD_TRANS) {
600 8bf959a5 2012-09-20 reyk relay_bindanyreq(con, 0, IPPROTO_TCP);
601 8bf959a5 2012-09-20 reyk return;
602 8bf959a5 2012-09-20 reyk }
603 03068b08 2014-08-10 bluhm if (relay_connect(con) == -1) {
604 8bf959a5 2012-09-20 reyk relay_abort_http(con, 502, "session failed", 0);
605 03068b08 2014-08-10 bluhm return;
606 03068b08 2014-08-10 bluhm }
607 8bf959a5 2012-09-20 reyk }
608 8bf959a5 2012-09-20 reyk }
609 8bf959a5 2012-09-20 reyk if (con->se_done) {
610 37ed6014 2018-08-06 benno relay_close(con, "last http read (done)", 0);
611 8bf959a5 2012-09-20 reyk return;
612 8bf959a5 2012-09-20 reyk }
613 114ae72f 2015-05-18 bluhm switch (relay_splice(cre)) {
614 114ae72f 2015-05-18 bluhm case -1:
615 37ed6014 2018-08-06 benno relay_close(con, strerror(errno), 1);
616 114ae72f 2015-05-18 bluhm case 1:
617 114ae72f 2015-05-18 bluhm return;
618 114ae72f 2015-05-18 bluhm case 0:
619 114ae72f 2015-05-18 bluhm break;
620 114ae72f 2015-05-18 bluhm }
621 114ae72f 2015-05-18 bluhm bufferevent_enable(bev, EV_READ);
622 114ae72f 2015-05-18 bluhm if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_http)
623 114ae72f 2015-05-18 bluhm bev->readcb(bev, arg);
624 114ae72f 2015-05-18 bluhm /* The callback readcb() might have freed the session. */
625 8bf959a5 2012-09-20 reyk return;
626 8bf959a5 2012-09-20 reyk fail:
627 8bf959a5 2012-09-20 reyk relay_abort_http(con, 500, strerror(errno), 0);
628 8bf959a5 2012-09-20 reyk return;
629 8bf959a5 2012-09-20 reyk abort:
630 8bf959a5 2012-09-20 reyk free(line);
631 8bf959a5 2012-09-20 reyk }
632 8bf959a5 2012-09-20 reyk
633 8bf959a5 2012-09-20 reyk void
634 8bf959a5 2012-09-20 reyk relay_read_httpcontent(struct bufferevent *bev, void *arg)
635 8bf959a5 2012-09-20 reyk {
636 6e65a975 2013-01-17 bluhm struct ctl_relay_event *cre = arg;
637 8bf959a5 2012-09-20 reyk struct rsession *con = cre->con;
638 01c76597 2015-07-18 benno struct protocol *proto = con->se_relay->rl_proto;
639 01c76597 2015-07-18 benno
640 8bf959a5 2012-09-20 reyk struct evbuffer *src = EVBUFFER_INPUT(bev);
641 8bf959a5 2012-09-20 reyk size_t size;
642 8bf959a5 2012-09-20 reyk
643 b7f7a948 2013-03-10 reyk getmonotime(&con->se_tv_last);
644 e442b42f 2014-07-14 bluhm cre->timedout = 0;
645 b7f7a948 2013-03-10 reyk
646 8bf959a5 2012-09-20 reyk size = EVBUFFER_LENGTH(src);
647 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
648 69fde657 2014-07-09 reyk con->se_id, size, cre->toread);
649 8bf959a5 2012-09-20 reyk if (!size)
650 8bf959a5 2012-09-20 reyk return;
651 b1e5969d 2013-03-09 bluhm if (relay_spliceadjust(cre) == -1)
652 b1e5969d 2013-03-09 bluhm goto fail;
653 268a5dac 2013-02-05 bluhm
654 268a5dac 2013-02-05 bluhm if (cre->toread > 0) {
655 268a5dac 2013-02-05 bluhm /* Read content data */
656 268a5dac 2013-02-05 bluhm if ((off_t)size > cre->toread) {
657 268a5dac 2013-02-05 bluhm size = cre->toread;
658 268a5dac 2013-02-05 bluhm if (relay_bufferevent_write_chunk(cre->dst, src, size)
659 268a5dac 2013-02-05 bluhm == -1)
660 268a5dac 2013-02-05 bluhm goto fail;
661 268a5dac 2013-02-05 bluhm cre->toread = 0;
662 268a5dac 2013-02-05 bluhm } else {
663 268a5dac 2013-02-05 bluhm if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
664 268a5dac 2013-02-05 bluhm goto fail;
665 268a5dac 2013-02-05 bluhm cre->toread -= size;
666 268a5dac 2013-02-05 bluhm }
667 268a5dac 2013-02-05 bluhm DPRINTF("%s: done, size %lu, to read %lld", __func__,
668 268a5dac 2013-02-05 bluhm size, cre->toread);
669 268a5dac 2013-02-05 bluhm }
670 268a5dac 2013-02-05 bluhm if (cre->toread == 0) {
671 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_HEADER;
672 8bf959a5 2012-09-20 reyk bev->readcb = relay_read_http;
673 268a5dac 2013-02-05 bluhm }
674 8bf959a5 2012-09-20 reyk if (con->se_done)
675 8bf959a5 2012-09-20 reyk goto done;
676 114ae72f 2015-05-18 bluhm bufferevent_enable(bev, EV_READ);
677 01c76597 2015-07-18 benno
678 01c76597 2015-07-18 benno if (cre->dst->bev && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(cre->dst->bev)) >
679 01c76597 2015-07-18 benno (size_t)RELAY_MAX_PREFETCH * proto->tcpbufsiz)
680 01c76597 2015-07-18 benno bufferevent_disable(cre->bev, EV_READ);
681 01c76597 2015-07-18 benno
682 8bf959a5 2012-09-20 reyk if (bev->readcb != relay_read_httpcontent)
683 8bf959a5 2012-09-20 reyk bev->readcb(bev, arg);
684 114ae72f 2015-05-18 bluhm /* The callback readcb() might have freed the session. */
685 8bf959a5 2012-09-20 reyk return;
686 8bf959a5 2012-09-20 reyk done:
687 37ed6014 2018-08-06 benno relay_close(con, "last http content read", 0);
688 8bf959a5 2012-09-20 reyk return;
689 8bf959a5 2012-09-20 reyk fail:
690 37ed6014 2018-08-06 benno relay_close(con, strerror(errno), 1);
691 8bf959a5 2012-09-20 reyk }
692 8bf959a5 2012-09-20 reyk
693 8bf959a5 2012-09-20 reyk void
694 8bf959a5 2012-09-20 reyk relay_read_httpchunks(struct bufferevent *bev, void *arg)
695 8bf959a5 2012-09-20 reyk {
696 6e65a975 2013-01-17 bluhm struct ctl_relay_event *cre = arg;
697 8bf959a5 2012-09-20 reyk struct rsession *con = cre->con;
698 01c76597 2015-07-18 benno struct protocol *proto = con->se_relay->rl_proto;
699 8bf959a5 2012-09-20 reyk struct evbuffer *src = EVBUFFER_INPUT(bev);
700 d335681c 2023-11-28 millert char *line, *ep;
701 ab334966 2013-05-07 reyk long long llval;
702 ce0360b4 2017-09-23 bluhm size_t size, linelen;
703 8bf959a5 2012-09-20 reyk
704 b7f7a948 2013-03-10 reyk getmonotime(&con->se_tv_last);
705 e442b42f 2014-07-14 bluhm cre->timedout = 0;
706 b7f7a948 2013-03-10 reyk
707 8bf959a5 2012-09-20 reyk size = EVBUFFER_LENGTH(src);
708 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
709 69fde657 2014-07-09 reyk con->se_id, size, cre->toread);
710 8bf959a5 2012-09-20 reyk if (!size)
711 8bf959a5 2012-09-20 reyk return;
712 b1e5969d 2013-03-09 bluhm if (relay_spliceadjust(cre) == -1)
713 b1e5969d 2013-03-09 bluhm goto fail;
714 8bf959a5 2012-09-20 reyk
715 268a5dac 2013-02-05 bluhm if (cre->toread > 0) {
716 268a5dac 2013-02-05 bluhm /* Read chunk data */
717 268a5dac 2013-02-05 bluhm if ((off_t)size > cre->toread) {
718 268a5dac 2013-02-05 bluhm size = cre->toread;
719 268a5dac 2013-02-05 bluhm if (relay_bufferevent_write_chunk(cre->dst, src, size)
720 268a5dac 2013-02-05 bluhm == -1)
721 268a5dac 2013-02-05 bluhm goto fail;
722 268a5dac 2013-02-05 bluhm cre->toread = 0;
723 268a5dac 2013-02-05 bluhm } else {
724 268a5dac 2013-02-05 bluhm if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
725 268a5dac 2013-02-05 bluhm goto fail;
726 268a5dac 2013-02-05 bluhm cre->toread -= size;
727 268a5dac 2013-02-05 bluhm }
728 268a5dac 2013-02-05 bluhm DPRINTF("%s: done, size %lu, to read %lld", __func__,
729 268a5dac 2013-02-05 bluhm size, cre->toread);
730 268a5dac 2013-02-05 bluhm }
731 268a5dac 2013-02-05 bluhm switch (cre->toread) {
732 268a5dac 2013-02-05 bluhm case TOREAD_HTTP_CHUNK_LENGTH:
733 ce0360b4 2017-09-23 bluhm line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
734 8bf959a5 2012-09-20 reyk if (line == NULL) {
735 8bf959a5 2012-09-20 reyk /* Ignore empty line, continue */
736 8bf959a5 2012-09-20 reyk bufferevent_enable(bev, EV_READ);
737 8bf959a5 2012-09-20 reyk return;
738 8bf959a5 2012-09-20 reyk }
739 ce0360b4 2017-09-23 bluhm if (linelen == 0) {
740 8bf959a5 2012-09-20 reyk free(line);
741 8bf959a5 2012-09-20 reyk goto next;
742 8bf959a5 2012-09-20 reyk }
743 8bf959a5 2012-09-20 reyk
744 ab334966 2013-05-07 reyk /*
745 d335681c 2023-11-28 millert * Read prepended chunk size in hex without leading +0[Xx].
746 ab334966 2013-05-07 reyk * The returned signed value must not be negative.
747 ab334966 2013-05-07 reyk */
748 d335681c 2023-11-28 millert if (line[0] == '+' || line[0] == '-' ||
749 d335681c 2023-11-28 millert (line[0] == '0' && (line[1] == 'x' || line[1] == 'X'))) {
750 d335681c 2023-11-28 millert /* Reject values like 0xdead and 0XBEEF or +FEED. */
751 d335681c 2023-11-28 millert ep = line;
752 d335681c 2023-11-28 millert } else {
753 d335681c 2023-11-28 millert errno = 0;
754 d335681c 2023-11-28 millert llval = strtoll(line, &ep, 16);
755 d335681c 2023-11-28 millert }
756 d335681c 2023-11-28 millert if (ep == line || *ep != '\0' || llval < 0 ||
757 d335681c 2023-11-28 millert (errno == ERANGE && llval == LLONG_MAX)) {
758 8bf959a5 2012-09-20 reyk free(line);
759 37ed6014 2018-08-06 benno relay_close(con, "invalid chunk size", 1);
760 8bf959a5 2012-09-20 reyk return;
761 8bf959a5 2012-09-20 reyk }
762 8bf959a5 2012-09-20 reyk
763 8bf959a5 2012-09-20 reyk if (relay_bufferevent_print(cre->dst, line) == -1 ||
764 8bf959a5 2012-09-20 reyk relay_bufferevent_print(cre->dst, "\r\n") == -1) {
765 8bf959a5 2012-09-20 reyk free(line);
766 8bf959a5 2012-09-20 reyk goto fail;
767 8bf959a5 2012-09-20 reyk }
768 8bf959a5 2012-09-20 reyk free(line);
769 8bf959a5 2012-09-20 reyk
770 ab334966 2013-05-07 reyk if ((cre->toread = llval) == 0) {
771 8bf959a5 2012-09-20 reyk DPRINTF("%s: last chunk", __func__);
772 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_CHUNK_TRAILER;
773 268a5dac 2013-02-05 bluhm }
774 268a5dac 2013-02-05 bluhm break;
775 268a5dac 2013-02-05 bluhm case TOREAD_HTTP_CHUNK_TRAILER:
776 268a5dac 2013-02-05 bluhm /* Last chunk is 0 bytes followed by trailer and empty line */
777 ce0360b4 2017-09-23 bluhm line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
778 268a5dac 2013-02-05 bluhm if (line == NULL) {
779 268a5dac 2013-02-05 bluhm /* Ignore empty line, continue */
780 268a5dac 2013-02-05 bluhm bufferevent_enable(bev, EV_READ);
781 268a5dac 2013-02-05 bluhm return;
782 268a5dac 2013-02-05 bluhm }
783 268a5dac 2013-02-05 bluhm if (relay_bufferevent_print(cre->dst, line) == -1 ||
784 268a5dac 2013-02-05 bluhm relay_bufferevent_print(cre->dst, "\r\n") == -1) {
785 8bf959a5 2012-09-20 reyk free(line);
786 268a5dac 2013-02-05 bluhm goto fail;
787 268a5dac 2013-02-05 bluhm }
788 ce0360b4 2017-09-23 bluhm if (linelen == 0) {
789 8bf959a5 2012-09-20 reyk /* Switch to HTTP header mode */
790 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_HEADER;
791 8bf959a5 2012-09-20 reyk bev->readcb = relay_read_http;
792 8bf959a5 2012-09-20 reyk }
793 268a5dac 2013-02-05 bluhm free(line);
794 268a5dac 2013-02-05 bluhm break;
795 268a5dac 2013-02-05 bluhm case 0:
796 268a5dac 2013-02-05 bluhm /* Chunk is terminated by an empty newline */
797 ce0360b4 2017-09-23 bluhm line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
798 ba24b6a0 2015-12-07 mmcc free(line);
799 268a5dac 2013-02-05 bluhm if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
800 8bf959a5 2012-09-20 reyk goto fail;
801 268a5dac 2013-02-05 bluhm cre->toread = TOREAD_HTTP_CHUNK_LENGTH;
802 268a5dac 2013-02-05 bluhm break;
803 8bf959a5 2012-09-20 reyk }
804 8bf959a5 2012-09-20 reyk
805 8bf959a5 2012-09-20 reyk next:
806 8bf959a5 2012-09-20 reyk if (con->se_done)
807 8bf959a5 2012-09-20 reyk goto done;
808 114ae72f 2015-05-18 bluhm bufferevent_enable(bev, EV_READ);
809 01c76597 2015-07-18 benno
810 01c76597 2015-07-18 benno if (cre->dst->bev && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(cre->dst->bev)) >
811 01c76597 2015-07-18 benno (size_t)RELAY_MAX_PREFETCH * proto->tcpbufsiz)
812 01c76597 2015-07-18 benno bufferevent_disable(cre->bev, EV_READ);
813 01c76597 2015-07-18 benno
814 8bf959a5 2012-09-20 reyk if (EVBUFFER_LENGTH(src))
815 8bf959a5 2012-09-20 reyk bev->readcb(bev, arg);
816 114ae72f 2015-05-18 bluhm /* The callback readcb() might have freed the session. */
817 8bf959a5 2012-09-20 reyk return;
818 8bf959a5 2012-09-20 reyk
819 8bf959a5 2012-09-20 reyk done:
820 37ed6014 2018-08-06 benno relay_close(con, "last http chunk read (done)", 0);
821 8bf959a5 2012-09-20 reyk return;
822 8bf959a5 2012-09-20 reyk fail:
823 37ed6014 2018-08-06 benno relay_close(con, strerror(errno), 1);
824 8bf959a5 2012-09-20 reyk }
825 8bf959a5 2012-09-20 reyk
826 8bf959a5 2012-09-20 reyk void
827 69fde657 2014-07-09 reyk relay_reset_http(struct ctl_relay_event *cre)
828 8bf959a5 2012-09-20 reyk {
829 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
830 8bf959a5 2012-09-20 reyk
831 69fde657 2014-07-09 reyk relay_httpdesc_free(desc);
832 69fde657 2014-07-09 reyk desc->http_method = 0;
833 69fde657 2014-07-09 reyk desc->http_chunked = 0;
834 fe3fcc3a 2026-06-03 kirill desc->http_cl = NULL;
835 dc0cba89 2014-07-11 reyk cre->headerlen = 0;
836 8bf959a5 2012-09-20 reyk cre->line = 0;
837 8bf959a5 2012-09-20 reyk cre->done = 0;
838 8bf959a5 2012-09-20 reyk }
839 8bf959a5 2012-09-20 reyk
840 8bf959a5 2012-09-20 reyk static int
841 8bf959a5 2012-09-20 reyk _relay_lookup_url(struct ctl_relay_event *cre, char *host, char *path,
842 69fde657 2014-07-09 reyk char *query, struct kv *kv)
843 8bf959a5 2012-09-20 reyk {
844 8bf959a5 2012-09-20 reyk struct rsession *con = cre->con;
845 8bf959a5 2012-09-20 reyk char *val, *md = NULL;
846 69fde657 2014-07-09 reyk int ret = RES_FAIL;
847 69fde657 2014-07-09 reyk const char *str = NULL;
848 8bf959a5 2012-09-20 reyk
849 8bf959a5 2012-09-20 reyk if (asprintf(&val, "%s%s%s%s",
850 8bf959a5 2012-09-20 reyk host, path,
851 8bf959a5 2012-09-20 reyk query == NULL ? "" : "?",
852 8bf959a5 2012-09-20 reyk query == NULL ? "" : query) == -1) {
853 8bf959a5 2012-09-20 reyk relay_abort_http(con, 500, "failed to allocate URL", 0);
854 69fde657 2014-07-09 reyk return (RES_FAIL);
855 8bf959a5 2012-09-20 reyk }
856 8bf959a5 2012-09-20 reyk
857 69fde657 2014-07-09 reyk switch (kv->kv_digest) {
858 8bf959a5 2012-09-20 reyk case DIGEST_SHA1:
859 8bf959a5 2012-09-20 reyk case DIGEST_MD5:
860 69fde657 2014-07-09 reyk if ((md = digeststr(kv->kv_digest,
861 69fde657 2014-07-09 reyk val, strlen(val), NULL)) == NULL) {
862 8bf959a5 2012-09-20 reyk relay_abort_http(con, 500,
863 8bf959a5 2012-09-20 reyk "failed to allocate digest", 0);
864 8bf959a5 2012-09-20 reyk goto fail;
865 8bf959a5 2012-09-20 reyk }
866 69fde657 2014-07-09 reyk str = md;
867 8bf959a5 2012-09-20 reyk break;
868 8bf959a5 2012-09-20 reyk case DIGEST_NONE:
869 69fde657 2014-07-09 reyk str = val;
870 8bf959a5 2012-09-20 reyk break;
871 8bf959a5 2012-09-20 reyk }
872 8bf959a5 2012-09-20 reyk
873 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: %s, %s: %d", __func__, con->se_id,
874 69fde657 2014-07-09 reyk str, kv->kv_key, strcasecmp(kv->kv_key, str));
875 8bf959a5 2012-09-20 reyk
876 69fde657 2014-07-09 reyk if (strcasecmp(kv->kv_key, str) == 0) {
877 69fde657 2014-07-09 reyk ret = RES_DROP;
878 69fde657 2014-07-09 reyk goto fail;
879 8bf959a5 2012-09-20 reyk }
880 8bf959a5 2012-09-20 reyk
881 69fde657 2014-07-09 reyk ret = RES_PASS;
882 8bf959a5 2012-09-20 reyk fail:
883 ba24b6a0 2015-12-07 mmcc free(md);
884 8bf959a5 2012-09-20 reyk free(val);
885 8bf959a5 2012-09-20 reyk return (ret);
886 8bf959a5 2012-09-20 reyk }
887 8bf959a5 2012-09-20 reyk
888 8bf959a5 2012-09-20 reyk int
889 69fde657 2014-07-09 reyk relay_lookup_url(struct ctl_relay_event *cre, const char *host, struct kv *kv)
890 8bf959a5 2012-09-20 reyk {
891 69fde657 2014-07-09 reyk struct http_descriptor *desc = (struct http_descriptor *)cre->desc;
892 69fde657 2014-07-09 reyk int i, j, dots;
893 69fde657 2014-07-09 reyk char *hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch;
894 2f6ec04d 2015-01-16 deraadt char ph[HOST_NAME_MAX+1];
895 69fde657 2014-07-09 reyk int ret;
896 8bf959a5 2012-09-20 reyk
897 69fde657 2014-07-09 reyk if (desc->http_path == NULL)
898 69fde657 2014-07-09 reyk return (RES_PASS);
899 8bf959a5 2012-09-20 reyk
900 8bf959a5 2012-09-20 reyk /*
901 8bf959a5 2012-09-20 reyk * This is an URL lookup algorithm inspired by
902 8bf959a5 2012-09-20 reyk * http://code.google.com/apis/safebrowsing/
903 8bf959a5 2012-09-20 reyk * developers_guide.html#PerformingLookups
904 8bf959a5 2012-09-20 reyk */
905 8bf959a5 2012-09-20 reyk
906 265f5a08 2016-07-22 benno DPRINTF("%s: host '%s', path '%s', query '%s'",
907 265f5a08 2016-07-22 benno __func__, host, desc->http_path,
908 69fde657 2014-07-09 reyk desc->http_query == NULL ? "" : desc->http_query);
909 8bf959a5 2012-09-20 reyk
910 69fde657 2014-07-09 reyk if (canonicalize_host(host, ph, sizeof(ph)) == NULL) {
911 265f5a08 2016-07-22 benno return (RES_BAD);
912 8bf959a5 2012-09-20 reyk }
913 8bf959a5 2012-09-20 reyk
914 8bf959a5 2012-09-20 reyk bzero(hi, sizeof(hi));
915 8bf959a5 2012-09-20 reyk for (dots = -1, i = strlen(ph) - 1; i > 0; i--) {
916 8bf959a5 2012-09-20 reyk if (ph[i] == '.' && ++dots)
917 8bf959a5 2012-09-20 reyk hi[dots - 1] = &ph[i + 1];
918 8bf959a5 2012-09-20 reyk if (dots > (RELAY_MAXLOOKUPLEVELS - 2))
919 8bf959a5 2012-09-20 reyk break;
920 8bf959a5 2012-09-20 reyk }
921 8bf959a5 2012-09-20 reyk if (dots == -1)
922 8bf959a5 2012-09-20 reyk dots = 0;
923 8bf959a5 2012-09-20 reyk hi[dots] = ph;
924 8bf959a5 2012-09-20 reyk
925 69fde657 2014-07-09 reyk if ((pp = strdup(desc->http_path)) == NULL) {
926 265f5a08 2016-07-22 benno return (RES_INTERNAL);
927 8bf959a5 2012-09-20 reyk }
928 8bf959a5 2012-09-20 reyk for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) {
929 8bf959a5 2012-09-20 reyk if (hi[i] == NULL)
930 8bf959a5 2012-09-20 reyk continue;
931 8bf959a5 2012-09-20 reyk
932 8bf959a5 2012-09-20 reyk /* 1. complete path with query */
933 69fde657 2014-07-09 reyk if (desc->http_query != NULL)
934 8bf959a5 2012-09-20 reyk if ((ret = _relay_lookup_url(cre, hi[i],
935 69fde657 2014-07-09 reyk pp, desc->http_query, kv)) != RES_PASS)
936 8bf959a5 2012-09-20 reyk goto done;
937 8bf959a5 2012-09-20 reyk
938 8bf959a5 2012-09-20 reyk /* 2. complete path without query */
939 8bf959a5 2012-09-20 reyk if ((ret = _relay_lookup_url(cre, hi[i],
940 69fde657 2014-07-09 reyk pp, NULL, kv)) != RES_PASS)
941 8bf959a5 2012-09-20 reyk goto done;
942 8bf959a5 2012-09-20 reyk
943 8bf959a5 2012-09-20 reyk /* 3. traverse path */
944 8bf959a5 2012-09-20 reyk for (j = 0, p = strchr(pp, '/');
945 8bf959a5 2012-09-20 reyk p != NULL; p = strchr(p, '/'), j++) {
946 69fde657 2014-07-09 reyk if (j > (RELAY_MAXLOOKUPLEVELS - 2) || *(++p) == '\0')
947 8bf959a5 2012-09-20 reyk break;
948 8bf959a5 2012-09-20 reyk c = &pp[p - pp];
949 8bf959a5 2012-09-20 reyk ch = *c;
950 8bf959a5 2012-09-20 reyk *c = '\0';
951 8bf959a5 2012-09-20 reyk if ((ret = _relay_lookup_url(cre, hi[i],
952 69fde657 2014-07-09 reyk pp, NULL, kv)) != RES_PASS)
953 8bf959a5 2012-09-20 reyk goto done;
954 8bf959a5 2012-09-20 reyk *c = ch;
955 8bf959a5 2012-09-20 reyk }
956 8bf959a5 2012-09-20 reyk }
957 8bf959a5 2012-09-20 reyk
958 69fde657 2014-07-09 reyk ret = RES_PASS;
959 8bf959a5 2012-09-20 reyk done:
960 8bf959a5 2012-09-20 reyk free(pp);
961 8bf959a5 2012-09-20 reyk return (ret);
962 8bf959a5 2012-09-20 reyk }
963 8bf959a5 2012-09-20 reyk
964 8bf959a5 2012-09-20 reyk int
965 69fde657 2014-07-09 reyk relay_lookup_cookie(struct ctl_relay_event *cre, const char *str,
966 69fde657 2014-07-09 reyk struct kv *kv)
967 8bf959a5 2012-09-20 reyk {
968 69fde657 2014-07-09 reyk char *val, *ptr, *key, *value;
969 8bf959a5 2012-09-20 reyk int ret;
970 8bf959a5 2012-09-20 reyk
971 8bf959a5 2012-09-20 reyk if ((val = strdup(str)) == NULL) {
972 265f5a08 2016-07-22 benno return (RES_INTERNAL);
973 8bf959a5 2012-09-20 reyk }
974 8bf959a5 2012-09-20 reyk
975 8bf959a5 2012-09-20 reyk for (ptr = val; ptr != NULL && strlen(ptr);) {
976 8bf959a5 2012-09-20 reyk if (*ptr == ' ')
977 8bf959a5 2012-09-20 reyk *ptr++ = '\0';
978 69fde657 2014-07-09 reyk key = ptr;
979 8bf959a5 2012-09-20 reyk if ((ptr = strchr(ptr, ';')) != NULL)
980 8bf959a5 2012-09-20 reyk *ptr++ = '\0';
981 8bf959a5 2012-09-20 reyk /*
982 8bf959a5 2012-09-20 reyk * XXX We do not handle attributes
983 8bf959a5 2012-09-20 reyk * ($Path, $Domain, or $Port)
984 8bf959a5 2012-09-20 reyk */
985 69fde657 2014-07-09 reyk if (*key == '$')
986 8bf959a5 2012-09-20 reyk continue;
987 8bf959a5 2012-09-20 reyk
988 69fde657 2014-07-09 reyk if ((value =
989 69fde657 2014-07-09 reyk strchr(key, '=')) == NULL ||
990 69fde657 2014-07-09 reyk strlen(value) < 1)
991 8bf959a5 2012-09-20 reyk continue;
992 69fde657 2014-07-09 reyk *value++ = '\0';
993 69fde657 2014-07-09 reyk if (*value == '"')
994 69fde657 2014-07-09 reyk *value++ = '\0';
995 69fde657 2014-07-09 reyk if (value[strlen(value) - 1] == '"')
996 69fde657 2014-07-09 reyk value[strlen(value) - 1] = '\0';
997 69fde657 2014-07-09 reyk
998 265f5a08 2016-07-22 benno DPRINTF("%s: key %s = %s, %s = %s : %d",
999 265f5a08 2016-07-22 benno __func__, key, value, kv->kv_key, kv->kv_value,
1000 69fde657 2014-07-09 reyk strcasecmp(kv->kv_key, key));
1001 69fde657 2014-07-09 reyk
1002 69fde657 2014-07-09 reyk if (strcasecmp(kv->kv_key, key) == 0 &&
1003 69fde657 2014-07-09 reyk ((kv->kv_value == NULL) ||
1004 69fde657 2014-07-09 reyk (fnmatch(kv->kv_value, value,
1005 69fde657 2014-07-09 reyk FNM_CASEFOLD) != FNM_NOMATCH))) {
1006 69fde657 2014-07-09 reyk ret = RES_DROP;
1007 69fde657 2014-07-09 reyk goto done;
1008 8bf959a5 2012-09-20 reyk }
1009 8bf959a5 2012-09-20 reyk }
1010 8bf959a5 2012-09-20 reyk
1011 69fde657 2014-07-09 reyk ret = RES_PASS;
1012 69fde657 2014-07-09 reyk
1013 8bf959a5 2012-09-20 reyk done:
1014 8bf959a5 2012-09-20 reyk free(val);
1015 8bf959a5 2012-09-20 reyk return (ret);
1016 8bf959a5 2012-09-20 reyk }
1017 8bf959a5 2012-09-20 reyk
1018 69fde657 2014-07-09 reyk int
1019 69fde657 2014-07-09 reyk relay_lookup_query(struct ctl_relay_event *cre, struct kv *kv)
1020 69fde657 2014-07-09 reyk {
1021 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1022 69fde657 2014-07-09 reyk struct kv *match = &desc->http_matchquery;
1023 69fde657 2014-07-09 reyk char *val, *ptr, *tmpkey = NULL, *tmpval = NULL;
1024 69fde657 2014-07-09 reyk int ret = -1;
1025 69fde657 2014-07-09 reyk
1026 69fde657 2014-07-09 reyk if (desc->http_query == NULL)
1027 69fde657 2014-07-09 reyk return (-1);
1028 69fde657 2014-07-09 reyk if ((val = strdup(desc->http_query)) == NULL) {
1029 265f5a08 2016-07-22 benno return (RES_INTERNAL);
1030 69fde657 2014-07-09 reyk }
1031 69fde657 2014-07-09 reyk
1032 69fde657 2014-07-09 reyk ptr = val;
1033 69fde657 2014-07-09 reyk while (ptr != NULL && strlen(ptr)) {
1034 69fde657 2014-07-09 reyk tmpkey = ptr;
1035 69fde657 2014-07-09 reyk if ((ptr = strchr(ptr, '&')) != NULL)
1036 69fde657 2014-07-09 reyk *ptr++ = '\0';
1037 69fde657 2014-07-09 reyk if ((tmpval = strchr(tmpkey, '=')) == NULL || strlen(tmpval)
1038 69fde657 2014-07-09 reyk < 1)
1039 69fde657 2014-07-09 reyk continue;
1040 69fde657 2014-07-09 reyk *tmpval++ = '\0';
1041 69fde657 2014-07-09 reyk
1042 69fde657 2014-07-09 reyk if (fnmatch(kv->kv_key, tmpkey, 0) != FNM_NOMATCH &&
1043 69fde657 2014-07-09 reyk (kv->kv_value == NULL || fnmatch(kv->kv_value, tmpval, 0)
1044 69fde657 2014-07-09 reyk != FNM_NOMATCH))
1045 69fde657 2014-07-09 reyk break;
1046 69fde657 2014-07-09 reyk else
1047 69fde657 2014-07-09 reyk tmpkey = NULL;
1048 69fde657 2014-07-09 reyk }
1049 69fde657 2014-07-09 reyk
1050 69fde657 2014-07-09 reyk if (tmpkey == NULL || tmpval == NULL)
1051 69fde657 2014-07-09 reyk goto done;
1052 69fde657 2014-07-09 reyk
1053 69fde657 2014-07-09 reyk match->kv_key = strdup(tmpkey);
1054 69fde657 2014-07-09 reyk if (match->kv_key == NULL)
1055 69fde657 2014-07-09 reyk goto done;
1056 69fde657 2014-07-09 reyk match->kv_value = strdup(tmpval);
1057 7ef192f5 2026-04-02 tb if (match->kv_value == NULL)
1058 69fde657 2014-07-09 reyk goto done;
1059 69fde657 2014-07-09 reyk ret = 0;
1060 69fde657 2014-07-09 reyk
1061 69fde657 2014-07-09 reyk done:
1062 69fde657 2014-07-09 reyk free(val);
1063 69fde657 2014-07-09 reyk return (ret);
1064 69fde657 2014-07-09 reyk }
1065 69fde657 2014-07-09 reyk
1066 b8e8b53b 2015-01-01 reyk ssize_t
1067 b8e8b53b 2015-01-01 reyk relay_http_time(time_t t, char *tmbuf, size_t len)
1068 b8e8b53b 2015-01-01 reyk {
1069 b8e8b53b 2015-01-01 reyk struct tm tm;
1070 69fde657 2014-07-09 reyk
1071 b8e8b53b 2015-01-01 reyk /* New HTTP/1.1 RFC 7231 prefers IMF-fixdate from RFC 5322 */
1072 b8e8b53b 2015-01-01 reyk if (t == -1 || gmtime_r(&t, &tm) == NULL)
1073 b8e8b53b 2015-01-01 reyk return (-1);
1074 b8e8b53b 2015-01-01 reyk else
1075 952c015b 2025-12-21 tb return (strftime(tmbuf, len, "%a, %d %h %Y %T GMT", &tm));
1076 b8e8b53b 2015-01-01 reyk }
1077 b8e8b53b 2015-01-01 reyk
1078 8bf959a5 2012-09-20 reyk void
1079 8bf959a5 2012-09-20 reyk relay_abort_http(struct rsession *con, u_int code, const char *msg,
1080 8bf959a5 2012-09-20 reyk u_int16_t labelid)
1081 8bf959a5 2012-09-20 reyk {
1082 6e65a975 2013-01-17 bluhm struct relay *rlay = con->se_relay;
1083 8bf959a5 2012-09-20 reyk struct bufferevent *bev = con->se_in.bev;
1084 fa847717 2014-07-12 reyk const char *httperr = NULL, *text = "";
1085 b8e8b53b 2015-01-01 reyk char *httpmsg, *body = NULL;
1086 8bf959a5 2012-09-20 reyk char tmbuf[32], hbuf[128];
1087 8bf959a5 2012-09-20 reyk const char *style, *label = NULL;
1088 b8e8b53b 2015-01-01 reyk int bodylen;
1089 8bf959a5 2012-09-20 reyk
1090 fa847717 2014-07-12 reyk if ((httperr = relay_httperror_byid(code)) == NULL)
1091 fa847717 2014-07-12 reyk httperr = "Unknown Error";
1092 fa847717 2014-07-12 reyk
1093 69fde657 2014-07-09 reyk if (labelid != 0)
1094 69fde657 2014-07-09 reyk label = label_id2name(labelid);
1095 69fde657 2014-07-09 reyk
1096 8bf959a5 2012-09-20 reyk /* In some cases this function may be called from generic places */
1097 8bf959a5 2012-09-20 reyk if (rlay->rl_proto->type != RELAY_PROTO_HTTP ||
1098 8bf959a5 2012-09-20 reyk (rlay->rl_proto->flags & F_RETURN) == 0) {
1099 37ed6014 2018-08-06 benno relay_close(con, msg, 0);
1100 8bf959a5 2012-09-20 reyk return;
1101 8bf959a5 2012-09-20 reyk }
1102 8bf959a5 2012-09-20 reyk
1103 8bf959a5 2012-09-20 reyk if (bev == NULL)
1104 8bf959a5 2012-09-20 reyk goto done;
1105 8bf959a5 2012-09-20 reyk
1106 8bf959a5 2012-09-20 reyk /* Some system information */
1107 8bf959a5 2012-09-20 reyk if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL)
1108 8bf959a5 2012-09-20 reyk goto done;
1109 8bf959a5 2012-09-20 reyk
1110 b8e8b53b 2015-01-01 reyk if (relay_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0)
1111 b8e8b53b 2015-01-01 reyk goto done;
1112 8bf959a5 2012-09-20 reyk
1113 8bf959a5 2012-09-20 reyk /* Do not send details of the Internal Server Error */
1114 b8e8b53b 2015-01-01 reyk switch (code) {
1115 b8e8b53b 2015-01-01 reyk case 500:
1116 b8e8b53b 2015-01-01 reyk break;
1117 b8e8b53b 2015-01-01 reyk default:
1118 8bf959a5 2012-09-20 reyk text = msg;
1119 b8e8b53b 2015-01-01 reyk break;
1120 b8e8b53b 2015-01-01 reyk }
1121 8bf959a5 2012-09-20 reyk
1122 8bf959a5 2012-09-20 reyk /* A CSS stylesheet allows minimal customization by the user */
1123 b8e8b53b 2015-01-01 reyk style = (rlay->rl_proto->style != NULL) ? rlay->rl_proto->style :
1124 b8e8b53b 2015-01-01 reyk "body { background-color: #a00000; color: white; font-family: "
1125 b8e8b53b 2015-01-01 reyk "'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }\n"
1126 b8e8b53b 2015-01-01 reyk "hr { border: 0; border-bottom: 1px dashed; }\n";
1127 8bf959a5 2012-09-20 reyk
1128 8bf959a5 2012-09-20 reyk /* Generate simple HTTP+HTML error document */
1129 b8e8b53b 2015-01-01 reyk if ((bodylen = asprintf(&body,
1130 91865213 2015-01-01 reyk "<!DOCTYPE html>\n"
1131 8bf959a5 2012-09-20 reyk "<html>\n"
1132 8bf959a5 2012-09-20 reyk "<head>\n"
1133 8bf959a5 2012-09-20 reyk "<title>%03d %s</title>\n"
1134 8bf959a5 2012-09-20 reyk "<style type=\"text/css\"><!--\n%s\n--></style>\n"
1135 8bf959a5 2012-09-20 reyk "</head>\n"
1136 8bf959a5 2012-09-20 reyk "<body>\n"
1137 8bf959a5 2012-09-20 reyk "<h1>%s</h1>\n"
1138 8bf959a5 2012-09-20 reyk "<div id='m'>%s</div>\n"
1139 8bf959a5 2012-09-20 reyk "<div id='l'>%s</div>\n"
1140 8bf959a5 2012-09-20 reyk "<hr><address>%s at %s port %d</address>\n"
1141 8bf959a5 2012-09-20 reyk "</body>\n"
1142 8bf959a5 2012-09-20 reyk "</html>\n",
1143 8bf959a5 2012-09-20 reyk code, httperr, style, httperr, text,
1144 8bf959a5 2012-09-20 reyk label == NULL ? "" : label,
1145 b8e8b53b 2015-01-01 reyk RELAYD_SERVERNAME, hbuf, ntohs(rlay->rl_conf.port))) == -1)
1146 8bf959a5 2012-09-20 reyk goto done;
1147 8bf959a5 2012-09-20 reyk
1148 b8e8b53b 2015-01-01 reyk /* Generate simple HTTP+HTML error document */
1149 b8e8b53b 2015-01-01 reyk if (asprintf(&httpmsg,
1150 b8e8b53b 2015-01-01 reyk "HTTP/1.0 %03d %s\r\n"
1151 b8e8b53b 2015-01-01 reyk "Date: %s\r\n"
1152 b8e8b53b 2015-01-01 reyk "Server: %s\r\n"
1153 b8e8b53b 2015-01-01 reyk "Connection: close\r\n"
1154 b8e8b53b 2015-01-01 reyk "Content-Type: text/html\r\n"
1155 b8e8b53b 2015-01-01 reyk "Content-Length: %d\r\n"
1156 b8e8b53b 2015-01-01 reyk "\r\n"
1157 b8e8b53b 2015-01-01 reyk "%s",
1158 b8e8b53b 2015-01-01 reyk code, httperr, tmbuf, RELAYD_SERVERNAME, bodylen, body) == -1)
1159 b8e8b53b 2015-01-01 reyk goto done;
1160 b8e8b53b 2015-01-01 reyk
1161 8bf959a5 2012-09-20 reyk /* Dump the message without checking for success */
1162 8bf959a5 2012-09-20 reyk relay_dump(&con->se_in, httpmsg, strlen(httpmsg));
1163 8bf959a5 2012-09-20 reyk free(httpmsg);
1164 8bf959a5 2012-09-20 reyk
1165 8bf959a5 2012-09-20 reyk done:
1166 b8e8b53b 2015-01-01 reyk free(body);
1167 8bf959a5 2012-09-20 reyk if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1)
1168 37ed6014 2018-08-06 benno relay_close(con, msg, 1);
1169 8bf959a5 2012-09-20 reyk else {
1170 37ed6014 2018-08-06 benno relay_close(con, httpmsg, 1);
1171 8bf959a5 2012-09-20 reyk free(httpmsg);
1172 8bf959a5 2012-09-20 reyk }
1173 8bf959a5 2012-09-20 reyk }
1174 8bf959a5 2012-09-20 reyk
1175 69fde657 2014-07-09 reyk void
1176 69fde657 2014-07-09 reyk relay_close_http(struct rsession *con)
1177 69fde657 2014-07-09 reyk {
1178 94c8a65e 2021-03-24 benno struct http_session *hs = con->se_priv;
1179 94c8a65e 2021-03-24 benno struct http_method_node *hmn;
1180 94c8a65e 2021-03-24 benno
1181 94c8a65e 2021-03-24 benno DPRINTF("%s: session %d http_session %p", __func__,
1182 94c8a65e 2021-03-24 benno con->se_id, hs);
1183 94c8a65e 2021-03-24 benno if (hs != NULL)
1184 94c8a65e 2021-03-24 benno while (!SIMPLEQ_EMPTY(&hs->hs_methods)) {
1185 94c8a65e 2021-03-24 benno hmn = SIMPLEQ_FIRST(&hs->hs_methods);
1186 94c8a65e 2021-03-24 benno SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
1187 94c8a65e 2021-03-24 benno DPRINTF("%s: session %d freeing %s", __func__,
1188 94c8a65e 2021-03-24 benno con->se_id, relay_httpmethod_byid(hmn->hmn_method));
1189 94c8a65e 2021-03-24 benno free(hmn);
1190 94c8a65e 2021-03-24 benno }
1191 f4fc50a1 2017-11-27 claudio relay_httpdesc_free(con->se_in.desc);
1192 f4fc50a1 2017-11-27 claudio free(con->se_in.desc);
1193 f4fc50a1 2017-11-27 claudio relay_httpdesc_free(con->se_out.desc);
1194 f4fc50a1 2017-11-27 claudio free(con->se_out.desc);
1195 69fde657 2014-07-09 reyk }
1196 69fde657 2014-07-09 reyk
1197 8bf959a5 2012-09-20 reyk char *
1198 69fde657 2014-07-09 reyk relay_expand_http(struct ctl_relay_event *cre, char *val, char *buf,
1199 69fde657 2014-07-09 reyk size_t len)
1200 8bf959a5 2012-09-20 reyk {
1201 4cc2f5fd 2019-07-05 robert struct rsession *con = cre->con;
1202 4cc2f5fd 2019-07-05 robert struct relay *rlay = con->se_relay;
1203 4cc2f5fd 2019-07-05 robert struct http_descriptor *desc = cre->desc;
1204 4cc2f5fd 2019-07-05 robert struct kv *host, key;
1205 4cc2f5fd 2019-07-05 robert char ibuf[128];
1206 8bf959a5 2012-09-20 reyk
1207 7f018056 2014-04-20 reyk if (strlcpy(buf, val, len) >= len)
1208 7f018056 2014-04-20 reyk return (NULL);
1209 8bf959a5 2012-09-20 reyk
1210 4cc2f5fd 2019-07-05 robert if (strstr(val, "$HOST") != NULL) {
1211 4cc2f5fd 2019-07-05 robert key.kv_key = "Host";
1212 4cc2f5fd 2019-07-05 robert host = kv_find(&desc->http_headers, &key);
1213 4cc2f5fd 2019-07-05 robert if (host) {
1214 4cc2f5fd 2019-07-05 robert if (host->kv_value == NULL)
1215 4cc2f5fd 2019-07-05 robert return (NULL);
1216 4cc2f5fd 2019-07-05 robert snprintf(ibuf, sizeof(ibuf), "%s", host->kv_value);
1217 4cc2f5fd 2019-07-05 robert } else {
1218 4cc2f5fd 2019-07-05 robert if (print_host(&rlay->rl_conf.ss,
1219 4cc2f5fd 2019-07-05 robert ibuf, sizeof(ibuf)) == NULL)
1220 4cc2f5fd 2019-07-05 robert return (NULL);
1221 4cc2f5fd 2019-07-05 robert }
1222 4cc2f5fd 2019-07-05 robert if (expand_string(buf, len, "$HOST", ibuf))
1223 4cc2f5fd 2019-07-05 robert return (NULL);
1224 4cc2f5fd 2019-07-05 robert }
1225 8bf959a5 2012-09-20 reyk if (strstr(val, "$REMOTE_") != NULL) {
1226 8bf959a5 2012-09-20 reyk if (strstr(val, "$REMOTE_ADDR") != NULL) {
1227 8bf959a5 2012-09-20 reyk if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL)
1228 8bf959a5 2012-09-20 reyk return (NULL);
1229 8bf959a5 2012-09-20 reyk if (expand_string(buf, len,
1230 8bf959a5 2012-09-20 reyk "$REMOTE_ADDR", ibuf) != 0)
1231 8bf959a5 2012-09-20 reyk return (NULL);
1232 8bf959a5 2012-09-20 reyk }
1233 8bf959a5 2012-09-20 reyk if (strstr(val, "$REMOTE_PORT") != NULL) {
1234 8bf959a5 2012-09-20 reyk snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port));
1235 8bf959a5 2012-09-20 reyk if (expand_string(buf, len,
1236 8bf959a5 2012-09-20 reyk "$REMOTE_PORT", ibuf) != 0)
1237 8bf959a5 2012-09-20 reyk return (NULL);
1238 8bf959a5 2012-09-20 reyk }
1239 8bf959a5 2012-09-20 reyk }
1240 8bf959a5 2012-09-20 reyk if (strstr(val, "$SERVER_") != NULL) {
1241 8bf959a5 2012-09-20 reyk if (strstr(val, "$SERVER_ADDR") != NULL) {
1242 8bf959a5 2012-09-20 reyk if (print_host(&rlay->rl_conf.ss,
1243 8bf959a5 2012-09-20 reyk ibuf, sizeof(ibuf)) == NULL)
1244 8bf959a5 2012-09-20 reyk return (NULL);
1245 8bf959a5 2012-09-20 reyk if (expand_string(buf, len,
1246 8bf959a5 2012-09-20 reyk "$SERVER_ADDR", ibuf) != 0)
1247 8bf959a5 2012-09-20 reyk return (NULL);
1248 8bf959a5 2012-09-20 reyk }
1249 8bf959a5 2012-09-20 reyk if (strstr(val, "$SERVER_PORT") != NULL) {
1250 8bf959a5 2012-09-20 reyk snprintf(ibuf, sizeof(ibuf), "%u",
1251 8bf959a5 2012-09-20 reyk ntohs(rlay->rl_conf.port));
1252 8bf959a5 2012-09-20 reyk if (expand_string(buf, len,
1253 8bf959a5 2012-09-20 reyk "$SERVER_PORT", ibuf) != 0)
1254 8bf959a5 2012-09-20 reyk return (NULL);
1255 8bf959a5 2012-09-20 reyk }
1256 8bf959a5 2012-09-20 reyk if (strstr(val, "$SERVER_NAME") != NULL) {
1257 8bf959a5 2012-09-20 reyk if (expand_string(buf, len,
1258 8bf959a5 2012-09-20 reyk "$SERVER_NAME", RELAYD_SERVERNAME) != 0)
1259 8bf959a5 2012-09-20 reyk return (NULL);
1260 8bf959a5 2012-09-20 reyk }
1261 8bf959a5 2012-09-20 reyk }
1262 8bf959a5 2012-09-20 reyk if (strstr(val, "$TIMEOUT") != NULL) {
1263 7fcbaa55 2013-04-20 deraadt snprintf(ibuf, sizeof(ibuf), "%lld",
1264 7fcbaa55 2013-04-20 deraadt (long long)rlay->rl_conf.timeout.tv_sec);
1265 8bf959a5 2012-09-20 reyk if (expand_string(buf, len, "$TIMEOUT", ibuf) != 0)
1266 8bf959a5 2012-09-20 reyk return (NULL);
1267 8bf959a5 2012-09-20 reyk }
1268 8bf959a5 2012-09-20 reyk
1269 8bf959a5 2012-09-20 reyk return (buf);
1270 8bf959a5 2012-09-20 reyk }
1271 8bf959a5 2012-09-20 reyk
1272 8bf959a5 2012-09-20 reyk int
1273 69fde657 2014-07-09 reyk relay_writerequest_http(struct ctl_relay_event *dst,
1274 69fde657 2014-07-09 reyk struct ctl_relay_event *cre)
1275 8bf959a5 2012-09-20 reyk {
1276 69fde657 2014-07-09 reyk struct http_descriptor *desc = (struct http_descriptor *)cre->desc;
1277 69fde657 2014-07-09 reyk const char *name = NULL;
1278 8bf959a5 2012-09-20 reyk
1279 69fde657 2014-07-09 reyk if ((name = relay_httpmethod_byid(desc->http_method)) == NULL)
1280 69fde657 2014-07-09 reyk return (-1);
1281 8bf959a5 2012-09-20 reyk
1282 69fde657 2014-07-09 reyk if (relay_bufferevent_print(dst, name) == -1 ||
1283 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, " ") == -1 ||
1284 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, desc->http_path) == -1 ||
1285 69fde657 2014-07-09 reyk (desc->http_query != NULL &&
1286 69fde657 2014-07-09 reyk (relay_bufferevent_print(dst, "?") == -1 ||
1287 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, desc->http_query) == -1)) ||
1288 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, " ") == -1 ||
1289 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, desc->http_version) == -1)
1290 69fde657 2014-07-09 reyk return (-1);
1291 69fde657 2014-07-09 reyk
1292 69fde657 2014-07-09 reyk return (0);
1293 69fde657 2014-07-09 reyk }
1294 69fde657 2014-07-09 reyk
1295 69fde657 2014-07-09 reyk int
1296 69fde657 2014-07-09 reyk relay_writeresponse_http(struct ctl_relay_event *dst,
1297 69fde657 2014-07-09 reyk struct ctl_relay_event *cre)
1298 69fde657 2014-07-09 reyk {
1299 69fde657 2014-07-09 reyk struct http_descriptor *desc = (struct http_descriptor *)cre->desc;
1300 69fde657 2014-07-09 reyk
1301 69fde657 2014-07-09 reyk DPRINTF("version: %s rescode: %s resmsg: %s", desc->http_version,
1302 69fde657 2014-07-09 reyk desc->http_rescode, desc->http_resmesg);
1303 69fde657 2014-07-09 reyk
1304 69fde657 2014-07-09 reyk if (relay_bufferevent_print(dst, desc->http_version) == -1 ||
1305 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, " ") == -1 ||
1306 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, desc->http_rescode) == -1 ||
1307 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, " ") == -1 ||
1308 69fde657 2014-07-09 reyk relay_bufferevent_print(dst, desc->http_resmesg) == -1)
1309 69fde657 2014-07-09 reyk return (-1);
1310 69fde657 2014-07-09 reyk
1311 69fde657 2014-07-09 reyk return (0);
1312 69fde657 2014-07-09 reyk }
1313 69fde657 2014-07-09 reyk
1314 69fde657 2014-07-09 reyk int
1315 2d9632ee 2014-07-11 reyk relay_writeheader_kv(struct ctl_relay_event *dst, struct kv *hdr)
1316 2d9632ee 2014-07-11 reyk {
1317 2d9632ee 2014-07-11 reyk char *ptr;
1318 2d9632ee 2014-07-11 reyk const char *key;
1319 2d9632ee 2014-07-11 reyk
1320 2d9632ee 2014-07-11 reyk if (hdr->kv_flags & KV_FLAG_INVALID)
1321 2d9632ee 2014-07-11 reyk return (0);
1322 2d9632ee 2014-07-11 reyk
1323 2d9632ee 2014-07-11 reyk /* The key might have been updated in the parent */
1324 2d9632ee 2014-07-11 reyk if (hdr->kv_parent != NULL && hdr->kv_parent->kv_key != NULL)
1325 2d9632ee 2014-07-11 reyk key = hdr->kv_parent->kv_key;
1326 2d9632ee 2014-07-11 reyk else
1327 2d9632ee 2014-07-11 reyk key = hdr->kv_key;
1328 2d9632ee 2014-07-11 reyk
1329 2d9632ee 2014-07-11 reyk ptr = hdr->kv_value;
1330 2d9632ee 2014-07-11 reyk if (relay_bufferevent_print(dst, key) == -1 ||
1331 2d9632ee 2014-07-11 reyk (ptr != NULL &&
1332 2d9632ee 2014-07-11 reyk (relay_bufferevent_print(dst, ": ") == -1 ||
1333 2d9632ee 2014-07-11 reyk relay_bufferevent_print(dst, ptr) == -1 ||
1334 2d9632ee 2014-07-11 reyk relay_bufferevent_print(dst, "\r\n") == -1)))
1335 2d9632ee 2014-07-11 reyk return (-1);
1336 2d9632ee 2014-07-11 reyk DPRINTF("%s: %s: %s", __func__, key,
1337 2d9632ee 2014-07-11 reyk hdr->kv_value == NULL ? "" : hdr->kv_value);
1338 2d9632ee 2014-07-11 reyk
1339 2d9632ee 2014-07-11 reyk return (0);
1340 2d9632ee 2014-07-11 reyk }
1341 2d9632ee 2014-07-11 reyk
1342 2d9632ee 2014-07-11 reyk int
1343 69fde657 2014-07-09 reyk relay_writeheader_http(struct ctl_relay_event *dst, struct ctl_relay_event
1344 69fde657 2014-07-09 reyk *cre)
1345 69fde657 2014-07-09 reyk {
1346 2d9632ee 2014-07-11 reyk struct kv *hdr, *kv;
1347 69fde657 2014-07-09 reyk struct http_descriptor *desc = (struct http_descriptor *)cre->desc;
1348 69fde657 2014-07-09 reyk
1349 2d9632ee 2014-07-11 reyk RB_FOREACH(hdr, kvtree, &desc->http_headers) {
1350 2d9632ee 2014-07-11 reyk if (relay_writeheader_kv(dst, hdr) == -1)
1351 69fde657 2014-07-09 reyk return (-1);
1352 2d9632ee 2014-07-11 reyk TAILQ_FOREACH(kv, &hdr->kv_children, kv_entry) {
1353 2d9632ee 2014-07-11 reyk if (relay_writeheader_kv(dst, kv) == -1)
1354 2d9632ee 2014-07-11 reyk return (-1);
1355 2d9632ee 2014-07-11 reyk }
1356 69fde657 2014-07-09 reyk }
1357 69fde657 2014-07-09 reyk
1358 69fde657 2014-07-09 reyk return (0);
1359 69fde657 2014-07-09 reyk }
1360 69fde657 2014-07-09 reyk
1361 69fde657 2014-07-09 reyk enum httpmethod
1362 69fde657 2014-07-09 reyk relay_httpmethod_byname(const char *name)
1363 69fde657 2014-07-09 reyk {
1364 69fde657 2014-07-09 reyk enum httpmethod id = HTTP_METHOD_NONE;
1365 69fde657 2014-07-09 reyk struct http_method method, *res = NULL;
1366 69fde657 2014-07-09 reyk
1367 69fde657 2014-07-09 reyk /* Set up key */
1368 69fde657 2014-07-09 reyk method.method_name = name;
1369 69fde657 2014-07-09 reyk
1370 69fde657 2014-07-09 reyk if ((res = bsearch(&method, http_methods,
1371 69fde657 2014-07-09 reyk sizeof(http_methods) / sizeof(http_methods[0]) - 1,
1372 69fde657 2014-07-09 reyk sizeof(http_methods[0]), relay_httpmethod_cmp)) != NULL)
1373 69fde657 2014-07-09 reyk id = res->method_id;
1374 69fde657 2014-07-09 reyk
1375 69fde657 2014-07-09 reyk return (id);
1376 69fde657 2014-07-09 reyk }
1377 69fde657 2014-07-09 reyk
1378 69fde657 2014-07-09 reyk const char *
1379 69fde657 2014-07-09 reyk relay_httpmethod_byid(u_int id)
1380 69fde657 2014-07-09 reyk {
1381 69fde657 2014-07-09 reyk const char *name = NULL;
1382 69fde657 2014-07-09 reyk int i;
1383 69fde657 2014-07-09 reyk
1384 69fde657 2014-07-09 reyk for (i = 0; http_methods[i].method_name != NULL; i++) {
1385 69fde657 2014-07-09 reyk if (http_methods[i].method_id == id) {
1386 69fde657 2014-07-09 reyk name = http_methods[i].method_name;
1387 69fde657 2014-07-09 reyk break;
1388 8bf959a5 2012-09-20 reyk }
1389 8bf959a5 2012-09-20 reyk }
1390 69fde657 2014-07-09 reyk
1391 69fde657 2014-07-09 reyk return (name);
1392 69fde657 2014-07-09 reyk }
1393 69fde657 2014-07-09 reyk
1394 69fde657 2014-07-09 reyk static int
1395 69fde657 2014-07-09 reyk relay_httpmethod_cmp(const void *a, const void *b)
1396 69fde657 2014-07-09 reyk {
1397 69fde657 2014-07-09 reyk const struct http_method *ma = a;
1398 69fde657 2014-07-09 reyk const struct http_method *mb = b;
1399 53fad893 2014-07-17 stsp
1400 53fad893 2014-07-17 stsp /*
1401 53fad893 2014-07-17 stsp * RFC 2616 section 5.1.1 says that the method is case
1402 53fad893 2014-07-17 stsp * sensitive so we don't do a strcasecmp here.
1403 53fad893 2014-07-17 stsp */
1404 69fde657 2014-07-09 reyk return (strcmp(ma->method_name, mb->method_name));
1405 69fde657 2014-07-09 reyk }
1406 69fde657 2014-07-09 reyk
1407 fa847717 2014-07-12 reyk const char *
1408 fa847717 2014-07-12 reyk relay_httperror_byid(u_int id)
1409 fa847717 2014-07-12 reyk {
1410 fa847717 2014-07-12 reyk struct http_error error, *res = NULL;
1411 fa847717 2014-07-12 reyk
1412 fa847717 2014-07-12 reyk /* Set up key */
1413 fa847717 2014-07-12 reyk error.error_code = (int)id;
1414 fa847717 2014-07-12 reyk
1415 4c3a9f7f 2026-04-02 tb if ((res = bsearch(&error, http_errors,
1416 fa847717 2014-07-12 reyk sizeof(http_errors) / sizeof(http_errors[0]) - 1,
1417 4c3a9f7f 2026-04-02 tb sizeof(http_errors[0]), relay_httperror_cmp)) != NULL)
1418 4c3a9f7f 2026-04-02 tb return (res->error_name);
1419 fa847717 2014-07-12 reyk
1420 4c3a9f7f 2026-04-02 tb return (NULL);
1421 fa847717 2014-07-12 reyk }
1422 fa847717 2014-07-12 reyk
1423 fa847717 2014-07-12 reyk static int
1424 fa847717 2014-07-12 reyk relay_httperror_cmp(const void *a, const void *b)
1425 fa847717 2014-07-12 reyk {
1426 fa847717 2014-07-12 reyk const struct http_error *ea = a;
1427 fa847717 2014-07-12 reyk const struct http_error *eb = b;
1428 fa847717 2014-07-12 reyk return (ea->error_code - eb->error_code);
1429 fa847717 2014-07-12 reyk }
1430 fa847717 2014-07-12 reyk
1431 69fde657 2014-07-09 reyk int
1432 69fde657 2014-07-09 reyk relay_httpquery_test(struct ctl_relay_event *cre, struct relay_rule *rule,
1433 69fde657 2014-07-09 reyk struct kvlist *actions)
1434 69fde657 2014-07-09 reyk {
1435 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1436 69fde657 2014-07-09 reyk struct kv *match = &desc->http_matchquery;
1437 69fde657 2014-07-09 reyk struct kv *kv = &rule->rule_kv[KEY_TYPE_QUERY];
1438 265f5a08 2016-07-22 benno int res = 0;
1439 69fde657 2014-07-09 reyk
1440 69fde657 2014-07-09 reyk if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_QUERY)
1441 69fde657 2014-07-09 reyk return (0);
1442 69fde657 2014-07-09 reyk else if (kv->kv_key == NULL)
1443 69fde657 2014-07-09 reyk return (0);
1444 265f5a08 2016-07-22 benno else if ((res = relay_lookup_query(cre, kv)) != 0)
1445 265f5a08 2016-07-22 benno return (res);
1446 69fde657 2014-07-09 reyk
1447 69fde657 2014-07-09 reyk relay_match(actions, kv, match, NULL);
1448 69fde657 2014-07-09 reyk
1449 69fde657 2014-07-09 reyk return (0);
1450 69fde657 2014-07-09 reyk }
1451 69fde657 2014-07-09 reyk
1452 69fde657 2014-07-09 reyk int
1453 69fde657 2014-07-09 reyk relay_httpheader_test(struct ctl_relay_event *cre, struct relay_rule *rule,
1454 69fde657 2014-07-09 reyk struct kvlist *actions)
1455 69fde657 2014-07-09 reyk {
1456 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1457 69fde657 2014-07-09 reyk struct kv *kv = &rule->rule_kv[KEY_TYPE_HEADER];
1458 69fde657 2014-07-09 reyk struct kv *match;
1459 69fde657 2014-07-09 reyk
1460 2d9632ee 2014-07-11 reyk if (kv->kv_type != KEY_TYPE_HEADER)
1461 69fde657 2014-07-09 reyk return (0);
1462 69fde657 2014-07-09 reyk
1463 2d9632ee 2014-07-11 reyk match = kv_find(&desc->http_headers, kv);
1464 2d9632ee 2014-07-11 reyk
1465 69fde657 2014-07-09 reyk if (kv->kv_option == KEY_OPTION_APPEND ||
1466 69fde657 2014-07-09 reyk kv->kv_option == KEY_OPTION_SET) {
1467 69fde657 2014-07-09 reyk /* header can be NULL and will be added later */
1468 69fde657 2014-07-09 reyk } else if (match == NULL) {
1469 69fde657 2014-07-09 reyk /* Fail if header doesn't exist */
1470 8bf959a5 2012-09-20 reyk return (-1);
1471 8ec17694 2014-07-13 benno } else {
1472 63e504f7 2015-01-22 reyk if (fnmatch(kv->kv_key, match->kv_key,
1473 63e504f7 2015-01-22 reyk FNM_CASEFOLD) == FNM_NOMATCH)
1474 8ec17694 2014-07-13 benno return (-1);
1475 8ec17694 2014-07-13 benno if (kv->kv_value != NULL &&
1476 8ec17694 2014-07-13 benno match->kv_value != NULL &&
1477 8ec17694 2014-07-13 benno fnmatch(kv->kv_value, match->kv_value, 0) == FNM_NOMATCH)
1478 8ec17694 2014-07-13 benno return (-1);
1479 8bf959a5 2012-09-20 reyk }
1480 69fde657 2014-07-09 reyk
1481 69fde657 2014-07-09 reyk relay_match(actions, kv, match, &desc->http_headers);
1482 69fde657 2014-07-09 reyk
1483 8bf959a5 2012-09-20 reyk return (0);
1484 8bf959a5 2012-09-20 reyk }
1485 8bf959a5 2012-09-20 reyk
1486 8bf959a5 2012-09-20 reyk int
1487 69fde657 2014-07-09 reyk relay_httppath_test(struct ctl_relay_event *cre, struct relay_rule *rule,
1488 69fde657 2014-07-09 reyk struct kvlist *actions)
1489 8bf959a5 2012-09-20 reyk {
1490 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1491 69fde657 2014-07-09 reyk struct kv *kv = &rule->rule_kv[KEY_TYPE_PATH];
1492 69fde657 2014-07-09 reyk struct kv *match = &desc->http_pathquery;
1493 69fde657 2014-07-09 reyk const char *query;
1494 8bf959a5 2012-09-20 reyk
1495 69fde657 2014-07-09 reyk if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_PATH)
1496 69fde657 2014-07-09 reyk return (0);
1497 d498e80a 2021-01-09 denis else if (kv->kv_option != KEY_OPTION_STRIP) {
1498 d498e80a 2021-01-09 denis if (kv->kv_key == NULL)
1499 d498e80a 2021-01-09 denis return (0);
1500 d498e80a 2021-01-09 denis else if (fnmatch(kv->kv_key, desc->http_path, 0) == FNM_NOMATCH)
1501 69fde657 2014-07-09 reyk return (-1);
1502 d498e80a 2021-01-09 denis else if (kv->kv_value != NULL && kv->kv_option == KEY_OPTION_NONE) {
1503 d498e80a 2021-01-09 denis query = desc->http_query == NULL ? "" : desc->http_query;
1504 d498e80a 2021-01-09 denis if (fnmatch(kv->kv_value, query, FNM_CASEFOLD) == FNM_NOMATCH)
1505 d498e80a 2021-01-09 denis return (-1);
1506 d498e80a 2021-01-09 denis }
1507 69fde657 2014-07-09 reyk }
1508 8bf959a5 2012-09-20 reyk
1509 69fde657 2014-07-09 reyk relay_match(actions, kv, match, NULL);
1510 69fde657 2014-07-09 reyk
1511 69fde657 2014-07-09 reyk return (0);
1512 69fde657 2014-07-09 reyk }
1513 69fde657 2014-07-09 reyk
1514 69fde657 2014-07-09 reyk int
1515 69fde657 2014-07-09 reyk relay_httpurl_test(struct ctl_relay_event *cre, struct relay_rule *rule,
1516 69fde657 2014-07-09 reyk struct kvlist *actions)
1517 69fde657 2014-07-09 reyk {
1518 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1519 2d9632ee 2014-07-11 reyk struct kv *host, key;
1520 69fde657 2014-07-09 reyk struct kv *kv = &rule->rule_kv[KEY_TYPE_URL];
1521 69fde657 2014-07-09 reyk struct kv *match = &desc->http_pathquery;
1522 265f5a08 2016-07-22 benno int res;
1523 69fde657 2014-07-09 reyk
1524 2d9632ee 2014-07-11 reyk if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_URL ||
1525 2d9632ee 2014-07-11 reyk kv->kv_key == NULL)
1526 69fde657 2014-07-09 reyk return (0);
1527 2d9632ee 2014-07-11 reyk
1528 2d9632ee 2014-07-11 reyk key.kv_key = "Host";
1529 2d9632ee 2014-07-11 reyk host = kv_find(&desc->http_headers, &key);
1530 2d9632ee 2014-07-11 reyk
1531 2d9632ee 2014-07-11 reyk if (host == NULL || host->kv_value == NULL)
1532 69fde657 2014-07-09 reyk return (0);
1533 69fde657 2014-07-09 reyk else if (rule->rule_action != RULE_ACTION_BLOCK &&
1534 69fde657 2014-07-09 reyk kv->kv_option == KEY_OPTION_LOG &&
1535 69fde657 2014-07-09 reyk fnmatch(kv->kv_key, match->kv_key, FNM_CASEFOLD) != FNM_NOMATCH) {
1536 69fde657 2014-07-09 reyk /* fnmatch url only for logging */
1537 265f5a08 2016-07-22 benno } else if ((res = relay_lookup_url(cre, host->kv_value, kv)) != 0)
1538 265f5a08 2016-07-22 benno return (res);
1539 69fde657 2014-07-09 reyk relay_match(actions, kv, match, NULL);
1540 69fde657 2014-07-09 reyk
1541 69fde657 2014-07-09 reyk return (0);
1542 69fde657 2014-07-09 reyk }
1543 69fde657 2014-07-09 reyk
1544 69fde657 2014-07-09 reyk int
1545 69fde657 2014-07-09 reyk relay_httpcookie_test(struct ctl_relay_event *cre, struct relay_rule *rule,
1546 69fde657 2014-07-09 reyk struct kvlist *actions)
1547 69fde657 2014-07-09 reyk {
1548 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1549 e8d462ca 2015-07-28 reyk struct kv *kv = &rule->rule_kv[KEY_TYPE_COOKIE], key;
1550 69fde657 2014-07-09 reyk struct kv *match = NULL;
1551 265f5a08 2016-07-22 benno int res;
1552 69fde657 2014-07-09 reyk
1553 69fde657 2014-07-09 reyk if (kv->kv_type != KEY_TYPE_COOKIE)
1554 69fde657 2014-07-09 reyk return (0);
1555 69fde657 2014-07-09 reyk
1556 69fde657 2014-07-09 reyk switch (cre->dir) {
1557 69fde657 2014-07-09 reyk case RELAY_DIR_REQUEST:
1558 2d9632ee 2014-07-11 reyk key.kv_key = "Cookie";
1559 8bf959a5 2012-09-20 reyk break;
1560 69fde657 2014-07-09 reyk case RELAY_DIR_RESPONSE:
1561 2d9632ee 2014-07-11 reyk key.kv_key = "Set-Cookie";
1562 69fde657 2014-07-09 reyk break;
1563 8bf959a5 2012-09-20 reyk default:
1564 69fde657 2014-07-09 reyk return (0);
1565 69fde657 2014-07-09 reyk /* NOTREACHED */
1566 8bf959a5 2012-09-20 reyk break;
1567 8bf959a5 2012-09-20 reyk }
1568 2d9632ee 2014-07-11 reyk
1569 69fde657 2014-07-09 reyk if (kv->kv_option == KEY_OPTION_APPEND ||
1570 69fde657 2014-07-09 reyk kv->kv_option == KEY_OPTION_SET) {
1571 69fde657 2014-07-09 reyk /* no cookie, can be NULL and will be added later */
1572 69fde657 2014-07-09 reyk } else {
1573 2d9632ee 2014-07-11 reyk match = kv_find(&desc->http_headers, &key);
1574 69fde657 2014-07-09 reyk if (match == NULL)
1575 69fde657 2014-07-09 reyk return (-1);
1576 69fde657 2014-07-09 reyk if (kv->kv_key == NULL || match->kv_value == NULL)
1577 69fde657 2014-07-09 reyk return (0);
1578 265f5a08 2016-07-22 benno else if ((res = relay_lookup_cookie(cre, match->kv_value,
1579 265f5a08 2016-07-22 benno kv)) != 0)
1580 265f5a08 2016-07-22 benno return (res);
1581 69fde657 2014-07-09 reyk }
1582 8bf959a5 2012-09-20 reyk
1583 69fde657 2014-07-09 reyk relay_match(actions, kv, match, &desc->http_headers);
1584 69fde657 2014-07-09 reyk
1585 69fde657 2014-07-09 reyk return (0);
1586 69fde657 2014-07-09 reyk }
1587 69fde657 2014-07-09 reyk
1588 69fde657 2014-07-09 reyk int
1589 69fde657 2014-07-09 reyk relay_match_actions(struct ctl_relay_event *cre, struct relay_rule *rule,
1590 b8764354 2019-05-13 reyk struct kvlist *matches, struct kvlist *actions, struct relay_table **tbl)
1591 69fde657 2014-07-09 reyk {
1592 69fde657 2014-07-09 reyk struct rsession *con = cre->con;
1593 c3aaa0ba 2020-09-04 bket struct kv *kv;
1594 69fde657 2014-07-09 reyk
1595 69fde657 2014-07-09 reyk /*
1596 69fde657 2014-07-09 reyk * Apply the following options instantly (action per match).
1597 69fde657 2014-07-09 reyk */
1598 d9d7e708 2019-07-13 chrisz if (rule->rule_table != NULL) {
1599 b8764354 2019-05-13 reyk *tbl = rule->rule_table;
1600 d9d7e708 2019-07-13 chrisz con->se_out.ss.ss_family = AF_UNSPEC;
1601 d9d7e708 2019-07-13 chrisz }
1602 69fde657 2014-07-09 reyk if (rule->rule_tag != 0)
1603 69fde657 2014-07-09 reyk con->se_tag = rule->rule_tag == -1 ? 0 : rule->rule_tag;
1604 69fde657 2014-07-09 reyk if (rule->rule_label != 0)
1605 69fde657 2014-07-09 reyk con->se_label = rule->rule_label == -1 ? 0 : rule->rule_label;
1606 69fde657 2014-07-09 reyk
1607 69fde657 2014-07-09 reyk /*
1608 69fde657 2014-07-09 reyk * Apply the remaining options once after evaluation.
1609 69fde657 2014-07-09 reyk */
1610 69fde657 2014-07-09 reyk if (matches == NULL) {
1611 69fde657 2014-07-09 reyk /* 'pass' or 'block' rule */
1612 c3aaa0ba 2020-09-04 bket TAILQ_CONCAT(actions, &rule->rule_kvlist, kv_rule_entry);
1613 69fde657 2014-07-09 reyk } else {
1614 69fde657 2014-07-09 reyk /* 'match' rule */
1615 69fde657 2014-07-09 reyk TAILQ_FOREACH(kv, matches, kv_match_entry) {
1616 2d9632ee 2014-07-11 reyk TAILQ_INSERT_TAIL(actions, kv, kv_action_entry);
1617 69fde657 2014-07-09 reyk }
1618 69fde657 2014-07-09 reyk }
1619 69fde657 2014-07-09 reyk
1620 69fde657 2014-07-09 reyk return (0);
1621 69fde657 2014-07-09 reyk }
1622 69fde657 2014-07-09 reyk
1623 69fde657 2014-07-09 reyk int
1624 b8764354 2019-05-13 reyk relay_apply_actions(struct ctl_relay_event *cre, struct kvlist *actions,
1625 b8764354 2019-05-13 reyk struct relay_table *tbl)
1626 69fde657 2014-07-09 reyk {
1627 69fde657 2014-07-09 reyk struct rsession *con = cre->con;
1628 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1629 69fde657 2014-07-09 reyk struct kv *host = NULL;
1630 69fde657 2014-07-09 reyk const char *value;
1631 2d9632ee 2014-07-11 reyk struct kv *kv, *match, *kp, *mp, kvcopy, matchcopy, key;
1632 d498e80a 2021-01-09 denis int addkv, ret, nstrip;
1633 69fde657 2014-07-09 reyk char buf[IBUF_READ_SIZE], *ptr;
1634 c72024a8 2014-07-13 benno char *msg = NULL;
1635 c72024a8 2014-07-13 benno const char *meth = NULL;
1636 69fde657 2014-07-09 reyk
1637 b3458fc2 2014-07-10 reyk memset(&kvcopy, 0, sizeof(kvcopy));
1638 b3458fc2 2014-07-10 reyk memset(&matchcopy, 0, sizeof(matchcopy));
1639 b3458fc2 2014-07-10 reyk
1640 69fde657 2014-07-09 reyk ret = -1;
1641 69fde657 2014-07-09 reyk kp = mp = NULL;
1642 2d9632ee 2014-07-11 reyk TAILQ_FOREACH(kv, actions, kv_action_entry) {
1643 69fde657 2014-07-09 reyk kp = NULL;
1644 69fde657 2014-07-09 reyk match = kv->kv_match;
1645 2d9632ee 2014-07-11 reyk addkv = 0;
1646 69fde657 2014-07-09 reyk
1647 8bf959a5 2012-09-20 reyk /*
1648 69fde657 2014-07-09 reyk * Although marked as deleted, give a chance to non-critical
1649 69fde657 2014-07-09 reyk * actions, ie. log, to be performed
1650 8bf959a5 2012-09-20 reyk */
1651 69fde657 2014-07-09 reyk if (match != NULL && (match->kv_flags & KV_FLAG_INVALID))
1652 69fde657 2014-07-09 reyk goto matchdel;
1653 69fde657 2014-07-09 reyk
1654 69fde657 2014-07-09 reyk switch (kv->kv_option) {
1655 69fde657 2014-07-09 reyk case KEY_OPTION_APPEND:
1656 69fde657 2014-07-09 reyk case KEY_OPTION_SET:
1657 69fde657 2014-07-09 reyk switch (kv->kv_type) {
1658 69fde657 2014-07-09 reyk case KEY_TYPE_PATH:
1659 69fde657 2014-07-09 reyk if (kv->kv_option == KEY_OPTION_APPEND) {
1660 69fde657 2014-07-09 reyk if (kv_setkey(match, "%s%s",
1661 69fde657 2014-07-09 reyk match->kv_key, kv->kv_key) == -1)
1662 69fde657 2014-07-09 reyk goto fail;
1663 69fde657 2014-07-09 reyk } else {
1664 69fde657 2014-07-09 reyk if (kv_setkey(match, "%s",
1665 69fde657 2014-07-09 reyk kv->kv_value) == -1)
1666 69fde657 2014-07-09 reyk goto fail;
1667 69fde657 2014-07-09 reyk }
1668 69fde657 2014-07-09 reyk break;
1669 69fde657 2014-07-09 reyk case KEY_TYPE_COOKIE:
1670 69fde657 2014-07-09 reyk kp = &kvcopy;
1671 69fde657 2014-07-09 reyk if (kv_inherit(kp, kv) == NULL)
1672 69fde657 2014-07-09 reyk goto fail;
1673 69fde657 2014-07-09 reyk if (kv_set(kp, "%s=%s;", kp->kv_key,
1674 69fde657 2014-07-09 reyk kp->kv_value) == -1)
1675 69fde657 2014-07-09 reyk goto fail;
1676 2d9632ee 2014-07-11 reyk if (kv_setkey(kp, "%s", cre->dir ==
1677 2d9632ee 2014-07-11 reyk RELAY_DIR_REQUEST ?
1678 2d9632ee 2014-07-11 reyk "Cookie" : "Set-Cookie") == -1)
1679 69fde657 2014-07-09 reyk goto fail;
1680 69fde657 2014-07-09 reyk /* FALLTHROUGH cookie is a header */
1681 69fde657 2014-07-09 reyk case KEY_TYPE_HEADER:
1682 69fde657 2014-07-09 reyk if (match == NULL) {
1683 69fde657 2014-07-09 reyk addkv = 1;
1684 69fde657 2014-07-09 reyk break;
1685 69fde657 2014-07-09 reyk }
1686 69fde657 2014-07-09 reyk if (match->kv_value == NULL ||
1687 69fde657 2014-07-09 reyk kv->kv_option == KEY_OPTION_SET) {
1688 69fde657 2014-07-09 reyk if (kv_set(match, "%s",
1689 69fde657 2014-07-09 reyk kv->kv_value) == -1)
1690 69fde657 2014-07-09 reyk goto fail;
1691 4bec380a 2014-07-12 benno } else
1692 4bec380a 2014-07-12 benno addkv = 1;
1693 69fde657 2014-07-09 reyk break;
1694 69fde657 2014-07-09 reyk default:
1695 69fde657 2014-07-09 reyk /* query, url not supported */
1696 69fde657 2014-07-09 reyk break;
1697 69fde657 2014-07-09 reyk }
1698 69fde657 2014-07-09 reyk break;
1699 69fde657 2014-07-09 reyk case KEY_OPTION_REMOVE:
1700 69fde657 2014-07-09 reyk switch (kv->kv_type) {
1701 69fde657 2014-07-09 reyk case KEY_TYPE_PATH:
1702 69fde657 2014-07-09 reyk if (kv_setkey(match, "/") == -1)
1703 69fde657 2014-07-09 reyk goto fail;
1704 69fde657 2014-07-09 reyk break;
1705 69fde657 2014-07-09 reyk case KEY_TYPE_COOKIE:
1706 69fde657 2014-07-09 reyk case KEY_TYPE_HEADER:
1707 2d9632ee 2014-07-11 reyk if (kv->kv_matchtree != NULL)
1708 69fde657 2014-07-09 reyk match->kv_flags |= KV_FLAG_INVALID;
1709 69fde657 2014-07-09 reyk else
1710 69fde657 2014-07-09 reyk kv_free(match);
1711 69fde657 2014-07-09 reyk match = kv->kv_match = NULL;
1712 69fde657 2014-07-09 reyk break;
1713 69fde657 2014-07-09 reyk default:
1714 69fde657 2014-07-09 reyk /* query and url not supported */
1715 69fde657 2014-07-09 reyk break;
1716 69fde657 2014-07-09 reyk }
1717 69fde657 2014-07-09 reyk break;
1718 69fde657 2014-07-09 reyk case KEY_OPTION_HASH:
1719 69fde657 2014-07-09 reyk switch (kv->kv_type) {
1720 69fde657 2014-07-09 reyk case KEY_TYPE_PATH:
1721 69fde657 2014-07-09 reyk value = match->kv_key;
1722 69fde657 2014-07-09 reyk break;
1723 69fde657 2014-07-09 reyk default:
1724 69fde657 2014-07-09 reyk value = match->kv_value;
1725 69fde657 2014-07-09 reyk break;
1726 69fde657 2014-07-09 reyk }
1727 3e04b122 2014-12-18 reyk SipHash24_Update(&con->se_siphashctx,
1728 3e04b122 2014-12-18 reyk value, strlen(value));
1729 69fde657 2014-07-09 reyk break;
1730 69fde657 2014-07-09 reyk case KEY_OPTION_LOG:
1731 69fde657 2014-07-09 reyk /* perform this later */
1732 69fde657 2014-07-09 reyk break;
1733 d498e80a 2021-01-09 denis case KEY_OPTION_STRIP:
1734 d498e80a 2021-01-09 denis nstrip = strtonum(kv->kv_value, 0, INT_MAX, NULL);
1735 d498e80a 2021-01-09 denis if (kv->kv_type == KEY_TYPE_PATH) {
1736 e4d9aa92 2021-07-25 benno if (kv_setkey(match, "%s",
1737 d498e80a 2021-01-09 denis server_root_strip(match->kv_key,
1738 d498e80a 2021-01-09 denis nstrip)) == -1)
1739 d498e80a 2021-01-09 denis goto fail;
1740 d498e80a 2021-01-09 denis }
1741 d498e80a 2021-01-09 denis break;
1742 69fde657 2014-07-09 reyk default:
1743 09e53fee 2017-05-28 benno fatalx("%s: invalid action", __func__);
1744 69fde657 2014-07-09 reyk /* NOTREACHED */
1745 8bf959a5 2012-09-20 reyk }
1746 8bf959a5 2012-09-20 reyk
1747 69fde657 2014-07-09 reyk /* from now on, reads from kp writes to kv */
1748 69fde657 2014-07-09 reyk if (kp == NULL)
1749 69fde657 2014-07-09 reyk kp = kv;
1750 2d9632ee 2014-07-11 reyk if (addkv && kv->kv_matchtree != NULL) {
1751 69fde657 2014-07-09 reyk /* Add new entry to the list (eg. new HTTP header) */
1752 2d9632ee 2014-07-11 reyk if ((match = kv_add(kv->kv_matchtree, kp->kv_key,
1753 4e975be3 2016-07-27 reyk kp->kv_value, 0)) == NULL)
1754 69fde657 2014-07-09 reyk goto fail;
1755 69fde657 2014-07-09 reyk match->kv_option = kp->kv_option;
1756 69fde657 2014-07-09 reyk match->kv_type = kp->kv_type;
1757 69fde657 2014-07-09 reyk kv->kv_match = match;
1758 69fde657 2014-07-09 reyk }
1759 69fde657 2014-07-09 reyk if (match != NULL && kp->kv_flags & KV_FLAG_MACRO) {
1760 69fde657 2014-07-09 reyk bzero(buf, sizeof(buf));
1761 69fde657 2014-07-09 reyk if ((ptr = relay_expand_http(cre, kp->kv_value, buf,
1762 69fde657 2014-07-09 reyk sizeof(buf))) == NULL)
1763 69fde657 2014-07-09 reyk goto fail;
1764 e4d9aa92 2021-07-25 benno if (kv_set(match, "%s", ptr) == -1)
1765 69fde657 2014-07-09 reyk goto fail;
1766 69fde657 2014-07-09 reyk }
1767 2d9632ee 2014-07-11 reyk
1768 69fde657 2014-07-09 reyk matchdel:
1769 63e504f7 2015-01-22 reyk switch (kv->kv_option) {
1770 69fde657 2014-07-09 reyk case KEY_OPTION_LOG:
1771 69fde657 2014-07-09 reyk if (match == NULL)
1772 69fde657 2014-07-09 reyk break;
1773 69fde657 2014-07-09 reyk mp = &matchcopy;
1774 69fde657 2014-07-09 reyk if (kv_inherit(mp, match) == NULL)
1775 69fde657 2014-07-09 reyk goto fail;
1776 69fde657 2014-07-09 reyk if (mp->kv_flags & KV_FLAG_INVALID) {
1777 d33dfa99 2014-07-10 bluhm if (kv_set(mp, "%s (removed)",
1778 63e504f7 2015-01-22 reyk mp->kv_value) == -1)
1779 69fde657 2014-07-09 reyk goto fail;
1780 69fde657 2014-07-09 reyk }
1781 63e504f7 2015-01-22 reyk switch (kv->kv_type) {
1782 69fde657 2014-07-09 reyk case KEY_TYPE_URL:
1783 2d9632ee 2014-07-11 reyk key.kv_key = "Host";
1784 2d9632ee 2014-07-11 reyk host = kv_find(&desc->http_headers, &key);
1785 69fde657 2014-07-09 reyk switch (kv->kv_digest) {
1786 69fde657 2014-07-09 reyk case DIGEST_NONE:
1787 69fde657 2014-07-09 reyk if (host == NULL ||
1788 69fde657 2014-07-09 reyk host->kv_value == NULL)
1789 69fde657 2014-07-09 reyk break;
1790 69fde657 2014-07-09 reyk if (kv_setkey(mp, "%s%s",
1791 69fde657 2014-07-09 reyk host->kv_value, mp->kv_key) ==
1792 69fde657 2014-07-09 reyk -1)
1793 69fde657 2014-07-09 reyk goto fail;
1794 69fde657 2014-07-09 reyk break;
1795 69fde657 2014-07-09 reyk default:
1796 69fde657 2014-07-09 reyk if (kv_setkey(mp, "%s", kv->kv_key)
1797 69fde657 2014-07-09 reyk == -1)
1798 69fde657 2014-07-09 reyk goto fail;
1799 69fde657 2014-07-09 reyk break;
1800 69fde657 2014-07-09 reyk }
1801 69fde657 2014-07-09 reyk break;
1802 69fde657 2014-07-09 reyk default:
1803 69fde657 2014-07-09 reyk break;
1804 69fde657 2014-07-09 reyk }
1805 c72024a8 2014-07-13 benno if (kv_log(con, mp, con->se_label, cre->dir)
1806 c72024a8 2014-07-13 benno == -1)
1807 69fde657 2014-07-09 reyk goto fail;
1808 69fde657 2014-07-09 reyk break;
1809 69fde657 2014-07-09 reyk default:
1810 69fde657 2014-07-09 reyk break;
1811 69fde657 2014-07-09 reyk }
1812 8bf959a5 2012-09-20 reyk
1813 69fde657 2014-07-09 reyk /* actions applied, cleanup kv */
1814 69fde657 2014-07-09 reyk kv->kv_match = NULL;
1815 2d9632ee 2014-07-11 reyk kv->kv_matchtree = NULL;
1816 69fde657 2014-07-09 reyk TAILQ_REMOVE(actions, kv, kv_match_entry);
1817 8bf959a5 2012-09-20 reyk
1818 69fde657 2014-07-09 reyk kv_free(&kvcopy);
1819 b3458fc2 2014-07-10 reyk kv_free(&matchcopy);
1820 8bf959a5 2012-09-20 reyk }
1821 8bf959a5 2012-09-20 reyk
1822 c72024a8 2014-07-13 benno /*
1823 b8764354 2019-05-13 reyk * Change the backend if the forward table has been changed.
1824 b8764354 2019-05-13 reyk * This only works in the request direction.
1825 b8764354 2019-05-13 reyk */
1826 b8764354 2019-05-13 reyk if (cre->dir == RELAY_DIR_REQUEST && con->se_table != tbl) {
1827 b8764354 2019-05-13 reyk relay_reset_event(con, &con->se_out);
1828 b8764354 2019-05-13 reyk con->se_table = tbl;
1829 b8764354 2019-05-13 reyk con->se_haslog = 1;
1830 b8764354 2019-05-13 reyk }
1831 b8764354 2019-05-13 reyk
1832 b8764354 2019-05-13 reyk /*
1833 c72024a8 2014-07-13 benno * log tag for request and response, request method
1834 c72024a8 2014-07-13 benno * and end of request marker ","
1835 c72024a8 2014-07-13 benno */
1836 c72024a8 2014-07-13 benno if ((con->se_log != NULL) &&
1837 c72024a8 2014-07-13 benno ((meth = relay_httpmethod_byid(desc->http_method)) != NULL) &&
1838 b8764354 2019-05-13 reyk (asprintf(&msg, " %s", meth) != -1))
1839 c72024a8 2014-07-13 benno evbuffer_add(con->se_log, msg, strlen(msg));
1840 c72024a8 2014-07-13 benno free(msg);
1841 c72024a8 2014-07-13 benno relay_log(con, cre->dir == RELAY_DIR_REQUEST ? "" : ";");
1842 69fde657 2014-07-09 reyk ret = 0;
1843 8bf959a5 2012-09-20 reyk fail:
1844 69fde657 2014-07-09 reyk kv_free(&kvcopy);
1845 69fde657 2014-07-09 reyk kv_free(&matchcopy);
1846 69fde657 2014-07-09 reyk
1847 69fde657 2014-07-09 reyk return (ret);
1848 8bf959a5 2012-09-20 reyk }
1849 69fde657 2014-07-09 reyk
1850 69fde657 2014-07-09 reyk #define RELAY_GET_SKIP_STEP(i) \
1851 69fde657 2014-07-09 reyk do { \
1852 69fde657 2014-07-09 reyk r = r->rule_skip[i]; \
1853 69fde657 2014-07-09 reyk DPRINTF("%s:%d: skip %d rules", __func__, __LINE__, i); \
1854 69fde657 2014-07-09 reyk } while (0)
1855 69fde657 2014-07-09 reyk
1856 69fde657 2014-07-09 reyk #define RELAY_GET_NEXT_STEP \
1857 69fde657 2014-07-09 reyk do { \
1858 69fde657 2014-07-09 reyk DPRINTF("%s:%d: next rule", __func__, __LINE__); \
1859 69fde657 2014-07-09 reyk goto nextrule; \
1860 69fde657 2014-07-09 reyk } while (0)
1861 69fde657 2014-07-09 reyk
1862 69fde657 2014-07-09 reyk int
1863 69fde657 2014-07-09 reyk relay_test(struct protocol *proto, struct ctl_relay_event *cre)
1864 69fde657 2014-07-09 reyk {
1865 69fde657 2014-07-09 reyk struct rsession *con;
1866 69fde657 2014-07-09 reyk struct http_descriptor *desc = cre->desc;
1867 69fde657 2014-07-09 reyk struct relay_rule *r = NULL, *rule = NULL;
1868 b8764354 2019-05-13 reyk struct relay_table *tbl = NULL;
1869 69fde657 2014-07-09 reyk u_int action = RES_PASS;
1870 69fde657 2014-07-09 reyk struct kvlist actions, matches;
1871 69fde657 2014-07-09 reyk struct kv *kv;
1872 265f5a08 2016-07-22 benno int res = 0;
1873 69fde657 2014-07-09 reyk
1874 69fde657 2014-07-09 reyk con = cre->con;
1875 69fde657 2014-07-09 reyk TAILQ_INIT(&actions);
1876 69fde657 2014-07-09 reyk
1877 69fde657 2014-07-09 reyk r = TAILQ_FIRST(&proto->rules);
1878 69fde657 2014-07-09 reyk while (r != NULL) {
1879 69fde657 2014-07-09 reyk TAILQ_INIT(&matches);
1880 69fde657 2014-07-09 reyk TAILQ_INIT(&r->rule_kvlist);
1881 265f5a08 2016-07-22 benno
1882 69fde657 2014-07-09 reyk if (r->rule_dir && r->rule_dir != cre->dir)
1883 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_DIR);
1884 69fde657 2014-07-09 reyk else if (proto->type != r->rule_proto)
1885 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_PROTO);
1886 fc2c091b 2019-05-10 reyk else if (RELAY_AF_NEQ(r->rule_af, cre->ss.ss_family) ||
1887 fc2c091b 2019-05-10 reyk RELAY_AF_NEQ(r->rule_af, cre->dst->ss.ss_family))
1888 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_AF);
1889 69fde657 2014-07-09 reyk else if (RELAY_ADDR_CMP(&r->rule_src, &cre->ss) != 0)
1890 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_SRC);
1891 fc2c091b 2019-05-10 reyk else if (RELAY_ADDR_CMP(&r->rule_dst, &con->se_sockname) != 0)
1892 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_DST);
1893 69fde657 2014-07-09 reyk else if (r->rule_method != HTTP_METHOD_NONE &&
1894 69fde657 2014-07-09 reyk (desc->http_method == HTTP_METHOD_RESPONSE ||
1895 69fde657 2014-07-09 reyk desc->http_method != r->rule_method))
1896 69fde657 2014-07-09 reyk RELAY_GET_SKIP_STEP(RULE_SKIP_METHOD);
1897 69fde657 2014-07-09 reyk else if (r->rule_tagged && con->se_tag != r->rule_tagged)
1898 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1899 69fde657 2014-07-09 reyk else if (relay_httpheader_test(cre, r, &matches) != 0)
1900 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1901 265f5a08 2016-07-22 benno else if ((res = relay_httpquery_test(cre, r, &matches)) != 0)
1902 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1903 69fde657 2014-07-09 reyk else if (relay_httppath_test(cre, r, &matches) != 0)
1904 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1905 265f5a08 2016-07-22 benno else if ((res = relay_httpurl_test(cre, r, &matches)) != 0)
1906 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1907 265f5a08 2016-07-22 benno else if ((res = relay_httpcookie_test(cre, r, &matches)) != 0)
1908 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1909 69fde657 2014-07-09 reyk else {
1910 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: matched rule %d",
1911 69fde657 2014-07-09 reyk __func__, con->se_id, r->rule_id);
1912 69fde657 2014-07-09 reyk
1913 69fde657 2014-07-09 reyk if (r->rule_action == RULE_ACTION_MATCH) {
1914 69fde657 2014-07-09 reyk if (relay_match_actions(cre, r, &matches,
1915 b8764354 2019-05-13 reyk &actions, &tbl) != 0) {
1916 69fde657 2014-07-09 reyk /* Something bad happened, drop */
1917 69fde657 2014-07-09 reyk action = RES_DROP;
1918 69fde657 2014-07-09 reyk break;
1919 69fde657 2014-07-09 reyk }
1920 69fde657 2014-07-09 reyk RELAY_GET_NEXT_STEP;
1921 69fde657 2014-07-09 reyk } else if (r->rule_action == RULE_ACTION_BLOCK)
1922 69fde657 2014-07-09 reyk action = RES_DROP;
1923 69fde657 2014-07-09 reyk else if (r->rule_action == RULE_ACTION_PASS)
1924 69fde657 2014-07-09 reyk action = RES_PASS;
1925 69fde657 2014-07-09 reyk
1926 69fde657 2014-07-09 reyk /* Rule matched */
1927 69fde657 2014-07-09 reyk rule = r;
1928 69fde657 2014-07-09 reyk
1929 69fde657 2014-07-09 reyk /* Temporarily save actions */
1930 69fde657 2014-07-09 reyk TAILQ_FOREACH(kv, &matches, kv_match_entry) {
1931 69fde657 2014-07-09 reyk TAILQ_INSERT_TAIL(&rule->rule_kvlist,
1932 69fde657 2014-07-09 reyk kv, kv_rule_entry);
1933 69fde657 2014-07-09 reyk }
1934 69fde657 2014-07-09 reyk
1935 69fde657 2014-07-09 reyk if (rule->rule_flags & RULE_FLAG_QUICK)
1936 69fde657 2014-07-09 reyk break;
1937 69fde657 2014-07-09 reyk
1938 69fde657 2014-07-09 reyk nextrule:
1939 69fde657 2014-07-09 reyk /* Continue to find last matching policy */
1940 265f5a08 2016-07-22 benno DPRINTF("%s: session %d, res %d", __func__,
1941 265f5a08 2016-07-22 benno con->se_id, res);
1942 265f5a08 2016-07-22 benno if (res == RES_BAD || res == RES_INTERNAL)
1943 04adeb63 2016-09-26 reyk return (res);
1944 265f5a08 2016-07-22 benno res = 0;
1945 dab2f2be 2016-08-01 benno r = TAILQ_NEXT(r, rule_entry);
1946 69fde657 2014-07-09 reyk }
1947 69fde657 2014-07-09 reyk }
1948 69fde657 2014-07-09 reyk
1949 b8764354 2019-05-13 reyk if (rule != NULL && relay_match_actions(cre, rule, NULL, &actions, &tbl)
1950 dab2f2be 2016-08-01 benno != 0) {
1951 69fde657 2014-07-09 reyk /* Something bad happened, drop */
1952 69fde657 2014-07-09 reyk action = RES_DROP;
1953 69fde657 2014-07-09 reyk }
1954 69fde657 2014-07-09 reyk
1955 b8764354 2019-05-13 reyk if (relay_apply_actions(cre, &actions, tbl) != 0) {
1956 69fde657 2014-07-09 reyk /* Something bad happened, drop */
1957 69fde657 2014-07-09 reyk action = RES_DROP;
1958 69fde657 2014-07-09 reyk }
1959 69fde657 2014-07-09 reyk
1960 69fde657 2014-07-09 reyk DPRINTF("%s: session %d: action %d", __func__,
1961 69fde657 2014-07-09 reyk con->se_id, action);
1962 69fde657 2014-07-09 reyk
1963 69fde657 2014-07-09 reyk return (action);
1964 69fde657 2014-07-09 reyk }
1965 69fde657 2014-07-09 reyk
1966 69fde657 2014-07-09 reyk #define RELAY_SET_SKIP_STEPS(i) \
1967 69fde657 2014-07-09 reyk do { \
1968 69fde657 2014-07-09 reyk while (head[i] != cur) { \
1969 69fde657 2014-07-09 reyk head[i]->rule_skip[i] = cur; \
1970 69fde657 2014-07-09 reyk head[i] = TAILQ_NEXT(head[i], rule_entry); \
1971 69fde657 2014-07-09 reyk } \
1972 69fde657 2014-07-09 reyk } while (0)
1973 69fde657 2014-07-09 reyk
1974 69fde657 2014-07-09 reyk /* This code is derived from pf_calc_skip_steps() from pf.c */
1975 69fde657 2014-07-09 reyk void
1976 69fde657 2014-07-09 reyk relay_calc_skip_steps(struct relay_rules *rules)
1977 69fde657 2014-07-09 reyk {
1978 69fde657 2014-07-09 reyk struct relay_rule *head[RULE_SKIP_COUNT], *cur, *prev;
1979 69fde657 2014-07-09 reyk int i;
1980 69fde657 2014-07-09 reyk
1981 69fde657 2014-07-09 reyk cur = TAILQ_FIRST(rules);
1982 69fde657 2014-07-09 reyk prev = cur;
1983 69fde657 2014-07-09 reyk for (i = 0; i < RULE_SKIP_COUNT; ++i)
1984 69fde657 2014-07-09 reyk head[i] = cur;
1985 69fde657 2014-07-09 reyk while (cur != NULL) {
1986 69fde657 2014-07-09 reyk if (cur->rule_dir != prev->rule_dir)
1987 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_DIR);
1988 69fde657 2014-07-09 reyk else if (cur->rule_proto != prev->rule_proto)
1989 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_PROTO);
1990 fc2c091b 2019-05-10 reyk else if (RELAY_AF_NEQ(cur->rule_af, prev->rule_af))
1991 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_AF);
1992 69fde657 2014-07-09 reyk else if (RELAY_ADDR_NEQ(&cur->rule_src, &prev->rule_src))
1993 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_SRC);
1994 69fde657 2014-07-09 reyk else if (RELAY_ADDR_NEQ(&cur->rule_dst, &prev->rule_dst))
1995 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_DST);
1996 69fde657 2014-07-09 reyk else if (cur->rule_method != prev->rule_method)
1997 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(RULE_SKIP_METHOD);
1998 69fde657 2014-07-09 reyk
1999 69fde657 2014-07-09 reyk prev = cur;
2000 69fde657 2014-07-09 reyk cur = TAILQ_NEXT(cur, rule_entry);
2001 69fde657 2014-07-09 reyk }
2002 69fde657 2014-07-09 reyk for (i = 0; i < RULE_SKIP_COUNT; ++i)
2003 69fde657 2014-07-09 reyk RELAY_SET_SKIP_STEPS(i);
2004 69fde657 2014-07-09 reyk }
2005 69fde657 2014-07-09 reyk
2006 69fde657 2014-07-09 reyk void
2007 69fde657 2014-07-09 reyk relay_match(struct kvlist *actions, struct kv *kv, struct kv *match,
2008 2d9632ee 2014-07-11 reyk struct kvtree *matchtree)
2009 69fde657 2014-07-09 reyk {
2010 69fde657 2014-07-09 reyk if (kv->kv_option != KEY_OPTION_NONE) {
2011 69fde657 2014-07-09 reyk kv->kv_match = match;
2012 2d9632ee 2014-07-11 reyk kv->kv_matchtree = matchtree;
2013 69fde657 2014-07-09 reyk TAILQ_INSERT_TAIL(actions, kv, kv_match_entry);
2014 69fde657 2014-07-09 reyk }
2015 69fde657 2014-07-09 reyk }
2016 d498e80a 2021-01-09 denis
2017 d498e80a 2021-01-09 denis char *
2018 d498e80a 2021-01-09 denis server_root_strip(char *path, int n)
2019 d498e80a 2021-01-09 denis {
2020 d498e80a 2021-01-09 denis char *p;
2021 d498e80a 2021-01-09 denis
2022 d498e80a 2021-01-09 denis /* Strip strip leading directories. Leading '/' is ignored. */
2023 d498e80a 2021-01-09 denis for (; n > 0 && *path != '\0'; n--)
2024 d498e80a 2021-01-09 denis if ((p = strchr(++path, '/')) != NULL)
2025 d498e80a 2021-01-09 denis path = p;
2026 d498e80a 2021-01-09 denis else
2027 d498e80a 2021-01-09 denis path--;
2028 d498e80a 2021-01-09 denis
2029 d498e80a 2021-01-09 denis return (path);
2030 d498e80a 2021-01-09 denis }
2031 d498e80a 2021-01-09 denis
2032 192c004f 2026-03-08 rsadowski /*
2033 192c004f 2026-03-08 rsadowski * Handle the first line of an HTTP message (Request- or Status-Line).
2034 192c004f 2026-03-08 rsadowski */
2035 192c004f 2026-03-08 rsadowski int
2036 192c004f 2026-03-08 rsadowski relay_http_parse_startline(struct ctl_relay_event *cre, char *line,
2037 192c004f 2026-03-08 rsadowski enum httpmethod *request_method)
2038 192c004f 2026-03-08 rsadowski {
2039 192c004f 2026-03-08 rsadowski struct rsession *con = cre->con;
2040 192c004f 2026-03-08 rsadowski struct http_descriptor *desc = cre->desc;
2041 192c004f 2026-03-08 rsadowski struct http_session *hs = con->se_priv;
2042 192c004f 2026-03-08 rsadowski struct http_method_node *hmn;
2043 192c004f 2026-03-08 rsadowski char *key, *value;
2044 192c004f 2026-03-08 rsadowski const char *errstr;
2045 192c004f 2026-03-08 rsadowski
2046 192c004f 2026-03-08 rsadowski DPRINTF("%s: session %d http_session %p", __func__, con->se_id, hs);
2047 192c004f 2026-03-08 rsadowski
2048 192c004f 2026-03-08 rsadowski key = line;
2049 192c004f 2026-03-08 rsadowski if ((value = strchr(key, ' ')) == NULL) {
2050 192c004f 2026-03-08 rsadowski relay_abort_http(con, 400, "malformed", 0);
2051 192c004f 2026-03-08 rsadowski return (-1);
2052 192c004f 2026-03-08 rsadowski }
2053 192c004f 2026-03-08 rsadowski *value++ = '\0';
2054 192c004f 2026-03-08 rsadowski
2055 192c004f 2026-03-08 rsadowski if (cre->dir == RELAY_DIR_RESPONSE) {
2056 192c004f 2026-03-08 rsadowski desc->http_method = HTTP_METHOD_RESPONSE;
2057 192c004f 2026-03-08 rsadowski hmn = SIMPLEQ_FIRST(&hs->hs_methods);
2058 192c004f 2026-03-08 rsadowski
2059 192c004f 2026-03-08 rsadowski /*
2060 192c004f 2026-03-08 rsadowski * There is nothing preventing the relay from
2061 192c004f 2026-03-08 rsadowski * sending an unbalanced response. Be prepared.
2062 192c004f 2026-03-08 rsadowski */
2063 192c004f 2026-03-08 rsadowski if (hmn == NULL) {
2064 192c004f 2026-03-08 rsadowski *request_method = HTTP_METHOD_NONE;
2065 192c004f 2026-03-08 rsadowski DPRINTF("%s: session %d unbalanced response",
2066 192c004f 2026-03-08 rsadowski __func__, con->se_id);
2067 192c004f 2026-03-08 rsadowski } else {
2068 192c004f 2026-03-08 rsadowski SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
2069 192c004f 2026-03-08 rsadowski *request_method = hmn->hmn_method;
2070 192c004f 2026-03-08 rsadowski DPRINTF("%s: session %d dequeuing %s",
2071 192c004f 2026-03-08 rsadowski __func__, con->se_id,
2072 192c004f 2026-03-08 rsadowski relay_httpmethod_byid(*request_method));
2073 192c004f 2026-03-08 rsadowski free(hmn);
2074 192c004f 2026-03-08 rsadowski }
2075 192c004f 2026-03-08 rsadowski
2076 192c004f 2026-03-08 rsadowski /*
2077 192c004f 2026-03-08 rsadowski * Decode response path and query
2078 192c004f 2026-03-08 rsadowski */
2079 192c004f 2026-03-08 rsadowski desc->http_version = strdup(key);
2080 192c004f 2026-03-08 rsadowski if (desc->http_version == NULL)
2081 192c004f 2026-03-08 rsadowski goto fail;
2082 192c004f 2026-03-08 rsadowski
2083 192c004f 2026-03-08 rsadowski desc->http_rescode = strdup(value);
2084 192c004f 2026-03-08 rsadowski if (desc->http_rescode == NULL)
2085 192c004f 2026-03-08 rsadowski goto fail;
2086 192c004f 2026-03-08 rsadowski
2087 192c004f 2026-03-08 rsadowski desc->http_resmesg = strchr(desc->http_rescode, ' ');
2088 192c004f 2026-03-08 rsadowski if (desc->http_resmesg == NULL)
2089 192c004f 2026-03-08 rsadowski goto fail;
2090 192c004f 2026-03-08 rsadowski
2091 192c004f 2026-03-08 rsadowski *desc->http_resmesg++ = '\0';
2092 192c004f 2026-03-08 rsadowski desc->http_resmesg = strdup(desc->http_resmesg);
2093 192c004f 2026-03-08 rsadowski if (desc->http_resmesg == NULL)
2094 192c004f 2026-03-08 rsadowski goto fail;
2095 192c004f 2026-03-08 rsadowski
2096 192c004f 2026-03-08 rsadowski desc->http_status = strtonum(desc->http_rescode, 100, 599,
2097 192c004f 2026-03-08 rsadowski &errstr);
2098 192c004f 2026-03-08 rsadowski if (errstr) {
2099 192c004f 2026-03-08 rsadowski DPRINTF(
2100 192c004f 2026-03-08 rsadowski "%s: http_status %s: errno %d, %s",
2101 192c004f 2026-03-08 rsadowski __func__, desc->http_rescode, errno,
2102 192c004f 2026-03-08 rsadowski errstr);
2103 192c004f 2026-03-08 rsadowski goto fail;
2104 192c004f 2026-03-08 rsadowski }
2105 192c004f 2026-03-08 rsadowski DPRINTF("http_version %s http_rescode %s http_resmesg %s",
2106 192c004f 2026-03-08 rsadowski desc->http_version, desc->http_rescode,
2107 192c004f 2026-03-08 rsadowski desc->http_resmesg);
2108 192c004f 2026-03-08 rsadowski } else if (cre->dir == RELAY_DIR_REQUEST) {
2109 192c004f 2026-03-08 rsadowski desc->http_method = relay_httpmethod_byname(key);
2110 192c004f 2026-03-08 rsadowski
2111 192c004f 2026-03-08 rsadowski if (desc->http_method == HTTP_METHOD_NONE)
2112 192c004f 2026-03-08 rsadowski goto fail;
2113 192c004f 2026-03-08 rsadowski
2114 192c004f 2026-03-08 rsadowski if ((hmn = calloc(1, sizeof *hmn)) == NULL)
2115 192c004f 2026-03-08 rsadowski goto fail;
2116 192c004f 2026-03-08 rsadowski hmn->hmn_method = desc->http_method;
2117 192c004f 2026-03-08 rsadowski DPRINTF("%s: session %d enqueuing %s", __func__, con->se_id,
2118 192c004f 2026-03-08 rsadowski relay_httpmethod_byid(hmn->hmn_method));
2119 192c004f 2026-03-08 rsadowski SIMPLEQ_INSERT_TAIL(&hs->hs_methods, hmn, hmn_entry);
2120 192c004f 2026-03-08 rsadowski /*
2121 192c004f 2026-03-08 rsadowski * Decode request path and query
2122 192c004f 2026-03-08 rsadowski */
2123 192c004f 2026-03-08 rsadowski desc->http_path = strdup(value);
2124 192c004f 2026-03-08 rsadowski if (desc->http_path == NULL)
2125 192c004f 2026-03-08 rsadowski goto fail;
2126 192c004f 2026-03-08 rsadowski
2127 192c004f 2026-03-08 rsadowski desc->http_version = strchr(desc->http_path, ' ');
2128 192c004f 2026-03-08 rsadowski if (desc->http_version == NULL)
2129 192c004f 2026-03-08 rsadowski goto fail;
2130 192c004f 2026-03-08 rsadowski
2131 192c004f 2026-03-08 rsadowski *desc->http_version++ = '\0';
2132 192c004f 2026-03-08 rsadowski desc->http_query = strchr(desc->http_path, '?');
2133 192c004f 2026-03-08 rsadowski if (desc->http_query != NULL)
2134 192c004f 2026-03-08 rsadowski *desc->http_query++ = '\0';
2135 192c004f 2026-03-08 rsadowski
2136 192c004f 2026-03-08 rsadowski /*
2137 192c004f 2026-03-08 rsadowski * Have to allocate the strings because they
2138 192c004f 2026-03-08 rsadowski * could be changed independently by the
2139 192c004f 2026-03-08 rsadowski * filters later.
2140 192c004f 2026-03-08 rsadowski */
2141 192c004f 2026-03-08 rsadowski if ((desc->http_version = strdup(desc->http_version)) == NULL)
2142 192c004f 2026-03-08 rsadowski goto fail;
2143 192c004f 2026-03-08 rsadowski
2144 192c004f 2026-03-08 rsadowski if (desc->http_query != NULL && (desc->http_query =
2145 192c004f 2026-03-08 rsadowski strdup(desc->http_query)) == NULL)
2146 192c004f 2026-03-08 rsadowski goto fail;
2147 192c004f 2026-03-08 rsadowski }
2148 192c004f 2026-03-08 rsadowski return (0);
2149 192c004f 2026-03-08 rsadowski fail:
2150 192c004f 2026-03-08 rsadowski relay_abort_http(con, 500, strerror(errno), 0);
2151 192c004f 2026-03-08 rsadowski return (-1);
2152 192c004f 2026-03-08 rsadowski }