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
 * HTTP request storage and manipulation
31
 */
32
33
#include "config.h"
34
35
#include "cache_varnishd.h"
36
#include <stdio.h>
37
#include <stdlib.h>
38
39
#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 614002
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 614002
        if (b == NULL || e == NULL)
188 54
                return (NULL);
189 614002
        u = pdiff(b, e);
190 614002
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
191 280
                return (NULL);
192 1227444
        u += http_asso_values[(uint8_t)(e[-1])] +
193 613722
             http_asso_values[(uint8_t)(b[0])];
194 613722
        if (u > GPERF_MAX_HASH_VALUE)
195 8368
                return (NULL);
196 605354
        retval = &http_hdrflg[u];
197 605354
        if (retval->hdr == NULL)
198 2320
                return (NULL);
199 603034
        AN(*retval->hdr);
200 603034
        if (!http_hdr_at(*retval->hdr + 1, b, e - b))
201 8488
                return (NULL);
202 594546
        return (retval);
203 614002
}
204
205
/*--------------------------------------------------------------------*/
206
207
static void
208 396812
http_init_hdr(hdr_t hdr, int flg)
209
{
210
        struct http_hdrflg *f;
211
212 396812
        f = http_hdr_flags(hdr->str, hdr->str + hdr->len - 1);
213 396812
        AN(f);
214 396812
        assert(*f->hdr == hdr);
215 396812
        f->flag = flg;
216 396812
}
217
218
void
219 7631
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 7631
        AN(vsb);
228
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
229
            heritage.identity);
230 7631
        AZ(VSB_finish(vsb));
231 7631
        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 1017197
http_VSLH(const struct http *hp, unsigned hdr)
245
{
246
        int i;
247
248 1017197
        if (hp->vsl != NULL) {
249 1017244
                assert(VXID_TAG(hp->vsl->wid));
250 1017244
                i = hdr;
251 1017244
                if (i > HTTP_HDR_FIRST)
252 535608
                        i = HTTP_HDR_FIRST;
253 1017244
                i += hp->logtag;
254 1017244
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
255 1017244
        }
256 1017293
}
257
258
static void
259 8312
http_VSLH_del(const struct http *hp, unsigned hdr)
260
{
261
        int i;
262
263 8312
        if (hp->vsl != NULL) {
264
                /* We don't support unsetting stuff in the first line */
265 8312
                assert (hdr >= HTTP_HDR_FIRST);
266 8312
                assert(VXID_TAG(hp->vsl->wid));
267 8312
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
268 8312
                i += hp->logtag;
269 8312
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
270 8312
        }
271 8312
}
272
273
/*--------------------------------------------------------------------*/
274
275
void
276 47312
http_VSL_log(const struct http *hp)
277
{
278
        unsigned u;
279
280 413310
        for (u = 0; u < hp->nhd; u++)
281 637401
                if (hp->hd[u].b != NULL)
282 271403
                        http_VSLH(hp, u);
283 47312
}
284
285
/*--------------------------------------------------------------------*/
286
287
static void
288 832
http_fail(const struct http *hp)
289
{
290
        char id[WS_ID_SIZE];
291
292 832
        VSC_C_main->losthdr++;
293 832
        WS_Id(hp->ws, id);
294 832
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
295 832
        WS_MarkOverflow(hp->ws);
296 832
}
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 12005
http_Status2Reason(unsigned status, const char **sstr)
314
{
315
        struct http_msg *mp;
316
317 12005
        status %= 1000;
318 12005
        assert(status >= 100);
319 366268
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
320 365908
                if (mp->nbr == status) {
321 11645
                        if (sstr)
322 8902
                                *sstr = mp->status;
323 11645
                        return (mp->txt);
324
                }
325 360
        return ("Unknown HTTP Status");
326 12005
}
327
328
/*--------------------------------------------------------------------*/
329
330
unsigned
331 43166
HTTP_estimate(unsigned nhttp)
332
{
333
334
        /* XXX: We trust the structs to size-aligned as necessary */
335 43166
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
336
}
337
338
struct http *
339 129498
HTTP_create(void *p, uint16_t nhttp, unsigned len)
340
{
341
        struct http *hp;
342
343 129498
        hp = p;
344 129498
        hp->magic = HTTP_MAGIC;
345 129498
        hp->hd = (void*)(hp + 1);
346 129498
        hp->shd = nhttp;
347 129498
        hp->hdf = (void*)(hp->hd + nhttp);
348 129498
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
349 129498
        return (hp);
350
}
351
352
/*--------------------------------------------------------------------*/
353
354
void
355 120875
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
356
    enum VSL_tag_e  whence)
357
{
358 120875
        http_Teardown(hp);
359 120875
        hp->nhd = HTTP_HDR_FIRST;
360 120875
        hp->logtag = whence;
361 120875
        hp->ws = ws;
362 120875
        hp->vsl = vsl;
363 120875
}
364
365
/*--------------------------------------------------------------------
366
 * http_Teardown() is a safety feature, we use it to zap all http
367
 * structs once we're done with them, to minimize the risk that
368
 * old stale pointers exist to no longer valid stuff.
369
 */
370
371
void
372 188694
http_Teardown(struct http *hp)
373
{
374
375 188694
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
376 188694
        AN(hp->shd);
377 188694
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
378 188694
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
379 188694
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
380 188694
}
381
382
/*--------------------------------------------------------------------
383
 * Duplicate the http content into another http
384
 * We cannot just memcpy the struct because the hd & hdf are private
385
 * storage to the struct http.
386
 */
