varnish-cache/bin/varnishd/cache/cache_http.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2017 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 226185
 * HTTP request storage and manipulation
31 15480
 */
32 10640
33 3200
#include "config.h"
34 2520
35 2320
#include "cache_varnishd.h"
36 2320
#include <stdio.h>
37 2320
#include <stdlib.h>
38 2320
39 2280
#include "common/heritage.h"
40
41
#include "vct.h"
42
#include "vend.h"
43
#include "vnum.h"
44
#include "vtim.h"
45
46
#define BODYSTATUS(U, l, n, a, k)                               \
47
        const struct body_status BS_##U[1] = {{                 \
48
                .name = #l,                                     \
49
                .nbr = n,                                       \
50
                .avail = a,                                     \
51
                .length_known = k                               \
52
        }};
53
#include "tbl/body_status.h"
54
55
56
#define HTTPH(a, b, c) hdr_t b = HDR(a);
57
#include "tbl/http_headers.h"
58
59
hdr_t H__Status = HDR(":status");
60
hdr_t H__Proto  = HDR(":proto");
61
hdr_t H__Reason = HDR(":reason");
62
63
static char * via_hdr;
64
65
/*--------------------------------------------------------------------
66
 * Perfect hash to rapidly recognize headers from tbl/http_headers.h
67
 * which have non-zero flags.
68
 *
69
 * A suitable algorithm can be found with `gperf`:
70
 *
71
 *      tr '" ,' '   ' < include/tbl/http_headers.h |
72
 *              awk '$1 == "H(" {print $2}' |
73
 *              gperf --ignore-case
74
 *
75
 */
76
77
#define GPERF_MIN_WORD_LENGTH 2
78
#define GPERF_MAX_WORD_LENGTH 19
79
#define GPERF_MAX_HASH_VALUE 79
80
81
static const unsigned char http_asso_values[256] = {
82
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
83
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
84
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
85
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
86
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
87
        80, 80, 80,  0, 80, 80, 80, 80, 80, 80,
88
        80, 80, 80, 80, 80,  5, 80, 20,  0,  0,
89
        5, 10,  5,  5, 80,  0, 15,  0, 20, 80,
90
        40, 80,  0, 35, 10, 20, 55, 45,  0,  0,
91
        80, 80, 80, 80, 80, 80, 80,  5, 80, 20,
92
        0,  0,  5, 10,  5,  5, 80,  0, 15,  0,
93
        20, 80, 40, 80,  0, 35, 10, 20, 55, 45,
94
        0,  0, 80, 80, 80, 80, 80, 80, 80, 80,
95
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
96
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
97
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
98
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
99
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
100
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
101
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
102
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
103
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
104
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
105
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
106
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
107
        80, 80, 80, 80, 80, 80
108
};
109
110
static struct http_hdrflg {
111
        hdr_t           *hdr;
112
        unsigned        flag;
113
} http_hdrflg[GPERF_MAX_HASH_VALUE + 1] = {
114
        { NULL }, { NULL }, { NULL }, { NULL },
115
        { &H_Date },
116
        { &H_Range },
117
        { NULL },
118
        { &H_Referer },
119
        { &H_Age },
120
        { &H_From },
121
        { &H_Keep_Alive },
122
        { &H_Retry_After },
123
        { &H_TE },
124
        { &H_If_Range },
125
        { &H_ETag },
126
        { &H_X_Forwarded_For },
127
        { &H_Expect },
128
        { &H_Trailer },
129
        { &H_If_Match },
130
        { &H_Host },
131
        { &H_Accept_Language },
132
        { &H_Accept },
133
        { &H_If_Modified_Since },
134
        { &H_If_None_Match },
135
        { &H_If_Unmodified_Since },
136
        { NULL },
137
        { &H_Cookie },
138
        { &H_Upgrade },
139
        { &H_Last_Modified },
140
        { &H_Accept_Charset },
141
        { &H_Accept_Encoding },
142
        { &H_Content_MD5 },
143
        { &H_Content_Type },
144
        { &H_Content_Range },
145
        { NULL }, { NULL },
146
        { &H_Content_Language },
147
        { &H_Transfer_Encoding },
148
        { &H_Authorization },
149
        { &H_Content_Length },
150
        { &H_User_Agent },
151
        { &H_Server },
152
        { &H_Expires },
153
        { &H_Location },
154
        { NULL },
155
        { &H_Set_Cookie },
156
        { &H_Content_Encoding },
157
        { &H_Max_Forwards },
158
        { &H_Cache_Control },
159
        { NULL },
160
        { &H_Connection },
161
        { &H_Pragma },
162
        { NULL },
163
        { &H_Accept_Ranges },
164
        { &H_HTTP2_Settings },
165
        { &H_Allow },
166
        { &H_Content_Location },
167
        { NULL },
168
        { &H_Proxy_Authenticate },
169
        { &H_Vary },
170
        { NULL },
171
        { &H_WWW_Authenticate },
172
        { &H_Warning },
173
        { &H_Via },
174
        { NULL }, { NULL }, { NULL }, { NULL },
175
        { NULL }, { NULL }, { NULL }, { NULL },
176
        { NULL }, { NULL }, { NULL }, { NULL },
177
        { NULL }, { NULL }, { NULL },
178
        { &H_Proxy_Authorization }
179
};
180
181
static struct http_hdrflg *
182 3082931
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 3082931
        if (b == NULL || e == NULL)
188 314
                return (NULL);
189 3082919
        u = pdiff(b, e);
190 3082919
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
191 1400
                return (NULL);
192 6163038
        u += http_asso_values[(uint8_t)(e[-1])] +
193 3081519
             http_asso_values[(uint8_t)(b[0])];
194 3081519
        if (u > GPERF_MAX_HASH_VALUE)
195 41840
                return (NULL);
196 3039679
        retval = &http_hdrflg[u];
197 3039679
        if (retval->hdr == NULL)
198 11574
                return (NULL);
199 3028105
        AN(*retval->hdr);
200 3028105
        if (!http_hdr_at(*retval->hdr + 1, b, e - b))
201 42440
                return (NULL);
202 2985665
        return (retval);
203 3082919
}
204
205
/*--------------------------------------------------------------------*/
206
207
static void
208 1994148
http_init_hdr(hdr_t hdr, int flg)
209
{
210
        struct http_hdrflg *f;
211
212 1994148
        f = http_hdr_flags(hdr->str, hdr->str + hdr->len - 1);
213 1994148
        AN(f);
214 1994148
        assert(*f->hdr == hdr);
215 1994148
        f->flag = flg;
216 1994148
}
217
218
void
219 38349
HTTP_Init(void)
220
{
221
        struct vsb *vsb;
222
223
#define HTTPH(a, b, c) http_init_hdr(b, c);
224
#include "tbl/http_headers.h"
225
226
        vsb = VSB_new_auto();
227 38349
        AN(vsb);
228
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
229
            heritage.identity);
