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) char b[] = "*" a ":";
57
#include "tbl/http_headers.h"
58
59
const char H__Status[]  = "\010:status:";
60
const char H__Proto[]   = "\007:proto:";
61
const char H__Reason[]  = "\010: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
        char            *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 2937041
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 2937041
        if (b == NULL || e == NULL)
188 266
                return (NULL);
189 2937007
        assert(b <= e);
190 2937007
        u = (unsigned)(e - b);
191 2937007
        assert(b + u == e);
192 2937007
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
193 1162
                return (NULL);
194 5871690
        u += http_asso_values[(uint8_t)(e[-1])] +
195 2935845
             http_asso_values[(uint8_t)(b[0])];
196 2935845
        if (u > GPERF_MAX_HASH_VALUE)
197 39880
                return (NULL);
198 2895965
        retval = &http_hdrflg[u];
199 2895965
        if (retval->hdr == NULL)
200 10105
                return (NULL);
201 2885860
        if (!http_hdr_at(retval->hdr + 1, b, e - b))
202 36240
                return (NULL);
203 2849620
        return (retval);
204 2937005
}
205
206
/*--------------------------------------------------------------------*/
207
208
static void
209 1907152
http_init_hdr(char *hdr, int flg)
210
{
211
        struct http_hdrflg *f;
212
213 1907152
        hdr[0] = strlen(hdr + 1);
214 1907152
        f = http_hdr_flags(hdr + 1, hdr + hdr[0]);
215 1907152
        AN(f);
216 1907152
        assert(f->hdr == hdr);
217 1907152
        f->flag = flg;
218 1907152
}
219
220
void
221 36676
HTTP_Init(void)
222
{
223
        struct vsb *vsb;
224
225
#define HTTPH(a, b, c) http_init_hdr(b, c);
226
#include "tbl/http_headers.h"
227
228
        vsb = VSB_new_auto();
229 36676
        AN(vsb);
230
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
231
            heritage.identity);
232 36676
        AZ(VSB_finish(vsb));
233 36676
        REPLACE(via_hdr, VSB_data(vsb));
234
        VSB_destroy(&vsb);
235
}
236
237
/*--------------------------------------------------------------------
238
 * These two functions are in an incestuous relationship with the
239
 * order of macros in include/tbl/vsl_tags_http.h
240
 *
241
 * The http->logtag is the SLT_*Method enum, and we add to that, to
242
 * get the SLT_ to use.
243
 */
244
245
static void
246 4842013
http_VSLH(const struct http *hp, unsigned hdr)
247
{
248
        int i;
249
250 4842013
        if (hp->vsl != NULL) {
251 4842127
                assert(VXID_TAG(hp->vsl->wid));
252 4842127
                i = hdr;
253 4842127
                if (i > HTTP_HDR_FIRST)
254 2542887
                        i = HTTP_HDR_FIRST;
255 4842127
                i += hp->logtag;
256 4842127
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
257 4842127
        }
258 4842281
}
259
260
static void
261 36920
http_VSLH_del(const struct http *hp, unsigned hdr)
262
{
263
        int i;
264
265 36920
        if (hp->vsl != NULL) {
266
                /* We don't support unsetting stuff in the first line */
267 36920
                assert (hdr >= HTTP_HDR_FIRST);
268 36920
                assert(VXID_TAG(hp->vsl->wid));
269 36920
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
270 36920
                i += hp->logtag;
271 36920
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
272 36920
        }
273 36920
}
274
275
/*--------------------------------------------------------------------*/
276
277
void
278 225821
http_VSL_log(const struct http *hp)
279
{
280
        unsigned u;
281
282 1972809
        for (u = 0; u < hp->nhd; u++)
283 3042453
                if (hp->hd[u].b != NULL)
284 1295465
                        http_VSLH(hp, u);
285 225821
}
286
287
/*--------------------------------------------------------------------*/
288
289
static void
290 4160
http_fail(const struct http *hp)
291
{
292
        char id[WS_ID_SIZE];
293
294 4160
        VSC_C_main->losthdr++;
295 4160
        WS_Id(hp->ws, id);
296 4160
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
297 4160
        WS_MarkOverflow(hp->ws);
298 4160
}
299
300
/*--------------------------------------------------------------------
301
 * List of canonical HTTP response code names from RFC2616
302
 */
303
304
static struct http_msg {
305
        unsigned        nbr;
306
        const char      *status;
307
        const char      *txt;
308
} http_msg[] = {
309
#define HTTP_RESP(n, t) { n, #n, t},
310
#include "tbl/http_response.h"
311
        { 0, "0", NULL }
312
};
313
314
const char *
315 57274
http_Status2Reason(unsigned status, const char **sstr)
316
{
317
        struct http_msg *mp;
318
319 57274
        status %= 1000;
320 57274
        assert(status >= 100);
321 1770299
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
322 1768499
                if (mp->nbr == status) {
323 55474
                        if (sstr)
324 42477
                                *sstr = mp->status;
325 55474
                        return (mp->txt);
326
                }
327 1800
        return ("Unknown HTTP Status");
328 57274
}
329
330
/*--------------------------------------------------------------------*/
331
332
unsigned
333 206378
HTTP_estimate(unsigned nhttp)
334
{
335
336
        /* XXX: We trust the structs to size-aligned as necessary */
337 206378
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
338
}
339
340
struct http *
341 619147
HTTP_create(void *p, uint16_t nhttp, unsigned len)
342
{
343
        struct http *hp;
344
345 619147
        hp = p;
346 619147
        hp->magic = HTTP_MAGIC;
347 619147
        hp->hd = (void*)(hp + 1);
348 619147
        hp->shd = nhttp;
349 619147
        hp->hdf = (void*)(hp->hd + nhttp);
350 619147
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
351 619147
        return (hp);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
void
357 577366
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
358
    enum VSL_tag_e  whence)
