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 301820
HTTP1_Complete(struct http_conn *htc)
67
{
68
        char *p;
69
        enum htc_status_e retval;
70
71 301820
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
72 301820
        AN(WS_Reservation(htc->ws));
73 301820
        assert(pdiff(htc->rxbuf_b, htc->rxbuf_e) <= WS_ReservationSize(htc->ws));
74
75
        /* Skip any leading white space */
76 302597
        for (p = htc->rxbuf_b ; p < htc->rxbuf_e && vct_islws(*p); p++)
77 777
                continue;
78 301820
        if (p == htc->rxbuf_e)
79 163843
                return (HTC_S_EMPTY);
80
81
        /* Do not return a partial H2 connection preface */
82 137977
        retval = H2_prism_complete(htc);
83 137977
        if (retval != HTC_S_JUNK)
84 6342
                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 474054
        while (1) {
91 474054
                p = vmemchr(p, '\n', htc->rxbuf_e - p);
92 474054
                if (p == NULL)
93 7761
                        return (HTC_S_MORE);
94 466293
                if (++p == htc->rxbuf_e)
95 687
                        return (HTC_S_MORE);
96 465606
                if (*p == '\r' && ++p == htc->rxbuf_e)
97 105
                        return (HTC_S_MORE);
98 465501
                if (*p == '\n')
99 123082
                        break;
100
        }
101 123082
        return (HTC_S_COMPLETE);
102 301820
}
103
104
/*--------------------------------------------------------------------
105
 * Report garbage and return the error argument
106
 */
107
static inline uint16_t
108 294
http1_garbage(struct http *hp, struct http_conn *htc, const char *p, uint16_t status)
109
{
110
111 294
        if (p == NULL || htc->rxbuf_b == NULL)
112 0
                return (status);
113 588
        VSLb(hp->vsl, SLT_HttpGarbage, "%.*s",
114 294
            (int)pdiff(p, htc->rxbuf_e), p);
115 294
        return (status);
116 294
}
117
118
/*--------------------------------------------------------------------
119
 * Dissect the headers of the HTTP protocol message.
120
 */
121
122
static uint16_t
123 123003
http1_dissect_hdrs(struct http *hp, struct http_conn *htc, char *p,
124
    unsigned maxhdr)
