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 2934314
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 2934314
        if (b == NULL || e == NULL)
188 198
                return (NULL);
189 2934300
        assert(b <= e);
190 2934300
        u = (unsigned)(e - b);
191 2934300
        assert(b + u == e);
192 2934300
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
193 1160
                return (NULL);
194 5866280
        u += http_asso_values[(uint8_t)(e[-1])] +
195 2933140
             http_asso_values[(uint8_t)(b[0])];
196 2933140
        if (u > GPERF_MAX_HASH_VALUE)
197 39880
                return (NULL);
198 2893260
        retval = &http_hdrflg[u];
199 2893260
        if (retval->hdr == NULL)
200 10109
                return (NULL);
201 2883151
        if (!http_hdr_at(retval->hdr + 1, b, e - b))
202 36239
                return (NULL);
203 2846912
        return (retval);
204 2934300
}
205
206
/*--------------------------------------------------------------------*/
207
208
static void
209 1904760
http_init_hdr(char *hdr, int flg)
210
{
211
        struct http_hdrflg *f;
212
213 1904760
        hdr[0] = strlen(hdr + 1);
214 1904760
        f = http_hdr_flags(hdr + 1, hdr + hdr[0]);
215 1904760
        AN(f);
216 1904760
        assert(f->hdr == hdr);
217 1904760
        f->flag = flg;
218 1904760
}
219
220
void
221 36630
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 36630
        AN(vsb);
230
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
231
            heritage.identity);
232 36630
        AZ(VSB_finish(vsb));
233 36630
        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 4816853
http_VSLH(const struct http *hp, unsigned hdr)
247
{
248
        int i;
249
250 4816853
        if (hp->vsl != NULL) {
251 4817008
                assert(VXID_TAG(hp->vsl->wid));
252 4817008
                i = hdr;
253 4817008
                if (i > HTTP_HDR_FIRST)
254 2529150
                        i = HTTP_HDR_FIRST;
255 4817008
                i += hp->logtag;
256 4817008
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
257 4817008
        }
258 4817163
}
259
260
static void
261 36280
http_VSLH_del(const struct http *hp, unsigned hdr)
262
{
263
        int i;
264
265 36280
        if (hp->vsl != NULL) {
266
                /* We don't support unsetting stuff in the first line */
267 36280
                assert (hdr >= HTTP_HDR_FIRST);
268 36280
                assert(VXID_TAG(hp->vsl->wid));
269 36280
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
270 36280
                i += hp->logtag;
271 36280
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
272 36280
        }
273 36280
}
274
275
/*--------------------------------------------------------------------*/
276
277
void
278 224487
http_VSL_log(const struct http *hp)
279
{
280
        unsigned u;
281
282 1962243
        for (u = 0; u < hp->nhd; u++)
283 3026587
                if (hp->hd[u].b != NULL)
284 1288831
                        http_VSLH(hp, u);
285 224487
}
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 1770168
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
322 1768368
                if (mp->nbr == status) {
323 55474
                        if (sstr)
324 42476
                                *sstr = mp->status;
325 55474
                        return (mp->txt);
326
                }
327 1800
        return ("Unknown HTTP Status");
328 57274
}
329
330
/*--------------------------------------------------------------------*/
331
332
unsigned
333 206257
HTTP_estimate(unsigned nhttp)
334
{
335
336
        /* XXX: We trust the structs to size-aligned as necessary */
337 206257
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
338
}
339
340
struct http *
341 618772
HTTP_create(void *p, uint16_t nhttp, unsigned len)
342
{
343
        struct http *hp;
344
345 618772
        hp = p;
346 618772
        hp->magic = HTTP_MAGIC;
347 618772
        hp->hd = (void*)(hp + 1);
348 618772
        hp->shd = nhttp;
349 618772
        hp->hdf = (void*)(hp->hd + nhttp);
350 618772
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
351 618772
        return (hp);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
void
357 574675
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
358
    enum VSL_tag_e  whence)