359
{
360 577366
        http_Teardown(hp);
361 577366
        hp->nhd = HTTP_HDR_FIRST;
362 577366
        hp->logtag = whence;
363 577366
        hp->ws = ws;
364 577366
        hp->vsl = vsl;
365 577366
}
366
367
/*--------------------------------------------------------------------
368
 * http_Teardown() is a safety feature, we use it to zap all http
369
 * structs once we're done with them, to minimize the risk that
370
 * old stale pointers exist to no longer valid stuff.
371
 */
372
373
void
374 901508
http_Teardown(struct http *hp)
375
{
376
377 901508
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
378 901508
        AN(hp->shd);
379 901508
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
380 901508
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
381 901508
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
382 901508
}
383
384
/*--------------------------------------------------------------------
385
 * Duplicate the http content into another http
386
 * We cannot just memcpy the struct because the hd & hdf are private
387
 * storage to the struct http.
388
 */
389
390
void
391 253920
HTTP_Dup(struct http *to, const struct http * fm)
392
{
393
394 253920
        assert(fm->nhd <= to->shd);
395 253920
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
396 253920
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
397 253920
        to->nhd = fm->nhd;
398 253920
        to->logtag = fm->logtag;
399 253920
        to->status = fm->status;
400 253920
        to->protover = fm->protover;
401 253920
}
402
403
404
/*--------------------------------------------------------------------
405
 * Clone the entire http structure, including vsl & ws
406
 */
407
408
void
409 239283
HTTP_Clone(struct http *to, const struct http * const fm)
410
{
411
412 239283
        HTTP_Dup(to, fm);
413 239283
        to->vsl = fm->vsl;
414 239283
        to->ws = fm->ws;
415 239283
}
416
417
/*--------------------------------------------------------------------*/
418
419
void
420 258239
http_Proto(struct http *to)
421
{
422
        const char *fm;
423
424 258239
        fm = to->hd[HTTP_HDR_PROTO].b;
425
426 516118
        if (fm != NULL &&
427 257920
            (fm[0] == 'H' || fm[0] == 'h') &&
428 257886
            (fm[1] == 'T' || fm[1] == 't') &&
429 257884
            (fm[2] == 'T' || fm[2] == 't') &&
430 257884
            (fm[3] == 'P' || fm[3] == 'p') &&
431 257884
            fm[4] == '/' &&
432 257884
            vct_isdigit(fm[5]) &&
433 257882
            fm[6] == '.' &&
434 257882
            vct_isdigit(fm[7]) &&
435 257879
            fm[8] == '\0') {
436 257879
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
437 257879
        } else {
438 360
                to->protover = 0;
439
        }
440 258239
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 1531451
http_SetH(struct http *to, unsigned n, const char *header)
446
{
447
448 1531451
        assert(n < to->nhd);
449 1531451
        AN(header);
450 1531451
        to->hd[n].b = TRUST_ME(header);
451 1531451
        to->hd[n].e = strchr(to->hd[n].b, '\0');
452 1531451
        to->hdf[n] = 0;
453 1531451
        http_VSLH(to, n);
454 1531451
        if (n == HTTP_HDR_PROTO)
455 52356
                http_Proto(to);
456 1531451
}
457
458
/*--------------------------------------------------------------------*/
459
460
static void
461 1440
http_PutField(struct http *to, int field, const char *string)
462
{
463
        const char *p;
464
465 1440
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
466 1440
        p = WS_Copy(to->ws, string, -1);
467 1440
        if (p == NULL) {
468 40
                http_fail(to);
469 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
470 40
                return;
471
        }
472 1400
        http_SetH(to, field, p);
473 1440
}
474
475
/*--------------------------------------------------------------------*/
476
477
int
478 4567717
http_IsHdr(const txt *hh, hdr_t hdr)
479
{
480
        unsigned l;
481
482 4567717
        Tcheck(*hh);
483 4567717
        AN(hdr);
484 4567717
        l = hdr[0];
485 4567717
        assert(l == strlen(hdr + 1));
486 4567717
        assert(hdr[l] == ':');
487 4567717
        hdr++;
488 4567717
        return (http_hdr_at(hdr, hh->b, l));
489
}
490
491
/*--------------------------------------------------------------------*/
492
493
static unsigned
494 5835819
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
495
{
496
        unsigned u;
497
498 25185552
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
499 20632943
                Tcheck(hp->hd[u]);
500 20632943
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
501 3772108
                        continue;
502 16860835
                if (hp->hd[u].b[l] != ':')
503 14186457
                        continue;
504 2674378
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
505 1391168
                        continue;
506 1283210
                return (u);
507
        }
508 4552609
        return (0);
509 5835819
}
510
511
/*--------------------------------------------------------------------
512
 * Count how many instances we have of this header
513
 */
514
515
unsigned
516 291871
http_CountHdr(const struct http *hp, hdr_t hdr)
517
{
518 291871
        unsigned retval = 0;
519
        unsigned u;
520
521 291871
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
522
523 974135
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
524 682264
                Tcheck(hp->hd[u]);
525 682264
                if (http_IsHdr(&hp->hd[u], hdr))
526 144986
                        retval++;
527 682264
        }
528 291871
        return (retval);
529
}
530
531
/*--------------------------------------------------------------------
532
 * This function collapses multiple header lines of the same name.
533
 * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
534
 */
535
536
void
537 941056
http_CollectHdr(struct http *hp, hdr_t hdr)
538
{
539
540 941056
        http_CollectHdrSep(hp, hdr, NULL);
541 941056
}
542
543
/*--------------------------------------------------------------------
544
 * You may prefer to collapse header fields using a different separator.
545
 * For Cookie headers, the separator is "; " for example. That's probably
546
 * the only example too.
547
 */
