blob: f7b09db04b305c1c57ff93ce3b0825dacea90959 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * HTTP protocol analyzer
3 *
Willy Tarreauf68a15a2011-01-06 16:53:21 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <syslog.h>
Willy Tarreau42250582007-04-01 01:30:43 +020020#include <time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +010026#include <common/base64.h>
Frédéric Lécaillea41d5312018-01-29 12:05:07 +010027#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020028#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020029#include <common/compat.h>
30#include <common/config.h>
Willy Tarreaua4cd1f52006-12-16 19:57:26 +010031#include <common/debug.h>
Willy Tarreauafba57a2018-12-11 13:44:24 +010032#include <common/h1.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020033#include <common/memory.h>
34#include <common/mini-clist.h>
35#include <common/standard.h>
Willy Tarreau0c303ee2008-07-07 00:09:58 +020036#include <common/ticks.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020037#include <common/time.h>
38#include <common/uri_auth.h>
39#include <common/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
41#include <types/capture.h>
Willy Tarreau12207b32016-11-22 19:48:51 +010042#include <types/cli.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020043#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <types/global.h>
William Lallemand9ed62032016-11-21 17:49:11 +010045#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
Willy Tarreau8797c062007-05-07 00:55:35 +020047#include <proto/acl.h>
Thierry FOURNIER322a1242015-08-19 09:07:47 +020048#include <proto/action.h>
Willy Tarreau61612d42012-04-19 18:42:05 +020049#include <proto/arg.h>
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +010050#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020052#include <proto/channel.h>
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +010053#include <proto/checks.h>
Willy Tarreau12207b32016-11-22 19:48:51 +010054#include <proto/cli.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020055#include <proto/compression.h>
Baptiste Assmann333939c2019-01-21 08:34:50 +010056#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010057#include <proto/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/fd.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020059#include <proto/filters.h>
Willy Tarreau03fa5df2010-05-24 21:02:37 +020060#include <proto/frontend.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/log.h>
Patrick Hemmere3faf022018-08-22 10:02:00 -040062#include <proto/hlua.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010063#include <proto/pattern.h>
Willy Tarreaub6866442008-07-14 23:54:42 +020064#include <proto/proto_tcp.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/proto_http.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010066#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/queue.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020068#include <proto/sample.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010069#include <proto/server.h>
Olivier Houchard985f1392018-11-30 17:31:52 +010070#include <proto/session.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020071#include <proto/stream.h>
Willy Tarreaucff64112008-11-03 06:26:53 +010072#include <proto/stream_interface.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/task.h>
Baptiste Assmannfabcbe02014-04-24 22:16:59 +020074#include <proto/pattern.h>
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020075#include <proto/vars.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Christopher Faulet711ed6a2019-07-16 14:16:10 +020077DECLARE_POOL(pool_head_http_txn, "http_txn", sizeof(struct http_txn));
78DECLARE_POOL(pool_head_uniqueid, "uniqueid", UNIQUEID_LEN);
Willy Tarreaue92693a2012-09-24 21:13:39 +020079
Christopher Faulet711ed6a2019-07-16 14:16:10 +020080struct pool_head *pool_head_requri = NULL;
81struct pool_head *pool_head_capture = NULL;
Willy Tarreau58f10d72006-12-04 02:26:12 +010082
Willy Tarreaueee5b512015-04-03 23:46:31 +020083
84/* Allocate a new HTTP transaction for stream <s> unless there is one already.
Christopher Faulet711ed6a2019-07-16 14:16:10 +020085 * In case of allocation failure, everything allocated is freed and NULL is
86 * returned. Otherwise the new transaction is assigned to the stream and
87 * returned.
Willy Tarreaueee5b512015-04-03 23:46:31 +020088 */
89struct http_txn *http_alloc_txn(struct stream *s)
90{
91 struct http_txn *txn = s->txn;
92
93 if (txn)
94 return txn;
95
Willy Tarreaubafbe012017-11-24 17:34:44 +010096 txn = pool_alloc(pool_head_http_txn);
Willy Tarreaueee5b512015-04-03 23:46:31 +020097 if (!txn)
98 return txn;
99
Willy Tarreaueee5b512015-04-03 23:46:31 +0200100 s->txn = txn;
101 return txn;
102}
103
Thierry FOURNIERfd50f0b2015-09-25 18:53:18 +0200104void http_txn_reset_req(struct http_txn *txn)
105{
106 txn->req.flags = 0;
Thierry FOURNIERfd50f0b2015-09-25 18:53:18 +0200107 txn->req.msg_state = HTTP_MSG_RQBEFORE; /* at the very beginning of the request */
108}
109
110void http_txn_reset_res(struct http_txn *txn)
111{
112 txn->rsp.flags = 0;
Thierry FOURNIERfd50f0b2015-09-25 18:53:18 +0200113 txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */
114}
115
Willy Tarreau0937bc42009-12-22 15:03:09 +0100116/*
Willy Tarreau87b09662015-04-03 00:22:06 +0200117 * Initialize a new HTTP transaction for stream <s>. It is assumed that all
Willy Tarreau0937bc42009-12-22 15:03:09 +0100118 * the required fields are properly allocated and that we only need to (re)init
119 * them. This should be used before processing any new request.
120 */
Willy Tarreau87b09662015-04-03 00:22:06 +0200121void http_init_txn(struct stream *s)
Willy Tarreau0937bc42009-12-22 15:03:09 +0100122{
Willy Tarreaueee5b512015-04-03 23:46:31 +0200123 struct http_txn *txn = s->txn;
Christopher Fauletf2824e62018-10-01 12:12:37 +0200124 struct conn_stream *cs = objt_cs(s->si[0].end);
Willy Tarreau0937bc42009-12-22 15:03:09 +0100125
Christopher Fauletf2824e62018-10-01 12:12:37 +0200126 txn->flags = ((cs && cs->flags & CS_FL_NOT_FIRST)
127 ? (TX_NOT_FIRST|TX_WAIT_NEXT_RQ)
128 : 0);
Willy Tarreau0937bc42009-12-22 15:03:09 +0100129 txn->status = -1;
Willy Tarreauc9036c02019-01-11 19:38:25 +0100130 *(unsigned int *)txn->cache_hash = 0;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100131
Willy Tarreauf64d1412010-10-07 20:06:11 +0200132 txn->cookie_first_date = 0;
133 txn->cookie_last_date = 0;
134
Willy Tarreaueee5b512015-04-03 23:46:31 +0200135 txn->srv_cookie = NULL;
136 txn->cli_cookie = NULL;
137 txn->uri = NULL;
138
Thierry FOURNIERfd50f0b2015-09-25 18:53:18 +0200139 http_txn_reset_req(txn);
140 http_txn_reset_res(txn);
141
Willy Tarreau22ec1ea2014-11-27 20:45:39 +0100142 txn->req.chn = &s->req;
143 txn->rsp.chn = &s->res;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100144
145 txn->auth.method = HTTP_AUTH_UNKNOWN;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100146
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200147 vars_init(&s->vars_txn, SCOPE_TXN);
148 vars_init(&s->vars_reqres, SCOPE_REQ);
Willy Tarreau0937bc42009-12-22 15:03:09 +0100149}
150
151/* to be used at the end of a transaction */
Willy Tarreau87b09662015-04-03 00:22:06 +0200152void http_end_txn(struct stream *s)
Willy Tarreau0937bc42009-12-22 15:03:09 +0100153{
Willy Tarreaueee5b512015-04-03 23:46:31 +0200154 struct http_txn *txn = s->txn;
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200155 struct proxy *fe = strm_fe(s);
Willy Tarreau0937bc42009-12-22 15:03:09 +0100156
157 /* these ones will have been dynamically allocated */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100158 pool_free(pool_head_requri, txn->uri);
159 pool_free(pool_head_capture, txn->cli_cookie);
160 pool_free(pool_head_capture, txn->srv_cookie);
161 pool_free(pool_head_uniqueid, s->unique_id);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100162
William Lallemanda73203e2012-03-12 12:48:57 +0100163 s->unique_id = NULL;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100164 txn->uri = NULL;
165 txn->srv_cookie = NULL;
166 txn->cli_cookie = NULL;
Willy Tarreau46023632010-01-07 22:51:47 +0100167
Willy Tarreaucb7dd012015-04-03 22:16:32 +0200168 if (s->req_cap) {
Willy Tarreau46023632010-01-07 22:51:47 +0100169 struct cap_hdr *h;
Willy Tarreaue36cbcb2015-04-03 15:40:56 +0200170 for (h = fe->req_cap; h; h = h->next)
Willy Tarreaubafbe012017-11-24 17:34:44 +0100171 pool_free(h->pool, s->req_cap[h->index]);
Willy Tarreaucb7dd012015-04-03 22:16:32 +0200172 memset(s->req_cap, 0, fe->nb_req_cap * sizeof(void *));
Willy Tarreau46023632010-01-07 22:51:47 +0100173 }
174
Willy Tarreaucb7dd012015-04-03 22:16:32 +0200175 if (s->res_cap) {
Willy Tarreau46023632010-01-07 22:51:47 +0100176 struct cap_hdr *h;
Willy Tarreaue36cbcb2015-04-03 15:40:56 +0200177 for (h = fe->rsp_cap; h; h = h->next)
Willy Tarreaubafbe012017-11-24 17:34:44 +0100178 pool_free(h->pool, s->res_cap[h->index]);
Willy Tarreaucb7dd012015-04-03 22:16:32 +0200179 memset(s->res_cap, 0, fe->nb_rsp_cap * sizeof(void *));
Willy Tarreau46023632010-01-07 22:51:47 +0100180 }
181
Willy Tarreaucda7f3f2018-10-28 13:44:36 +0100182 if (!LIST_ISEMPTY(&s->vars_txn.head))
183 vars_prune(&s->vars_txn, s->sess, s);
184 if (!LIST_ISEMPTY(&s->vars_reqres.head))
185 vars_prune(&s->vars_reqres, s->sess, s);
Willy Tarreau0937bc42009-12-22 15:03:09 +0100186}
187
188/* to be used at the end of a transaction to prepare a new one */
Willy Tarreau87b09662015-04-03 00:22:06 +0200189void http_reset_txn(struct stream *s)
Willy Tarreau0937bc42009-12-22 15:03:09 +0100190{
191 http_end_txn(s);
192 http_init_txn(s);
193
Thierry FOURNIERbc4c1ac2015-02-25 13:36:14 +0100194 /* reinitialise the current rule list pointer to NULL. We are sure that
195 * any rulelist match the NULL pointer.
196 */
197 s->current_rule_list = NULL;
198
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200199 s->be = strm_fe(s);
200 s->logs.logwait = strm_fe(s)->to_log;
Willy Tarreauabcd5142013-06-11 17:18:02 +0200201 s->logs.level = 0;
Willy Tarreau87b09662015-04-03 00:22:06 +0200202 stream_del_srv_conn(s);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100203 s->target = NULL;
Emeric Brunb982a3d2010-01-04 15:45:53 +0100204 /* re-init store persistence */
205 s->store_count = 0;
Olivier Houcharda798bf52019-03-08 18:52:00 +0100206 s->uniq_id = _HA_ATOMIC_XADD(&global.req_count, 1);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100207
Willy Tarreau22ec1ea2014-11-27 20:45:39 +0100208 s->req.flags |= CF_READ_DONTWAIT; /* one read is usually enough */
Willy Tarreau0937bc42009-12-22 15:03:09 +0100209
Willy Tarreau739cfba2010-01-25 23:11:14 +0100210 /* We must trim any excess data from the response buffer, because we
211 * may have blocked an invalid response from a server that we don't
Joseph Herlant5ba80252018-11-15 09:25:36 -0800212 * want to accidently forward once we disable the analysers, nor do
Willy Tarreau739cfba2010-01-25 23:11:14 +0100213 * we want those data to come along with next response. A typical
214 * example of such data would be from a buggy server responding to
215 * a HEAD with some data, or sending more than the advertised
216 * content-length.
217 */
Willy Tarreauf37954d2018-06-15 18:31:02 +0200218 if (unlikely(ci_data(&s->res)))
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200219 b_set_data(&s->res.buf, co_data(&s->res));
Willy Tarreau739cfba2010-01-25 23:11:14 +0100220
Christopher Fauletc0c672a2017-03-28 11:51:33 +0200221 /* Now we can realign the response buffer */
Willy Tarreaud5b343b2018-06-06 06:42:46 +0200222 c_realign_if_empty(&s->res);
Christopher Fauletc0c672a2017-03-28 11:51:33 +0200223
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200224 s->req.rto = strm_fe(s)->timeout.client;
Willy Tarreau22ec1ea2014-11-27 20:45:39 +0100225 s->req.wto = TICK_ETERNITY;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100226
Willy Tarreau22ec1ea2014-11-27 20:45:39 +0100227 s->res.rto = TICK_ETERNITY;
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200228 s->res.wto = strm_fe(s)->timeout.client;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100229
Willy Tarreau22ec1ea2014-11-27 20:45:39 +0100230 s->req.rex = TICK_ETERNITY;
231 s->req.wex = TICK_ETERNITY;
232 s->req.analyse_exp = TICK_ETERNITY;
233 s->res.rex = TICK_ETERNITY;
234 s->res.wex = TICK_ETERNITY;
235 s->res.analyse_exp = TICK_ETERNITY;
Hongbo Longe39683c2017-03-10 18:41:51 +0100236 s->si[1].hcto = TICK_ETERNITY;
Willy Tarreau0937bc42009-12-22 15:03:09 +0100237}
Willy Tarreau58f10d72006-12-04 02:26:12 +0100238
239/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 * Local variables:
241 * c-indent-level: 8
242 * c-basic-offset: 8
243 * End:
244 */