230 38349
        AZ(VSB_finish(vsb));
231 38349
        REPLACE(via_hdr, VSB_data(vsb));
232
        VSB_destroy(&vsb);
233
}
234
235
/*--------------------------------------------------------------------
236
 * These two functions are in an incestuous relationship with the
237
 * order of macros in include/tbl/vsl_tags_http.h
238
 *
239
 * The http->logtag is the SLT_*Method enum, and we add to that, to
240
 * get the SLT_ to use.
241
 */
242
243
static void
244 5100662
http_VSLH(const struct http *hp, unsigned hdr)
245
{
246
        int i;
247
248 5100662
        if (hp->vsl != NULL) {
249 5100851
                assert(VXID_TAG(hp->vsl->wid));
250 5100851
                i = hdr;
251 5100851
                if (i > HTTP_HDR_FIRST)
252 2685990
                        i = HTTP_HDR_FIRST;
253 5100851
                i += hp->logtag;
254 5100851
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
255 5100851
        }
256 5101068
}
257
258
static void
259 41720
http_VSLH_del(const struct http *hp, unsigned hdr)
260
{
261
        int i;
262
263 41720
        if (hp->vsl != NULL) {
264
                /* We don't support unsetting stuff in the first line */
265 41720
                assert (hdr >= HTTP_HDR_FIRST);
266 41720
                assert(VXID_TAG(hp->vsl->wid));
267 41720
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
268 41720
                i += hp->logtag;
269 41720
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
270 41720
        }
271 41720
}
272
273
/*--------------------------------------------------------------------*/
274
275
void
276 237182
http_VSL_log(const struct http *hp)
277
{
278
        unsigned u;
279
280 2072371
        for (u = 0; u < hp->nhd; u++)
281 3196105
                if (hp->hd[u].b != NULL)
282 1360916
                        http_VSLH(hp, u);
283 237182
}
284
285
/*--------------------------------------------------------------------*/
286
287
static void
288 4160
http_fail(const struct http *hp)
289
{
290
        char id[WS_ID_SIZE];
291
292 4160
        VSC_C_main->losthdr++;
293 4160
        WS_Id(hp->ws, id);
294 4160
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
295 4160
        WS_MarkOverflow(hp->ws);
296 4160
}
297
298
/*--------------------------------------------------------------------
299
 * List of canonical HTTP response code names from RFC2616
300
 */
301
302
static struct http_msg {
303
        unsigned        nbr;
304
        const char      *status;
305
        const char      *txt;
306
} http_msg[] = {
307
#define HTTP_RESP(n, t) { n, #n, t},
308
#include "tbl/http_response.h"
309
        { 0, "0", NULL }
310
};
311
312
const char *
313 60349
http_Status2Reason(unsigned status, const char **sstr)
314
{
315
        struct http_msg *mp;
316
317 60349
        status %= 1000;
318 60349
        assert(status >= 100);
319 1836697
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
320 1834897
                if (mp->nbr == status) {
321 58549
                        if (sstr)
322 44712
                                *sstr = mp->status;
323 58549
                        return (mp->txt);
324
                }
325 1800
        return ("Unknown HTTP Status");
326 60349
}
327
328
/*--------------------------------------------------------------------*/
329
330
unsigned
331 216364
HTTP_estimate(unsigned nhttp)
332
{
333
334
        /* XXX: We trust the structs to size-aligned as necessary */
335 216364
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
336
}
337
338
struct http *
339 649082
HTTP_create(void *p, uint16_t nhttp, unsigned len)
340
{
341
        struct http *hp;
342
343 649082
        hp = p;
344 649082
        hp->magic = HTTP_MAGIC;
345 649082
        hp->hd = (void*)(hp + 1);
346 649082
        hp->shd = nhttp;
347 649082
        hp->hdf = (void*)(hp->hd + nhttp);
348 649082
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
349 649082
        return (hp);
350
}
351
352
/*--------------------------------------------------------------------*/
353
354
void
355 605874
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
356
    enum VSL_tag_e  whence)
357
{
358 605874
        http_Teardown(hp);
359 605874
        hp->nhd = HTTP_HDR_FIRST;
360 605874
        hp->logtag = whence;
361 605874
        hp->ws = ws;
362 605874
        hp->vsl = vsl;
363 605874
        hp->wkm = WKM_UNKNOWN;
364 605874
}
365
366
/*--------------------------------------------------------------------
367
 * http_Teardown() is a safety feature, we use it to zap all http
368
 * structs once we're done with them, to minimize the risk that
369
 * old stale pointers exist to no longer valid stuff.
370
 */
371
372
void
373 945770
http_Teardown(struct http *hp)
374
{
375
376 945770
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
377 945770
        AN(hp->shd);
378 945770
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
379 945770
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
380 945770
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
381 945770
}
382
383
/*--------------------------------------------------------------------
384
 * Duplicate the http content into another http
385
 * We cannot just memcpy the struct because the hd & hdf are private
386
 * storage to the struct http.
387
 */
388
389
void
390 265796
HTTP_Dup(struct http *to, const struct http * fm)
391
{
392
393 265796
        assert(fm->nhd <= to->shd);
394 265796
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
395 265796
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
396 265796
        to->nhd = fm->nhd;
397 265796
        to->logtag = fm->logtag;
398 265796
        to->status = fm->status;
399 265796
        to->protover = fm->protover;
400 265796
        to->wkm = fm->wkm;
401 265796
}
402
403
404
/*--------------------------------------------------------------------
405
 * Clone the entire http structure, including vsl & ws
406
 */
