vinyl-cache/bin/vinyld/http1/cache_http1_proto.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * HTTP protocol requests
31
 *
32
 * The trouble with the "until magic sequence" design of HTTP protocol messages
33
 * is that either you have to read a single character at a time, which is
34
 * inefficient, or you risk reading too much, and pre-read some of the object,
35
 * or even the next pipelined request, which follows the one you want.
36
 *
37
 * HTC reads a HTTP protocol header into a workspace, subject to limits,
38
 * and stops when we see the magic marker (double [CR]NL), and if we overshoot,
39
 * it keeps track of the "pipelined" data.
40
 *
41
 * We use this both for client and backend connections.
42
 */
43
44
#include "config.h"
45
46
#include "cache/cache_int.h"
47
#include "cache/cache_transport.h"
48
49
#include "cache_http1.h"
50
51
#include "vct.h"
52
53
const int HTTP1_Req[3] = {
54
        HTTP_HDR_METHOD, HTTP_HDR_URL, HTTP_HDR_PROTO
55
};
56
57
const int HTTP1_Resp[3] = {
58
        HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_REASON
59
};
60
61
/*--------------------------------------------------------------------
62
 * Check if we have a complete HTTP request or response yet
63
 */
64
65
enum htc_status_e v_matchproto_(htc_complete_f)
66 54169
HTTP1_Complete(struct http_conn *htc)
67
{
68
        char *p;
69
        enum htc_status_e retval;
70
71 54169
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
72 54169
        AN(WS_Reservation(htc->ws));
73 54169
        assert(pdiff(htc->rxbuf_b, htc->rxbuf_e) <= WS_ReservationSize(htc->ws));
74
75
        /* Skip any leading white space */
76 54317
        for (p = htc->rxbuf_b ; p < htc->rxbuf_e && vct_islws(*p); p++)
77 148
                continue;
78 54169
        if (p == htc->rxbuf_e)
79 29628
                return (HTC_S_EMPTY);
80
81
        /* Do not return a partial H2 connection preface */
82 24541
        retval = H2_prism_complete(htc);
83 24541
        if (retval != HTC_S_JUNK)
84 1200
                return (retval);
85
86
        /*
87
         * Here we just look for NL[CR]NL to see that reception
88
         * is completed.  More stringent validation happens later.
89
         */
90 85070
        while (1) {
91 85070
                p = memchr(p, '\n', htc->rxbuf_e - p);
92 85070
                if (p == NULL)
93 1038
                        return (HTC_S_MORE);
94 84032
                if (++p == htc->rxbuf_e)
95 107
                        return (HTC_S_MORE);
96 83925
                if (*p == '\r' && ++p == htc->rxbuf_e)
97 12
                        return (HTC_S_MORE);
98 83913
                if (*p == '\n')
99 22184
                        break;
100
        }
101 22184
        return (HTC_S_COMPLETE);
102 54169
}
103
104
/*--------------------------------------------------------------------
105
 * Dissect the headers of the HTTP protocol message.
106
 */
107
108
static uint16_t
109 22170
http1_dissect_hdrs(struct http *hp, char *p, struct http_conn *htc,
110
    unsigned maxhdr)
