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 997672
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 997672
        if (b == NULL || e == NULL)
188 78
                return (NULL);
189 997668
        u = pdiff(b, e);
190 997668
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
191 455
                return (NULL);
192 1994426
        u += http_asso_values[(uint8_t)(e[-1])] +
193 997213
             http_asso_values[(uint8_t)(b[0])];
194 997213
        if (u > GPERF_MAX_HASH_VALUE)
195 13598
                return (NULL);
196 983615
        retval = &http_hdrflg[u];
197 983615
        if (retval->hdr == NULL)
198 3762
                return (NULL);
199 979853
        AN(*retval->hdr);
200 979853
        if (!http_hdr_at(*retval->hdr + 1, b, e - b))
201 13793
                return (NULL);
202 966060
        return (retval);
203 997668
}
204
205
/*--------------------------------------------------------------------*/
206
207
static void
208 644748
http_init_hdr(hdr_t hdr, int flg)
209
{
210
        struct http_hdrflg *f;
211
212 644748
        f = http_hdr_flags(hdr->str, hdr->str + hdr->len - 1);
213 644748
        AN(f);
214 644748
        assert(*f->hdr == hdr);
215 644748
        f->flag = flg;
216 644748
}
217
218
void
219 12399
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 12399
        AN(vsb);
228
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
229
            heritage.identity);
230 12399
        AZ(VSB_finish(vsb));
231 12399
        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 1652978
http_VSLH(const struct http *hp, unsigned hdr)
245
{
246
        int i;
247
248 1652978
        if (hp->vsl != NULL) {
249 1653041
                assert(VXID_TAG(hp->vsl->wid));
250 1653041
                i = hdr;
251 1653041
                if (i > HTTP_HDR_FIRST)
252 870318
                        i = HTTP_HDR_FIRST;
253 1653041
                i += hp->logtag;
254 1653041
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
255 1653041
        }
256 1653110
}
257
258
static void
259 13520
http_VSLH_del(const struct http *hp, unsigned hdr)
260
{
261
        int i;
262
263 13520
        if (hp->vsl != NULL) {
264
                /* We don't support unsetting stuff in the first line */
265 13520
                assert (hdr >= HTTP_HDR_FIRST);
266 13520
                assert(VXID_TAG(hp->vsl->wid));
267 13520
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
268 13520
                i += hp->logtag;
269 13520
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
270 13520
        }
271 13520
}
272
273
/*--------------------------------------------------------------------*/
274
275
void
276 76875
http_VSL_log(const struct http *hp)
277
{
278
        unsigned u;
279
280 671598
        for (u = 0; u < hp->nhd; u++)
281 1035724
                if (hp->hd[u].b != NULL)
282 441001
                        http_VSLH(hp, u);
283 76875
}
284
285
/*--------------------------------------------------------------------*/
286
287
static void
288 1352
http_fail(const struct http *hp)
289
{
290
        char id[WS_ID_SIZE];
291
292 1352
        VSC_C_main->losthdr++;
293 1352
        WS_Id(hp->ws, id);
294 1352
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
295 1352
        WS_MarkOverflow(hp->ws);
296 1352
}
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 19511
http_Status2Reason(unsigned status, const char **sstr)
314
{
315
        struct http_msg *mp;
316
317 19511
        status %= 1000;
318 19511
        assert(status >= 100);
319 595177
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
320 594592
                if (mp->nbr == status) {
321 18926
                        if (sstr)
322 14468
                                *sstr = mp->status;
323 18926
                        return (mp->txt);
324
                }
325 585
        return ("Unknown HTTP Status");
326 19511
}
327
328
/*--------------------------------------------------------------------*/
329
330
unsigned
331 70142
HTTP_estimate(unsigned nhttp)
332
{
333
334
        /* XXX: We trust the structs to size-aligned as necessary */
335 70142
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
336
}
337
338
struct http *
339 210423
HTTP_create(void *p, uint16_t nhttp, unsigned len)
340
{
341
        struct http *hp;
342
343 210423
        hp = p;
344 210423
        hp->magic = HTTP_MAGIC;
345 210423
        hp->hd = (void*)(hp + 1);
346 210423
        hp->shd = nhttp;
347 210423
        hp->hdf = (void*)(hp->hd + nhttp);
348 210423
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
349 210423
        return (hp);
350
}
351
352
/*--------------------------------------------------------------------*/
353
354
void
355 196415
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
356
    enum VSL_tag_e  whence)