125
{
126
        char *q, *r, *s;
127
        int i;
128
129 123003
        assert(p > htc->rxbuf_b);
130 123003
        assert(p <= htc->rxbuf_e);
131 123003
        hp->nhd = HTTP_HDR_FIRST;
132 123003
        r = NULL;               /* For FlexeLint */
133 458321
        for (; p < htc->rxbuf_e; p = r) {
134
135
                /* Find end of next header */
136 458318
                q = r = p;
137 458318
                if (vct_iscrlf(p, htc->rxbuf_e))
138 122574
                        break;
139 6670206
                while (r < htc->rxbuf_e) {
140 6670191
                        if (vct_ishdrval(*r)) {
141 6334275
                                r++;
142 6334275
                                continue;
143
                        }
144 335916
                        i = vct_iscrlf(r, htc->rxbuf_e);
145 335916
                        if (i == 0) {
146
                                // b00040.vtc
147 210
                                VSLb(hp->vsl, SLT_BogoHeader,
148 105
                                    "Header has ctrl char 0x%02x", *r);
149 105
                                return (http1_garbage(hp, htc, p, 400));
150
                        }
151 335811
                        q = r;
152 335811
                        r += i;
153 335811
                        assert(r <= htc->rxbuf_e);
154 335811
                        if (r == htc->rxbuf_e)
155 0
                                break;
156 335811
                        if (vct_iscrlf(r, htc->rxbuf_e))
157 122411
                                break;
158
                        /* If line does not continue: got it. */
159 213400
                        if (!vct_issp(*r))
160 213211
                                break;
161
162
                        /* Clear line continuation LWS to spaces */
163 378
                        while (q < r)
164 189
                                *q++ = ' ';
165 399
                        while (q < htc->rxbuf_e && vct_issp(*q))
166 210
                                *q++ = ' ';
167
                }
168
169
                /* Empty header = end of headers */
170 335637
                if (p == q)
171 0
                        break;
172
173 335629
                if (q - p > maxhdr) {
174
                        // c00039.vtc
175 168
                        VSLb(hp->vsl, SLT_BogoHeader, "Header too long: %.*s",
176 84
                            (int)(q - p > 20 ? 20 : q - p), p);
177 84
                        return (400);
178
                }
179
180 335545
                if (vct_islws(*p)) {
181
                        // b00040.vtc
182 84
                        VSLb(hp->vsl, SLT_BogoHeader,
183
                            "1st header has white space: %.*s",
184 42
                            (int)(q - p > 20 ? 20 : q - p), p);
185 42
                        return (400);
186
                }
187
188 335503
                if (*p == ':') {
189
                        // b00040.vtc
190 42
                        VSLb(hp->vsl, SLT_BogoHeader,
191
                            "Missing header name: %.*s",
192 21
                            (int)(q - p > 20 ? 20 : q - p), p);
193 21
                        return (400);
194
                }
195
196 335860
                while (q > p && vct_issp(q[-1]))
197 378
                        q--;
198 335444
                *q = '\0';
199
200 2919163
                for (s = p; *s != ':' && s < q; s++) {
201 2583824
                        if (!vct_istchar(*s)) {
202 210
                                VSLb(hp->vsl, SLT_BogoHeader,
203 105
                                    "Illegal char 0x%02x in header name", *s);
204 105
                                return (400);
205
                        }
206 2583719
                }
207 335339
                if (*s != ':') {
208 42
                        VSLb(hp->vsl, SLT_BogoHeader, "Header without ':' %.*s",
209 21
                            (int)(q - p > 20 ? 20 : q - p), p);
210 21
                        return (400);
211
                }
212
213 335318
                if (hp->nhd < hp->shd) {
214 335318
                        hp->hdf[hp->nhd] = 0;
215 335318
                        hp->hd[hp->nhd].b = p;
216 335318
                        hp->hd[hp->nhd].e = q;
217 335318
                        hp->nhd++;
218 335318
                } else {
219 0
                        VSLb(hp->vsl, SLT_BogoHeader, "Too many headers: %.*s",
220 0
                            (int)(q - p > 20 ? 20 : q - p), p);
221 0
                        return (400);
222
                }
223 335318
        }
224 122577
        i = vct_iscrlf(p, htc->rxbuf_e);
225 122577
        assert(i > 0);          /* HTTP1_Complete guarantees this */
226 122571
        p += i;
227 122571
        HTC_RxPipeline(htc, p);
228 122571
        htc->rxbuf_e = p;
229 122571
        return (0);
230 122949
}
231
232
/*--------------------------------------------------------------------
233
 * Deal with first line of HTTP protocol message.
234
 */
235
236
static uint16_t
237 123077
http1_splitline(struct http *hp, struct http_conn *htc, const int *hf,
238
    unsigned maxhdr)