548
549
void
550 946136
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
551
{
552
        unsigned u, l, lsep, ml, f, x, d;
553 946136
        char *b = NULL, *e = NULL;
554
        const char *v;
555
556 946136
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
557 946136
        if (WS_Overflowed(hp->ws))
558 800
                return;
559
560 945336
        if (sep == NULL || *sep == '\0')
561 940263
                sep = ", ";
562 945348
        lsep = strlen(sep);
563
564 945348
        l = hdr[0];
565 945348
        assert(l == strlen(hdr + 1));
566 945348
        assert(hdr[l] == ':');
567 945348
        f = http_findhdr(hp, l - 1, hdr + 1);
568 945348
        if (f == 0)
569 929285
                return;
570
571 59021
        for (d = u = f + 1; u < hp->nhd; u++) {
572 42958
                Tcheck(hp->hd[u]);
573 42958
                if (!http_IsHdr(&hp->hd[u], hdr)) {
574 42238
                        if (d != u) {
575 2840
                                hp->hd[d] = hp->hd[u];
576 2840
                                hp->hdf[d] = hp->hdf[u];
577 2840
                        }
578 42238
                        d++;
579 42238
                        continue;
580
                }
581 720
                if (b == NULL) {
582
                        /* Found second header, start our collection */
583 640
                        ml = WS_ReserveAll(hp->ws);
584 640
                        b = WS_Reservation(hp->ws);
585 640
                        e = b + ml;
586 640
                        x = Tlen(hp->hd[f]);
587 640
                        if (b + x >= e) {
588 0
                                http_fail(hp);
589 0
                                VSLbs(hp->vsl, SLT_LostHeader,
590 0
                                    TOSTRAND(hdr + 1));
591 0
                                WS_Release(hp->ws, 0);
592 0
                                return;
593
                        }
594 640
                        memcpy(b, hp->hd[f].b, x);
595 640
                        b += x;
596 640
                }
597
598 720
                AN(b);
599 720
                AN(e);
600
601
                /* Append the Nth header we found */
602 720
                x = Tlen(hp->hd[u]) - l;
603
604 720
                v = hp->hd[u].b + *hdr;
605 1440
                while (vct_issp(*v)) {
606 720
                        v++;
607 720
                        x--;
608
                }
609
610 720
                if (b + lsep + x >= e) {
611 0
                        http_fail(hp);
612 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hdr + 1));
613 0
                        WS_Release(hp->ws, 0);
614 0
                        return;
615
                }
616 720
                memcpy(b, sep, lsep);
617 720
                b += lsep;
618 720
                memcpy(b, v, x);
619 720
                b += x;
620 720
        }
621 16063
        if (b == NULL)
622 15423
                return;
623 640
        hp->nhd = (uint16_t)d;
624 640
        AN(e);
625 640
        *b = '\0';
626 640
        hp->hd[f].b = WS_Reservation(hp->ws);
627 640
        hp->hd[f].e = b;
628 640
        WS_ReleaseP(hp->ws, b + 1);
629 946148
}
630
631
/*--------------------------------------------------------------------*/
632
633
int
634 4885608
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
635
{
636
        unsigned u, l;
637
        const char *p;
638
639 4885608
        l = hdr[0];
640 4885608
        assert(l == strlen(hdr + 1));
641 4885608
        assert(hdr[l] == ':');
642 4885608
        hdr++;
643 4885608
        u = http_findhdr(hp, l - 1, hdr);
644 4885608
        if (u == 0) {
645 3621556
                if (ptr != NULL)
646 3256608
                        *ptr = NULL;
647 3621556
                return (0);
648
        }
649 1264052
        if (ptr != NULL) {
650 1033749
                p = hp->hd[u].b + l;
651 2065750
                while (vct_issp(*p))
652 1032001
                        p++;
653 1033749
                *ptr = p;
654 1033749
        }
655 1264052
        return (1);
656 4885608
}
657
658
/*-----------------------------------------------------------------------------
659
 * Split source string at any of the separators, return pointer to first
660
 * and last+1 char of substrings, with whitespace trimmed at both ends.
661
 * If sep being an empty string is shorthand for VCT::SP
662
 * If stop is NULL, src is NUL terminated.
663
 */
664
665
static int
666 90930
http_split(const char **src, const char *stop, const char *sep,
667
    const char **b, const char **e)
668
{
669
        const char *p, *q;
670
671 90930
        AN(src);
672 90930
        AN(*src);
673 90930
        AN(sep);
674 90930
        AN(b);
675 90930
        AN(e);
676
677 90930
        if (stop == NULL)
678 90649
                stop = strchr(*src, '\0');
679
680 156275
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
681 3480
                continue;
682
683 90930
        if (p >= stop) {
684 32545
                *b = NULL;
685 32545
                *e = NULL;
686 32545
                return (0);
687
        }
688
689 58385
        *b = p;
690 58385
        if (*sep == '\0') {
691 0
                for (q = p + 1; q < stop && !vct_issp(*q); q++)
692 0
                        continue;
693 0
                *e = q;
694 0
                *src = q;
695 0
                return (1);
696
        }
697 287282
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
698 228897
                continue;
699 58385
        *src = q;
700 58385
        while (q > p && vct_issp(q[-1]))
701 0
                q--;
702 58383
        *e = q;
703 58383
        return (1);
704 90928
}
705
706
/*-----------------------------------------------------------------------------
707
 * Comparison rule for tokens:
708
 *      if target string starts with '"', we use memcmp() and expect closing
709
 *      double quote as well
710
 *      otherwise we use http_tok_at()
711
 *
712
 * On match we increment *bp past the token name.
713
 */