357
{
358 196415
        http_Teardown(hp);
359 196415
        hp->nhd = HTTP_HDR_FIRST;
360 196415
        hp->logtag = whence;
361 196415
        hp->ws = ws;
362 196415
        hp->vsl = vsl;
363 196415
}
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 306603
http_Teardown(struct http *hp)
373
{
374
375 306603
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
376 306603
        AN(hp->shd);
377 306603
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
378 306603
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
379 306603
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
380 306603
}
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 86181
HTTP_Dup(struct http *to, const struct http * fm)
390
{
391
392 86181
        assert(fm->nhd <= to->shd);
393 86181
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
394 86181
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
395 86181
        to->nhd = fm->nhd;
396 86181
        to->logtag = fm->logtag;
397 86181
        to->status = fm->status;
398 86181
        to->protover = fm->protover;
399 86181
}
400
401
402
/*--------------------------------------------------------------------
403
 * Clone the entire http structure, including vsl & ws
404
 */
405
406
void
407 81422
HTTP_Clone(struct http *to, const struct http * const fm)
408
{
409
410 81422
        HTTP_Dup(to, fm);
411 81422
        to->vsl = fm->vsl;
412 81422
        to->ws = fm->ws;
413 81422
}
414
415
/*--------------------------------------------------------------------*/
416
417
void
418 87975
http_Proto(struct http *to)
419
{
420
        const char *fm;
421
422 87975
        fm = to->hd[HTTP_HDR_PROTO].b;
423
424 175833
        if (fm != NULL &&
425 87873
            (fm[0] == 'H' || fm[0] == 'h') &&
426 87860
            (fm[1] == 'T' || fm[1] == 't') &&
427 87860
            (fm[2] == 'T' || fm[2] == 't') &&
428 87860
            (fm[3] == 'P' || fm[3] == 'p') &&
429 87860
            fm[4] == '/' &&
430 87860
            vct_isdigit(fm[5]) &&
431 87859
            fm[6] == '.' &&
432 87859
            vct_isdigit(fm[7]) &&
433 87858
            fm[8] == '\0') {
434 87858
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
435 87858
        } else {
436 117
                to->protover = 0;
437
        }
438 87975
}
439
440
/*--------------------------------------------------------------------*/
441
442
void
443 524039
http_SetH(struct http *to, unsigned n, const char *header)
444
{
445
446 524039
        assert(n < to->nhd);
447 524039
        AN(header);
448 524039
        to->hd[n].b = TRUST_ME(header);
449 524039
        to->hd[n].e = strchr(to->hd[n].b, '\0');
450 524039
        to->hdf[n] = 0;
451 524039
        http_VSLH(to, n);
452 524039
        if (n == HTTP_HDR_PROTO)
453 17989
                http_Proto(to);
454 524039
}
455
456
/*--------------------------------------------------------------------*/
457
458
static void
459 468
http_PutField(struct http *to, int field, const char *string)
460
{
461
        const char *p;
462
463 468
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
464 468
        p = WS_Copy(to->ws, string, -1);
465 468
        if (p == NULL) {
466 13
                http_fail(to);
467 13
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
468 13
                return;
469
        }
470 455
        http_SetH(to, field, p);
471 468
}
472
473
/*--------------------------------------------------------------------*/
474
475
int
476 1911589
http_IsHdr(const txt *hh, hdr_t hdr)
477
{
478
479 1911589
        Tcheck(*hh);
480 1911589
        CHECK_HDR(hdr);
481 1911589
        return (http_hdr_at(hdr->str, hh->b, hdr->len));
482
}
483
484
/*--------------------------------------------------------------------*/
485
486
static unsigned
487 1971945
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
488
{
489
        unsigned u;
490
491 8564726
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
492 7030123
                Tcheck(hp->hd[u]);
493 7030123
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
494 1268151
                        continue;
495 5761972
                if (hp->hd[u].b[l] != ':')
496 4844429
                        continue;
497 917543
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
498 480201
                        continue;
499 437342
                return (u);
500
        }
501 1534603
        return (0);
502 1971945
}
503
504
/*--------------------------------------------------------------------
505
 * Count how many instances we have of this header
506
 */
507
508
unsigned
509 99720
http_CountHdr(const struct http *hp, hdr_t hdr)
510
{
511 99720
        unsigned retval = 0;
512
        unsigned u;
513
514 99720
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
515
516 332401
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
517 232681
                Tcheck(hp->hd[u]);
518 232681
                if (http_IsHdr(&hp->hd[u], hdr))
519 49304
                        retval++;
520 232681
        }
521 99720
        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 320905