359
{
360 574675
        http_Teardown(hp);
361 574675
        hp->nhd = HTTP_HDR_FIRST;
362 574675
        hp->logtag = whence;
363 574675
        hp->ws = ws;
364 574675
        hp->vsl = vsl;
365 574675
}
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 897428
http_Teardown(struct http *hp)
375
{
376
377 897428
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
378 897428
        AN(hp->shd);
379 897428
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
380 897428
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
381 897428
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
382 897428
}
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 252604
HTTP_Dup(struct http *to, const struct http * fm)
392
{
393
394 252604
        assert(fm->nhd <= to->shd);
395 252604
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
396 252604
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
397 252604
        to->nhd = fm->nhd;
398 252604
        to->logtag = fm->logtag;
399 252604
        to->status = fm->status;
400 252604
        to->protover = fm->protover;
401 252604
}
402
403
404
/*--------------------------------------------------------------------
405
 * Clone the entire http structure, including vsl & ws
406
 */
407
408
void
409 237965
HTTP_Clone(struct http *to, const struct http * const fm)
410
{
411
412 237965
        HTTP_Dup(to, fm);
413 237965
        to->vsl = fm->vsl;
414 237965
        to->ws = fm->ws;
415 237965
}
416
417
/*--------------------------------------------------------------------*/
418
419
void
420 256889
http_Proto(struct http *to)
421
{
422
        const char *fm;
423
424 256889
        fm = to->hd[HTTP_HDR_PROTO].b;
425
426 513439
        if (fm != NULL &&
427 256581
            (fm[0] == 'H' || fm[0] == 'h') &&
428 256544
            (fm[1] == 'T' || fm[1] == 't') &&
429 256544
            (fm[2] == 'T' || fm[2] == 't') &&
430 256544
            (fm[3] == 'P' || fm[3] == 'p') &&
431 256544
            fm[4] == '/' &&
432 256544
            vct_isdigit(fm[5]) &&
433 256543
            fm[6] == '.' &&
434 256544
            vct_isdigit(fm[7]) &&
435 256550
            fm[8] == '\0') {
436 256549
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
437 256549
        } else {
438 360
                to->protover = 0;
439
        }
440 256909
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 1521626
http_SetH(struct http *to, unsigned n, const char *header)
446
{
447
448 1521626
        assert(n < to->nhd);
449 1521626
        AN(header);
450 1521626
        to->hd[n].b = TRUST_ME(header);
451 1521626
        to->hd[n].e = strchr(to->hd[n].b, '\0');
452 1521626
        to->hdf[n] = 0;
453 1521626
        http_VSLH(to, n);
454 1521626
        if (n == HTTP_HDR_PROTO)
455 52357
                http_Proto(to);
456 1521626
}
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 4541450
http_IsHdr(const txt *hh, hdr_t hdr)
479
{
480
        unsigned l;
481
482 4541450
        Tcheck(*hh);
483 4541450
        AN(hdr);
484 4541450
        l = hdr[0];
485 4541450
        assert(l == strlen(hdr + 1));
486 4541450
        assert(hdr[l] == ':');
487 4541450
        hdr++;
488 4541450
        return (http_hdr_at(hdr, hh->b, l));
489
}
490
491
/*--------------------------------------------------------------------*/
492
493
static unsigned
494 5799537
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
495
{
496
        unsigned u;
497
498 25024073
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
499 20502401
                Tcheck(hp->hd[u]);
500 20502401
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
501 3748774
                        continue;
502 16753627
                if (hp->hd[u].b[l] != ':')
503 14092524
                        continue;
504 2661103
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
505 1383238
                        continue;
506 1277865
                return (u);
507
        }
508 4521672
        return (0);
509 5799537
}
510
511
/*--------------------------------------------------------------------
512
 * Count how many instances we have of this header
513
 */