714
715
static int
716 50919
http_istoken(const char **bp, const char *e, const char *token)
717
{
718 50919
        int fl = strlen(token);
719
        const char *b;
720
721 50919
        AN(bp);
722 50919
        AN(e);
723 50919
        AN(token);
724
725 50919
        b = *bp;
726
727 50919
        if (b + fl + 2 <= e && *b == '"' &&
728 0
            !memcmp(b + 1, token, fl) && b[fl + 1] == '"') {
729 0
                *bp += fl + 2;
730 0
                return (1);
731
        }
732 52519
        if (b + fl <= e && http_tok_at(b, token, fl) &&
733 23840
            (b + fl == e || !vct_istchar(b[fl]))) {
734 23840
                *bp += fl;
735 23840
                return (1);
736
        }
737 27079
        return (0);
738 50919
}
739
740
/*-----------------------------------------------------------------------------
741
 * Find a given data element (token) in a header according to RFC2616's #rule
742
 * (section 2.1, p15)
743
 *
744
 * On case sensitivity:
745
 *
746
 * Section 4.2 (Messages Headers) defines field (header) name as case
747
 * insensitive, but the field (header) value/content may be case-sensitive.
748
 *
749
 * http_GetHdrToken looks up a token in a header value and the rfc does not say
750
 * explicitly if tokens are to be compared with or without respect to case.
751
 *
752
 * But all examples and specific statements regarding tokens follow the rule
753
 * that unquoted tokens are to be matched case-insensitively and quoted tokens
754
 * case-sensitively.
755
 *
756
 * The optional pb and pe arguments will point to the token content start and
757
 * end+1, white space trimmed on both sides.
758
 */
759
760
int
761 569855
http_GetHdrToken(const struct http *hp, hdr_t hdr,
762
    const char *token, const char **pb, const char **pe)
763
{
764
        const char *h, *b, *e;
765
766 569855
        if (pb != NULL)
767 432914
                *pb = NULL;
768 569855
        if (pe != NULL)
769 132009
                *pe = NULL;
770 569855
        if (!http_GetHdr(hp, hdr, &h))
771 520415
                return (0);
772 49440
        AN(h);
773
774 76520
        while (http_split(&h, NULL, ",", &b, &e))
775 50920
                if (http_istoken(&b, e, token))
776 23840
                        break;
777 49440
        if (b == NULL)
778 25600
                return (0);
779 23840
        if (pb != NULL) {
780 23680
                for (; vct_islws(*b); b++)
781 200
                        continue;
782 23480
                if (b == e) {
783 21920
                        b = NULL;
784 21920
                        e = NULL;
785 21920
                }
786 23480
                *pb = b;
787 23480
                if (pe != NULL)
788 21640
                        *pe = e;
789 23480
        }
790 23840
        return (1);
791 569855
}
792
793
/*--------------------------------------------------------------------
794
 * Find a given header field's quality value (qvalue).
795
 */
796
797
double
798 132010
http_GetHdrQ(const struct http *hp, hdr_t hdr, const char *field)
799
{
800
        const char *hb, *he, *b, *e;
801
        int i;
802
        double a, f;
803
804 132010
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
805 132010
        if (!i)
806 110370
                return (0.);
807
808 21640
        if (hb == NULL)
809 21360
                return (1.);
810 280
        while (http_split(&hb, he, ";", &b, &e)) {
811 280
                if (*b != 'q')
812 0
                        continue;
813 280
                for (b++; b < e && vct_issp(*b); b++)
814 0
                        continue;
815 280
                if (b == e || *b != '=')
816 0
                        continue;
817 280
                break;
818
        }
819 280
        if (b == NULL)
820 0
                return (1.);
821 280
        for (b++; b < e && vct_issp(*b); b++)
822 0
                continue;
823 280
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
824 40
                return (0.);
825 240
        a = 0;
826 480
        while (b < e && vct_isdigit(*b)) {
827 240
                a *= 10.;
828 240
                a += *b - '0';
829 240
                b++;
830
        }
831 240
        if (b == e || *b++ != '.')
832 40
                return (a);
833 200
        f = .1;
834 640
        while (b < e && vct_isdigit(*b)) {
835 440
                a += f * (*b - '0');
836 440
                f *= .1;
837 440
                b++;
838
        }
839 200
        return (a);
840 132010
}
841
842
/*--------------------------------------------------------------------
843
 * Find a given header field's value.
844
 */
845
846
int
847 300920
http_GetHdrField(const struct http *hp, hdr_t hdr,
848
    const char *field, const char **ptr)
849
{
850
        const char *h;
851
        int i;
852
853 300920
        if (ptr != NULL)
854 152716
                *ptr = NULL;
855
856 300920
        h = NULL;
857 300920
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
858 300920
        if (!i)
859 299080
                return (i);
860
861 1840
        if (ptr != NULL && h != NULL) {
862
                /* Skip whitespace, looking for '=' */
863 1280
                while (*h && vct_issp(*h))
864 0
                        h++;
865 1280
                if (*h == '=') {
866 1280
                        h++;
867 1440
                        while (*h && vct_issp(*h))
868 160
                                h++;
869 1280
                        *ptr = h;
870 1280
                }
871 1280
        }
872 1840
        return (i);
873 300920
}
874
875
/*--------------------------------------------------------------------*/
876
877
ssize_t
878 431573
http_GetContentLength(const struct http *hp)
879
{
880
        ssize_t cl;
881
        const char *b;
882
883 431573
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
884
885 431573
        if (!http_GetHdr(hp, H_Content_Length, &b))
886 169249
                return (-1);
887 262324
        cl = VNUM_uint(b, NULL, &b);
888 262324
        if (cl < 0)
889 160
                return (-2);
890 262164
        while (vct_islws(*b))
891 0
                b++;
892 262164
        if (*b != '\0')
893 0
                return (-2);
894 262164
        return (cl);
895 431573
}
896
897
ssize_t
898 78000
http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi)
899
{
900
        ssize_t tmp, cl;
901
        const char *b, *t;
902
903 78000
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
904
905 78000
        if (lo == NULL)
906 0
                lo = &tmp;
907 78000
        if (hi == NULL)
908 0
                hi = &tmp;
909
910 78000
        *lo = *hi = -1;
911
912 78000
        if (!http_GetHdr(hp, H_Content_Range, &b))
913 77680
                return (-1);
914
915 320
        t = strchr(b, ' ');
916 320
        if (t == NULL)
917 40
                return (-2);            // Missing space after range unit
918
919 280
        if (!http_range_at(b, bytes, t - b))
920 0
                return (-1);            // Unknown range unit, ignore
921 280
        b = t + 1;
922
923 280
        if (*b == '*') {                // Content-Range: bytes */123
924 120
                *lo = *hi = -1;
925 120
                b++;
926 120
        } else {                        // Content-Range: bytes 1-2/3
927 160
                *lo = VNUM_uint(b, NULL, &b);
928 160
                if (*lo < 0)
929 0
                        return (-2);
930 160
                if (*b != '-')
931 0
                        return (-2);
932 160
                *hi = VNUM_uint(b + 1, NULL, &b);
933 160
                if (*hi < 0)
934 0
                        return (-2);
935
        }
936 280
        if (*b != '/')
937 0
                return (-2);
938 280
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
939 40
                cl = -1;
940 40
                b += 2;
941 40
        } else {
942 240
                cl = VNUM_uint(b + 1, NULL, &b);
943 240
                if (cl <= 0)
944 0
                        return (-2);
945
        }