http_CollectHdr(struct http *hp, hdr_t hdr)
531
{
532
533 320905
        http_CollectHdrSep(hp, hdr, NULL);
534 320905
}
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 322860
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
544
{
545
        unsigned u, lsep, ml, f, x, d;
546 322860
        char *b = NULL, *e = NULL;
547
        const char *v;
548
549 322860
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
550 322860
        CHECK_HDR(hdr);
551
552 322860
        if (WS_Overflowed(hp->ws))
553 260
                return;
554
555 322600
        if (sep == NULL || *sep == '\0')
556 320655
                sep = ", ";
557 322600
        lsep = strlen(sep);
558
559 322600
        f = http_findhdr(hp, hdr->len - 1, hdr->str);
560 322600
        if (f == 0)
561 317121
                return;
562
563 20197
        for (d = u = f + 1; u < hp->nhd; u++) {
564 14718
                Tcheck(hp->hd[u]);
565 14718
                if (!http_IsHdr(&hp->hd[u], hdr)) {
566 14484
                        if (d != u) {
567 923
                                hp->hd[d] = hp->hd[u];
568 923
                                hp->hdf[d] = hp->hdf[u];
569 923
                        }
570 14484
                        d++;
571 14484
                        continue;
572
                }
573 234
                if (b == NULL) {
574
                        /* Found second header, start our collection */
575 208
                        ml = WS_ReserveAll(hp->ws);
576 208
                        b = WS_Reservation(hp->ws);
577 208
                        e = b + ml;
578 208
                        x = Tlen(hp->hd[f]);
579 208
                        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 208
                        memcpy(b, hp->hd[f].b, x);
587 208
                        b += x;
588 208
                }
589
590 234
                AN(b);
591 234
                AN(e);
592
593
                /* Append the Nth header we found */
594 234
                x = Tlen(hp->hd[u]) - hdr->len;
595
596 234
                v = hp->hd[u].b + hdr->len;
597 468
                while (vct_issp(*v)) {
598 234
                        v++;
599 234
                        x--;
600
                }
601
602 234
                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 234
                memcpy(b, sep, lsep);
609 234
                b += lsep;
610 234
                memcpy(b, v, x);
611 234
                b += x;
612 234
        }
613 5479
        if (b == NULL)
614 5271
                return;
615 208
        hp->nhd = (uint16_t)d;
616 208
        AN(e);
617 208
        *b = '\0';
618 208
        hp->hd[f].b = WS_Reservation(hp->ws);
619 208
        hp->hd[f].e = b;
620 208
        WS_ReleaseP(hp->ws, b + 1);
621 322860
}
622
623
/*--------------------------------------------------------------------*/
624
625
int
626 1647560
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
627
{
628
        unsigned u;
629
        const char *p;
630
631 1647560
        CHECK_HDR(hdr);
632 1647560
        u = http_findhdr(hp, hdr->len - 1, hdr->str);
633 1647560
        if (u == 0) {
634 1216766
                if (ptr != NULL)
635 1118425
                        *ptr = NULL;
636 1216766
                return (0);
637
        }
638 430794
        if (ptr != NULL) {
639 352365
                p = hp->hd[u].b + hdr->len;
640 704153
                while (vct_issp(*p))
641 351788
                        p++;
642 352365
                *ptr = p;
643 352365
        }
644 430794
        return (1);
645 1647560
}
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 32655
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 32655
        AN(src);
661 32655
        AN(*src);
662 32655
        AN(sep);
663 32655
        AN(b);
664 32655
        AN(e);
665
666 32655
        if (stop == NULL)
667 32564
                stop = strchr(*src, '\0');
668
669 55866
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
670 1131
                continue;
671
672 32655
        if (p >= stop) {
673 11706
                *b = NULL;
674 11706
                *e = NULL;
675 11706
                return (0);
676
        }
677
678 20949
        *b = p;
679 20949
        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 102912
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
687 81963
                continue;
688 20949
        *src = q;
689 20949
        while (q > p && vct_issp(q[-1]))
690 0
                q--;
691 20949
        *e = q;
692 20949
        return (1);
693 32655
}
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 18421
http_istoken(const char **bp, const char *e, const char *token)
706
{
707 18421
        int fl = strlen(token);
708
        const char *b;
709
710 18421
        AN(bp);
711 18421
        AN(e);
712 18421
        AN(token);
713
714 18421
        b = *bp;
715
716 18421
        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 18954
        if (b + fl <= e && http_tok_at(b, token, fl) &&
722 8593
            (b + fl == e || !vct_istchar(b[fl]))) {
723 8593
                *bp += fl;
724 8593
                return (1);
725
        }
726 9828
        return (0);
727 18421
}
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 196502
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 196502
        if (pb != NULL)
756 148530
                *pb = NULL;
757 196502
        if (pe != NULL)
758 46353
                *pe = NULL;
759 196502
        if (!http_GetHdr(hp, hdr, &h))
760 178562
                return (0);
761 17940
        AN(h);
762
763 27768
        while (http_split(&h, NULL, ",", &b, &e))
764 18421
                if (http_istoken(&b, e, token))
765 8593
                        break;
766 17940
        if (b == NULL)
767 9347
                return (0);
768 8593
        if (pb != NULL) {
769 8541
                for (; vct_islws(*b); b++)
770 65
                        continue;
771 8476
                if (b == e) {
772 7956
                        b = NULL;
773 7956
                        e = NULL;
774 7956
                }
775 8476
                *pb = b;
776 8476
                if (pe != NULL)
777 7865
                        *pe = e;
778 8476
        }
779 8593
        return (1);