407
408
void
409 251156
HTTP_Clone(struct http *to, const struct http * const fm)
410
{
411
412 251156
        HTTP_Dup(to, fm);
413 251156
        to->vsl = fm->vsl;
414 251156
        to->ws = fm->ws;
415 251156
}
416
417
/*--------------------------------------------------------------------*/
418
419
void
420 271451
http_Proto(struct http *to)
421
{
422
        const char *fm;
423
424 271451
        fm = to->hd[HTTP_HDR_PROTO].b;
425
426 542545
        if (fm != NULL &&
427 271138
            (fm[0] == 'H' || fm[0] == 'h') &&
428 271105
            (fm[1] == 'T' || fm[1] == 't') &&
429 271097
            (fm[2] == 'T' || fm[2] == 't') &&
430 271097
            (fm[3] == 'P' || fm[3] == 'p') &&
431 271097
            fm[4] == '/' &&
432 271097
            vct_isdigit(fm[5]) &&
433 271092
            fm[6] == '.' &&
434 271093
            vct_isdigit(fm[7]) &&
435 271094
            fm[8] == '\0') {
436 271095
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
437 271095
        } else {
438 360
                to->protover = 0;
439
        }
440 271455
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 1617799
http_SetH(struct http *to, unsigned n, const char *header)
446
{
447
448 1617799
        assert(n < to->nhd);
449 1617799
        AN(header);
450 1617799
        to->hd[n].b = TRUST_ME(header);
451 1617799
        to->hd[n].e = strchr(to->hd[n].b, '\0');
452 1617799
        to->hdf[n] = 0;
453 1617799
        http_VSLH(to, n);
454 1617799
        if (n == HTTP_HDR_PROTO)
455 55516
                http_Proto(to);
456 1617799
        if (n == HTTP_HDR_METHOD)
457 1360
                http_SetWellKnownMethod(to);
458 1617799
}
459
460
/*--------------------------------------------------------------------*/
461
462
static void
463 1440
http_PutField(struct http *to, int field, const char *string)
464
{
465
        const char *p;
466
467 1440
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
468 1440
        p = WS_Copy(to->ws, string, -1);
469 1440
        if (p == NULL) {
470 40
                http_fail(to);
471 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
472 40
                return;
473
        }
474 1400
        http_SetH(to, field, p);
475 1440
}
476
477
/*--------------------------------------------------------------------*/
478
479
int
480 5900270
http_IsHdr(const txt *hh, hdr_t hdr)
481
{
482
483 5900270
        Tcheck(*hh);
484 5900270
        CHECK_HDR(hdr);
485 5900270
        return (http_hdr_at(hdr->str, hh->b, hdr->len));
486
}
487
488
/*--------------------------------------------------------------------*/
489
490
static unsigned
491 6086502
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
492
{
493
        unsigned u;
494
495 26440111
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
496 21703462
                Tcheck(hp->hd[u]);
497 21703462
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
498 3913328
                        continue;
499 17790134
                if (hp->hd[u].b[l] != ':')
500 14958787
                        continue;
501 2831347
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
502 1481494
                        continue;
503 1349853
                return (u);
504
        }
505 4736649
        return (0);
506 6086502
}
507
508
/*--------------------------------------------------------------------
509
 * Count how many instances we have of this header
510
 */
511
512
unsigned
513 307557
http_CountHdr(const struct http *hp, hdr_t hdr)
514
{
515 307557
        unsigned retval = 0;
516
        unsigned u;
517
518 307557
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
519
520 1025198
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
521 717641
                Tcheck(hp->hd[u]);
522 717641
                if (http_IsHdr(&hp->hd[u], hdr))
523 152147
                        retval++;
524 717641
        }
525 307557
        return (retval);
526
}
527
528
/*--------------------------------------------------------------------
529
 * This function collapses multiple header lines of the same name.
530
 * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
531
 */
532
533
void
534 989856
http_CollectHdr(struct http *hp, hdr_t hdr)
535
{
536
537 989856
        http_CollectHdrSep(hp, hdr, NULL);
538 989856
}
539
540
/*--------------------------------------------------------------------
541
 * You may prefer to collapse header fields using a different separator.
542
 * For Cookie headers, the separator is "; " for example. That's probably
543
 * the only example too.
544
 */
545
546
void
547 995928
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
548
{
549
        unsigned u, lsep, ml, f, x, d;
550 995928
        char *b = NULL, *e = NULL;
551
        const char *v;
552
553 995928
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
554 995928
        CHECK_HDR(hdr);
555
556 995928
        if (WS_Overflowed(hp->ws))
557 800
                return;
558
559 995128
        if (sep == NULL || *sep == '\0')
560 989034
                sep = ", ";
561 995158
        lsep = strlen(sep);
562
563 995158
        f = http_findhdr(hp, hdr->len - 1, hdr->str);
564 995158
        if (f == 0)
565 978185
                return;
566
567 62672
        for (d = u = f + 1; u < hp->nhd; u++) {
568 45699
                Tcheck(hp->hd[u]);
569 45699
                if (!http_IsHdr(&hp->hd[u], hdr)) {
570 44979
                        if (d != u) {
571 2840
                                hp->hd[d] = hp->hd[u];
572 2840
                                hp->hdf[d] = hp->hdf[u];
573 2840
                        }
574 44979
                        d++;
575 44979
                        continue;
576
                }
577 720
                if (b == NULL) {
578
                        /* Found second header, start our collection */
579 640
                        ml = WS_ReserveAll(hp->ws);
580 640
                        b = WS_Reservation(hp->ws);
581 640
                        e = b + ml;
582 640
                        x = Tlen(hp->hd[f]);
583 640
                        if (b + x >= e) {
584 0
                                http_fail(hp);
585 0
                                VSLbs(hp->vsl, SLT_LostHeader,
586 0
                                    TOSTRAND(hdr->str));
587 0
                                WS_Release(hp->ws, 0);
588 0
                                return;
589
                        }
590 640
                        memcpy(b, hp->hd[f].b, x);
591 640
                        b += x;
592 640
                }
593
594 720
                AN(b);
595 720
                AN(e);
596
597
                /* Append the Nth header we found */
598 720
                x = Tlen(hp->hd[u]) - hdr->len;
599
600 720
                v = hp->hd[u].b + hdr->len;
601 1440
                while (vct_issp(*v)) {
602 720
                        v++;
603 720
                        x--;
604
                }
605
606 720
                if (b + lsep + x >= e) {
607 0
                        http_fail(hp);
608 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hdr->str));
609 0
                        WS_Release(hp->ws, 0);
610 0
                        return;
611
                }
612 720
                memcpy(b, sep, lsep);
613 720
                b += lsep;
614 720
                memcpy(b, v, x);
615 720
                b += x;
616 720
        }
617 16973
        if (b == NULL)
618 16333
                return;
619 640
        hp->nhd = (uint16_t)d;
620 640
        AN(e);
621 640
        *b = '\0';
622 640
        hp->hd[f].b = WS_Reservation(hp->ws);
623 640
        hp->hd[f].e = b;
624 640
        WS_ReleaseP(hp->ws, b + 1);