946 280
        while (vct_islws(*b))
947 0
                b++;
948 280
        if (*b != '\0')
949 0
                return (-2);
950 280
        if (*lo > *hi)
951 0
                return (-2);
952 280
        assert(cl >= -1);
953 280
        if (*lo >= cl || *hi >= cl)
954 40
                return (-2);
955 240
        AN(cl);
956 240
        return (cl);
957 78000
}
958
959
const char *
960 79879
http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi, ssize_t len)
961
{
962
        ssize_t tmp_lo, tmp_hi;
963
        const char *b, *t;
964
965 79879
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
966
967 79879
        if (lo == NULL)
968 0
                lo = &tmp_lo;
969 79879
        if (hi == NULL)
970 0
                hi = &tmp_hi;
971
972 79879
        *lo = *hi = -1;
973
974 79879
        if (!http_GetHdr(hp, H_Range, &b))
975 77799
                return (NULL);
976
977 2080
        t = strchr(b, '=');
978 2080
        if (t == NULL)
979 80
                return ("Missing '='");
980
981 2000
        if (!http_range_at(b, bytes, t - b))
982 120
                return ("Not Bytes");
983 1880
        b = t + 1;
984
985 1880
        *lo = VNUM_uint(b, NULL, &b);
986 1880
        if (*lo == -2)
987 0
                return ("Low number too big");
988 1880
        if (*b++ != '-')
989 0
                return ("Missing hyphen");
990
991 1880
        *hi = VNUM_uint(b, NULL, &b);
992 1880
        if (*hi == -2)
993 0
                return ("High number too big");
994 1880
        if (*lo == -1 && *hi == -1)
995 40
                return ("Neither high nor low");
996 1840
        if (*lo == -1 && *hi == 0)
997 40
                return ("No low, high is zero");
998 1800
        if (*hi >= 0 && *hi < *lo)
999 40
                return ("high smaller than low");
1000
1001 1800
        while (vct_islws(*b))
1002 40
                b++;
1003 1760
        if (*b != '\0')
1004 40
                return ("Trailing stuff");
1005
1006 1720
        assert(*lo >= -1);
1007 1720
        assert(*hi >= -1);
1008
1009 1720
        if (len <= 0)
1010 640
                return (NULL);                  // Allow 200 response
1011
1012 1080
        if (*lo < 0) {
1013 120
                assert(*hi > 0);
1014 120
                *lo = len - *hi;
1015 120
                if (*lo < 0)
1016 40
                        *lo = 0;
1017 120
                *hi = len - 1;
1018 1080
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1019 320
                *hi = len - 1;
1020 320
        }
1021
1022 1080
        if (*lo >= len)
1023 40
                return ("low range beyond object");
1024
1025 1040
        return (NULL);
1026 79879
}
1027
1028
/*--------------------------------------------------------------------
1029
 */
1030
1031
stream_close_t
1032 226448
http_DoConnection(struct http *hp, stream_close_t sc_close)
1033
{
1034
        const char *h, *b, *e;
1035
        stream_close_t retval;
1036
        unsigned u, v;
1037
        struct http_hdrflg *f;
1038
1039 226448
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1040 226448
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1041
1042 226448
        if (hp->protover == 10)
1043 1545
                retval = SC_REQ_HTTP10;
1044
        else
1045 224903
                retval = SC_NULL;
1046
1047 226448
        http_CollectHdr(hp, H_Connection);
1048 226448
        if (!http_GetHdr(hp, H_Connection, &h))
1049 219383
                return (retval);
1050 7065
        AN(h);
1051 14129
        while (http_split(&h, NULL, ",", &b, &e)) {
1052 7184
                u = pdiff(b, e);
1053 7184
                if (u == 5 && http_hdr_at(b, "close", u))
1054 5785
                        retval = sc_close;
1055 7184
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1056 920
                        retval = SC_NULL;
1057
1058
                /* Refuse removal of well-known-headers if they would pass. */
1059 7184
                f = http_hdr_flags(b, e);
1060 7184
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1061 120
                        return (SC_RX_BAD);
1062
1063 34307
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1064 27243
                        Tcheck(hp->hd[v]);
1065 27243
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1066 1240
                                continue;
1067 26003
                        if (hp->hd[v].b[u] != ':')
1068 24003
                                continue;
1069 2000
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1070 1520
                                continue;
1071 480
                        hp->hdf[v] |= HDF_FILTER;
1072 480
                }
1073
        }
1074 6945
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1075 6945
        return (retval);
1076 226448
}
1077
1078
/*--------------------------------------------------------------------*/
1079
1080
int
1081 430359
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1082
{
1083
        const char *p;
1084
1085 430359
        if (!http_GetHdr(hp, hdr, &p))
1086 407359
                return (0);
1087 23000
        AN(p);
1088 23000
        if (http_tok_eq(p, val))
1089 21960
                return (1);
1090 1040
        return (0);
1091 430359
}
1092
1093
/*--------------------------------------------------------------------*/
1094
1095
uint16_t
1096 557127
http_GetStatus(const struct http *hp)
1097
{
1098
1099 557127
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1100 557127
        return (hp->status);
1101
}
1102
1103
int
1104 389114
http_IsStatus(const struct http *hp, int val)
1105
{
1106
1107 389114
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1108 389114
        assert(val >= 100 && val <= 999);
1109 389114
        return (val == (hp->status % 1000));
1110
}
1111
1112
/*--------------------------------------------------------------------
1113
 * Setting the status will also set the Reason appropriately
1114
 */