111
{
112
        char *q, *r, *s;
113
        int i;
114
115 22170
        assert(p > htc->rxbuf_b);
116 22170
        assert(p <= htc->rxbuf_e);
117 22170
        hp->nhd = HTTP_HDR_FIRST;
118 22170
        r = NULL;               /* For FlexeLint */
119 82889
        for (; p < htc->rxbuf_e; p = r) {
120
121
                /* Find end of next header */
122 82889
                q = r = p;
123 82889
                if (vct_iscrlf(p, htc->rxbuf_e))
124 22092
                        break;
125 1215149
                while (r < htc->rxbuf_e) {
126 1215144
                        if (vct_ishdrval(*r)) {
127 1154316
                                r++;
128 1154316
                                continue;
129
                        }
130 60828
                        i = vct_iscrlf(r, htc->rxbuf_e);
131 60828
                        if (i == 0) {
132 32
                                VSLb(hp->vsl, SLT_BogoHeader,
133 16
                                    "Header has ctrl char 0x%02x", *r);
134 16
                                return (400);
135
                        }
136 60812
                        q = r;
137 60812
                        r += i;
138 60812
                        assert(r <= htc->rxbuf_e);
139 60812
                        if (r == htc->rxbuf_e)
140 0
                                break;
141 60812
                        if (vct_iscrlf(r, htc->rxbuf_e))
142 22060
                                break;
143
                        /* If line does not continue: got it. */
144 38752
                        if (!vct_issp(*r))
145 38716
                                break;
146
147
                        /* Clear line continuation LWS to spaces */
148 72
                        while (q < r)
149 36
                                *q++ = ' ';
150 76
                        while (q < htc->rxbuf_e && vct_issp(*q))
151 40
                                *q++ = ' ';
152
                }
153
154
                /* Empty header = end of headers */
155 60781
                if (p == q)
156 0
                        break;
157
158 60779
                if (q - p > maxhdr) {
159 32
                        VSLb(hp->vsl, SLT_BogoHeader, "Header too long: %.*s",
160 16
                            (int)(q - p > 20 ? 20 : q - p), p);
161 16
                        return (400);
162
                }
163
164 60763
                if (vct_islws(*p)) {
165 16
                        VSLb(hp->vsl, SLT_BogoHeader,
166
                            "1st header has white space: %.*s",
167 8
                            (int)(q - p > 20 ? 20 : q - p), p);
168 8
                        return (400);
169
                }
170
171 60755
                if (*p == ':') {
172 8
                        VSLb(hp->vsl, SLT_BogoHeader,
173
                            "Missing header name: %.*s",
174 4
                            (int)(q - p > 20 ? 20 : q - p), p);
175 4
                        return (400);
176
                }
177
178 60823
                while (q > p && vct_issp(q[-1]))
179 72
                        q--;
180 60743
                *q = '\0';
181
182 527078
                for (s = p; *s != ':' && s < q; s++) {
183 466355
                        if (!vct_istchar(*s)) {
184 40
                                VSLb(hp->vsl, SLT_BogoHeader,
185 20
                                    "Illegal char 0x%02x in header name", *s);
186 20
                                return (400);
187
                        }
188 466335
                }
189 60723
                if (*s != ':') {
190 8
                        VSLb(hp->vsl, SLT_BogoHeader, "Header without ':' %.*s",
191 4
                            (int)(q - p > 20 ? 20 : q - p), p);
192 4
                        return (400);
193
                }
194
195 60719
                if (hp->nhd < hp->shd) {
196 60719
                        hp->hdf[hp->nhd] = 0;
197 60719
                        hp->hd[hp->nhd].b = p;
198 60719
                        hp->hd[hp->nhd].e = q;
199 60719
                        hp->nhd++;
200 60719
                } else {
201 0
                        VSLb(hp->vsl, SLT_BogoHeader, "Too many headers: %.*s",
202 0
                            (int)(q - p > 20 ? 20 : q - p), p);
203 0
                        return (400);
204
                }
205 60719
        }
206 22092
        i = vct_iscrlf(p, htc->rxbuf_e);
207 22092
        assert(i > 0);          /* HTTP1_Complete guarantees this */
208 22092
        p += i;
209 22092
        HTC_RxPipeline(htc, p);
210 22092
        htc->rxbuf_e = p;
211 22092
        return (0);
212 22160
}
213
214
/*--------------------------------------------------------------------
215
 * Deal with first line of HTTP protocol message.
216
 */
217
218
static uint16_t
219 22183
http1_splitline(struct http *hp, struct http_conn *htc, const int *hf,
220
    unsigned maxhdr)