514
515
unsigned
516 289305
http_CountHdr(const struct http *hp, hdr_t hdr)
517
{
518 289305
        unsigned retval = 0;
519
        unsigned u;
520
521 289305
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
522
523 966509
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
524 677204
                Tcheck(hp->hd[u]);
525 677204
                if (http_IsHdr(&hp->hd[u], hdr))
526 143698
                        retval++;
527 677204
        }
528 289305
        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 934544
http_CollectHdr(struct http *hp, hdr_t hdr)
538
{
539
540 934544
        http_CollectHdrSep(hp, hdr, NULL);
541 934544
}
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 939566
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
551
{
552
        unsigned u, l, lsep, ml, f, x, d;
553 939566
        char *b = NULL, *e = NULL;
554
        const char *v;
555
556 939566
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
557 939566
        if (WS_Overflowed(hp->ws))
558 800
                return;
559
560 938766
        if (sep == NULL || *sep == '\0')
561 933725
                sep = ", ";
562 938780
        lsep = strlen(sep);
563
564 938780
        l = hdr[0];
565 938780
        assert(l == strlen(hdr + 1));
566 938780
        assert(hdr[l] == ':');
567 938780
        f = http_findhdr(hp, l - 1, hdr + 1);
568 938780
        if (f == 0)
569 922712
                return;
570
571 59049
        for (d = u = f + 1; u < hp->nhd; u++) {
572 42981
                Tcheck(hp->hd[u]);
573 42981
                if (!http_IsHdr(&hp->hd[u], hdr)) {
574 42261
                        if (d != u) {
575 2840
                                hp->hd[d] = hp->hd[u];
576 2840
                                hp->hdf[d] = hp->hdf[u];
577 2840
                        }
578 42261
                        d++;
579 42261
                        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 16068
        if (b == NULL)
622 15428
                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 939580
}
630
631
/*--------------------------------------------------------------------*/
632
633
int
634 4855547
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
635
{
636
        unsigned u, l;
637
        const char *p;
638
639 4855547
        l = hdr[0];
640 4855547
        assert(l == strlen(hdr + 1));
641 4855547
        assert(hdr[l] == ':');
642 4855547
        hdr++;
643 4855547
        u = http_findhdr(hp, l - 1, hdr);
644 4855547
        if (u == 0) {
645 3596834
                if (ptr != NULL)
646 3234608
                        *ptr = NULL;
647 3596834
                return (0);
648
        }
649 1258713
        if (ptr != NULL) {
650 1029123
                p = hp->hd[u].b + l;
651 2056514
                while (vct_issp(*p))
652 1027391
                        p++;
653 1029123
                *ptr = p;
654 1029123
        }
655 1258713
        return (1);
656 4855547
}
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 90937
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 90937
        AN(src);
672 90937
        AN(*src);
673 90937
        AN(sep);
674 90937
        AN(b);
675 90937
        AN(e);
676
677 90937
        if (stop == NULL)
678 90654
                stop = strchr(*src, '\0');
679
680 156285
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
681 3480
                continue;
682
683 90937
        if (p >= stop) {
684 32548
                *b = NULL;
685 32548
                *e = NULL;
686 32548
                return (0);
687
        }
688
689 58389
        *b = p;
690 58389
        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 287297
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
698 228908
                continue;
699 58389
        *src = q;
700 58389
        while (q > p && vct_issp(q[-1]))
701 0
                q--;
702 58387
        *e = q;
703 58387
        return (1);
704 90935
}
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 50920
http_istoken(const char **bp, const char *e, const char *token)
717
{
718 50920
        int fl = strlen(token);
719
        const char *b;
720
721 50920
        AN(bp);
722 50920
        AN(e);
723 50920
        AN(token);
724
725 50920
        b = *bp;
726
727 50920
        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 52520
        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 27080
        return (0);
738 50920
}
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 567113
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 567113
        if (pb != NULL)
767 431452
                *pb = NULL;
768 567113
        if (pe != NULL)
769 130735
                *pe = NULL;
770 567113
        if (!http_GetHdr(hp, hdr, &h))
771 517673
                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 567113
}
792
793
/*--------------------------------------------------------------------
794
 * Find a given header field's quality value (qvalue).
795
 */
