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