780 196502
}
781
782
/*--------------------------------------------------------------------
783
 * Find a given header field's quality value (qvalue).
784
 */
785
786
double
787 46355
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 46355
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
794 46355
        if (!i)
795 38490
                return (0.);
796
797 7865
        if (hb == NULL)
798 7774
                return (1.);
799 91
        while (http_split(&hb, he, ";", &b, &e)) {
800 91
                if (*b != 'q')
801 0
                        continue;
802 91
                for (b++; b < e && vct_issp(*b); b++)
803 0
                        continue;
804 91
                if (b == e || *b != '=')
805 0
                        continue;
806 91
                break;
807
        }
808 91
        if (b == NULL)
809 0
                return (1.);
810 91
        for (b++; b < e && vct_issp(*b); b++)
811 0
                continue;
812 91
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
813 13
                return (0.);
814 78
        a = 0;
815 156
        while (b < e && vct_isdigit(*b)) {
816 78
                a *= 10.;
817 78
                a += *b - '0';
818 78
                b++;
819
        }
820 78
        if (b == e || *b++ != '.')
821 13
                return (a);
822 65
        f = .1;
823 208
        while (b < e && vct_isdigit(*b)) {
824 143
                a += f * (*b - '0');
825 143
                f *= .1;
826 143
                b++;
827
        }
828 65
        return (a);
829 46355
}
830
831
/*--------------------------------------------------------------------
832
 * Find a given header field's value.
833
 */
834
835
int
836 102175
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 102175
        if (ptr != NULL)
843 51933
                *ptr = NULL;
844
845 102175
        h = NULL;
846 102175
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
847 102175
        if (!i)
848 101564
                return (i);
849
850 611
        if (ptr != NULL && h != NULL) {
851
                /* Skip whitespace, looking for '=' */
852 429
                while (*h && vct_issp(*h))
853 0
                        h++;
854 429
                if (*h == '=') {
855 429
                        h++;
856 481
                        while (*h && vct_issp(*h))
857 52
                                h++;
858 429
                        *ptr = h;
859 429
                }
860 429
        }
861 611
        return (i);
862 102175
}
863
864
/*--------------------------------------------------------------------*/
865
866
ssize_t
867 147029
http_GetContentLength(const struct http *hp)
868
{
869
        ssize_t cl;
870
        const char *b;
871
872 147029
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
873
874 147029
        if (!http_GetHdr(hp, H_Content_Length, &b))
875 57692
                return (-1);
876 89337
        cl = VNUM_uint(b, NULL, &b);
877 89337
        if (cl < 0)
878 52
                return (-2);
879 89285
        while (vct_islws(*b))
880 0
                b++;
881 89285
        if (*b != '\0')
882 0
                return (-2);
883 89285
        return (cl);
884 147029
}
885
886
ssize_t
887 26388
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 26388
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
893
894 26388
        if (lo == NULL)
895 0
                lo = &tmp;
896 26388
        if (hi == NULL)
897 0
                hi = &tmp;
898
899 26388
        *lo = *hi = -1;
900
901 26388
        if (!http_GetHdr(hp, H_Content_Range, &b))
902 26258
                return (-1);
903
904 130
        t = strchr(b, ' ');
905 130
        if (t == NULL)
906 13
                return (-2);            // Missing space after range unit
907
908 117
        if (!http_range_at(b, bytes, t - b))
909 13
                return (-1);            // Unknown range unit, ignore
910 104
        b = t + 1;
911
912 104
        if (*b == '*') {                // Content-Range: bytes */123
913 39
                *lo = *hi = -1;
914 39
                b++;
915 39
        } else {                        // Content-Range: bytes 1-2/3
916 65
                *lo = VNUM_uint(b, NULL, &b);
917 65
                if (*lo < 0)
918 0
                        return (-2);
919 65
                if (*b != '-')
920 0
                        return (-2);
921 65
                *hi = VNUM_uint(b + 1, NULL, &b);
922 65
                if (*hi < 0)
923 0
                        return (-2);
924
        }
925 104
        if (*b != '/')
926 0
                return (-2);
927 104
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
928 13
                cl = -1;
929 13
                b += 2;
930 13
        } else {
931 91
                cl = VNUM_uint(b + 1, NULL, &b);
932 91
                if (cl <= 0)
933 0
                        return (-2);
934
        }
935 104
        while (vct_islws(*b))
936 0
                b++;
937 104
        if (*b != '\0')
938 0
                return (-2);
939 104
        if (*lo > *hi)
940 0
                return (-2);
941 104
        assert(cl >= -1);
942 104
        if (*lo >= cl || *hi >= cl)
943 13
                return (-2);
944 91
        AN(cl);
945 91
        return (cl);
946 26388
}
947
948
const char *
949 27024
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 27024
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
955
956 27024
        if (lo == NULL)
957 0
                lo = &tmp_lo;
958 27024
        if (hi == NULL)