387
388
void
389 53042
HTTP_Dup(struct http *to, const struct http * fm)
390
{
391
392 53042
        assert(fm->nhd <= to->shd);
393 53042
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
394 53042
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
395 53042
        to->nhd = fm->nhd;
396 53042
        to->logtag = fm->logtag;
397 53042
        to->status = fm->status;
398 53042
        to->protover = fm->protover;
399 53042
}
400
401
402
/*--------------------------------------------------------------------
403
 * Clone the entire http structure, including vsl & ws
404
 */
405
406
void
407 50114
HTTP_Clone(struct http *to, const struct http * const fm)
408
{
409
410 50114
        HTTP_Dup(to, fm);
411 50114
        to->vsl = fm->vsl;
412 50114
        to->ws = fm->ws;
413 50114
}
414
415
/*--------------------------------------------------------------------*/
416
417
void
418 54138
http_Proto(struct http *to)
419
{
420
        const char *fm;
421
422 54138
        fm = to->hd[HTTP_HDR_PROTO].b;
423
424 108208
        if (fm != NULL &&
425 54076
            (fm[0] == 'H' || fm[0] == 'h') &&
426 54068
            (fm[1] == 'T' || fm[1] == 't') &&
427 54068
            (fm[2] == 'T' || fm[2] == 't') &&
428 54068
            (fm[3] == 'P' || fm[3] == 'p') &&
429 54068
            fm[4] == '/' &&
430 54068
            vct_isdigit(fm[5]) &&
431 54069
            fm[6] == '.' &&
432 54069
            vct_isdigit(fm[7]) &&
433 54070
            fm[8] == '\0') {
434 54070
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
435 54070
        } else {
436 72
                to->protover = 0;
437
        }
438 54142
}
439
440
/*--------------------------------------------------------------------*/
441
442
void
443 322481
http_SetH(struct http *to, unsigned n, const char *header)
444
{
445
446 322481
        assert(n < to->nhd);
447 322481
        AN(header);
448 322481
        to->hd[n].b = TRUST_ME(header);
449 322481
        to->hd[n].e = strchr(to->hd[n].b, '\0');
450 322481
        to->hdf[n] = 0;
451 322481
        http_VSLH(to, n);
452 322481
        if (n == HTTP_HDR_PROTO)
453 11070
                http_Proto(to);
454 322481
}
455
456
/*--------------------------------------------------------------------*/
457
458
static void
459 288
http_PutField(struct http *to, int field, const char *string)
460
{
461
        const char *p;
462
463 288
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
464 288
        p = WS_Copy(to->ws, string, -1);
465 288
        if (p == NULL) {
466 8
                http_fail(to);
467 8
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
468 8
                return;
469
        }
470 280
        http_SetH(to, field, p);
471 288
}
472
473
/*--------------------------------------------------------------------*/
474
475
int
476 1176247
http_IsHdr(const txt *hh, hdr_t hdr)
477
{
478
479 1176247
        Tcheck(*hh);
480 1176247
        CHECK_HDR(hdr);
481 1176247
        return (http_hdr_at(hdr->str, hh->b, hdr->len));
482
}
483
484
/*--------------------------------------------------------------------*/
485
486
static unsigned
487 1213709
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
488
{
489
        unsigned u;
490
491 5271379
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
492 4326836
                Tcheck(hp->hd[u]);
493 4326836
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
494 780475
                        continue;
495 3546361
                if (hp->hd[u].b[l] != ':')
496 2981659
                        continue;
497 564702
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
498 295536
                        continue;
499 269166
                return (u);
500
        }
501 944543
        return (0);
502 1213709
}
503
504
/*--------------------------------------------------------------------
505
 * Count how many instances we have of this header
506
 */
507
508
unsigned
509 61372
http_CountHdr(const struct http *hp, hdr_t hdr)
510
{
511 61372
        unsigned retval = 0;
512
        unsigned u;
513
514 61372
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
515
516 204563
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
517 143191
                Tcheck(hp->hd[u]);
518 143191
                if (http_IsHdr(&hp->hd[u], hdr))
519 30344
                        retval++;
520 143191
        }
521 61372
        return (retval);
522
}
523
524
/*--------------------------------------------------------------------
525
 * This function collapses multiple header lines of the same name.
526
 * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
527
 */
528
529
void
530 197503
http_CollectHdr(struct http *hp, hdr_t hdr)
531
{
532
533 197503
        http_CollectHdrSep(hp, hdr, NULL);
534 197503
}
535
536
/*--------------------------------------------------------------------
537
 * You may prefer to collapse header fields using a different separator.
538
 * For Cookie headers, the separator is "; " for example. That's probably
539
 * the only example too.
540
 */
541
542
void
543 198722
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
544
{
545
        unsigned u, lsep, ml, f, x, d;
546 198722
        char *b = NULL, *e = NULL;
547
        const char *v;
548
549 198722
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
550 198722
        CHECK_HDR(hdr);
551
552 198722
        if (WS_Overflowed(hp->ws))
553 160
                return;
554
555 198562
        if (sep == NULL || *sep == '\0')
556 197350
                sep = ", ";
557 198562
        lsep = strlen(sep);
558
559 198562
        f = http_findhdr(hp, hdr->len - 1, hdr->str);
560 198562
        if (f == 0)
561 195186
                return;
562
563 12436
        for (d = u = f + 1; u < hp->nhd; u++) {
564 9060
                Tcheck(hp->hd[u]);
565 9060
                if (!http_IsHdr(&hp->hd[u], hdr)) {
566 8916
                        if (d != u) {
567 568
                                hp->hd[d] = hp->hd[u];
568 568
                                hp->hdf[d] = hp->hdf[u];
569 568
                        }
570 8916
                        d++;
571 8916
                        continue;
572
                }
573 144
                if (b == NULL) {
574
                        /* Found second header, start our collection */
575 128
                        ml = WS_ReserveAll(hp->ws);
576 128
                        b = WS_Reservation(hp->ws);
577 128
                        e = b + ml;
578 128
                        x = Tlen(hp->hd[f]);
579 128
                        if (b + x >= e) {
580 0
                                http_fail(hp);
581 0
                                VSLbs(hp->vsl, SLT_LostHeader,
582 0
                                    TOSTRAND(hdr->str));
583 0
                                WS_Release(hp->ws, 0);
584 0
                                return;
585
                        }
586 128
                        memcpy(b, hp->hd[f].b, x);
587 128
                        b += x;
588 128
                }
589
590 144
                AN(b);
591 144
                AN(e);
592
593
                /* Append the Nth header we found */
594 144
                x = Tlen(hp->hd[u]) - hdr->len;
595
596 144
                v = hp->hd[u].b + hdr->len;
597 288
                while (vct_issp(*v)) {
598 144
                        v++;
599 144
                        x--;
600
                }
601
602 144
                if (b + lsep + x >= e) {
603 0
                        http_fail(hp);
604 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hdr->str));
605 0
                        WS_Release(hp->ws, 0);
606 0
                        return;
607
                }