796
797
double
798 130727
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 130727
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
805 130727
        if (!i)
806 109087
                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 130727
}
841
842
/*--------------------------------------------------------------------
843
 * Find a given header field's value.
844
 */
845
846
int
847 300721
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 300721
        if (ptr != NULL)
854 152600
                *ptr = NULL;
855
856 300721
        h = NULL;
857 300721
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
858 300721
        if (!i)
859 298881
                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 300721
}
874
875
/*--------------------------------------------------------------------*/
876
877
ssize_t
878 428899
http_GetContentLength(const struct http *hp)
879
{
880
        ssize_t cl;
881
        const char *b;
882
883 428899
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
884
885 428899
        if (!http_GetHdr(hp, H_Content_Length, &b))
886 167947
                return (-1);
887 260952
        cl = VNUM_uint(b, NULL, &b);
888 260952
        if (cl < 0)
889 160
                return (-2);
890 260792
        while (vct_islws(*b))
891 0
                b++;
892 260792
        if (*b != '\0')
893 0
                return (-2);
894 260792
        return (cl);
895 428899
}
896
897
ssize_t
898 77958
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 77958
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
904
905 77958
        if (lo == NULL)
906 0
                lo = &tmp;
907 77958
        if (hi == NULL)
908 0
                hi = &tmp;
909
910 77958
        *lo = *hi = -1;
911
912 77958
        if (!http_GetHdr(hp, H_Content_Range, &b))
913 77638
                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 77958
}
958
959
const char *
960 79839
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 79839
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
966
967 79839
        if (lo == NULL)
968 0
                lo = &tmp_lo;
969 79839
        if (hi == NULL)
970 0
                hi = &tmp_hi;
971
972 79839
        *lo = *hi = -1;
973
974 79839
        if (!http_GetHdr(hp, H_Range, &b))
975 77759
                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 79839
}
1027
1028
/*--------------------------------------------------------------------
1029
 */
1030
1031
stream_close_t
1032 225125
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 225125
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1040 225125
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1041
1042 225125
        if (hp->protover == 10)
1043 1551
                retval = SC_REQ_HTTP10;
1044
        else
1045 223574
                retval = SC_NULL;
1046
1047 225125
        http_CollectHdr(hp, H_Connection);
1048 225125
        if (!http_GetHdr(hp, H_Connection, &h))
1049 218058
                return (retval);
1050 7067
        AN(h);
1051 14135
        while (http_split(&h, NULL, ",", &b, &e)) {
1052 7188
                u = pdiff(b, e);
1053 7188
                if (u == 5 && http_hdr_at(b, "close", u))
1054 5789
                        retval = sc_close;
1055 7188
                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 7188
                f = http_hdr_flags(b, e);
1060 7188
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1061 120
                        return (SC_RX_BAD);
1062
1063 34335
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1064 27267
                        Tcheck(hp->hd[v]);
1065 27267
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1066 1240
                                continue;
1067 26027
                        if (hp->hd[v].b[u] != ':')
1068 24027
                                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 6947
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1075 6947
        return (retval);
1076 225125
}
1077
1078
/*--------------------------------------------------------------------*/
1079
1080
int
1081 426456
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1082
{
1083
        const char *p;
1084
1085 426456
        if (!http_GetHdr(hp, hdr, &p))
1086 403456
                return (0);
1087 23000
        AN(p);
1088 23000
        if (http_tok_eq(p, val))
1089 21960
                return (1);
1090 1040
        return (0);
1091 426456
}
1092
1093
/*--------------------------------------------------------------------*/
1094
1095
uint16_t
1096 553854
http_GetStatus(const struct http *hp)
1097
{
1098
1099 553854
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1100 553854
        return (hp->status);
1101
}
1102
1103
int
1104 387680
http_IsStatus(const struct http *hp, int val)
1105
{
1106
1107 387680
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1108 387680
        assert(val >= 100 && val <= 999);
1109 387680
        return (val == (hp->status % 1000));
1110
}
1111
1112
/*--------------------------------------------------------------------
1113
 * Setting the status will also set the Reason appropriately
1114
 */