625 995958
}
626
627
/*--------------------------------------------------------------------*/
628
629
int
630 5084871
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
631
{
632
        unsigned u;
633
        const char *p;
634
635 5084871
        CHECK_HDR(hdr);
636 5084871
        u = http_findhdr(hp, hdr->len - 1, hdr->str);
637 5084871
        if (u == 0) {
638 3755403
                if (ptr != NULL)
639 3452234
                        *ptr = NULL;
640 3755403
                return (0);
641
        }
642 1329468
        if (ptr != NULL) {
643 1087526
                p = hp->hd[u].b + hdr->len;
644 2173271
                while (vct_issp(*p))
645 1085745
                        p++;
646 1087526
                *ptr = p;
647 1087526
        }
648 1329468
        return (1);
649 5084871
}
650
651
/*-----------------------------------------------------------------------------
652
 * Split source string at any of the separators, return pointer to first
653
 * and last+1 char of substrings, with whitespace trimmed at both ends.
654
 * If sep being an empty string is shorthand for VCT::SP
655
 * If stop is NULL, src is NUL terminated.
656
 */
657
658
static int
659 101108
http_split(const char **src, const char *stop, const char *sep,
660
    const char **b, const char **e)
661
{
662
        const char *p, *q;
663
664 101108
        AN(src);
665 101108
        AN(*src);
666 101108
        AN(sep);
667 101108
        AN(b);
668 101108
        AN(e);
669
670 101108
        if (stop == NULL)
671 100825
                stop = strchr(*src, '\0');
672
673 174243
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
674 4040
                continue;
675
676 101108
        if (p >= stop) {
677 36053
                *b = NULL;
678 36053
                *e = NULL;
679 36053
                return (0);
680
        }
681
682 65055
        *b = p;
683 65055
        if (*sep == '\0') {
684 0
                for (q = p + 1; q < stop && !vct_issp(*q); q++)
685 0
                        continue;
686 0
                *e = q;
687 0
                *src = q;
688 0
                return (1);
689
        }
690 324195
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
691 259140
                continue;
692 65055
        *src = q;
693 65055
        while (q > p && vct_issp(q[-1]))
694 0
                q--;
695 65055
        *e = q;
696 65055
        return (1);
697 101108
}
698
699
/*-----------------------------------------------------------------------------
700
 * Comparison rule for tokens:
701
 *      if target string starts with '"', we use memcmp() and expect closing
702
 *      double quote as well
703
 *      otherwise we use http_tok_at()
704
 *
705
 * On match we increment *bp past the token name.
706
 */
707
708
static int
709 57280
http_istoken(const char **bp, const char *e, const char *token)
710
{
711 57280
        int fl = strlen(token);
712
        const char *b;
713
714 57280
        AN(bp);
715 57280
        AN(e);
716 57280
        AN(token);
717
718 57280
        b = *bp;
719
720 57280
        if (b + fl + 2 <= e && *b == '"' &&
721 0
            !memcmp(b + 1, token, fl) && b[fl + 1] == '"') {
722 0
                *bp += fl + 2;
723 0
                return (1);
724
        }
725 59200
        if (b + fl <= e && http_tok_at(b, token, fl) &&
726 26720
            (b + fl == e || !vct_istchar(b[fl]))) {
727 26720
                *bp += fl;
728 26720
                return (1);
729
        }
730 30560
        return (0);
731 57280
}
732
733
/*-----------------------------------------------------------------------------
734
 * Find a given data element (token) in a header according to RFC2616's #rule
735
 * (section 2.1, p15)
736
 *
737
 * On case sensitivity:
738
 *
739
 * Section 4.2 (Messages Headers) defines field (header) name as case
740
 * insensitive, but the field (header) value/content may be case-sensitive.
741
 *
742
 * http_GetHdrToken looks up a token in a header value and the rfc does not say
743
 * explicitly if tokens are to be compared with or without respect to case.
744
 *
745
 * But all examples and specific statements regarding tokens follow the rule
746
 * that unquoted tokens are to be matched case-insensitively and quoted tokens
747
 * case-sensitively.
748
 *
749
 * The optional pb and pe arguments will point to the token content start and
750
 * end+1, white space trimmed on both sides.
751
 */
752
753
int
754 606301
http_GetHdrToken(const struct http *hp, hdr_t hdr,
755
    const char *token, const char **pb, const char **pe)
756
{
757
        const char *h, *b, *e;
758
759 606301
        if (pb != NULL)
760 458360
                *pb = NULL;
761 606301
        if (pe != NULL)
762 142941
                *pe = NULL;
763 606301
        if (!http_GetHdr(hp, hdr, &h))
764 550781
                return (0);
765 55520
        AN(h);
766
767 86080
        while (http_split(&h, NULL, ",", &b, &e))
768 57280
                if (http_istoken(&b, e, token))
769 26720
                        break;
770 55520
        if (b == NULL)
771 28800
                return (0);
772 26720
        if (pb != NULL) {
773 26560
                for (; vct_islws(*b); b++)
774 200
                        continue;
775 26360
                if (b == e) {
776 24480
                        b = NULL;
777 24480
                        e = NULL;
778 24480
                }
779 26360
                *pb = b;
780 26360
                if (pe != NULL)
781 24200
                        *pe = e;
782 26360
        }
783 26720
        return (1);
784 606301
}
785
786
/*--------------------------------------------------------------------
787
 * Find a given header field's quality value (qvalue).
788
 */
789
790
double
791 142938
http_GetHdrQ(const struct http *hp, hdr_t hdr, const char *field)
792
{
793
        const char *hb, *he, *b, *e;
794
        int i;
795
        double a, f;
796
797 142938
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
798 142938
        if (!i)
799 118738
                return (0.);
800
801 24200
        if (hb == NULL)
802 23920
                return (1.);
803 280
        while (http_split(&hb, he, ";", &b, &e)) {
804 280
                if (*b != 'q')
805 0
                        continue;
806 280
                for (b++; b < e && vct_issp(*b); b++)
807 0
                        continue;
808 280
                if (b == e || *b != '=')
809 0
                        continue;
810 280
                break;
811
        }
812 280
        if (b == NULL)
813 0
                return (1.);
814 280
        for (b++; b < e && vct_issp(*b); b++)
815 0
                continue;
816 280
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
817 40
                return (0.);
818 240
        a = 0;
819 480
        while (b < e && vct_isdigit(*b)) {
820 240
                a *= 10.;
821 240
                a += *b - '0';
822 240
                b++;
823
        }
824 240
        if (b == e || *b++ != '.')
825 40
                return (a);
826 200
        f = .1;
827 640
        while (b < e && vct_isdigit(*b)) {
828 440
                a += f * (*b - '0');
829 440
                f *= .1;
830 440
                b++;
831
        }
832 200
        return (a);
833 142938
}
834
835
/*--------------------------------------------------------------------
836
 * Find a given header field's value.
837
 */
838
839
int
840 315437
http_GetHdrField(const struct http *hp, hdr_t hdr,
841
    const char *field, const char **ptr)