608 144
                memcpy(b, sep, lsep);
609 144
                b += lsep;
610 144
                memcpy(b, v, x);
611 144
                b += x;
612 144
        }
613 3376
        if (b == NULL)
614 3248
                return;
615 128
        hp->nhd = (uint16_t)d;
616 128
        AN(e);
617 128
        *b = '\0';
618 128
        hp->hd[f].b = WS_Reservation(hp->ws);
619 128
        hp->hd[f].e = b;
620 128
        WS_ReleaseP(hp->ws, b + 1);
621 198722
}
622
623
/*--------------------------------------------------------------------*/
624
625
int
626 1014020
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
627
{
628
        unsigned u;
629
        const char *p;
630
631 1014020
        CHECK_HDR(hdr);
632 1014020
        u = http_findhdr(hp, hdr->len - 1, hdr->str);
633 1014020
        if (u == 0) {
634 748890
                if (ptr != NULL)
635 688363
                        *ptr = NULL;
636 748890
                return (0);
637
        }
638 265130
        if (ptr != NULL) {
639 216864
                p = hp->hd[u].b + hdr->len;
640 433374
                while (vct_issp(*p))
641 216510
                        p++;
642 216864
                *ptr = p;
643 216864
        }
644 265130
        return (1);
645 1014020
}
646
647
/*-----------------------------------------------------------------------------
648
 * Split source string at any of the separators, return pointer to first
649
 * and last+1 char of substrings, with whitespace trimmed at both ends.
650
 * If sep being an empty string is shorthand for VCT::SP
651
 * If stop is NULL, src is NUL terminated.
652
 */
653
654
static int
655 20104
http_split(const char **src, const char *stop, const char *sep,
656
    const char **b, const char **e)
657
{
658
        const char *p, *q;
659
660 20104
        AN(src);
661 20104
        AN(*src);
662 20104
        AN(sep);
663 20104
        AN(b);
664 20104
        AN(e);
665
666 20104
        if (stop == NULL)
667 20047
                stop = strchr(*src, '\0');
668
669 34391
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
670 696
                continue;
671
672 20104
        if (p >= stop) {
673 7208
                *b = NULL;
674 7208
                *e = NULL;
675 7208
                return (0);
676
        }
677
678 12896
        *b = p;
679 12896
        if (*sep == '\0') {
680 0
                for (q = p + 1; q < stop && !vct_issp(*q); q++)
681 0
                        continue;
682 0
                *e = q;
683 0
                *src = q;
684 0
                return (1);
685
        }
686 63349
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
687 50453
                continue;
688 12896
        *src = q;
689 12896
        while (q > p && vct_issp(q[-1]))
690 0
                q--;
691 12896
        *e = q;
692 12896
        return (1);
693 20104
}
694
695
/*-----------------------------------------------------------------------------
696
 * Comparison rule for tokens:
697
 *      if target string starts with '"', we use memcmp() and expect closing
698
 *      double quote as well
699
 *      otherwise we use http_tok_at()
700
 *
701
 * On match we increment *bp past the token name.
702
 */
703
704
static int
705 11336
http_istoken(const char **bp, const char *e, const char *token)
706
{
707 11336
        int fl = strlen(token);
708
        const char *b;
709
710 11336
        AN(bp);
711 11336
        AN(e);
712 11336
        AN(token);
713
714 11336
        b = *bp;
715
716 11336
        if (b + fl + 2 <= e && *b == '"' &&
717 0
            !memcmp(b + 1, token, fl) && b[fl + 1] == '"') {
718 0
                *bp += fl + 2;
719 0
                return (1);
720
        }
721 11664
        if (b + fl <= e && http_tok_at(b, token, fl) &&
722 5288
            (b + fl == e || !vct_istchar(b[fl]))) {
723 5288
                *bp += fl;
724 5288
                return (1);
725
        }
726 6048
        return (0);
727 11336
}
728
729
/*-----------------------------------------------------------------------------
730
 * Find a given data element (token) in a header according to RFC2616's #rule
731
 * (section 2.1, p15)
732
 *
733
 * On case sensitivity:
734
 *
735
 * Section 4.2 (Messages Headers) defines field (header) name as case
736
 * insensitive, but the field (header) value/content may be case-sensitive.
737
 *
738
 * http_GetHdrToken looks up a token in a header value and the rfc does not say
739
 * explicitly if tokens are to be compared with or without respect to case.
740
 *
741
 * But all examples and specific statements regarding tokens follow the rule
742
 * that unquoted tokens are to be matched case-insensitively and quoted tokens
743
 * case-sensitively.
744
 *
745
 * The optional pb and pe arguments will point to the token content start and
746
 * end+1, white space trimmed on both sides.
747
 */