221
{
222
        char *p, *q;
223
        int i;
224
225 22183
        assert(hf == HTTP1_Req || hf == HTTP1_Resp);
226 22183
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
227 22183
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
228 22183
        assert(htc->rxbuf_e >= htc->rxbuf_b);
229
230 22183
        AZ(hp->hd[hf[0]].b);
231 22183
        AZ(hp->hd[hf[1]].b);
232 22183
        AZ(hp->hd[hf[2]].b);
233
234
        /* Skip leading LWS */
235 22203
        for (p = htc->rxbuf_b ; vct_islws(*p); p++)
236 20
                continue;
237 22183
        hp->hd[hf[0]].b = p;
238
239
        /* First field cannot contain SP or CTL */
240 132720
        for (; !vct_issp(*p); p++) {
241 110553
                if (vct_isctl(*p))
242 16
                        return (400);
243 110537
        }
244 22167
        hp->hd[hf[0]].e = p;
245 22167
        assert(Tlen(hp->hd[hf[0]]));
246 22167
        *p++ = '\0';
247
248
        /* Skip SP */
249 22191
        for (; vct_issp(*p); p++) {
250 24
                if (vct_isctl(*p))
251 0
                        return (400);
252 24
        }
253 22167
        hp->hd[hf[1]].b = p;
254
255
        /* Second field cannot contain LWS or CTL */
256 156320
        for (; !vct_islws(*p); p++) {
257 134153
                if (vct_isctl(*p))
258 0
                        return (400);
259 134153
        }
260 22167
        hp->hd[hf[1]].e = p;
261 22167
        if (!Tlen(hp->hd[hf[1]]))
262 4
                return (400);
263
264
        /* Skip SP */
265 22163
        q = p;
266 44299
        for (; vct_issp(*p); p++) {
267 22136
                if (vct_isctl(*p))
268 0
                        return (400);
269 22136
        }
270 22163
        if (q < p)
271 22131
                *q = '\0';      /* Nul guard for the 2nd field. If q == p
272
                                 * (the third optional field is not
273
                                 * present), the last nul guard will
274
                                 * cover this field. */
275
276
        /* Third field is optional and cannot contain CTL except TAB */
277 22163
        q = p;
278 148120
        for (; p < htc->rxbuf_e && !vct_iscrlf(p, htc->rxbuf_e); p++) {
279 125961
                if (vct_isctl(*p) && !vct_issp(*p))
280 4
                        return (400);
281 125957
        }
282 22159
        if (p > q) {
283 22115
                hp->hd[hf[2]].b = q;
284 22115
                hp->hd[hf[2]].e = p;
285 22115
        }
286
287
        /* Skip CRLF */
288 22159
        i = vct_iscrlf(p, htc->rxbuf_e);
289 22159
        if (!i)
290 0
                return (400);
291 22159
        *p = '\0';
292 22159
        p += i;
293
294 22159
        http_Proto(hp);
295
296 22159
        return (http1_dissect_hdrs(hp, p, htc, maxhdr));
297 22183
}
298
299
/*--------------------------------------------------------------------*/
300
301
static body_status_t
302 22063
http1_body_status(const struct http *hp, struct http_conn *htc, int request)
303
{
304
        ssize_t cl;
305
        const char *b;
306
307 22063
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
308 22063
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
309
310 22063
        htc->content_length = -1;
311
312 22063
        cl = http_GetContentLength(hp);
313 22063
        if (cl == -2)
314 16
                return (BS_ERROR);
315 22047
        if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
316 716
                if (!http_coding_eq(b, chunked))
317 8
                        return (BS_ERROR);
318 708
                if (cl != -1) {
319
                        /*
320
                         * RFC7230 3.3.3 allows more lenient handling
321
                         * but we're going to be strict.
322
                         */
323 8
                        return (BS_ERROR);
324
                }
325 700
                return (BS_CHUNKED);
326
        }