959 0
                hi = &tmp_hi;
960
961 27024
        *lo = *hi = -1;
962
963 27024
        if (!http_GetHdr(hp, H_Range, &b))
964 26309
                return (NULL);
965
966 715
        t = strchr(b, '=');
967 715
        if (t == NULL)
968 26
                return ("Missing '='");
969
970 689
        if (!http_range_at(b, bytes, t - b))
971 39
                return ("Not Bytes");
972 650
        b = t + 1;
973
974 650
        *lo = VNUM_uint(b, NULL, &b);
975 650
        if (*lo == -2)
976 0
                return ("Low number too big");
977 650
        if (*b++ != '-')
978 0
                return ("Missing hyphen");
979
980 650
        *hi = VNUM_uint(b, NULL, &b);
981 650
        if (*hi == -2)
982 0
                return ("High number too big");
983 650
        if (*lo == -1 && *hi == -1)
984 13
                return ("Neither high nor low");
985 637
        if (*lo == -1 && *hi == 0)
986 13
                return ("No low, high is zero");
987 624
        if (*hi >= 0 && *hi < *lo)
988 13
                return ("high smaller than low");
989
990 624
        while (vct_islws(*b))
991 13
                b++;
992 611
        if (*b != '\0')
993 13
                return ("Trailing stuff");
994
995 598
        assert(*lo >= -1);
996 598
        assert(*hi >= -1);
997
998 598
        if (*lo < 0) {
999 52
                assert(*hi > 0);
1000 52
                *lo = len - *hi;
1001 52
                if (*lo < 0)
1002 26
                        *lo = 0;
1003 52
                *hi = len - 1;
1004 598
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1005 117
                *hi = len - 1;
1006 117
        }
1007
1008 598
        if (len <= 0)
1009 234
                return (NULL);                  // Allow 200 response
1010
1011 364
        if (*lo >= len)
1012 13
                return ("low range beyond object");
1013
1014 351
        return (NULL);
1015 27024
}
1016
1017
/*--------------------------------------------------------------------
1018
 */
1019
1020
stream_close_t
1021 77257
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 77257
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1029 77257
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1030
1031 77257
        if (hp->protover == 10)
1032 505
                retval = SC_REQ_HTTP10;
1033
        else
1034 76752
                retval = SC_NULL;
1035
1036 77257
        http_CollectHdr(hp, H_Connection);
1037 77257
        if (!http_GetHdr(hp, H_Connection, &h))
1038 74860
                return (retval);
1039 2397
        AN(h);
1040 4795
        while (http_split(&h, NULL, ",", &b, &e)) {
1041 2437
                u = pdiff(b, e);
1042 2437
                if (u == 5 && http_hdr_at(b, "close", u))
1043 1891
                        retval = sc_close;
1044 2437
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1045 390
                        retval = SC_NULL;
1046
1047
                /* Refuse removal of well-known-headers if they would pass. */
1048 2437
                f = http_hdr_flags(b, e);
1049 2437
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1050 39
                        return (SC_RX_BAD);
1051
1052 11644
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1053 9246
                        Tcheck(hp->hd[v]);
1054 9246
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1055 494
                                continue;
1056 8752
                        if (hp->hd[v].b[u] != ':')
1057 8011
                                continue;
1058 741
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1059 585
                                continue;
1060 156
                        hp->hdf[v] |= HDF_FILTER;
1061 156
                }
1062
        }
1063 2358
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1064 2358
        return (retval);
1065 77257
}
1066
1067
/*--------------------------------------------------------------------*/
1068
1069
int
1070 151856
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1071
{
1072
        const char *p;
1073
1074 151856
        if (!http_GetHdr(hp, hdr, &p))
1075 144139
                return (0);
1076 7717
        AN(p);
1077 7717
        if (http_tok_eq(p, val))
1078 7379
                return (1);
1079 338
        return (0);
1080 151856
}
1081
1082
/*--------------------------------------------------------------------*/
1083
1084
uint16_t
1085 190000
http_GetStatus(const struct http *hp)
1086
{
1087
1088 190000
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1089 190000
        return (hp->status);
1090
}
1091
1092
int
1093 131836
http_IsStatus(const struct http *hp, int val)
1094
{
1095
1096 131836
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1097 131836
        assert(val >= 100 && val <= 999);
1098 131836
        return (val == (hp->status % 1000));
1099
}
1100
1101
/*--------------------------------------------------------------------
1102
 * Setting the status will also set the Reason appropriately
1103
 */