842
{
843
        const char *h;
844
        int i;
845
846 315437
        if (ptr != NULL)
847 160358
                *ptr = NULL;
848
849 315437
        h = NULL;
850 315437
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
851 315437
        if (!i)
852 313277
                return (i);
853
854 2160
        if (ptr != NULL && h != NULL) {
855
                /* Skip whitespace, looking for '=' */
856 1600
                while (*h && vct_issp(*h))
857 0
                        h++;
858 1600
                if (*h == '=') {
859 1600
                        h++;
860 1760
                        while (*h && vct_issp(*h))
861 160
                                h++;
862 1600
                        *ptr = h;
863 1600
                }
864 1600
        }
865 2160
        return (i);
866 315437
}
867
868
/*--------------------------------------------------------------------*/
869
870
ssize_t
871 453574
http_GetContentLength(const struct http *hp)
872
{
873
        ssize_t cl;
874
        const char *b;
875
876 453574
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
877
878 453574
        if (!http_GetHdr(hp, H_Content_Length, &b))
879 177787
                return (-1);
880 275787
        cl = VNUM_uint(b, NULL, &b);
881 275787
        if (cl < 0)
882 160
                return (-2);
883 275627
        while (vct_islws(*b))
884 0
                b++;
885 275627
        if (*b != '\0')
886 0
                return (-2);
887 275627
        return (cl);
888 453574
}
889
890
ssize_t
891 81440
http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi)
892
{
893
        ssize_t tmp, cl;
894
        const char *b, *t;
895
896 81440
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
897
898 81440
        if (lo == NULL)
899 0
                lo = &tmp;
900 81440
        if (hi == NULL)
901 0
                hi = &tmp;
902
903 81440
        *lo = *hi = -1;
904
905 81440
        if (!http_GetHdr(hp, H_Content_Range, &b))
906 81040
                return (-1);
907
908 400
        t = strchr(b, ' ');
909 400
        if (t == NULL)
910 40
                return (-2);            // Missing space after range unit
911
912 360
        if (!http_range_at(b, bytes, t - b))
913 40
                return (-1);            // Unknown range unit, ignore
914 320
        b = t + 1;
915
916 320
        if (*b == '*') {                // Content-Range: bytes */123
917 120
                *lo = *hi = -1;
918 120
                b++;
919 120
        } else {                        // Content-Range: bytes 1-2/3
920 200
                *lo = VNUM_uint(b, NULL, &b);
921 200
                if (*lo < 0)
922 0
                        return (-2);
923 200
                if (*b != '-')
924 0
                        return (-2);
925 200
                *hi = VNUM_uint(b + 1, NULL, &b);
926 200
                if (*hi < 0)
927 0
                        return (-2);
928
        }
929 320
        if (*b != '/')
930 0
                return (-2);
931 320
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
932 40
                cl = -1;
933 40
                b += 2;
934 40
        } else {
935 280
                cl = VNUM_uint(b + 1, NULL, &b);
936 280
                if (cl <= 0)
937 0
                        return (-2);
938
        }
939 320
        while (vct_islws(*b))
940 0
                b++;
941 320
        if (*b != '\0')
942 0
                return (-2);
943 320
        if (*lo > *hi)
944 0
                return (-2);
945 320
        assert(cl >= -1);
946 320
        if (*lo >= cl || *hi >= cl)
947 40
                return (-2);
948 280
        AN(cl);
949 280
        return (cl);
950 81440
}
951
952
const char *
953 83400
http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi, ssize_t len)
954
{
955
        ssize_t tmp_lo, tmp_hi;
956
        const char *b, *t;
957
958 83400
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
959
960 83400
        if (lo == NULL)
961 0
                lo = &tmp_lo;
962 83400
        if (hi == NULL)
963 0
                hi = &tmp_hi;
964
965 83400
        *lo = *hi = -1;
966
967 83400
        if (!http_GetHdr(hp, H_Range, &b))
968 81200
                return (NULL);
969
970 2200
        t = strchr(b, '=');
971 2200
        if (t == NULL)
972 80
                return ("Missing '='");
973
974 2120
        if (!http_range_at(b, bytes, t - b))
975 120
                return ("Not Bytes");
976 2000
        b = t + 1;
977
978 2000
        *lo = VNUM_uint(b, NULL, &b);
979 2000
        if (*lo == -2)
980 0
                return ("Low number too big");
981 2000
        if (*b++ != '-')
982 0
                return ("Missing hyphen");
983
984 2000
        *hi = VNUM_uint(b, NULL, &b);
985 2000
        if (*hi == -2)
986 0
                return ("High number too big");
987 2000
        if (*lo == -1 && *hi == -1)
988 40
                return ("Neither high nor low");
989 1960
        if (*lo == -1 && *hi == 0)
990 40
                return ("No low, high is zero");
991 1920
        if (*hi >= 0 && *hi < *lo)
992 40
                return ("high smaller than low");
993
994 1920
        while (vct_islws(*b))
995 40
                b++;
996 1880
        if (*b != '\0')
997 40
                return ("Trailing stuff");
998
999 1840
        assert(*lo >= -1);
1000 1840
        assert(*hi >= -1);
1001
1002 1840
        if (*lo < 0) {
1003 160
                assert(*hi > 0);
1004 160
                *lo = len - *hi;
1005 160
                if (*lo < 0)
1006 80
                        *lo = 0;
1007 160
                *hi = len - 1;
1008 1840
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1009 360
                *hi = len - 1;
1010 360
        }
1011
1012 1840
        if (len <= 0)
1013 720
                return (NULL);                  // Allow 200 response
1014
1015 1120
        if (*lo >= len)
1016 40
                return ("low range beyond object");
1017
1018 1080
        return (NULL);
1019 83400
}
1020
1021
/*--------------------------------------------------------------------
1022
 */
1023
1024
stream_close_t
1025 238317
http_DoConnection(struct http *hp, stream_close_t sc_close)
1026
{
1027
        const char *h, *b, *e;
1028
        stream_close_t retval;
1029
        unsigned u, v;
1030
        struct http_hdrflg *f;
1031
1032 238317
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1033 238317
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1034
1035 238317
        if (hp->protover == 10)
1036 1551
                retval = SC_REQ_HTTP10;
1037
        else
1038 236766
                retval = SC_NULL;
1039
1040 238317
        http_CollectHdr(hp, H_Connection);
1041 238317
        if (!http_GetHdr(hp, H_Connection, &h))
1042 230944
                return (retval);
1043 7373
        AN(h);
1044 14745
        while (http_split(&h, NULL, ",", &b, &e)) {
1045 7492
                u = pdiff(b, e);
1046 7492
                if (u == 5 && http_hdr_at(b, "close", u))
1047 5814
                        retval = sc_close;
1048 7492
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1049 1200
                        retval = SC_NULL;
1050
1051
                /* Refuse removal of well-known-headers if they would pass. */
1052 7492
                f = http_hdr_flags(b, e);
1053 7492
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1054 120
                        return (SC_RX_BAD);
1055
1056 35806
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1057 28434
                        Tcheck(hp->hd[v]);
1058 28434
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1059 1520
                                continue;
1060 26914
                        if (hp->hd[v].b[u] != ':')
1061 24634
                                continue;
1062 2280
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1063 1800
                                continue;
1064 480
                        hp->hdf[v] |= HDF_FILTER;
1065 480
                }
1066
        }