748
749
int
750 120926
http_GetHdrToken(const struct http *hp, hdr_t hdr,
751
    const char *token, const char **pb, const char **pe)
752
{
753
        const char *h, *b, *e;
754
755 120926
        if (pb != NULL)
756 91402
                *pb = NULL;
757 120926
        if (pe != NULL)
758 28528
                *pe = NULL;
759 120926
        if (!http_GetHdr(hp, hdr, &h))
760 109886
                return (0);
761 11040
        AN(h);
762
763 17088
        while (http_split(&h, NULL, ",", &b, &e))
764 11336
                if (http_istoken(&b, e, token))
765 5288
                        break;
766 11040
        if (b == NULL)
767 5752
                return (0);
768 5288
        if (pb != NULL) {
769 5256
                for (; vct_islws(*b); b++)
770 40
                        continue;
771 5216
                if (b == e) {
772 4896
                        b = NULL;
773 4896
                        e = NULL;
774 4896
                }
775 5216
                *pb = b;
776 5216
                if (pe != NULL)
777 4840
                        *pe = e;
778 5216
        }
779 5288
        return (1);
780 120926
}
781
782
/*--------------------------------------------------------------------
783
 * Find a given header field's quality value (qvalue).
784
 */
785
786
double
787 28524
http_GetHdrQ(const struct http *hp, hdr_t hdr, const char *field)
788
{
789
        const char *hb, *he, *b, *e;
790
        int i;
791
        double a, f;
792
793 28524
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
794 28524
        if (!i)
795 23684
                return (0.);
796
797 4840
        if (hb == NULL)
798 4784
                return (1.);
799 56
        while (http_split(&hb, he, ";", &b, &e)) {
800 56
                if (*b != 'q')
801 0
                        continue;
802 56
                for (b++; b < e && vct_issp(*b); b++)
803 0
                        continue;
804 56
                if (b == e || *b != '=')
805 0
                        continue;
806 56
                break;
807
        }
808 56
        if (b == NULL)
809 0
                return (1.);
810 56
        for (b++; b < e && vct_issp(*b); b++)
811 0
                continue;
812 56
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
813 8
                return (0.);
814 48
        a = 0;
815 96
        while (b < e && vct_isdigit(*b)) {
816 48
                a *= 10.;
817 48
                a += *b - '0';
818 48
                b++;
819
        }
820 48
        if (b == e || *b++ != '.')
821 8
                return (a);
822 40
        f = .1;
823 128
        while (b < e && vct_isdigit(*b)) {
824 88
                a += f * (*b - '0');
825 88
                f *= .1;
826 88
                b++;
827
        }
828 40
        return (a);
829 28524
}
830
831
/*--------------------------------------------------------------------
832
 * Find a given header field's value.
833
 */
834
835
int
836 62877
http_GetHdrField(const struct http *hp, hdr_t hdr,
837
    const char *field, const char **ptr)
838
{
839
        const char *h;
840
        int i;
841
842 62877
        if (ptr != NULL)
843 31958
                *ptr = NULL;
844
845 62877
        h = NULL;
846 62877
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
847 62877
        if (!i)
848 62501
                return (i);
849
850 376
        if (ptr != NULL && h != NULL) {
851
                /* Skip whitespace, looking for '=' */
852 264
                while (*h && vct_issp(*h))
853 0
                        h++;
854 264
                if (*h == '=') {
855 264
                        h++;
856 296
                        while (*h && vct_issp(*h))
857 32
                                h++;
858 264
                        *ptr = h;
859 264
                }
860 264
        }
861 376
        return (i);
862 62877
}
863
864
/*--------------------------------------------------------------------*/
865
866
ssize_t
867 90490
http_GetContentLength(const struct http *hp)
868
{
869
        ssize_t cl;
870
        const char *b;
871
872 90490
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
873
874 90490
        if (!http_GetHdr(hp, H_Content_Length, &b))
875 35508
                return (-1);
876 54982
        cl = VNUM_uint(b, NULL, &b);
877 54982
        if (cl < 0)
878 32
                return (-2);
879 54950
        while (vct_islws(*b))
880 0
                b++;
881 54950
        if (*b != '\0')
882 0
                return (-2);
883 54950
        return (cl);
884 90490
}
885
886
ssize_t
887 16240
http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi)
888
{
889
        ssize_t tmp, cl;
890
        const char *b, *t;
891
892 16240
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
893
894 16240
        if (lo == NULL)
895 0
                lo = &tmp;
896 16240
        if (hi == NULL)
897 0
                hi = &tmp;
898
899 16240
        *lo = *hi = -1;
900
901 16240
        if (!http_GetHdr(hp, H_Content_Range, &b))
902 16160
                return (-1);
903
904 80
        t = strchr(b, ' ');
905 80
        if (t == NULL)
906 8
                return (-2);            // Missing space after range unit
907
908 72
        if (!http_range_at(b, bytes, t - b))
909 8
                return (-1);            // Unknown range unit, ignore
910 64
        b = t + 1;
911
912 64
        if (*b == '*') {                // Content-Range: bytes */123
913 24
                *lo = *hi = -1;
914 24
                b++;
915 24
        } else {                        // Content-Range: bytes 1-2/3
916 40
                *lo = VNUM_uint(b, NULL, &b);
917 40
                if (*lo < 0)
918 0
                        return (-2);
919 40
                if (*b != '-')
920 0
                        return (-2);
921 40
                *hi = VNUM_uint(b + 1, NULL, &b);
922 40
                if (*hi < 0)
923 0
                        return (-2);
924
        }
925 64
        if (*b != '/')
926 0
                return (-2);
927 64
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
928 8
                cl = -1;
929 8
                b += 2;
930 8
        } else {
931 56
                cl = VNUM_uint(b + 1, NULL, &b);
932 56
                if (cl <= 0)
933 0
                        return (-2);
934
        }