1115
1116
void
1117 43914
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1118
{
1119
        char buf[4];
1120 43914
        const char *sstr = NULL;
1121
1122 43914
        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 43914
        to->status = status;
1128 43914
        status %= 1000;
1129 43914
        assert(status >= 100);
1130
1131 43914
        if (reason == NULL)
1132 8160
                reason = http_Status2Reason(status, &sstr);
1133
        else
1134 35754
                (void)http_Status2Reason(status, &sstr);
1135
1136 43914
        if (sstr) {
1137 42474
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1138 42474
        } else {
1139 1440
                bprintf(buf, "%03d", status);
1140 1440
                http_PutField(to, HTTP_HDR_STATUS, buf);
1141
        }
1142 43914
        http_SetH(to, HTTP_HDR_REASON, reason);
1143 43914
}
1144
1145
/*--------------------------------------------------------------------*/
1146
1147
const char *
1148 202838
http_GetMethod(const struct http *hp)
1149
{
1150
1151 202838
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1152 202838
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1153 202838
        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 299076
http_ForceField(struct http *to, unsigned n, const char *t)
1162
{
1163
        int i;
1164
1165 299076
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1166 299076
        assert(n < HTTP_HDR_FIRST);
1167 299076
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1168 299076
        AN(t);
1169
1170
        /* NB: method names and protocol versions are case-sensitive. */
1171 299076
        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 299078
}
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 1543941
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1201
{
1202
        const char *e;
1203
        const struct http_hdrflg *f;
1204
1205 1543941
        if (fm->hdf[u] & HDF_FILTER)
1206 680
                return (1);
1207 1543261
        if (u < HTTP_HDR_FIRST)
1208 520924
                return (0);
1209 1022337
        e = strchr(fm->hd[u].b, ':');
1210 1022337
        if (e == NULL)
1211 0
                return (0);
1212 1022337
        f = http_hdr_flags(fm->hd[u].b, e);
1213 1022337
        return (f != NULL && f->flag & how);
1214 1543941
}
1215
1216
int
1217 24626
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1218
{
1219
1220 24626
        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 86956
http_EstimateWS(const struct http *fm, unsigned how)
1230
{
1231
        unsigned u, l;
1232
1233 86956
        l = 4;
1234 86956
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1235 830436
        for (u = 0; u < fm->nhd; u++) {
1236 743480
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1237 173912
                        continue;
1238 569568
                Tcheck(fm->hd[u]);
1239 569568
                if (http_isfiltered(fm, u, how))
1240 10368
                        continue;
1241 559200
                l += Tlen(fm->hd[u]) + 1L;
1242 559200
        }
1243 86956
        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 86719
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 86719
        AN(p0);
1263 86719
        AN(l);
1264 86719
        p = p0;
1265 86719
        e = p + l;
1266 86719
        assert(p + 5 <= e);
1267 86719
        assert(fm->nhd <= fm->shd);
1268 86719
        n = HTTP_HDR_FIRST - 3;
1269 86719
        vbe16enc(p + 2, fm->status);
1270 86719
        p += 4;
1271 86719
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1272 827964
        for (u = 0; u < fm->nhd; u++) {
1273 741245
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1274 173432
                        continue;
1275 567813
                Tcheck(fm->hd[u]);
1276 567813
                if (http_isfiltered(fm, u, how))
1277 10368
                        continue;
1278 557445
                http_VSLH(fm, u);
1279 557445
                w = Tlen(fm->hd[u]) + 1L;
1280 557445
                assert(p + w + 1 <= e);
1281 557445
                memcpy(p, fm->hd[u].b, w);
1282 557445
                p += w;
1283 557445
                n++;
1284 557445
        }
1285 86719
        *p++ = '\0';
1286 86719
        assert(p <= e);
1287 86719
        vbe16enc(p0, n + 1);
1288 86719
}
1289
1290
/*--------------------------------------------------------------------
1291
 * Decode byte string into http struct
1292
 */
1293
1294
int
1295 124847
HTTP_Decode(struct http *to, const uint8_t *fm)
1296
{
1297
1298 124847
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1299 124847
        AN(to->vsl);
1300 124847
        AN(fm);
1301 124847
        if (vbe16dec(fm) <= to->shd) {
1302 124772
                to->status = vbe16dec(fm + 2);
1303 124772
                fm += 4;
1304 1180072
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1305 1180072
                        if (to->nhd == HTTP_HDR_METHOD ||
1306 1055207
                            to->nhd == HTTP_HDR_URL) {
1307 249522
                                to->hd[to->nhd].b = NULL;
1308 249522
                                to->hd[to->nhd].e = NULL;
1309 249522
                                continue;
1310
                        }
1311 930550
                        if (*fm == '\0')
1312 124772
                                return (0);
1313 805778
                        to->hd[to->nhd].b = (const void*)fm;
1314 805778
                        fm = (const void*)strchr((const void*)fm, '\0');
1315 805778
                        to->hd[to->nhd].e = (const void*)fm;
1316 805778
                        fm++;
1317 805778
                        http_VSLH(to, to->nhd);
1318 805778
                }
1319 0
        }
1320 150
        VSLb(to->vsl, SLT_Error,
1321
            "Too many headers to Decode object (%u vs. %u)",
1322 75
            vbe16dec(fm), to->shd);
1323 75
        return (-1);
1324 124847
}
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 29035
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1343
{
1344
        const char *ptr;
1345
1346 29035
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1347 29035
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1348 29035
        AN(p);
1349
1350 29035
        if (*p == NULL) {
1351 9204
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1352 9204
                AN(ptr);
1353 9204
                ptr += 4;       /* Skip nhd and status */
1354 9204
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1355 9204
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1356 9204
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1357 9204
                *p = ptr;
1358 9204
        } else {
1359 19831
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1360
        }
1361 29035
        if (**p == '\0')
1362 1782
                return (0);
1363 27253
        return (1);
1364 29035
}
1365
1366
const char *
1367 9444
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1368
{
1369
        const char *ptr;
1370
        unsigned l;
1371
1372 9444
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1373 9444
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1374 9444
        AN(hdr);
1375
1376 9444
        l = hdr[0];
1377 9444
        assert(l > 0);
1378 9444
        assert(l == strlen(hdr + 1));
1379 9444
        assert(hdr[l] == ':');
1380 9444
        hdr++;
1381
1382 9444
        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 29041
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1401 27259
                if (http_hdr_at(ptr, hdr, l)) {
1402 7422
                        ptr += l;
1403 14803
                        while (vct_islws(*ptr))
1404 7381
                                ptr++;
1405 7422
                        return (ptr);
1406
                }
1407
        }
1408
1409 1782
        return (NULL);
1410 9444
}
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 267347
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1456
{
1457
1458 267347
        assert(n < HTTP_HDR_FIRST);
1459 267347
        Tcheck(fm->hd[n]);
1460 267347
        to->hd[n] = fm->hd[n];
1461 267347
        to->hdf[n] = fm->hdf[n];
1462 267347
        http_VSLH(to, n);
1463 267347
}
1464
1465
/*--------------------------------------------------------------------*/
1466
1467
void
1468 89120
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1469
{
1470
        unsigned u;
1471
1472 89120
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1473 89120
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1474
1475 89120
        http_linkh(to, fm, HTTP_HDR_METHOD);
1476 89120
        http_linkh(to, fm, HTTP_HDR_URL);
1477 89120
        http_linkh(to, fm, HTTP_HDR_PROTO);
1478 89120
        to->protover = fm->protover;
1479 89120
        to->status = fm->status;
1480
1481 89120
        to->nhd = HTTP_HDR_FIRST;
1482 471061
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1483 381941
                Tcheck(fm->hd[u]);
1484 381941
                if (http_isfiltered(fm, u, how))
1485 4360
                        continue;
1486 377581
                assert (to->nhd < to->shd);
1487 377581
                to->hd[to->nhd] = fm->hd[u];
1488 377581
                to->hdf[to->nhd] = 0;
1489 377581
                http_VSLH(to, to->nhd);
1490 377581
                to->nhd++;
1491 377581
        }