1067 7253
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1068 7253
        return (retval);
1069 238317
}
1070
1071
/*--------------------------------------------------------------------*/
1072
1073
int
1074 469213
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1075
{
1076
        const char *p;
1077
1078 469213
        if (!http_GetHdr(hp, hdr, &p))
1079 445395
                return (0);
1080 23818
        AN(p);
1081 23818
        if (http_tok_eq(p, val))
1082 22778
                return (1);
1083 1040
        return (0);
1084 469213
}
1085
1086
/*--------------------------------------------------------------------*/
1087
1088
uint16_t
1089 586034
http_GetStatus(const struct http *hp)
1090
{
1091
1092 586034
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1093 586034
        return (hp->status);
1094
}
1095
1096
int
1097 406856
http_IsStatus(const struct http *hp, int val)
1098
{
1099
1100 406856
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1101 406856
        assert(val >= 100 && val <= 999);
1102 406856
        return (val == (hp->status % 1000));
1103
}
1104
1105
/*--------------------------------------------------------------------
1106
 * Setting the status will also set the Reason appropriately
1107
 */
1108
1109
void
1110 46152
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1111
{
1112
        char buf[4];
1113 46152
        const char *sstr = NULL;
1114
1115 46152
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1116
        /*
1117
         * We allow people to use top digits for internal VCL
1118
         * signalling, but strip them from the ASCII version.
1119
         */
1120 46152
        to->status = status;
1121 46152
        status %= 1000;
1122 46152
        assert(status >= 100);
1123
1124 46152
        if (reason == NULL)
1125 9400
                reason = http_Status2Reason(status, &sstr);
1126
        else
1127 36752
                (void)http_Status2Reason(status, &sstr);
1128
1129 46152
        if (sstr) {
1130 44712
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1131 44712
        } else {
1132 1440
                bprintf(buf, "%03d", status);
1133 1440
                http_PutField(to, HTTP_HDR_STATUS, buf);
1134
        }
1135 46152
        http_SetH(to, HTTP_HDR_REASON, reason);
1136 46152
}
1137
1138
/*--------------------------------------------------------------------*/
1139
1140
const char *
1141 357870
http_GetMethod(const struct http *hp)
1142
{
1143
1144 357870
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1145 357870
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1146 357870
        return (hp->hd[HTTP_HDR_METHOD].b);
1147
}
1148
1149
/*--------------------------------------------------------------------
1150
 * Force a particular header field to a particular value
1151
 */
1152
1153
void
1154 314439
http_ForceField(struct http *to, unsigned n, const char *t)
1155
{
1156
        int i;
1157
1158 314439
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1159 314439
        assert(n < HTTP_HDR_FIRST);
1160 314439
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1161 314439
        AN(t);
1162
1163
        /* NB: method names and protocol versions are case-sensitive. */
1164 314439
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1165 4800
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1166 4800
                i += to->logtag;
1167
                /* XXX: this is a dead branch */
1168 4800
                if (n >= HTTP_HDR_FIRST)
1169 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1170 4800
                http_SetH(to, n, t);
1171 4800
        }
1172 314441
}
1173
1174
/*--------------------------------------------------------------------*/
1175
1176
void
1177 42077
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1178
    const char *reason)
1179
{
1180
1181 42077
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1182 42077
        if (proto != NULL)
1183 42078
                http_SetH(to, HTTP_HDR_PROTO, proto);
1184 42079
        http_SetStatus(to, status, reason);
1185 42079
}
1186
1187
/*--------------------------------------------------------------------
1188
 * check if header is filtered by the dynamic marker or the static
1189
 * definitions in http_headers.h
1190
 */
1191
1192
static inline int
1193 1627017
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1194
{
1195
        const char *e;
1196
        const struct http_hdrflg *f;
1197
1198 1627017
        if (fm->hdf[u] & HDF_FILTER)
1199 680
                return (1);
1200 1626337
        if (u < HTTP_HDR_FIRST)
1201 545068
                return (0);
1202 1081269
        e = strchr(fm->hd[u].b, ':');
1203 1081269
        if (e == NULL)
1204 0
                return (0);
1205 1081269
        f = http_hdr_flags(fm->hd[u].b, e);
1206 1081269
        return (f != NULL && f->flag & how);
1207 1627017
}
1208
1209
int
1210 33579
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1211
{
1212
1213 33579
        return (http_isfiltered(fm, u, how));
1214
}
1215
1216
/*--------------------------------------------------------------------
1217
 * Estimate how much workspace we need to Filter this header according
1218
 * to 'how'.
1219
 */
1220
1221
unsigned
1222 90995
http_EstimateWS(const struct http *fm, unsigned how)
1223
{
1224
        unsigned u, l;
1225
1226 90995
        l = 4;
1227 90995
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1228 870814
        for (u = 0; u < fm->nhd; u++) {
1229 779819
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1230 181977
                        continue;
1231 597842
                Tcheck(fm->hd[u]);
1232 597842
                if (http_isfiltered(fm, u, how))
1233 10807
                        continue;
1234 587035
                l += Tlen(fm->hd[u]) + 1L;
1235 587035
        }
1236 90995
        return (PRNDUP(l + 1L));
1237
}
1238
1239
/*--------------------------------------------------------------------
1240
 * Encode http struct as byte string.
1241
 *
1242
 * XXX: We could save considerable special-casing below by encoding also
1243
 * XXX: H__Status, H__Reason and H__Proto into the string, but it would
1244
 * XXX: add 26-30 bytes to all encoded objects to save a little code.
1245
 * XXX: It could possibly be a good idea for later HTTP versions.
1246
 */