327 21331
        if (cl >= 0) {
328 8124
                htc->content_length = cl;
329 8124
                return (cl == 0 ? BS_NONE : BS_LENGTH);
330
        }
331
332 13207
        if (hp->protover == 11 && request)
333 12979
                return (BS_NONE);
334
335 228
        if (http_HdrIs(hp, H_Connection, "keep-alive")) {
336
                /*
337
                 * Keep alive with neither TE=Chunked or C-Len is impossible.
338
                 * We assume a zero length body.
339
                 */
340 8
                return (BS_NONE);
341
        }
342
343
        /*
344
         * Fall back to EOF transfer.
345
         */
346 220
        return (BS_EOF);
347 22063
}
348
349
/*--------------------------------------------------------------------*/
350
351
uint16_t
352 13631
HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
353
{
354
        uint16_t retval;
355 13631
        const char *b = NULL, *e;
356 13631
        char c = '\0';
357
358 13631
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
359 13631
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
360
361 27262
        retval = http1_splitline(hp, htc,
362 13631
            HTTP1_Req, cache_param->http_req_hdr_len);
363 13631
        if (retval != 0)
364 60
                return (retval);
365
366 13571
        if (hp->protover < 10 || hp->protover > 11)
367 48
                return (400);
368
369 13523
        http_SetWellKnownMethod(hp);
370
371 13523
        VSLbt(hp->vsl, SLT_ReqTarget, hp->hd[HTTP_HDR_URL]);
372
373
        /* RFC2616, section 5.2, point 1 */
374 13523
        if (http_scheme_at(hp->hd[HTTP_HDR_URL].b, http))
375 36
                b = hp->hd[HTTP_HDR_URL].b + 7;
376 13487
        else if (FEATURE(FEATURE_HTTPS_SCHEME) &&
377 13484
            http_scheme_at(hp->hd[HTTP_HDR_URL].b, https))
378 12
                b = hp->hd[HTTP_HDR_URL].b + 8;
379 13523
        if (b) {
380 48
                VSC_C_main->http1_absolute_form++;
381 48
                e = strpbrk(b, "/?");
382 48
                if (e == NULL)
383 20
                        e = hp->hd[HTTP_HDR_URL].e;
384
                else
385 28
                        c = *e;
386 48
                if (e == b) {
387
                        // rfc9110 4.2.1 4.2.2 reject empty host
388 12
                        return (400);
389
                }
390 36
                http_Unset(hp, H_Host);
391 36
                http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b);
392 36
                hp->hd[HTTP_HDR_URL].b = e;
393 36
                if (Tlen(hp->hd[HTTP_HDR_URL]) == 0) {
394
                        // empty path
395 12
                        if (http_method_eq(hp->wkm, WKM_OPTIONS))
396 4
                                hp->hd[HTTP_HDR_URL] = Tstr("*");
397
                        else
398 8
                                hp->hd[HTTP_HDR_URL] = Tstr("/");
399 36
                } else if (c == '?') {
400 4
                        hp->hd[HTTP_HDR_URL].b--;
401 4
                        char *t = TRUST_ME(hp->hd[HTTP_HDR_URL].b);
402 4
                        *t = '/';
403 4
                }
404 36
        }
405
406 13511
        htc->body_status = http1_body_status(hp, htc, 1);
407 13511
        if (htc->body_status == BS_ERROR)
408 16
                return (400);
409
410 13495
        if (htc->body_status == BS_EOF) {
411 56
                assert(hp->protover == 10);
412
                /* RFC1945 8.3 p32 and D.1.1 p58 */
413 56
                if (http_method_among(hp->wkm, (WKM_POST | WKM_PUT)))
414 8
                        return (400);
415 48
                htc->body_status = BS_NONE;
416 48
        }
417
418
        /* HEAD with a body is a hard error */
419 13487
        if (htc->body_status != BS_NONE && http_method_eq(hp->wkm, WKM_HEAD))
420 0
                return (400);
421
422 13487
        return (retval);