239
{
240
        char *p, *q;
241
        int i;
242
243 123077
        assert(hf == HTTP1_Req || hf == HTTP1_Resp);
244 123077
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
245 123077
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
246 123077
        assert(htc->rxbuf_e >= htc->rxbuf_b);
247
248 123077
        AZ(hp->hd[hf[0]].b);
249 123077
        AZ(hp->hd[hf[1]].b);
250 123077
        AZ(hp->hd[hf[2]].b);
251
252
        /* Skip leading LWS */
253 123182
        for (p = htc->rxbuf_b ; vct_islws(*p); p++)
254 105
                continue;
255 123077
        hp->hd[hf[0]].b = p;
256
257
        /* First field cannot contain SP or CTL */
258 731785
        for (; !vct_issp(*p); p++) {
259 608792
                if (vct_isctl(*p))
260 84
                        return (http1_garbage(hp, htc, hp->hd[hf[0]].b, 400));
261 608708
        }
262 122993
        hp->hd[hf[0]].e = p;
263 122993
        assert(Tlen(hp->hd[hf[0]]));
264 122993
        *p++ = '\0';
265
266
        /* Skip SP */
267 123119
        for (; vct_issp(*p); p++) {
268 126
                if (vct_isctl(*p))
269 0
                        return (http1_garbage(hp, htc, hp->hd[hf[0]].e + 1, 400));
270 126
        }
271 122993
        hp->hd[hf[1]].b = p;
272
273
        /* Second field cannot contain LWS or CTL */
274 839324
        for (; !vct_islws(*p); p++) {
275 716331
                if (vct_isctl(*p))
276 0
                        return (http1_garbage(hp, htc, hp->hd[hf[1]].b, 400));
277 716331
        }
278 122993
        hp->hd[hf[1]].e = p;
279 122993
        if (!Tlen(hp->hd[hf[1]]))
280 21
                return (http1_garbage(hp, htc, hp->hd[hf[1]].b, 400));
281
282
        /* Skip SP */
283 122972
        q = p;
284 245793
        for (; vct_issp(*p); p++) {
285 122821
                if (vct_isctl(*p))
286 0
                        return (http1_garbage(hp, htc, q, 400));
287 122821
        }
288 122972
        if (q < p)
289 122797
                *q = '\0';      /* Nul guard for the 2nd field. If q == p
290
                                 * (the third optional field is not
291
                                 * present), the last nul guard will
292
                                 * cover this field. */
293
294
        /* Third field is optional and cannot contain CTL except TAB */
295 122972
        q = p;
296 827112
        for (; p < htc->rxbuf_e && !vct_iscrlf(p, htc->rxbuf_e); p++) {
297 704161
                if (vct_isctl(*p) && !vct_issp(*p))
298 21
                        return (http1_garbage(hp, htc, q, 400));
299 704140
        }
300 122945
        if (p > q) {
301 122714
                hp->hd[hf[2]].b = q;
302 122714
                hp->hd[hf[2]].e = p;
303 122714
        }
304
305
        /* Skip CRLF */
306 122945
        i = vct_iscrlf(p, htc->rxbuf_e);
307 122945
        if (!i)
308 0
                return (http1_garbage(hp, htc, p, 400));
309 122945
        *p = '\0';
310 122945
        p += i;
311
312 122945
        http_Proto(hp);
313
314 122945
        return (http1_dissect_hdrs(hp, htc, p, maxhdr));
315 123071
}
316
317
/*--------------------------------------------------------------------*/
318
319
static body_status_t
320 122045
http1_body_status(struct http *hp, struct http_conn *htc, int request)
321
{
322
        ssize_t cl;
323
        const char *b;
324
325 122045
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
326 122045
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
327
328 122045
        htc->content_length = -1;
329
330 122045
        cl = http_GetContentLength(hp);
331 122045
        if (cl == -2) {
332
                /* RFC 9110 8.6, no length to be had */
333 210
                VSLb(hp->vsl, SLT_BogoHeader, "Invalid Content-Length");
334 210
                return (BS_ERROR);
335
        }
336 121835
        if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
337 5459
                if (!http_coding_eq(b, chunked)) {
338
                        /* RFC 9112 6.1 unimplemented transfer coding */
339 63
                        VSLb(hp->vsl, SLT_BogoHeader,
340
                            "Transfer-Encoding is not chunked");
341 63
                        return (BS_ERROR);
342
                }
343 5396
                if (cl != -1) {
344
                        /* RFC 9112 6.3 is more lenient, we are strict */
345 42
                        VSLb(hp->vsl, SLT_BogoHeader,
346
                            "Transfer-Encoding with Content-Length");
347 42
                        return (BS_ERROR);
348
                }
349 5354
                if (http_CountHdr(hp, H_Transfer_Encoding) > 1) {
350
                        /* RFC 9110 5.3, the checks above saw only the first */
351 42
                        VSLb(hp->vsl, SLT_BogoHeader,
352
                            "Multiple Transfer-Encoding: headers");
353 42
                        return (BS_ERROR);
354
                }
355 5312
                if (request && hp->protover < 11) {
356
                        /* RFC 9112 6.1 faulty framing */
357 21
                        VSLb(hp->vsl, SLT_BogoHeader,
358
                            "Transfer-Encoding on HTTP/1.0 request");
359 21
                        return (BS_ERROR);
360
                }
361 5291
                return (BS_CHUNKED);
362
        }