1247
1248
void
1249 90754
HTTP_Encode(const struct http *fm, uint8_t *p0, unsigned l, unsigned how)
1250
{
1251
        unsigned u, w;
1252
        uint16_t n;
1253
        uint8_t *p, *e;
1254
1255 90754
        AN(p0);
1256 90754
        AN(l);
1257 90754
        p = p0;
1258 90754
        e = p + l;
1259 90754
        assert(p + 5 <= e);
1260 90754
        assert(fm->nhd <= fm->shd);
1261 90754
        n = HTTP_HDR_FIRST - 3;
1262 90754
        vbe16enc(p + 2, fm->status);
1263 90754
        p += 4;
1264 90754
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1265 868295
        for (u = 0; u < fm->nhd; u++) {
1266 777541
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1267 181500
                        continue;
1268 596041
                Tcheck(fm->hd[u]);
1269 596041
                if (http_isfiltered(fm, u, how))
1270 10806
                        continue;
1271 585235
                http_VSLH(fm, u);
1272 585235
                w = Tlen(fm->hd[u]) + 1L;
1273 585235
                assert(p + w + 1 <= e);
1274 585235
                memcpy(p, fm->hd[u].b, w);
1275 585235
                p += w;
1276 585235
                n++;
1277 585235
        }
1278 90754
        *p++ = '\0';
1279 90754
        assert(p <= e);
1280 90754
        vbe16enc(p0, n + 1);
1281 90754
}
1282
1283
/*--------------------------------------------------------------------
1284
 * Decode byte string into http struct
1285
 */
1286
1287
int
1288 133267
HTTP_Decode(struct http *to, const uint8_t *fm)
1289
{
1290
1291 133267
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1292 133267
        AN(to->vsl);
1293 133267
        AN(fm);
1294 133267
        if (vbe16dec(fm) <= to->shd) {
1295 133190
                to->status = vbe16dec(fm + 2);
1296 133190
                fm += 4;
1297 1263378
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1298 1263378
                        if (to->nhd == HTTP_HDR_METHOD ||
1299 1130098
                            to->nhd == HTTP_HDR_URL) {
1300 266324
                                to->hd[to->nhd].b = NULL;
1301 266324
                                to->hd[to->nhd].e = NULL;
1302 266324
                                continue;
1303
                        }
1304 997054
                        if (*fm == '\0')
1305 133190
                                return (0);
1306 863864
                        to->hd[to->nhd].b = (const void*)fm;
1307 863864
                        fm = (const void*)strchr((const void*)fm, '\0');
1308 863864
                        to->hd[to->nhd].e = (const void*)fm;
1309 863864
                        fm++;
1310 863864
                        http_VSLH(to, to->nhd);
1311 863864
                }
1312 0
        }
1313 154
        VSLb(to->vsl, SLT_Error,
1314
            "Too many headers to Decode object (%u vs. %u)",
1315 77
            vbe16dec(fm), to->shd);
1316 77
        return (-1);
1317 133267
}
1318
1319
/*--------------------------------------------------------------------*/
1320
1321
uint16_t
1322 1360
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1323
{
1324
        const char *ptr;
1325 1360
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1326 1360
        AN(ptr);
1327
1328 1360
        return (vbe16dec(ptr + 2));
1329
}
1330
1331
/*--------------------------------------------------------------------*/
1332
1333
/* Get the first packed header */
1334
int
1335 36243
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1336
{
1337
        const char *ptr;
1338
1339 36243
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1340 36243
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1341 36243
        AN(p);
1342
1343 36243
        if (*p == NULL) {
1344 11142
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1345 11142
                AN(ptr);
1346 11142
                ptr += 4;       /* Skip nhd and status */
1347 11142
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1348 11142
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1349 11142
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1350 11142
                *p = ptr;
1351 11142
        } else {
1352 25101
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1353
        }
1354 36243
        if (**p == '\0')
1355 2382
                return (0);
1356 33861
        return (1);
1357 36243
}
1358
1359
const char *
1360 11860
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1361
{
1362
        const char *ptr;
1363
1364 11860
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1365 11860
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1366 11860
        CHECK_HDR(hdr);
1367
1368 11860
        if (hdr->str[0] == ':') {
1369
                /* Special cases */
1370 720
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1371 720
                AN(ptr);
1372 720
                ptr += 4;       /* Skip nhd and status */
1373
1374
                /* XXX: should we also have h2_hdr_eq() ? */
1375 720
                if (!strcmp(hdr->str, ":proto:"))
1376 80
                        return (ptr);
1377 640
                ptr = strchr(ptr, '\0') + 1;
1378 640
                if (!strcmp(hdr->str, ":status:"))
1379 560
                        return (ptr);
1380 80
                ptr = strchr(ptr, '\0') + 1;
1381 80
                if (!strcmp(hdr->str, ":reason:"))
1382 80
                        return (ptr);
1383 0
                WRONG("Unknown magic packed header");
1384 0
        }
1385
1386 36243
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1387 33861
                if (http_hdr_at(ptr, hdr->str, hdr->len)) {
1388 8758
                        ptr += hdr->len;
1389 17476
                        while (vct_islws(*ptr))
1390 8718
                                ptr++;
1391 8758
                        return (ptr);
1392
                }
1393
        }
1394
1395 2382
        return (NULL);
1396 11860
}
1397
1398
/*--------------------------------------------------------------------
1399
 * Merge any headers in the oc->OA_HEADER into the struct http if they
1400
 * are not there already.
1401
 */
1402
1403
void
1404 1280
HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to)
1405
{
1406
        const char *ptr;
1407
        unsigned u;
1408
        const char *p;
1409
        unsigned nhd_before_merge;
1410
1411 1280
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1412 1280
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1413 1280
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1414
1415 1280
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1416 1280
        AN(ptr);
1417
1418 1280
        to->status = vbe16dec(ptr + 2);
1419 1280
        ptr += 4;
1420
1421 7680
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1422 6400
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1423 2560
                        continue;
1424 3840
                http_SetH(to, u, ptr);
1425 3840
                ptr = strchr(ptr, '\0') + 1;
1426 3840
        }
1427 1280
        nhd_before_merge = to->nhd;
1428 7640
        while (*ptr != '\0') {
1429 6360
                p = strchr(ptr, ':');
1430 6360
                AN(p);
1431 6360
                u = http_findhdr(to, p - ptr, ptr);
1432 6360
                if (u == 0 || u >= nhd_before_merge)
1433 3000
                        http_SetHeader(to, ptr);
1434 6360
                ptr = strchr(ptr, '\0') + 1;
1435
        }