423 13631
}
424
425
/*--------------------------------------------------------------------*/
426
427
uint16_t
428 8552
HTTP1_DissectResponse(struct http_conn *htc, struct http *hp,
429
    const struct http *rhttp)
430
{
431 8552
        uint16_t retval = 0;
432
        const char *p;
433
434 8552
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
435 8552
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
436 8552
        CHECK_OBJ_NOTNULL(rhttp, HTTP_MAGIC);
437
438 17104
        if (http1_splitline(hp, htc,
439 8552
            HTTP1_Resp, cache_param->http_resp_hdr_len))
440 32
                retval = 503;
441
442 8552
        if (retval == 0 && hp->protover < 10)
443 0
                retval = 503;
444
445 8552
        if (retval == 0 && hp->protover > rhttp->protover)
446 4
                http_SetH(hp, HTTP_HDR_PROTO, rhttp->hd[HTTP_HDR_PROTO].b);
447
448 8552
        if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
449 12
                retval = 503;
450
451 8552
        if (retval == 0) {
452 8508
                p = hp->hd[HTTP_HDR_STATUS].b;
453
454 16992
                if (p[0] >= '1' && p[0] <= '9' &&
455 8496
                    p[1] >= '0' && p[1] <= '9' &&
456 8488
                    p[2] >= '0' && p[2] <= '9')
457 8480
                        hp->status =
458 8480
                            100 * (p[0] - '0') + 10 * (p[1] - '0') + p[2] - '0';
459
                else
460 28
                        retval = 503;
461 8508
        }
462
463 8552
        if (retval != 0) {
464 144
                VSLb(hp->vsl, SLT_HttpGarbage, "%.*s",
465 72
                    (int)(htc->rxbuf_e - htc->rxbuf_b), htc->rxbuf_b);
466 72
                assert(retval >= 100 && retval <= 999);
467 72
                assert(retval == 503);
468 72
                http_SetStatus(hp, 503, NULL);
469 72
        }
470
471 8552
        if (hp->hd[HTTP_HDR_REASON].b == NULL ||
472 8544
            !Tlen(hp->hd[HTTP_HDR_REASON])) {
473 16
                http_SetH(hp, HTTP_HDR_REASON,
474 8
                    http_Status2Reason(hp->status, NULL));
475 8
        }
476
477 8552
        htc->body_status = http1_body_status(hp, htc, 0);
478
479 8552
        return (retval);
480
}
481
482
/*--------------------------------------------------------------------*/
483
484
static unsigned
485 228029
http1_WrTxt(struct v1l *v1l, const txt *hh, const char *suf)
486
{
487
        unsigned u;
488
489 228029
        AN(hh);
490 228029
        AN(hh->b);
491 228029
        AN(hh->e);
492 228029
        u = V1L_Write(v1l, hh->b, hh->e - hh->b);
493 228029
        if (suf != NULL)
494 228029
                u += V1L_Write(v1l, suf, -1);
495 228043
        return (u);
496
}
497
498
unsigned
499 21503
HTTP1_Write(struct v1l *v1l, const struct http *hp, const int *hf)
500
{
501
        unsigned u, l;
502
503 21503
        assert(hf == HTTP1_Req || hf == HTTP1_Resp);
504 21503
        AN(hp->hd[hf[0]].b);
505 21503
        AN(hp->hd[hf[1]].b);
506 21503
        AN(hp->hd[hf[2]].b);
507 21503
        l = http1_WrTxt(v1l, &hp->hd[hf[0]], " ");
508 21503
        l += http1_WrTxt(v1l, &hp->hd[hf[1]], " ");
509 21503
        l += http1_WrTxt(v1l, &hp->hd[hf[2]], "\r\n");
510
511 185136
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++)
512 163633
                l += http1_WrTxt(v1l, &hp->hd[u], "\r\n");
513 21503
        l += V1L_Write(v1l, "\r\n", -1);
514 21503
        return (l);
515
}