1104
1105
void
1106 14936
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1107
{
1108
        char buf[4];
1109 14936
        const char *sstr = NULL;
1110
1111 14936
        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 14936
        to->status = status;
1117 14936
        status %= 1000;
1118 14936
        assert(status >= 100);
1119
1120 14936
        if (reason == NULL)
1121 3029
                reason = http_Status2Reason(status, &sstr);
1122
        else
1123 11907
                (void)http_Status2Reason(status, &sstr);
1124
1125 14936
        if (sstr) {
1126 14468
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1127 14468
        } else {
1128 468
                bprintf(buf, "%03d", status);
1129 468
                http_PutField(to, HTTP_HDR_STATUS, buf);
1130
        }
1131 14936
        http_SetH(to, HTTP_HDR_REASON, reason);
1132 14936
}
1133
1134
/*--------------------------------------------------------------------*/
1135
1136
const char *
1137 69433
http_GetMethod(const struct http *hp)
1138
{
1139
1140 69433
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1141 69433
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1142 69433
        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 101955
http_ForceField(struct http *to, unsigned n, const char *t)
1151
{
1152
        int i;
1153
1154 101955
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1155 101955
        assert(n < HTTP_HDR_FIRST);
1156 101955
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1157 101955
        AN(t);
1158
1159
        /* NB: method names and protocol versions are case-sensitive. */
1160 101955
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1161 1560
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1162 1560
                i += to->logtag;
1163
                /* XXX: this is a dead branch */
1164 1560
                if (n >= HTTP_HDR_FIRST)
1165 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1166 1560
                http_SetH(to, n, t);
1167 1560
        }
1168 101955
}
1169
1170
/*--------------------------------------------------------------------*/
1171
1172
void
1173 13637
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1174
    const char *reason)
1175
{
1176
1177 13637
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1178 13637
        if (proto != NULL)
1179 13637
                http_SetH(to, HTTP_HDR_PROTO, proto);
1180 13637
        http_SetStatus(to, status, reason);
1181 13637
}
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 527393
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1190
{
1191
        const char *e;
1192
        const struct http_hdrflg *f;
1193
1194 527393
        if (fm->hdf[u] & HDF_FILTER)
1195 221
                return (1);
1196 527172
        if (u < HTTP_HDR_FIRST)
1197 176708
                return (0);
1198 350464
        e = strchr(fm->hd[u].b, ':');
1199 350464
        if (e == NULL)
1200 0
                return (0);
1201 350464
        f = http_hdr_flags(fm->hd[u].b, e);
1202 350464
        return (f != NULL && f->flag & how);
1203 527393
}
1204
1205
int
1206 10914
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1207
{
1208
1209 10914
        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 29497
http_EstimateWS(const struct http *fm, unsigned how)
1219
{
1220
        unsigned u, l;
1221
1222 29497
        l = 4;
1223 29497
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1224 282275
        for (u = 0; u < fm->nhd; u++) {
1225 252778
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1226 58992
                        continue;
1227 193786
                Tcheck(fm->hd[u]);
1228 193786
                if (http_isfiltered(fm, u, how))
1229 3511
                        continue;
1230 190275
                l += Tlen(fm->hd[u]) + 1L;
1231 190275
        }
1232 29497
        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 29418
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 29418
        AN(p0);
1252 29418
        AN(l);
1253 29418
        p = p0;
1254 29418
        e = p + l;
1255 29418
        assert(p + 5 <= e);
1256 29418
        assert(fm->nhd <= fm->shd);
1257 29418
        n = HTTP_HDR_FIRST - 3;
1258 29418
        vbe16enc(p + 2, fm->status);
1259 29418
        p += 4;
1260 29418
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1261 281472
        for (u = 0; u < fm->nhd; u++) {
1262 252054
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1263 58834
                        continue;
1264 193220
                Tcheck(fm->hd[u]);
1265 193220
                if (http_isfiltered(fm, u, how))
1266 3512
                        continue;
1267 189708
                http_VSLH(fm, u);
1268 189708
                w = Tlen(fm->hd[u]) + 1L;
1269 189708
                assert(p + w + 1 <= e);
1270 189708
                memcpy(p, fm->hd[u].b, w);
1271 189708
                p += w;
1272 189708
                n++;
1273 189708
        }
1274 29418
        *p++ = '\0';
1275 29418
        assert(p <= e);
1276 29418
        vbe16enc(p0, n + 1);
1277 29418
}
1278
1279
/*--------------------------------------------------------------------
1280
 * Decode byte string into http struct
1281
 */
1282
1283
int
1284 43219
HTTP_Decode(struct http *to, const uint8_t *fm)
1285
{
1286
1287 43219
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1288 43219
        AN(to->vsl);
1289 43219
        AN(fm);
1290 43219
        if (vbe16dec(fm) <= to->shd) {
1291 43198
                to->status = vbe16dec(fm + 2);
1292 43198
                fm += 4;
1293 409711
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1294 409711
                        if (to->nhd == HTTP_HDR_METHOD ||
1295 366496
                            to->nhd == HTTP_HDR_URL) {
1296 86377
                                to->hd[to->nhd].b = NULL;
1297 86377
                                to->hd[to->nhd].e = NULL;
1298 86377
                                continue;
1299
                        }
1300 323334
                        if (*fm == '\0')
1301 43198
                                return (0);
1302 280136
                        to->hd[to->nhd].b = (const void*)fm;
1303 280136
                        fm = (const void*)strchr((const void*)fm, '\0');
1304 280136
                        to->hd[to->nhd].e = (const void*)fm;
1305 280136
                        fm++;
1306 280136
                        http_VSLH(to, to->nhd);
1307 280136
                }
1308 0
        }
1309 42
        VSLb(to->vsl, SLT_Error,
1310
            "Too many headers to Decode object (%u vs. %u)",
1311 21
            vbe16dec(fm), to->shd);
1312 21
        return (-1);
1313 43219
}
1314
1315
/*--------------------------------------------------------------------*/
1316
1317
uint16_t
1318 429
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1319
{
1320
        const char *ptr;
1321 429
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1322 429
        AN(ptr);
1323
1324 429
        return (vbe16dec(ptr + 2));
1325
}
1326
1327
/*--------------------------------------------------------------------*/
1328
1329
/* Get the first packed header */
1330
int
1331 11731
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1332
{
1333
        const char *ptr;
1334
1335 11731
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1336 11731
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1337 11731
        AN(p);
1338
1339 11731
        if (*p == NULL) {
1340 3606
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1341 3606
                AN(ptr);
1342 3606
                ptr += 4;       /* Skip nhd and status */
1343 3606
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1344 3606
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1345 3606
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1346 3606
                *p = ptr;
1347 3606
        } else {
1348 8125
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1349
        }
1350 11731
        if (**p == '\0')
1351 762
                return (0);
1352 10969
        return (1);
1353 11731
}
1354
1355
const char *
1356 3840
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1357
{
1358
        const char *ptr;
1359
1360 3840
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1361 3840
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1362 3840
        CHECK_HDR(hdr);
1363
1364 3840
        if (hdr->str[0] == ':') {
1365
                /* Special cases */
1366 234
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1367 234
                AN(ptr);
1368 234
                ptr += 4;       /* Skip nhd and status */
1369
1370
                /* XXX: should we also have h2_hdr_eq() ? */
1371 234
                if (!strcmp(hdr->str, ":proto:"))
1372 26
                        return (ptr);
1373 208
                ptr = strchr(ptr, '\0') + 1;
1374 208
                if (!strcmp(hdr->str, ":status:"))
1375 182
                        return (ptr);
1376 26
                ptr = strchr(ptr, '\0') + 1;
1377 26
                if (!strcmp(hdr->str, ":reason:"))
1378 26
                        return (ptr);
1379 0
                WRONG("Unknown magic packed header");
1380 0
        }
1381
1382 11732
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1383 10970
                if (http_hdr_at(ptr, hdr->str, hdr->len)) {
1384 2844
                        ptr += hdr->len;
1385 5675
                        while (vct_islws(*ptr))
1386 2831
                                ptr++;
1387 2844
                        return (ptr);
1388
                }
1389
        }