363 116376
        if (cl >= 0) {
364 45233
                htc->content_length = cl;
365 45233
                return (cl == 0 ? BS_NONE : BS_LENGTH);
366
        }
367
368 71143
        if (hp->protover == 11 && request)
369 70051
                return (BS_NONE);
370
371 1092
        if (http_HdrIs(hp, H_Connection, "keep-alive")) {
372
                /*
373
                 * Keep alive with neither TE=Chunked or C-Len is impossible.
374
                 * We assume a zero length body.
375
                 */
376 84
                return (BS_NONE);
377
        }
378
379
        /*
380
         * Fall back to EOF transfer.
381
         */
382 1008
        return (BS_EOF);
383 122045
}
384
385
/*--------------------------------------------------------------------*/
386
387
uint16_t
388 76521
HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
389
{
390
        uint16_t retval;
391 76521
        const char *b = NULL, *e;
392 76521
        char c = '\0';
393
394 76521
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
395 76521
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
396
397 153042
        retval = http1_splitline(hp, htc,
398 76521
            HTTP1_Req, cache_param->http_req_hdr_len);
399 76521
        if (retval != 0)
400 336
                return (retval);
401
402 76185
        if (hp->protover < 10 || hp->protover > 11)
403 252
                return (400);
404
405 75933
        http_SetWellKnownMethod(hp);
406
407 75933
        VSLbt(hp->vsl, SLT_ReqTarget, hp->hd[HTTP_HDR_URL]);
408
409
        /* RFC2616, section 5.2, point 1 */
410 75933
        if (http_scheme_at(hp->hd[HTTP_HDR_URL].b, http))
411 189
                b = hp->hd[HTTP_HDR_URL].b + 7;
412 75744
        else if (FEATURE(FEATURE_HTTPS_SCHEME) &&
413 75725
            http_scheme_at(hp->hd[HTTP_HDR_URL].b, https))
414 63
                b = hp->hd[HTTP_HDR_URL].b + 8;
415 75933
        if (b) {
416 252
                VSC_C_main->http1_absolute_form++;
417 252
                e = strpbrk(b, "/?");
418 252
                if (e == NULL)
419 105
                        e = hp->hd[HTTP_HDR_URL].e;
420
                else
421 147
                        c = *e;
422 252
                if (e == b) {
423
                        // rfc9110 4.2.1 4.2.2 reject empty host
424 63
                        return (http1_garbage(hp, htc, hp->hd[HTTP_HDR_URL].b, 400));
425
                }
426 189
                http_Unset(hp, H_Host);
427 189
                http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b);
428 189
                hp->hd[HTTP_HDR_URL].b = e;
429 189
                if (Tlen(hp->hd[HTTP_HDR_URL]) == 0) {
430
                        // empty path
431 63
                        if (http_method_eq(hp->wkm, WKM_OPTIONS))
432 21
                                hp->hd[HTTP_HDR_URL] = Tstr("*");
433
                        else
434 42
                                hp->hd[HTTP_HDR_URL] = Tstr("/");
435 189
                } else if (c == '?') {
436 21
                        hp->hd[HTTP_HDR_URL].b--;
437 21
                        char *t = TRUST_ME(hp->hd[HTTP_HDR_URL].b);
438 21
                        *t = '/';
439 21
                }
440 189
        }
441
442 75870
        htc->body_status = http1_body_status(hp, htc, 1);
443 75870
        if (htc->body_status == BS_ERROR)
444 273
                return (400);
445
446 75597
        if (htc->body_status == BS_EOF) {
447 336
                assert(hp->protover == 10);
448
                /* RFC1945 8.3 p32 and D.1.1 p58 */
449 336
                if (http_method_among(hp->wkm, (WKM_POST | WKM_PUT)))
450 42
                        return (400);
451 294
                htc->body_status = BS_NONE;
452 294
        }
453
454
        /* HEAD with a body is a hard error */
455 75555
        if (htc->body_status != BS_NONE && http_method_eq(hp->wkm, WKM_HEAD))
456 0
                return (400);