935 64
        while (vct_islws(*b))
936 0
                b++;
937 64
        if (*b != '\0')
938 0
                return (-2);
939 64
        if (*lo > *hi)
940 0
                return (-2);
941 64
        assert(cl >= -1);
942 64
        if (*lo >= cl || *hi >= cl)
943 8
                return (-2);
944 56
        AN(cl);
945 56
        return (cl);
946 16240
}
947
948
const char *
949 16632
http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi, ssize_t len)
950
{
951
        ssize_t tmp_lo, tmp_hi;
952
        const char *b, *t;
953
954 16632
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
955
956 16632
        if (lo == NULL)
957 0
                lo = &tmp_lo;
958 16632
        if (hi == NULL)
959 0
                hi = &tmp_hi;
960
961 16632
        *lo = *hi = -1;
962
963 16632
        if (!http_GetHdr(hp, H_Range, &b))
964 16192
                return (NULL);
965
966 440
        t = strchr(b, '=');
967 440
        if (t == NULL)
968 16
                return ("Missing '='");
969
970 424
        if (!http_range_at(b, bytes, t - b))
971 24
                return ("Not Bytes");
972 400
        b = t + 1;
973
974 400
        *lo = VNUM_uint(b, NULL, &b);
975 400
        if (*lo == -2)
976 0
                return ("Low number too big");
977 400
        if (*b++ != '-')
978 0
                return ("Missing hyphen");
979
980 400
        *hi = VNUM_uint(b, NULL, &b);
981 400
        if (*hi == -2)
982 0
                return ("High number too big");
983 400
        if (*lo == -1 && *hi == -1)
984 8
                return ("Neither high nor low");
985 392
        if (*lo == -1 && *hi == 0)
986 8
                return ("No low, high is zero");
987 384
        if (*hi >= 0 && *hi < *lo)
988 8
                return ("high smaller than low");
989
990 384
        while (vct_islws(*b))
991 8
                b++;
992 376
        if (*b != '\0')
993 8
                return ("Trailing stuff");
994
995 368
        assert(*lo >= -1);
996 368
        assert(*hi >= -1);
997
998 368
        if (*lo < 0) {
999 32
                assert(*hi > 0);
1000 32
                *lo = len - *hi;
1001 32
                if (*lo < 0)
1002 16
                        *lo = 0;
1003 32
                *hi = len - 1;
1004 368
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1005 72
                *hi = len - 1;
1006 72
        }
1007
1008 368
        if (len <= 0)
1009 144
                return (NULL);                  // Allow 200 response
1010
1011 224
        if (*lo >= len)
1012 8
                return ("low range beyond object");
1013
1014 216
        return (NULL);
1015 16632
}
1016
1017
/*--------------------------------------------------------------------
1018
 */
1019
1020
stream_close_t
1021 47546
http_DoConnection(struct http *hp, stream_close_t sc_close)
1022
{
1023
        const char *h, *b, *e;
1024
        stream_close_t retval;
1025
        unsigned u, v;
1026
        struct http_hdrflg *f;
1027
1028 47546
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1029 47546
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1030
1031 47546
        if (hp->protover == 10)
1032 311
                retval = SC_REQ_HTTP10;
1033
        else
1034 47235
                retval = SC_NULL;
1035
1036 47546
        http_CollectHdr(hp, H_Connection);
1037 47546
        if (!http_GetHdr(hp, H_Connection, &h))
1038 46067
                return (retval);
1039 1479
        AN(h);
1040 2959
        while (http_split(&h, NULL, ",", &b, &e)) {
1041 1504
                u = pdiff(b, e);
1042 1504
                if (u == 5 && http_hdr_at(b, "close", u))
1043 1168
                        retval = sc_close;
1044 1504
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1045 240
                        retval = SC_NULL;
1046
1047
                /* Refuse removal of well-known-headers if they would pass. */
1048 1504
                f = http_hdr_flags(b, e);
1049 1504
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1050 24
                        return (SC_RX_BAD);
1051
1052 7180
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1053 5700
                        Tcheck(hp->hd[v]);
1054 5700
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1055 304
                                continue;
1056 5396
                        if (hp->hd[v].b[u] != ':')
1057 4940
                                continue;
1058 456
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1059 360
                                continue;
1060 96
                        hp->hdf[v] |= HDF_FILTER;
1061 96
                }
1062
        }
1063 1455
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1064 1455
        return (retval);
1065 47546
}
1066
1067
/*--------------------------------------------------------------------*/
1068
1069
int
1070 93461
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1071
{
1072
        const char *p;
1073
1074 93461
        if (!http_GetHdr(hp, hdr, &p))
1075 88717
                return (0);
1076 4744
        AN(p);
1077 4744
        if (http_tok_eq(p, val))
1078 4536
                return (1);
1079 208
        return (0);
1080 93461
}
1081
1082
/*--------------------------------------------------------------------*/
1083
1084
uint16_t
1085 116929
http_GetStatus(const struct http *hp)
1086
{
1087
1088 116929
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1089 116929
        return (hp->status);
1090
}
1091
1092
int
1093 81139
http_IsStatus(const struct http *hp, int val)
1094
{
1095
1096 81139
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1097 81139
        assert(val >= 100 && val <= 999);
1098 81139
        return (val == (hp->status % 1000));
1099
}
1100
1101
/*--------------------------------------------------------------------
1102
 * Setting the status will also set the Reason appropriately
1103
 */