1390
1391 762
        return (NULL);
1392 3840
}
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 403
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 403
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1408 403
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1409 403
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1410
1411 403
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1412 403
        AN(ptr);
1413
1414 403
        to->status = vbe16dec(ptr + 2);
1415 403
        ptr += 4;
1416
1417 2418
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1418 2015
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1419 806
                        continue;
1420 1209
                http_SetH(to, u, ptr);
1421 1209
                ptr = strchr(ptr, '\0') + 1;
1422 1209
        }
1423 403
        nhd_before_merge = to->nhd;
1424 2405
        while (*ptr != '\0') {
1425 2002
                p = strchr(ptr, ':');
1426 2002
                AN(p);
1427 2002
                u = http_findhdr(to, p - ptr, ptr);
1428 2002
                if (u == 0 || u >= nhd_before_merge)
1429 949
                        http_SetHeader(to, ptr);
1430 2002
                ptr = strchr(ptr, '\0') + 1;
1431
        }
1432 403
}
1433
1434
/*--------------------------------------------------------------------*/
1435
1436
static void
1437 90549
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1438
{
1439
1440 90549
        assert(n < HTTP_HDR_FIRST);
1441 90549
        Tcheck(fm->hd[n]);
1442 90549
        to->hd[n] = fm->hd[n];
1443 90549
        to->hdf[n] = fm->hdf[n];
1444 90549
        http_VSLH(to, n);
1445 90549
}
1446
1447
/*--------------------------------------------------------------------*/
1448
1449
void
1450 30186
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1451
{
1452
        unsigned u;
1453
1454 30186
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1455 30186
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1456
1457 30186
        http_linkh(to, fm, HTTP_HDR_METHOD);
1458 30186
        http_linkh(to, fm, HTTP_HDR_URL);
1459 30186
        http_linkh(to, fm, HTTP_HDR_PROTO);
1460 30186
        to->protover = fm->protover;
1461 30186
        to->status = fm->status;
1462
1463 30186
        to->nhd = HTTP_HDR_FIRST;
1464 159663
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1465 129477
                Tcheck(fm->hd[u]);
1466 129477
                if (http_isfiltered(fm, u, how))
1467 1495
                        continue;
1468 127982
                assert (to->nhd < to->shd);
1469 127982
                to->hd[to->nhd] = fm->hd[u];
1470 127982
                to->hdf[to->nhd] = 0;
1471 127982
                http_VSLH(to, to->nhd);
1472 127982
                to->nhd++;
1473 127982
        }