457
458 75555
        return (retval);
459 76521
}
460
461
/*--------------------------------------------------------------------*/
462
463
uint16_t
464 46557
HTTP1_DissectResponse(struct http_conn *htc, struct http *hp,
465
    const struct http *rhttp)
466
{
467 46557
        uint16_t retval = 0;
468
        const char *p;
469
470 46557
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
471 46557
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
472 46557
        CHECK_OBJ_NOTNULL(rhttp, HTTP_MAGIC);
473
474 93114
        if (http1_splitline(hp, htc,
475 46557
            HTTP1_Resp, cache_param->http_resp_hdr_len))
476 168
                retval = 503;
477
478 46557
        if (retval == 0 && hp->protover < 10)
479 0
                retval = 503;
480
481 46557
        if (retval == 0 && hp->protover > rhttp->protover)
482 21
                http_SetH(hp, HTTP_HDR_PROTO, rhttp->hd[HTTP_HDR_PROTO].b);
483
484 46557
        if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
485 63
                retval = 503;
486
487 46557
        if (retval == 0) {
488 46324
                p = hp->hd[HTTP_HDR_STATUS].b;
489
490 92522
                if (p[0] >= '1' && p[0] <= '9' &&
491 46261
                    p[1] >= '0' && p[1] <= '9' &&
492 46219
                    p[2] >= '0' && p[2] <= '9')
493 46177
                        hp->status =
494 46177
                            100 * (p[0] - '0') + 10 * (p[1] - '0') + p[2] - '0';
495
                else
496 147
                        retval = 503;
497 46324
        }
498
499 46557
        if (retval != 0) {
500 756
                VSLb(hp->vsl, SLT_HttpGarbage, "%.*s",
501 378
                    (int)(htc->rxbuf_e - htc->rxbuf_b), htc->rxbuf_b);
502 378
        }
503
504 46557
        if (retval == 0)
505 46177
                htc->body_status = http1_body_status(hp, htc, 0);
506
507 46557
        if (retval == 0 && htc->body_status == BS_ERROR)
508 105
                retval = 503;
509
510 46557
        if (retval != 0) {
511 483
                assert(retval == 503);
512 483
                http_SetStatus(hp, 503, NULL);
513 483
        }
514
515 46557
        if (hp->hd[HTTP_HDR_REASON].b == NULL ||
516 46513
            !Tlen(hp->hd[HTTP_HDR_REASON])) {
517 92
                http_SetH(hp, HTTP_HDR_REASON,
518 46
                    http_Status2Reason(hp->status, NULL));
519 46
        }
520
521 46553
        return (retval);
522
}
523
524
/*--------------------------------------------------------------------*/
525
526
static unsigned
527 1245040
http1_WrTxt(struct v1l *v1l, const txt *hh, const char *suf)
528
{
529
        unsigned u;
530
531 1245040
        AN(hh);
532 1245040
        AN(hh->b);
533 1245040
        AN(hh->e);
534 1245040
        u = V1L_Write(v1l, hh->b, hh->e - hh->b);
535 1245040
        if (suf != NULL)
536 1245057
                u += V1L_Write(v1l, suf, -1);
537 1245142
        return (u);
538
}
539
540
unsigned
541 118028
HTTP1_Write(struct v1l *v1l, const struct http *hp, const int *hf)
542
{
543
        unsigned u, l;
544
545 118028
        assert(hf == HTTP1_Req || hf == HTTP1_Resp);
546 118028
        AN(hp->hd[hf[0]].b);
547 118028
        AN(hp->hd[hf[1]].b);
548 118028
        AN(hp->hd[hf[2]].b);
549 118028
        l = http1_WrTxt(v1l, &hp->hd[hf[0]], " ");
550 118028
        l += http1_WrTxt(v1l, &hp->hd[hf[1]], " ");
551 118028
        l += http1_WrTxt(v1l, &hp->hd[hf[2]], "\r\n");
552
553 1009327
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++)
554 891299
                l += http1_WrTxt(v1l, &hp->hd[u], "\r\n");
555 118028
        l += V1L_Write(v1l, "\r\n", -1);
556 118028
        return (l);
557
}