1115
1116
void
1117 43918
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1118
{
1119
        char buf[4];
1120 43918
        const char *sstr = NULL;
1121
1122 43918
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1123
        /*
1124
         * We allow people to use top digits for internal VCL
1125
         * signalling, but strip them from the ASCII version.
1126
         */
1127 43918
        to->status = status;
1128 43918
        status %= 1000;
1129 43918
        assert(status >= 100);
1130
1131 43918
        if (reason == NULL)
1132 8160
                reason = http_Status2Reason(status, &sstr);
1133
        else
1134 35758
                (void)http_Status2Reason(status, &sstr);
1135
1136 43918
        if (sstr) {
1137 42478
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1138 42478
        } else {
1139 1440
                bprintf(buf, "%03d", status);
1140 1440
                http_PutField(to, HTTP_HDR_STATUS, buf);
1141
        }
1142 43918
        http_SetH(to, HTTP_HDR_REASON, reason);
1143 43918
}
1144
1145
/*--------------------------------------------------------------------*/
1146
1147
const char *
1148 204168
http_GetMethod(const struct http *hp)
1149
{
1150
1151 204168
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1152 204168
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1153 204168
        return (hp->hd[HTTP_HDR_METHOD].b);
1154
}
1155
1156
/*--------------------------------------------------------------------
1157
 * Force a particular header field to a particular value
1158
 */
1159
1160
void
1161 300456
http_ForceField(struct http *to, unsigned n, const char *t)
1162
{
1163
        int i;
1164
1165 300456
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1166 300456
        assert(n < HTTP_HDR_FIRST);
1167 300456
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1168 300456
        AN(t);
1169
1170
        /* NB: method names and protocol versions are case-sensitive. */
1171 300456
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1172 4480
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1173 4480
                i += to->logtag;
1174
                /* XXX: this is a dead branch */
1175 4480
                if (n >= HTTP_HDR_FIRST)
1176 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1177 4480
                http_SetH(to, n, t);
1178 4480
        }
1179 300456
}
1180
1181
/*--------------------------------------------------------------------*/
1182
1183
void
1184 40399
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1185
    const char *reason)
1186
{
1187
1188 40399
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1189 40399
        if (proto != NULL)
1190 40399
                http_SetH(to, HTTP_HDR_PROTO, proto);
1191 40399
        http_SetStatus(to, status, reason);
1192 40399
}
1193
1194
/*--------------------------------------------------------------------
1195
 * check if header is filtered by the dynamic marker or the static
1196
 * definitions in http_headers.h
1197
 */
1198
1199
static inline int
1200 1544439
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1201
{
1202
        const char *e;
1203
        const struct http_hdrflg *f;
1204
1205 1544439
        if (fm->hdf[u] & HDF_FILTER)
1206 680
                return (1);
1207 1543759
        if (u < HTTP_HDR_FIRST)
1208 521110
                return (0);
1209 1022649
        e = strchr(fm->hd[u].b, ':');
1210 1022649
        if (e == NULL)
1211 0
                return (0);
1212 1022649
        f = http_hdr_flags(fm->hd[u].b, e);
1213 1022649
        return (f != NULL && f->flag & how);
1214 1544439
}
1215
1216
int
1217 24631
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1218
{
1219
1220 24631
        return (http_isfiltered(fm, u, how));
1221
}
1222
1223
/*--------------------------------------------------------------------
1224
 * Estimate how much workspace we need to Filter this header according
1225
 * to 'how'.
1226
 */
1227
1228
unsigned
1229 86992
http_EstimateWS(const struct http *fm, unsigned how)
1230
{
1231
        unsigned u, l;
1232
1233 86992
        l = 4;
1234 86992
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1235 830719
        for (u = 0; u < fm->nhd; u++) {
1236 743727
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1237 173984
                        continue;
1238 569743
                Tcheck(fm->hd[u]);
1239 569743
                if (http_isfiltered(fm, u, how))
1240 10360
                        continue;
1241 559383
                l += Tlen(fm->hd[u]) + 1L;
1242 559383
        }
1243 86992
        return (PRNDUP(l + 1L));
1244
}
1245
1246
/*--------------------------------------------------------------------
1247
 * Encode http struct as byte string.
1248
 *
1249
 * XXX: We could save considerable special-casing below by encoding also
1250
 * XXX: H__Status, H__Reason and H__Proto into the string, but it would
1251
 * XXX: add 26-30 bytes to all encoded objects to save a little code.
1252
 * XXX: It could possibly be a good idea for later HTTP versions.
1253
 */
1254
1255
void
1256 86758
HTTP_Encode(const struct http *fm, uint8_t *p0, unsigned l, unsigned how)
1257
{
1258
        unsigned u, w;
1259
        uint16_t n;
1260
        uint8_t *p, *e;
1261
1262 86758
        AN(p0);
1263 86758
        AN(l);
1264 86758
        p = p0;
1265 86758
        e = p + l;
1266 86758
        assert(p + 5 <= e);
1267 86758
        assert(fm->nhd <= fm->shd);
1268 86758
        n = HTTP_HDR_FIRST - 3;
1269 86758
        vbe16enc(p + 2, fm->status);
1270 86758
        p += 4;
1271 86758
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1272 828197
        for (u = 0; u < fm->nhd; u++) {
1273 741439
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1274 173516
                        continue;
1275 567923
                Tcheck(fm->hd[u]);
1276 567923
                if (http_isfiltered(fm, u, how))
1277 10357
                        continue;
1278 557566
                http_VSLH(fm, u);
1279 557566
                w = Tlen(fm->hd[u]) + 1L;
1280 557566
                assert(p + w + 1 <= e);
1281 557566
                memcpy(p, fm->hd[u].b, w);
1282 557566
                p += w;
1283 557566
                n++;
1284 557566
        }
1285 86758
        *p++ = '\0';
1286 86758
        assert(p <= e);
1287 86758
        vbe16enc(p0, n + 1);
1288 86758
}
1289
1290
/*--------------------------------------------------------------------
1291
 * Decode byte string into http struct
1292
 */