1492 89120
}
1493
1494
/*--------------------------------------------------------------------
1495
 * This function copies any header fields which reference foreign
1496
 * storage into our own WS.
1497
 */
1498
1499
void
1500 87877
http_CopyHome(const struct http *hp)
1501
{
1502
        unsigned u, l;
1503
        const char *p;
1504
1505 954235
        for (u = 0; u < hp->nhd; u++) {
1506 866358
                if (hp->hd[u].b == NULL) {
1507 175750
                        assert(u < HTTP_HDR_FIRST);
1508 175750
                        continue;
1509
                }
1510
1511 690608
                l = Tlen(hp->hd[u]);
1512 690608
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1513 55040
                        continue;
1514
1515 635568
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1516 635568
                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 635568
                hp->hd[u].b = p;
1522 635568
                hp->hd[u].e = p + l;
1523 635568
        }
1524 87877
}
1525
1526
/*--------------------------------------------------------------------*/
1527
1528
void
1529 360318
http_SetHeader(struct http *to, const char *header)
1530
{
1531
1532 360318
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1533 360318
        if (to->nhd >= to->shd) {
1534 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1535 40
                http_fail(to);
1536 40
                return;
1537
        }
1538 360278
        http_SetH(to, to->nhd++, header);
1539 360318
}
1540
1541
/*--------------------------------------------------------------------*/
1542
1543
void
1544 160261
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1545
{
1546
1547 160261
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1548 160261
        if (http_HdrIs(to, hdr, val))
1549 14800
                return;
1550 145461
        http_Unset(to, hdr);
1551 145461
        http_PrintfHeader(to, "%s %s", hdr + 1, val);
1552 160261
}
1553
1554
void
1555 410304
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1556
{
1557
        const char *old;
1558
1559 410304
        http_CollectHdr(to, hdr);
1560 410304
        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 408384
                http_PrintfHeader(to, "%s %s", hdr + 1, val);
1565
        }