1104
1105
void
1106 9190
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1107
{
1108
        char buf[4];
1109 9190
        const char *sstr = NULL;
1110
1111 9190
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1112
        /*
1113
         * We allow people to use top digits for internal VCL
1114
         * signalling, but strip them from the ASCII version.
1115
         */
1116 9190
        to->status = status;
1117 9190
        status %= 1000;
1118 9190
        assert(status >= 100);
1119
1120 9190
        if (reason == NULL)
1121 1864
                reason = http_Status2Reason(status, &sstr);
1122
        else
1123 7326
                (void)http_Status2Reason(status, &sstr);
1124
1125 9190
        if (sstr) {
1126 8902
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1127 8902
        } else {
1128 288
                bprintf(buf, "%03d", status);
1129 288
                http_PutField(to, HTTP_HDR_STATUS, buf);
1130
        }
1131 9190
        http_SetH(to, HTTP_HDR_REASON, reason);
1132 9190
}
1133
1134
/*--------------------------------------------------------------------*/
1135
1136
const char *
1137 42730
http_GetMethod(const struct http *hp)
1138
{
1139
1140 42730
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1141 42730
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1142 42730
        return (hp->hd[HTTP_HDR_METHOD].b);
1143
}
1144
1145
/*--------------------------------------------------------------------
1146
 * Force a particular header field to a particular value
1147
 */
1148
1149
void
1150 62747
http_ForceField(struct http *to, unsigned n, const char *t)
1151
{
1152
        int i;
1153
1154 62747
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1155 62747
        assert(n < HTTP_HDR_FIRST);
1156 62747
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1157 62747
        AN(t);
1158
1159
        /* NB: method names and protocol versions are case-sensitive. */
1160 62747
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1161 960
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1162 960
                i += to->logtag;
1163
                /* XXX: this is a dead branch */
1164 960
                if (n >= HTTP_HDR_FIRST)
1165 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1166 960
                http_SetH(to, n, t);
1167 960
        }
1168 62747
}
1169
1170
/*--------------------------------------------------------------------*/
1171
1172
void
1173 8391
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1174
    const char *reason)
1175
{
1176
1177 8391
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1178 8391
        if (proto != NULL)
1179 8391
                http_SetH(to, HTTP_HDR_PROTO, proto);
1180 8391
        http_SetStatus(to, status, reason);
1181 8391
}
1182
1183
/*--------------------------------------------------------------------
1184
 * check if header is filtered by the dynamic marker or the static
1185
 * definitions in http_headers.h
1186
 */
1187
1188
static inline int
1189 324546
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1190
{
1191
        const char *e;
1192
        const struct http_hdrflg *f;
1193
1194 324546
        if (fm->hdf[u] & HDF_FILTER)
1195 136
                return (1);
1196 324410
        if (u < HTTP_HDR_FIRST)
1197 108736
                return (0);
1198 215674
        e = strchr(fm->hd[u].b, ':');
1199 215674
        if (e == NULL)
1200 0
                return (0);
1201 215674
        f = http_hdr_flags(fm->hd[u].b, e);
1202 215674
        return (f != NULL && f->flag & how);
1203 324546
}
1204
1205
int
1206 6716
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1207
{
1208
1209 6716
        return (http_isfiltered(fm, u, how));
1210
}
1211
1212
/*--------------------------------------------------------------------
1213
 * Estimate how much workspace we need to Filter this header according
1214
 * to 'how'.
1215
 */
1216
1217
unsigned
1218 18152
http_EstimateWS(const struct http *fm, unsigned how)
1219
{
1220
        unsigned u, l;
1221
1222 18152
        l = 4;
1223 18152
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1224 173707
        for (u = 0; u < fm->nhd; u++) {
1225 155555
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1226 36304
                        continue;
1227 119251
                Tcheck(fm->hd[u]);
1228 119251
                if (http_isfiltered(fm, u, how))
1229 2162
                        continue;
1230 117089
                l += Tlen(fm->hd[u]) + 1L;
1231 117089
        }
1232 18152
        return (PRNDUP(l + 1L));
1233
}
1234
1235
/*--------------------------------------------------------------------
1236
 * Encode http struct as byte string.
1237
 *
1238
 * XXX: We could save considerable special-casing below by encoding also
1239
 * XXX: H__Status, H__Reason and H__Proto into the string, but it would
1240
 * XXX: add 26-30 bytes to all encoded objects to save a little code.
1241
 * XXX: It could possibly be a good idea for later HTTP versions.
1242
 */
1243
1244
void
1245 18104
HTTP_Encode(const struct http *fm, uint8_t *p0, unsigned l, unsigned how)
1246
{
1247
        unsigned u, w;
1248
        uint16_t n;
1249
        uint8_t *p, *e;
1250
1251 18104
        AN(p0);
1252 18104
        AN(l);
1253 18104
        p = p0;
1254 18104
        e = p + l;
1255 18104
        assert(p + 5 <= e);
1256 18104
        assert(fm->nhd <= fm->shd);
1257 18104
        n = HTTP_HDR_FIRST - 3;
1258 18104
        vbe16enc(p + 2, fm->status);
1259 18104
        p += 4;
1260 18104
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1261 173194
        for (u = 0; u < fm->nhd; u++) {
1262 155090
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1263 36208
                        continue;
1264 118882
                Tcheck(fm->hd[u]);
1265 118882
                if (http_isfiltered(fm, u, how))
1266 2162
                        continue;
1267 116720
                http_VSLH(fm, u);
1268 116720
                w = Tlen(fm->hd[u]) + 1L;
1269 116720
                assert(p + w + 1 <= e);
1270 116720
                memcpy(p, fm->hd[u].b, w);
1271 116720
                p += w;
1272 116720
                n++;
1273 116720
        }
1274 18104
        *p++ = '\0';
1275 18104
        assert(p <= e);
1276 18104
        vbe16enc(p0, n + 1);
1277 18104
}
1278
1279
/*--------------------------------------------------------------------
1280
 * Decode byte string into http struct
1281
 */