1436 1280
}
1437
1438
/*--------------------------------------------------------------------*/
1439
1440
static void
1441 279344
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1442
{
1443
1444 279344
        assert(n < HTTP_HDR_FIRST);
1445 279344
        Tcheck(fm->hd[n]);
1446 279344
        to->hd[n] = fm->hd[n];
1447 279344
        to->hdf[n] = fm->hdf[n];
1448 279344
        http_VSLH(to, n);
1449 279344
}
1450
1451
/*--------------------------------------------------------------------*/
1452
1453
void
1454 93118
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1455
{
1456
        unsigned u;
1457
1458 93118
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1459 93118
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1460
1461 93118
        http_linkh(to, fm, HTTP_HDR_METHOD);
1462 93118
        http_SetWellKnownMethod(to);
1463 93118
        http_linkh(to, fm, HTTP_HDR_URL);
1464 93118
        http_linkh(to, fm, HTTP_HDR_PROTO);
1465 93118
        to->protover = fm->protover;
1466 93118
        to->status = fm->status;
1467
1468 93118
        to->nhd = HTTP_HDR_FIRST;
1469 492560
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1470 399442
                Tcheck(fm->hd[u]);
1471 399442
                if (http_isfiltered(fm, u, how))
1472 4600
                        continue;
1473 394842
                assert (to->nhd < to->shd);
1474 394842
                to->hd[to->nhd] = fm->hd[u];
1475 394842
                to->hdf[to->nhd] = 0;
1476 394842
                http_VSLH(to, to->nhd);
1477 394842
                to->nhd++;
1478 394842
        }
1479 93118
}
1480
1481
/*--------------------------------------------------------------------
1482
 * This function copies any header fields which reference foreign
1483
 * storage into our own WS.
1484
 */
1485
1486
void
1487 91918
http_CopyHome(const struct http *hp)
1488
{
1489
        unsigned u, l;
1490
        const char *p;
1491
1492 999279
        for (u = 0; u < hp->nhd; u++) {
1493 907361
                if (hp->hd[u].b == NULL) {
1494 183830
                        assert(u < HTTP_HDR_FIRST);
1495 183830
                        continue;
1496
                }
1497
1498 723531
                l = Tlen(hp->hd[u]);
1499 723531
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1500 58301
                        continue;
1501
1502 665230
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1503 665230
                if (p == NULL) {
1504 0
                        http_fail(hp);
1505 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hp->hd[u].b));
1506 0
                        return;
1507
                }
1508 665230
                hp->hd[u].b = p;
1509 665230
                hp->hd[u].e = p + l;
1510 665230
        }
1511 91918
}
1512
1513
/*--------------------------------------------------------------------*/
1514
1515
void
1516 384079
http_SetHeader(struct http *to, const char *header)
1517
{
1518
1519 384079
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1520 384079
        if (to->nhd >= to->shd) {
1521 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1522 40
                http_fail(to);
1523 40
                return;
1524
        }
1525 384039
        http_SetH(to, to->nhd++, header);
1526 384079
}
1527
1528
/*--------------------------------------------------------------------*/
1529
1530
void
1531 171323
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1532
{
1533
1534 171323
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1535 171323
        if (http_HdrIs(to, hdr, val))
1536 15538
                return;
1537 155785
        http_Unset(to, hdr);
1538 155785
        http_PrintfHeader(to, "%s %s", hdr->str, val);
1539 171323
}
1540
1541
void
1542 436582
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1543
{
1544
        const char *old;
1545
1546 436582
        http_CollectHdr(to, hdr);
1547 436582
        if (http_GetHdr(to, hdr, &old)) {
1548 1920
                http_Unset(to, hdr);
1549 1920
                http_PrintfHeader(to, "%s %s, %s", hdr->str, old, val);
1550 1920
        } else {
1551 434662
                http_PrintfHeader(to, "%s %s", hdr->str, val);
1552
        }
1553 436582
}
1554
1555
void
1556 1027499
http_PrintfHeader(struct http *to, const char *fmt, ...)
1557
{
1558
        va_list ap, ap2;
1559
        struct vsb vsb[1];
1560
        size_t sz;
1561
        char *p;
1562
1563 1027499
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1564
1565 1027499
        va_start(ap, fmt);
1566 1027499
        va_copy(ap2, ap);
1567
1568 1027499
        WS_VSB_new(vsb, to->ws);
1569 1027499
        VSB_vprintf(vsb, fmt, ap);
1570 1027499
        p = WS_VSB_finish(vsb, to->ws, &sz);
1571
1572 1027499
        if (p == NULL || to->nhd >= to->shd) {
1573 1046
                http_fail(to);
1574 1046
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1575 1046
        } else {
1576 1026483
                http_SetH(to, to->nhd++, p);
1577
        }
1578 1027529
        va_end(ap);
1579 1027529
        va_end(ap2);
1580 1027529
}
1581
1582
void
1583 42397
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1584
{
1585
        char *p;
1586
1587 42397
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1588 42397
        if (to->nhd >= to->shd) {
1589 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1590 0
                http_fail(to);
1591 0
                return;
1592
        }
1593 42397
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1594 42397
        if (p == NULL) {
1595 3080
                http_fail(to);
1596 3080
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1597 3080
                return;
1598
        }
1599 39317
        strcpy(p, fmt);
1600 39317
        VTIM_format(now, strchr(p, '\0'));
1601 39317
        http_SetH(to, to->nhd++, p);
1602 42397
}
1603
1604
const char *
1605 284886
http_ViaHeader(void)
1606
{
1607
1608 284886
        return (via_hdr);
1609
}
1610
1611
/*--------------------------------------------------------------------*/
1612
1613
void
1614 933984
http_Unset(struct http *hp, hdr_t hdr)
1615
{
1616
        uint16_t u, v;
1617
1618 6070797
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1619 5136813
                Tcheck(hp->hd[u]);
1620 5136813
                if (http_IsHdr(&hp->hd[u], hdr)) {
1621 41720
                        http_VSLH_del(hp, u);
1622 41720
                        continue;
1623
                }
1624 5095093
                if (v != u) {
1625 118635
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1626 118635
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1627 118635
                }
1628 5095093
                v++;
1629 5095093
        }
1630 933984
        hp->nhd = v;
1631 933984
}
1632
1633
void
1634 226185
http_SetWellKnownMethod(struct http *hp)
1635
{
1636
        size_t l;
1637
        const char *method;
1638
1639 226185
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1640
1641 226185
        method = http_GetMethod(hp);
1642 226185
        AN(method);
1643 226185
        hp->wkm = WKM_UNKNOWN;
1644
#define WKM(wk, bit)                                                    \
1645
        do {                                                            \
1646
                l = vstrlen(method);                                    \
1647
                if (l == vstrlen(#wk) && !vstrcmp(#wk, method)) {       \
1648
                        hp->wkm = WKM_##wk;                             \
1649
                        return;                                         \
1650
                }                                                       \
1651
        } while (0);
1652
#include "tbl/well_known_methods.h"
1653
#undef WKM
1654
}