1293
1294
int
1295 126144
HTTP_Decode(struct http *to, const uint8_t *fm)
1296
{
1297
1298 126144
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1299 126144
        AN(to->vsl);
1300 126144
        AN(fm);
1301 126144
        if (vbe16dec(fm) <= to->shd) {
1302 126058
                to->status = vbe16dec(fm + 2);
1303 126058
                fm += 4;
1304 1191630
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1305 1191630
                        if (to->nhd == HTTP_HDR_METHOD ||
1306 1065432
                            to->nhd == HTTP_HDR_URL) {
1307 252100
                                to->hd[to->nhd].b = NULL;
1308 252100
                                to->hd[to->nhd].e = NULL;
1309 252100
                                continue;
1310
                        }
1311 939530
                        if (*fm == '\0')
1312 126058
                                return (0);
1313 813472
                        to->hd[to->nhd].b = (const void*)fm;
1314 813472
                        fm = (const void*)strchr((const void*)fm, '\0');
1315 813472
                        to->hd[to->nhd].e = (const void*)fm;
1316 813472
                        fm++;
1317 813472
                        http_VSLH(to, to->nhd);
1318 813472
                }
1319 0
        }
1320 172
        VSLb(to->vsl, SLT_Error,
1321
            "Too many headers to Decode object (%u vs. %u)",
1322 86
            vbe16dec(fm), to->shd);
1323 86
        return (-1);
1324 126144
}
1325
1326
/*--------------------------------------------------------------------*/
1327
1328
uint16_t
1329 40
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1330
{
1331
        const char *ptr;
1332 40
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1333 40
        AN(ptr);
1334
1335 40
        return (vbe16dec(ptr + 2));
1336
}
1337
1338
/*--------------------------------------------------------------------*/
1339
1340
/* Get the first packed header */
1341
int
1342 28910
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1343
{
1344
        const char *ptr;
1345
1346 28910
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1347 28910
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1348 28910
        AN(p);
1349
1350 28910
        if (*p == NULL) {
1351 9184
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1352 9184
                AN(ptr);
1353 9184
                ptr += 4;       /* Skip nhd and status */
1354 9184
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1355 9184
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1356 9184
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1357 9184
                *p = ptr;
1358 9184
        } else {
1359 19726
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1360
        }
1361 28910
        if (**p == '\0')
1362 1760
                return (0);
1363 27150
        return (1);
1364 28910
}
1365
1366
const char *
1367 9425
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1368
{
1369
        const char *ptr;
1370
        unsigned l;
1371
1372 9425
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1373 9425
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1374 9425
        AN(hdr);
1375
1376 9425
        l = hdr[0];
1377 9425
        assert(l > 0);
1378 9425
        assert(l == strlen(hdr + 1));
1379 9425
        assert(hdr[l] == ':');
1380 9425
        hdr++;
1381
1382 9425
        if (hdr[0] == ':') {
1383
                /* Special cases */
1384 240
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1385 240
                AN(ptr);
1386 240
                ptr += 4;       /* Skip nhd and status */
1387
1388
                /* XXX: should we also have h2_hdr_eq() ? */
1389 240
                if (!strcmp(hdr, ":proto:"))
1390 40
                        return (ptr);
1391 200
                ptr = strchr(ptr, '\0') + 1;
1392 200
                if (!strcmp(hdr, ":status:"))
1393 160
                        return (ptr);
1394 40
                ptr = strchr(ptr, '\0') + 1;
1395 40
                if (!strcmp(hdr, ":reason:"))
1396 40
                        return (ptr);
1397 0
                WRONG("Unknown magic packed header");
1398 0
        }
1399
1400 28910
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1401 27150
                if (http_hdr_at(ptr, hdr, l)) {
1402 7425
                        ptr += l;
1403 14810
                        while (vct_islws(*ptr))
1404 7385
                                ptr++;
1405 7425
                        return (ptr);
1406
                }
1407
        }
1408
1409 1760
        return (NULL);
1410 9425
}
1411
1412
/*--------------------------------------------------------------------
1413
 * Merge any headers in the oc->OA_HEADER into the struct http if they
1414
 * are not there already.
1415
 */
1416
1417
void
1418 1120
HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to)
1419
{
1420
        const char *ptr;
1421
        unsigned u;
1422
        const char *p;
1423
        unsigned nhd_before_merge;
1424
1425 1120
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1426 1120
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1427 1120
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1428
1429 1120
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1430 1120
        AN(ptr);
1431
1432 1120
        to->status = vbe16dec(ptr + 2);
1433 1120
        ptr += 4;
1434
1435 6720
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1436 5600
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1437 2240
                        continue;
1438 3360
                http_SetH(to, u, ptr);
1439 3360
                ptr = strchr(ptr, '\0') + 1;
1440 3360
        }
1441 1120
        nhd_before_merge = to->nhd;
1442 6600
        while (*ptr != '\0') {
1443 5480
                p = strchr(ptr, ':');
1444 5480
                AN(p);
1445 5480
                u = http_findhdr(to, p - ptr, ptr);
1446 5480
                if (u == 0 || u >= nhd_before_merge)
1447 2440
                        http_SetHeader(to, ptr);
1448 5480
                ptr = strchr(ptr, '\0') + 1;
1449
        }