1282
1283
int
1284 26603
HTTP_Decode(struct http *to, const uint8_t *fm)
1285
{
1286
1287 26603
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1288 26603
        AN(to->vsl);
1289 26603
        AN(fm);
1290 26603
        if (vbe16dec(fm) <= to->shd) {
1291 26589
                to->status = vbe16dec(fm + 2);
1292 26589
                fm += 4;
1293 252205
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1294 252205
                        if (to->nhd == HTTP_HDR_METHOD ||
1295 225602
                            to->nhd == HTTP_HDR_URL) {
1296 53177
                                to->hd[to->nhd].b = NULL;
1297 53177
                                to->hd[to->nhd].e = NULL;
1298 53177
                                continue;
1299
                        }
1300 199028
                        if (*fm == '\0')
1301 26589
                                return (0);
1302 172439
                        to->hd[to->nhd].b = (const void*)fm;
1303 172439
                        fm = (const void*)strchr((const void*)fm, '\0');
1304 172439
                        to->hd[to->nhd].e = (const void*)fm;
1305 172439
                        fm++;
1306 172439
                        http_VSLH(to, to->nhd);
1307 172439
                }
1308 0
        }
1309 28
        VSLb(to->vsl, SLT_Error,
1310
            "Too many headers to Decode object (%u vs. %u)",
1311 14
            vbe16dec(fm), to->shd);
1312 14
        return (-1);
1313 26603
}
1314
1315
/*--------------------------------------------------------------------*/
1316
1317
uint16_t
1318 264
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1319
{
1320
        const char *ptr;
1321 264
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1322 264
        AN(ptr);
1323
1324 264
        return (vbe16dec(ptr + 2));
1325
}
1326
1327
/*--------------------------------------------------------------------*/
1328
1329
/* Get the first packed header */
1330
int
1331 7239
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1332
{
1333
        const char *ptr;
1334
1335 7239
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1336 7239
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1337 7239
        AN(p);
1338
1339 7239
        if (*p == NULL) {
1340 2222
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1341 2222
                AN(ptr);
1342 2222
                ptr += 4;       /* Skip nhd and status */
1343 2222
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1344 2222
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1345 2222
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1346 2222
                *p = ptr;
1347 2222
        } else {
1348 5017
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1349
        }
1350 7239
        if (**p == '\0')
1351 471
                return (0);
1352 6768
        return (1);
1353 7239
}
1354
1355
const char *
1356 2366
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1357
{
1358
        const char *ptr;
1359
1360 2366
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1361 2366
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1362 2366
        CHECK_HDR(hdr);
1363
1364 2366
        if (hdr->str[0] == ':') {
1365
                /* Special cases */
1366 144
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1367 144
                AN(ptr);
1368 144
                ptr += 4;       /* Skip nhd and status */
1369
1370
                /* XXX: should we also have h2_hdr_eq() ? */
1371 144
                if (!strcmp(hdr->str, ":proto:"))
1372 16
                        return (ptr);
1373 128
                ptr = strchr(ptr, '\0') + 1;
1374 128
                if (!strcmp(hdr->str, ":status:"))
1375 112
                        return (ptr);
1376 16
                ptr = strchr(ptr, '\0') + 1;
1377 16
                if (!strcmp(hdr->str, ":reason:"))
1378 16
                        return (ptr);
1379 0
                WRONG("Unknown magic packed header");
1380 0
        }
1381
1382 7239
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1383 6768
                if (http_hdr_at(ptr, hdr->str, hdr->len)) {
1384 1751
                        ptr += hdr->len;
1385 3494
                        while (vct_islws(*ptr))
1386 1743
                                ptr++;
1387 1751
                        return (ptr);
1388
                }
1389
        }
1390
1391 471
        return (NULL);
1392 2366
}
1393
1394
/*--------------------------------------------------------------------
1395
 * Merge any headers in the oc->OA_HEADER into the struct http if they
1396
 * are not there already.
1397
 */
1398
1399
void
1400 248
HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to)
1401
{
1402
        const char *ptr;
1403
        unsigned u;
1404
        const char *p;
1405
        unsigned nhd_before_merge;
1406
1407 248
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1408 248
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1409 248
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1410
1411 248
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1412 248
        AN(ptr);
1413
1414 248
        to->status = vbe16dec(ptr + 2);
1415 248
        ptr += 4;
1416
1417 1488
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1418 1240
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1419 496
                        continue;
1420 744
                http_SetH(to, u, ptr);
1421 744
                ptr = strchr(ptr, '\0') + 1;
1422 744
        }
1423 248
        nhd_before_merge = to->nhd;
1424 1480
        while (*ptr != '\0') {
1425 1232
                p = strchr(ptr, ':');
1426 1232
                AN(p);
1427 1232
                u = http_findhdr(to, p - ptr, ptr);
1428 1232
                if (u == 0 || u >= nhd_before_merge)
1429 584
                        http_SetHeader(to, ptr);
1430 1232
                ptr = strchr(ptr, '\0') + 1;
1431
        }