1566 410304
}
1567
1568
void
1569 965512
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 965512
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1577
1578 965512
        va_start(ap, fmt);
1579 965512
        va_copy(ap2, ap);
1580
1581 965512
        WS_VSB_new(vsb, to->ws);
1582 965512
        VSB_vprintf(vsb, fmt, ap);
1583 965512
        p = WS_VSB_finish(vsb, to->ws, &sz);
1584
1585 965512
        if (p == NULL || to->nhd >= to->shd) {
1586 1062
                http_fail(to);
1587 1062
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1588 1062
        } else {
1589 964458
                http_SetH(to, to->nhd++, p);
1590
        }
1591 965520
        va_end(ap);
1592 965520
        va_end(ap2);
1593 965520
}
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 267553
http_ViaHeader(void)
1619
{
1620
1621 267553
        return (via_hdr);
1622
}
1623
1624
/*--------------------------------------------------------------------*/
1625
1626
void
1627 714943
http_Unset(struct http *hp, hdr_t hdr)
1628
{
1629
        uint16_t u, v;
1630
1631 4536295
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1632 3821352
                Tcheck(hp->hd[u]);
1633 3821352
                if (http_IsHdr(&hp->hd[u], hdr)) {
1634 36280
                        http_VSLH_del(hp, u);
1635 36280
                        continue;
1636
                }
1637 3785072
                if (v != u) {
1638 91038
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1639 91038
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1640 91038
                }
1641 3785072
                v++;
1642 3785072
        }
1643 714943
        hp->nhd = v;
1644 714943
}