1450 1120
}
1451
1452
/*--------------------------------------------------------------------*/
1453
1454
static void
1455 267463
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1456
{
1457
1458 267463
        assert(n < HTTP_HDR_FIRST);
1459 267463
        Tcheck(fm->hd[n]);
1460 267463
        to->hd[n] = fm->hd[n];
1461 267463
        to->hdf[n] = fm->hdf[n];
1462 267463
        http_VSLH(to, n);
1463 267463
}
1464
1465
/*--------------------------------------------------------------------*/
1466
1467
void
1468 89158
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1469
{
1470
        unsigned u;
1471
1472 89158
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1473 89158
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1474
1475 89158
        http_linkh(to, fm, HTTP_HDR_METHOD);
1476 89158
        http_linkh(to, fm, HTTP_HDR_URL);
1477 89158
        http_linkh(to, fm, HTTP_HDR_PROTO);
1478 89158
        to->protover = fm->protover;
1479 89158
        to->status = fm->status;
1480
1481 89158
        to->nhd = HTTP_HDR_FIRST;
1482 471252
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1483 382094
                Tcheck(fm->hd[u]);
1484 382094
                if (http_isfiltered(fm, u, how))
1485 4360
                        continue;
1486 377734
                assert (to->nhd < to->shd);
1487 377734
                to->hd[to->nhd] = fm->hd[u];
1488 377734
                to->hdf[to->nhd] = 0;
1489 377734
                http_VSLH(to, to->nhd);
1490 377734
                to->nhd++;
1491 377734
        }
1492 89158
}
1493
1494
/*--------------------------------------------------------------------
1495
 * This function copies any header fields which reference foreign
1496
 * storage into our own WS.
1497
 */
1498
1499
void
1500 87916
http_CopyHome(const struct http *hp)
1501
{
1502
        unsigned u, l;
1503
        const char *p;
1504
1505 954638
        for (u = 0; u < hp->nhd; u++) {
1506 866722
                if (hp->hd[u].b == NULL) {
1507 175832
                        assert(u < HTTP_HDR_FIRST);
1508 175832
                        continue;
1509
                }
1510
1511 690890
                l = Tlen(hp->hd[u]);
1512 690890
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1513 55079
                        continue;
1514
1515 635811
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1516 635811
                if (p == NULL) {
1517 0
                        http_fail(hp);
1518 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hp->hd[u].b));
1519 0
                        return;
1520
                }
1521 635811
                hp->hd[u].b = p;
1522 635811
                hp->hd[u].e = p + l;
1523 635811
        }
1524 87916
}
1525
1526
/*--------------------------------------------------------------------*/
1527
1528
void
1529 362237
http_SetHeader(struct http *to, const char *header)
1530
{
1531
1532 362237
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1533 362237
        if (to->nhd >= to->shd) {
1534 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1535 40
                http_fail(to);
1536 40
                return;
1537
        }
1538 362197
        http_SetH(to, to->nhd++, header);
1539 362237
}
1540
1541
/*--------------------------------------------------------------------*/
1542
1543
void
1544 161590
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1545
{
1546
1547 161590
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1548 161590
        if (http_HdrIs(to, hdr, val))
1549 14800
                return;
1550 146790
        http_Unset(to, hdr);
1551 146790
        http_PrintfHeader(to, "%s %s", hdr + 1, val);
1552 161590
}
1553
1554
void
1555 414156
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1556
{
1557
        const char *old;
1558
1559 414156
        http_CollectHdr(to, hdr);
1560 414156
        if (http_GetHdr(to, hdr, &old)) {
1561 1920
                http_Unset(to, hdr);
1562 1920
                http_PrintfHeader(to, "%s %s, %s", hdr + 1, old, val);
1563 1920
        } else {
1564 412236
                http_PrintfHeader(to, "%s %s", hdr + 1, val);
1565
        }
1566 414156
}
1567
1568
void
1569 973318
http_PrintfHeader(struct http *to, const char *fmt, ...)
1570
{
1571
        va_list ap, ap2;
1572
        struct vsb vsb[1];
1573
        size_t sz;
1574
        char *p;
1575
1576 973318
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1577
1578 973318
        va_start(ap, fmt);
1579 973318
        va_copy(ap2, ap);
1580
1581 973318
        WS_VSB_new(vsb, to->ws);
1582 973318
        VSB_vprintf(vsb, fmt, ap);
1583 973318
        p = WS_VSB_finish(vsb, to->ws, &sz);
1584
1585 973318
        if (p == NULL || to->nhd >= to->shd) {
1586 1116
                http_fail(to);
1587 1116
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1588 1116
        } else {
1589 972224
                http_SetH(to, to->nhd++, p);
1590
        }
1591 973340
        va_end(ap);
1592 973340
        va_end(ap2);
1593 973340
}
1594
1595
void
1596 40755
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1597
{
1598
        char *p;
1599
1600 40755
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1601 40755
        if (to->nhd >= to->shd) {
1602 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1603 0
                http_fail(to);
1604 0
                return;
1605
        }
1606 40755
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1607 40755
        if (p == NULL) {
1608 3080
                http_fail(to);
1609 3080
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1610 3080
                return;
1611
        }
1612 37675
        strcpy(p, fmt);
1613 37675
        VTIM_format(now, strchr(p, '\0'));
1614 37675
        http_SetH(to, to->nhd++, p);
1615 40755
}
1616
1617
const char *
1618 270121
http_ViaHeader(void)
1619
{
1620
1621 270121
        return (via_hdr);
1622
}
1623
1624
/*--------------------------------------------------------------------*/
1625
1626
void
1627 718859
http_Unset(struct http *hp, hdr_t hdr)
1628
{
1629
        uint16_t u, v;
1630
1631 4561347
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1632 3842488
                Tcheck(hp->hd[u]);
1633 3842488
                if (http_IsHdr(&hp->hd[u], hdr)) {
1634 36920
                        http_VSLH_del(hp, u);
1635 36920
                        continue;
1636
                }
1637 3805568
                if (v != u) {
1638 93600
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1639 93600
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1640 93600
                }
1641 3805568
                v++;
1642 3805568
        }
1643 718859
        hp->nhd = v;
1644 718859
}