1432 248
}
1433
1434
/*--------------------------------------------------------------------*/
1435
1436
static void
1437 55722
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1438
{
1439
1440 55722
        assert(n < HTTP_HDR_FIRST);
1441 55722
        Tcheck(fm->hd[n]);
1442 55722
        to->hd[n] = fm->hd[n];
1443 55722
        to->hdf[n] = fm->hdf[n];
1444 55722
        http_VSLH(to, n);
1445 55722
}
1446
1447
/*--------------------------------------------------------------------*/
1448
1449
void
1450 18576
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1451
{
1452
        unsigned u;
1453
1454 18576
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1455 18576
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1456
1457 18576
        http_linkh(to, fm, HTTP_HDR_METHOD);
1458 18576
        http_linkh(to, fm, HTTP_HDR_URL);
1459 18576
        http_linkh(to, fm, HTTP_HDR_PROTO);
1460 18576
        to->protover = fm->protover;
1461 18576
        to->status = fm->status;
1462
1463 18576
        to->nhd = HTTP_HDR_FIRST;
1464 98250
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1465 79674
                Tcheck(fm->hd[u]);
1466 79674
                if (http_isfiltered(fm, u, how))
1467 920
                        continue;
1468 78754
                assert (to->nhd < to->shd);
1469 78754
                to->hd[to->nhd] = fm->hd[u];
1470 78754
                to->hdf[to->nhd] = 0;
1471 78754
                http_VSLH(to, to->nhd);
1472 78754
                to->nhd++;
1473 78754
        }
1474 18576
}
1475
1476
/*--------------------------------------------------------------------
1477
 * This function copies any header fields which reference foreign
1478
 * storage into our own WS.
1479
 */
1480
1481
void
1482 18336
http_CopyHome(const struct http *hp)
1483
{
1484
        unsigned u, l;
1485
        const char *p;
1486
1487 199291
        for (u = 0; u < hp->nhd; u++) {
1488 180955
                if (hp->hd[u].b == NULL) {
1489 36664
                        assert(u < HTTP_HDR_FIRST);
1490 36664
                        continue;
1491
                }
1492
1493 144291
                l = Tlen(hp->hd[u]);
1494 144291
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1495 11615
                        continue;
1496
1497 132676
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1498 132676
                if (p == NULL) {
1499 0
                        http_fail(hp);
1500 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hp->hd[u].b));
1501 0
                        return;
1502
                }
1503 132676
                hp->hd[u].b = p;
1504 132676
                hp->hd[u].e = p + l;
1505 132676
        }
1506 18336
}
1507
1508
/*--------------------------------------------------------------------*/
1509
1510
void
1511 76523
http_SetHeader(struct http *to, const char *header)
1512
{
1513
1514 76523
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1515 76523
        if (to->nhd >= to->shd) {
1516 8
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1517 8
                http_fail(to);
1518 8
                return;
1519
        }
1520 76515
        http_SetH(to, to->nhd++, header);
1521 76523
}
1522
1523
/*--------------------------------------------------------------------*/
1524
1525
void
1526 34028
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1527
{
1528
1529 34028
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1530 34028
        if (http_HdrIs(to, hdr, val))
1531 3088
                return;
1532 30940
        http_Unset(to, hdr);
1533 30940
        http_PrintfHeader(to, "%s %s", hdr->str, val);
1534 34028
}
1535
1536
void
1537 87132
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1538
{
1539
        const char *old;
1540
1541 87132
        http_CollectHdr(to, hdr);
1542 87132
        if (http_GetHdr(to, hdr, &old)) {
1543 384
                http_Unset(to, hdr);
1544 384
                http_PrintfHeader(to, "%s %s, %s", hdr->str, old, val);
1545 384
        } else {
1546 86748
                http_PrintfHeader(to, "%s %s", hdr->str, val);
1547
        }
1548 87132
}
1549
1550
void
1551 204913
http_PrintfHeader(struct http *to, const char *fmt, ...)
1552
{
1553
        va_list ap, ap2;
1554
        struct vsb vsb[1];
1555
        size_t sz;
1556
        char *p;
1557
1558 204913
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1559
1560 204913
        va_start(ap, fmt);
1561 204913
        va_copy(ap2, ap);
1562
1563 204913
        WS_VSB_new(vsb, to->ws);
1564 204913
        VSB_vprintf(vsb, fmt, ap);
1565 204913
        p = WS_VSB_finish(vsb, to->ws, &sz);
1566
1567 204913
        if (p == NULL || to->nhd >= to->shd) {
1568 226
                http_fail(to);
1569 226
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1570 226
        } else {
1571 204689
                http_SetH(to, to->nhd++, p);
1572
        }
1573 204915
        va_end(ap);
1574 204915
        va_end(ap2);
1575 204915
}
1576
1577
void
1578 8455
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1579
{
1580
        char *p;
1581
1582 8455
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1583 8455
        if (to->nhd >= to->shd) {
1584 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1585 0
                http_fail(to);
1586 0
                return;
1587
        }
1588 8455
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1589 8455
        if (p == NULL) {
1590 616
                http_fail(to);
1591 616
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1592 616
                return;
1593
        }
1594 7839
        strcpy(p, fmt);
1595 7839
        VTIM_format(now, strchr(p, '\0'));
1596 7839
        http_SetH(to, to->nhd++, p);
1597 8455
}
1598
1599
const char *
1600 56860
http_ViaHeader(void)
1601
{
1602
1603 56860
        return (via_hdr);
1604
}
1605
1606
/*--------------------------------------------------------------------*/
1607
1608
void
1609 186287
http_Unset(struct http *hp, hdr_t hdr)
1610
{
1611
        uint16_t u, v;
1612
1613 1210286
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1614 1023999
                Tcheck(hp->hd[u]);
1615 1023999
                if (http_IsHdr(&hp->hd[u], hdr)) {
1616 8312
                        http_VSLH_del(hp, u);
1617 8312
                        continue;
1618
                }
1619 1015687
                if (v != u) {
1620 23688
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1621 23688
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1622 23688
                }
1623 1015687
                v++;
1624 1015687
        }
1625 186287
        hp->nhd = v;
1626 186287
}