1474 30186
}
1475
1476
/*--------------------------------------------------------------------
1477
 * This function copies any header fields which reference foreign
1478
 * storage into our own WS.
1479
 */
1480
1481
void
1482 29795
http_CopyHome(const struct http *hp)
1483
{
1484
        unsigned u, l;
1485
        const char *p;
1486
1487 323871
        for (u = 0; u < hp->nhd; u++) {
1488 294076
                if (hp->hd[u].b == NULL) {
1489 59588
                        assert(u < HTTP_HDR_FIRST);
1490 59588
                        continue;
1491
                }
1492
1493 234488
                l = Tlen(hp->hd[u]);
1494 234488
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1495 18868
                        continue;
1496
1497 215620
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1498 215620
                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 215620
                hp->hd[u].b = p;
1504 215620
                hp->hd[u].e = p + l;
1505 215620
        }
1506 29795
}
1507
1508
/*--------------------------------------------------------------------*/
1509
1510
void
1511 124379
http_SetHeader(struct http *to, const char *header)
1512
{
1513
1514 124379
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1515 124379
        if (to->nhd >= to->shd) {
1516 13
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1517 13
                http_fail(to);
1518 13
                return;
1519
        }
1520 124366
        http_SetH(to, to->nhd++, header);
1521 124379
}
1522
1523
/*--------------------------------------------------------------------*/
1524
1525
void
1526 55288
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1527
{
1528
1529 55288
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1530 55288
        if (http_HdrIs(to, hdr, val))
1531 5026
                return;
1532 50262
        http_Unset(to, hdr);
1533 50262
        http_PrintfHeader(to, "%s %s", hdr->str, val);
1534 55288
}
1535
1536
void
1537 141570
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1538
{
1539
        const char *old;
1540
1541 141570
        http_CollectHdr(to, hdr);
1542 141570
        if (http_GetHdr(to, hdr, &old)) {
1543 624
                http_Unset(to, hdr);
1544 624
                http_PrintfHeader(to, "%s %s, %s", hdr->str, old, val);
1545 624
        } else {
1546 140946
                http_PrintfHeader(to, "%s %s", hdr->str, val);
1547
        }
1548 141570
}
1549
1550
void
1551 332939
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 332939
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1559
1560 332939
        va_start(ap, fmt);
1561 332939
        va_copy(ap2, ap);
1562
1563 332939
        WS_VSB_new(vsb, to->ws);
1564 332939
        VSB_vprintf(vsb, fmt, ap);
1565 332939
        p = WS_VSB_finish(vsb, to->ws, &sz);
1566
1567 332939
        if (p == NULL || to->nhd >= to->shd) {
1568 362
                http_fail(to);
1569 362
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1570 362
        } else {
1571 332579
                http_SetH(to, to->nhd++, p);
1572
        }
1573 332941
        va_end(ap);
1574 332941
        va_end(ap2);
1575 332941
}
1576
1577
void
1578 13739
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1579
{
1580
        char *p;
1581
1582 13739
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1583 13739
        if (to->nhd >= to->shd) {
1584 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1585 0
                http_fail(to);
1586 0
                return;
1587
        }
1588 13739
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1589 13739
        if (p == NULL) {
1590 1001
                http_fail(to);
1591 1001
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1592 1001
                return;
1593
        }
1594 12738
        strcpy(p, fmt);
1595 12738
        VTIM_format(now, strchr(p, '\0'));
1596 12738
        http_SetH(to, to->nhd++, p);
1597 13739
}
1598
1599
const char *
1600 92381
http_ViaHeader(void)
1601
{
1602
1603 92381
        return (via_hdr);
1604
}
1605
1606
/*--------------------------------------------------------------------*/
1607
1608
void
1609 302741
http_Unset(struct http *hp, hdr_t hdr)
1610
{
1611
        uint16_t u, v;
1612
1613 1966920
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1614 1664179
                Tcheck(hp->hd[u]);
1615 1664179
                if (http_IsHdr(&hp->hd[u], hdr)) {
1616 13520
                        http_VSLH_del(hp, u);
1617 13520
                        continue;
1618
                }
1619 1650659
                if (v != u) {
1620 38489
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1621 38489
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1622 38489
                }
1623 1650659
                v++;
1624 1650659
        }
1625 302741
        hp->nhd = v;
1626 302741
}