xref: /aosp_15_r20/external/curl/lib/http.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HTTP
28*6236dae4SAndroid Build Coastguard Worker 
29*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
30*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
31*6236dae4SAndroid Build Coastguard Worker #endif
32*6236dae4SAndroid Build Coastguard Worker 
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
34*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
37*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
38*6236dae4SAndroid Build Coastguard Worker #endif
39*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NET_IF_H
40*6236dae4SAndroid Build Coastguard Worker #include <net/if.h>
41*6236dae4SAndroid Build Coastguard Worker #endif
42*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
43*6236dae4SAndroid Build Coastguard Worker #include <sys/ioctl.h>
44*6236dae4SAndroid Build Coastguard Worker #endif
45*6236dae4SAndroid Build Coastguard Worker 
46*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_PARAM_H
47*6236dae4SAndroid Build Coastguard Worker #include <sys/param.h>
48*6236dae4SAndroid Build Coastguard Worker #endif
49*6236dae4SAndroid Build Coastguard Worker 
50*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HYPER
51*6236dae4SAndroid Build Coastguard Worker #include <hyper.h>
52*6236dae4SAndroid Build Coastguard Worker #endif
53*6236dae4SAndroid Build Coastguard Worker 
54*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
55*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
56*6236dae4SAndroid Build Coastguard Worker #include "transfer.h"
57*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
58*6236dae4SAndroid Build Coastguard Worker #include "formdata.h"
59*6236dae4SAndroid Build Coastguard Worker #include "mime.h"
60*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
61*6236dae4SAndroid Build Coastguard Worker #include "curl_base64.h"
62*6236dae4SAndroid Build Coastguard Worker #include "cookie.h"
63*6236dae4SAndroid Build Coastguard Worker #include "vauth/vauth.h"
64*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
65*6236dae4SAndroid Build Coastguard Worker #include "vquic/vquic.h"
66*6236dae4SAndroid Build Coastguard Worker #include "http_digest.h"
67*6236dae4SAndroid Build Coastguard Worker #include "http_ntlm.h"
68*6236dae4SAndroid Build Coastguard Worker #include "http_negotiate.h"
69*6236dae4SAndroid Build Coastguard Worker #include "http_aws_sigv4.h"
70*6236dae4SAndroid Build Coastguard Worker #include "url.h"
71*6236dae4SAndroid Build Coastguard Worker #include "share.h"
72*6236dae4SAndroid Build Coastguard Worker #include "hostip.h"
73*6236dae4SAndroid Build Coastguard Worker #include "dynhds.h"
74*6236dae4SAndroid Build Coastguard Worker #include "http.h"
75*6236dae4SAndroid Build Coastguard Worker #include "headers.h"
76*6236dae4SAndroid Build Coastguard Worker #include "select.h"
77*6236dae4SAndroid Build Coastguard Worker #include "parsedate.h" /* for the week day and month names */
78*6236dae4SAndroid Build Coastguard Worker #include "strtoofft.h"
79*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
80*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
81*6236dae4SAndroid Build Coastguard Worker #include "content_encoding.h"
82*6236dae4SAndroid Build Coastguard Worker #include "http_proxy.h"
83*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
84*6236dae4SAndroid Build Coastguard Worker #include "http2.h"
85*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
86*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
87*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
88*6236dae4SAndroid Build Coastguard Worker #include "altsvc.h"
89*6236dae4SAndroid Build Coastguard Worker #include "hsts.h"
90*6236dae4SAndroid Build Coastguard Worker #include "ws.h"
91*6236dae4SAndroid Build Coastguard Worker #include "c-hyper.h"
92*6236dae4SAndroid Build Coastguard Worker #include "curl_ctype.h"
93*6236dae4SAndroid Build Coastguard Worker 
94*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
95*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
96*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
97*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
98*6236dae4SAndroid Build Coastguard Worker 
99*6236dae4SAndroid Build Coastguard Worker /*
100*6236dae4SAndroid Build Coastguard Worker  * Forward declarations.
101*6236dae4SAndroid Build Coastguard Worker  */
102*6236dae4SAndroid Build Coastguard Worker 
103*6236dae4SAndroid Build Coastguard Worker static bool http_should_fail(struct Curl_easy *data, int httpcode);
104*6236dae4SAndroid Build Coastguard Worker static bool http_exp100_is_waiting(struct Curl_easy *data);
105*6236dae4SAndroid Build Coastguard Worker static CURLcode http_exp100_add_reader(struct Curl_easy *data);
106*6236dae4SAndroid Build Coastguard Worker static void http_exp100_send_anyway(struct Curl_easy *data);
107*6236dae4SAndroid Build Coastguard Worker 
108*6236dae4SAndroid Build Coastguard Worker /*
109*6236dae4SAndroid Build Coastguard Worker  * HTTP handler interface.
110*6236dae4SAndroid Build Coastguard Worker  */
111*6236dae4SAndroid Build Coastguard Worker const struct Curl_handler Curl_handler_http = {
112*6236dae4SAndroid Build Coastguard Worker   "http",                               /* scheme */
113*6236dae4SAndroid Build Coastguard Worker   Curl_http_setup_conn,                 /* setup_connection */
114*6236dae4SAndroid Build Coastguard Worker   Curl_http,                            /* do_it */
115*6236dae4SAndroid Build Coastguard Worker   Curl_http_done,                       /* done */
116*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* do_more */
117*6236dae4SAndroid Build Coastguard Worker   Curl_http_connect,                    /* connect_it */
118*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* connecting */
119*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing */
120*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* proto_getsock */
121*6236dae4SAndroid Build Coastguard Worker   Curl_http_getsock_do,                 /* doing_getsock */
122*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* domore_getsock */
123*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* perform_getsock */
124*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* disconnect */
125*6236dae4SAndroid Build Coastguard Worker   Curl_http_write_resp,                 /* write_resp */
126*6236dae4SAndroid Build Coastguard Worker   Curl_http_write_resp_hd,              /* write_resp_hd */
127*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* connection_check */
128*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* attach connection */
129*6236dae4SAndroid Build Coastguard Worker   PORT_HTTP,                            /* defport */
130*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_HTTP,                       /* protocol */
131*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_HTTP,                       /* family */
132*6236dae4SAndroid Build Coastguard Worker   PROTOPT_CREDSPERREQUEST |             /* flags */
133*6236dae4SAndroid Build Coastguard Worker   PROTOPT_USERPWDCTRL
134*6236dae4SAndroid Build Coastguard Worker };
135*6236dae4SAndroid Build Coastguard Worker 
136*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
137*6236dae4SAndroid Build Coastguard Worker /*
138*6236dae4SAndroid Build Coastguard Worker  * HTTPS handler interface.
139*6236dae4SAndroid Build Coastguard Worker  */
140*6236dae4SAndroid Build Coastguard Worker const struct Curl_handler Curl_handler_https = {
141*6236dae4SAndroid Build Coastguard Worker   "https",                              /* scheme */
142*6236dae4SAndroid Build Coastguard Worker   Curl_http_setup_conn,                 /* setup_connection */
143*6236dae4SAndroid Build Coastguard Worker   Curl_http,                            /* do_it */
144*6236dae4SAndroid Build Coastguard Worker   Curl_http_done,                       /* done */
145*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* do_more */
146*6236dae4SAndroid Build Coastguard Worker   Curl_http_connect,                    /* connect_it */
147*6236dae4SAndroid Build Coastguard Worker   NULL,                                 /* connecting */
148*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing */
149*6236dae4SAndroid Build Coastguard Worker   NULL,                                 /* proto_getsock */
150*6236dae4SAndroid Build Coastguard Worker   Curl_http_getsock_do,                 /* doing_getsock */
151*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* domore_getsock */
152*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* perform_getsock */
153*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* disconnect */
154*6236dae4SAndroid Build Coastguard Worker   Curl_http_write_resp,                 /* write_resp */
155*6236dae4SAndroid Build Coastguard Worker   Curl_http_write_resp_hd,              /* write_resp_hd */
156*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* connection_check */
157*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* attach connection */
158*6236dae4SAndroid Build Coastguard Worker   PORT_HTTPS,                           /* defport */
159*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_HTTPS,                      /* protocol */
160*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_HTTP,                       /* family */
161*6236dae4SAndroid Build Coastguard Worker   PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
162*6236dae4SAndroid Build Coastguard Worker   PROTOPT_USERPWDCTRL
163*6236dae4SAndroid Build Coastguard Worker };
164*6236dae4SAndroid Build Coastguard Worker 
165*6236dae4SAndroid Build Coastguard Worker #endif
166*6236dae4SAndroid Build Coastguard Worker 
Curl_http_setup_conn(struct Curl_easy * data,struct connectdata * conn)167*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_setup_conn(struct Curl_easy *data,
168*6236dae4SAndroid Build Coastguard Worker                               struct connectdata *conn)
169*6236dae4SAndroid Build Coastguard Worker {
170*6236dae4SAndroid Build Coastguard Worker   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
171*6236dae4SAndroid Build Coastguard Worker      during this request */
172*6236dae4SAndroid Build Coastguard Worker   connkeep(conn, "HTTP default");
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker   if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
175*6236dae4SAndroid Build Coastguard Worker     CURLcode result = Curl_conn_may_http3(data, conn);
176*6236dae4SAndroid Build Coastguard Worker     if(result)
177*6236dae4SAndroid Build Coastguard Worker       return result;
178*6236dae4SAndroid Build Coastguard Worker   }
179*6236dae4SAndroid Build Coastguard Worker 
180*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
181*6236dae4SAndroid Build Coastguard Worker }
182*6236dae4SAndroid Build Coastguard Worker 
183*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
184*6236dae4SAndroid Build Coastguard Worker /*
185*6236dae4SAndroid Build Coastguard Worker  * checkProxyHeaders() checks the linked list of custom proxy headers
186*6236dae4SAndroid Build Coastguard Worker  * if proxy headers are not available, then it will lookup into http header
187*6236dae4SAndroid Build Coastguard Worker  * link list
188*6236dae4SAndroid Build Coastguard Worker  *
189*6236dae4SAndroid Build Coastguard Worker  * It takes a connectdata struct as input to see if this is a proxy request or
190*6236dae4SAndroid Build Coastguard Worker  * not, as it then might check a different header list. Provide the header
191*6236dae4SAndroid Build Coastguard Worker  * prefix without colon!
192*6236dae4SAndroid Build Coastguard Worker  */
Curl_checkProxyheaders(struct Curl_easy * data,const struct connectdata * conn,const char * thisheader,const size_t thislen)193*6236dae4SAndroid Build Coastguard Worker char *Curl_checkProxyheaders(struct Curl_easy *data,
194*6236dae4SAndroid Build Coastguard Worker                              const struct connectdata *conn,
195*6236dae4SAndroid Build Coastguard Worker                              const char *thisheader,
196*6236dae4SAndroid Build Coastguard Worker                              const size_t thislen)
197*6236dae4SAndroid Build Coastguard Worker {
198*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *head;
199*6236dae4SAndroid Build Coastguard Worker 
200*6236dae4SAndroid Build Coastguard Worker   for(head = (conn->bits.proxy && data->set.sep_headers) ?
201*6236dae4SAndroid Build Coastguard Worker         data->set.proxyheaders : data->set.headers;
202*6236dae4SAndroid Build Coastguard Worker       head; head = head->next) {
203*6236dae4SAndroid Build Coastguard Worker     if(strncasecompare(head->data, thisheader, thislen) &&
204*6236dae4SAndroid Build Coastguard Worker        Curl_headersep(head->data[thislen]))
205*6236dae4SAndroid Build Coastguard Worker       return head->data;
206*6236dae4SAndroid Build Coastguard Worker   }
207*6236dae4SAndroid Build Coastguard Worker 
208*6236dae4SAndroid Build Coastguard Worker   return NULL;
209*6236dae4SAndroid Build Coastguard Worker }
210*6236dae4SAndroid Build Coastguard Worker #else
211*6236dae4SAndroid Build Coastguard Worker /* disabled */
212*6236dae4SAndroid Build Coastguard Worker #define Curl_checkProxyheaders(x,y,z,a) NULL
213*6236dae4SAndroid Build Coastguard Worker #endif
214*6236dae4SAndroid Build Coastguard Worker 
215*6236dae4SAndroid Build Coastguard Worker /*
216*6236dae4SAndroid Build Coastguard Worker  * Strip off leading and trailing whitespace from the value in the
217*6236dae4SAndroid Build Coastguard Worker  * given HTTP header line and return a strdupped copy. Returns NULL in
218*6236dae4SAndroid Build Coastguard Worker  * case of allocation failure. Returns an empty string if the header value
219*6236dae4SAndroid Build Coastguard Worker  * consists entirely of whitespace.
220*6236dae4SAndroid Build Coastguard Worker  */
Curl_copy_header_value(const char * header)221*6236dae4SAndroid Build Coastguard Worker char *Curl_copy_header_value(const char *header)
222*6236dae4SAndroid Build Coastguard Worker {
223*6236dae4SAndroid Build Coastguard Worker   const char *start;
224*6236dae4SAndroid Build Coastguard Worker   const char *end;
225*6236dae4SAndroid Build Coastguard Worker   size_t len;
226*6236dae4SAndroid Build Coastguard Worker 
227*6236dae4SAndroid Build Coastguard Worker   /* Find the end of the header name */
228*6236dae4SAndroid Build Coastguard Worker   while(*header && (*header != ':'))
229*6236dae4SAndroid Build Coastguard Worker     ++header;
230*6236dae4SAndroid Build Coastguard Worker 
231*6236dae4SAndroid Build Coastguard Worker   if(*header)
232*6236dae4SAndroid Build Coastguard Worker     /* Skip over colon */
233*6236dae4SAndroid Build Coastguard Worker     ++header;
234*6236dae4SAndroid Build Coastguard Worker 
235*6236dae4SAndroid Build Coastguard Worker   /* Find the first non-space letter */
236*6236dae4SAndroid Build Coastguard Worker   start = header;
237*6236dae4SAndroid Build Coastguard Worker   while(*start && ISSPACE(*start))
238*6236dae4SAndroid Build Coastguard Worker     start++;
239*6236dae4SAndroid Build Coastguard Worker 
240*6236dae4SAndroid Build Coastguard Worker   end = strchr(start, '\r');
241*6236dae4SAndroid Build Coastguard Worker   if(!end)
242*6236dae4SAndroid Build Coastguard Worker     end = strchr(start, '\n');
243*6236dae4SAndroid Build Coastguard Worker   if(!end)
244*6236dae4SAndroid Build Coastguard Worker     end = strchr(start, '\0');
245*6236dae4SAndroid Build Coastguard Worker   if(!end)
246*6236dae4SAndroid Build Coastguard Worker     return NULL;
247*6236dae4SAndroid Build Coastguard Worker 
248*6236dae4SAndroid Build Coastguard Worker   /* skip all trailing space letters */
249*6236dae4SAndroid Build Coastguard Worker   while((end > start) && ISSPACE(*end))
250*6236dae4SAndroid Build Coastguard Worker     end--;
251*6236dae4SAndroid Build Coastguard Worker 
252*6236dae4SAndroid Build Coastguard Worker   /* get length of the type */
253*6236dae4SAndroid Build Coastguard Worker   len = end - start + 1;
254*6236dae4SAndroid Build Coastguard Worker 
255*6236dae4SAndroid Build Coastguard Worker   return Curl_memdup0(start, len);
256*6236dae4SAndroid Build Coastguard Worker }
257*6236dae4SAndroid Build Coastguard Worker 
258*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HTTP_AUTH
259*6236dae4SAndroid Build Coastguard Worker 
260*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BASIC_AUTH
261*6236dae4SAndroid Build Coastguard Worker /*
262*6236dae4SAndroid Build Coastguard Worker  * http_output_basic() sets up an Authorization: header (or the proxy version)
263*6236dae4SAndroid Build Coastguard Worker  * for HTTP Basic authentication.
264*6236dae4SAndroid Build Coastguard Worker  *
265*6236dae4SAndroid Build Coastguard Worker  * Returns CURLcode.
266*6236dae4SAndroid Build Coastguard Worker  */
http_output_basic(struct Curl_easy * data,bool proxy)267*6236dae4SAndroid Build Coastguard Worker static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
268*6236dae4SAndroid Build Coastguard Worker {
269*6236dae4SAndroid Build Coastguard Worker   size_t size = 0;
270*6236dae4SAndroid Build Coastguard Worker   char *authorization = NULL;
271*6236dae4SAndroid Build Coastguard Worker   char **userp;
272*6236dae4SAndroid Build Coastguard Worker   const char *user;
273*6236dae4SAndroid Build Coastguard Worker   const char *pwd;
274*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
275*6236dae4SAndroid Build Coastguard Worker   char *out;
276*6236dae4SAndroid Build Coastguard Worker 
277*6236dae4SAndroid Build Coastguard Worker   /* credentials are unique per transfer for HTTP, do not use the ones for the
278*6236dae4SAndroid Build Coastguard Worker      connection */
279*6236dae4SAndroid Build Coastguard Worker   if(proxy) {
280*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
281*6236dae4SAndroid Build Coastguard Worker     userp = &data->state.aptr.proxyuserpwd;
282*6236dae4SAndroid Build Coastguard Worker     user = data->state.aptr.proxyuser;
283*6236dae4SAndroid Build Coastguard Worker     pwd = data->state.aptr.proxypasswd;
284*6236dae4SAndroid Build Coastguard Worker #else
285*6236dae4SAndroid Build Coastguard Worker     return CURLE_NOT_BUILT_IN;
286*6236dae4SAndroid Build Coastguard Worker #endif
287*6236dae4SAndroid Build Coastguard Worker   }
288*6236dae4SAndroid Build Coastguard Worker   else {
289*6236dae4SAndroid Build Coastguard Worker     userp = &data->state.aptr.userpwd;
290*6236dae4SAndroid Build Coastguard Worker     user = data->state.aptr.user;
291*6236dae4SAndroid Build Coastguard Worker     pwd = data->state.aptr.passwd;
292*6236dae4SAndroid Build Coastguard Worker   }
293*6236dae4SAndroid Build Coastguard Worker 
294*6236dae4SAndroid Build Coastguard Worker   out = aprintf("%s:%s", user ? user : "", pwd ? pwd : "");
295*6236dae4SAndroid Build Coastguard Worker   if(!out)
296*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
297*6236dae4SAndroid Build Coastguard Worker 
298*6236dae4SAndroid Build Coastguard Worker   result = Curl_base64_encode(out, strlen(out), &authorization, &size);
299*6236dae4SAndroid Build Coastguard Worker   if(result)
300*6236dae4SAndroid Build Coastguard Worker     goto fail;
301*6236dae4SAndroid Build Coastguard Worker 
302*6236dae4SAndroid Build Coastguard Worker   if(!authorization) {
303*6236dae4SAndroid Build Coastguard Worker     result = CURLE_REMOTE_ACCESS_DENIED;
304*6236dae4SAndroid Build Coastguard Worker     goto fail;
305*6236dae4SAndroid Build Coastguard Worker   }
306*6236dae4SAndroid Build Coastguard Worker 
307*6236dae4SAndroid Build Coastguard Worker   free(*userp);
308*6236dae4SAndroid Build Coastguard Worker   *userp = aprintf("%sAuthorization: Basic %s\r\n",
309*6236dae4SAndroid Build Coastguard Worker                    proxy ? "Proxy-" : "",
310*6236dae4SAndroid Build Coastguard Worker                    authorization);
311*6236dae4SAndroid Build Coastguard Worker   free(authorization);
312*6236dae4SAndroid Build Coastguard Worker   if(!*userp) {
313*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
314*6236dae4SAndroid Build Coastguard Worker     goto fail;
315*6236dae4SAndroid Build Coastguard Worker   }
316*6236dae4SAndroid Build Coastguard Worker 
317*6236dae4SAndroid Build Coastguard Worker fail:
318*6236dae4SAndroid Build Coastguard Worker   free(out);
319*6236dae4SAndroid Build Coastguard Worker   return result;
320*6236dae4SAndroid Build Coastguard Worker }
321*6236dae4SAndroid Build Coastguard Worker 
322*6236dae4SAndroid Build Coastguard Worker #endif
323*6236dae4SAndroid Build Coastguard Worker 
324*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BEARER_AUTH
325*6236dae4SAndroid Build Coastguard Worker /*
326*6236dae4SAndroid Build Coastguard Worker  * http_output_bearer() sets up an Authorization: header
327*6236dae4SAndroid Build Coastguard Worker  * for HTTP Bearer authentication.
328*6236dae4SAndroid Build Coastguard Worker  *
329*6236dae4SAndroid Build Coastguard Worker  * Returns CURLcode.
330*6236dae4SAndroid Build Coastguard Worker  */
http_output_bearer(struct Curl_easy * data)331*6236dae4SAndroid Build Coastguard Worker static CURLcode http_output_bearer(struct Curl_easy *data)
332*6236dae4SAndroid Build Coastguard Worker {
333*6236dae4SAndroid Build Coastguard Worker   char **userp;
334*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
335*6236dae4SAndroid Build Coastguard Worker 
336*6236dae4SAndroid Build Coastguard Worker   userp = &data->state.aptr.userpwd;
337*6236dae4SAndroid Build Coastguard Worker   free(*userp);
338*6236dae4SAndroid Build Coastguard Worker   *userp = aprintf("Authorization: Bearer %s\r\n",
339*6236dae4SAndroid Build Coastguard Worker                    data->set.str[STRING_BEARER]);
340*6236dae4SAndroid Build Coastguard Worker 
341*6236dae4SAndroid Build Coastguard Worker   if(!*userp) {
342*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
343*6236dae4SAndroid Build Coastguard Worker     goto fail;
344*6236dae4SAndroid Build Coastguard Worker   }
345*6236dae4SAndroid Build Coastguard Worker 
346*6236dae4SAndroid Build Coastguard Worker fail:
347*6236dae4SAndroid Build Coastguard Worker   return result;
348*6236dae4SAndroid Build Coastguard Worker }
349*6236dae4SAndroid Build Coastguard Worker 
350*6236dae4SAndroid Build Coastguard Worker #endif
351*6236dae4SAndroid Build Coastguard Worker 
352*6236dae4SAndroid Build Coastguard Worker #endif
353*6236dae4SAndroid Build Coastguard Worker 
354*6236dae4SAndroid Build Coastguard Worker /* pickoneauth() selects the most favourable authentication method from the
355*6236dae4SAndroid Build Coastguard Worker  * ones available and the ones we want.
356*6236dae4SAndroid Build Coastguard Worker  *
357*6236dae4SAndroid Build Coastguard Worker  * return TRUE if one was picked
358*6236dae4SAndroid Build Coastguard Worker  */
pickoneauth(struct auth * pick,unsigned long mask)359*6236dae4SAndroid Build Coastguard Worker static bool pickoneauth(struct auth *pick, unsigned long mask)
360*6236dae4SAndroid Build Coastguard Worker {
361*6236dae4SAndroid Build Coastguard Worker   bool picked;
362*6236dae4SAndroid Build Coastguard Worker   /* only deal with authentication we want */
363*6236dae4SAndroid Build Coastguard Worker   unsigned long avail = pick->avail & pick->want & mask;
364*6236dae4SAndroid Build Coastguard Worker   picked = TRUE;
365*6236dae4SAndroid Build Coastguard Worker 
366*6236dae4SAndroid Build Coastguard Worker   /* The order of these checks is highly relevant, as this will be the order
367*6236dae4SAndroid Build Coastguard Worker      of preference in case of the existence of multiple accepted types. */
368*6236dae4SAndroid Build Coastguard Worker   if(avail & CURLAUTH_NEGOTIATE)
369*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_NEGOTIATE;
370*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BEARER_AUTH
371*6236dae4SAndroid Build Coastguard Worker   else if(avail & CURLAUTH_BEARER)
372*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_BEARER;
373*6236dae4SAndroid Build Coastguard Worker #endif
374*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DIGEST_AUTH
375*6236dae4SAndroid Build Coastguard Worker   else if(avail & CURLAUTH_DIGEST)
376*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_DIGEST;
377*6236dae4SAndroid Build Coastguard Worker #endif
378*6236dae4SAndroid Build Coastguard Worker   else if(avail & CURLAUTH_NTLM)
379*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_NTLM;
380*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BASIC_AUTH
381*6236dae4SAndroid Build Coastguard Worker   else if(avail & CURLAUTH_BASIC)
382*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_BASIC;
383*6236dae4SAndroid Build Coastguard Worker #endif
384*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_AWS
385*6236dae4SAndroid Build Coastguard Worker   else if(avail & CURLAUTH_AWS_SIGV4)
386*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_AWS_SIGV4;
387*6236dae4SAndroid Build Coastguard Worker #endif
388*6236dae4SAndroid Build Coastguard Worker   else {
389*6236dae4SAndroid Build Coastguard Worker     pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
390*6236dae4SAndroid Build Coastguard Worker     picked = FALSE;
391*6236dae4SAndroid Build Coastguard Worker   }
392*6236dae4SAndroid Build Coastguard Worker   pick->avail = CURLAUTH_NONE; /* clear it here */
393*6236dae4SAndroid Build Coastguard Worker 
394*6236dae4SAndroid Build Coastguard Worker   return picked;
395*6236dae4SAndroid Build Coastguard Worker }
396*6236dae4SAndroid Build Coastguard Worker 
397*6236dae4SAndroid Build Coastguard Worker /*
398*6236dae4SAndroid Build Coastguard Worker  * http_perhapsrewind()
399*6236dae4SAndroid Build Coastguard Worker  *
400*6236dae4SAndroid Build Coastguard Worker  * The current request needs to be done again - maybe due to a follow
401*6236dae4SAndroid Build Coastguard Worker  * or authentication negotiation. Check if:
402*6236dae4SAndroid Build Coastguard Worker  * 1) a rewind of the data sent to the server is necessary
403*6236dae4SAndroid Build Coastguard Worker  * 2) the current transfer should continue or be stopped early
404*6236dae4SAndroid Build Coastguard Worker  */
http_perhapsrewind(struct Curl_easy * data,struct connectdata * conn)405*6236dae4SAndroid Build Coastguard Worker static CURLcode http_perhapsrewind(struct Curl_easy *data,
406*6236dae4SAndroid Build Coastguard Worker                                    struct connectdata *conn)
407*6236dae4SAndroid Build Coastguard Worker {
408*6236dae4SAndroid Build Coastguard Worker   curl_off_t bytessent = data->req.writebytecount;
409*6236dae4SAndroid Build Coastguard Worker   curl_off_t expectsend = Curl_creader_total_length(data);
410*6236dae4SAndroid Build Coastguard Worker   curl_off_t upload_remain = (expectsend >= 0) ? (expectsend - bytessent) : -1;
411*6236dae4SAndroid Build Coastguard Worker   bool little_upload_remains = (upload_remain >= 0 && upload_remain < 2000);
412*6236dae4SAndroid Build Coastguard Worker   bool needs_rewind = Curl_creader_needs_rewind(data);
413*6236dae4SAndroid Build Coastguard Worker   /* By default, we would like to abort the transfer when little or unknown
414*6236dae4SAndroid Build Coastguard Worker    * amount remains. This may be overridden by authentications further
415*6236dae4SAndroid Build Coastguard Worker    * below! */
416*6236dae4SAndroid Build Coastguard Worker   bool abort_upload = (!data->req.upload_done && !little_upload_remains);
417*6236dae4SAndroid Build Coastguard Worker   const char *ongoing_auth = NULL;
418*6236dae4SAndroid Build Coastguard Worker 
419*6236dae4SAndroid Build Coastguard Worker   /* We need a rewind before uploading client read data again. The
420*6236dae4SAndroid Build Coastguard Worker    * checks below just influence of the upload is to be continued
421*6236dae4SAndroid Build Coastguard Worker    * or aborted early.
422*6236dae4SAndroid Build Coastguard Worker    * This depends on how much remains to be sent and in what state
423*6236dae4SAndroid Build Coastguard Worker    * the authentication is. Some auth schemes such as NTLM do not work
424*6236dae4SAndroid Build Coastguard Worker    * for a new connection. */
425*6236dae4SAndroid Build Coastguard Worker   if(needs_rewind) {
426*6236dae4SAndroid Build Coastguard Worker     infof(data, "Need to rewind upload for next request");
427*6236dae4SAndroid Build Coastguard Worker     Curl_creader_set_rewind(data, TRUE);
428*6236dae4SAndroid Build Coastguard Worker   }
429*6236dae4SAndroid Build Coastguard Worker 
430*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.close)
431*6236dae4SAndroid Build Coastguard Worker     /* If we already decided to close this connection, we cannot veto. */
432*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
433*6236dae4SAndroid Build Coastguard Worker 
434*6236dae4SAndroid Build Coastguard Worker   if(abort_upload) {
435*6236dae4SAndroid Build Coastguard Worker     /* We'd like to abort the upload - but should we? */
436*6236dae4SAndroid Build Coastguard Worker #if defined(USE_NTLM)
437*6236dae4SAndroid Build Coastguard Worker     if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
438*6236dae4SAndroid Build Coastguard Worker        (data->state.authhost.picked == CURLAUTH_NTLM)) {
439*6236dae4SAndroid Build Coastguard Worker       ongoing_auth = "NTML";
440*6236dae4SAndroid Build Coastguard Worker       if((conn->http_ntlm_state != NTLMSTATE_NONE) ||
441*6236dae4SAndroid Build Coastguard Worker          (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
442*6236dae4SAndroid Build Coastguard Worker         /* The NTLM-negotiation has started, keep on sending.
443*6236dae4SAndroid Build Coastguard Worker          * Need to do further work on same connection */
444*6236dae4SAndroid Build Coastguard Worker         abort_upload = FALSE;
445*6236dae4SAndroid Build Coastguard Worker       }
446*6236dae4SAndroid Build Coastguard Worker     }
447*6236dae4SAndroid Build Coastguard Worker #endif
448*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SPNEGO)
449*6236dae4SAndroid Build Coastguard Worker     /* There is still data left to send */
450*6236dae4SAndroid Build Coastguard Worker     if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
451*6236dae4SAndroid Build Coastguard Worker        (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
452*6236dae4SAndroid Build Coastguard Worker       ongoing_auth = "NEGOTIATE";
453*6236dae4SAndroid Build Coastguard Worker       if((conn->http_negotiate_state != GSS_AUTHNONE) ||
454*6236dae4SAndroid Build Coastguard Worker          (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
455*6236dae4SAndroid Build Coastguard Worker         /* The NEGOTIATE-negotiation has started, keep on sending.
456*6236dae4SAndroid Build Coastguard Worker          * Need to do further work on same connection */
457*6236dae4SAndroid Build Coastguard Worker         abort_upload = FALSE;
458*6236dae4SAndroid Build Coastguard Worker       }
459*6236dae4SAndroid Build Coastguard Worker     }
460*6236dae4SAndroid Build Coastguard Worker #endif
461*6236dae4SAndroid Build Coastguard Worker   }
462*6236dae4SAndroid Build Coastguard Worker 
463*6236dae4SAndroid Build Coastguard Worker   if(abort_upload) {
464*6236dae4SAndroid Build Coastguard Worker     if(upload_remain >= 0)
465*6236dae4SAndroid Build Coastguard Worker       infof(data, "%s%sclose instead of sending %" FMT_OFF_T " more bytes",
466*6236dae4SAndroid Build Coastguard Worker             ongoing_auth ? ongoing_auth : "",
467*6236dae4SAndroid Build Coastguard Worker             ongoing_auth ? " send, " : "",
468*6236dae4SAndroid Build Coastguard Worker             upload_remain);
469*6236dae4SAndroid Build Coastguard Worker     else
470*6236dae4SAndroid Build Coastguard Worker       infof(data, "%s%sclose instead of sending unknown amount "
471*6236dae4SAndroid Build Coastguard Worker             "of more bytes",
472*6236dae4SAndroid Build Coastguard Worker             ongoing_auth ? ongoing_auth : "",
473*6236dae4SAndroid Build Coastguard Worker             ongoing_auth ? " send, " : "");
474*6236dae4SAndroid Build Coastguard Worker     /* We decided to abort the ongoing transfer */
475*6236dae4SAndroid Build Coastguard Worker     streamclose(conn, "Mid-auth HTTP and much data left to send");
476*6236dae4SAndroid Build Coastguard Worker     /* FIXME: questionable manipulation here, can we do this differently? */
477*6236dae4SAndroid Build Coastguard Worker     data->req.size = 0; /* do not download any more than 0 bytes */
478*6236dae4SAndroid Build Coastguard Worker   }
479*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
480*6236dae4SAndroid Build Coastguard Worker }
481*6236dae4SAndroid Build Coastguard Worker 
482*6236dae4SAndroid Build Coastguard Worker /*
483*6236dae4SAndroid Build Coastguard Worker  * Curl_http_auth_act() gets called when all HTTP headers have been received
484*6236dae4SAndroid Build Coastguard Worker  * and it checks what authentication methods that are available and decides
485*6236dae4SAndroid Build Coastguard Worker  * which one (if any) to use. It will set 'newurl' if an auth method was
486*6236dae4SAndroid Build Coastguard Worker  * picked.
487*6236dae4SAndroid Build Coastguard Worker  */
488*6236dae4SAndroid Build Coastguard Worker 
Curl_http_auth_act(struct Curl_easy * data)489*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_auth_act(struct Curl_easy *data)
490*6236dae4SAndroid Build Coastguard Worker {
491*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
492*6236dae4SAndroid Build Coastguard Worker   bool pickhost = FALSE;
493*6236dae4SAndroid Build Coastguard Worker   bool pickproxy = FALSE;
494*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
495*6236dae4SAndroid Build Coastguard Worker   unsigned long authmask = ~0ul;
496*6236dae4SAndroid Build Coastguard Worker 
497*6236dae4SAndroid Build Coastguard Worker   if(!data->set.str[STRING_BEARER])
498*6236dae4SAndroid Build Coastguard Worker     authmask &= (unsigned long)~CURLAUTH_BEARER;
499*6236dae4SAndroid Build Coastguard Worker 
500*6236dae4SAndroid Build Coastguard Worker   if(100 <= data->req.httpcode && data->req.httpcode <= 199)
501*6236dae4SAndroid Build Coastguard Worker     /* this is a transient response code, ignore */
502*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
503*6236dae4SAndroid Build Coastguard Worker 
504*6236dae4SAndroid Build Coastguard Worker   if(data->state.authproblem)
505*6236dae4SAndroid Build Coastguard Worker     return data->set.http_fail_on_error ? CURLE_HTTP_RETURNED_ERROR : CURLE_OK;
506*6236dae4SAndroid Build Coastguard Worker 
507*6236dae4SAndroid Build Coastguard Worker   if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
508*6236dae4SAndroid Build Coastguard Worker      ((data->req.httpcode == 401) ||
509*6236dae4SAndroid Build Coastguard Worker       (data->req.authneg && data->req.httpcode < 300))) {
510*6236dae4SAndroid Build Coastguard Worker     pickhost = pickoneauth(&data->state.authhost, authmask);
511*6236dae4SAndroid Build Coastguard Worker     if(!pickhost)
512*6236dae4SAndroid Build Coastguard Worker       data->state.authproblem = TRUE;
513*6236dae4SAndroid Build Coastguard Worker     if(data->state.authhost.picked == CURLAUTH_NTLM &&
514*6236dae4SAndroid Build Coastguard Worker        conn->httpversion > 11) {
515*6236dae4SAndroid Build Coastguard Worker       infof(data, "Forcing HTTP/1.1 for NTLM");
516*6236dae4SAndroid Build Coastguard Worker       connclose(conn, "Force HTTP/1.1 connection");
517*6236dae4SAndroid Build Coastguard Worker       data->state.httpwant = CURL_HTTP_VERSION_1_1;
518*6236dae4SAndroid Build Coastguard Worker     }
519*6236dae4SAndroid Build Coastguard Worker   }
520*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
521*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.proxy_user_passwd &&
522*6236dae4SAndroid Build Coastguard Worker      ((data->req.httpcode == 407) ||
523*6236dae4SAndroid Build Coastguard Worker       (data->req.authneg && data->req.httpcode < 300))) {
524*6236dae4SAndroid Build Coastguard Worker     pickproxy = pickoneauth(&data->state.authproxy,
525*6236dae4SAndroid Build Coastguard Worker                             authmask & ~CURLAUTH_BEARER);
526*6236dae4SAndroid Build Coastguard Worker     if(!pickproxy)
527*6236dae4SAndroid Build Coastguard Worker       data->state.authproblem = TRUE;
528*6236dae4SAndroid Build Coastguard Worker   }
529*6236dae4SAndroid Build Coastguard Worker #endif
530*6236dae4SAndroid Build Coastguard Worker 
531*6236dae4SAndroid Build Coastguard Worker   if(pickhost || pickproxy) {
532*6236dae4SAndroid Build Coastguard Worker     result = http_perhapsrewind(data, conn);
533*6236dae4SAndroid Build Coastguard Worker     if(result)
534*6236dae4SAndroid Build Coastguard Worker       return result;
535*6236dae4SAndroid Build Coastguard Worker 
536*6236dae4SAndroid Build Coastguard Worker     /* In case this is GSS auth, the newurl field is already allocated so
537*6236dae4SAndroid Build Coastguard Worker        we must make sure to free it before allocating a new one. As figured
538*6236dae4SAndroid Build Coastguard Worker        out in bug #2284386 */
539*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->req.newurl);
540*6236dae4SAndroid Build Coastguard Worker     data->req.newurl = strdup(data->state.url); /* clone URL */
541*6236dae4SAndroid Build Coastguard Worker     if(!data->req.newurl)
542*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
543*6236dae4SAndroid Build Coastguard Worker   }
544*6236dae4SAndroid Build Coastguard Worker   else if((data->req.httpcode < 300) &&
545*6236dae4SAndroid Build Coastguard Worker           (!data->state.authhost.done) &&
546*6236dae4SAndroid Build Coastguard Worker           data->req.authneg) {
547*6236dae4SAndroid Build Coastguard Worker     /* no (known) authentication available,
548*6236dae4SAndroid Build Coastguard Worker        authentication is not "done" yet and
549*6236dae4SAndroid Build Coastguard Worker        no authentication seems to be required and
550*6236dae4SAndroid Build Coastguard Worker        we did not try HEAD or GET */
551*6236dae4SAndroid Build Coastguard Worker     if((data->state.httpreq != HTTPREQ_GET) &&
552*6236dae4SAndroid Build Coastguard Worker        (data->state.httpreq != HTTPREQ_HEAD)) {
553*6236dae4SAndroid Build Coastguard Worker       data->req.newurl = strdup(data->state.url); /* clone URL */
554*6236dae4SAndroid Build Coastguard Worker       if(!data->req.newurl)
555*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
556*6236dae4SAndroid Build Coastguard Worker       data->state.authhost.done = TRUE;
557*6236dae4SAndroid Build Coastguard Worker     }
558*6236dae4SAndroid Build Coastguard Worker   }
559*6236dae4SAndroid Build Coastguard Worker   if(http_should_fail(data, data->req.httpcode)) {
560*6236dae4SAndroid Build Coastguard Worker     failf(data, "The requested URL returned error: %d",
561*6236dae4SAndroid Build Coastguard Worker           data->req.httpcode);
562*6236dae4SAndroid Build Coastguard Worker     result = CURLE_HTTP_RETURNED_ERROR;
563*6236dae4SAndroid Build Coastguard Worker   }
564*6236dae4SAndroid Build Coastguard Worker 
565*6236dae4SAndroid Build Coastguard Worker   return result;
566*6236dae4SAndroid Build Coastguard Worker }
567*6236dae4SAndroid Build Coastguard Worker 
568*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HTTP_AUTH
569*6236dae4SAndroid Build Coastguard Worker /*
570*6236dae4SAndroid Build Coastguard Worker  * Output the correct authentication header depending on the auth type
571*6236dae4SAndroid Build Coastguard Worker  * and whether or not it is to a proxy.
572*6236dae4SAndroid Build Coastguard Worker  */
573*6236dae4SAndroid Build Coastguard Worker static CURLcode
output_auth_headers(struct Curl_easy * data,struct connectdata * conn,struct auth * authstatus,const char * request,const char * path,bool proxy)574*6236dae4SAndroid Build Coastguard Worker output_auth_headers(struct Curl_easy *data,
575*6236dae4SAndroid Build Coastguard Worker                     struct connectdata *conn,
576*6236dae4SAndroid Build Coastguard Worker                     struct auth *authstatus,
577*6236dae4SAndroid Build Coastguard Worker                     const char *request,
578*6236dae4SAndroid Build Coastguard Worker                     const char *path,
579*6236dae4SAndroid Build Coastguard Worker                     bool proxy)
580*6236dae4SAndroid Build Coastguard Worker {
581*6236dae4SAndroid Build Coastguard Worker   const char *auth = NULL;
582*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
583*6236dae4SAndroid Build Coastguard Worker   (void)conn;
584*6236dae4SAndroid Build Coastguard Worker 
585*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_DIGEST_AUTH
586*6236dae4SAndroid Build Coastguard Worker   (void)request;
587*6236dae4SAndroid Build Coastguard Worker   (void)path;
588*6236dae4SAndroid Build Coastguard Worker #endif
589*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_AWS
590*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
591*6236dae4SAndroid Build Coastguard Worker     auth = "AWS_SIGV4";
592*6236dae4SAndroid Build Coastguard Worker     result = Curl_output_aws_sigv4(data, proxy);
593*6236dae4SAndroid Build Coastguard Worker     if(result)
594*6236dae4SAndroid Build Coastguard Worker       return result;
595*6236dae4SAndroid Build Coastguard Worker   }
596*6236dae4SAndroid Build Coastguard Worker   else
597*6236dae4SAndroid Build Coastguard Worker #endif
598*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SPNEGO
599*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_NEGOTIATE) {
600*6236dae4SAndroid Build Coastguard Worker     auth = "Negotiate";
601*6236dae4SAndroid Build Coastguard Worker     result = Curl_output_negotiate(data, conn, proxy);
602*6236dae4SAndroid Build Coastguard Worker     if(result)
603*6236dae4SAndroid Build Coastguard Worker       return result;
604*6236dae4SAndroid Build Coastguard Worker   }
605*6236dae4SAndroid Build Coastguard Worker   else
606*6236dae4SAndroid Build Coastguard Worker #endif
607*6236dae4SAndroid Build Coastguard Worker #ifdef USE_NTLM
608*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_NTLM) {
609*6236dae4SAndroid Build Coastguard Worker     auth = "NTLM";
610*6236dae4SAndroid Build Coastguard Worker     result = Curl_output_ntlm(data, proxy);
611*6236dae4SAndroid Build Coastguard Worker     if(result)
612*6236dae4SAndroid Build Coastguard Worker       return result;
613*6236dae4SAndroid Build Coastguard Worker   }
614*6236dae4SAndroid Build Coastguard Worker   else
615*6236dae4SAndroid Build Coastguard Worker #endif
616*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DIGEST_AUTH
617*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_DIGEST) {
618*6236dae4SAndroid Build Coastguard Worker     auth = "Digest";
619*6236dae4SAndroid Build Coastguard Worker     result = Curl_output_digest(data,
620*6236dae4SAndroid Build Coastguard Worker                                 proxy,
621*6236dae4SAndroid Build Coastguard Worker                                 (const unsigned char *)request,
622*6236dae4SAndroid Build Coastguard Worker                                 (const unsigned char *)path);
623*6236dae4SAndroid Build Coastguard Worker     if(result)
624*6236dae4SAndroid Build Coastguard Worker       return result;
625*6236dae4SAndroid Build Coastguard Worker   }
626*6236dae4SAndroid Build Coastguard Worker   else
627*6236dae4SAndroid Build Coastguard Worker #endif
628*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BASIC_AUTH
629*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_BASIC) {
630*6236dae4SAndroid Build Coastguard Worker     /* Basic */
631*6236dae4SAndroid Build Coastguard Worker     if(
632*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
633*6236dae4SAndroid Build Coastguard Worker       (proxy && conn->bits.proxy_user_passwd &&
634*6236dae4SAndroid Build Coastguard Worker        !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
635*6236dae4SAndroid Build Coastguard Worker #endif
636*6236dae4SAndroid Build Coastguard Worker       (!proxy && data->state.aptr.user &&
637*6236dae4SAndroid Build Coastguard Worker        !Curl_checkheaders(data, STRCONST("Authorization")))) {
638*6236dae4SAndroid Build Coastguard Worker       auth = "Basic";
639*6236dae4SAndroid Build Coastguard Worker       result = http_output_basic(data, proxy);
640*6236dae4SAndroid Build Coastguard Worker       if(result)
641*6236dae4SAndroid Build Coastguard Worker         return result;
642*6236dae4SAndroid Build Coastguard Worker     }
643*6236dae4SAndroid Build Coastguard Worker 
644*6236dae4SAndroid Build Coastguard Worker     /* NOTE: this function should set 'done' TRUE, as the other auth
645*6236dae4SAndroid Build Coastguard Worker        functions work that way */
646*6236dae4SAndroid Build Coastguard Worker     authstatus->done = TRUE;
647*6236dae4SAndroid Build Coastguard Worker   }
648*6236dae4SAndroid Build Coastguard Worker #endif
649*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BEARER_AUTH
650*6236dae4SAndroid Build Coastguard Worker   if(authstatus->picked == CURLAUTH_BEARER) {
651*6236dae4SAndroid Build Coastguard Worker     /* Bearer */
652*6236dae4SAndroid Build Coastguard Worker     if((!proxy && data->set.str[STRING_BEARER] &&
653*6236dae4SAndroid Build Coastguard Worker         !Curl_checkheaders(data, STRCONST("Authorization")))) {
654*6236dae4SAndroid Build Coastguard Worker       auth = "Bearer";
655*6236dae4SAndroid Build Coastguard Worker       result = http_output_bearer(data);
656*6236dae4SAndroid Build Coastguard Worker       if(result)
657*6236dae4SAndroid Build Coastguard Worker         return result;
658*6236dae4SAndroid Build Coastguard Worker     }
659*6236dae4SAndroid Build Coastguard Worker 
660*6236dae4SAndroid Build Coastguard Worker     /* NOTE: this function should set 'done' TRUE, as the other auth
661*6236dae4SAndroid Build Coastguard Worker        functions work that way */
662*6236dae4SAndroid Build Coastguard Worker     authstatus->done = TRUE;
663*6236dae4SAndroid Build Coastguard Worker   }
664*6236dae4SAndroid Build Coastguard Worker #endif
665*6236dae4SAndroid Build Coastguard Worker 
666*6236dae4SAndroid Build Coastguard Worker   if(auth) {
667*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
668*6236dae4SAndroid Build Coastguard Worker     infof(data, "%s auth using %s with user '%s'",
669*6236dae4SAndroid Build Coastguard Worker           proxy ? "Proxy" : "Server", auth,
670*6236dae4SAndroid Build Coastguard Worker           proxy ? (data->state.aptr.proxyuser ?
671*6236dae4SAndroid Build Coastguard Worker                    data->state.aptr.proxyuser : "") :
672*6236dae4SAndroid Build Coastguard Worker           (data->state.aptr.user ?
673*6236dae4SAndroid Build Coastguard Worker            data->state.aptr.user : ""));
674*6236dae4SAndroid Build Coastguard Worker #else
675*6236dae4SAndroid Build Coastguard Worker     (void)proxy;
676*6236dae4SAndroid Build Coastguard Worker     infof(data, "Server auth using %s with user '%s'",
677*6236dae4SAndroid Build Coastguard Worker           auth, data->state.aptr.user ?
678*6236dae4SAndroid Build Coastguard Worker           data->state.aptr.user : "");
679*6236dae4SAndroid Build Coastguard Worker #endif
680*6236dae4SAndroid Build Coastguard Worker     authstatus->multipass = !authstatus->done;
681*6236dae4SAndroid Build Coastguard Worker   }
682*6236dae4SAndroid Build Coastguard Worker   else
683*6236dae4SAndroid Build Coastguard Worker     authstatus->multipass = FALSE;
684*6236dae4SAndroid Build Coastguard Worker 
685*6236dae4SAndroid Build Coastguard Worker   return result;
686*6236dae4SAndroid Build Coastguard Worker }
687*6236dae4SAndroid Build Coastguard Worker 
688*6236dae4SAndroid Build Coastguard Worker /**
689*6236dae4SAndroid Build Coastguard Worker  * Curl_http_output_auth() setups the authentication headers for the
690*6236dae4SAndroid Build Coastguard Worker  * host/proxy and the correct authentication
691*6236dae4SAndroid Build Coastguard Worker  * method. data->state.authdone is set to TRUE when authentication is
692*6236dae4SAndroid Build Coastguard Worker  * done.
693*6236dae4SAndroid Build Coastguard Worker  *
694*6236dae4SAndroid Build Coastguard Worker  * @param conn all information about the current connection
695*6236dae4SAndroid Build Coastguard Worker  * @param request pointer to the request keyword
696*6236dae4SAndroid Build Coastguard Worker  * @param path pointer to the requested path; should include query part
697*6236dae4SAndroid Build Coastguard Worker  * @param proxytunnel boolean if this is the request setting up a "proxy
698*6236dae4SAndroid Build Coastguard Worker  * tunnel"
699*6236dae4SAndroid Build Coastguard Worker  *
700*6236dae4SAndroid Build Coastguard Worker  * @returns CURLcode
701*6236dae4SAndroid Build Coastguard Worker  */
702*6236dae4SAndroid Build Coastguard Worker CURLcode
Curl_http_output_auth(struct Curl_easy * data,struct connectdata * conn,const char * request,Curl_HttpReq httpreq,const char * path,bool proxytunnel)703*6236dae4SAndroid Build Coastguard Worker Curl_http_output_auth(struct Curl_easy *data,
704*6236dae4SAndroid Build Coastguard Worker                       struct connectdata *conn,
705*6236dae4SAndroid Build Coastguard Worker                       const char *request,
706*6236dae4SAndroid Build Coastguard Worker                       Curl_HttpReq httpreq,
707*6236dae4SAndroid Build Coastguard Worker                       const char *path,
708*6236dae4SAndroid Build Coastguard Worker                       bool proxytunnel) /* TRUE if this is the request setting
709*6236dae4SAndroid Build Coastguard Worker                                            up the proxy tunnel */
710*6236dae4SAndroid Build Coastguard Worker {
711*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
712*6236dae4SAndroid Build Coastguard Worker   struct auth *authhost;
713*6236dae4SAndroid Build Coastguard Worker   struct auth *authproxy;
714*6236dae4SAndroid Build Coastguard Worker 
715*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
716*6236dae4SAndroid Build Coastguard Worker 
717*6236dae4SAndroid Build Coastguard Worker   authhost = &data->state.authhost;
718*6236dae4SAndroid Build Coastguard Worker   authproxy = &data->state.authproxy;
719*6236dae4SAndroid Build Coastguard Worker 
720*6236dae4SAndroid Build Coastguard Worker   if(
721*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
722*6236dae4SAndroid Build Coastguard Worker     (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
723*6236dae4SAndroid Build Coastguard Worker #endif
724*6236dae4SAndroid Build Coastguard Worker      data->state.aptr.user ||
725*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SPNEGO
726*6236dae4SAndroid Build Coastguard Worker      authhost->want & CURLAUTH_NEGOTIATE ||
727*6236dae4SAndroid Build Coastguard Worker      authproxy->want & CURLAUTH_NEGOTIATE ||
728*6236dae4SAndroid Build Coastguard Worker #endif
729*6236dae4SAndroid Build Coastguard Worker      data->set.str[STRING_BEARER])
730*6236dae4SAndroid Build Coastguard Worker     /* continue please */;
731*6236dae4SAndroid Build Coastguard Worker   else {
732*6236dae4SAndroid Build Coastguard Worker     authhost->done = TRUE;
733*6236dae4SAndroid Build Coastguard Worker     authproxy->done = TRUE;
734*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK; /* no authentication with no user or password */
735*6236dae4SAndroid Build Coastguard Worker   }
736*6236dae4SAndroid Build Coastguard Worker 
737*6236dae4SAndroid Build Coastguard Worker   if(authhost->want && !authhost->picked)
738*6236dae4SAndroid Build Coastguard Worker     /* The app has selected one or more methods, but none has been picked
739*6236dae4SAndroid Build Coastguard Worker        so far by a server round-trip. Then we set the picked one to the
740*6236dae4SAndroid Build Coastguard Worker        want one, and if this is one single bit it will be used instantly. */
741*6236dae4SAndroid Build Coastguard Worker     authhost->picked = authhost->want;
742*6236dae4SAndroid Build Coastguard Worker 
743*6236dae4SAndroid Build Coastguard Worker   if(authproxy->want && !authproxy->picked)
744*6236dae4SAndroid Build Coastguard Worker     /* The app has selected one or more methods, but none has been picked so
745*6236dae4SAndroid Build Coastguard Worker        far by a proxy round-trip. Then we set the picked one to the want one,
746*6236dae4SAndroid Build Coastguard Worker        and if this is one single bit it will be used instantly. */
747*6236dae4SAndroid Build Coastguard Worker     authproxy->picked = authproxy->want;
748*6236dae4SAndroid Build Coastguard Worker 
749*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
750*6236dae4SAndroid Build Coastguard Worker   /* Send proxy authentication header if needed */
751*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.httpproxy &&
752*6236dae4SAndroid Build Coastguard Worker      (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
753*6236dae4SAndroid Build Coastguard Worker     result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
754*6236dae4SAndroid Build Coastguard Worker     if(result)
755*6236dae4SAndroid Build Coastguard Worker       return result;
756*6236dae4SAndroid Build Coastguard Worker   }
757*6236dae4SAndroid Build Coastguard Worker   else
758*6236dae4SAndroid Build Coastguard Worker #else
759*6236dae4SAndroid Build Coastguard Worker   (void)proxytunnel;
760*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_PROXY */
761*6236dae4SAndroid Build Coastguard Worker     /* we have no proxy so let's pretend we are done authenticating
762*6236dae4SAndroid Build Coastguard Worker        with it */
763*6236dae4SAndroid Build Coastguard Worker     authproxy->done = TRUE;
764*6236dae4SAndroid Build Coastguard Worker 
765*6236dae4SAndroid Build Coastguard Worker   /* To prevent the user+password to get sent to other than the original host
766*6236dae4SAndroid Build Coastguard Worker      due to a location-follow */
767*6236dae4SAndroid Build Coastguard Worker   if(Curl_auth_allowed_to_host(data)
768*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_NETRC
769*6236dae4SAndroid Build Coastguard Worker      || conn->bits.netrc
770*6236dae4SAndroid Build Coastguard Worker #endif
771*6236dae4SAndroid Build Coastguard Worker     )
772*6236dae4SAndroid Build Coastguard Worker     result = output_auth_headers(data, conn, authhost, request, path, FALSE);
773*6236dae4SAndroid Build Coastguard Worker   else
774*6236dae4SAndroid Build Coastguard Worker     authhost->done = TRUE;
775*6236dae4SAndroid Build Coastguard Worker 
776*6236dae4SAndroid Build Coastguard Worker   if(((authhost->multipass && !authhost->done) ||
777*6236dae4SAndroid Build Coastguard Worker       (authproxy->multipass && !authproxy->done)) &&
778*6236dae4SAndroid Build Coastguard Worker      (httpreq != HTTPREQ_GET) &&
779*6236dae4SAndroid Build Coastguard Worker      (httpreq != HTTPREQ_HEAD)) {
780*6236dae4SAndroid Build Coastguard Worker     /* Auth is required and we are not authenticated yet. Make a PUT or POST
781*6236dae4SAndroid Build Coastguard Worker        with content-length zero as a "probe". */
782*6236dae4SAndroid Build Coastguard Worker     data->req.authneg = TRUE;
783*6236dae4SAndroid Build Coastguard Worker   }
784*6236dae4SAndroid Build Coastguard Worker   else
785*6236dae4SAndroid Build Coastguard Worker     data->req.authneg = FALSE;
786*6236dae4SAndroid Build Coastguard Worker 
787*6236dae4SAndroid Build Coastguard Worker   return result;
788*6236dae4SAndroid Build Coastguard Worker }
789*6236dae4SAndroid Build Coastguard Worker 
790*6236dae4SAndroid Build Coastguard Worker #else
791*6236dae4SAndroid Build Coastguard Worker /* when disabled */
792*6236dae4SAndroid Build Coastguard Worker CURLcode
Curl_http_output_auth(struct Curl_easy * data,struct connectdata * conn,const char * request,Curl_HttpReq httpreq,const char * path,bool proxytunnel)793*6236dae4SAndroid Build Coastguard Worker Curl_http_output_auth(struct Curl_easy *data,
794*6236dae4SAndroid Build Coastguard Worker                       struct connectdata *conn,
795*6236dae4SAndroid Build Coastguard Worker                       const char *request,
796*6236dae4SAndroid Build Coastguard Worker                       Curl_HttpReq httpreq,
797*6236dae4SAndroid Build Coastguard Worker                       const char *path,
798*6236dae4SAndroid Build Coastguard Worker                       bool proxytunnel)
799*6236dae4SAndroid Build Coastguard Worker {
800*6236dae4SAndroid Build Coastguard Worker   (void)data;
801*6236dae4SAndroid Build Coastguard Worker   (void)conn;
802*6236dae4SAndroid Build Coastguard Worker   (void)request;
803*6236dae4SAndroid Build Coastguard Worker   (void)httpreq;
804*6236dae4SAndroid Build Coastguard Worker   (void)path;
805*6236dae4SAndroid Build Coastguard Worker   (void)proxytunnel;
806*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
807*6236dae4SAndroid Build Coastguard Worker }
808*6236dae4SAndroid Build Coastguard Worker #endif
809*6236dae4SAndroid Build Coastguard Worker 
810*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SPNEGO) || defined(USE_NTLM) || \
811*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_DIGEST_AUTH) || \
812*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_BASIC_AUTH) || \
813*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_BEARER_AUTH)
is_valid_auth_separator(char ch)814*6236dae4SAndroid Build Coastguard Worker static int is_valid_auth_separator(char ch)
815*6236dae4SAndroid Build Coastguard Worker {
816*6236dae4SAndroid Build Coastguard Worker   return ch == '\0' || ch == ',' || ISSPACE(ch);
817*6236dae4SAndroid Build Coastguard Worker }
818*6236dae4SAndroid Build Coastguard Worker #endif
819*6236dae4SAndroid Build Coastguard Worker 
820*6236dae4SAndroid Build Coastguard Worker /*
821*6236dae4SAndroid Build Coastguard Worker  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
822*6236dae4SAndroid Build Coastguard Worker  * headers. They are dealt with both in the transfer.c main loop and in the
823*6236dae4SAndroid Build Coastguard Worker  * proxy CONNECT loop.
824*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_input_auth(struct Curl_easy * data,bool proxy,const char * auth)825*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
826*6236dae4SAndroid Build Coastguard Worker                               const char *auth) /* the first non-space */
827*6236dae4SAndroid Build Coastguard Worker {
828*6236dae4SAndroid Build Coastguard Worker   /*
829*6236dae4SAndroid Build Coastguard Worker    * This resource requires authentication
830*6236dae4SAndroid Build Coastguard Worker    */
831*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
832*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SPNEGO
833*6236dae4SAndroid Build Coastguard Worker   curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
834*6236dae4SAndroid Build Coastguard Worker                                     &conn->http_negotiate_state;
835*6236dae4SAndroid Build Coastguard Worker #endif
836*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SPNEGO) || \
837*6236dae4SAndroid Build Coastguard Worker   defined(USE_NTLM) || \
838*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_DIGEST_AUTH) || \
839*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_BASIC_AUTH) || \
840*6236dae4SAndroid Build Coastguard Worker   !defined(CURL_DISABLE_BEARER_AUTH)
841*6236dae4SAndroid Build Coastguard Worker 
842*6236dae4SAndroid Build Coastguard Worker   unsigned long *availp;
843*6236dae4SAndroid Build Coastguard Worker   struct auth *authp;
844*6236dae4SAndroid Build Coastguard Worker 
845*6236dae4SAndroid Build Coastguard Worker   if(proxy) {
846*6236dae4SAndroid Build Coastguard Worker     availp = &data->info.proxyauthavail;
847*6236dae4SAndroid Build Coastguard Worker     authp = &data->state.authproxy;
848*6236dae4SAndroid Build Coastguard Worker   }
849*6236dae4SAndroid Build Coastguard Worker   else {
850*6236dae4SAndroid Build Coastguard Worker     availp = &data->info.httpauthavail;
851*6236dae4SAndroid Build Coastguard Worker     authp = &data->state.authhost;
852*6236dae4SAndroid Build Coastguard Worker   }
853*6236dae4SAndroid Build Coastguard Worker #else
854*6236dae4SAndroid Build Coastguard Worker   (void) proxy;
855*6236dae4SAndroid Build Coastguard Worker #endif
856*6236dae4SAndroid Build Coastguard Worker 
857*6236dae4SAndroid Build Coastguard Worker   (void) conn; /* In case conditionals make it unused. */
858*6236dae4SAndroid Build Coastguard Worker 
859*6236dae4SAndroid Build Coastguard Worker   /*
860*6236dae4SAndroid Build Coastguard Worker    * Here we check if we want the specific single authentication (using ==) and
861*6236dae4SAndroid Build Coastguard Worker    * if we do, we initiate usage of it.
862*6236dae4SAndroid Build Coastguard Worker    *
863*6236dae4SAndroid Build Coastguard Worker    * If the provided authentication is wanted as one out of several accepted
864*6236dae4SAndroid Build Coastguard Worker    * types (using &), we OR this authentication type to the authavail
865*6236dae4SAndroid Build Coastguard Worker    * variable.
866*6236dae4SAndroid Build Coastguard Worker    *
867*6236dae4SAndroid Build Coastguard Worker    * Note:
868*6236dae4SAndroid Build Coastguard Worker    *
869*6236dae4SAndroid Build Coastguard Worker    * ->picked is first set to the 'want' value (one or more bits) before the
870*6236dae4SAndroid Build Coastguard Worker    * request is sent, and then it is again set _after_ all response 401/407
871*6236dae4SAndroid Build Coastguard Worker    * headers have been received but then only to a single preferred method
872*6236dae4SAndroid Build Coastguard Worker    * (bit).
873*6236dae4SAndroid Build Coastguard Worker    */
874*6236dae4SAndroid Build Coastguard Worker 
875*6236dae4SAndroid Build Coastguard Worker   while(*auth) {
876*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SPNEGO
877*6236dae4SAndroid Build Coastguard Worker     if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) {
878*6236dae4SAndroid Build Coastguard Worker       if((authp->avail & CURLAUTH_NEGOTIATE) ||
879*6236dae4SAndroid Build Coastguard Worker          Curl_auth_is_spnego_supported()) {
880*6236dae4SAndroid Build Coastguard Worker         *availp |= CURLAUTH_NEGOTIATE;
881*6236dae4SAndroid Build Coastguard Worker         authp->avail |= CURLAUTH_NEGOTIATE;
882*6236dae4SAndroid Build Coastguard Worker 
883*6236dae4SAndroid Build Coastguard Worker         if(authp->picked == CURLAUTH_NEGOTIATE) {
884*6236dae4SAndroid Build Coastguard Worker           CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
885*6236dae4SAndroid Build Coastguard Worker           if(!result) {
886*6236dae4SAndroid Build Coastguard Worker             free(data->req.newurl);
887*6236dae4SAndroid Build Coastguard Worker             data->req.newurl = strdup(data->state.url);
888*6236dae4SAndroid Build Coastguard Worker             if(!data->req.newurl)
889*6236dae4SAndroid Build Coastguard Worker               return CURLE_OUT_OF_MEMORY;
890*6236dae4SAndroid Build Coastguard Worker             data->state.authproblem = FALSE;
891*6236dae4SAndroid Build Coastguard Worker             /* we received a GSS auth token and we dealt with it fine */
892*6236dae4SAndroid Build Coastguard Worker             *negstate = GSS_AUTHRECV;
893*6236dae4SAndroid Build Coastguard Worker           }
894*6236dae4SAndroid Build Coastguard Worker           else
895*6236dae4SAndroid Build Coastguard Worker             data->state.authproblem = TRUE;
896*6236dae4SAndroid Build Coastguard Worker         }
897*6236dae4SAndroid Build Coastguard Worker       }
898*6236dae4SAndroid Build Coastguard Worker     }
899*6236dae4SAndroid Build Coastguard Worker     else
900*6236dae4SAndroid Build Coastguard Worker #endif
901*6236dae4SAndroid Build Coastguard Worker #ifdef USE_NTLM
902*6236dae4SAndroid Build Coastguard Worker       /* NTLM support requires the SSL crypto libs */
903*6236dae4SAndroid Build Coastguard Worker       if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) {
904*6236dae4SAndroid Build Coastguard Worker         if((authp->avail & CURLAUTH_NTLM) ||
905*6236dae4SAndroid Build Coastguard Worker            Curl_auth_is_ntlm_supported()) {
906*6236dae4SAndroid Build Coastguard Worker           *availp |= CURLAUTH_NTLM;
907*6236dae4SAndroid Build Coastguard Worker           authp->avail |= CURLAUTH_NTLM;
908*6236dae4SAndroid Build Coastguard Worker 
909*6236dae4SAndroid Build Coastguard Worker           if(authp->picked == CURLAUTH_NTLM) {
910*6236dae4SAndroid Build Coastguard Worker             /* NTLM authentication is picked and activated */
911*6236dae4SAndroid Build Coastguard Worker             CURLcode result = Curl_input_ntlm(data, proxy, auth);
912*6236dae4SAndroid Build Coastguard Worker             if(!result) {
913*6236dae4SAndroid Build Coastguard Worker               data->state.authproblem = FALSE;
914*6236dae4SAndroid Build Coastguard Worker             }
915*6236dae4SAndroid Build Coastguard Worker             else {
916*6236dae4SAndroid Build Coastguard Worker               infof(data, "Authentication problem. Ignoring this.");
917*6236dae4SAndroid Build Coastguard Worker               data->state.authproblem = TRUE;
918*6236dae4SAndroid Build Coastguard Worker             }
919*6236dae4SAndroid Build Coastguard Worker           }
920*6236dae4SAndroid Build Coastguard Worker         }
921*6236dae4SAndroid Build Coastguard Worker       }
922*6236dae4SAndroid Build Coastguard Worker       else
923*6236dae4SAndroid Build Coastguard Worker #endif
924*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DIGEST_AUTH
925*6236dae4SAndroid Build Coastguard Worker         if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
926*6236dae4SAndroid Build Coastguard Worker           if((authp->avail & CURLAUTH_DIGEST) != 0)
927*6236dae4SAndroid Build Coastguard Worker             infof(data, "Ignoring duplicate digest auth header.");
928*6236dae4SAndroid Build Coastguard Worker           else if(Curl_auth_is_digest_supported()) {
929*6236dae4SAndroid Build Coastguard Worker             CURLcode result;
930*6236dae4SAndroid Build Coastguard Worker 
931*6236dae4SAndroid Build Coastguard Worker             *availp |= CURLAUTH_DIGEST;
932*6236dae4SAndroid Build Coastguard Worker             authp->avail |= CURLAUTH_DIGEST;
933*6236dae4SAndroid Build Coastguard Worker 
934*6236dae4SAndroid Build Coastguard Worker             /* We call this function on input Digest headers even if Digest
935*6236dae4SAndroid Build Coastguard Worker              * authentication is not activated yet, as we need to store the
936*6236dae4SAndroid Build Coastguard Worker              * incoming data from this header in case we are going to use
937*6236dae4SAndroid Build Coastguard Worker              * Digest */
938*6236dae4SAndroid Build Coastguard Worker             result = Curl_input_digest(data, proxy, auth);
939*6236dae4SAndroid Build Coastguard Worker             if(result) {
940*6236dae4SAndroid Build Coastguard Worker               infof(data, "Authentication problem. Ignoring this.");
941*6236dae4SAndroid Build Coastguard Worker               data->state.authproblem = TRUE;
942*6236dae4SAndroid Build Coastguard Worker             }
943*6236dae4SAndroid Build Coastguard Worker           }
944*6236dae4SAndroid Build Coastguard Worker         }
945*6236dae4SAndroid Build Coastguard Worker         else
946*6236dae4SAndroid Build Coastguard Worker #endif
947*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BASIC_AUTH
948*6236dae4SAndroid Build Coastguard Worker           if(checkprefix("Basic", auth) &&
949*6236dae4SAndroid Build Coastguard Worker              is_valid_auth_separator(auth[5])) {
950*6236dae4SAndroid Build Coastguard Worker             *availp |= CURLAUTH_BASIC;
951*6236dae4SAndroid Build Coastguard Worker             authp->avail |= CURLAUTH_BASIC;
952*6236dae4SAndroid Build Coastguard Worker             if(authp->picked == CURLAUTH_BASIC) {
953*6236dae4SAndroid Build Coastguard Worker               /* We asked for Basic authentication but got a 40X back
954*6236dae4SAndroid Build Coastguard Worker                  anyway, which basically means our name+password is not
955*6236dae4SAndroid Build Coastguard Worker                  valid. */
956*6236dae4SAndroid Build Coastguard Worker               authp->avail = CURLAUTH_NONE;
957*6236dae4SAndroid Build Coastguard Worker               infof(data, "Authentication problem. Ignoring this.");
958*6236dae4SAndroid Build Coastguard Worker               data->state.authproblem = TRUE;
959*6236dae4SAndroid Build Coastguard Worker             }
960*6236dae4SAndroid Build Coastguard Worker           }
961*6236dae4SAndroid Build Coastguard Worker           else
962*6236dae4SAndroid Build Coastguard Worker #endif
963*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_BEARER_AUTH
964*6236dae4SAndroid Build Coastguard Worker             if(checkprefix("Bearer", auth) &&
965*6236dae4SAndroid Build Coastguard Worker                is_valid_auth_separator(auth[6])) {
966*6236dae4SAndroid Build Coastguard Worker               *availp |= CURLAUTH_BEARER;
967*6236dae4SAndroid Build Coastguard Worker               authp->avail |= CURLAUTH_BEARER;
968*6236dae4SAndroid Build Coastguard Worker               if(authp->picked == CURLAUTH_BEARER) {
969*6236dae4SAndroid Build Coastguard Worker                 /* We asked for Bearer authentication but got a 40X back
970*6236dae4SAndroid Build Coastguard Worker                   anyway, which basically means our token is not valid. */
971*6236dae4SAndroid Build Coastguard Worker                 authp->avail = CURLAUTH_NONE;
972*6236dae4SAndroid Build Coastguard Worker                 infof(data, "Authentication problem. Ignoring this.");
973*6236dae4SAndroid Build Coastguard Worker                 data->state.authproblem = TRUE;
974*6236dae4SAndroid Build Coastguard Worker               }
975*6236dae4SAndroid Build Coastguard Worker             }
976*6236dae4SAndroid Build Coastguard Worker #else
977*6236dae4SAndroid Build Coastguard Worker             {
978*6236dae4SAndroid Build Coastguard Worker               /*
979*6236dae4SAndroid Build Coastguard Worker                * Empty block to terminate the if-else chain correctly.
980*6236dae4SAndroid Build Coastguard Worker                *
981*6236dae4SAndroid Build Coastguard Worker                * A semicolon would yield the same result here, but can cause a
982*6236dae4SAndroid Build Coastguard Worker                * compiler warning when -Wextra is enabled.
983*6236dae4SAndroid Build Coastguard Worker                */
984*6236dae4SAndroid Build Coastguard Worker             }
985*6236dae4SAndroid Build Coastguard Worker #endif
986*6236dae4SAndroid Build Coastguard Worker 
987*6236dae4SAndroid Build Coastguard Worker     /* there may be multiple methods on one line, so keep reading */
988*6236dae4SAndroid Build Coastguard Worker     while(*auth && *auth != ',') /* read up to the next comma */
989*6236dae4SAndroid Build Coastguard Worker       auth++;
990*6236dae4SAndroid Build Coastguard Worker     if(*auth == ',') /* if we are on a comma, skip it */
991*6236dae4SAndroid Build Coastguard Worker       auth++;
992*6236dae4SAndroid Build Coastguard Worker     while(*auth && ISSPACE(*auth))
993*6236dae4SAndroid Build Coastguard Worker       auth++;
994*6236dae4SAndroid Build Coastguard Worker   }
995*6236dae4SAndroid Build Coastguard Worker 
996*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
997*6236dae4SAndroid Build Coastguard Worker }
998*6236dae4SAndroid Build Coastguard Worker 
999*6236dae4SAndroid Build Coastguard Worker /**
1000*6236dae4SAndroid Build Coastguard Worker  * http_should_fail() determines whether an HTTP response code has gotten us
1001*6236dae4SAndroid Build Coastguard Worker  * into an error state or not.
1002*6236dae4SAndroid Build Coastguard Worker  *
1003*6236dae4SAndroid Build Coastguard Worker  * @retval FALSE communications should continue
1004*6236dae4SAndroid Build Coastguard Worker  *
1005*6236dae4SAndroid Build Coastguard Worker  * @retval TRUE communications should not continue
1006*6236dae4SAndroid Build Coastguard Worker  */
http_should_fail(struct Curl_easy * data,int httpcode)1007*6236dae4SAndroid Build Coastguard Worker static bool http_should_fail(struct Curl_easy *data, int httpcode)
1008*6236dae4SAndroid Build Coastguard Worker {
1009*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
1010*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data->conn);
1011*6236dae4SAndroid Build Coastguard Worker 
1012*6236dae4SAndroid Build Coastguard Worker   /*
1013*6236dae4SAndroid Build Coastguard Worker   ** If we have not been asked to fail on error,
1014*6236dae4SAndroid Build Coastguard Worker   ** do not fail.
1015*6236dae4SAndroid Build Coastguard Worker   */
1016*6236dae4SAndroid Build Coastguard Worker   if(!data->set.http_fail_on_error)
1017*6236dae4SAndroid Build Coastguard Worker     return FALSE;
1018*6236dae4SAndroid Build Coastguard Worker 
1019*6236dae4SAndroid Build Coastguard Worker   /*
1020*6236dae4SAndroid Build Coastguard Worker   ** Any code < 400 is never terminal.
1021*6236dae4SAndroid Build Coastguard Worker   */
1022*6236dae4SAndroid Build Coastguard Worker   if(httpcode < 400)
1023*6236dae4SAndroid Build Coastguard Worker     return FALSE;
1024*6236dae4SAndroid Build Coastguard Worker 
1025*6236dae4SAndroid Build Coastguard Worker   /*
1026*6236dae4SAndroid Build Coastguard Worker   ** A 416 response to a resume request is presumably because the file is
1027*6236dae4SAndroid Build Coastguard Worker   ** already completely downloaded and thus not actually a fail.
1028*6236dae4SAndroid Build Coastguard Worker   */
1029*6236dae4SAndroid Build Coastguard Worker   if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
1030*6236dae4SAndroid Build Coastguard Worker      httpcode == 416)
1031*6236dae4SAndroid Build Coastguard Worker     return FALSE;
1032*6236dae4SAndroid Build Coastguard Worker 
1033*6236dae4SAndroid Build Coastguard Worker   /*
1034*6236dae4SAndroid Build Coastguard Worker   ** Any code >= 400 that is not 401 or 407 is always
1035*6236dae4SAndroid Build Coastguard Worker   ** a terminal error
1036*6236dae4SAndroid Build Coastguard Worker   */
1037*6236dae4SAndroid Build Coastguard Worker   if((httpcode != 401) && (httpcode != 407))
1038*6236dae4SAndroid Build Coastguard Worker     return TRUE;
1039*6236dae4SAndroid Build Coastguard Worker 
1040*6236dae4SAndroid Build Coastguard Worker   /*
1041*6236dae4SAndroid Build Coastguard Worker   ** All we have left to deal with is 401 and 407
1042*6236dae4SAndroid Build Coastguard Worker   */
1043*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT((httpcode == 401) || (httpcode == 407));
1044*6236dae4SAndroid Build Coastguard Worker 
1045*6236dae4SAndroid Build Coastguard Worker   /*
1046*6236dae4SAndroid Build Coastguard Worker   ** Examine the current authentication state to see if this is an error. The
1047*6236dae4SAndroid Build Coastguard Worker   ** idea is for this function to get called after processing all the headers
1048*6236dae4SAndroid Build Coastguard Worker   ** in a response message. So, if we have been to asked to authenticate a
1049*6236dae4SAndroid Build Coastguard Worker   ** particular stage, and we have done it, we are OK. If we are already
1050*6236dae4SAndroid Build Coastguard Worker   ** completely authenticated, it is not OK to get another 401 or 407.
1051*6236dae4SAndroid Build Coastguard Worker   **
1052*6236dae4SAndroid Build Coastguard Worker   ** It is possible for authentication to go stale such that the client needs
1053*6236dae4SAndroid Build Coastguard Worker   ** to reauthenticate. Once that info is available, use it here.
1054*6236dae4SAndroid Build Coastguard Worker   */
1055*6236dae4SAndroid Build Coastguard Worker 
1056*6236dae4SAndroid Build Coastguard Worker   /*
1057*6236dae4SAndroid Build Coastguard Worker   ** Either we are not authenticating, or we are supposed to be authenticating
1058*6236dae4SAndroid Build Coastguard Worker   ** something else. This is an error.
1059*6236dae4SAndroid Build Coastguard Worker   */
1060*6236dae4SAndroid Build Coastguard Worker   if((httpcode == 401) && !data->state.aptr.user)
1061*6236dae4SAndroid Build Coastguard Worker     return TRUE;
1062*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1063*6236dae4SAndroid Build Coastguard Worker   if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
1064*6236dae4SAndroid Build Coastguard Worker     return TRUE;
1065*6236dae4SAndroid Build Coastguard Worker #endif
1066*6236dae4SAndroid Build Coastguard Worker 
1067*6236dae4SAndroid Build Coastguard Worker   return data->state.authproblem;
1068*6236dae4SAndroid Build Coastguard Worker }
1069*6236dae4SAndroid Build Coastguard Worker 
1070*6236dae4SAndroid Build Coastguard Worker /*
1071*6236dae4SAndroid Build Coastguard Worker  * Curl_compareheader()
1072*6236dae4SAndroid Build Coastguard Worker  *
1073*6236dae4SAndroid Build Coastguard Worker  * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1074*6236dae4SAndroid Build Coastguard Worker  * Pass headers WITH the colon.
1075*6236dae4SAndroid Build Coastguard Worker  */
1076*6236dae4SAndroid Build Coastguard Worker bool
Curl_compareheader(const char * headerline,const char * header,const size_t hlen,const char * content,const size_t clen)1077*6236dae4SAndroid Build Coastguard Worker Curl_compareheader(const char *headerline, /* line to check */
1078*6236dae4SAndroid Build Coastguard Worker                    const char *header,  /* header keyword _with_ colon */
1079*6236dae4SAndroid Build Coastguard Worker                    const size_t hlen,   /* len of the keyword in bytes */
1080*6236dae4SAndroid Build Coastguard Worker                    const char *content, /* content string to find */
1081*6236dae4SAndroid Build Coastguard Worker                    const size_t clen)   /* len of the content in bytes */
1082*6236dae4SAndroid Build Coastguard Worker {
1083*6236dae4SAndroid Build Coastguard Worker   /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1084*6236dae4SAndroid Build Coastguard Worker    * by a colon (":") and the field value. Field names are case-insensitive.
1085*6236dae4SAndroid Build Coastguard Worker    * The field value MAY be preceded by any amount of LWS, though a single SP
1086*6236dae4SAndroid Build Coastguard Worker    * is preferred." */
1087*6236dae4SAndroid Build Coastguard Worker 
1088*6236dae4SAndroid Build Coastguard Worker   size_t len;
1089*6236dae4SAndroid Build Coastguard Worker   const char *start;
1090*6236dae4SAndroid Build Coastguard Worker   const char *end;
1091*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(hlen);
1092*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(clen);
1093*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(header);
1094*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(content);
1095*6236dae4SAndroid Build Coastguard Worker 
1096*6236dae4SAndroid Build Coastguard Worker   if(!strncasecompare(headerline, header, hlen))
1097*6236dae4SAndroid Build Coastguard Worker     return FALSE; /* does not start with header */
1098*6236dae4SAndroid Build Coastguard Worker 
1099*6236dae4SAndroid Build Coastguard Worker   /* pass the header */
1100*6236dae4SAndroid Build Coastguard Worker   start = &headerline[hlen];
1101*6236dae4SAndroid Build Coastguard Worker 
1102*6236dae4SAndroid Build Coastguard Worker   /* pass all whitespace */
1103*6236dae4SAndroid Build Coastguard Worker   while(*start && ISSPACE(*start))
1104*6236dae4SAndroid Build Coastguard Worker     start++;
1105*6236dae4SAndroid Build Coastguard Worker 
1106*6236dae4SAndroid Build Coastguard Worker   /* find the end of the header line */
1107*6236dae4SAndroid Build Coastguard Worker   end = strchr(start, '\r'); /* lines end with CRLF */
1108*6236dae4SAndroid Build Coastguard Worker   if(!end) {
1109*6236dae4SAndroid Build Coastguard Worker     /* in case there is a non-standard compliant line here */
1110*6236dae4SAndroid Build Coastguard Worker     end = strchr(start, '\n');
1111*6236dae4SAndroid Build Coastguard Worker 
1112*6236dae4SAndroid Build Coastguard Worker     if(!end)
1113*6236dae4SAndroid Build Coastguard Worker       /* hm, there is no line ending here, use the zero byte! */
1114*6236dae4SAndroid Build Coastguard Worker       end = strchr(start, '\0');
1115*6236dae4SAndroid Build Coastguard Worker   }
1116*6236dae4SAndroid Build Coastguard Worker 
1117*6236dae4SAndroid Build Coastguard Worker   len = end-start; /* length of the content part of the input line */
1118*6236dae4SAndroid Build Coastguard Worker 
1119*6236dae4SAndroid Build Coastguard Worker   /* find the content string in the rest of the line */
1120*6236dae4SAndroid Build Coastguard Worker   for(; len >= clen; len--, start++) {
1121*6236dae4SAndroid Build Coastguard Worker     if(strncasecompare(start, content, clen))
1122*6236dae4SAndroid Build Coastguard Worker       return TRUE; /* match! */
1123*6236dae4SAndroid Build Coastguard Worker   }
1124*6236dae4SAndroid Build Coastguard Worker 
1125*6236dae4SAndroid Build Coastguard Worker   return FALSE; /* no match */
1126*6236dae4SAndroid Build Coastguard Worker }
1127*6236dae4SAndroid Build Coastguard Worker 
1128*6236dae4SAndroid Build Coastguard Worker /*
1129*6236dae4SAndroid Build Coastguard Worker  * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1130*6236dae4SAndroid Build Coastguard Worker  * the generic Curl_connect().
1131*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_connect(struct Curl_easy * data,bool * done)1132*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
1133*6236dae4SAndroid Build Coastguard Worker {
1134*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1135*6236dae4SAndroid Build Coastguard Worker 
1136*6236dae4SAndroid Build Coastguard Worker   /* We default to persistent connections. We set this already in this connect
1137*6236dae4SAndroid Build Coastguard Worker      function to make the reuse checks properly be able to check this bit. */
1138*6236dae4SAndroid Build Coastguard Worker   connkeep(conn, "HTTP default");
1139*6236dae4SAndroid Build Coastguard Worker 
1140*6236dae4SAndroid Build Coastguard Worker   return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
1141*6236dae4SAndroid Build Coastguard Worker }
1142*6236dae4SAndroid Build Coastguard Worker 
1143*6236dae4SAndroid Build Coastguard Worker /* this returns the socket to wait for in the DO and DOING state for the multi
1144*6236dae4SAndroid Build Coastguard Worker    interface and then we are always _sending_ a request and thus we wait for
1145*6236dae4SAndroid Build Coastguard Worker    the single socket to become writable only */
Curl_http_getsock_do(struct Curl_easy * data,struct connectdata * conn,curl_socket_t * socks)1146*6236dae4SAndroid Build Coastguard Worker int Curl_http_getsock_do(struct Curl_easy *data,
1147*6236dae4SAndroid Build Coastguard Worker                          struct connectdata *conn,
1148*6236dae4SAndroid Build Coastguard Worker                          curl_socket_t *socks)
1149*6236dae4SAndroid Build Coastguard Worker {
1150*6236dae4SAndroid Build Coastguard Worker   /* write mode */
1151*6236dae4SAndroid Build Coastguard Worker   (void)conn;
1152*6236dae4SAndroid Build Coastguard Worker   socks[0] = Curl_conn_get_socket(data, FIRSTSOCKET);
1153*6236dae4SAndroid Build Coastguard Worker   return GETSOCK_WRITESOCK(0);
1154*6236dae4SAndroid Build Coastguard Worker }
1155*6236dae4SAndroid Build Coastguard Worker 
1156*6236dae4SAndroid Build Coastguard Worker /*
1157*6236dae4SAndroid Build Coastguard Worker  * Curl_http_done() gets called after a single HTTP request has been
1158*6236dae4SAndroid Build Coastguard Worker  * performed.
1159*6236dae4SAndroid Build Coastguard Worker  */
1160*6236dae4SAndroid Build Coastguard Worker 
Curl_http_done(struct Curl_easy * data,CURLcode status,bool premature)1161*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_done(struct Curl_easy *data,
1162*6236dae4SAndroid Build Coastguard Worker                         CURLcode status, bool premature)
1163*6236dae4SAndroid Build Coastguard Worker {
1164*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1165*6236dae4SAndroid Build Coastguard Worker 
1166*6236dae4SAndroid Build Coastguard Worker   /* Clear multipass flag. If authentication is not done yet, then it will get
1167*6236dae4SAndroid Build Coastguard Worker    * a chance to be set back to true when we output the next auth header */
1168*6236dae4SAndroid Build Coastguard Worker   data->state.authhost.multipass = FALSE;
1169*6236dae4SAndroid Build Coastguard Worker   data->state.authproxy.multipass = FALSE;
1170*6236dae4SAndroid Build Coastguard Worker 
1171*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_reset(&data->state.headerb);
1172*6236dae4SAndroid Build Coastguard Worker   Curl_hyper_done(data);
1173*6236dae4SAndroid Build Coastguard Worker 
1174*6236dae4SAndroid Build Coastguard Worker   if(status)
1175*6236dae4SAndroid Build Coastguard Worker     return status;
1176*6236dae4SAndroid Build Coastguard Worker 
1177*6236dae4SAndroid Build Coastguard Worker   if(!premature && /* this check is pointless when DONE is called before the
1178*6236dae4SAndroid Build Coastguard Worker                       entire operation is complete */
1179*6236dae4SAndroid Build Coastguard Worker      !conn->bits.retry &&
1180*6236dae4SAndroid Build Coastguard Worker      !data->set.connect_only &&
1181*6236dae4SAndroid Build Coastguard Worker      (data->req.bytecount +
1182*6236dae4SAndroid Build Coastguard Worker       data->req.headerbytecount -
1183*6236dae4SAndroid Build Coastguard Worker       data->req.deductheadercount) <= 0) {
1184*6236dae4SAndroid Build Coastguard Worker     /* If this connection is not simply closed to be retried, AND nothing was
1185*6236dae4SAndroid Build Coastguard Worker        read from the HTTP server (that counts), this cannot be right so we
1186*6236dae4SAndroid Build Coastguard Worker        return an error here */
1187*6236dae4SAndroid Build Coastguard Worker     failf(data, "Empty reply from server");
1188*6236dae4SAndroid Build Coastguard Worker     /* Mark it as closed to avoid the "left intact" message */
1189*6236dae4SAndroid Build Coastguard Worker     streamclose(conn, "Empty reply from server");
1190*6236dae4SAndroid Build Coastguard Worker     return CURLE_GOT_NOTHING;
1191*6236dae4SAndroid Build Coastguard Worker   }
1192*6236dae4SAndroid Build Coastguard Worker 
1193*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1194*6236dae4SAndroid Build Coastguard Worker }
1195*6236dae4SAndroid Build Coastguard Worker 
1196*6236dae4SAndroid Build Coastguard Worker /*
1197*6236dae4SAndroid Build Coastguard Worker  * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1198*6236dae4SAndroid Build Coastguard Worker  * to avoid it include:
1199*6236dae4SAndroid Build Coastguard Worker  *
1200*6236dae4SAndroid Build Coastguard Worker  * - if the user specifically requested HTTP 1.0
1201*6236dae4SAndroid Build Coastguard Worker  * - if the server we are connected to only supports 1.0
1202*6236dae4SAndroid Build Coastguard Worker  * - if any server previously contacted to handle this request only supports
1203*6236dae4SAndroid Build Coastguard Worker  * 1.0.
1204*6236dae4SAndroid Build Coastguard Worker  */
Curl_use_http_1_1plus(const struct Curl_easy * data,const struct connectdata * conn)1205*6236dae4SAndroid Build Coastguard Worker bool Curl_use_http_1_1plus(const struct Curl_easy *data,
1206*6236dae4SAndroid Build Coastguard Worker                            const struct connectdata *conn)
1207*6236dae4SAndroid Build Coastguard Worker {
1208*6236dae4SAndroid Build Coastguard Worker   if((data->state.httpversion == 10) || (conn->httpversion == 10))
1209*6236dae4SAndroid Build Coastguard Worker     return FALSE;
1210*6236dae4SAndroid Build Coastguard Worker   if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
1211*6236dae4SAndroid Build Coastguard Worker      (conn->httpversion <= 10))
1212*6236dae4SAndroid Build Coastguard Worker     return FALSE;
1213*6236dae4SAndroid Build Coastguard Worker   return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
1214*6236dae4SAndroid Build Coastguard Worker           (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
1215*6236dae4SAndroid Build Coastguard Worker }
1216*6236dae4SAndroid Build Coastguard Worker 
1217*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
get_http_string(const struct Curl_easy * data,const struct connectdata * conn)1218*6236dae4SAndroid Build Coastguard Worker static const char *get_http_string(const struct Curl_easy *data,
1219*6236dae4SAndroid Build Coastguard Worker                                    const struct connectdata *conn)
1220*6236dae4SAndroid Build Coastguard Worker {
1221*6236dae4SAndroid Build Coastguard Worker   if(Curl_conn_is_http3(data, conn, FIRSTSOCKET))
1222*6236dae4SAndroid Build Coastguard Worker     return "3";
1223*6236dae4SAndroid Build Coastguard Worker   if(Curl_conn_is_http2(data, conn, FIRSTSOCKET))
1224*6236dae4SAndroid Build Coastguard Worker     return "2";
1225*6236dae4SAndroid Build Coastguard Worker   if(Curl_use_http_1_1plus(data, conn))
1226*6236dae4SAndroid Build Coastguard Worker     return "1.1";
1227*6236dae4SAndroid Build Coastguard Worker 
1228*6236dae4SAndroid Build Coastguard Worker   return "1.0";
1229*6236dae4SAndroid Build Coastguard Worker }
1230*6236dae4SAndroid Build Coastguard Worker #endif
1231*6236dae4SAndroid Build Coastguard Worker 
1232*6236dae4SAndroid Build Coastguard Worker enum proxy_use {
1233*6236dae4SAndroid Build Coastguard Worker   HEADER_SERVER,  /* direct to server */
1234*6236dae4SAndroid Build Coastguard Worker   HEADER_PROXY,   /* regular request to proxy */
1235*6236dae4SAndroid Build Coastguard Worker   HEADER_CONNECT  /* sending CONNECT to a proxy */
1236*6236dae4SAndroid Build Coastguard Worker };
1237*6236dae4SAndroid Build Coastguard Worker 
hd_name_eq(const char * n1,size_t n1len,const char * n2,size_t n2len)1238*6236dae4SAndroid Build Coastguard Worker static bool hd_name_eq(const char *n1, size_t n1len,
1239*6236dae4SAndroid Build Coastguard Worker                        const char *n2, size_t n2len)
1240*6236dae4SAndroid Build Coastguard Worker {
1241*6236dae4SAndroid Build Coastguard Worker   if(n1len == n2len) {
1242*6236dae4SAndroid Build Coastguard Worker     return strncasecompare(n1, n2, n1len);
1243*6236dae4SAndroid Build Coastguard Worker   }
1244*6236dae4SAndroid Build Coastguard Worker   return FALSE;
1245*6236dae4SAndroid Build Coastguard Worker }
1246*6236dae4SAndroid Build Coastguard Worker 
Curl_dynhds_add_custom(struct Curl_easy * data,bool is_connect,struct dynhds * hds)1247*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
1248*6236dae4SAndroid Build Coastguard Worker                                 bool is_connect,
1249*6236dae4SAndroid Build Coastguard Worker                                 struct dynhds *hds)
1250*6236dae4SAndroid Build Coastguard Worker {
1251*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1252*6236dae4SAndroid Build Coastguard Worker   char *ptr;
1253*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *h[2];
1254*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *headers;
1255*6236dae4SAndroid Build Coastguard Worker   int numlists = 1; /* by default */
1256*6236dae4SAndroid Build Coastguard Worker   int i;
1257*6236dae4SAndroid Build Coastguard Worker 
1258*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1259*6236dae4SAndroid Build Coastguard Worker   enum proxy_use proxy;
1260*6236dae4SAndroid Build Coastguard Worker 
1261*6236dae4SAndroid Build Coastguard Worker   if(is_connect)
1262*6236dae4SAndroid Build Coastguard Worker     proxy = HEADER_CONNECT;
1263*6236dae4SAndroid Build Coastguard Worker   else
1264*6236dae4SAndroid Build Coastguard Worker     proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ?
1265*6236dae4SAndroid Build Coastguard Worker       HEADER_PROXY : HEADER_SERVER;
1266*6236dae4SAndroid Build Coastguard Worker 
1267*6236dae4SAndroid Build Coastguard Worker   switch(proxy) {
1268*6236dae4SAndroid Build Coastguard Worker   case HEADER_SERVER:
1269*6236dae4SAndroid Build Coastguard Worker     h[0] = data->set.headers;
1270*6236dae4SAndroid Build Coastguard Worker     break;
1271*6236dae4SAndroid Build Coastguard Worker   case HEADER_PROXY:
1272*6236dae4SAndroid Build Coastguard Worker     h[0] = data->set.headers;
1273*6236dae4SAndroid Build Coastguard Worker     if(data->set.sep_headers) {
1274*6236dae4SAndroid Build Coastguard Worker       h[1] = data->set.proxyheaders;
1275*6236dae4SAndroid Build Coastguard Worker       numlists++;
1276*6236dae4SAndroid Build Coastguard Worker     }
1277*6236dae4SAndroid Build Coastguard Worker     break;
1278*6236dae4SAndroid Build Coastguard Worker   case HEADER_CONNECT:
1279*6236dae4SAndroid Build Coastguard Worker     if(data->set.sep_headers)
1280*6236dae4SAndroid Build Coastguard Worker       h[0] = data->set.proxyheaders;
1281*6236dae4SAndroid Build Coastguard Worker     else
1282*6236dae4SAndroid Build Coastguard Worker       h[0] = data->set.headers;
1283*6236dae4SAndroid Build Coastguard Worker     break;
1284*6236dae4SAndroid Build Coastguard Worker   }
1285*6236dae4SAndroid Build Coastguard Worker #else
1286*6236dae4SAndroid Build Coastguard Worker   (void)is_connect;
1287*6236dae4SAndroid Build Coastguard Worker   h[0] = data->set.headers;
1288*6236dae4SAndroid Build Coastguard Worker #endif
1289*6236dae4SAndroid Build Coastguard Worker 
1290*6236dae4SAndroid Build Coastguard Worker   /* loop through one or two lists */
1291*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < numlists; i++) {
1292*6236dae4SAndroid Build Coastguard Worker     for(headers = h[i]; headers; headers = headers->next) {
1293*6236dae4SAndroid Build Coastguard Worker       const char *name, *value;
1294*6236dae4SAndroid Build Coastguard Worker       size_t namelen, valuelen;
1295*6236dae4SAndroid Build Coastguard Worker 
1296*6236dae4SAndroid Build Coastguard Worker       /* There are 2 quirks in place for custom headers:
1297*6236dae4SAndroid Build Coastguard Worker        * 1. setting only 'name:' to suppress a header from being sent
1298*6236dae4SAndroid Build Coastguard Worker        * 2. setting only 'name;' to send an empty (illegal) header
1299*6236dae4SAndroid Build Coastguard Worker        */
1300*6236dae4SAndroid Build Coastguard Worker       ptr = strchr(headers->data, ':');
1301*6236dae4SAndroid Build Coastguard Worker       if(ptr) {
1302*6236dae4SAndroid Build Coastguard Worker         name = headers->data;
1303*6236dae4SAndroid Build Coastguard Worker         namelen = ptr - headers->data;
1304*6236dae4SAndroid Build Coastguard Worker         ptr++; /* pass the colon */
1305*6236dae4SAndroid Build Coastguard Worker         while(*ptr && ISSPACE(*ptr))
1306*6236dae4SAndroid Build Coastguard Worker           ptr++;
1307*6236dae4SAndroid Build Coastguard Worker         if(*ptr) {
1308*6236dae4SAndroid Build Coastguard Worker           value = ptr;
1309*6236dae4SAndroid Build Coastguard Worker           valuelen = strlen(value);
1310*6236dae4SAndroid Build Coastguard Worker         }
1311*6236dae4SAndroid Build Coastguard Worker         else {
1312*6236dae4SAndroid Build Coastguard Worker           /* quirk #1, suppress this header */
1313*6236dae4SAndroid Build Coastguard Worker           continue;
1314*6236dae4SAndroid Build Coastguard Worker         }
1315*6236dae4SAndroid Build Coastguard Worker       }
1316*6236dae4SAndroid Build Coastguard Worker       else {
1317*6236dae4SAndroid Build Coastguard Worker         ptr = strchr(headers->data, ';');
1318*6236dae4SAndroid Build Coastguard Worker 
1319*6236dae4SAndroid Build Coastguard Worker         if(!ptr) {
1320*6236dae4SAndroid Build Coastguard Worker           /* neither : nor ; in provided header value. We seem
1321*6236dae4SAndroid Build Coastguard Worker            * to ignore this silently */
1322*6236dae4SAndroid Build Coastguard Worker           continue;
1323*6236dae4SAndroid Build Coastguard Worker         }
1324*6236dae4SAndroid Build Coastguard Worker 
1325*6236dae4SAndroid Build Coastguard Worker         name = headers->data;
1326*6236dae4SAndroid Build Coastguard Worker         namelen = ptr - headers->data;
1327*6236dae4SAndroid Build Coastguard Worker         ptr++; /* pass the semicolon */
1328*6236dae4SAndroid Build Coastguard Worker         while(*ptr && ISSPACE(*ptr))
1329*6236dae4SAndroid Build Coastguard Worker           ptr++;
1330*6236dae4SAndroid Build Coastguard Worker         if(!*ptr) {
1331*6236dae4SAndroid Build Coastguard Worker           /* quirk #2, send an empty header */
1332*6236dae4SAndroid Build Coastguard Worker           value = "";
1333*6236dae4SAndroid Build Coastguard Worker           valuelen = 0;
1334*6236dae4SAndroid Build Coastguard Worker         }
1335*6236dae4SAndroid Build Coastguard Worker         else {
1336*6236dae4SAndroid Build Coastguard Worker           /* this may be used for something else in the future,
1337*6236dae4SAndroid Build Coastguard Worker            * ignore this for now */
1338*6236dae4SAndroid Build Coastguard Worker           continue;
1339*6236dae4SAndroid Build Coastguard Worker         }
1340*6236dae4SAndroid Build Coastguard Worker       }
1341*6236dae4SAndroid Build Coastguard Worker 
1342*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(name && value);
1343*6236dae4SAndroid Build Coastguard Worker       if(data->state.aptr.host &&
1344*6236dae4SAndroid Build Coastguard Worker          /* a Host: header was sent already, do not pass on any custom Host:
1345*6236dae4SAndroid Build Coastguard Worker             header as that will produce *two* in the same request! */
1346*6236dae4SAndroid Build Coastguard Worker          hd_name_eq(name, namelen, STRCONST("Host:")))
1347*6236dae4SAndroid Build Coastguard Worker         ;
1348*6236dae4SAndroid Build Coastguard Worker       else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1349*6236dae4SAndroid Build Coastguard Worker               /* this header (extended by formdata.c) is sent later */
1350*6236dae4SAndroid Build Coastguard Worker               hd_name_eq(name, namelen, STRCONST("Content-Type:")))
1351*6236dae4SAndroid Build Coastguard Worker         ;
1352*6236dae4SAndroid Build Coastguard Worker       else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1353*6236dae4SAndroid Build Coastguard Worker               /* this header is sent later */
1354*6236dae4SAndroid Build Coastguard Worker               hd_name_eq(name, namelen, STRCONST("Content-Type:")))
1355*6236dae4SAndroid Build Coastguard Worker         ;
1356*6236dae4SAndroid Build Coastguard Worker       else if(data->req.authneg &&
1357*6236dae4SAndroid Build Coastguard Worker               /* while doing auth neg, do not allow the custom length since
1358*6236dae4SAndroid Build Coastguard Worker                  we will force length zero then */
1359*6236dae4SAndroid Build Coastguard Worker               hd_name_eq(name, namelen, STRCONST("Content-Length:")))
1360*6236dae4SAndroid Build Coastguard Worker         ;
1361*6236dae4SAndroid Build Coastguard Worker       else if(data->state.aptr.te &&
1362*6236dae4SAndroid Build Coastguard Worker               /* when asking for Transfer-Encoding, do not pass on a custom
1363*6236dae4SAndroid Build Coastguard Worker                  Connection: */
1364*6236dae4SAndroid Build Coastguard Worker               hd_name_eq(name, namelen, STRCONST("Connection:")))
1365*6236dae4SAndroid Build Coastguard Worker         ;
1366*6236dae4SAndroid Build Coastguard Worker       else if((conn->httpversion >= 20) &&
1367*6236dae4SAndroid Build Coastguard Worker               hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:")))
1368*6236dae4SAndroid Build Coastguard Worker         /* HTTP/2 does not support chunked requests */
1369*6236dae4SAndroid Build Coastguard Worker         ;
1370*6236dae4SAndroid Build Coastguard Worker       else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) ||
1371*6236dae4SAndroid Build Coastguard Worker                hd_name_eq(name, namelen, STRCONST("Cookie:"))) &&
1372*6236dae4SAndroid Build Coastguard Worker               /* be careful of sending this potentially sensitive header to
1373*6236dae4SAndroid Build Coastguard Worker                  other hosts */
1374*6236dae4SAndroid Build Coastguard Worker               !Curl_auth_allowed_to_host(data))
1375*6236dae4SAndroid Build Coastguard Worker         ;
1376*6236dae4SAndroid Build Coastguard Worker       else {
1377*6236dae4SAndroid Build Coastguard Worker         CURLcode result;
1378*6236dae4SAndroid Build Coastguard Worker 
1379*6236dae4SAndroid Build Coastguard Worker         result = Curl_dynhds_add(hds, name, namelen, value, valuelen);
1380*6236dae4SAndroid Build Coastguard Worker         if(result)
1381*6236dae4SAndroid Build Coastguard Worker           return result;
1382*6236dae4SAndroid Build Coastguard Worker       }
1383*6236dae4SAndroid Build Coastguard Worker     }
1384*6236dae4SAndroid Build Coastguard Worker   }
1385*6236dae4SAndroid Build Coastguard Worker 
1386*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1387*6236dae4SAndroid Build Coastguard Worker }
1388*6236dae4SAndroid Build Coastguard Worker 
Curl_add_custom_headers(struct Curl_easy * data,bool is_connect,struct dynbuf * req)1389*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_add_custom_headers(struct Curl_easy *data,
1390*6236dae4SAndroid Build Coastguard Worker                                  bool is_connect,
1391*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
1392*6236dae4SAndroid Build Coastguard Worker                                  struct dynbuf *req
1393*6236dae4SAndroid Build Coastguard Worker #else
1394*6236dae4SAndroid Build Coastguard Worker                                  void *req
1395*6236dae4SAndroid Build Coastguard Worker #endif
1396*6236dae4SAndroid Build Coastguard Worker   )
1397*6236dae4SAndroid Build Coastguard Worker {
1398*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1399*6236dae4SAndroid Build Coastguard Worker   char *ptr;
1400*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *h[2];
1401*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *headers;
1402*6236dae4SAndroid Build Coastguard Worker   int numlists = 1; /* by default */
1403*6236dae4SAndroid Build Coastguard Worker   int i;
1404*6236dae4SAndroid Build Coastguard Worker 
1405*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1406*6236dae4SAndroid Build Coastguard Worker   enum proxy_use proxy;
1407*6236dae4SAndroid Build Coastguard Worker 
1408*6236dae4SAndroid Build Coastguard Worker   if(is_connect)
1409*6236dae4SAndroid Build Coastguard Worker     proxy = HEADER_CONNECT;
1410*6236dae4SAndroid Build Coastguard Worker   else
1411*6236dae4SAndroid Build Coastguard Worker     proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ?
1412*6236dae4SAndroid Build Coastguard Worker       HEADER_PROXY : HEADER_SERVER;
1413*6236dae4SAndroid Build Coastguard Worker 
1414*6236dae4SAndroid Build Coastguard Worker   switch(proxy) {
1415*6236dae4SAndroid Build Coastguard Worker   case HEADER_SERVER:
1416*6236dae4SAndroid Build Coastguard Worker     h[0] = data->set.headers;
1417*6236dae4SAndroid Build Coastguard Worker     break;
1418*6236dae4SAndroid Build Coastguard Worker   case HEADER_PROXY:
1419*6236dae4SAndroid Build Coastguard Worker     h[0] = data->set.headers;
1420*6236dae4SAndroid Build Coastguard Worker     if(data->set.sep_headers) {
1421*6236dae4SAndroid Build Coastguard Worker       h[1] = data->set.proxyheaders;
1422*6236dae4SAndroid Build Coastguard Worker       numlists++;
1423*6236dae4SAndroid Build Coastguard Worker     }
1424*6236dae4SAndroid Build Coastguard Worker     break;
1425*6236dae4SAndroid Build Coastguard Worker   case HEADER_CONNECT:
1426*6236dae4SAndroid Build Coastguard Worker     if(data->set.sep_headers)
1427*6236dae4SAndroid Build Coastguard Worker       h[0] = data->set.proxyheaders;
1428*6236dae4SAndroid Build Coastguard Worker     else
1429*6236dae4SAndroid Build Coastguard Worker       h[0] = data->set.headers;
1430*6236dae4SAndroid Build Coastguard Worker     break;
1431*6236dae4SAndroid Build Coastguard Worker   }
1432*6236dae4SAndroid Build Coastguard Worker #else
1433*6236dae4SAndroid Build Coastguard Worker   (void)is_connect;
1434*6236dae4SAndroid Build Coastguard Worker   h[0] = data->set.headers;
1435*6236dae4SAndroid Build Coastguard Worker #endif
1436*6236dae4SAndroid Build Coastguard Worker 
1437*6236dae4SAndroid Build Coastguard Worker   /* loop through one or two lists */
1438*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < numlists; i++) {
1439*6236dae4SAndroid Build Coastguard Worker     headers = h[i];
1440*6236dae4SAndroid Build Coastguard Worker 
1441*6236dae4SAndroid Build Coastguard Worker     while(headers) {
1442*6236dae4SAndroid Build Coastguard Worker       char *semicolonp = NULL;
1443*6236dae4SAndroid Build Coastguard Worker       ptr = strchr(headers->data, ':');
1444*6236dae4SAndroid Build Coastguard Worker       if(!ptr) {
1445*6236dae4SAndroid Build Coastguard Worker         char *optr;
1446*6236dae4SAndroid Build Coastguard Worker         /* no colon, semicolon? */
1447*6236dae4SAndroid Build Coastguard Worker         ptr = strchr(headers->data, ';');
1448*6236dae4SAndroid Build Coastguard Worker         if(ptr) {
1449*6236dae4SAndroid Build Coastguard Worker           optr = ptr;
1450*6236dae4SAndroid Build Coastguard Worker           ptr++; /* pass the semicolon */
1451*6236dae4SAndroid Build Coastguard Worker           while(*ptr && ISSPACE(*ptr))
1452*6236dae4SAndroid Build Coastguard Worker             ptr++;
1453*6236dae4SAndroid Build Coastguard Worker 
1454*6236dae4SAndroid Build Coastguard Worker           if(*ptr) {
1455*6236dae4SAndroid Build Coastguard Worker             /* this may be used for something else in the future */
1456*6236dae4SAndroid Build Coastguard Worker             optr = NULL;
1457*6236dae4SAndroid Build Coastguard Worker           }
1458*6236dae4SAndroid Build Coastguard Worker           else {
1459*6236dae4SAndroid Build Coastguard Worker             if(*(--ptr) == ';') {
1460*6236dae4SAndroid Build Coastguard Worker               /* copy the source */
1461*6236dae4SAndroid Build Coastguard Worker               semicolonp = strdup(headers->data);
1462*6236dae4SAndroid Build Coastguard Worker               if(!semicolonp) {
1463*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
1464*6236dae4SAndroid Build Coastguard Worker                 Curl_dyn_free(req);
1465*6236dae4SAndroid Build Coastguard Worker #endif
1466*6236dae4SAndroid Build Coastguard Worker                 return CURLE_OUT_OF_MEMORY;
1467*6236dae4SAndroid Build Coastguard Worker               }
1468*6236dae4SAndroid Build Coastguard Worker               /* put a colon where the semicolon is */
1469*6236dae4SAndroid Build Coastguard Worker               semicolonp[ptr - headers->data] = ':';
1470*6236dae4SAndroid Build Coastguard Worker               /* point at the colon */
1471*6236dae4SAndroid Build Coastguard Worker               optr = &semicolonp [ptr - headers->data];
1472*6236dae4SAndroid Build Coastguard Worker             }
1473*6236dae4SAndroid Build Coastguard Worker           }
1474*6236dae4SAndroid Build Coastguard Worker           ptr = optr;
1475*6236dae4SAndroid Build Coastguard Worker         }
1476*6236dae4SAndroid Build Coastguard Worker       }
1477*6236dae4SAndroid Build Coastguard Worker       if(ptr && (ptr != headers->data)) {
1478*6236dae4SAndroid Build Coastguard Worker         /* we require a colon for this to be a true header */
1479*6236dae4SAndroid Build Coastguard Worker 
1480*6236dae4SAndroid Build Coastguard Worker         ptr++; /* pass the colon */
1481*6236dae4SAndroid Build Coastguard Worker         while(*ptr && ISSPACE(*ptr))
1482*6236dae4SAndroid Build Coastguard Worker           ptr++;
1483*6236dae4SAndroid Build Coastguard Worker 
1484*6236dae4SAndroid Build Coastguard Worker         if(*ptr || semicolonp) {
1485*6236dae4SAndroid Build Coastguard Worker           /* only send this if the contents was non-blank or done special */
1486*6236dae4SAndroid Build Coastguard Worker           CURLcode result = CURLE_OK;
1487*6236dae4SAndroid Build Coastguard Worker           char *compare = semicolonp ? semicolonp : headers->data;
1488*6236dae4SAndroid Build Coastguard Worker 
1489*6236dae4SAndroid Build Coastguard Worker           if(data->state.aptr.host &&
1490*6236dae4SAndroid Build Coastguard Worker              /* a Host: header was sent already, do not pass on any custom
1491*6236dae4SAndroid Build Coastguard Worker                 Host: header as that will produce *two* in the same
1492*6236dae4SAndroid Build Coastguard Worker                 request! */
1493*6236dae4SAndroid Build Coastguard Worker              checkprefix("Host:", compare))
1494*6236dae4SAndroid Build Coastguard Worker             ;
1495*6236dae4SAndroid Build Coastguard Worker           else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1496*6236dae4SAndroid Build Coastguard Worker                   /* this header (extended by formdata.c) is sent later */
1497*6236dae4SAndroid Build Coastguard Worker                   checkprefix("Content-Type:", compare))
1498*6236dae4SAndroid Build Coastguard Worker             ;
1499*6236dae4SAndroid Build Coastguard Worker           else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1500*6236dae4SAndroid Build Coastguard Worker                   /* this header is sent later */
1501*6236dae4SAndroid Build Coastguard Worker                   checkprefix("Content-Type:", compare))
1502*6236dae4SAndroid Build Coastguard Worker             ;
1503*6236dae4SAndroid Build Coastguard Worker           else if(data->req.authneg &&
1504*6236dae4SAndroid Build Coastguard Worker                   /* while doing auth neg, do not allow the custom length since
1505*6236dae4SAndroid Build Coastguard Worker                      we will force length zero then */
1506*6236dae4SAndroid Build Coastguard Worker                   checkprefix("Content-Length:", compare))
1507*6236dae4SAndroid Build Coastguard Worker             ;
1508*6236dae4SAndroid Build Coastguard Worker           else if(data->state.aptr.te &&
1509*6236dae4SAndroid Build Coastguard Worker                   /* when asking for Transfer-Encoding, do not pass on a custom
1510*6236dae4SAndroid Build Coastguard Worker                      Connection: */
1511*6236dae4SAndroid Build Coastguard Worker                   checkprefix("Connection:", compare))
1512*6236dae4SAndroid Build Coastguard Worker             ;
1513*6236dae4SAndroid Build Coastguard Worker           else if((conn->httpversion >= 20) &&
1514*6236dae4SAndroid Build Coastguard Worker                   checkprefix("Transfer-Encoding:", compare))
1515*6236dae4SAndroid Build Coastguard Worker             /* HTTP/2 does not support chunked requests */
1516*6236dae4SAndroid Build Coastguard Worker             ;
1517*6236dae4SAndroid Build Coastguard Worker           else if((checkprefix("Authorization:", compare) ||
1518*6236dae4SAndroid Build Coastguard Worker                    checkprefix("Cookie:", compare)) &&
1519*6236dae4SAndroid Build Coastguard Worker                   /* be careful of sending this potentially sensitive header to
1520*6236dae4SAndroid Build Coastguard Worker                      other hosts */
1521*6236dae4SAndroid Build Coastguard Worker                   !Curl_auth_allowed_to_host(data))
1522*6236dae4SAndroid Build Coastguard Worker             ;
1523*6236dae4SAndroid Build Coastguard Worker           else {
1524*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HYPER
1525*6236dae4SAndroid Build Coastguard Worker             result = Curl_hyper_header(data, req, compare);
1526*6236dae4SAndroid Build Coastguard Worker #else
1527*6236dae4SAndroid Build Coastguard Worker             result = Curl_dyn_addf(req, "%s\r\n", compare);
1528*6236dae4SAndroid Build Coastguard Worker #endif
1529*6236dae4SAndroid Build Coastguard Worker           }
1530*6236dae4SAndroid Build Coastguard Worker           if(semicolonp)
1531*6236dae4SAndroid Build Coastguard Worker             free(semicolonp);
1532*6236dae4SAndroid Build Coastguard Worker           if(result)
1533*6236dae4SAndroid Build Coastguard Worker             return result;
1534*6236dae4SAndroid Build Coastguard Worker         }
1535*6236dae4SAndroid Build Coastguard Worker       }
1536*6236dae4SAndroid Build Coastguard Worker       headers = headers->next;
1537*6236dae4SAndroid Build Coastguard Worker     }
1538*6236dae4SAndroid Build Coastguard Worker   }
1539*6236dae4SAndroid Build Coastguard Worker 
1540*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1541*6236dae4SAndroid Build Coastguard Worker }
1542*6236dae4SAndroid Build Coastguard Worker 
1543*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PARSEDATE
Curl_add_timecondition(struct Curl_easy * data,struct dynbuf * req)1544*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_add_timecondition(struct Curl_easy *data,
1545*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
1546*6236dae4SAndroid Build Coastguard Worker                                 struct dynbuf *req
1547*6236dae4SAndroid Build Coastguard Worker #else
1548*6236dae4SAndroid Build Coastguard Worker                                 void *req
1549*6236dae4SAndroid Build Coastguard Worker #endif
1550*6236dae4SAndroid Build Coastguard Worker   )
1551*6236dae4SAndroid Build Coastguard Worker {
1552*6236dae4SAndroid Build Coastguard Worker   const struct tm *tm;
1553*6236dae4SAndroid Build Coastguard Worker   struct tm keeptime;
1554*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1555*6236dae4SAndroid Build Coastguard Worker   char datestr[80];
1556*6236dae4SAndroid Build Coastguard Worker   const char *condp;
1557*6236dae4SAndroid Build Coastguard Worker   size_t len;
1558*6236dae4SAndroid Build Coastguard Worker 
1559*6236dae4SAndroid Build Coastguard Worker   if(data->set.timecondition == CURL_TIMECOND_NONE)
1560*6236dae4SAndroid Build Coastguard Worker     /* no condition was asked for */
1561*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
1562*6236dae4SAndroid Build Coastguard Worker 
1563*6236dae4SAndroid Build Coastguard Worker   result = Curl_gmtime(data->set.timevalue, &keeptime);
1564*6236dae4SAndroid Build Coastguard Worker   if(result) {
1565*6236dae4SAndroid Build Coastguard Worker     failf(data, "Invalid TIMEVALUE");
1566*6236dae4SAndroid Build Coastguard Worker     return result;
1567*6236dae4SAndroid Build Coastguard Worker   }
1568*6236dae4SAndroid Build Coastguard Worker   tm = &keeptime;
1569*6236dae4SAndroid Build Coastguard Worker 
1570*6236dae4SAndroid Build Coastguard Worker   switch(data->set.timecondition) {
1571*6236dae4SAndroid Build Coastguard Worker   default:
1572*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "invalid time condition"));
1573*6236dae4SAndroid Build Coastguard Worker     return CURLE_BAD_FUNCTION_ARGUMENT;
1574*6236dae4SAndroid Build Coastguard Worker 
1575*6236dae4SAndroid Build Coastguard Worker   case CURL_TIMECOND_IFMODSINCE:
1576*6236dae4SAndroid Build Coastguard Worker     condp = "If-Modified-Since";
1577*6236dae4SAndroid Build Coastguard Worker     len = 17;
1578*6236dae4SAndroid Build Coastguard Worker     break;
1579*6236dae4SAndroid Build Coastguard Worker   case CURL_TIMECOND_IFUNMODSINCE:
1580*6236dae4SAndroid Build Coastguard Worker     condp = "If-Unmodified-Since";
1581*6236dae4SAndroid Build Coastguard Worker     len = 19;
1582*6236dae4SAndroid Build Coastguard Worker     break;
1583*6236dae4SAndroid Build Coastguard Worker   case CURL_TIMECOND_LASTMOD:
1584*6236dae4SAndroid Build Coastguard Worker     condp = "Last-Modified";
1585*6236dae4SAndroid Build Coastguard Worker     len = 13;
1586*6236dae4SAndroid Build Coastguard Worker     break;
1587*6236dae4SAndroid Build Coastguard Worker   }
1588*6236dae4SAndroid Build Coastguard Worker 
1589*6236dae4SAndroid Build Coastguard Worker   if(Curl_checkheaders(data, condp, len)) {
1590*6236dae4SAndroid Build Coastguard Worker     /* A custom header was specified; it will be sent instead. */
1591*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
1592*6236dae4SAndroid Build Coastguard Worker   }
1593*6236dae4SAndroid Build Coastguard Worker 
1594*6236dae4SAndroid Build Coastguard Worker   /* The If-Modified-Since header family should have their times set in
1595*6236dae4SAndroid Build Coastguard Worker    * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1596*6236dae4SAndroid Build Coastguard Worker    * represented in Greenwich Mean Time (GMT), without exception. For the
1597*6236dae4SAndroid Build Coastguard Worker    * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1598*6236dae4SAndroid Build Coastguard Worker    * Time)." (see page 20 of RFC2616).
1599*6236dae4SAndroid Build Coastguard Worker    */
1600*6236dae4SAndroid Build Coastguard Worker 
1601*6236dae4SAndroid Build Coastguard Worker   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1602*6236dae4SAndroid Build Coastguard Worker   msnprintf(datestr, sizeof(datestr),
1603*6236dae4SAndroid Build Coastguard Worker             "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
1604*6236dae4SAndroid Build Coastguard Worker             condp,
1605*6236dae4SAndroid Build Coastguard Worker             Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
1606*6236dae4SAndroid Build Coastguard Worker             tm->tm_mday,
1607*6236dae4SAndroid Build Coastguard Worker             Curl_month[tm->tm_mon],
1608*6236dae4SAndroid Build Coastguard Worker             tm->tm_year + 1900,
1609*6236dae4SAndroid Build Coastguard Worker             tm->tm_hour,
1610*6236dae4SAndroid Build Coastguard Worker             tm->tm_min,
1611*6236dae4SAndroid Build Coastguard Worker             tm->tm_sec);
1612*6236dae4SAndroid Build Coastguard Worker 
1613*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
1614*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_add(req, datestr);
1615*6236dae4SAndroid Build Coastguard Worker #else
1616*6236dae4SAndroid Build Coastguard Worker   result = Curl_hyper_header(data, req, datestr);
1617*6236dae4SAndroid Build Coastguard Worker #endif
1618*6236dae4SAndroid Build Coastguard Worker 
1619*6236dae4SAndroid Build Coastguard Worker   return result;
1620*6236dae4SAndroid Build Coastguard Worker }
1621*6236dae4SAndroid Build Coastguard Worker #else
1622*6236dae4SAndroid Build Coastguard Worker /* disabled */
Curl_add_timecondition(struct Curl_easy * data,struct dynbuf * req)1623*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_add_timecondition(struct Curl_easy *data,
1624*6236dae4SAndroid Build Coastguard Worker                                 struct dynbuf *req)
1625*6236dae4SAndroid Build Coastguard Worker {
1626*6236dae4SAndroid Build Coastguard Worker   (void)data;
1627*6236dae4SAndroid Build Coastguard Worker   (void)req;
1628*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1629*6236dae4SAndroid Build Coastguard Worker }
1630*6236dae4SAndroid Build Coastguard Worker #endif
1631*6236dae4SAndroid Build Coastguard Worker 
Curl_http_method(struct Curl_easy * data,struct connectdata * conn,const char ** method,Curl_HttpReq * reqp)1632*6236dae4SAndroid Build Coastguard Worker void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
1633*6236dae4SAndroid Build Coastguard Worker                       const char **method, Curl_HttpReq *reqp)
1634*6236dae4SAndroid Build Coastguard Worker {
1635*6236dae4SAndroid Build Coastguard Worker   Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq;
1636*6236dae4SAndroid Build Coastguard Worker   const char *request;
1637*6236dae4SAndroid Build Coastguard Worker   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
1638*6236dae4SAndroid Build Coastguard Worker      data->state.upload)
1639*6236dae4SAndroid Build Coastguard Worker     httpreq = HTTPREQ_PUT;
1640*6236dae4SAndroid Build Coastguard Worker 
1641*6236dae4SAndroid Build Coastguard Worker   /* Now set the 'request' pointer to the proper request string */
1642*6236dae4SAndroid Build Coastguard Worker   if(data->set.str[STRING_CUSTOMREQUEST])
1643*6236dae4SAndroid Build Coastguard Worker     request = data->set.str[STRING_CUSTOMREQUEST];
1644*6236dae4SAndroid Build Coastguard Worker   else {
1645*6236dae4SAndroid Build Coastguard Worker     if(data->req.no_body)
1646*6236dae4SAndroid Build Coastguard Worker       request = "HEAD";
1647*6236dae4SAndroid Build Coastguard Worker     else {
1648*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
1649*6236dae4SAndroid Build Coastguard Worker       switch(httpreq) {
1650*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST:
1651*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST_FORM:
1652*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST_MIME:
1653*6236dae4SAndroid Build Coastguard Worker         request = "POST";
1654*6236dae4SAndroid Build Coastguard Worker         break;
1655*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_PUT:
1656*6236dae4SAndroid Build Coastguard Worker         request = "PUT";
1657*6236dae4SAndroid Build Coastguard Worker         break;
1658*6236dae4SAndroid Build Coastguard Worker       default: /* this should never happen */
1659*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_GET:
1660*6236dae4SAndroid Build Coastguard Worker         request = "GET";
1661*6236dae4SAndroid Build Coastguard Worker         break;
1662*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_HEAD:
1663*6236dae4SAndroid Build Coastguard Worker         request = "HEAD";
1664*6236dae4SAndroid Build Coastguard Worker         break;
1665*6236dae4SAndroid Build Coastguard Worker       }
1666*6236dae4SAndroid Build Coastguard Worker     }
1667*6236dae4SAndroid Build Coastguard Worker   }
1668*6236dae4SAndroid Build Coastguard Worker   *method = request;
1669*6236dae4SAndroid Build Coastguard Worker   *reqp = httpreq;
1670*6236dae4SAndroid Build Coastguard Worker }
1671*6236dae4SAndroid Build Coastguard Worker 
Curl_http_useragent(struct Curl_easy * data)1672*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_useragent(struct Curl_easy *data)
1673*6236dae4SAndroid Build Coastguard Worker {
1674*6236dae4SAndroid Build Coastguard Worker   /* The User-Agent string might have been allocated in url.c already, because
1675*6236dae4SAndroid Build Coastguard Worker      it might have been used in the proxy connect, but if we have got a header
1676*6236dae4SAndroid Build Coastguard Worker      with the user-agent string specified, we erase the previously made string
1677*6236dae4SAndroid Build Coastguard Worker      here. */
1678*6236dae4SAndroid Build Coastguard Worker   if(Curl_checkheaders(data, STRCONST("User-Agent"))) {
1679*6236dae4SAndroid Build Coastguard Worker     free(data->state.aptr.uagent);
1680*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.uagent = NULL;
1681*6236dae4SAndroid Build Coastguard Worker   }
1682*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1683*6236dae4SAndroid Build Coastguard Worker }
1684*6236dae4SAndroid Build Coastguard Worker 
1685*6236dae4SAndroid Build Coastguard Worker 
Curl_http_host(struct Curl_easy * data,struct connectdata * conn)1686*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
1687*6236dae4SAndroid Build Coastguard Worker {
1688*6236dae4SAndroid Build Coastguard Worker   const char *ptr;
1689*6236dae4SAndroid Build Coastguard Worker   struct dynamically_allocated_data *aptr = &data->state.aptr;
1690*6236dae4SAndroid Build Coastguard Worker   if(!data->state.this_is_a_follow) {
1691*6236dae4SAndroid Build Coastguard Worker     /* Free to avoid leaking memory on multiple requests */
1692*6236dae4SAndroid Build Coastguard Worker     free(data->state.first_host);
1693*6236dae4SAndroid Build Coastguard Worker 
1694*6236dae4SAndroid Build Coastguard Worker     data->state.first_host = strdup(conn->host.name);
1695*6236dae4SAndroid Build Coastguard Worker     if(!data->state.first_host)
1696*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1697*6236dae4SAndroid Build Coastguard Worker 
1698*6236dae4SAndroid Build Coastguard Worker     data->state.first_remote_port = conn->remote_port;
1699*6236dae4SAndroid Build Coastguard Worker     data->state.first_remote_protocol = conn->handler->protocol;
1700*6236dae4SAndroid Build Coastguard Worker   }
1701*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(aptr->host);
1702*6236dae4SAndroid Build Coastguard Worker 
1703*6236dae4SAndroid Build Coastguard Worker   ptr = Curl_checkheaders(data, STRCONST("Host"));
1704*6236dae4SAndroid Build Coastguard Worker   if(ptr && (!data->state.this_is_a_follow ||
1705*6236dae4SAndroid Build Coastguard Worker              strcasecompare(data->state.first_host, conn->host.name))) {
1706*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_COOKIES)
1707*6236dae4SAndroid Build Coastguard Worker     /* If we have a given custom Host: header, we extract the hostname in
1708*6236dae4SAndroid Build Coastguard Worker        order to possibly use it for cookie reasons later on. We only allow the
1709*6236dae4SAndroid Build Coastguard Worker        custom Host: header if this is NOT a redirect, as setting Host: in the
1710*6236dae4SAndroid Build Coastguard Worker        redirected request is being out on thin ice. Except if the hostname
1711*6236dae4SAndroid Build Coastguard Worker        is the same as the first one! */
1712*6236dae4SAndroid Build Coastguard Worker     char *cookiehost = Curl_copy_header_value(ptr);
1713*6236dae4SAndroid Build Coastguard Worker     if(!cookiehost)
1714*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1715*6236dae4SAndroid Build Coastguard Worker     if(!*cookiehost)
1716*6236dae4SAndroid Build Coastguard Worker       /* ignore empty data */
1717*6236dae4SAndroid Build Coastguard Worker       free(cookiehost);
1718*6236dae4SAndroid Build Coastguard Worker     else {
1719*6236dae4SAndroid Build Coastguard Worker       /* If the host begins with '[', we start searching for the port after
1720*6236dae4SAndroid Build Coastguard Worker          the bracket has been closed */
1721*6236dae4SAndroid Build Coastguard Worker       if(*cookiehost == '[') {
1722*6236dae4SAndroid Build Coastguard Worker         char *closingbracket;
1723*6236dae4SAndroid Build Coastguard Worker         /* since the 'cookiehost' is an allocated memory area that will be
1724*6236dae4SAndroid Build Coastguard Worker            freed later we cannot simply increment the pointer */
1725*6236dae4SAndroid Build Coastguard Worker         memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
1726*6236dae4SAndroid Build Coastguard Worker         closingbracket = strchr(cookiehost, ']');
1727*6236dae4SAndroid Build Coastguard Worker         if(closingbracket)
1728*6236dae4SAndroid Build Coastguard Worker           *closingbracket = 0;
1729*6236dae4SAndroid Build Coastguard Worker       }
1730*6236dae4SAndroid Build Coastguard Worker       else {
1731*6236dae4SAndroid Build Coastguard Worker         int startsearch = 0;
1732*6236dae4SAndroid Build Coastguard Worker         char *colon = strchr(cookiehost + startsearch, ':');
1733*6236dae4SAndroid Build Coastguard Worker         if(colon)
1734*6236dae4SAndroid Build Coastguard Worker           *colon = 0; /* The host must not include an embedded port number */
1735*6236dae4SAndroid Build Coastguard Worker       }
1736*6236dae4SAndroid Build Coastguard Worker       Curl_safefree(aptr->cookiehost);
1737*6236dae4SAndroid Build Coastguard Worker       aptr->cookiehost = cookiehost;
1738*6236dae4SAndroid Build Coastguard Worker     }
1739*6236dae4SAndroid Build Coastguard Worker #endif
1740*6236dae4SAndroid Build Coastguard Worker 
1741*6236dae4SAndroid Build Coastguard Worker     if(!strcasecompare("Host:", ptr)) {
1742*6236dae4SAndroid Build Coastguard Worker       aptr->host = aprintf("Host:%s\r\n", &ptr[5]);
1743*6236dae4SAndroid Build Coastguard Worker       if(!aptr->host)
1744*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1745*6236dae4SAndroid Build Coastguard Worker     }
1746*6236dae4SAndroid Build Coastguard Worker   }
1747*6236dae4SAndroid Build Coastguard Worker   else {
1748*6236dae4SAndroid Build Coastguard Worker     /* When building Host: headers, we must put the hostname within
1749*6236dae4SAndroid Build Coastguard Worker        [brackets] if the hostname is a plain IPv6-address. RFC2732-style. */
1750*6236dae4SAndroid Build Coastguard Worker     const char *host = conn->host.name;
1751*6236dae4SAndroid Build Coastguard Worker 
1752*6236dae4SAndroid Build Coastguard Worker     if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) &&
1753*6236dae4SAndroid Build Coastguard Worker         (conn->remote_port == PORT_HTTPS)) ||
1754*6236dae4SAndroid Build Coastguard Worker        ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) &&
1755*6236dae4SAndroid Build Coastguard Worker         (conn->remote_port == PORT_HTTP)) )
1756*6236dae4SAndroid Build Coastguard Worker       /* if(HTTPS on port 443) OR (HTTP on port 80) then do not include
1757*6236dae4SAndroid Build Coastguard Worker          the port number in the host string */
1758*6236dae4SAndroid Build Coastguard Worker       aptr->host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip ? "[" : "",
1759*6236dae4SAndroid Build Coastguard Worker                            host, conn->bits.ipv6_ip ? "]" : "");
1760*6236dae4SAndroid Build Coastguard Worker     else
1761*6236dae4SAndroid Build Coastguard Worker       aptr->host = aprintf("Host: %s%s%s:%d\r\n",
1762*6236dae4SAndroid Build Coastguard Worker                            conn->bits.ipv6_ip ? "[" : "",
1763*6236dae4SAndroid Build Coastguard Worker                            host, conn->bits.ipv6_ip ? "]" : "",
1764*6236dae4SAndroid Build Coastguard Worker                            conn->remote_port);
1765*6236dae4SAndroid Build Coastguard Worker 
1766*6236dae4SAndroid Build Coastguard Worker     if(!aptr->host)
1767*6236dae4SAndroid Build Coastguard Worker       /* without Host: we cannot make a nice request */
1768*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1769*6236dae4SAndroid Build Coastguard Worker   }
1770*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1771*6236dae4SAndroid Build Coastguard Worker }
1772*6236dae4SAndroid Build Coastguard Worker 
1773*6236dae4SAndroid Build Coastguard Worker /*
1774*6236dae4SAndroid Build Coastguard Worker  * Append the request-target to the HTTP request
1775*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_target(struct Curl_easy * data,struct connectdata * conn,struct dynbuf * r)1776*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_target(struct Curl_easy *data,
1777*6236dae4SAndroid Build Coastguard Worker                           struct connectdata *conn,
1778*6236dae4SAndroid Build Coastguard Worker                           struct dynbuf *r)
1779*6236dae4SAndroid Build Coastguard Worker {
1780*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
1781*6236dae4SAndroid Build Coastguard Worker   const char *path = data->state.up.path;
1782*6236dae4SAndroid Build Coastguard Worker   const char *query = data->state.up.query;
1783*6236dae4SAndroid Build Coastguard Worker 
1784*6236dae4SAndroid Build Coastguard Worker   if(data->set.str[STRING_TARGET]) {
1785*6236dae4SAndroid Build Coastguard Worker     path = data->set.str[STRING_TARGET];
1786*6236dae4SAndroid Build Coastguard Worker     query = NULL;
1787*6236dae4SAndroid Build Coastguard Worker   }
1788*6236dae4SAndroid Build Coastguard Worker 
1789*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1790*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
1791*6236dae4SAndroid Build Coastguard Worker     /* Using a proxy but does not tunnel through it */
1792*6236dae4SAndroid Build Coastguard Worker 
1793*6236dae4SAndroid Build Coastguard Worker     /* The path sent to the proxy is in fact the entire URL. But if the remote
1794*6236dae4SAndroid Build Coastguard Worker        host is a IDN-name, we must make sure that the request we produce only
1795*6236dae4SAndroid Build Coastguard Worker        uses the encoded hostname! */
1796*6236dae4SAndroid Build Coastguard Worker 
1797*6236dae4SAndroid Build Coastguard Worker     /* and no fragment part */
1798*6236dae4SAndroid Build Coastguard Worker     CURLUcode uc;
1799*6236dae4SAndroid Build Coastguard Worker     char *url;
1800*6236dae4SAndroid Build Coastguard Worker     CURLU *h = curl_url_dup(data->state.uh);
1801*6236dae4SAndroid Build Coastguard Worker     if(!h)
1802*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1803*6236dae4SAndroid Build Coastguard Worker 
1804*6236dae4SAndroid Build Coastguard Worker     if(conn->host.dispname != conn->host.name) {
1805*6236dae4SAndroid Build Coastguard Worker       uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
1806*6236dae4SAndroid Build Coastguard Worker       if(uc) {
1807*6236dae4SAndroid Build Coastguard Worker         curl_url_cleanup(h);
1808*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1809*6236dae4SAndroid Build Coastguard Worker       }
1810*6236dae4SAndroid Build Coastguard Worker     }
1811*6236dae4SAndroid Build Coastguard Worker     uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
1812*6236dae4SAndroid Build Coastguard Worker     if(uc) {
1813*6236dae4SAndroid Build Coastguard Worker       curl_url_cleanup(h);
1814*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1815*6236dae4SAndroid Build Coastguard Worker     }
1816*6236dae4SAndroid Build Coastguard Worker 
1817*6236dae4SAndroid Build Coastguard Worker     if(strcasecompare("http", data->state.up.scheme)) {
1818*6236dae4SAndroid Build Coastguard Worker       /* when getting HTTP, we do not want the userinfo the URL */
1819*6236dae4SAndroid Build Coastguard Worker       uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
1820*6236dae4SAndroid Build Coastguard Worker       if(uc) {
1821*6236dae4SAndroid Build Coastguard Worker         curl_url_cleanup(h);
1822*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1823*6236dae4SAndroid Build Coastguard Worker       }
1824*6236dae4SAndroid Build Coastguard Worker       uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
1825*6236dae4SAndroid Build Coastguard Worker       if(uc) {
1826*6236dae4SAndroid Build Coastguard Worker         curl_url_cleanup(h);
1827*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1828*6236dae4SAndroid Build Coastguard Worker       }
1829*6236dae4SAndroid Build Coastguard Worker     }
1830*6236dae4SAndroid Build Coastguard Worker     /* Extract the URL to use in the request. */
1831*6236dae4SAndroid Build Coastguard Worker     uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
1832*6236dae4SAndroid Build Coastguard Worker     if(uc) {
1833*6236dae4SAndroid Build Coastguard Worker       curl_url_cleanup(h);
1834*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
1835*6236dae4SAndroid Build Coastguard Worker     }
1836*6236dae4SAndroid Build Coastguard Worker 
1837*6236dae4SAndroid Build Coastguard Worker     curl_url_cleanup(h);
1838*6236dae4SAndroid Build Coastguard Worker 
1839*6236dae4SAndroid Build Coastguard Worker     /* target or URL */
1840*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_add(r, data->set.str[STRING_TARGET] ?
1841*6236dae4SAndroid Build Coastguard Worker       data->set.str[STRING_TARGET] : url);
1842*6236dae4SAndroid Build Coastguard Worker     free(url);
1843*6236dae4SAndroid Build Coastguard Worker     if(result)
1844*6236dae4SAndroid Build Coastguard Worker       return (result);
1845*6236dae4SAndroid Build Coastguard Worker 
1846*6236dae4SAndroid Build Coastguard Worker     if(strcasecompare("ftp", data->state.up.scheme)) {
1847*6236dae4SAndroid Build Coastguard Worker       if(data->set.proxy_transfer_mode) {
1848*6236dae4SAndroid Build Coastguard Worker         /* when doing ftp, append ;type=<a|i> if not present */
1849*6236dae4SAndroid Build Coastguard Worker         char *type = strstr(path, ";type=");
1850*6236dae4SAndroid Build Coastguard Worker         if(type && type[6] && type[7] == 0) {
1851*6236dae4SAndroid Build Coastguard Worker           switch(Curl_raw_toupper(type[6])) {
1852*6236dae4SAndroid Build Coastguard Worker           case 'A':
1853*6236dae4SAndroid Build Coastguard Worker           case 'D':
1854*6236dae4SAndroid Build Coastguard Worker           case 'I':
1855*6236dae4SAndroid Build Coastguard Worker             break;
1856*6236dae4SAndroid Build Coastguard Worker           default:
1857*6236dae4SAndroid Build Coastguard Worker             type = NULL;
1858*6236dae4SAndroid Build Coastguard Worker           }
1859*6236dae4SAndroid Build Coastguard Worker         }
1860*6236dae4SAndroid Build Coastguard Worker         if(!type) {
1861*6236dae4SAndroid Build Coastguard Worker           result = Curl_dyn_addf(r, ";type=%c",
1862*6236dae4SAndroid Build Coastguard Worker                                  data->state.prefer_ascii ? 'a' : 'i');
1863*6236dae4SAndroid Build Coastguard Worker           if(result)
1864*6236dae4SAndroid Build Coastguard Worker             return result;
1865*6236dae4SAndroid Build Coastguard Worker         }
1866*6236dae4SAndroid Build Coastguard Worker       }
1867*6236dae4SAndroid Build Coastguard Worker     }
1868*6236dae4SAndroid Build Coastguard Worker   }
1869*6236dae4SAndroid Build Coastguard Worker 
1870*6236dae4SAndroid Build Coastguard Worker   else
1871*6236dae4SAndroid Build Coastguard Worker #else
1872*6236dae4SAndroid Build Coastguard Worker     (void)conn; /* not used in disabled-proxy builds */
1873*6236dae4SAndroid Build Coastguard Worker #endif
1874*6236dae4SAndroid Build Coastguard Worker   {
1875*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_add(r, path);
1876*6236dae4SAndroid Build Coastguard Worker     if(result)
1877*6236dae4SAndroid Build Coastguard Worker       return result;
1878*6236dae4SAndroid Build Coastguard Worker     if(query)
1879*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addf(r, "?%s", query);
1880*6236dae4SAndroid Build Coastguard Worker   }
1881*6236dae4SAndroid Build Coastguard Worker 
1882*6236dae4SAndroid Build Coastguard Worker   return result;
1883*6236dae4SAndroid Build Coastguard Worker }
1884*6236dae4SAndroid Build Coastguard Worker 
1885*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
set_post_reader(struct Curl_easy * data,Curl_HttpReq httpreq)1886*6236dae4SAndroid Build Coastguard Worker static CURLcode set_post_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
1887*6236dae4SAndroid Build Coastguard Worker {
1888*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1889*6236dae4SAndroid Build Coastguard Worker 
1890*6236dae4SAndroid Build Coastguard Worker   switch(httpreq) {
1891*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_MIME
1892*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_MIME:
1893*6236dae4SAndroid Build Coastguard Worker     data->state.mimepost = &data->set.mimepost;
1894*6236dae4SAndroid Build Coastguard Worker     break;
1895*6236dae4SAndroid Build Coastguard Worker #endif
1896*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_FORM_API
1897*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_FORM:
1898*6236dae4SAndroid Build Coastguard Worker     /* Convert the form structure into a mime structure, then keep
1899*6236dae4SAndroid Build Coastguard Worker        the conversion */
1900*6236dae4SAndroid Build Coastguard Worker     if(!data->state.formp) {
1901*6236dae4SAndroid Build Coastguard Worker       data->state.formp = calloc(1, sizeof(curl_mimepart));
1902*6236dae4SAndroid Build Coastguard Worker       if(!data->state.formp)
1903*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1904*6236dae4SAndroid Build Coastguard Worker       Curl_mime_cleanpart(data->state.formp);
1905*6236dae4SAndroid Build Coastguard Worker       result = Curl_getformdata(data, data->state.formp, data->set.httppost,
1906*6236dae4SAndroid Build Coastguard Worker                                 data->state.fread_func);
1907*6236dae4SAndroid Build Coastguard Worker       if(result) {
1908*6236dae4SAndroid Build Coastguard Worker         Curl_safefree(data->state.formp);
1909*6236dae4SAndroid Build Coastguard Worker         return result;
1910*6236dae4SAndroid Build Coastguard Worker       }
1911*6236dae4SAndroid Build Coastguard Worker       data->state.mimepost = data->state.formp;
1912*6236dae4SAndroid Build Coastguard Worker     }
1913*6236dae4SAndroid Build Coastguard Worker     break;
1914*6236dae4SAndroid Build Coastguard Worker #endif
1915*6236dae4SAndroid Build Coastguard Worker   default:
1916*6236dae4SAndroid Build Coastguard Worker     data->state.mimepost = NULL;
1917*6236dae4SAndroid Build Coastguard Worker     break;
1918*6236dae4SAndroid Build Coastguard Worker   }
1919*6236dae4SAndroid Build Coastguard Worker 
1920*6236dae4SAndroid Build Coastguard Worker   switch(httpreq) {
1921*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_FORM:
1922*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_MIME:
1923*6236dae4SAndroid Build Coastguard Worker     /* This is form posting using mime data. */
1924*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_MIME
1925*6236dae4SAndroid Build Coastguard Worker     if(data->state.mimepost) {
1926*6236dae4SAndroid Build Coastguard Worker       const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
1927*6236dae4SAndroid Build Coastguard Worker 
1928*6236dae4SAndroid Build Coastguard Worker       /* Read and seek body only. */
1929*6236dae4SAndroid Build Coastguard Worker       data->state.mimepost->flags |= MIME_BODY_ONLY;
1930*6236dae4SAndroid Build Coastguard Worker 
1931*6236dae4SAndroid Build Coastguard Worker       /* Prepare the mime structure headers & set content type. */
1932*6236dae4SAndroid Build Coastguard Worker 
1933*6236dae4SAndroid Build Coastguard Worker       if(cthdr)
1934*6236dae4SAndroid Build Coastguard Worker         for(cthdr += 13; *cthdr == ' '; cthdr++)
1935*6236dae4SAndroid Build Coastguard Worker           ;
1936*6236dae4SAndroid Build Coastguard Worker       else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
1937*6236dae4SAndroid Build Coastguard Worker         cthdr = "multipart/form-data";
1938*6236dae4SAndroid Build Coastguard Worker 
1939*6236dae4SAndroid Build Coastguard Worker       curl_mime_headers(data->state.mimepost, data->set.headers, 0);
1940*6236dae4SAndroid Build Coastguard Worker       result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
1941*6236dae4SAndroid Build Coastguard Worker                                          NULL, MIMESTRATEGY_FORM);
1942*6236dae4SAndroid Build Coastguard Worker       if(result)
1943*6236dae4SAndroid Build Coastguard Worker         return result;
1944*6236dae4SAndroid Build Coastguard Worker       curl_mime_headers(data->state.mimepost, NULL, 0);
1945*6236dae4SAndroid Build Coastguard Worker       result = Curl_creader_set_mime(data, data->state.mimepost);
1946*6236dae4SAndroid Build Coastguard Worker       if(result)
1947*6236dae4SAndroid Build Coastguard Worker         return result;
1948*6236dae4SAndroid Build Coastguard Worker     }
1949*6236dae4SAndroid Build Coastguard Worker     else
1950*6236dae4SAndroid Build Coastguard Worker #endif
1951*6236dae4SAndroid Build Coastguard Worker     {
1952*6236dae4SAndroid Build Coastguard Worker       result = Curl_creader_set_null(data);
1953*6236dae4SAndroid Build Coastguard Worker     }
1954*6236dae4SAndroid Build Coastguard Worker     data->state.infilesize = Curl_creader_total_length(data);
1955*6236dae4SAndroid Build Coastguard Worker     return result;
1956*6236dae4SAndroid Build Coastguard Worker 
1957*6236dae4SAndroid Build Coastguard Worker   default:
1958*6236dae4SAndroid Build Coastguard Worker     return Curl_creader_set_null(data);
1959*6236dae4SAndroid Build Coastguard Worker   }
1960*6236dae4SAndroid Build Coastguard Worker   /* never reached */
1961*6236dae4SAndroid Build Coastguard Worker }
1962*6236dae4SAndroid Build Coastguard Worker #endif
1963*6236dae4SAndroid Build Coastguard Worker 
set_reader(struct Curl_easy * data,Curl_HttpReq httpreq)1964*6236dae4SAndroid Build Coastguard Worker static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
1965*6236dae4SAndroid Build Coastguard Worker {
1966*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
1967*6236dae4SAndroid Build Coastguard Worker   curl_off_t postsize = data->state.infilesize;
1968*6236dae4SAndroid Build Coastguard Worker 
1969*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data->conn);
1970*6236dae4SAndroid Build Coastguard Worker 
1971*6236dae4SAndroid Build Coastguard Worker   if(data->req.authneg) {
1972*6236dae4SAndroid Build Coastguard Worker     return Curl_creader_set_null(data);
1973*6236dae4SAndroid Build Coastguard Worker   }
1974*6236dae4SAndroid Build Coastguard Worker 
1975*6236dae4SAndroid Build Coastguard Worker   switch(httpreq) {
1976*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_PUT: /* Let's PUT the data to the server! */
1977*6236dae4SAndroid Build Coastguard Worker     return postsize ? Curl_creader_set_fread(data, postsize) :
1978*6236dae4SAndroid Build Coastguard Worker       Curl_creader_set_null(data);
1979*6236dae4SAndroid Build Coastguard Worker 
1980*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
1981*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_FORM:
1982*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_MIME:
1983*6236dae4SAndroid Build Coastguard Worker     return set_post_reader(data, httpreq);
1984*6236dae4SAndroid Build Coastguard Worker #endif
1985*6236dae4SAndroid Build Coastguard Worker 
1986*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST:
1987*6236dae4SAndroid Build Coastguard Worker     /* this is the simple POST, using x-www-form-urlencoded style */
1988*6236dae4SAndroid Build Coastguard Worker     /* the size of the post body */
1989*6236dae4SAndroid Build Coastguard Worker     if(!postsize) {
1990*6236dae4SAndroid Build Coastguard Worker       result = Curl_creader_set_null(data);
1991*6236dae4SAndroid Build Coastguard Worker     }
1992*6236dae4SAndroid Build Coastguard Worker     else if(data->set.postfields) {
1993*6236dae4SAndroid Build Coastguard Worker       if(postsize > 0)
1994*6236dae4SAndroid Build Coastguard Worker         result = Curl_creader_set_buf(data, data->set.postfields,
1995*6236dae4SAndroid Build Coastguard Worker                                       (size_t)postsize);
1996*6236dae4SAndroid Build Coastguard Worker       else
1997*6236dae4SAndroid Build Coastguard Worker         result = Curl_creader_set_null(data);
1998*6236dae4SAndroid Build Coastguard Worker     }
1999*6236dae4SAndroid Build Coastguard Worker     else {
2000*6236dae4SAndroid Build Coastguard Worker       /* we read the bytes from the callback. In case "chunked" encoding
2001*6236dae4SAndroid Build Coastguard Worker        * is forced by the application, we disregard `postsize`. This is
2002*6236dae4SAndroid Build Coastguard Worker        * a backward compatibility decision to earlier versions where
2003*6236dae4SAndroid Build Coastguard Worker        * chunking disregarded this. See issue #13229. */
2004*6236dae4SAndroid Build Coastguard Worker       bool chunked = FALSE;
2005*6236dae4SAndroid Build Coastguard Worker       char *ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
2006*6236dae4SAndroid Build Coastguard Worker       if(ptr) {
2007*6236dae4SAndroid Build Coastguard Worker         /* Some kind of TE is requested, check if 'chunked' is chosen */
2008*6236dae4SAndroid Build Coastguard Worker         chunked = Curl_compareheader(ptr, STRCONST("Transfer-Encoding:"),
2009*6236dae4SAndroid Build Coastguard Worker                                      STRCONST("chunked"));
2010*6236dae4SAndroid Build Coastguard Worker       }
2011*6236dae4SAndroid Build Coastguard Worker       result = Curl_creader_set_fread(data, chunked ? -1 : postsize);
2012*6236dae4SAndroid Build Coastguard Worker     }
2013*6236dae4SAndroid Build Coastguard Worker     return result;
2014*6236dae4SAndroid Build Coastguard Worker 
2015*6236dae4SAndroid Build Coastguard Worker   default:
2016*6236dae4SAndroid Build Coastguard Worker     /* HTTP GET/HEAD download, has no body, needs no Content-Length */
2017*6236dae4SAndroid Build Coastguard Worker     data->state.infilesize = 0;
2018*6236dae4SAndroid Build Coastguard Worker     return Curl_creader_set_null(data);
2019*6236dae4SAndroid Build Coastguard Worker   }
2020*6236dae4SAndroid Build Coastguard Worker   /* not reached */
2021*6236dae4SAndroid Build Coastguard Worker }
2022*6236dae4SAndroid Build Coastguard Worker 
http_resume(struct Curl_easy * data,Curl_HttpReq httpreq)2023*6236dae4SAndroid Build Coastguard Worker static CURLcode http_resume(struct Curl_easy *data, Curl_HttpReq httpreq)
2024*6236dae4SAndroid Build Coastguard Worker {
2025*6236dae4SAndroid Build Coastguard Worker   if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
2026*6236dae4SAndroid Build Coastguard Worker      data->state.resume_from) {
2027*6236dae4SAndroid Build Coastguard Worker     /**********************************************************************
2028*6236dae4SAndroid Build Coastguard Worker      * Resuming upload in HTTP means that we PUT or POST and that we have
2029*6236dae4SAndroid Build Coastguard Worker      * got a resume_from value set. The resume value has already created
2030*6236dae4SAndroid Build Coastguard Worker      * a Range: header that will be passed along. We need to "fast forward"
2031*6236dae4SAndroid Build Coastguard Worker      * the file the given number of bytes and decrease the assume upload
2032*6236dae4SAndroid Build Coastguard Worker      * file size before we continue this venture in the dark lands of HTTP.
2033*6236dae4SAndroid Build Coastguard Worker      * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
2034*6236dae4SAndroid Build Coastguard Worker      *********************************************************************/
2035*6236dae4SAndroid Build Coastguard Worker 
2036*6236dae4SAndroid Build Coastguard Worker     if(data->state.resume_from < 0) {
2037*6236dae4SAndroid Build Coastguard Worker       /*
2038*6236dae4SAndroid Build Coastguard Worker        * This is meant to get the size of the present remote-file by itself.
2039*6236dae4SAndroid Build Coastguard Worker        * We do not support this now. Bail out!
2040*6236dae4SAndroid Build Coastguard Worker        */
2041*6236dae4SAndroid Build Coastguard Worker       data->state.resume_from = 0;
2042*6236dae4SAndroid Build Coastguard Worker     }
2043*6236dae4SAndroid Build Coastguard Worker 
2044*6236dae4SAndroid Build Coastguard Worker     if(data->state.resume_from && !data->req.authneg) {
2045*6236dae4SAndroid Build Coastguard Worker       /* only act on the first request */
2046*6236dae4SAndroid Build Coastguard Worker       CURLcode result;
2047*6236dae4SAndroid Build Coastguard Worker       result = Curl_creader_resume_from(data, data->state.resume_from);
2048*6236dae4SAndroid Build Coastguard Worker       if(result) {
2049*6236dae4SAndroid Build Coastguard Worker         failf(data, "Unable to resume from offset %" FMT_OFF_T,
2050*6236dae4SAndroid Build Coastguard Worker               data->state.resume_from);
2051*6236dae4SAndroid Build Coastguard Worker         return result;
2052*6236dae4SAndroid Build Coastguard Worker       }
2053*6236dae4SAndroid Build Coastguard Worker     }
2054*6236dae4SAndroid Build Coastguard Worker   }
2055*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2056*6236dae4SAndroid Build Coastguard Worker }
2057*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_set_reader(struct Curl_easy * data,Curl_HttpReq httpreq,const char ** tep)2058*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_req_set_reader(struct Curl_easy *data,
2059*6236dae4SAndroid Build Coastguard Worker                                   Curl_HttpReq httpreq,
2060*6236dae4SAndroid Build Coastguard Worker                                   const char **tep)
2061*6236dae4SAndroid Build Coastguard Worker {
2062*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2063*6236dae4SAndroid Build Coastguard Worker   const char *ptr;
2064*6236dae4SAndroid Build Coastguard Worker 
2065*6236dae4SAndroid Build Coastguard Worker   result = set_reader(data, httpreq);
2066*6236dae4SAndroid Build Coastguard Worker   if(result)
2067*6236dae4SAndroid Build Coastguard Worker     return result;
2068*6236dae4SAndroid Build Coastguard Worker 
2069*6236dae4SAndroid Build Coastguard Worker   result = http_resume(data, httpreq);
2070*6236dae4SAndroid Build Coastguard Worker   if(result)
2071*6236dae4SAndroid Build Coastguard Worker     return result;
2072*6236dae4SAndroid Build Coastguard Worker 
2073*6236dae4SAndroid Build Coastguard Worker   ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
2074*6236dae4SAndroid Build Coastguard Worker   if(ptr) {
2075*6236dae4SAndroid Build Coastguard Worker     /* Some kind of TE is requested, check if 'chunked' is chosen */
2076*6236dae4SAndroid Build Coastguard Worker     data->req.upload_chunky =
2077*6236dae4SAndroid Build Coastguard Worker       Curl_compareheader(ptr,
2078*6236dae4SAndroid Build Coastguard Worker                          STRCONST("Transfer-Encoding:"), STRCONST("chunked"));
2079*6236dae4SAndroid Build Coastguard Worker     if(data->req.upload_chunky &&
2080*6236dae4SAndroid Build Coastguard Worker        Curl_use_http_1_1plus(data, data->conn) &&
2081*6236dae4SAndroid Build Coastguard Worker        (data->conn->httpversion >= 20)) {
2082*6236dae4SAndroid Build Coastguard Worker        infof(data, "suppressing chunked transfer encoding on connection "
2083*6236dae4SAndroid Build Coastguard Worker              "using HTTP version 2 or higher");
2084*6236dae4SAndroid Build Coastguard Worker        data->req.upload_chunky = FALSE;
2085*6236dae4SAndroid Build Coastguard Worker     }
2086*6236dae4SAndroid Build Coastguard Worker   }
2087*6236dae4SAndroid Build Coastguard Worker   else {
2088*6236dae4SAndroid Build Coastguard Worker     curl_off_t req_clen = Curl_creader_total_length(data);
2089*6236dae4SAndroid Build Coastguard Worker 
2090*6236dae4SAndroid Build Coastguard Worker     if(req_clen < 0) {
2091*6236dae4SAndroid Build Coastguard Worker       /* indeterminate request content length */
2092*6236dae4SAndroid Build Coastguard Worker       if(Curl_use_http_1_1plus(data, data->conn)) {
2093*6236dae4SAndroid Build Coastguard Worker         /* On HTTP/1.1, enable chunked, on HTTP/2 and later we do not
2094*6236dae4SAndroid Build Coastguard Worker          * need it */
2095*6236dae4SAndroid Build Coastguard Worker         data->req.upload_chunky = (data->conn->httpversion < 20);
2096*6236dae4SAndroid Build Coastguard Worker       }
2097*6236dae4SAndroid Build Coastguard Worker       else {
2098*6236dae4SAndroid Build Coastguard Worker         failf(data, "Chunky upload is not supported by HTTP 1.0");
2099*6236dae4SAndroid Build Coastguard Worker         return CURLE_UPLOAD_FAILED;
2100*6236dae4SAndroid Build Coastguard Worker       }
2101*6236dae4SAndroid Build Coastguard Worker     }
2102*6236dae4SAndroid Build Coastguard Worker     else {
2103*6236dae4SAndroid Build Coastguard Worker       /* else, no chunky upload */
2104*6236dae4SAndroid Build Coastguard Worker       data->req.upload_chunky = FALSE;
2105*6236dae4SAndroid Build Coastguard Worker     }
2106*6236dae4SAndroid Build Coastguard Worker 
2107*6236dae4SAndroid Build Coastguard Worker     if(data->req.upload_chunky)
2108*6236dae4SAndroid Build Coastguard Worker       *tep = "Transfer-Encoding: chunked\r\n";
2109*6236dae4SAndroid Build Coastguard Worker   }
2110*6236dae4SAndroid Build Coastguard Worker   return result;
2111*6236dae4SAndroid Build Coastguard Worker }
2112*6236dae4SAndroid Build Coastguard Worker 
addexpect(struct Curl_easy * data,struct dynbuf * r,bool * announced_exp100)2113*6236dae4SAndroid Build Coastguard Worker static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
2114*6236dae4SAndroid Build Coastguard Worker                           bool *announced_exp100)
2115*6236dae4SAndroid Build Coastguard Worker {
2116*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
2117*6236dae4SAndroid Build Coastguard Worker   char *ptr;
2118*6236dae4SAndroid Build Coastguard Worker 
2119*6236dae4SAndroid Build Coastguard Worker   *announced_exp100 = FALSE;
2120*6236dae4SAndroid Build Coastguard Worker   /* Avoid Expect: 100-continue if Upgrade: is used */
2121*6236dae4SAndroid Build Coastguard Worker   if(data->req.upgr101 != UPGR101_INIT)
2122*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
2123*6236dae4SAndroid Build Coastguard Worker 
2124*6236dae4SAndroid Build Coastguard Worker   /* For really small puts we do not use Expect: headers at all, and for
2125*6236dae4SAndroid Build Coastguard Worker      the somewhat bigger ones we allow the app to disable it. Just make
2126*6236dae4SAndroid Build Coastguard Worker      sure that the expect100header is always set to the preferred value
2127*6236dae4SAndroid Build Coastguard Worker      here. */
2128*6236dae4SAndroid Build Coastguard Worker   ptr = Curl_checkheaders(data, STRCONST("Expect"));
2129*6236dae4SAndroid Build Coastguard Worker   if(ptr) {
2130*6236dae4SAndroid Build Coastguard Worker     *announced_exp100 =
2131*6236dae4SAndroid Build Coastguard Worker       Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
2132*6236dae4SAndroid Build Coastguard Worker   }
2133*6236dae4SAndroid Build Coastguard Worker   else if(!data->state.disableexpect &&
2134*6236dae4SAndroid Build Coastguard Worker           Curl_use_http_1_1plus(data, data->conn) &&
2135*6236dae4SAndroid Build Coastguard Worker           (data->conn->httpversion < 20)) {
2136*6236dae4SAndroid Build Coastguard Worker     /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
2137*6236dae4SAndroid Build Coastguard Worker        Expect: 100-continue to the headers which actually speeds up post
2138*6236dae4SAndroid Build Coastguard Worker        operations (as there is one packet coming back from the web server) */
2139*6236dae4SAndroid Build Coastguard Worker     curl_off_t client_len = Curl_creader_client_length(data);
2140*6236dae4SAndroid Build Coastguard Worker     if(client_len > EXPECT_100_THRESHOLD || client_len < 0) {
2141*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addn(r, STRCONST("Expect: 100-continue\r\n"));
2142*6236dae4SAndroid Build Coastguard Worker       if(result)
2143*6236dae4SAndroid Build Coastguard Worker         return result;
2144*6236dae4SAndroid Build Coastguard Worker       *announced_exp100 = TRUE;
2145*6236dae4SAndroid Build Coastguard Worker     }
2146*6236dae4SAndroid Build Coastguard Worker   }
2147*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2148*6236dae4SAndroid Build Coastguard Worker }
2149*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_complete(struct Curl_easy * data,struct dynbuf * r,Curl_HttpReq httpreq)2150*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_req_complete(struct Curl_easy *data,
2151*6236dae4SAndroid Build Coastguard Worker                                 struct dynbuf *r, Curl_HttpReq httpreq)
2152*6236dae4SAndroid Build Coastguard Worker {
2153*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2154*6236dae4SAndroid Build Coastguard Worker   curl_off_t req_clen;
2155*6236dae4SAndroid Build Coastguard Worker   bool announced_exp100 = FALSE;
2156*6236dae4SAndroid Build Coastguard Worker 
2157*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data->conn);
2158*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
2159*6236dae4SAndroid Build Coastguard Worker   if(data->req.upload_chunky) {
2160*6236dae4SAndroid Build Coastguard Worker     result = Curl_httpchunk_add_reader(data);
2161*6236dae4SAndroid Build Coastguard Worker     if(result)
2162*6236dae4SAndroid Build Coastguard Worker       return result;
2163*6236dae4SAndroid Build Coastguard Worker   }
2164*6236dae4SAndroid Build Coastguard Worker #endif
2165*6236dae4SAndroid Build Coastguard Worker 
2166*6236dae4SAndroid Build Coastguard Worker   /* Get the request body length that has been set up */
2167*6236dae4SAndroid Build Coastguard Worker   req_clen = Curl_creader_total_length(data);
2168*6236dae4SAndroid Build Coastguard Worker   switch(httpreq) {
2169*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_PUT:
2170*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST:
2171*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
2172*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_FORM:
2173*6236dae4SAndroid Build Coastguard Worker   case HTTPREQ_POST_MIME:
2174*6236dae4SAndroid Build Coastguard Worker #endif
2175*6236dae4SAndroid Build Coastguard Worker     /* We only set Content-Length and allow a custom Content-Length if
2176*6236dae4SAndroid Build Coastguard Worker        we do not upload data chunked, as RFC2616 forbids us to set both
2177*6236dae4SAndroid Build Coastguard Worker        kinds of headers (Transfer-Encoding: chunked and Content-Length).
2178*6236dae4SAndroid Build Coastguard Worker        We do not override a custom "Content-Length" header, but during
2179*6236dae4SAndroid Build Coastguard Worker        authentication negotiation that header is suppressed.
2180*6236dae4SAndroid Build Coastguard Worker      */
2181*6236dae4SAndroid Build Coastguard Worker     if(req_clen >= 0 && !data->req.upload_chunky &&
2182*6236dae4SAndroid Build Coastguard Worker        (data->req.authneg ||
2183*6236dae4SAndroid Build Coastguard Worker         !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2184*6236dae4SAndroid Build Coastguard Worker       /* we allow replacing this header if not during auth negotiation,
2185*6236dae4SAndroid Build Coastguard Worker          although it is not very wise to actually set your own */
2186*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addf(r, "Content-Length: %" FMT_OFF_T "\r\n",
2187*6236dae4SAndroid Build Coastguard Worker                              req_clen);
2188*6236dae4SAndroid Build Coastguard Worker     }
2189*6236dae4SAndroid Build Coastguard Worker     if(result)
2190*6236dae4SAndroid Build Coastguard Worker       goto out;
2191*6236dae4SAndroid Build Coastguard Worker 
2192*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_MIME
2193*6236dae4SAndroid Build Coastguard Worker     /* Output mime-generated headers. */
2194*6236dae4SAndroid Build Coastguard Worker     if(data->state.mimepost &&
2195*6236dae4SAndroid Build Coastguard Worker        ((httpreq == HTTPREQ_POST_FORM) || (httpreq == HTTPREQ_POST_MIME))) {
2196*6236dae4SAndroid Build Coastguard Worker       struct curl_slist *hdr;
2197*6236dae4SAndroid Build Coastguard Worker 
2198*6236dae4SAndroid Build Coastguard Worker       for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
2199*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
2200*6236dae4SAndroid Build Coastguard Worker         if(result)
2201*6236dae4SAndroid Build Coastguard Worker           goto out;
2202*6236dae4SAndroid Build Coastguard Worker       }
2203*6236dae4SAndroid Build Coastguard Worker     }
2204*6236dae4SAndroid Build Coastguard Worker #endif
2205*6236dae4SAndroid Build Coastguard Worker     if(httpreq == HTTPREQ_POST) {
2206*6236dae4SAndroid Build Coastguard Worker       if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
2207*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_addn(r, STRCONST("Content-Type: application/"
2208*6236dae4SAndroid Build Coastguard Worker                                            "x-www-form-urlencoded\r\n"));
2209*6236dae4SAndroid Build Coastguard Worker         if(result)
2210*6236dae4SAndroid Build Coastguard Worker           goto out;
2211*6236dae4SAndroid Build Coastguard Worker       }
2212*6236dae4SAndroid Build Coastguard Worker     }
2213*6236dae4SAndroid Build Coastguard Worker     result = addexpect(data, r, &announced_exp100);
2214*6236dae4SAndroid Build Coastguard Worker     if(result)
2215*6236dae4SAndroid Build Coastguard Worker       goto out;
2216*6236dae4SAndroid Build Coastguard Worker     break;
2217*6236dae4SAndroid Build Coastguard Worker   default:
2218*6236dae4SAndroid Build Coastguard Worker     break;
2219*6236dae4SAndroid Build Coastguard Worker   }
2220*6236dae4SAndroid Build Coastguard Worker 
2221*6236dae4SAndroid Build Coastguard Worker   /* end of headers */
2222*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_addn(r, STRCONST("\r\n"));
2223*6236dae4SAndroid Build Coastguard Worker   if(!result) {
2224*6236dae4SAndroid Build Coastguard Worker     Curl_pgrsSetUploadSize(data, req_clen);
2225*6236dae4SAndroid Build Coastguard Worker     if(announced_exp100)
2226*6236dae4SAndroid Build Coastguard Worker       result = http_exp100_add_reader(data);
2227*6236dae4SAndroid Build Coastguard Worker   }
2228*6236dae4SAndroid Build Coastguard Worker 
2229*6236dae4SAndroid Build Coastguard Worker out:
2230*6236dae4SAndroid Build Coastguard Worker   if(!result) {
2231*6236dae4SAndroid Build Coastguard Worker     /* setup variables for the upcoming transfer */
2232*6236dae4SAndroid Build Coastguard Worker     Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
2233*6236dae4SAndroid Build Coastguard Worker   }
2234*6236dae4SAndroid Build Coastguard Worker   return result;
2235*6236dae4SAndroid Build Coastguard Worker }
2236*6236dae4SAndroid Build Coastguard Worker 
2237*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_COOKIES)
2238*6236dae4SAndroid Build Coastguard Worker 
Curl_http_cookies(struct Curl_easy * data,struct connectdata * conn,struct dynbuf * r)2239*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_cookies(struct Curl_easy *data,
2240*6236dae4SAndroid Build Coastguard Worker                            struct connectdata *conn,
2241*6236dae4SAndroid Build Coastguard Worker                            struct dynbuf *r)
2242*6236dae4SAndroid Build Coastguard Worker {
2243*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2244*6236dae4SAndroid Build Coastguard Worker   char *addcookies = NULL;
2245*6236dae4SAndroid Build Coastguard Worker   bool linecap = FALSE;
2246*6236dae4SAndroid Build Coastguard Worker   if(data->set.str[STRING_COOKIE] &&
2247*6236dae4SAndroid Build Coastguard Worker      !Curl_checkheaders(data, STRCONST("Cookie")))
2248*6236dae4SAndroid Build Coastguard Worker     addcookies = data->set.str[STRING_COOKIE];
2249*6236dae4SAndroid Build Coastguard Worker 
2250*6236dae4SAndroid Build Coastguard Worker   if(data->cookies || addcookies) {
2251*6236dae4SAndroid Build Coastguard Worker     struct Curl_llist list;
2252*6236dae4SAndroid Build Coastguard Worker     int count = 0;
2253*6236dae4SAndroid Build Coastguard Worker     int rc = 1;
2254*6236dae4SAndroid Build Coastguard Worker 
2255*6236dae4SAndroid Build Coastguard Worker     if(data->cookies && data->state.cookie_engine) {
2256*6236dae4SAndroid Build Coastguard Worker       const char *host = data->state.aptr.cookiehost ?
2257*6236dae4SAndroid Build Coastguard Worker         data->state.aptr.cookiehost : conn->host.name;
2258*6236dae4SAndroid Build Coastguard Worker       const bool secure_context =
2259*6236dae4SAndroid Build Coastguard Worker         conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
2260*6236dae4SAndroid Build Coastguard Worker         strcasecompare("localhost", host) ||
2261*6236dae4SAndroid Build Coastguard Worker         !strcmp(host, "127.0.0.1") ||
2262*6236dae4SAndroid Build Coastguard Worker         !strcmp(host, "::1");
2263*6236dae4SAndroid Build Coastguard Worker       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2264*6236dae4SAndroid Build Coastguard Worker       rc = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
2265*6236dae4SAndroid Build Coastguard Worker                                secure_context, &list);
2266*6236dae4SAndroid Build Coastguard Worker       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2267*6236dae4SAndroid Build Coastguard Worker     }
2268*6236dae4SAndroid Build Coastguard Worker     if(!rc) {
2269*6236dae4SAndroid Build Coastguard Worker       struct Curl_llist_node *n;
2270*6236dae4SAndroid Build Coastguard Worker       size_t clen = 8; /* hold the size of the generated Cookie: header */
2271*6236dae4SAndroid Build Coastguard Worker 
2272*6236dae4SAndroid Build Coastguard Worker       /* loop through all cookies that matched */
2273*6236dae4SAndroid Build Coastguard Worker       for(n = Curl_llist_head(&list); n; n = Curl_node_next(n)) {
2274*6236dae4SAndroid Build Coastguard Worker         struct Cookie *co = Curl_node_elem(n);
2275*6236dae4SAndroid Build Coastguard Worker         if(co->value) {
2276*6236dae4SAndroid Build Coastguard Worker           size_t add;
2277*6236dae4SAndroid Build Coastguard Worker           if(!count) {
2278*6236dae4SAndroid Build Coastguard Worker             result = Curl_dyn_addn(r, STRCONST("Cookie: "));
2279*6236dae4SAndroid Build Coastguard Worker             if(result)
2280*6236dae4SAndroid Build Coastguard Worker               break;
2281*6236dae4SAndroid Build Coastguard Worker           }
2282*6236dae4SAndroid Build Coastguard Worker           add = strlen(co->name) + strlen(co->value) + 1;
2283*6236dae4SAndroid Build Coastguard Worker           if(clen + add >= MAX_COOKIE_HEADER_LEN) {
2284*6236dae4SAndroid Build Coastguard Worker             infof(data, "Restricted outgoing cookies due to header size, "
2285*6236dae4SAndroid Build Coastguard Worker                   "'%s' not sent", co->name);
2286*6236dae4SAndroid Build Coastguard Worker             linecap = TRUE;
2287*6236dae4SAndroid Build Coastguard Worker             break;
2288*6236dae4SAndroid Build Coastguard Worker           }
2289*6236dae4SAndroid Build Coastguard Worker           result = Curl_dyn_addf(r, "%s%s=%s", count ? "; " : "",
2290*6236dae4SAndroid Build Coastguard Worker                                  co->name, co->value);
2291*6236dae4SAndroid Build Coastguard Worker           if(result)
2292*6236dae4SAndroid Build Coastguard Worker             break;
2293*6236dae4SAndroid Build Coastguard Worker           clen += add + (count ? 2 : 0);
2294*6236dae4SAndroid Build Coastguard Worker           count++;
2295*6236dae4SAndroid Build Coastguard Worker         }
2296*6236dae4SAndroid Build Coastguard Worker       }
2297*6236dae4SAndroid Build Coastguard Worker       Curl_llist_destroy(&list, NULL);
2298*6236dae4SAndroid Build Coastguard Worker     }
2299*6236dae4SAndroid Build Coastguard Worker     if(addcookies && !result && !linecap) {
2300*6236dae4SAndroid Build Coastguard Worker       if(!count)
2301*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_addn(r, STRCONST("Cookie: "));
2302*6236dae4SAndroid Build Coastguard Worker       if(!result) {
2303*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_addf(r, "%s%s", count ? "; " : "", addcookies);
2304*6236dae4SAndroid Build Coastguard Worker         count++;
2305*6236dae4SAndroid Build Coastguard Worker       }
2306*6236dae4SAndroid Build Coastguard Worker     }
2307*6236dae4SAndroid Build Coastguard Worker     if(count && !result)
2308*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addn(r, STRCONST("\r\n"));
2309*6236dae4SAndroid Build Coastguard Worker 
2310*6236dae4SAndroid Build Coastguard Worker     if(result)
2311*6236dae4SAndroid Build Coastguard Worker       return result;
2312*6236dae4SAndroid Build Coastguard Worker   }
2313*6236dae4SAndroid Build Coastguard Worker   return result;
2314*6236dae4SAndroid Build Coastguard Worker }
2315*6236dae4SAndroid Build Coastguard Worker #endif
2316*6236dae4SAndroid Build Coastguard Worker 
Curl_http_range(struct Curl_easy * data,Curl_HttpReq httpreq)2317*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_range(struct Curl_easy *data,
2318*6236dae4SAndroid Build Coastguard Worker                          Curl_HttpReq httpreq)
2319*6236dae4SAndroid Build Coastguard Worker {
2320*6236dae4SAndroid Build Coastguard Worker   if(data->state.use_range) {
2321*6236dae4SAndroid Build Coastguard Worker     /*
2322*6236dae4SAndroid Build Coastguard Worker      * A range is selected. We use different headers whether we are downloading
2323*6236dae4SAndroid Build Coastguard Worker      * or uploading and we always let customized headers override our internal
2324*6236dae4SAndroid Build Coastguard Worker      * ones if any such are specified.
2325*6236dae4SAndroid Build Coastguard Worker      */
2326*6236dae4SAndroid Build Coastguard Worker     if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2327*6236dae4SAndroid Build Coastguard Worker        !Curl_checkheaders(data, STRCONST("Range"))) {
2328*6236dae4SAndroid Build Coastguard Worker       /* if a line like this was already allocated, free the previous one */
2329*6236dae4SAndroid Build Coastguard Worker       free(data->state.aptr.rangeline);
2330*6236dae4SAndroid Build Coastguard Worker       data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
2331*6236dae4SAndroid Build Coastguard Worker                                            data->state.range);
2332*6236dae4SAndroid Build Coastguard Worker     }
2333*6236dae4SAndroid Build Coastguard Worker     else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
2334*6236dae4SAndroid Build Coastguard Worker             !Curl_checkheaders(data, STRCONST("Content-Range"))) {
2335*6236dae4SAndroid Build Coastguard Worker       curl_off_t req_clen = Curl_creader_total_length(data);
2336*6236dae4SAndroid Build Coastguard Worker       /* if a line like this was already allocated, free the previous one */
2337*6236dae4SAndroid Build Coastguard Worker       free(data->state.aptr.rangeline);
2338*6236dae4SAndroid Build Coastguard Worker 
2339*6236dae4SAndroid Build Coastguard Worker       if(data->set.set_resume_from < 0) {
2340*6236dae4SAndroid Build Coastguard Worker         /* Upload resume was asked for, but we do not know the size of the
2341*6236dae4SAndroid Build Coastguard Worker            remote part so we tell the server (and act accordingly) that we
2342*6236dae4SAndroid Build Coastguard Worker            upload the whole file (again) */
2343*6236dae4SAndroid Build Coastguard Worker         data->state.aptr.rangeline =
2344*6236dae4SAndroid Build Coastguard Worker           aprintf("Content-Range: bytes 0-%" FMT_OFF_T "/%" FMT_OFF_T "\r\n",
2345*6236dae4SAndroid Build Coastguard Worker                   req_clen - 1, req_clen);
2346*6236dae4SAndroid Build Coastguard Worker 
2347*6236dae4SAndroid Build Coastguard Worker       }
2348*6236dae4SAndroid Build Coastguard Worker       else if(data->state.resume_from) {
2349*6236dae4SAndroid Build Coastguard Worker         /* This is because "resume" was selected */
2350*6236dae4SAndroid Build Coastguard Worker         /* TODO: not sure if we want to send this header during authentication
2351*6236dae4SAndroid Build Coastguard Worker          * negotiation, but test1084 checks for it. In which case we have a
2352*6236dae4SAndroid Build Coastguard Worker          * "null" client reader installed that gives an unexpected length. */
2353*6236dae4SAndroid Build Coastguard Worker         curl_off_t total_len = data->req.authneg ?
2354*6236dae4SAndroid Build Coastguard Worker                                data->state.infilesize :
2355*6236dae4SAndroid Build Coastguard Worker                                (data->state.resume_from + req_clen);
2356*6236dae4SAndroid Build Coastguard Worker         data->state.aptr.rangeline =
2357*6236dae4SAndroid Build Coastguard Worker           aprintf("Content-Range: bytes %s%" FMT_OFF_T "/%" FMT_OFF_T "\r\n",
2358*6236dae4SAndroid Build Coastguard Worker                   data->state.range, total_len-1, total_len);
2359*6236dae4SAndroid Build Coastguard Worker       }
2360*6236dae4SAndroid Build Coastguard Worker       else {
2361*6236dae4SAndroid Build Coastguard Worker         /* Range was selected and then we just pass the incoming range and
2362*6236dae4SAndroid Build Coastguard Worker            append total size */
2363*6236dae4SAndroid Build Coastguard Worker         data->state.aptr.rangeline =
2364*6236dae4SAndroid Build Coastguard Worker           aprintf("Content-Range: bytes %s/%" FMT_OFF_T "\r\n",
2365*6236dae4SAndroid Build Coastguard Worker                   data->state.range, req_clen);
2366*6236dae4SAndroid Build Coastguard Worker       }
2367*6236dae4SAndroid Build Coastguard Worker       if(!data->state.aptr.rangeline)
2368*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
2369*6236dae4SAndroid Build Coastguard Worker     }
2370*6236dae4SAndroid Build Coastguard Worker   }
2371*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2372*6236dae4SAndroid Build Coastguard Worker }
2373*6236dae4SAndroid Build Coastguard Worker 
Curl_http_firstwrite(struct Curl_easy * data)2374*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_firstwrite(struct Curl_easy *data)
2375*6236dae4SAndroid Build Coastguard Worker {
2376*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
2377*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
2378*6236dae4SAndroid Build Coastguard Worker 
2379*6236dae4SAndroid Build Coastguard Worker   if(data->req.newurl) {
2380*6236dae4SAndroid Build Coastguard Worker     if(conn->bits.close) {
2381*6236dae4SAndroid Build Coastguard Worker       /* Abort after the headers if "follow Location" is set
2382*6236dae4SAndroid Build Coastguard Worker          and we are set to close anyway. */
2383*6236dae4SAndroid Build Coastguard Worker       k->keepon &= ~KEEP_RECV;
2384*6236dae4SAndroid Build Coastguard Worker       k->done = TRUE;
2385*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2386*6236dae4SAndroid Build Coastguard Worker     }
2387*6236dae4SAndroid Build Coastguard Worker     /* We have a new URL to load, but since we want to be able to reuse this
2388*6236dae4SAndroid Build Coastguard Worker        connection properly, we read the full response in "ignore more" */
2389*6236dae4SAndroid Build Coastguard Worker     k->ignorebody = TRUE;
2390*6236dae4SAndroid Build Coastguard Worker     infof(data, "Ignoring the response-body");
2391*6236dae4SAndroid Build Coastguard Worker   }
2392*6236dae4SAndroid Build Coastguard Worker   if(data->state.resume_from && !k->content_range &&
2393*6236dae4SAndroid Build Coastguard Worker      (data->state.httpreq == HTTPREQ_GET) &&
2394*6236dae4SAndroid Build Coastguard Worker      !k->ignorebody) {
2395*6236dae4SAndroid Build Coastguard Worker 
2396*6236dae4SAndroid Build Coastguard Worker     if(k->size == data->state.resume_from) {
2397*6236dae4SAndroid Build Coastguard Worker       /* The resume point is at the end of file, consider this fine even if it
2398*6236dae4SAndroid Build Coastguard Worker          does not allow resume from here. */
2399*6236dae4SAndroid Build Coastguard Worker       infof(data, "The entire document is already downloaded");
2400*6236dae4SAndroid Build Coastguard Worker       streamclose(conn, "already downloaded");
2401*6236dae4SAndroid Build Coastguard Worker       /* Abort download */
2402*6236dae4SAndroid Build Coastguard Worker       k->keepon &= ~KEEP_RECV;
2403*6236dae4SAndroid Build Coastguard Worker       k->done = TRUE;
2404*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2405*6236dae4SAndroid Build Coastguard Worker     }
2406*6236dae4SAndroid Build Coastguard Worker 
2407*6236dae4SAndroid Build Coastguard Worker     /* we wanted to resume a download, although the server does not seem to
2408*6236dae4SAndroid Build Coastguard Worker      * support this and we did this with a GET (if it was not a GET we did a
2409*6236dae4SAndroid Build Coastguard Worker      * POST or PUT resume) */
2410*6236dae4SAndroid Build Coastguard Worker     failf(data, "HTTP server does not seem to support "
2411*6236dae4SAndroid Build Coastguard Worker           "byte ranges. Cannot resume.");
2412*6236dae4SAndroid Build Coastguard Worker     return CURLE_RANGE_ERROR;
2413*6236dae4SAndroid Build Coastguard Worker   }
2414*6236dae4SAndroid Build Coastguard Worker 
2415*6236dae4SAndroid Build Coastguard Worker   if(data->set.timecondition && !data->state.range) {
2416*6236dae4SAndroid Build Coastguard Worker     /* A time condition has been set AND no ranges have been requested. This
2417*6236dae4SAndroid Build Coastguard Worker        seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
2418*6236dae4SAndroid Build Coastguard Worker        action for an HTTP/1.1 client */
2419*6236dae4SAndroid Build Coastguard Worker 
2420*6236dae4SAndroid Build Coastguard Worker     if(!Curl_meets_timecondition(data, k->timeofdoc)) {
2421*6236dae4SAndroid Build Coastguard Worker       k->done = TRUE;
2422*6236dae4SAndroid Build Coastguard Worker       /* We are simulating an HTTP 304 from server so we return
2423*6236dae4SAndroid Build Coastguard Worker          what should have been returned from the server */
2424*6236dae4SAndroid Build Coastguard Worker       data->info.httpcode = 304;
2425*6236dae4SAndroid Build Coastguard Worker       infof(data, "Simulate an HTTP 304 response");
2426*6236dae4SAndroid Build Coastguard Worker       /* we abort the transfer before it is completed == we ruin the
2427*6236dae4SAndroid Build Coastguard Worker          reuse ability. Close the connection */
2428*6236dae4SAndroid Build Coastguard Worker       streamclose(conn, "Simulated 304 handling");
2429*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2430*6236dae4SAndroid Build Coastguard Worker     }
2431*6236dae4SAndroid Build Coastguard Worker   } /* we have a time condition */
2432*6236dae4SAndroid Build Coastguard Worker 
2433*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2434*6236dae4SAndroid Build Coastguard Worker }
2435*6236dae4SAndroid Build Coastguard Worker 
2436*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
Curl_transferencode(struct Curl_easy * data)2437*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_transferencode(struct Curl_easy *data)
2438*6236dae4SAndroid Build Coastguard Worker {
2439*6236dae4SAndroid Build Coastguard Worker   if(!Curl_checkheaders(data, STRCONST("TE")) &&
2440*6236dae4SAndroid Build Coastguard Worker      data->set.http_transfer_encoding) {
2441*6236dae4SAndroid Build Coastguard Worker     /* When we are to insert a TE: header in the request, we must also insert
2442*6236dae4SAndroid Build Coastguard Worker        TE in a Connection: header, so we need to merge the custom provided
2443*6236dae4SAndroid Build Coastguard Worker        Connection: header and prevent the original to get sent. Note that if
2444*6236dae4SAndroid Build Coastguard Worker        the user has inserted his/her own TE: header we do not do this magic
2445*6236dae4SAndroid Build Coastguard Worker        but then assume that the user will handle it all! */
2446*6236dae4SAndroid Build Coastguard Worker     char *cptr = Curl_checkheaders(data, STRCONST("Connection"));
2447*6236dae4SAndroid Build Coastguard Worker #define TE_HEADER "TE: gzip\r\n"
2448*6236dae4SAndroid Build Coastguard Worker 
2449*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->state.aptr.te);
2450*6236dae4SAndroid Build Coastguard Worker 
2451*6236dae4SAndroid Build Coastguard Worker     if(cptr) {
2452*6236dae4SAndroid Build Coastguard Worker       cptr = Curl_copy_header_value(cptr);
2453*6236dae4SAndroid Build Coastguard Worker       if(!cptr)
2454*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
2455*6236dae4SAndroid Build Coastguard Worker     }
2456*6236dae4SAndroid Build Coastguard Worker 
2457*6236dae4SAndroid Build Coastguard Worker     /* Create the (updated) Connection: header */
2458*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
2459*6236dae4SAndroid Build Coastguard Worker                                 cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
2460*6236dae4SAndroid Build Coastguard Worker 
2461*6236dae4SAndroid Build Coastguard Worker     free(cptr);
2462*6236dae4SAndroid Build Coastguard Worker     if(!data->state.aptr.te)
2463*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
2464*6236dae4SAndroid Build Coastguard Worker   }
2465*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2466*6236dae4SAndroid Build Coastguard Worker }
2467*6236dae4SAndroid Build Coastguard Worker #endif
2468*6236dae4SAndroid Build Coastguard Worker 
2469*6236dae4SAndroid Build Coastguard Worker #ifndef USE_HYPER
2470*6236dae4SAndroid Build Coastguard Worker /*
2471*6236dae4SAndroid Build Coastguard Worker  * Curl_http() gets called from the generic multi_do() function when an HTTP
2472*6236dae4SAndroid Build Coastguard Worker  * request is to be performed. This creates and sends a properly constructed
2473*6236dae4SAndroid Build Coastguard Worker  * HTTP request.
2474*6236dae4SAndroid Build Coastguard Worker  */
Curl_http(struct Curl_easy * data,bool * done)2475*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http(struct Curl_easy *data, bool *done)
2476*6236dae4SAndroid Build Coastguard Worker {
2477*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
2478*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2479*6236dae4SAndroid Build Coastguard Worker   Curl_HttpReq httpreq;
2480*6236dae4SAndroid Build Coastguard Worker   const char *te = ""; /* transfer-encoding */
2481*6236dae4SAndroid Build Coastguard Worker   const char *request;
2482*6236dae4SAndroid Build Coastguard Worker   const char *httpstring;
2483*6236dae4SAndroid Build Coastguard Worker   struct dynbuf req;
2484*6236dae4SAndroid Build Coastguard Worker   char *altused = NULL;
2485*6236dae4SAndroid Build Coastguard Worker   const char *p_accept;      /* Accept: string */
2486*6236dae4SAndroid Build Coastguard Worker 
2487*6236dae4SAndroid Build Coastguard Worker   /* Always consider the DO phase done after this function call, even if there
2488*6236dae4SAndroid Build Coastguard Worker      may be parts of the request that are not yet sent, since we can deal with
2489*6236dae4SAndroid Build Coastguard Worker      the rest of the request in the PERFORM phase. */
2490*6236dae4SAndroid Build Coastguard Worker   *done = TRUE;
2491*6236dae4SAndroid Build Coastguard Worker 
2492*6236dae4SAndroid Build Coastguard Worker   switch(conn->alpn) {
2493*6236dae4SAndroid Build Coastguard Worker   case CURL_HTTP_VERSION_3:
2494*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(Curl_conn_is_http3(data, conn, FIRSTSOCKET));
2495*6236dae4SAndroid Build Coastguard Worker     break;
2496*6236dae4SAndroid Build Coastguard Worker   case CURL_HTTP_VERSION_2:
2497*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2498*6236dae4SAndroid Build Coastguard Worker     if(!Curl_conn_is_http2(data, conn, FIRSTSOCKET) &&
2499*6236dae4SAndroid Build Coastguard Worker        conn->bits.proxy && !conn->bits.tunnel_proxy
2500*6236dae4SAndroid Build Coastguard Worker       ) {
2501*6236dae4SAndroid Build Coastguard Worker       result = Curl_http2_switch(data, conn, FIRSTSOCKET);
2502*6236dae4SAndroid Build Coastguard Worker       if(result)
2503*6236dae4SAndroid Build Coastguard Worker         goto fail;
2504*6236dae4SAndroid Build Coastguard Worker     }
2505*6236dae4SAndroid Build Coastguard Worker     else
2506*6236dae4SAndroid Build Coastguard Worker #endif
2507*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
2508*6236dae4SAndroid Build Coastguard Worker     break;
2509*6236dae4SAndroid Build Coastguard Worker   case CURL_HTTP_VERSION_1_1:
2510*6236dae4SAndroid Build Coastguard Worker     /* continue with HTTP/1.x when explicitly requested */
2511*6236dae4SAndroid Build Coastguard Worker     break;
2512*6236dae4SAndroid Build Coastguard Worker   default:
2513*6236dae4SAndroid Build Coastguard Worker     /* Check if user wants to use HTTP/2 with clear TCP */
2514*6236dae4SAndroid Build Coastguard Worker     if(Curl_http2_may_switch(data, conn, FIRSTSOCKET)) {
2515*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "HTTP/2 over clean TCP"));
2516*6236dae4SAndroid Build Coastguard Worker       result = Curl_http2_switch(data, conn, FIRSTSOCKET);
2517*6236dae4SAndroid Build Coastguard Worker       if(result)
2518*6236dae4SAndroid Build Coastguard Worker         goto fail;
2519*6236dae4SAndroid Build Coastguard Worker     }
2520*6236dae4SAndroid Build Coastguard Worker     break;
2521*6236dae4SAndroid Build Coastguard Worker   }
2522*6236dae4SAndroid Build Coastguard Worker 
2523*6236dae4SAndroid Build Coastguard Worker   /* Add collecting of headers written to client. For a new connection,
2524*6236dae4SAndroid Build Coastguard Worker    * we might have done that already, but reuse
2525*6236dae4SAndroid Build Coastguard Worker    * or multiplex needs it here as well. */
2526*6236dae4SAndroid Build Coastguard Worker   result = Curl_headers_init(data);
2527*6236dae4SAndroid Build Coastguard Worker   if(result)
2528*6236dae4SAndroid Build Coastguard Worker     goto fail;
2529*6236dae4SAndroid Build Coastguard Worker 
2530*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_host(data, conn);
2531*6236dae4SAndroid Build Coastguard Worker   if(result)
2532*6236dae4SAndroid Build Coastguard Worker     goto fail;
2533*6236dae4SAndroid Build Coastguard Worker 
2534*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_useragent(data);
2535*6236dae4SAndroid Build Coastguard Worker   if(result)
2536*6236dae4SAndroid Build Coastguard Worker     goto fail;
2537*6236dae4SAndroid Build Coastguard Worker 
2538*6236dae4SAndroid Build Coastguard Worker   Curl_http_method(data, conn, &request, &httpreq);
2539*6236dae4SAndroid Build Coastguard Worker 
2540*6236dae4SAndroid Build Coastguard Worker   /* setup the authentication headers */
2541*6236dae4SAndroid Build Coastguard Worker   {
2542*6236dae4SAndroid Build Coastguard Worker     char *pq = NULL;
2543*6236dae4SAndroid Build Coastguard Worker     if(data->state.up.query) {
2544*6236dae4SAndroid Build Coastguard Worker       pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
2545*6236dae4SAndroid Build Coastguard Worker       if(!pq)
2546*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
2547*6236dae4SAndroid Build Coastguard Worker     }
2548*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_output_auth(data, conn, request, httpreq,
2549*6236dae4SAndroid Build Coastguard Worker                                    (pq ? pq : data->state.up.path), FALSE);
2550*6236dae4SAndroid Build Coastguard Worker     free(pq);
2551*6236dae4SAndroid Build Coastguard Worker     if(result)
2552*6236dae4SAndroid Build Coastguard Worker       goto fail;
2553*6236dae4SAndroid Build Coastguard Worker   }
2554*6236dae4SAndroid Build Coastguard Worker 
2555*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.ref);
2556*6236dae4SAndroid Build Coastguard Worker   if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
2557*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
2558*6236dae4SAndroid Build Coastguard Worker     if(!data->state.aptr.ref)
2559*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
2560*6236dae4SAndroid Build Coastguard Worker   }
2561*6236dae4SAndroid Build Coastguard Worker 
2562*6236dae4SAndroid Build Coastguard Worker   if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
2563*6236dae4SAndroid Build Coastguard Worker      data->set.str[STRING_ENCODING]) {
2564*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->state.aptr.accept_encoding);
2565*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.accept_encoding =
2566*6236dae4SAndroid Build Coastguard Worker       aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
2567*6236dae4SAndroid Build Coastguard Worker     if(!data->state.aptr.accept_encoding)
2568*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
2569*6236dae4SAndroid Build Coastguard Worker   }
2570*6236dae4SAndroid Build Coastguard Worker   else
2571*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->state.aptr.accept_encoding);
2572*6236dae4SAndroid Build Coastguard Worker 
2573*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
2574*6236dae4SAndroid Build Coastguard Worker   /* we only consider transfer-encoding magic if libz support is built-in */
2575*6236dae4SAndroid Build Coastguard Worker   result = Curl_transferencode(data);
2576*6236dae4SAndroid Build Coastguard Worker   if(result)
2577*6236dae4SAndroid Build Coastguard Worker     goto fail;
2578*6236dae4SAndroid Build Coastguard Worker #endif
2579*6236dae4SAndroid Build Coastguard Worker 
2580*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_req_set_reader(data, httpreq, &te);
2581*6236dae4SAndroid Build Coastguard Worker   if(result)
2582*6236dae4SAndroid Build Coastguard Worker     goto fail;
2583*6236dae4SAndroid Build Coastguard Worker 
2584*6236dae4SAndroid Build Coastguard Worker   p_accept = Curl_checkheaders(data,
2585*6236dae4SAndroid Build Coastguard Worker                                STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
2586*6236dae4SAndroid Build Coastguard Worker 
2587*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_range(data, httpreq);
2588*6236dae4SAndroid Build Coastguard Worker   if(result)
2589*6236dae4SAndroid Build Coastguard Worker     goto fail;
2590*6236dae4SAndroid Build Coastguard Worker 
2591*6236dae4SAndroid Build Coastguard Worker   httpstring = get_http_string(data, conn);
2592*6236dae4SAndroid Build Coastguard Worker 
2593*6236dae4SAndroid Build Coastguard Worker   /* initialize a dynamic send-buffer */
2594*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&req, DYN_HTTP_REQUEST);
2595*6236dae4SAndroid Build Coastguard Worker 
2596*6236dae4SAndroid Build Coastguard Worker   /* make sure the header buffer is reset - if there are leftovers from a
2597*6236dae4SAndroid Build Coastguard Worker      previous transfer */
2598*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_reset(&data->state.headerb);
2599*6236dae4SAndroid Build Coastguard Worker 
2600*6236dae4SAndroid Build Coastguard Worker   /* add the main request stuff */
2601*6236dae4SAndroid Build Coastguard Worker   /* GET/HEAD/POST/PUT */
2602*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_addf(&req, "%s ", request);
2603*6236dae4SAndroid Build Coastguard Worker   if(!result)
2604*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_target(data, conn, &req);
2605*6236dae4SAndroid Build Coastguard Worker   if(result) {
2606*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&req);
2607*6236dae4SAndroid Build Coastguard Worker     goto fail;
2608*6236dae4SAndroid Build Coastguard Worker   }
2609*6236dae4SAndroid Build Coastguard Worker 
2610*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_ALTSVC
2611*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
2612*6236dae4SAndroid Build Coastguard Worker     altused = aprintf("Alt-Used: %s:%d\r\n",
2613*6236dae4SAndroid Build Coastguard Worker                       conn->conn_to_host.name, conn->conn_to_port);
2614*6236dae4SAndroid Build Coastguard Worker     if(!altused) {
2615*6236dae4SAndroid Build Coastguard Worker       Curl_dyn_free(&req);
2616*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
2617*6236dae4SAndroid Build Coastguard Worker     }
2618*6236dae4SAndroid Build Coastguard Worker   }
2619*6236dae4SAndroid Build Coastguard Worker #endif
2620*6236dae4SAndroid Build Coastguard Worker   result =
2621*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_addf(&req,
2622*6236dae4SAndroid Build Coastguard Worker                   " HTTP/%s\r\n" /* HTTP version */
2623*6236dae4SAndroid Build Coastguard Worker                   "%s" /* host */
2624*6236dae4SAndroid Build Coastguard Worker                   "%s" /* proxyuserpwd */
2625*6236dae4SAndroid Build Coastguard Worker                   "%s" /* userpwd */
2626*6236dae4SAndroid Build Coastguard Worker                   "%s" /* range */
2627*6236dae4SAndroid Build Coastguard Worker                   "%s" /* user agent */
2628*6236dae4SAndroid Build Coastguard Worker                   "%s" /* accept */
2629*6236dae4SAndroid Build Coastguard Worker                   "%s" /* TE: */
2630*6236dae4SAndroid Build Coastguard Worker                   "%s" /* accept-encoding */
2631*6236dae4SAndroid Build Coastguard Worker                   "%s" /* referer */
2632*6236dae4SAndroid Build Coastguard Worker                   "%s" /* Proxy-Connection */
2633*6236dae4SAndroid Build Coastguard Worker                   "%s" /* transfer-encoding */
2634*6236dae4SAndroid Build Coastguard Worker                   "%s",/* Alt-Used */
2635*6236dae4SAndroid Build Coastguard Worker 
2636*6236dae4SAndroid Build Coastguard Worker                   httpstring,
2637*6236dae4SAndroid Build Coastguard Worker                   (data->state.aptr.host ? data->state.aptr.host : ""),
2638*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2639*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.proxyuserpwd ?
2640*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.proxyuserpwd : "",
2641*6236dae4SAndroid Build Coastguard Worker #else
2642*6236dae4SAndroid Build Coastguard Worker                   "",
2643*6236dae4SAndroid Build Coastguard Worker #endif
2644*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.userpwd ? data->state.aptr.userpwd : "",
2645*6236dae4SAndroid Build Coastguard Worker                   (data->state.use_range && data->state.aptr.rangeline) ?
2646*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.rangeline : "",
2647*6236dae4SAndroid Build Coastguard Worker                   (data->set.str[STRING_USERAGENT] &&
2648*6236dae4SAndroid Build Coastguard Worker                    *data->set.str[STRING_USERAGENT] &&
2649*6236dae4SAndroid Build Coastguard Worker                    data->state.aptr.uagent) ?
2650*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.uagent : "",
2651*6236dae4SAndroid Build Coastguard Worker                   p_accept ? p_accept : "",
2652*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.te ? data->state.aptr.te : "",
2653*6236dae4SAndroid Build Coastguard Worker                   (data->set.str[STRING_ENCODING] &&
2654*6236dae4SAndroid Build Coastguard Worker                    *data->set.str[STRING_ENCODING] &&
2655*6236dae4SAndroid Build Coastguard Worker                    data->state.aptr.accept_encoding) ?
2656*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.accept_encoding : "",
2657*6236dae4SAndroid Build Coastguard Worker                   (data->state.referer && data->state.aptr.ref) ?
2658*6236dae4SAndroid Build Coastguard Worker                   data->state.aptr.ref : "" /* Referer: <data> */,
2659*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2660*6236dae4SAndroid Build Coastguard Worker                   (conn->bits.httpproxy &&
2661*6236dae4SAndroid Build Coastguard Worker                    !conn->bits.tunnel_proxy &&
2662*6236dae4SAndroid Build Coastguard Worker                    !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
2663*6236dae4SAndroid Build Coastguard Worker                    !Curl_checkProxyheaders(data, conn,
2664*6236dae4SAndroid Build Coastguard Worker                                            STRCONST("Proxy-Connection"))) ?
2665*6236dae4SAndroid Build Coastguard Worker                   "Proxy-Connection: Keep-Alive\r\n":"",
2666*6236dae4SAndroid Build Coastguard Worker #else
2667*6236dae4SAndroid Build Coastguard Worker                   "",
2668*6236dae4SAndroid Build Coastguard Worker #endif
2669*6236dae4SAndroid Build Coastguard Worker                   te,
2670*6236dae4SAndroid Build Coastguard Worker                   altused ? altused : ""
2671*6236dae4SAndroid Build Coastguard Worker       );
2672*6236dae4SAndroid Build Coastguard Worker 
2673*6236dae4SAndroid Build Coastguard Worker   /* clear userpwd and proxyuserpwd to avoid reusing old credentials
2674*6236dae4SAndroid Build Coastguard Worker    * from reused connections */
2675*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.userpwd);
2676*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
2677*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.proxyuserpwd);
2678*6236dae4SAndroid Build Coastguard Worker #endif
2679*6236dae4SAndroid Build Coastguard Worker   free(altused);
2680*6236dae4SAndroid Build Coastguard Worker 
2681*6236dae4SAndroid Build Coastguard Worker   if(result) {
2682*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&req);
2683*6236dae4SAndroid Build Coastguard Worker     goto fail;
2684*6236dae4SAndroid Build Coastguard Worker   }
2685*6236dae4SAndroid Build Coastguard Worker 
2686*6236dae4SAndroid Build Coastguard Worker   if(!(conn->handler->flags&PROTOPT_SSL) &&
2687*6236dae4SAndroid Build Coastguard Worker      conn->httpversion < 20 &&
2688*6236dae4SAndroid Build Coastguard Worker      (data->state.httpwant == CURL_HTTP_VERSION_2)) {
2689*6236dae4SAndroid Build Coastguard Worker     /* append HTTP2 upgrade magic stuff to the HTTP request if it is not done
2690*6236dae4SAndroid Build Coastguard Worker        over SSL */
2691*6236dae4SAndroid Build Coastguard Worker     result = Curl_http2_request_upgrade(&req, data);
2692*6236dae4SAndroid Build Coastguard Worker     if(result) {
2693*6236dae4SAndroid Build Coastguard Worker       Curl_dyn_free(&req);
2694*6236dae4SAndroid Build Coastguard Worker       return result;
2695*6236dae4SAndroid Build Coastguard Worker     }
2696*6236dae4SAndroid Build Coastguard Worker   }
2697*6236dae4SAndroid Build Coastguard Worker 
2698*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_cookies(data, conn, &req);
2699*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_WEBSOCKETS
2700*6236dae4SAndroid Build Coastguard Worker   if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
2701*6236dae4SAndroid Build Coastguard Worker     result = Curl_ws_request(data, &req);
2702*6236dae4SAndroid Build Coastguard Worker #endif
2703*6236dae4SAndroid Build Coastguard Worker   if(!result)
2704*6236dae4SAndroid Build Coastguard Worker     result = Curl_add_timecondition(data, &req);
2705*6236dae4SAndroid Build Coastguard Worker   if(!result)
2706*6236dae4SAndroid Build Coastguard Worker     result = Curl_add_custom_headers(data, FALSE, &req);
2707*6236dae4SAndroid Build Coastguard Worker 
2708*6236dae4SAndroid Build Coastguard Worker   if(!result) {
2709*6236dae4SAndroid Build Coastguard Worker     /* req_send takes ownership of the 'req' memory on success */
2710*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_req_complete(data, &req, httpreq);
2711*6236dae4SAndroid Build Coastguard Worker     if(!result)
2712*6236dae4SAndroid Build Coastguard Worker       result = Curl_req_send(data, &req);
2713*6236dae4SAndroid Build Coastguard Worker   }
2714*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&req);
2715*6236dae4SAndroid Build Coastguard Worker   if(result)
2716*6236dae4SAndroid Build Coastguard Worker     goto fail;
2717*6236dae4SAndroid Build Coastguard Worker 
2718*6236dae4SAndroid Build Coastguard Worker   if((conn->httpversion >= 20) && data->req.upload_chunky)
2719*6236dae4SAndroid Build Coastguard Worker     /* upload_chunky was set above to set up the request in a chunky fashion,
2720*6236dae4SAndroid Build Coastguard Worker        but is disabled here again to avoid that the chunked encoded version is
2721*6236dae4SAndroid Build Coastguard Worker        actually used when sending the request body over h2 */
2722*6236dae4SAndroid Build Coastguard Worker     data->req.upload_chunky = FALSE;
2723*6236dae4SAndroid Build Coastguard Worker fail:
2724*6236dae4SAndroid Build Coastguard Worker   if(CURLE_TOO_LARGE == result)
2725*6236dae4SAndroid Build Coastguard Worker     failf(data, "HTTP request too large");
2726*6236dae4SAndroid Build Coastguard Worker   return result;
2727*6236dae4SAndroid Build Coastguard Worker }
2728*6236dae4SAndroid Build Coastguard Worker 
2729*6236dae4SAndroid Build Coastguard Worker #endif /* USE_HYPER */
2730*6236dae4SAndroid Build Coastguard Worker 
2731*6236dae4SAndroid Build Coastguard Worker typedef enum {
2732*6236dae4SAndroid Build Coastguard Worker   STATUS_UNKNOWN, /* not enough data to tell yet */
2733*6236dae4SAndroid Build Coastguard Worker   STATUS_DONE, /* a status line was read */
2734*6236dae4SAndroid Build Coastguard Worker   STATUS_BAD /* not a status line */
2735*6236dae4SAndroid Build Coastguard Worker } statusline;
2736*6236dae4SAndroid Build Coastguard Worker 
2737*6236dae4SAndroid Build Coastguard Worker 
2738*6236dae4SAndroid Build Coastguard Worker /* Check a string for a prefix. Check no more than 'len' bytes */
checkprefixmax(const char * prefix,const char * buffer,size_t len)2739*6236dae4SAndroid Build Coastguard Worker static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
2740*6236dae4SAndroid Build Coastguard Worker {
2741*6236dae4SAndroid Build Coastguard Worker   size_t ch = CURLMIN(strlen(prefix), len);
2742*6236dae4SAndroid Build Coastguard Worker   return curl_strnequal(prefix, buffer, ch);
2743*6236dae4SAndroid Build Coastguard Worker }
2744*6236dae4SAndroid Build Coastguard Worker 
2745*6236dae4SAndroid Build Coastguard Worker /*
2746*6236dae4SAndroid Build Coastguard Worker  * checkhttpprefix()
2747*6236dae4SAndroid Build Coastguard Worker  *
2748*6236dae4SAndroid Build Coastguard Worker  * Returns TRUE if member of the list matches prefix of string
2749*6236dae4SAndroid Build Coastguard Worker  */
2750*6236dae4SAndroid Build Coastguard Worker static statusline
checkhttpprefix(struct Curl_easy * data,const char * s,size_t len)2751*6236dae4SAndroid Build Coastguard Worker checkhttpprefix(struct Curl_easy *data,
2752*6236dae4SAndroid Build Coastguard Worker                 const char *s, size_t len)
2753*6236dae4SAndroid Build Coastguard Worker {
2754*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *head = data->set.http200aliases;
2755*6236dae4SAndroid Build Coastguard Worker   statusline rc = STATUS_BAD;
2756*6236dae4SAndroid Build Coastguard Worker   statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
2757*6236dae4SAndroid Build Coastguard Worker 
2758*6236dae4SAndroid Build Coastguard Worker   while(head) {
2759*6236dae4SAndroid Build Coastguard Worker     if(checkprefixmax(head->data, s, len)) {
2760*6236dae4SAndroid Build Coastguard Worker       rc = onmatch;
2761*6236dae4SAndroid Build Coastguard Worker       break;
2762*6236dae4SAndroid Build Coastguard Worker     }
2763*6236dae4SAndroid Build Coastguard Worker     head = head->next;
2764*6236dae4SAndroid Build Coastguard Worker   }
2765*6236dae4SAndroid Build Coastguard Worker 
2766*6236dae4SAndroid Build Coastguard Worker   if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
2767*6236dae4SAndroid Build Coastguard Worker     rc = onmatch;
2768*6236dae4SAndroid Build Coastguard Worker 
2769*6236dae4SAndroid Build Coastguard Worker   return rc;
2770*6236dae4SAndroid Build Coastguard Worker }
2771*6236dae4SAndroid Build Coastguard Worker 
2772*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_RTSP
2773*6236dae4SAndroid Build Coastguard Worker static statusline
checkrtspprefix(struct Curl_easy * data,const char * s,size_t len)2774*6236dae4SAndroid Build Coastguard Worker checkrtspprefix(struct Curl_easy *data,
2775*6236dae4SAndroid Build Coastguard Worker                 const char *s, size_t len)
2776*6236dae4SAndroid Build Coastguard Worker {
2777*6236dae4SAndroid Build Coastguard Worker   statusline result = STATUS_BAD;
2778*6236dae4SAndroid Build Coastguard Worker   statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
2779*6236dae4SAndroid Build Coastguard Worker   (void)data; /* unused */
2780*6236dae4SAndroid Build Coastguard Worker   if(checkprefixmax("RTSP/", s, len))
2781*6236dae4SAndroid Build Coastguard Worker     result = onmatch;
2782*6236dae4SAndroid Build Coastguard Worker 
2783*6236dae4SAndroid Build Coastguard Worker   return result;
2784*6236dae4SAndroid Build Coastguard Worker }
2785*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_RTSP */
2786*6236dae4SAndroid Build Coastguard Worker 
2787*6236dae4SAndroid Build Coastguard Worker static statusline
checkprotoprefix(struct Curl_easy * data,struct connectdata * conn,const char * s,size_t len)2788*6236dae4SAndroid Build Coastguard Worker checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
2789*6236dae4SAndroid Build Coastguard Worker                  const char *s, size_t len)
2790*6236dae4SAndroid Build Coastguard Worker {
2791*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_RTSP
2792*6236dae4SAndroid Build Coastguard Worker   if(conn->handler->protocol & CURLPROTO_RTSP)
2793*6236dae4SAndroid Build Coastguard Worker     return checkrtspprefix(data, s, len);
2794*6236dae4SAndroid Build Coastguard Worker #else
2795*6236dae4SAndroid Build Coastguard Worker   (void)conn;
2796*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_RTSP */
2797*6236dae4SAndroid Build Coastguard Worker 
2798*6236dae4SAndroid Build Coastguard Worker   return checkhttpprefix(data, s, len);
2799*6236dae4SAndroid Build Coastguard Worker }
2800*6236dae4SAndroid Build Coastguard Worker 
2801*6236dae4SAndroid Build Coastguard Worker /* HTTP header has field name `n` (a string constant) */
2802*6236dae4SAndroid Build Coastguard Worker #define HD_IS(hd, hdlen, n) \
2803*6236dae4SAndroid Build Coastguard Worker   (((hdlen) >= (sizeof(n)-1)) && curl_strnequal((n), (hd), (sizeof(n)-1)))
2804*6236dae4SAndroid Build Coastguard Worker 
2805*6236dae4SAndroid Build Coastguard Worker #define HD_VAL(hd, hdlen, n) \
2806*6236dae4SAndroid Build Coastguard Worker   ((((hdlen) >= (sizeof(n)-1)) && \
2807*6236dae4SAndroid Build Coastguard Worker     curl_strnequal((n), (hd), (sizeof(n)-1)))? (hd + (sizeof(n)-1)) : NULL)
2808*6236dae4SAndroid Build Coastguard Worker 
2809*6236dae4SAndroid Build Coastguard Worker /* HTTP header has field name `n` (a string constant) and contains `v`
2810*6236dae4SAndroid Build Coastguard Worker  * (a string constant) in its value(s) */
2811*6236dae4SAndroid Build Coastguard Worker #define HD_IS_AND_SAYS(hd, hdlen, n, v) \
2812*6236dae4SAndroid Build Coastguard Worker   (HD_IS(hd, hdlen, n) && \
2813*6236dae4SAndroid Build Coastguard Worker    ((hdlen) > ((sizeof(n)-1) + (sizeof(v)-1))) && \
2814*6236dae4SAndroid Build Coastguard Worker    Curl_compareheader(hd, STRCONST(n), STRCONST(v)))
2815*6236dae4SAndroid Build Coastguard Worker 
2816*6236dae4SAndroid Build Coastguard Worker /*
2817*6236dae4SAndroid Build Coastguard Worker  * Curl_http_header() parses a single response header.
2818*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_header(struct Curl_easy * data,const char * hd,size_t hdlen)2819*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_header(struct Curl_easy *data,
2820*6236dae4SAndroid Build Coastguard Worker                           const char *hd, size_t hdlen)
2821*6236dae4SAndroid Build Coastguard Worker {
2822*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
2823*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
2824*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
2825*6236dae4SAndroid Build Coastguard Worker   const char *v;
2826*6236dae4SAndroid Build Coastguard Worker 
2827*6236dae4SAndroid Build Coastguard Worker   switch(hd[0]) {
2828*6236dae4SAndroid Build Coastguard Worker   case 'a':
2829*6236dae4SAndroid Build Coastguard Worker   case 'A':
2830*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_ALTSVC
2831*6236dae4SAndroid Build Coastguard Worker     v = (data->asi &&
2832*6236dae4SAndroid Build Coastguard Worker          ((data->conn->handler->flags & PROTOPT_SSL) ||
2833*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
2834*6236dae4SAndroid Build Coastguard Worker           /* allow debug builds to circumvent the HTTPS restriction */
2835*6236dae4SAndroid Build Coastguard Worker           getenv("CURL_ALTSVC_HTTP")
2836*6236dae4SAndroid Build Coastguard Worker #else
2837*6236dae4SAndroid Build Coastguard Worker           0
2838*6236dae4SAndroid Build Coastguard Worker #endif
2839*6236dae4SAndroid Build Coastguard Worker         )) ? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
2840*6236dae4SAndroid Build Coastguard Worker     if(v) {
2841*6236dae4SAndroid Build Coastguard Worker       /* the ALPN of the current request */
2842*6236dae4SAndroid Build Coastguard Worker       enum alpnid id = (conn->httpversion == 30) ? ALPN_h3 :
2843*6236dae4SAndroid Build Coastguard Worker                          (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
2844*6236dae4SAndroid Build Coastguard Worker       return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
2845*6236dae4SAndroid Build Coastguard Worker                                curlx_uitous((unsigned int)conn->remote_port));
2846*6236dae4SAndroid Build Coastguard Worker     }
2847*6236dae4SAndroid Build Coastguard Worker #endif
2848*6236dae4SAndroid Build Coastguard Worker     break;
2849*6236dae4SAndroid Build Coastguard Worker   case 'c':
2850*6236dae4SAndroid Build Coastguard Worker   case 'C':
2851*6236dae4SAndroid Build Coastguard Worker     /* Check for Content-Length: header lines to get size */
2852*6236dae4SAndroid Build Coastguard Worker     v = (!k->http_bodyless && !data->set.ignorecl) ?
2853*6236dae4SAndroid Build Coastguard Worker       HD_VAL(hd, hdlen, "Content-Length:") : NULL;
2854*6236dae4SAndroid Build Coastguard Worker     if(v) {
2855*6236dae4SAndroid Build Coastguard Worker       curl_off_t contentlength;
2856*6236dae4SAndroid Build Coastguard Worker       CURLofft offt = curlx_strtoofft(v, NULL, 10, &contentlength);
2857*6236dae4SAndroid Build Coastguard Worker 
2858*6236dae4SAndroid Build Coastguard Worker       if(offt == CURL_OFFT_OK) {
2859*6236dae4SAndroid Build Coastguard Worker         k->size = contentlength;
2860*6236dae4SAndroid Build Coastguard Worker         k->maxdownload = k->size;
2861*6236dae4SAndroid Build Coastguard Worker       }
2862*6236dae4SAndroid Build Coastguard Worker       else if(offt == CURL_OFFT_FLOW) {
2863*6236dae4SAndroid Build Coastguard Worker         /* out of range */
2864*6236dae4SAndroid Build Coastguard Worker         if(data->set.max_filesize) {
2865*6236dae4SAndroid Build Coastguard Worker           failf(data, "Maximum file size exceeded");
2866*6236dae4SAndroid Build Coastguard Worker           return CURLE_FILESIZE_EXCEEDED;
2867*6236dae4SAndroid Build Coastguard Worker         }
2868*6236dae4SAndroid Build Coastguard Worker         streamclose(conn, "overflow content-length");
2869*6236dae4SAndroid Build Coastguard Worker         infof(data, "Overflow Content-Length: value");
2870*6236dae4SAndroid Build Coastguard Worker       }
2871*6236dae4SAndroid Build Coastguard Worker       else {
2872*6236dae4SAndroid Build Coastguard Worker         /* negative or just rubbish - bad HTTP */
2873*6236dae4SAndroid Build Coastguard Worker         failf(data, "Invalid Content-Length: value");
2874*6236dae4SAndroid Build Coastguard Worker         return CURLE_WEIRD_SERVER_REPLY;
2875*6236dae4SAndroid Build Coastguard Worker       }
2876*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2877*6236dae4SAndroid Build Coastguard Worker     }
2878*6236dae4SAndroid Build Coastguard Worker     v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ?
2879*6236dae4SAndroid Build Coastguard Worker       HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
2880*6236dae4SAndroid Build Coastguard Worker     if(v) {
2881*6236dae4SAndroid Build Coastguard Worker       /*
2882*6236dae4SAndroid Build Coastguard Worker        * Process Content-Encoding. Look for the values: identity,
2883*6236dae4SAndroid Build Coastguard Worker        * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
2884*6236dae4SAndroid Build Coastguard Worker        * x-compress are the same as gzip and compress. (Sec 3.5 RFC
2885*6236dae4SAndroid Build Coastguard Worker        * 2616). zlib cannot handle compress. However, errors are
2886*6236dae4SAndroid Build Coastguard Worker        * handled further down when the response body is processed
2887*6236dae4SAndroid Build Coastguard Worker        */
2888*6236dae4SAndroid Build Coastguard Worker       return Curl_build_unencoding_stack(data, v, FALSE);
2889*6236dae4SAndroid Build Coastguard Worker     }
2890*6236dae4SAndroid Build Coastguard Worker     /* check for Content-Type: header lines to get the MIME-type */
2891*6236dae4SAndroid Build Coastguard Worker     v = HD_VAL(hd, hdlen, "Content-Type:");
2892*6236dae4SAndroid Build Coastguard Worker     if(v) {
2893*6236dae4SAndroid Build Coastguard Worker       char *contenttype = Curl_copy_header_value(hd);
2894*6236dae4SAndroid Build Coastguard Worker       if(!contenttype)
2895*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
2896*6236dae4SAndroid Build Coastguard Worker       if(!*contenttype)
2897*6236dae4SAndroid Build Coastguard Worker         /* ignore empty data */
2898*6236dae4SAndroid Build Coastguard Worker         free(contenttype);
2899*6236dae4SAndroid Build Coastguard Worker       else {
2900*6236dae4SAndroid Build Coastguard Worker         Curl_safefree(data->info.contenttype);
2901*6236dae4SAndroid Build Coastguard Worker         data->info.contenttype = contenttype;
2902*6236dae4SAndroid Build Coastguard Worker       }
2903*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2904*6236dae4SAndroid Build Coastguard Worker     }
2905*6236dae4SAndroid Build Coastguard Worker     if(HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) {
2906*6236dae4SAndroid Build Coastguard Worker       /*
2907*6236dae4SAndroid Build Coastguard Worker        * [RFC 2616, section 8.1.2.1]
2908*6236dae4SAndroid Build Coastguard Worker        * "Connection: close" is HTTP/1.1 language and means that
2909*6236dae4SAndroid Build Coastguard Worker        * the connection will close when this request has been
2910*6236dae4SAndroid Build Coastguard Worker        * served.
2911*6236dae4SAndroid Build Coastguard Worker        */
2912*6236dae4SAndroid Build Coastguard Worker       streamclose(conn, "Connection: close used");
2913*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2914*6236dae4SAndroid Build Coastguard Worker     }
2915*6236dae4SAndroid Build Coastguard Worker     if((conn->httpversion == 10) &&
2916*6236dae4SAndroid Build Coastguard Worker        HD_IS_AND_SAYS(hd, hdlen, "Connection:", "keep-alive")) {
2917*6236dae4SAndroid Build Coastguard Worker       /*
2918*6236dae4SAndroid Build Coastguard Worker        * An HTTP/1.0 reply with the 'Connection: keep-alive' line
2919*6236dae4SAndroid Build Coastguard Worker        * tells us the connection will be kept alive for our
2920*6236dae4SAndroid Build Coastguard Worker        * pleasure. Default action for 1.0 is to close.
2921*6236dae4SAndroid Build Coastguard Worker        *
2922*6236dae4SAndroid Build Coastguard Worker        * [RFC2068, section 19.7.1] */
2923*6236dae4SAndroid Build Coastguard Worker       connkeep(conn, "Connection keep-alive");
2924*6236dae4SAndroid Build Coastguard Worker       infof(data, "HTTP/1.0 connection set to keep alive");
2925*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2926*6236dae4SAndroid Build Coastguard Worker     }
2927*6236dae4SAndroid Build Coastguard Worker     v = !k->http_bodyless ? HD_VAL(hd, hdlen, "Content-Range:") : NULL;
2928*6236dae4SAndroid Build Coastguard Worker     if(v) {
2929*6236dae4SAndroid Build Coastguard Worker       /* Content-Range: bytes [num]-
2930*6236dae4SAndroid Build Coastguard Worker          Content-Range: bytes: [num]-
2931*6236dae4SAndroid Build Coastguard Worker          Content-Range: [num]-
2932*6236dae4SAndroid Build Coastguard Worker          Content-Range: [asterisk]/[total]
2933*6236dae4SAndroid Build Coastguard Worker 
2934*6236dae4SAndroid Build Coastguard Worker          The second format was added since Sun's webserver
2935*6236dae4SAndroid Build Coastguard Worker          JavaWebServer/1.1.1 obviously sends the header this way!
2936*6236dae4SAndroid Build Coastguard Worker          The third added since some servers use that!
2937*6236dae4SAndroid Build Coastguard Worker          The fourth means the requested range was unsatisfied.
2938*6236dae4SAndroid Build Coastguard Worker       */
2939*6236dae4SAndroid Build Coastguard Worker 
2940*6236dae4SAndroid Build Coastguard Worker       const char *ptr = v;
2941*6236dae4SAndroid Build Coastguard Worker 
2942*6236dae4SAndroid Build Coastguard Worker       /* Move forward until first digit or asterisk */
2943*6236dae4SAndroid Build Coastguard Worker       while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
2944*6236dae4SAndroid Build Coastguard Worker         ptr++;
2945*6236dae4SAndroid Build Coastguard Worker 
2946*6236dae4SAndroid Build Coastguard Worker       /* if it truly stopped on a digit */
2947*6236dae4SAndroid Build Coastguard Worker       if(ISDIGIT(*ptr)) {
2948*6236dae4SAndroid Build Coastguard Worker         if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
2949*6236dae4SAndroid Build Coastguard Worker           if(data->state.resume_from == k->offset)
2950*6236dae4SAndroid Build Coastguard Worker             /* we asked for a resume and we got it */
2951*6236dae4SAndroid Build Coastguard Worker             k->content_range = TRUE;
2952*6236dae4SAndroid Build Coastguard Worker         }
2953*6236dae4SAndroid Build Coastguard Worker       }
2954*6236dae4SAndroid Build Coastguard Worker       else if(k->httpcode < 300)
2955*6236dae4SAndroid Build Coastguard Worker         data->state.resume_from = 0; /* get everything */
2956*6236dae4SAndroid Build Coastguard Worker     }
2957*6236dae4SAndroid Build Coastguard Worker     break;
2958*6236dae4SAndroid Build Coastguard Worker   case 'l':
2959*6236dae4SAndroid Build Coastguard Worker   case 'L':
2960*6236dae4SAndroid Build Coastguard Worker     v = (!k->http_bodyless &&
2961*6236dae4SAndroid Build Coastguard Worker          (data->set.timecondition || data->set.get_filetime)) ?
2962*6236dae4SAndroid Build Coastguard Worker         HD_VAL(hd, hdlen, "Last-Modified:") : NULL;
2963*6236dae4SAndroid Build Coastguard Worker     if(v) {
2964*6236dae4SAndroid Build Coastguard Worker       k->timeofdoc = Curl_getdate_capped(v);
2965*6236dae4SAndroid Build Coastguard Worker       if(data->set.get_filetime)
2966*6236dae4SAndroid Build Coastguard Worker         data->info.filetime = k->timeofdoc;
2967*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
2968*6236dae4SAndroid Build Coastguard Worker     }
2969*6236dae4SAndroid Build Coastguard Worker     if((k->httpcode >= 300 && k->httpcode < 400) &&
2970*6236dae4SAndroid Build Coastguard Worker             HD_IS(hd, hdlen, "Location:") &&
2971*6236dae4SAndroid Build Coastguard Worker             !data->req.location) {
2972*6236dae4SAndroid Build Coastguard Worker       /* this is the URL that the server advises us to use instead */
2973*6236dae4SAndroid Build Coastguard Worker       char *location = Curl_copy_header_value(hd);
2974*6236dae4SAndroid Build Coastguard Worker       if(!location)
2975*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
2976*6236dae4SAndroid Build Coastguard Worker       if(!*location)
2977*6236dae4SAndroid Build Coastguard Worker         /* ignore empty data */
2978*6236dae4SAndroid Build Coastguard Worker         free(location);
2979*6236dae4SAndroid Build Coastguard Worker       else {
2980*6236dae4SAndroid Build Coastguard Worker         data->req.location = location;
2981*6236dae4SAndroid Build Coastguard Worker 
2982*6236dae4SAndroid Build Coastguard Worker         if(data->set.http_follow_location) {
2983*6236dae4SAndroid Build Coastguard Worker           DEBUGASSERT(!data->req.newurl);
2984*6236dae4SAndroid Build Coastguard Worker           data->req.newurl = strdup(data->req.location); /* clone */
2985*6236dae4SAndroid Build Coastguard Worker           if(!data->req.newurl)
2986*6236dae4SAndroid Build Coastguard Worker             return CURLE_OUT_OF_MEMORY;
2987*6236dae4SAndroid Build Coastguard Worker 
2988*6236dae4SAndroid Build Coastguard Worker           /* some cases of POST and PUT etc needs to rewind the data
2989*6236dae4SAndroid Build Coastguard Worker              stream at this point */
2990*6236dae4SAndroid Build Coastguard Worker           result = http_perhapsrewind(data, conn);
2991*6236dae4SAndroid Build Coastguard Worker           if(result)
2992*6236dae4SAndroid Build Coastguard Worker             return result;
2993*6236dae4SAndroid Build Coastguard Worker 
2994*6236dae4SAndroid Build Coastguard Worker           /* mark the next request as a followed location: */
2995*6236dae4SAndroid Build Coastguard Worker           data->state.this_is_a_follow = TRUE;
2996*6236dae4SAndroid Build Coastguard Worker         }
2997*6236dae4SAndroid Build Coastguard Worker       }
2998*6236dae4SAndroid Build Coastguard Worker     }
2999*6236dae4SAndroid Build Coastguard Worker     break;
3000*6236dae4SAndroid Build Coastguard Worker   case 'p':
3001*6236dae4SAndroid Build Coastguard Worker   case 'P':
3002*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
3003*6236dae4SAndroid Build Coastguard Worker     v = HD_VAL(hd, hdlen, "Proxy-Connection:");
3004*6236dae4SAndroid Build Coastguard Worker     if(v) {
3005*6236dae4SAndroid Build Coastguard Worker       if((conn->httpversion == 10) && conn->bits.httpproxy &&
3006*6236dae4SAndroid Build Coastguard Worker          HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "keep-alive")) {
3007*6236dae4SAndroid Build Coastguard Worker         /*
3008*6236dae4SAndroid Build Coastguard Worker          * When an HTTP/1.0 reply comes when using a proxy, the
3009*6236dae4SAndroid Build Coastguard Worker          * 'Proxy-Connection: keep-alive' line tells us the
3010*6236dae4SAndroid Build Coastguard Worker          * connection will be kept alive for our pleasure.
3011*6236dae4SAndroid Build Coastguard Worker          * Default action for 1.0 is to close.
3012*6236dae4SAndroid Build Coastguard Worker          */
3013*6236dae4SAndroid Build Coastguard Worker         connkeep(conn, "Proxy-Connection keep-alive"); /* do not close */
3014*6236dae4SAndroid Build Coastguard Worker         infof(data, "HTTP/1.0 proxy connection set to keep alive");
3015*6236dae4SAndroid Build Coastguard Worker       }
3016*6236dae4SAndroid Build Coastguard Worker       else if((conn->httpversion == 11) && conn->bits.httpproxy &&
3017*6236dae4SAndroid Build Coastguard Worker               HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "close")) {
3018*6236dae4SAndroid Build Coastguard Worker         /*
3019*6236dae4SAndroid Build Coastguard Worker          * We get an HTTP/1.1 response from a proxy and it says it will
3020*6236dae4SAndroid Build Coastguard Worker          * close down after this transfer.
3021*6236dae4SAndroid Build Coastguard Worker          */
3022*6236dae4SAndroid Build Coastguard Worker         connclose(conn, "Proxy-Connection: asked to close after done");
3023*6236dae4SAndroid Build Coastguard Worker         infof(data, "HTTP/1.1 proxy connection set close");
3024*6236dae4SAndroid Build Coastguard Worker       }
3025*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
3026*6236dae4SAndroid Build Coastguard Worker     }
3027*6236dae4SAndroid Build Coastguard Worker #endif
3028*6236dae4SAndroid Build Coastguard Worker     if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) {
3029*6236dae4SAndroid Build Coastguard Worker       char *auth = Curl_copy_header_value(hd);
3030*6236dae4SAndroid Build Coastguard Worker       if(!auth)
3031*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
3032*6236dae4SAndroid Build Coastguard Worker       result = Curl_http_input_auth(data, TRUE, auth);
3033*6236dae4SAndroid Build Coastguard Worker       free(auth);
3034*6236dae4SAndroid Build Coastguard Worker       return result;
3035*6236dae4SAndroid Build Coastguard Worker     }
3036*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SPNEGO
3037*6236dae4SAndroid Build Coastguard Worker     if(HD_IS(hd, hdlen, "Persistent-Auth:")) {
3038*6236dae4SAndroid Build Coastguard Worker       struct negotiatedata *negdata = &conn->negotiate;
3039*6236dae4SAndroid Build Coastguard Worker       struct auth *authp = &data->state.authhost;
3040*6236dae4SAndroid Build Coastguard Worker       if(authp->picked == CURLAUTH_NEGOTIATE) {
3041*6236dae4SAndroid Build Coastguard Worker         char *persistentauth = Curl_copy_header_value(hd);
3042*6236dae4SAndroid Build Coastguard Worker         if(!persistentauth)
3043*6236dae4SAndroid Build Coastguard Worker           return CURLE_OUT_OF_MEMORY;
3044*6236dae4SAndroid Build Coastguard Worker         negdata->noauthpersist = !!checkprefix("false", persistentauth);
3045*6236dae4SAndroid Build Coastguard Worker         negdata->havenoauthpersist = TRUE;
3046*6236dae4SAndroid Build Coastguard Worker         infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
3047*6236dae4SAndroid Build Coastguard Worker               negdata->noauthpersist, persistentauth);
3048*6236dae4SAndroid Build Coastguard Worker         free(persistentauth);
3049*6236dae4SAndroid Build Coastguard Worker       }
3050*6236dae4SAndroid Build Coastguard Worker     }
3051*6236dae4SAndroid Build Coastguard Worker #endif
3052*6236dae4SAndroid Build Coastguard Worker     break;
3053*6236dae4SAndroid Build Coastguard Worker   case 'r':
3054*6236dae4SAndroid Build Coastguard Worker   case 'R':
3055*6236dae4SAndroid Build Coastguard Worker     v = HD_VAL(hd, hdlen, "Retry-After:");
3056*6236dae4SAndroid Build Coastguard Worker     if(v) {
3057*6236dae4SAndroid Build Coastguard Worker       /* Retry-After = HTTP-date / delay-seconds */
3058*6236dae4SAndroid Build Coastguard Worker       curl_off_t retry_after = 0; /* zero for unknown or "now" */
3059*6236dae4SAndroid Build Coastguard Worker       /* Try it as a decimal number, if it works it is not a date */
3060*6236dae4SAndroid Build Coastguard Worker       (void)curlx_strtoofft(v, NULL, 10, &retry_after);
3061*6236dae4SAndroid Build Coastguard Worker       if(!retry_after) {
3062*6236dae4SAndroid Build Coastguard Worker         time_t date = Curl_getdate_capped(v);
3063*6236dae4SAndroid Build Coastguard Worker         if(-1 != date)
3064*6236dae4SAndroid Build Coastguard Worker           /* convert date to number of seconds into the future */
3065*6236dae4SAndroid Build Coastguard Worker           retry_after = date - time(NULL);
3066*6236dae4SAndroid Build Coastguard Worker       }
3067*6236dae4SAndroid Build Coastguard Worker       data->info.retry_after = retry_after; /* store it */
3068*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
3069*6236dae4SAndroid Build Coastguard Worker     }
3070*6236dae4SAndroid Build Coastguard Worker     break;
3071*6236dae4SAndroid Build Coastguard Worker   case 's':
3072*6236dae4SAndroid Build Coastguard Worker   case 'S':
3073*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_COOKIES)
3074*6236dae4SAndroid Build Coastguard Worker     v = (data->cookies && data->state.cookie_engine) ?
3075*6236dae4SAndroid Build Coastguard Worker         HD_VAL(hd, hdlen, "Set-Cookie:") : NULL;
3076*6236dae4SAndroid Build Coastguard Worker     if(v) {
3077*6236dae4SAndroid Build Coastguard Worker       /* If there is a custom-set Host: name, use it here, or else use
3078*6236dae4SAndroid Build Coastguard Worker        * real peer hostname. */
3079*6236dae4SAndroid Build Coastguard Worker       const char *host = data->state.aptr.cookiehost ?
3080*6236dae4SAndroid Build Coastguard Worker         data->state.aptr.cookiehost : conn->host.name;
3081*6236dae4SAndroid Build Coastguard Worker       const bool secure_context =
3082*6236dae4SAndroid Build Coastguard Worker         conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
3083*6236dae4SAndroid Build Coastguard Worker         strcasecompare("localhost", host) ||
3084*6236dae4SAndroid Build Coastguard Worker         !strcmp(host, "127.0.0.1") ||
3085*6236dae4SAndroid Build Coastguard Worker         !strcmp(host, "::1");
3086*6236dae4SAndroid Build Coastguard Worker 
3087*6236dae4SAndroid Build Coastguard Worker       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3088*6236dae4SAndroid Build Coastguard Worker                       CURL_LOCK_ACCESS_SINGLE);
3089*6236dae4SAndroid Build Coastguard Worker       Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host,
3090*6236dae4SAndroid Build Coastguard Worker                       data->state.up.path, secure_context);
3091*6236dae4SAndroid Build Coastguard Worker       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3092*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
3093*6236dae4SAndroid Build Coastguard Worker     }
3094*6236dae4SAndroid Build Coastguard Worker #endif
3095*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HSTS
3096*6236dae4SAndroid Build Coastguard Worker     /* If enabled, the header is incoming and this is over HTTPS */
3097*6236dae4SAndroid Build Coastguard Worker     v = (data->hsts &&
3098*6236dae4SAndroid Build Coastguard Worker          ((conn->handler->flags & PROTOPT_SSL) ||
3099*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
3100*6236dae4SAndroid Build Coastguard Worker            /* allow debug builds to circumvent the HTTPS restriction */
3101*6236dae4SAndroid Build Coastguard Worker            getenv("CURL_HSTS_HTTP")
3102*6236dae4SAndroid Build Coastguard Worker #else
3103*6236dae4SAndroid Build Coastguard Worker            0
3104*6236dae4SAndroid Build Coastguard Worker #endif
3105*6236dae4SAndroid Build Coastguard Worker             )
3106*6236dae4SAndroid Build Coastguard Worker         ) ? HD_VAL(hd, hdlen, "Strict-Transport-Security:") : NULL;
3107*6236dae4SAndroid Build Coastguard Worker     if(v) {
3108*6236dae4SAndroid Build Coastguard Worker       CURLcode check =
3109*6236dae4SAndroid Build Coastguard Worker         Curl_hsts_parse(data->hsts, conn->host.name, v);
3110*6236dae4SAndroid Build Coastguard Worker       if(check)
3111*6236dae4SAndroid Build Coastguard Worker         infof(data, "Illegal STS header skipped");
3112*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
3113*6236dae4SAndroid Build Coastguard Worker       else
3114*6236dae4SAndroid Build Coastguard Worker         infof(data, "Parsed STS header fine (%zu entries)",
3115*6236dae4SAndroid Build Coastguard Worker               Curl_llist_count(&data->hsts->list));
3116*6236dae4SAndroid Build Coastguard Worker #endif
3117*6236dae4SAndroid Build Coastguard Worker     }
3118*6236dae4SAndroid Build Coastguard Worker #endif
3119*6236dae4SAndroid Build Coastguard Worker     break;
3120*6236dae4SAndroid Build Coastguard Worker   case 't':
3121*6236dae4SAndroid Build Coastguard Worker   case 'T':
3122*6236dae4SAndroid Build Coastguard Worker     /* RFC 9112, ch. 6.1
3123*6236dae4SAndroid Build Coastguard Worker      * "Transfer-Encoding MAY be sent in a response to a HEAD request or
3124*6236dae4SAndroid Build Coastguard Worker      *  in a 304 (Not Modified) response (Section 15.4.5 of [HTTP]) to a
3125*6236dae4SAndroid Build Coastguard Worker      *  GET request, neither of which includes a message body, to indicate
3126*6236dae4SAndroid Build Coastguard Worker      *  that the origin server would have applied a transfer coding to the
3127*6236dae4SAndroid Build Coastguard Worker      *  message body if the request had been an unconditional GET."
3128*6236dae4SAndroid Build Coastguard Worker      *
3129*6236dae4SAndroid Build Coastguard Worker      * Read: in these cases the 'Transfer-Encoding' does not apply
3130*6236dae4SAndroid Build Coastguard Worker      * to any data following the response headers. Do not add any decoders.
3131*6236dae4SAndroid Build Coastguard Worker      */
3132*6236dae4SAndroid Build Coastguard Worker     v = (!k->http_bodyless &&
3133*6236dae4SAndroid Build Coastguard Worker          (data->state.httpreq != HTTPREQ_HEAD) &&
3134*6236dae4SAndroid Build Coastguard Worker          (k->httpcode != 304)) ?
3135*6236dae4SAndroid Build Coastguard Worker       HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
3136*6236dae4SAndroid Build Coastguard Worker     if(v) {
3137*6236dae4SAndroid Build Coastguard Worker       /* One or more encodings. We check for chunked and/or a compression
3138*6236dae4SAndroid Build Coastguard Worker          algorithm. */
3139*6236dae4SAndroid Build Coastguard Worker       result = Curl_build_unencoding_stack(data, v, TRUE);
3140*6236dae4SAndroid Build Coastguard Worker       if(result)
3141*6236dae4SAndroid Build Coastguard Worker         return result;
3142*6236dae4SAndroid Build Coastguard Worker       if(!k->chunk && data->set.http_transfer_encoding) {
3143*6236dae4SAndroid Build Coastguard Worker         /* if this is not chunked, only close can signal the end of this
3144*6236dae4SAndroid Build Coastguard Worker          * transfer as Content-Length is said not to be trusted for
3145*6236dae4SAndroid Build Coastguard Worker          * transfer-encoding! */
3146*6236dae4SAndroid Build Coastguard Worker         connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
3147*6236dae4SAndroid Build Coastguard Worker         k->ignore_cl = TRUE;
3148*6236dae4SAndroid Build Coastguard Worker       }
3149*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
3150*6236dae4SAndroid Build Coastguard Worker     }
3151*6236dae4SAndroid Build Coastguard Worker     v = HD_VAL(hd, hdlen, "Trailer:");
3152*6236dae4SAndroid Build Coastguard Worker     if(v) {
3153*6236dae4SAndroid Build Coastguard Worker       data->req.resp_trailer = TRUE;
3154*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
3155*6236dae4SAndroid Build Coastguard Worker     }
3156*6236dae4SAndroid Build Coastguard Worker     break;
3157*6236dae4SAndroid Build Coastguard Worker   case 'w':
3158*6236dae4SAndroid Build Coastguard Worker   case 'W':
3159*6236dae4SAndroid Build Coastguard Worker     if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) {
3160*6236dae4SAndroid Build Coastguard Worker       char *auth = Curl_copy_header_value(hd);
3161*6236dae4SAndroid Build Coastguard Worker       if(!auth)
3162*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
3163*6236dae4SAndroid Build Coastguard Worker       result = Curl_http_input_auth(data, FALSE, auth);
3164*6236dae4SAndroid Build Coastguard Worker       free(auth);
3165*6236dae4SAndroid Build Coastguard Worker       return result;
3166*6236dae4SAndroid Build Coastguard Worker     }
3167*6236dae4SAndroid Build Coastguard Worker     break;
3168*6236dae4SAndroid Build Coastguard Worker   }
3169*6236dae4SAndroid Build Coastguard Worker 
3170*6236dae4SAndroid Build Coastguard Worker   if(conn->handler->protocol & CURLPROTO_RTSP) {
3171*6236dae4SAndroid Build Coastguard Worker     result = Curl_rtsp_parseheader(data, hd);
3172*6236dae4SAndroid Build Coastguard Worker     if(result)
3173*6236dae4SAndroid Build Coastguard Worker       return result;
3174*6236dae4SAndroid Build Coastguard Worker   }
3175*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3176*6236dae4SAndroid Build Coastguard Worker }
3177*6236dae4SAndroid Build Coastguard Worker 
3178*6236dae4SAndroid Build Coastguard Worker /*
3179*6236dae4SAndroid Build Coastguard Worker  * Called after the first HTTP response line (the status line) has been
3180*6236dae4SAndroid Build Coastguard Worker  * received and parsed.
3181*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_statusline(struct Curl_easy * data,struct connectdata * conn)3182*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_statusline(struct Curl_easy *data,
3183*6236dae4SAndroid Build Coastguard Worker                               struct connectdata *conn)
3184*6236dae4SAndroid Build Coastguard Worker {
3185*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3186*6236dae4SAndroid Build Coastguard Worker 
3187*6236dae4SAndroid Build Coastguard Worker   switch(k->httpversion) {
3188*6236dae4SAndroid Build Coastguard Worker   case 10:
3189*6236dae4SAndroid Build Coastguard Worker   case 11:
3190*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP2
3191*6236dae4SAndroid Build Coastguard Worker   case 20:
3192*6236dae4SAndroid Build Coastguard Worker #endif
3193*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTP3
3194*6236dae4SAndroid Build Coastguard Worker   case 30:
3195*6236dae4SAndroid Build Coastguard Worker #endif
3196*6236dae4SAndroid Build Coastguard Worker     /* no major version switch mid-connection */
3197*6236dae4SAndroid Build Coastguard Worker     if(conn->httpversion &&
3198*6236dae4SAndroid Build Coastguard Worker        (k->httpversion/10 != conn->httpversion/10)) {
3199*6236dae4SAndroid Build Coastguard Worker       failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)",
3200*6236dae4SAndroid Build Coastguard Worker             conn->httpversion/10, k->httpversion/10);
3201*6236dae4SAndroid Build Coastguard Worker       return CURLE_UNSUPPORTED_PROTOCOL;
3202*6236dae4SAndroid Build Coastguard Worker     }
3203*6236dae4SAndroid Build Coastguard Worker     break;
3204*6236dae4SAndroid Build Coastguard Worker   default:
3205*6236dae4SAndroid Build Coastguard Worker     failf(data, "Unsupported HTTP version (%u.%d) in response",
3206*6236dae4SAndroid Build Coastguard Worker           k->httpversion/10, k->httpversion%10);
3207*6236dae4SAndroid Build Coastguard Worker     return CURLE_UNSUPPORTED_PROTOCOL;
3208*6236dae4SAndroid Build Coastguard Worker   }
3209*6236dae4SAndroid Build Coastguard Worker 
3210*6236dae4SAndroid Build Coastguard Worker   data->info.httpcode = k->httpcode;
3211*6236dae4SAndroid Build Coastguard Worker   data->info.httpversion = k->httpversion;
3212*6236dae4SAndroid Build Coastguard Worker   conn->httpversion = (unsigned char)k->httpversion;
3213*6236dae4SAndroid Build Coastguard Worker 
3214*6236dae4SAndroid Build Coastguard Worker   if(!data->state.httpversion || data->state.httpversion > k->httpversion)
3215*6236dae4SAndroid Build Coastguard Worker     /* store the lowest server version we encounter */
3216*6236dae4SAndroid Build Coastguard Worker     data->state.httpversion = (unsigned char)k->httpversion;
3217*6236dae4SAndroid Build Coastguard Worker 
3218*6236dae4SAndroid Build Coastguard Worker   /*
3219*6236dae4SAndroid Build Coastguard Worker    * This code executes as part of processing the header. As a
3220*6236dae4SAndroid Build Coastguard Worker    * result, it is not totally clear how to interpret the
3221*6236dae4SAndroid Build Coastguard Worker    * response code yet as that depends on what other headers may
3222*6236dae4SAndroid Build Coastguard Worker    * be present. 401 and 407 may be errors, but may be OK
3223*6236dae4SAndroid Build Coastguard Worker    * depending on how authentication is working. Other codes
3224*6236dae4SAndroid Build Coastguard Worker    * are definitely errors, so give up here.
3225*6236dae4SAndroid Build Coastguard Worker    */
3226*6236dae4SAndroid Build Coastguard Worker   if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
3227*6236dae4SAndroid Build Coastguard Worker      k->httpcode == 416) {
3228*6236dae4SAndroid Build Coastguard Worker     /* "Requested Range Not Satisfiable", just proceed and
3229*6236dae4SAndroid Build Coastguard Worker        pretend this is no error */
3230*6236dae4SAndroid Build Coastguard Worker     k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
3231*6236dae4SAndroid Build Coastguard Worker   }
3232*6236dae4SAndroid Build Coastguard Worker 
3233*6236dae4SAndroid Build Coastguard Worker   if(k->httpversion == 10) {
3234*6236dae4SAndroid Build Coastguard Worker     /* Default action for HTTP/1.0 must be to close, unless
3235*6236dae4SAndroid Build Coastguard Worker        we get one of those fancy headers that tell us the
3236*6236dae4SAndroid Build Coastguard Worker        server keeps it open for us! */
3237*6236dae4SAndroid Build Coastguard Worker     infof(data, "HTTP 1.0, assume close after body");
3238*6236dae4SAndroid Build Coastguard Worker     connclose(conn, "HTTP/1.0 close after body");
3239*6236dae4SAndroid Build Coastguard Worker   }
3240*6236dae4SAndroid Build Coastguard Worker   else if(k->httpversion == 20 ||
3241*6236dae4SAndroid Build Coastguard Worker           (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
3242*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
3243*6236dae4SAndroid Build Coastguard Worker   }
3244*6236dae4SAndroid Build Coastguard Worker 
3245*6236dae4SAndroid Build Coastguard Worker   k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
3246*6236dae4SAndroid Build Coastguard Worker   switch(k->httpcode) {
3247*6236dae4SAndroid Build Coastguard Worker   case 304:
3248*6236dae4SAndroid Build Coastguard Worker     /* (quote from RFC2616, section 10.3.5): The 304 response
3249*6236dae4SAndroid Build Coastguard Worker      * MUST NOT contain a message-body, and thus is always
3250*6236dae4SAndroid Build Coastguard Worker      * terminated by the first empty line after the header
3251*6236dae4SAndroid Build Coastguard Worker      * fields.  */
3252*6236dae4SAndroid Build Coastguard Worker     if(data->set.timecondition)
3253*6236dae4SAndroid Build Coastguard Worker       data->info.timecond = TRUE;
3254*6236dae4SAndroid Build Coastguard Worker     FALLTHROUGH();
3255*6236dae4SAndroid Build Coastguard Worker   case 204:
3256*6236dae4SAndroid Build Coastguard Worker     /* (quote from RFC2616, section 10.2.5): The server has
3257*6236dae4SAndroid Build Coastguard Worker      * fulfilled the request but does not need to return an
3258*6236dae4SAndroid Build Coastguard Worker      * entity-body ... The 204 response MUST NOT include a
3259*6236dae4SAndroid Build Coastguard Worker      * message-body, and thus is always terminated by the first
3260*6236dae4SAndroid Build Coastguard Worker      * empty line after the header fields. */
3261*6236dae4SAndroid Build Coastguard Worker     k->size = 0;
3262*6236dae4SAndroid Build Coastguard Worker     k->maxdownload = 0;
3263*6236dae4SAndroid Build Coastguard Worker     k->http_bodyless = TRUE;
3264*6236dae4SAndroid Build Coastguard Worker     break;
3265*6236dae4SAndroid Build Coastguard Worker   default:
3266*6236dae4SAndroid Build Coastguard Worker     break;
3267*6236dae4SAndroid Build Coastguard Worker   }
3268*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3269*6236dae4SAndroid Build Coastguard Worker }
3270*6236dae4SAndroid Build Coastguard Worker 
3271*6236dae4SAndroid Build Coastguard Worker /* Content-Length must be ignored if any Transfer-Encoding is present in the
3272*6236dae4SAndroid Build Coastguard Worker    response. Refer to RFC 7230 section 3.3.3 and RFC2616 section 4.4. This is
3273*6236dae4SAndroid Build Coastguard Worker    figured out here after all headers have been received but before the final
3274*6236dae4SAndroid Build Coastguard Worker    call to the user's header callback, so that a valid content length can be
3275*6236dae4SAndroid Build Coastguard Worker    retrieved by the user in the final call. */
Curl_http_size(struct Curl_easy * data)3276*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_size(struct Curl_easy *data)
3277*6236dae4SAndroid Build Coastguard Worker {
3278*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3279*6236dae4SAndroid Build Coastguard Worker   if(data->req.ignore_cl || k->chunk) {
3280*6236dae4SAndroid Build Coastguard Worker     k->size = k->maxdownload = -1;
3281*6236dae4SAndroid Build Coastguard Worker   }
3282*6236dae4SAndroid Build Coastguard Worker   else if(k->size != -1) {
3283*6236dae4SAndroid Build Coastguard Worker     if(data->set.max_filesize &&
3284*6236dae4SAndroid Build Coastguard Worker        !k->ignorebody &&
3285*6236dae4SAndroid Build Coastguard Worker        (k->size > data->set.max_filesize)) {
3286*6236dae4SAndroid Build Coastguard Worker       failf(data, "Maximum file size exceeded");
3287*6236dae4SAndroid Build Coastguard Worker       return CURLE_FILESIZE_EXCEEDED;
3288*6236dae4SAndroid Build Coastguard Worker     }
3289*6236dae4SAndroid Build Coastguard Worker     if(k->ignorebody)
3290*6236dae4SAndroid Build Coastguard Worker       infof(data, "setting size while ignoring");
3291*6236dae4SAndroid Build Coastguard Worker     Curl_pgrsSetDownloadSize(data, k->size);
3292*6236dae4SAndroid Build Coastguard Worker     k->maxdownload = k->size;
3293*6236dae4SAndroid Build Coastguard Worker   }
3294*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3295*6236dae4SAndroid Build Coastguard Worker }
3296*6236dae4SAndroid Build Coastguard Worker 
verify_header(struct Curl_easy * data,const char * hd,size_t hdlen)3297*6236dae4SAndroid Build Coastguard Worker static CURLcode verify_header(struct Curl_easy *data,
3298*6236dae4SAndroid Build Coastguard Worker                               const char *hd, size_t hdlen)
3299*6236dae4SAndroid Build Coastguard Worker {
3300*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3301*6236dae4SAndroid Build Coastguard Worker   char *ptr = memchr(hd, 0x00, hdlen);
3302*6236dae4SAndroid Build Coastguard Worker   if(ptr) {
3303*6236dae4SAndroid Build Coastguard Worker     /* this is bad, bail out */
3304*6236dae4SAndroid Build Coastguard Worker     failf(data, "Nul byte in header");
3305*6236dae4SAndroid Build Coastguard Worker     return CURLE_WEIRD_SERVER_REPLY;
3306*6236dae4SAndroid Build Coastguard Worker   }
3307*6236dae4SAndroid Build Coastguard Worker   if(k->headerline < 2)
3308*6236dae4SAndroid Build Coastguard Worker     /* the first "header" is the status-line and it has no colon */
3309*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
3310*6236dae4SAndroid Build Coastguard Worker   if(((hd[0] == ' ') || (hd[0] == '\t')) && k->headerline > 2)
3311*6236dae4SAndroid Build Coastguard Worker     /* line folding, cannot happen on line 2 */
3312*6236dae4SAndroid Build Coastguard Worker     ;
3313*6236dae4SAndroid Build Coastguard Worker   else {
3314*6236dae4SAndroid Build Coastguard Worker     ptr = memchr(hd, ':', hdlen);
3315*6236dae4SAndroid Build Coastguard Worker     if(!ptr) {
3316*6236dae4SAndroid Build Coastguard Worker       /* this is bad, bail out */
3317*6236dae4SAndroid Build Coastguard Worker       failf(data, "Header without colon");
3318*6236dae4SAndroid Build Coastguard Worker       return CURLE_WEIRD_SERVER_REPLY;
3319*6236dae4SAndroid Build Coastguard Worker     }
3320*6236dae4SAndroid Build Coastguard Worker   }
3321*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3322*6236dae4SAndroid Build Coastguard Worker }
3323*6236dae4SAndroid Build Coastguard Worker 
Curl_bump_headersize(struct Curl_easy * data,size_t delta,bool connect_only)3324*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_bump_headersize(struct Curl_easy *data,
3325*6236dae4SAndroid Build Coastguard Worker                               size_t delta,
3326*6236dae4SAndroid Build Coastguard Worker                               bool connect_only)
3327*6236dae4SAndroid Build Coastguard Worker {
3328*6236dae4SAndroid Build Coastguard Worker   size_t bad = 0;
3329*6236dae4SAndroid Build Coastguard Worker   unsigned int max = MAX_HTTP_RESP_HEADER_SIZE;
3330*6236dae4SAndroid Build Coastguard Worker   if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
3331*6236dae4SAndroid Build Coastguard Worker     data->info.header_size += (unsigned int)delta;
3332*6236dae4SAndroid Build Coastguard Worker     data->req.allheadercount += (unsigned int)delta;
3333*6236dae4SAndroid Build Coastguard Worker     if(!connect_only)
3334*6236dae4SAndroid Build Coastguard Worker       data->req.headerbytecount += (unsigned int)delta;
3335*6236dae4SAndroid Build Coastguard Worker     if(data->req.allheadercount > max)
3336*6236dae4SAndroid Build Coastguard Worker       bad = data->req.allheadercount;
3337*6236dae4SAndroid Build Coastguard Worker     else if(data->info.header_size > (max * 20)) {
3338*6236dae4SAndroid Build Coastguard Worker       bad = data->info.header_size;
3339*6236dae4SAndroid Build Coastguard Worker       max *= 20;
3340*6236dae4SAndroid Build Coastguard Worker     }
3341*6236dae4SAndroid Build Coastguard Worker   }
3342*6236dae4SAndroid Build Coastguard Worker   else
3343*6236dae4SAndroid Build Coastguard Worker     bad = data->req.allheadercount + delta;
3344*6236dae4SAndroid Build Coastguard Worker   if(bad) {
3345*6236dae4SAndroid Build Coastguard Worker     failf(data, "Too large response headers: %zu > %u", bad, max);
3346*6236dae4SAndroid Build Coastguard Worker     return CURLE_RECV_ERROR;
3347*6236dae4SAndroid Build Coastguard Worker   }
3348*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3349*6236dae4SAndroid Build Coastguard Worker }
3350*6236dae4SAndroid Build Coastguard Worker 
http_write_header(struct Curl_easy * data,const char * hd,size_t hdlen)3351*6236dae4SAndroid Build Coastguard Worker static CURLcode http_write_header(struct Curl_easy *data,
3352*6236dae4SAndroid Build Coastguard Worker                                   const char *hd, size_t hdlen)
3353*6236dae4SAndroid Build Coastguard Worker {
3354*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
3355*6236dae4SAndroid Build Coastguard Worker   int writetype;
3356*6236dae4SAndroid Build Coastguard Worker 
3357*6236dae4SAndroid Build Coastguard Worker   /* now, only output this if the header AND body are requested:
3358*6236dae4SAndroid Build Coastguard Worker    */
3359*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_IN, (char *)hd, hdlen);
3360*6236dae4SAndroid Build Coastguard Worker 
3361*6236dae4SAndroid Build Coastguard Worker   writetype = CLIENTWRITE_HEADER |
3362*6236dae4SAndroid Build Coastguard Worker     ((data->req.httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
3363*6236dae4SAndroid Build Coastguard Worker 
3364*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_write(data, writetype, hd, hdlen);
3365*6236dae4SAndroid Build Coastguard Worker   if(result)
3366*6236dae4SAndroid Build Coastguard Worker     return result;
3367*6236dae4SAndroid Build Coastguard Worker 
3368*6236dae4SAndroid Build Coastguard Worker   result = Curl_bump_headersize(data, hdlen, FALSE);
3369*6236dae4SAndroid Build Coastguard Worker   if(result)
3370*6236dae4SAndroid Build Coastguard Worker     return result;
3371*6236dae4SAndroid Build Coastguard Worker 
3372*6236dae4SAndroid Build Coastguard Worker   data->req.deductheadercount = (100 <= data->req.httpcode &&
3373*6236dae4SAndroid Build Coastguard Worker                                  199 >= data->req.httpcode) ?
3374*6236dae4SAndroid Build Coastguard Worker     data->req.headerbytecount : 0;
3375*6236dae4SAndroid Build Coastguard Worker   return result;
3376*6236dae4SAndroid Build Coastguard Worker }
3377*6236dae4SAndroid Build Coastguard Worker 
http_on_response(struct Curl_easy * data,const char * last_hd,size_t last_hd_len,const char * buf,size_t blen,size_t * pconsumed)3378*6236dae4SAndroid Build Coastguard Worker static CURLcode http_on_response(struct Curl_easy *data,
3379*6236dae4SAndroid Build Coastguard Worker                                  const char *last_hd, size_t last_hd_len,
3380*6236dae4SAndroid Build Coastguard Worker                                  const char *buf, size_t blen,
3381*6236dae4SAndroid Build Coastguard Worker                                  size_t *pconsumed)
3382*6236dae4SAndroid Build Coastguard Worker {
3383*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
3384*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3385*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3386*6236dae4SAndroid Build Coastguard Worker 
3387*6236dae4SAndroid Build Coastguard Worker   (void)buf; /* not used without HTTP2 enabled */
3388*6236dae4SAndroid Build Coastguard Worker   *pconsumed = 0;
3389*6236dae4SAndroid Build Coastguard Worker 
3390*6236dae4SAndroid Build Coastguard Worker   if(k->upgr101 == UPGR101_RECEIVED) {
3391*6236dae4SAndroid Build Coastguard Worker     /* supposedly upgraded to http2 now */
3392*6236dae4SAndroid Build Coastguard Worker     if(conn->httpversion != 20)
3393*6236dae4SAndroid Build Coastguard Worker       infof(data, "Lying server, not serving HTTP/2");
3394*6236dae4SAndroid Build Coastguard Worker   }
3395*6236dae4SAndroid Build Coastguard Worker 
3396*6236dae4SAndroid Build Coastguard Worker   if(k->httpcode < 200 && last_hd) {
3397*6236dae4SAndroid Build Coastguard Worker     /* Intermediate responses might trigger processing of more
3398*6236dae4SAndroid Build Coastguard Worker      * responses, write the last header to the client before
3399*6236dae4SAndroid Build Coastguard Worker      * proceeding. */
3400*6236dae4SAndroid Build Coastguard Worker     result = http_write_header(data, last_hd, last_hd_len);
3401*6236dae4SAndroid Build Coastguard Worker     last_hd = NULL; /* handled it */
3402*6236dae4SAndroid Build Coastguard Worker     if(result)
3403*6236dae4SAndroid Build Coastguard Worker       goto out;
3404*6236dae4SAndroid Build Coastguard Worker   }
3405*6236dae4SAndroid Build Coastguard Worker 
3406*6236dae4SAndroid Build Coastguard Worker   if(k->httpcode < 100) {
3407*6236dae4SAndroid Build Coastguard Worker     failf(data, "Unsupported response code in HTTP response");
3408*6236dae4SAndroid Build Coastguard Worker     result = CURLE_UNSUPPORTED_PROTOCOL;
3409*6236dae4SAndroid Build Coastguard Worker     goto out;
3410*6236dae4SAndroid Build Coastguard Worker   }
3411*6236dae4SAndroid Build Coastguard Worker   else if(k->httpcode < 200) {
3412*6236dae4SAndroid Build Coastguard Worker     /* "A user agent MAY ignore unexpected 1xx status responses."
3413*6236dae4SAndroid Build Coastguard Worker      * By default, we expect to get more responses after this one. */
3414*6236dae4SAndroid Build Coastguard Worker     k->header = TRUE;
3415*6236dae4SAndroid Build Coastguard Worker     k->headerline = 0; /* restart the header line counter */
3416*6236dae4SAndroid Build Coastguard Worker 
3417*6236dae4SAndroid Build Coastguard Worker     switch(k->httpcode) {
3418*6236dae4SAndroid Build Coastguard Worker     case 100:
3419*6236dae4SAndroid Build Coastguard Worker       /*
3420*6236dae4SAndroid Build Coastguard Worker        * We have made an HTTP PUT or POST and this is 1.1-lingo
3421*6236dae4SAndroid Build Coastguard Worker        * that tells us that the server is OK with this and ready
3422*6236dae4SAndroid Build Coastguard Worker        * to receive the data.
3423*6236dae4SAndroid Build Coastguard Worker        */
3424*6236dae4SAndroid Build Coastguard Worker       Curl_http_exp100_got100(data);
3425*6236dae4SAndroid Build Coastguard Worker       break;
3426*6236dae4SAndroid Build Coastguard Worker     case 101:
3427*6236dae4SAndroid Build Coastguard Worker       /* Switching Protocols only allowed from HTTP/1.1 */
3428*6236dae4SAndroid Build Coastguard Worker 
3429*6236dae4SAndroid Build Coastguard Worker       if(conn->httpversion != 11) {
3430*6236dae4SAndroid Build Coastguard Worker         /* invalid for other HTTP versions */
3431*6236dae4SAndroid Build Coastguard Worker         failf(data, "unexpected 101 response code");
3432*6236dae4SAndroid Build Coastguard Worker         result = CURLE_WEIRD_SERVER_REPLY;
3433*6236dae4SAndroid Build Coastguard Worker         goto out;
3434*6236dae4SAndroid Build Coastguard Worker       }
3435*6236dae4SAndroid Build Coastguard Worker       if(k->upgr101 == UPGR101_H2) {
3436*6236dae4SAndroid Build Coastguard Worker         /* Switching to HTTP/2, where we will get more responses */
3437*6236dae4SAndroid Build Coastguard Worker         infof(data, "Received 101, Switching to HTTP/2");
3438*6236dae4SAndroid Build Coastguard Worker         k->upgr101 = UPGR101_RECEIVED;
3439*6236dae4SAndroid Build Coastguard Worker         data->conn->bits.asks_multiplex = FALSE;
3440*6236dae4SAndroid Build Coastguard Worker         /* We expect more response from HTTP/2 later */
3441*6236dae4SAndroid Build Coastguard Worker         k->header = TRUE;
3442*6236dae4SAndroid Build Coastguard Worker         k->headerline = 0; /* restart the header line counter */
3443*6236dae4SAndroid Build Coastguard Worker         /* Any remaining `buf` bytes are already HTTP/2 and passed to
3444*6236dae4SAndroid Build Coastguard Worker          * be processed. */
3445*6236dae4SAndroid Build Coastguard Worker         result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
3446*6236dae4SAndroid Build Coastguard Worker         if(result)
3447*6236dae4SAndroid Build Coastguard Worker           goto out;
3448*6236dae4SAndroid Build Coastguard Worker         *pconsumed += blen;
3449*6236dae4SAndroid Build Coastguard Worker       }
3450*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_WEBSOCKETS
3451*6236dae4SAndroid Build Coastguard Worker       else if(k->upgr101 == UPGR101_WS) {
3452*6236dae4SAndroid Build Coastguard Worker         /* verify the response. Any passed `buf` bytes are already in
3453*6236dae4SAndroid Build Coastguard Worker          * WebSockets format and taken in by the protocol handler. */
3454*6236dae4SAndroid Build Coastguard Worker         result = Curl_ws_accept(data, buf, blen);
3455*6236dae4SAndroid Build Coastguard Worker         if(result)
3456*6236dae4SAndroid Build Coastguard Worker           goto out;
3457*6236dae4SAndroid Build Coastguard Worker         *pconsumed += blen; /* ws accept handled the data */
3458*6236dae4SAndroid Build Coastguard Worker         k->header = FALSE; /* we will not get more responses */
3459*6236dae4SAndroid Build Coastguard Worker         if(data->set.connect_only)
3460*6236dae4SAndroid Build Coastguard Worker           k->keepon &= ~KEEP_RECV; /* read no more content */
3461*6236dae4SAndroid Build Coastguard Worker       }
3462*6236dae4SAndroid Build Coastguard Worker #endif
3463*6236dae4SAndroid Build Coastguard Worker       else {
3464*6236dae4SAndroid Build Coastguard Worker         /* We silently accept this as the final response.
3465*6236dae4SAndroid Build Coastguard Worker          * TODO: this looks, uhm, wrong. What are we switching to if we
3466*6236dae4SAndroid Build Coastguard Worker          * did not ask for an Upgrade? Maybe the application provided an
3467*6236dae4SAndroid Build Coastguard Worker          * `Upgrade: xxx` header? */
3468*6236dae4SAndroid Build Coastguard Worker         k->header = FALSE;
3469*6236dae4SAndroid Build Coastguard Worker       }
3470*6236dae4SAndroid Build Coastguard Worker       break;
3471*6236dae4SAndroid Build Coastguard Worker     default:
3472*6236dae4SAndroid Build Coastguard Worker       /* The server may send us other 1xx responses, like informative
3473*6236dae4SAndroid Build Coastguard Worker        * 103. This have no influence on request processing and we expect
3474*6236dae4SAndroid Build Coastguard Worker        * to receive a final response eventually. */
3475*6236dae4SAndroid Build Coastguard Worker       break;
3476*6236dae4SAndroid Build Coastguard Worker     }
3477*6236dae4SAndroid Build Coastguard Worker     goto out;
3478*6236dae4SAndroid Build Coastguard Worker   }
3479*6236dae4SAndroid Build Coastguard Worker 
3480*6236dae4SAndroid Build Coastguard Worker   /* k->httpcode >= 200, final response */
3481*6236dae4SAndroid Build Coastguard Worker   k->header = FALSE;
3482*6236dae4SAndroid Build Coastguard Worker 
3483*6236dae4SAndroid Build Coastguard Worker   if(k->upgr101 == UPGR101_H2) {
3484*6236dae4SAndroid Build Coastguard Worker     /* A requested upgrade was denied, poke the multi handle to possibly
3485*6236dae4SAndroid Build Coastguard Worker        allow a pending pipewait to continue */
3486*6236dae4SAndroid Build Coastguard Worker     data->conn->bits.asks_multiplex = FALSE;
3487*6236dae4SAndroid Build Coastguard Worker     Curl_multi_connchanged(data->multi);
3488*6236dae4SAndroid Build Coastguard Worker   }
3489*6236dae4SAndroid Build Coastguard Worker 
3490*6236dae4SAndroid Build Coastguard Worker   if((k->size == -1) && !k->chunk && !conn->bits.close &&
3491*6236dae4SAndroid Build Coastguard Worker      (conn->httpversion == 11) &&
3492*6236dae4SAndroid Build Coastguard Worker      !(conn->handler->protocol & CURLPROTO_RTSP) &&
3493*6236dae4SAndroid Build Coastguard Worker      data->state.httpreq != HTTPREQ_HEAD) {
3494*6236dae4SAndroid Build Coastguard Worker     /* On HTTP 1.1, when connection is not to get closed, but no
3495*6236dae4SAndroid Build Coastguard Worker        Content-Length nor Transfer-Encoding chunked have been
3496*6236dae4SAndroid Build Coastguard Worker        received, according to RFC2616 section 4.4 point 5, we
3497*6236dae4SAndroid Build Coastguard Worker        assume that the server will close the connection to
3498*6236dae4SAndroid Build Coastguard Worker        signal the end of the document. */
3499*6236dae4SAndroid Build Coastguard Worker     infof(data, "no chunk, no close, no size. Assume close to "
3500*6236dae4SAndroid Build Coastguard Worker           "signal end");
3501*6236dae4SAndroid Build Coastguard Worker     streamclose(conn, "HTTP: No end-of-message indicator");
3502*6236dae4SAndroid Build Coastguard Worker   }
3503*6236dae4SAndroid Build Coastguard Worker 
3504*6236dae4SAndroid Build Coastguard Worker   /* At this point we have some idea about the fate of the connection.
3505*6236dae4SAndroid Build Coastguard Worker      If we are closing the connection it may result auth failure. */
3506*6236dae4SAndroid Build Coastguard Worker #if defined(USE_NTLM)
3507*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.close &&
3508*6236dae4SAndroid Build Coastguard Worker      (((data->req.httpcode == 401) &&
3509*6236dae4SAndroid Build Coastguard Worker        (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
3510*6236dae4SAndroid Build Coastguard Worker       ((data->req.httpcode == 407) &&
3511*6236dae4SAndroid Build Coastguard Worker        (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
3512*6236dae4SAndroid Build Coastguard Worker     infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
3513*6236dae4SAndroid Build Coastguard Worker     data->state.authproblem = TRUE;
3514*6236dae4SAndroid Build Coastguard Worker   }
3515*6236dae4SAndroid Build Coastguard Worker #endif
3516*6236dae4SAndroid Build Coastguard Worker #if defined(USE_SPNEGO)
3517*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.close &&
3518*6236dae4SAndroid Build Coastguard Worker     (((data->req.httpcode == 401) &&
3519*6236dae4SAndroid Build Coastguard Worker       (conn->http_negotiate_state == GSS_AUTHRECV)) ||
3520*6236dae4SAndroid Build Coastguard Worker      ((data->req.httpcode == 407) &&
3521*6236dae4SAndroid Build Coastguard Worker       (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
3522*6236dae4SAndroid Build Coastguard Worker     infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
3523*6236dae4SAndroid Build Coastguard Worker     data->state.authproblem = TRUE;
3524*6236dae4SAndroid Build Coastguard Worker   }
3525*6236dae4SAndroid Build Coastguard Worker   if((conn->http_negotiate_state == GSS_AUTHDONE) &&
3526*6236dae4SAndroid Build Coastguard Worker      (data->req.httpcode != 401)) {
3527*6236dae4SAndroid Build Coastguard Worker     conn->http_negotiate_state = GSS_AUTHSUCC;
3528*6236dae4SAndroid Build Coastguard Worker   }
3529*6236dae4SAndroid Build Coastguard Worker   if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
3530*6236dae4SAndroid Build Coastguard Worker      (data->req.httpcode != 407)) {
3531*6236dae4SAndroid Build Coastguard Worker     conn->proxy_negotiate_state = GSS_AUTHSUCC;
3532*6236dae4SAndroid Build Coastguard Worker   }
3533*6236dae4SAndroid Build Coastguard Worker #endif
3534*6236dae4SAndroid Build Coastguard Worker 
3535*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_WEBSOCKETS
3536*6236dae4SAndroid Build Coastguard Worker   /* All >=200 HTTP status codes are errors when wanting WebSockets */
3537*6236dae4SAndroid Build Coastguard Worker   if(data->req.upgr101 == UPGR101_WS) {
3538*6236dae4SAndroid Build Coastguard Worker     failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
3539*6236dae4SAndroid Build Coastguard Worker     result = CURLE_HTTP_RETURNED_ERROR;
3540*6236dae4SAndroid Build Coastguard Worker     goto out;
3541*6236dae4SAndroid Build Coastguard Worker   }
3542*6236dae4SAndroid Build Coastguard Worker #endif
3543*6236dae4SAndroid Build Coastguard Worker 
3544*6236dae4SAndroid Build Coastguard Worker   /* Check if this response means the transfer errored. */
3545*6236dae4SAndroid Build Coastguard Worker   if(http_should_fail(data, data->req.httpcode)) {
3546*6236dae4SAndroid Build Coastguard Worker     failf(data, "The requested URL returned error: %d",
3547*6236dae4SAndroid Build Coastguard Worker           k->httpcode);
3548*6236dae4SAndroid Build Coastguard Worker     result = CURLE_HTTP_RETURNED_ERROR;
3549*6236dae4SAndroid Build Coastguard Worker     goto out;
3550*6236dae4SAndroid Build Coastguard Worker   }
3551*6236dae4SAndroid Build Coastguard Worker 
3552*6236dae4SAndroid Build Coastguard Worker   /* Curl_http_auth_act() checks what authentication methods
3553*6236dae4SAndroid Build Coastguard Worker    * that are available and decides which one (if any) to
3554*6236dae4SAndroid Build Coastguard Worker    * use. It will set 'newurl' if an auth method was picked. */
3555*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_auth_act(data);
3556*6236dae4SAndroid Build Coastguard Worker   if(result)
3557*6236dae4SAndroid Build Coastguard Worker     goto out;
3558*6236dae4SAndroid Build Coastguard Worker 
3559*6236dae4SAndroid Build Coastguard Worker   if(k->httpcode >= 300) {
3560*6236dae4SAndroid Build Coastguard Worker     if((!data->req.authneg) && !conn->bits.close &&
3561*6236dae4SAndroid Build Coastguard Worker        !Curl_creader_will_rewind(data)) {
3562*6236dae4SAndroid Build Coastguard Worker       /*
3563*6236dae4SAndroid Build Coastguard Worker        * General treatment of errors when about to send data. Including :
3564*6236dae4SAndroid Build Coastguard Worker        * "417 Expectation Failed", while waiting for 100-continue.
3565*6236dae4SAndroid Build Coastguard Worker        *
3566*6236dae4SAndroid Build Coastguard Worker        * The check for close above is done simply because of something
3567*6236dae4SAndroid Build Coastguard Worker        * else has already deemed the connection to get closed then
3568*6236dae4SAndroid Build Coastguard Worker        * something else should've considered the big picture and we
3569*6236dae4SAndroid Build Coastguard Worker        * avoid this check.
3570*6236dae4SAndroid Build Coastguard Worker        *
3571*6236dae4SAndroid Build Coastguard Worker        */
3572*6236dae4SAndroid Build Coastguard Worker 
3573*6236dae4SAndroid Build Coastguard Worker       switch(data->state.httpreq) {
3574*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_PUT:
3575*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST:
3576*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST_FORM:
3577*6236dae4SAndroid Build Coastguard Worker       case HTTPREQ_POST_MIME:
3578*6236dae4SAndroid Build Coastguard Worker         /* We got an error response. If this happened before the whole
3579*6236dae4SAndroid Build Coastguard Worker          * request body has been sent we stop sending and mark the
3580*6236dae4SAndroid Build Coastguard Worker          * connection for closure after we have read the entire response.
3581*6236dae4SAndroid Build Coastguard Worker          */
3582*6236dae4SAndroid Build Coastguard Worker         if(!Curl_req_done_sending(data)) {
3583*6236dae4SAndroid Build Coastguard Worker           if((k->httpcode == 417) && Curl_http_exp100_is_selected(data)) {
3584*6236dae4SAndroid Build Coastguard Worker             /* 417 Expectation Failed - try again without the Expect
3585*6236dae4SAndroid Build Coastguard Worker                header */
3586*6236dae4SAndroid Build Coastguard Worker             if(!k->writebytecount && http_exp100_is_waiting(data)) {
3587*6236dae4SAndroid Build Coastguard Worker               infof(data, "Got HTTP failure 417 while waiting for a 100");
3588*6236dae4SAndroid Build Coastguard Worker             }
3589*6236dae4SAndroid Build Coastguard Worker             else {
3590*6236dae4SAndroid Build Coastguard Worker               infof(data, "Got HTTP failure 417 while sending data");
3591*6236dae4SAndroid Build Coastguard Worker               streamclose(conn,
3592*6236dae4SAndroid Build Coastguard Worker                           "Stop sending data before everything sent");
3593*6236dae4SAndroid Build Coastguard Worker               result = http_perhapsrewind(data, conn);
3594*6236dae4SAndroid Build Coastguard Worker               if(result)
3595*6236dae4SAndroid Build Coastguard Worker                 goto out;
3596*6236dae4SAndroid Build Coastguard Worker             }
3597*6236dae4SAndroid Build Coastguard Worker             data->state.disableexpect = TRUE;
3598*6236dae4SAndroid Build Coastguard Worker             DEBUGASSERT(!data->req.newurl);
3599*6236dae4SAndroid Build Coastguard Worker             data->req.newurl = strdup(data->state.url);
3600*6236dae4SAndroid Build Coastguard Worker             Curl_req_abort_sending(data);
3601*6236dae4SAndroid Build Coastguard Worker           }
3602*6236dae4SAndroid Build Coastguard Worker           else if(data->set.http_keep_sending_on_error) {
3603*6236dae4SAndroid Build Coastguard Worker             infof(data, "HTTP error before end of send, keep sending");
3604*6236dae4SAndroid Build Coastguard Worker             http_exp100_send_anyway(data);
3605*6236dae4SAndroid Build Coastguard Worker           }
3606*6236dae4SAndroid Build Coastguard Worker           else {
3607*6236dae4SAndroid Build Coastguard Worker             infof(data, "HTTP error before end of send, stop sending");
3608*6236dae4SAndroid Build Coastguard Worker             streamclose(conn, "Stop sending data before everything sent");
3609*6236dae4SAndroid Build Coastguard Worker             result = Curl_req_abort_sending(data);
3610*6236dae4SAndroid Build Coastguard Worker             if(result)
3611*6236dae4SAndroid Build Coastguard Worker               goto out;
3612*6236dae4SAndroid Build Coastguard Worker           }
3613*6236dae4SAndroid Build Coastguard Worker         }
3614*6236dae4SAndroid Build Coastguard Worker         break;
3615*6236dae4SAndroid Build Coastguard Worker 
3616*6236dae4SAndroid Build Coastguard Worker       default: /* default label present to avoid compiler warnings */
3617*6236dae4SAndroid Build Coastguard Worker         break;
3618*6236dae4SAndroid Build Coastguard Worker       }
3619*6236dae4SAndroid Build Coastguard Worker     }
3620*6236dae4SAndroid Build Coastguard Worker 
3621*6236dae4SAndroid Build Coastguard Worker     if(Curl_creader_will_rewind(data) && !Curl_req_done_sending(data)) {
3622*6236dae4SAndroid Build Coastguard Worker       /* We rewind before next send, continue sending now */
3623*6236dae4SAndroid Build Coastguard Worker       infof(data, "Keep sending data to get tossed away");
3624*6236dae4SAndroid Build Coastguard Worker       k->keepon |= KEEP_SEND;
3625*6236dae4SAndroid Build Coastguard Worker     }
3626*6236dae4SAndroid Build Coastguard Worker 
3627*6236dae4SAndroid Build Coastguard Worker   }
3628*6236dae4SAndroid Build Coastguard Worker 
3629*6236dae4SAndroid Build Coastguard Worker   /* If we requested a "no body", this is a good time to get
3630*6236dae4SAndroid Build Coastguard Worker    * out and return home.
3631*6236dae4SAndroid Build Coastguard Worker    */
3632*6236dae4SAndroid Build Coastguard Worker   if(data->req.no_body)
3633*6236dae4SAndroid Build Coastguard Worker     k->download_done = TRUE;
3634*6236dae4SAndroid Build Coastguard Worker 
3635*6236dae4SAndroid Build Coastguard Worker   /* If max download size is *zero* (nothing) we already have
3636*6236dae4SAndroid Build Coastguard Worker      nothing and can safely return ok now!  But for HTTP/2, we would
3637*6236dae4SAndroid Build Coastguard Worker      like to call http2_handle_stream_close to properly close a
3638*6236dae4SAndroid Build Coastguard Worker      stream. In order to do this, we keep reading until we
3639*6236dae4SAndroid Build Coastguard Worker      close the stream. */
3640*6236dae4SAndroid Build Coastguard Worker   if(0 == k->maxdownload
3641*6236dae4SAndroid Build Coastguard Worker      && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
3642*6236dae4SAndroid Build Coastguard Worker      && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
3643*6236dae4SAndroid Build Coastguard Worker     k->download_done = TRUE;
3644*6236dae4SAndroid Build Coastguard Worker 
3645*6236dae4SAndroid Build Coastguard Worker   /* final response without error, prepare to receive the body */
3646*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_firstwrite(data);
3647*6236dae4SAndroid Build Coastguard Worker 
3648*6236dae4SAndroid Build Coastguard Worker   if(!result)
3649*6236dae4SAndroid Build Coastguard Worker     /* This is the last response that we get for the current request.
3650*6236dae4SAndroid Build Coastguard Worker      * Check on the body size and determine if the response is complete.
3651*6236dae4SAndroid Build Coastguard Worker      */
3652*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_size(data);
3653*6236dae4SAndroid Build Coastguard Worker 
3654*6236dae4SAndroid Build Coastguard Worker out:
3655*6236dae4SAndroid Build Coastguard Worker   if(last_hd) {
3656*6236dae4SAndroid Build Coastguard Worker     /* if not written yet, write it now */
3657*6236dae4SAndroid Build Coastguard Worker     CURLcode r2 = http_write_header(data, last_hd, last_hd_len);
3658*6236dae4SAndroid Build Coastguard Worker     if(!result)
3659*6236dae4SAndroid Build Coastguard Worker       result = r2;
3660*6236dae4SAndroid Build Coastguard Worker   }
3661*6236dae4SAndroid Build Coastguard Worker   return result;
3662*6236dae4SAndroid Build Coastguard Worker }
3663*6236dae4SAndroid Build Coastguard Worker 
http_rw_hd(struct Curl_easy * data,const char * hd,size_t hdlen,const char * buf_remain,size_t blen,size_t * pconsumed)3664*6236dae4SAndroid Build Coastguard Worker static CURLcode http_rw_hd(struct Curl_easy *data,
3665*6236dae4SAndroid Build Coastguard Worker                            const char *hd, size_t hdlen,
3666*6236dae4SAndroid Build Coastguard Worker                            const char *buf_remain, size_t blen,
3667*6236dae4SAndroid Build Coastguard Worker                            size_t *pconsumed)
3668*6236dae4SAndroid Build Coastguard Worker {
3669*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3670*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3671*6236dae4SAndroid Build Coastguard Worker   int writetype;
3672*6236dae4SAndroid Build Coastguard Worker 
3673*6236dae4SAndroid Build Coastguard Worker   *pconsumed = 0;
3674*6236dae4SAndroid Build Coastguard Worker   if((0x0a == *hd) || (0x0d == *hd)) {
3675*6236dae4SAndroid Build Coastguard Worker     /* Empty header line means end of headers! */
3676*6236dae4SAndroid Build Coastguard Worker     struct dynbuf last_header;
3677*6236dae4SAndroid Build Coastguard Worker     size_t consumed;
3678*6236dae4SAndroid Build Coastguard Worker 
3679*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_init(&last_header, hdlen + 1);
3680*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_addn(&last_header, hd, hdlen);
3681*6236dae4SAndroid Build Coastguard Worker     if(result)
3682*6236dae4SAndroid Build Coastguard Worker       return result;
3683*6236dae4SAndroid Build Coastguard Worker 
3684*6236dae4SAndroid Build Coastguard Worker     /* analyze the response to find out what to do. */
3685*6236dae4SAndroid Build Coastguard Worker     /* Caveat: we clear anything in the header brigade, because a
3686*6236dae4SAndroid Build Coastguard Worker      * response might switch HTTP version which may call use recursively.
3687*6236dae4SAndroid Build Coastguard Worker      * Not nice, but that is currently the way of things. */
3688*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_reset(&data->state.headerb);
3689*6236dae4SAndroid Build Coastguard Worker     result = http_on_response(data, Curl_dyn_ptr(&last_header),
3690*6236dae4SAndroid Build Coastguard Worker                               Curl_dyn_len(&last_header),
3691*6236dae4SAndroid Build Coastguard Worker                               buf_remain, blen, &consumed);
3692*6236dae4SAndroid Build Coastguard Worker     *pconsumed += consumed;
3693*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&last_header);
3694*6236dae4SAndroid Build Coastguard Worker     return result;
3695*6236dae4SAndroid Build Coastguard Worker   }
3696*6236dae4SAndroid Build Coastguard Worker 
3697*6236dae4SAndroid Build Coastguard Worker   /*
3698*6236dae4SAndroid Build Coastguard Worker    * Checks for special headers coming up.
3699*6236dae4SAndroid Build Coastguard Worker    */
3700*6236dae4SAndroid Build Coastguard Worker 
3701*6236dae4SAndroid Build Coastguard Worker   writetype = CLIENTWRITE_HEADER;
3702*6236dae4SAndroid Build Coastguard Worker   if(!k->headerline++) {
3703*6236dae4SAndroid Build Coastguard Worker     /* This is the first header, it MUST be the error code line
3704*6236dae4SAndroid Build Coastguard Worker        or else we consider this to be the body right away! */
3705*6236dae4SAndroid Build Coastguard Worker     bool fine_statusline = FALSE;
3706*6236dae4SAndroid Build Coastguard Worker 
3707*6236dae4SAndroid Build Coastguard Worker     k->httpversion = 0; /* Do not know yet */
3708*6236dae4SAndroid Build Coastguard Worker     if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
3709*6236dae4SAndroid Build Coastguard Worker       /*
3710*6236dae4SAndroid Build Coastguard Worker        * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
3711*6236dae4SAndroid Build Coastguard Worker        *
3712*6236dae4SAndroid Build Coastguard Worker        * The response code is always a three-digit number in HTTP as the spec
3713*6236dae4SAndroid Build Coastguard Worker        * says. We allow any three-digit number here, but we cannot make
3714*6236dae4SAndroid Build Coastguard Worker        * guarantees on future behaviors since it is not within the protocol.
3715*6236dae4SAndroid Build Coastguard Worker        */
3716*6236dae4SAndroid Build Coastguard Worker       const char *p = hd;
3717*6236dae4SAndroid Build Coastguard Worker 
3718*6236dae4SAndroid Build Coastguard Worker       while(*p && ISBLANK(*p))
3719*6236dae4SAndroid Build Coastguard Worker         p++;
3720*6236dae4SAndroid Build Coastguard Worker       if(!strncmp(p, "HTTP/", 5)) {
3721*6236dae4SAndroid Build Coastguard Worker         p += 5;
3722*6236dae4SAndroid Build Coastguard Worker         switch(*p) {
3723*6236dae4SAndroid Build Coastguard Worker         case '1':
3724*6236dae4SAndroid Build Coastguard Worker           p++;
3725*6236dae4SAndroid Build Coastguard Worker           if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
3726*6236dae4SAndroid Build Coastguard Worker             if(ISBLANK(p[2])) {
3727*6236dae4SAndroid Build Coastguard Worker               k->httpversion = 10 + (p[1] - '0');
3728*6236dae4SAndroid Build Coastguard Worker               p += 3;
3729*6236dae4SAndroid Build Coastguard Worker               if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
3730*6236dae4SAndroid Build Coastguard Worker                 k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
3731*6236dae4SAndroid Build Coastguard Worker                   (p[2] - '0');
3732*6236dae4SAndroid Build Coastguard Worker                 p += 3;
3733*6236dae4SAndroid Build Coastguard Worker                 if(ISSPACE(*p))
3734*6236dae4SAndroid Build Coastguard Worker                   fine_statusline = TRUE;
3735*6236dae4SAndroid Build Coastguard Worker               }
3736*6236dae4SAndroid Build Coastguard Worker             }
3737*6236dae4SAndroid Build Coastguard Worker           }
3738*6236dae4SAndroid Build Coastguard Worker           if(!fine_statusline) {
3739*6236dae4SAndroid Build Coastguard Worker             failf(data, "Unsupported HTTP/1 subversion in response");
3740*6236dae4SAndroid Build Coastguard Worker             return CURLE_UNSUPPORTED_PROTOCOL;
3741*6236dae4SAndroid Build Coastguard Worker           }
3742*6236dae4SAndroid Build Coastguard Worker           break;
3743*6236dae4SAndroid Build Coastguard Worker         case '2':
3744*6236dae4SAndroid Build Coastguard Worker         case '3':
3745*6236dae4SAndroid Build Coastguard Worker           if(!ISBLANK(p[1]))
3746*6236dae4SAndroid Build Coastguard Worker             break;
3747*6236dae4SAndroid Build Coastguard Worker           k->httpversion = (*p - '0') * 10;
3748*6236dae4SAndroid Build Coastguard Worker           p += 2;
3749*6236dae4SAndroid Build Coastguard Worker           if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
3750*6236dae4SAndroid Build Coastguard Worker             k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
3751*6236dae4SAndroid Build Coastguard Worker               (p[2] - '0');
3752*6236dae4SAndroid Build Coastguard Worker             p += 3;
3753*6236dae4SAndroid Build Coastguard Worker             if(!ISSPACE(*p))
3754*6236dae4SAndroid Build Coastguard Worker               break;
3755*6236dae4SAndroid Build Coastguard Worker             fine_statusline = TRUE;
3756*6236dae4SAndroid Build Coastguard Worker           }
3757*6236dae4SAndroid Build Coastguard Worker           break;
3758*6236dae4SAndroid Build Coastguard Worker         default: /* unsupported */
3759*6236dae4SAndroid Build Coastguard Worker           failf(data, "Unsupported HTTP version in response");
3760*6236dae4SAndroid Build Coastguard Worker           return CURLE_UNSUPPORTED_PROTOCOL;
3761*6236dae4SAndroid Build Coastguard Worker         }
3762*6236dae4SAndroid Build Coastguard Worker       }
3763*6236dae4SAndroid Build Coastguard Worker 
3764*6236dae4SAndroid Build Coastguard Worker       if(!fine_statusline) {
3765*6236dae4SAndroid Build Coastguard Worker         /* If user has set option HTTP200ALIASES,
3766*6236dae4SAndroid Build Coastguard Worker            compare header line against list of aliases
3767*6236dae4SAndroid Build Coastguard Worker         */
3768*6236dae4SAndroid Build Coastguard Worker         statusline check = checkhttpprefix(data, hd, hdlen);
3769*6236dae4SAndroid Build Coastguard Worker         if(check == STATUS_DONE) {
3770*6236dae4SAndroid Build Coastguard Worker           fine_statusline = TRUE;
3771*6236dae4SAndroid Build Coastguard Worker           k->httpcode = 200;
3772*6236dae4SAndroid Build Coastguard Worker           k->httpversion = 10;
3773*6236dae4SAndroid Build Coastguard Worker         }
3774*6236dae4SAndroid Build Coastguard Worker       }
3775*6236dae4SAndroid Build Coastguard Worker     }
3776*6236dae4SAndroid Build Coastguard Worker     else if(data->conn->handler->protocol & CURLPROTO_RTSP) {
3777*6236dae4SAndroid Build Coastguard Worker       const char *p = hd;
3778*6236dae4SAndroid Build Coastguard Worker       while(*p && ISBLANK(*p))
3779*6236dae4SAndroid Build Coastguard Worker         p++;
3780*6236dae4SAndroid Build Coastguard Worker       if(!strncmp(p, "RTSP/", 5)) {
3781*6236dae4SAndroid Build Coastguard Worker         p += 5;
3782*6236dae4SAndroid Build Coastguard Worker         if(ISDIGIT(*p)) {
3783*6236dae4SAndroid Build Coastguard Worker           p++;
3784*6236dae4SAndroid Build Coastguard Worker           if((p[0] == '.') && ISDIGIT(p[1])) {
3785*6236dae4SAndroid Build Coastguard Worker             if(ISBLANK(p[2])) {
3786*6236dae4SAndroid Build Coastguard Worker               p += 3;
3787*6236dae4SAndroid Build Coastguard Worker               if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
3788*6236dae4SAndroid Build Coastguard Worker                 k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
3789*6236dae4SAndroid Build Coastguard Worker                   (p[2] - '0');
3790*6236dae4SAndroid Build Coastguard Worker                 p += 3;
3791*6236dae4SAndroid Build Coastguard Worker                 if(ISSPACE(*p)) {
3792*6236dae4SAndroid Build Coastguard Worker                   fine_statusline = TRUE;
3793*6236dae4SAndroid Build Coastguard Worker                   k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
3794*6236dae4SAndroid Build Coastguard Worker                 }
3795*6236dae4SAndroid Build Coastguard Worker               }
3796*6236dae4SAndroid Build Coastguard Worker             }
3797*6236dae4SAndroid Build Coastguard Worker           }
3798*6236dae4SAndroid Build Coastguard Worker         }
3799*6236dae4SAndroid Build Coastguard Worker         if(!fine_statusline)
3800*6236dae4SAndroid Build Coastguard Worker           return CURLE_WEIRD_SERVER_REPLY;
3801*6236dae4SAndroid Build Coastguard Worker       }
3802*6236dae4SAndroid Build Coastguard Worker     }
3803*6236dae4SAndroid Build Coastguard Worker 
3804*6236dae4SAndroid Build Coastguard Worker     if(fine_statusline) {
3805*6236dae4SAndroid Build Coastguard Worker       result = Curl_http_statusline(data, data->conn);
3806*6236dae4SAndroid Build Coastguard Worker       if(result)
3807*6236dae4SAndroid Build Coastguard Worker         return result;
3808*6236dae4SAndroid Build Coastguard Worker       writetype |= CLIENTWRITE_STATUS;
3809*6236dae4SAndroid Build Coastguard Worker     }
3810*6236dae4SAndroid Build Coastguard Worker     else {
3811*6236dae4SAndroid Build Coastguard Worker       k->header = FALSE;   /* this is not a header line */
3812*6236dae4SAndroid Build Coastguard Worker       return CURLE_WEIRD_SERVER_REPLY;
3813*6236dae4SAndroid Build Coastguard Worker     }
3814*6236dae4SAndroid Build Coastguard Worker   }
3815*6236dae4SAndroid Build Coastguard Worker 
3816*6236dae4SAndroid Build Coastguard Worker   result = verify_header(data, hd, hdlen);
3817*6236dae4SAndroid Build Coastguard Worker   if(result)
3818*6236dae4SAndroid Build Coastguard Worker     return result;
3819*6236dae4SAndroid Build Coastguard Worker 
3820*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_header(data, hd, hdlen);
3821*6236dae4SAndroid Build Coastguard Worker   if(result)
3822*6236dae4SAndroid Build Coastguard Worker     return result;
3823*6236dae4SAndroid Build Coastguard Worker 
3824*6236dae4SAndroid Build Coastguard Worker   /*
3825*6236dae4SAndroid Build Coastguard Worker    * Taken in one (more) header. Write it to the client.
3826*6236dae4SAndroid Build Coastguard Worker    */
3827*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_IN, (char *)hd, hdlen);
3828*6236dae4SAndroid Build Coastguard Worker 
3829*6236dae4SAndroid Build Coastguard Worker   if(k->httpcode/100 == 1)
3830*6236dae4SAndroid Build Coastguard Worker     writetype |= CLIENTWRITE_1XX;
3831*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_write(data, writetype, hd, hdlen);
3832*6236dae4SAndroid Build Coastguard Worker   if(result)
3833*6236dae4SAndroid Build Coastguard Worker     return result;
3834*6236dae4SAndroid Build Coastguard Worker 
3835*6236dae4SAndroid Build Coastguard Worker   result = Curl_bump_headersize(data, hdlen, FALSE);
3836*6236dae4SAndroid Build Coastguard Worker   if(result)
3837*6236dae4SAndroid Build Coastguard Worker     return result;
3838*6236dae4SAndroid Build Coastguard Worker 
3839*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3840*6236dae4SAndroid Build Coastguard Worker }
3841*6236dae4SAndroid Build Coastguard Worker 
3842*6236dae4SAndroid Build Coastguard Worker /*
3843*6236dae4SAndroid Build Coastguard Worker  * Read any HTTP header lines from the server and pass them to the client app.
3844*6236dae4SAndroid Build Coastguard Worker  */
http_parse_headers(struct Curl_easy * data,const char * buf,size_t blen,size_t * pconsumed)3845*6236dae4SAndroid Build Coastguard Worker static CURLcode http_parse_headers(struct Curl_easy *data,
3846*6236dae4SAndroid Build Coastguard Worker                                    const char *buf, size_t blen,
3847*6236dae4SAndroid Build Coastguard Worker                                    size_t *pconsumed)
3848*6236dae4SAndroid Build Coastguard Worker {
3849*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
3850*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3851*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
3852*6236dae4SAndroid Build Coastguard Worker   char *end_ptr;
3853*6236dae4SAndroid Build Coastguard Worker   bool leftover_body = FALSE;
3854*6236dae4SAndroid Build Coastguard Worker 
3855*6236dae4SAndroid Build Coastguard Worker   /* header line within buffer loop */
3856*6236dae4SAndroid Build Coastguard Worker   *pconsumed = 0;
3857*6236dae4SAndroid Build Coastguard Worker   while(blen && k->header) {
3858*6236dae4SAndroid Build Coastguard Worker     size_t consumed;
3859*6236dae4SAndroid Build Coastguard Worker 
3860*6236dae4SAndroid Build Coastguard Worker     end_ptr = memchr(buf, '\n', blen);
3861*6236dae4SAndroid Build Coastguard Worker     if(!end_ptr) {
3862*6236dae4SAndroid Build Coastguard Worker       /* Not a complete header line within buffer, append the data to
3863*6236dae4SAndroid Build Coastguard Worker          the end of the headerbuff. */
3864*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addn(&data->state.headerb, buf, blen);
3865*6236dae4SAndroid Build Coastguard Worker       if(result)
3866*6236dae4SAndroid Build Coastguard Worker         return result;
3867*6236dae4SAndroid Build Coastguard Worker       *pconsumed += blen;
3868*6236dae4SAndroid Build Coastguard Worker 
3869*6236dae4SAndroid Build Coastguard Worker       if(!k->headerline) {
3870*6236dae4SAndroid Build Coastguard Worker         /* check if this looks like a protocol header */
3871*6236dae4SAndroid Build Coastguard Worker         statusline st =
3872*6236dae4SAndroid Build Coastguard Worker           checkprotoprefix(data, conn,
3873*6236dae4SAndroid Build Coastguard Worker                            Curl_dyn_ptr(&data->state.headerb),
3874*6236dae4SAndroid Build Coastguard Worker                            Curl_dyn_len(&data->state.headerb));
3875*6236dae4SAndroid Build Coastguard Worker 
3876*6236dae4SAndroid Build Coastguard Worker         if(st == STATUS_BAD) {
3877*6236dae4SAndroid Build Coastguard Worker           /* this is not the beginning of a protocol first header line */
3878*6236dae4SAndroid Build Coastguard Worker           k->header = FALSE;
3879*6236dae4SAndroid Build Coastguard Worker           streamclose(conn, "bad HTTP: No end-of-message indicator");
3880*6236dae4SAndroid Build Coastguard Worker           if(conn->httpversion >= 10) {
3881*6236dae4SAndroid Build Coastguard Worker             failf(data, "Invalid status line");
3882*6236dae4SAndroid Build Coastguard Worker             return CURLE_WEIRD_SERVER_REPLY;
3883*6236dae4SAndroid Build Coastguard Worker           }
3884*6236dae4SAndroid Build Coastguard Worker           if(!data->set.http09_allowed) {
3885*6236dae4SAndroid Build Coastguard Worker             failf(data, "Received HTTP/0.9 when not allowed");
3886*6236dae4SAndroid Build Coastguard Worker             return CURLE_UNSUPPORTED_PROTOCOL;
3887*6236dae4SAndroid Build Coastguard Worker           }
3888*6236dae4SAndroid Build Coastguard Worker           leftover_body = TRUE;
3889*6236dae4SAndroid Build Coastguard Worker           goto out;
3890*6236dae4SAndroid Build Coastguard Worker         }
3891*6236dae4SAndroid Build Coastguard Worker       }
3892*6236dae4SAndroid Build Coastguard Worker       goto out; /* read more and try again */
3893*6236dae4SAndroid Build Coastguard Worker     }
3894*6236dae4SAndroid Build Coastguard Worker 
3895*6236dae4SAndroid Build Coastguard Worker     /* decrease the size of the remaining (supposed) header line */
3896*6236dae4SAndroid Build Coastguard Worker     consumed = (end_ptr - buf) + 1;
3897*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_addn(&data->state.headerb, buf, consumed);
3898*6236dae4SAndroid Build Coastguard Worker     if(result)
3899*6236dae4SAndroid Build Coastguard Worker       return result;
3900*6236dae4SAndroid Build Coastguard Worker     blen -= consumed;
3901*6236dae4SAndroid Build Coastguard Worker     buf += consumed;
3902*6236dae4SAndroid Build Coastguard Worker     *pconsumed += consumed;
3903*6236dae4SAndroid Build Coastguard Worker 
3904*6236dae4SAndroid Build Coastguard Worker     /****
3905*6236dae4SAndroid Build Coastguard Worker      * We now have a FULL header line in 'headerb'.
3906*6236dae4SAndroid Build Coastguard Worker      *****/
3907*6236dae4SAndroid Build Coastguard Worker 
3908*6236dae4SAndroid Build Coastguard Worker     if(!k->headerline) {
3909*6236dae4SAndroid Build Coastguard Worker       /* the first read header */
3910*6236dae4SAndroid Build Coastguard Worker       statusline st = checkprotoprefix(data, conn,
3911*6236dae4SAndroid Build Coastguard Worker                                        Curl_dyn_ptr(&data->state.headerb),
3912*6236dae4SAndroid Build Coastguard Worker                                        Curl_dyn_len(&data->state.headerb));
3913*6236dae4SAndroid Build Coastguard Worker       if(st == STATUS_BAD) {
3914*6236dae4SAndroid Build Coastguard Worker         streamclose(conn, "bad HTTP: No end-of-message indicator");
3915*6236dae4SAndroid Build Coastguard Worker         /* this is not the beginning of a protocol first header line */
3916*6236dae4SAndroid Build Coastguard Worker         if(conn->httpversion >= 10) {
3917*6236dae4SAndroid Build Coastguard Worker           failf(data, "Invalid status line");
3918*6236dae4SAndroid Build Coastguard Worker           return CURLE_WEIRD_SERVER_REPLY;
3919*6236dae4SAndroid Build Coastguard Worker         }
3920*6236dae4SAndroid Build Coastguard Worker         if(!data->set.http09_allowed) {
3921*6236dae4SAndroid Build Coastguard Worker           failf(data, "Received HTTP/0.9 when not allowed");
3922*6236dae4SAndroid Build Coastguard Worker           return CURLE_UNSUPPORTED_PROTOCOL;
3923*6236dae4SAndroid Build Coastguard Worker         }
3924*6236dae4SAndroid Build Coastguard Worker         k->header = FALSE;
3925*6236dae4SAndroid Build Coastguard Worker         leftover_body = TRUE;
3926*6236dae4SAndroid Build Coastguard Worker         goto out;
3927*6236dae4SAndroid Build Coastguard Worker       }
3928*6236dae4SAndroid Build Coastguard Worker     }
3929*6236dae4SAndroid Build Coastguard Worker 
3930*6236dae4SAndroid Build Coastguard Worker     result = http_rw_hd(data, Curl_dyn_ptr(&data->state.headerb),
3931*6236dae4SAndroid Build Coastguard Worker                         Curl_dyn_len(&data->state.headerb),
3932*6236dae4SAndroid Build Coastguard Worker                         buf, blen, &consumed);
3933*6236dae4SAndroid Build Coastguard Worker     /* We are done with this line. We reset because response
3934*6236dae4SAndroid Build Coastguard Worker      * processing might switch to HTTP/2 and that might call us
3935*6236dae4SAndroid Build Coastguard Worker      * directly again. */
3936*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_reset(&data->state.headerb);
3937*6236dae4SAndroid Build Coastguard Worker     if(consumed) {
3938*6236dae4SAndroid Build Coastguard Worker       blen -= consumed;
3939*6236dae4SAndroid Build Coastguard Worker       buf += consumed;
3940*6236dae4SAndroid Build Coastguard Worker       *pconsumed += consumed;
3941*6236dae4SAndroid Build Coastguard Worker     }
3942*6236dae4SAndroid Build Coastguard Worker     if(result)
3943*6236dae4SAndroid Build Coastguard Worker       return result;
3944*6236dae4SAndroid Build Coastguard Worker   }
3945*6236dae4SAndroid Build Coastguard Worker 
3946*6236dae4SAndroid Build Coastguard Worker   /* We might have reached the end of the header part here, but
3947*6236dae4SAndroid Build Coastguard Worker      there might be a non-header part left in the end of the read
3948*6236dae4SAndroid Build Coastguard Worker      buffer. */
3949*6236dae4SAndroid Build Coastguard Worker out:
3950*6236dae4SAndroid Build Coastguard Worker   if(!k->header && !leftover_body) {
3951*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&data->state.headerb);
3952*6236dae4SAndroid Build Coastguard Worker   }
3953*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3954*6236dae4SAndroid Build Coastguard Worker }
3955*6236dae4SAndroid Build Coastguard Worker 
Curl_http_write_resp_hd(struct Curl_easy * data,const char * hd,size_t hdlen,bool is_eos)3956*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_write_resp_hd(struct Curl_easy *data,
3957*6236dae4SAndroid Build Coastguard Worker                                  const char *hd, size_t hdlen,
3958*6236dae4SAndroid Build Coastguard Worker                                  bool is_eos)
3959*6236dae4SAndroid Build Coastguard Worker {
3960*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
3961*6236dae4SAndroid Build Coastguard Worker   size_t consumed;
3962*6236dae4SAndroid Build Coastguard Worker   char tmp = 0;
3963*6236dae4SAndroid Build Coastguard Worker 
3964*6236dae4SAndroid Build Coastguard Worker   result = http_rw_hd(data, hd, hdlen, &tmp, 0, &consumed);
3965*6236dae4SAndroid Build Coastguard Worker   if(!result && is_eos) {
3966*6236dae4SAndroid Build Coastguard Worker     result = Curl_client_write(data, (CLIENTWRITE_BODY|CLIENTWRITE_EOS),
3967*6236dae4SAndroid Build Coastguard Worker                                &tmp, 0);
3968*6236dae4SAndroid Build Coastguard Worker   }
3969*6236dae4SAndroid Build Coastguard Worker   return result;
3970*6236dae4SAndroid Build Coastguard Worker }
3971*6236dae4SAndroid Build Coastguard Worker 
3972*6236dae4SAndroid Build Coastguard Worker /*
3973*6236dae4SAndroid Build Coastguard Worker  * HTTP protocol `write_resp` implementation. Will parse headers
3974*6236dae4SAndroid Build Coastguard Worker  * when not done yet and otherwise return without consuming data.
3975*6236dae4SAndroid Build Coastguard Worker  */
Curl_http_write_resp_hds(struct Curl_easy * data,const char * buf,size_t blen,size_t * pconsumed)3976*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
3977*6236dae4SAndroid Build Coastguard Worker                                   const char *buf, size_t blen,
3978*6236dae4SAndroid Build Coastguard Worker                                   size_t *pconsumed)
3979*6236dae4SAndroid Build Coastguard Worker {
3980*6236dae4SAndroid Build Coastguard Worker   if(!data->req.header) {
3981*6236dae4SAndroid Build Coastguard Worker     *pconsumed = 0;
3982*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
3983*6236dae4SAndroid Build Coastguard Worker   }
3984*6236dae4SAndroid Build Coastguard Worker   else {
3985*6236dae4SAndroid Build Coastguard Worker     CURLcode result;
3986*6236dae4SAndroid Build Coastguard Worker 
3987*6236dae4SAndroid Build Coastguard Worker     result = http_parse_headers(data, buf, blen, pconsumed);
3988*6236dae4SAndroid Build Coastguard Worker     if(!result && !data->req.header) {
3989*6236dae4SAndroid Build Coastguard Worker       if(!data->req.no_body && Curl_dyn_len(&data->state.headerb)) {
3990*6236dae4SAndroid Build Coastguard Worker         /* leftover from parsing something that turned out not
3991*6236dae4SAndroid Build Coastguard Worker          * to be a header, only happens if we allow for
3992*6236dae4SAndroid Build Coastguard Worker          * HTTP/0.9 like responses */
3993*6236dae4SAndroid Build Coastguard Worker         result = Curl_client_write(data, CLIENTWRITE_BODY,
3994*6236dae4SAndroid Build Coastguard Worker                                    Curl_dyn_ptr(&data->state.headerb),
3995*6236dae4SAndroid Build Coastguard Worker                                    Curl_dyn_len(&data->state.headerb));
3996*6236dae4SAndroid Build Coastguard Worker       }
3997*6236dae4SAndroid Build Coastguard Worker       Curl_dyn_free(&data->state.headerb);
3998*6236dae4SAndroid Build Coastguard Worker     }
3999*6236dae4SAndroid Build Coastguard Worker     return result;
4000*6236dae4SAndroid Build Coastguard Worker   }
4001*6236dae4SAndroid Build Coastguard Worker }
4002*6236dae4SAndroid Build Coastguard Worker 
Curl_http_write_resp(struct Curl_easy * data,const char * buf,size_t blen,bool is_eos)4003*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_write_resp(struct Curl_easy *data,
4004*6236dae4SAndroid Build Coastguard Worker                               const char *buf, size_t blen,
4005*6236dae4SAndroid Build Coastguard Worker                               bool is_eos)
4006*6236dae4SAndroid Build Coastguard Worker {
4007*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
4008*6236dae4SAndroid Build Coastguard Worker   size_t consumed;
4009*6236dae4SAndroid Build Coastguard Worker   int flags;
4010*6236dae4SAndroid Build Coastguard Worker 
4011*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_write_resp_hds(data, buf, blen, &consumed);
4012*6236dae4SAndroid Build Coastguard Worker   if(result || data->req.done)
4013*6236dae4SAndroid Build Coastguard Worker     goto out;
4014*6236dae4SAndroid Build Coastguard Worker 
4015*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(consumed <= blen);
4016*6236dae4SAndroid Build Coastguard Worker   blen -= consumed;
4017*6236dae4SAndroid Build Coastguard Worker   buf += consumed;
4018*6236dae4SAndroid Build Coastguard Worker   /* either all was consumed in header parsing, or we have data left
4019*6236dae4SAndroid Build Coastguard Worker    * and are done with headers, e.g. it is BODY data */
4020*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!blen || !data->req.header);
4021*6236dae4SAndroid Build Coastguard Worker   if(!data->req.header && (blen || is_eos)) {
4022*6236dae4SAndroid Build Coastguard Worker     /* BODY data after header been parsed, write and consume */
4023*6236dae4SAndroid Build Coastguard Worker     flags = CLIENTWRITE_BODY;
4024*6236dae4SAndroid Build Coastguard Worker     if(is_eos)
4025*6236dae4SAndroid Build Coastguard Worker       flags |= CLIENTWRITE_EOS;
4026*6236dae4SAndroid Build Coastguard Worker     result = Curl_client_write(data, flags, (char *)buf, blen);
4027*6236dae4SAndroid Build Coastguard Worker   }
4028*6236dae4SAndroid Build Coastguard Worker out:
4029*6236dae4SAndroid Build Coastguard Worker   return result;
4030*6236dae4SAndroid Build Coastguard Worker }
4031*6236dae4SAndroid Build Coastguard Worker 
4032*6236dae4SAndroid Build Coastguard Worker /* Decode HTTP status code string. */
Curl_http_decode_status(int * pstatus,const char * s,size_t len)4033*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
4034*6236dae4SAndroid Build Coastguard Worker {
4035*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
4036*6236dae4SAndroid Build Coastguard Worker   int status = 0;
4037*6236dae4SAndroid Build Coastguard Worker   int i;
4038*6236dae4SAndroid Build Coastguard Worker 
4039*6236dae4SAndroid Build Coastguard Worker   if(len != 3)
4040*6236dae4SAndroid Build Coastguard Worker     goto out;
4041*6236dae4SAndroid Build Coastguard Worker 
4042*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < 3; ++i) {
4043*6236dae4SAndroid Build Coastguard Worker     char c = s[i];
4044*6236dae4SAndroid Build Coastguard Worker 
4045*6236dae4SAndroid Build Coastguard Worker     if(c < '0' || c > '9')
4046*6236dae4SAndroid Build Coastguard Worker       goto out;
4047*6236dae4SAndroid Build Coastguard Worker 
4048*6236dae4SAndroid Build Coastguard Worker     status *= 10;
4049*6236dae4SAndroid Build Coastguard Worker     status += c - '0';
4050*6236dae4SAndroid Build Coastguard Worker   }
4051*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4052*6236dae4SAndroid Build Coastguard Worker out:
4053*6236dae4SAndroid Build Coastguard Worker   *pstatus = result ? -1 : status;
4054*6236dae4SAndroid Build Coastguard Worker   return result;
4055*6236dae4SAndroid Build Coastguard Worker }
4056*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_make(struct httpreq ** preq,const char * method,size_t m_len,const char * scheme,size_t s_len,const char * authority,size_t a_len,const char * path,size_t p_len)4057*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_req_make(struct httpreq **preq,
4058*6236dae4SAndroid Build Coastguard Worker                             const char *method, size_t m_len,
4059*6236dae4SAndroid Build Coastguard Worker                             const char *scheme, size_t s_len,
4060*6236dae4SAndroid Build Coastguard Worker                             const char *authority, size_t a_len,
4061*6236dae4SAndroid Build Coastguard Worker                             const char *path, size_t p_len)
4062*6236dae4SAndroid Build Coastguard Worker {
4063*6236dae4SAndroid Build Coastguard Worker   struct httpreq *req;
4064*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OUT_OF_MEMORY;
4065*6236dae4SAndroid Build Coastguard Worker 
4066*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(method);
4067*6236dae4SAndroid Build Coastguard Worker   if(m_len + 1 > sizeof(req->method))
4068*6236dae4SAndroid Build Coastguard Worker     return CURLE_BAD_FUNCTION_ARGUMENT;
4069*6236dae4SAndroid Build Coastguard Worker 
4070*6236dae4SAndroid Build Coastguard Worker   req = calloc(1, sizeof(*req));
4071*6236dae4SAndroid Build Coastguard Worker   if(!req)
4072*6236dae4SAndroid Build Coastguard Worker     goto out;
4073*6236dae4SAndroid Build Coastguard Worker   memcpy(req->method, method, m_len);
4074*6236dae4SAndroid Build Coastguard Worker   if(scheme) {
4075*6236dae4SAndroid Build Coastguard Worker     req->scheme = Curl_memdup0(scheme, s_len);
4076*6236dae4SAndroid Build Coastguard Worker     if(!req->scheme)
4077*6236dae4SAndroid Build Coastguard Worker       goto out;
4078*6236dae4SAndroid Build Coastguard Worker   }
4079*6236dae4SAndroid Build Coastguard Worker   if(authority) {
4080*6236dae4SAndroid Build Coastguard Worker     req->authority = Curl_memdup0(authority, a_len);
4081*6236dae4SAndroid Build Coastguard Worker     if(!req->authority)
4082*6236dae4SAndroid Build Coastguard Worker       goto out;
4083*6236dae4SAndroid Build Coastguard Worker   }
4084*6236dae4SAndroid Build Coastguard Worker   if(path) {
4085*6236dae4SAndroid Build Coastguard Worker     req->path = Curl_memdup0(path, p_len);
4086*6236dae4SAndroid Build Coastguard Worker     if(!req->path)
4087*6236dae4SAndroid Build Coastguard Worker       goto out;
4088*6236dae4SAndroid Build Coastguard Worker   }
4089*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
4090*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
4091*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4092*6236dae4SAndroid Build Coastguard Worker 
4093*6236dae4SAndroid Build Coastguard Worker out:
4094*6236dae4SAndroid Build Coastguard Worker   if(result && req)
4095*6236dae4SAndroid Build Coastguard Worker     Curl_http_req_free(req);
4096*6236dae4SAndroid Build Coastguard Worker   *preq = result ? NULL : req;
4097*6236dae4SAndroid Build Coastguard Worker   return result;
4098*6236dae4SAndroid Build Coastguard Worker }
4099*6236dae4SAndroid Build Coastguard Worker 
req_assign_url_authority(struct httpreq * req,CURLU * url)4100*6236dae4SAndroid Build Coastguard Worker static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url)
4101*6236dae4SAndroid Build Coastguard Worker {
4102*6236dae4SAndroid Build Coastguard Worker   char *user, *pass, *host, *port;
4103*6236dae4SAndroid Build Coastguard Worker   struct dynbuf buf;
4104*6236dae4SAndroid Build Coastguard Worker   CURLUcode uc;
4105*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_URL_MALFORMAT;
4106*6236dae4SAndroid Build Coastguard Worker 
4107*6236dae4SAndroid Build Coastguard Worker   user = pass = host = port = NULL;
4108*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
4109*6236dae4SAndroid Build Coastguard Worker 
4110*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_HOST, &host, 0);
4111*6236dae4SAndroid Build Coastguard Worker   if(uc && uc != CURLUE_NO_HOST)
4112*6236dae4SAndroid Build Coastguard Worker     goto out;
4113*6236dae4SAndroid Build Coastguard Worker   if(!host) {
4114*6236dae4SAndroid Build Coastguard Worker     req->authority = NULL;
4115*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OK;
4116*6236dae4SAndroid Build Coastguard Worker     goto out;
4117*6236dae4SAndroid Build Coastguard Worker   }
4118*6236dae4SAndroid Build Coastguard Worker 
4119*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_PORT, &port, CURLU_NO_DEFAULT_PORT);
4120*6236dae4SAndroid Build Coastguard Worker   if(uc && uc != CURLUE_NO_PORT)
4121*6236dae4SAndroid Build Coastguard Worker     goto out;
4122*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_USER, &user, 0);
4123*6236dae4SAndroid Build Coastguard Worker   if(uc && uc != CURLUE_NO_USER)
4124*6236dae4SAndroid Build Coastguard Worker     goto out;
4125*6236dae4SAndroid Build Coastguard Worker   if(user) {
4126*6236dae4SAndroid Build Coastguard Worker     uc = curl_url_get(url, CURLUPART_PASSWORD, &pass, 0);
4127*6236dae4SAndroid Build Coastguard Worker     if(uc && uc != CURLUE_NO_PASSWORD)
4128*6236dae4SAndroid Build Coastguard Worker       goto out;
4129*6236dae4SAndroid Build Coastguard Worker   }
4130*6236dae4SAndroid Build Coastguard Worker 
4131*6236dae4SAndroid Build Coastguard Worker   if(user) {
4132*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_add(&buf, user);
4133*6236dae4SAndroid Build Coastguard Worker     if(result)
4134*6236dae4SAndroid Build Coastguard Worker       goto out;
4135*6236dae4SAndroid Build Coastguard Worker     if(pass) {
4136*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addf(&buf, ":%s", pass);
4137*6236dae4SAndroid Build Coastguard Worker       if(result)
4138*6236dae4SAndroid Build Coastguard Worker         goto out;
4139*6236dae4SAndroid Build Coastguard Worker     }
4140*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_add(&buf, "@");
4141*6236dae4SAndroid Build Coastguard Worker     if(result)
4142*6236dae4SAndroid Build Coastguard Worker       goto out;
4143*6236dae4SAndroid Build Coastguard Worker   }
4144*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_add(&buf, host);
4145*6236dae4SAndroid Build Coastguard Worker   if(result)
4146*6236dae4SAndroid Build Coastguard Worker     goto out;
4147*6236dae4SAndroid Build Coastguard Worker   if(port) {
4148*6236dae4SAndroid Build Coastguard Worker     result = Curl_dyn_addf(&buf, ":%s", port);
4149*6236dae4SAndroid Build Coastguard Worker     if(result)
4150*6236dae4SAndroid Build Coastguard Worker       goto out;
4151*6236dae4SAndroid Build Coastguard Worker   }
4152*6236dae4SAndroid Build Coastguard Worker   req->authority = strdup(Curl_dyn_ptr(&buf));
4153*6236dae4SAndroid Build Coastguard Worker   if(!req->authority)
4154*6236dae4SAndroid Build Coastguard Worker     goto out;
4155*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4156*6236dae4SAndroid Build Coastguard Worker 
4157*6236dae4SAndroid Build Coastguard Worker out:
4158*6236dae4SAndroid Build Coastguard Worker   free(user);
4159*6236dae4SAndroid Build Coastguard Worker   free(pass);
4160*6236dae4SAndroid Build Coastguard Worker   free(host);
4161*6236dae4SAndroid Build Coastguard Worker   free(port);
4162*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&buf);
4163*6236dae4SAndroid Build Coastguard Worker   return result;
4164*6236dae4SAndroid Build Coastguard Worker }
4165*6236dae4SAndroid Build Coastguard Worker 
req_assign_url_path(struct httpreq * req,CURLU * url)4166*6236dae4SAndroid Build Coastguard Worker static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
4167*6236dae4SAndroid Build Coastguard Worker {
4168*6236dae4SAndroid Build Coastguard Worker   char *path, *query;
4169*6236dae4SAndroid Build Coastguard Worker   struct dynbuf buf;
4170*6236dae4SAndroid Build Coastguard Worker   CURLUcode uc;
4171*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_URL_MALFORMAT;
4172*6236dae4SAndroid Build Coastguard Worker 
4173*6236dae4SAndroid Build Coastguard Worker   path = query = NULL;
4174*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
4175*6236dae4SAndroid Build Coastguard Worker 
4176*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_PATH, &path, CURLU_PATH_AS_IS);
4177*6236dae4SAndroid Build Coastguard Worker   if(uc)
4178*6236dae4SAndroid Build Coastguard Worker     goto out;
4179*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_QUERY, &query, 0);
4180*6236dae4SAndroid Build Coastguard Worker   if(uc && uc != CURLUE_NO_QUERY)
4181*6236dae4SAndroid Build Coastguard Worker     goto out;
4182*6236dae4SAndroid Build Coastguard Worker 
4183*6236dae4SAndroid Build Coastguard Worker   if(!path && !query) {
4184*6236dae4SAndroid Build Coastguard Worker     req->path = NULL;
4185*6236dae4SAndroid Build Coastguard Worker   }
4186*6236dae4SAndroid Build Coastguard Worker   else if(path && !query) {
4187*6236dae4SAndroid Build Coastguard Worker     req->path = path;
4188*6236dae4SAndroid Build Coastguard Worker     path = NULL;
4189*6236dae4SAndroid Build Coastguard Worker   }
4190*6236dae4SAndroid Build Coastguard Worker   else {
4191*6236dae4SAndroid Build Coastguard Worker     if(path) {
4192*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_add(&buf, path);
4193*6236dae4SAndroid Build Coastguard Worker       if(result)
4194*6236dae4SAndroid Build Coastguard Worker         goto out;
4195*6236dae4SAndroid Build Coastguard Worker     }
4196*6236dae4SAndroid Build Coastguard Worker     if(query) {
4197*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_addf(&buf, "?%s", query);
4198*6236dae4SAndroid Build Coastguard Worker       if(result)
4199*6236dae4SAndroid Build Coastguard Worker         goto out;
4200*6236dae4SAndroid Build Coastguard Worker     }
4201*6236dae4SAndroid Build Coastguard Worker     req->path = strdup(Curl_dyn_ptr(&buf));
4202*6236dae4SAndroid Build Coastguard Worker     if(!req->path)
4203*6236dae4SAndroid Build Coastguard Worker       goto out;
4204*6236dae4SAndroid Build Coastguard Worker   }
4205*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4206*6236dae4SAndroid Build Coastguard Worker 
4207*6236dae4SAndroid Build Coastguard Worker out:
4208*6236dae4SAndroid Build Coastguard Worker   free(path);
4209*6236dae4SAndroid Build Coastguard Worker   free(query);
4210*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&buf);
4211*6236dae4SAndroid Build Coastguard Worker   return result;
4212*6236dae4SAndroid Build Coastguard Worker }
4213*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_make2(struct httpreq ** preq,const char * method,size_t m_len,CURLU * url,const char * scheme_default)4214*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_req_make2(struct httpreq **preq,
4215*6236dae4SAndroid Build Coastguard Worker                              const char *method, size_t m_len,
4216*6236dae4SAndroid Build Coastguard Worker                              CURLU *url, const char *scheme_default)
4217*6236dae4SAndroid Build Coastguard Worker {
4218*6236dae4SAndroid Build Coastguard Worker   struct httpreq *req;
4219*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OUT_OF_MEMORY;
4220*6236dae4SAndroid Build Coastguard Worker   CURLUcode uc;
4221*6236dae4SAndroid Build Coastguard Worker 
4222*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(method);
4223*6236dae4SAndroid Build Coastguard Worker   if(m_len + 1 > sizeof(req->method))
4224*6236dae4SAndroid Build Coastguard Worker     return CURLE_BAD_FUNCTION_ARGUMENT;
4225*6236dae4SAndroid Build Coastguard Worker 
4226*6236dae4SAndroid Build Coastguard Worker   req = calloc(1, sizeof(*req));
4227*6236dae4SAndroid Build Coastguard Worker   if(!req)
4228*6236dae4SAndroid Build Coastguard Worker     goto out;
4229*6236dae4SAndroid Build Coastguard Worker   memcpy(req->method, method, m_len);
4230*6236dae4SAndroid Build Coastguard Worker 
4231*6236dae4SAndroid Build Coastguard Worker   uc = curl_url_get(url, CURLUPART_SCHEME, &req->scheme, 0);
4232*6236dae4SAndroid Build Coastguard Worker   if(uc && uc != CURLUE_NO_SCHEME)
4233*6236dae4SAndroid Build Coastguard Worker     goto out;
4234*6236dae4SAndroid Build Coastguard Worker   if(!req->scheme && scheme_default) {
4235*6236dae4SAndroid Build Coastguard Worker     req->scheme = strdup(scheme_default);
4236*6236dae4SAndroid Build Coastguard Worker     if(!req->scheme)
4237*6236dae4SAndroid Build Coastguard Worker       goto out;
4238*6236dae4SAndroid Build Coastguard Worker   }
4239*6236dae4SAndroid Build Coastguard Worker 
4240*6236dae4SAndroid Build Coastguard Worker   result = req_assign_url_authority(req, url);
4241*6236dae4SAndroid Build Coastguard Worker   if(result)
4242*6236dae4SAndroid Build Coastguard Worker     goto out;
4243*6236dae4SAndroid Build Coastguard Worker   result = req_assign_url_path(req, url);
4244*6236dae4SAndroid Build Coastguard Worker   if(result)
4245*6236dae4SAndroid Build Coastguard Worker     goto out;
4246*6236dae4SAndroid Build Coastguard Worker 
4247*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
4248*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
4249*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4250*6236dae4SAndroid Build Coastguard Worker 
4251*6236dae4SAndroid Build Coastguard Worker out:
4252*6236dae4SAndroid Build Coastguard Worker   if(result && req)
4253*6236dae4SAndroid Build Coastguard Worker     Curl_http_req_free(req);
4254*6236dae4SAndroid Build Coastguard Worker   *preq = result ? NULL : req;
4255*6236dae4SAndroid Build Coastguard Worker   return result;
4256*6236dae4SAndroid Build Coastguard Worker }
4257*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_free(struct httpreq * req)4258*6236dae4SAndroid Build Coastguard Worker void Curl_http_req_free(struct httpreq *req)
4259*6236dae4SAndroid Build Coastguard Worker {
4260*6236dae4SAndroid Build Coastguard Worker   if(req) {
4261*6236dae4SAndroid Build Coastguard Worker     free(req->scheme);
4262*6236dae4SAndroid Build Coastguard Worker     free(req->authority);
4263*6236dae4SAndroid Build Coastguard Worker     free(req->path);
4264*6236dae4SAndroid Build Coastguard Worker     Curl_dynhds_free(&req->headers);
4265*6236dae4SAndroid Build Coastguard Worker     Curl_dynhds_free(&req->trailers);
4266*6236dae4SAndroid Build Coastguard Worker     free(req);
4267*6236dae4SAndroid Build Coastguard Worker   }
4268*6236dae4SAndroid Build Coastguard Worker }
4269*6236dae4SAndroid Build Coastguard Worker 
4270*6236dae4SAndroid Build Coastguard Worker struct name_const {
4271*6236dae4SAndroid Build Coastguard Worker   const char *name;
4272*6236dae4SAndroid Build Coastguard Worker   size_t namelen;
4273*6236dae4SAndroid Build Coastguard Worker };
4274*6236dae4SAndroid Build Coastguard Worker 
4275*6236dae4SAndroid Build Coastguard Worker static struct name_const H2_NON_FIELD[] = {
4276*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Host") },
4277*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Upgrade") },
4278*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Connection") },
4279*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Keep-Alive") },
4280*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Proxy-Connection") },
4281*6236dae4SAndroid Build Coastguard Worker   { STRCONST("Transfer-Encoding") },
4282*6236dae4SAndroid Build Coastguard Worker };
4283*6236dae4SAndroid Build Coastguard Worker 
h2_non_field(const char * name,size_t namelen)4284*6236dae4SAndroid Build Coastguard Worker static bool h2_non_field(const char *name, size_t namelen)
4285*6236dae4SAndroid Build Coastguard Worker {
4286*6236dae4SAndroid Build Coastguard Worker   size_t i;
4287*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < sizeof(H2_NON_FIELD)/sizeof(H2_NON_FIELD[0]); ++i) {
4288*6236dae4SAndroid Build Coastguard Worker     if(namelen < H2_NON_FIELD[i].namelen)
4289*6236dae4SAndroid Build Coastguard Worker       return FALSE;
4290*6236dae4SAndroid Build Coastguard Worker     if(namelen == H2_NON_FIELD[i].namelen &&
4291*6236dae4SAndroid Build Coastguard Worker        strcasecompare(H2_NON_FIELD[i].name, name))
4292*6236dae4SAndroid Build Coastguard Worker       return TRUE;
4293*6236dae4SAndroid Build Coastguard Worker   }
4294*6236dae4SAndroid Build Coastguard Worker   return FALSE;
4295*6236dae4SAndroid Build Coastguard Worker }
4296*6236dae4SAndroid Build Coastguard Worker 
Curl_http_req_to_h2(struct dynhds * h2_headers,struct httpreq * req,struct Curl_easy * data)4297*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
4298*6236dae4SAndroid Build Coastguard Worker                              struct httpreq *req, struct Curl_easy *data)
4299*6236dae4SAndroid Build Coastguard Worker {
4300*6236dae4SAndroid Build Coastguard Worker   const char *scheme = NULL, *authority = NULL;
4301*6236dae4SAndroid Build Coastguard Worker   struct dynhds_entry *e;
4302*6236dae4SAndroid Build Coastguard Worker   size_t i;
4303*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
4304*6236dae4SAndroid Build Coastguard Worker 
4305*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(req);
4306*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(h2_headers);
4307*6236dae4SAndroid Build Coastguard Worker 
4308*6236dae4SAndroid Build Coastguard Worker   if(req->scheme) {
4309*6236dae4SAndroid Build Coastguard Worker     scheme = req->scheme;
4310*6236dae4SAndroid Build Coastguard Worker   }
4311*6236dae4SAndroid Build Coastguard Worker   else if(strcmp("CONNECT", req->method)) {
4312*6236dae4SAndroid Build Coastguard Worker     scheme = Curl_checkheaders(data, STRCONST(HTTP_PSEUDO_SCHEME));
4313*6236dae4SAndroid Build Coastguard Worker     if(scheme) {
4314*6236dae4SAndroid Build Coastguard Worker       scheme += sizeof(HTTP_PSEUDO_SCHEME);
4315*6236dae4SAndroid Build Coastguard Worker       while(*scheme && ISBLANK(*scheme))
4316*6236dae4SAndroid Build Coastguard Worker         scheme++;
4317*6236dae4SAndroid Build Coastguard Worker       infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
4318*6236dae4SAndroid Build Coastguard Worker     }
4319*6236dae4SAndroid Build Coastguard Worker     else {
4320*6236dae4SAndroid Build Coastguard Worker       scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL) ?
4321*6236dae4SAndroid Build Coastguard Worker         "https" : "http";
4322*6236dae4SAndroid Build Coastguard Worker     }
4323*6236dae4SAndroid Build Coastguard Worker   }
4324*6236dae4SAndroid Build Coastguard Worker 
4325*6236dae4SAndroid Build Coastguard Worker   if(req->authority) {
4326*6236dae4SAndroid Build Coastguard Worker     authority = req->authority;
4327*6236dae4SAndroid Build Coastguard Worker   }
4328*6236dae4SAndroid Build Coastguard Worker   else {
4329*6236dae4SAndroid Build Coastguard Worker     e = Curl_dynhds_get(&req->headers, STRCONST("Host"));
4330*6236dae4SAndroid Build Coastguard Worker     if(e)
4331*6236dae4SAndroid Build Coastguard Worker       authority = e->value;
4332*6236dae4SAndroid Build Coastguard Worker   }
4333*6236dae4SAndroid Build Coastguard Worker 
4334*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_reset(h2_headers);
4335*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_set_opts(h2_headers, DYNHDS_OPT_LOWERCASE);
4336*6236dae4SAndroid Build Coastguard Worker   result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_METHOD),
4337*6236dae4SAndroid Build Coastguard Worker                            req->method, strlen(req->method));
4338*6236dae4SAndroid Build Coastguard Worker   if(!result && scheme) {
4339*6236dae4SAndroid Build Coastguard Worker     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_SCHEME),
4340*6236dae4SAndroid Build Coastguard Worker                              scheme, strlen(scheme));
4341*6236dae4SAndroid Build Coastguard Worker   }
4342*6236dae4SAndroid Build Coastguard Worker   if(!result && authority) {
4343*6236dae4SAndroid Build Coastguard Worker     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_AUTHORITY),
4344*6236dae4SAndroid Build Coastguard Worker                              authority, strlen(authority));
4345*6236dae4SAndroid Build Coastguard Worker   }
4346*6236dae4SAndroid Build Coastguard Worker   if(!result && req->path) {
4347*6236dae4SAndroid Build Coastguard Worker     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_PATH),
4348*6236dae4SAndroid Build Coastguard Worker                              req->path, strlen(req->path));
4349*6236dae4SAndroid Build Coastguard Worker   }
4350*6236dae4SAndroid Build Coastguard Worker   for(i = 0; !result && i < Curl_dynhds_count(&req->headers); ++i) {
4351*6236dae4SAndroid Build Coastguard Worker     e = Curl_dynhds_getn(&req->headers, i);
4352*6236dae4SAndroid Build Coastguard Worker     if(!h2_non_field(e->name, e->namelen)) {
4353*6236dae4SAndroid Build Coastguard Worker       result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
4354*6236dae4SAndroid Build Coastguard Worker                                e->value, e->valuelen);
4355*6236dae4SAndroid Build Coastguard Worker     }
4356*6236dae4SAndroid Build Coastguard Worker   }
4357*6236dae4SAndroid Build Coastguard Worker 
4358*6236dae4SAndroid Build Coastguard Worker   return result;
4359*6236dae4SAndroid Build Coastguard Worker }
4360*6236dae4SAndroid Build Coastguard Worker 
Curl_http_resp_make(struct http_resp ** presp,int status,const char * description)4361*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http_resp_make(struct http_resp **presp,
4362*6236dae4SAndroid Build Coastguard Worker                              int status,
4363*6236dae4SAndroid Build Coastguard Worker                              const char *description)
4364*6236dae4SAndroid Build Coastguard Worker {
4365*6236dae4SAndroid Build Coastguard Worker   struct http_resp *resp;
4366*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OUT_OF_MEMORY;
4367*6236dae4SAndroid Build Coastguard Worker 
4368*6236dae4SAndroid Build Coastguard Worker   resp = calloc(1, sizeof(*resp));
4369*6236dae4SAndroid Build Coastguard Worker   if(!resp)
4370*6236dae4SAndroid Build Coastguard Worker     goto out;
4371*6236dae4SAndroid Build Coastguard Worker 
4372*6236dae4SAndroid Build Coastguard Worker   resp->status = status;
4373*6236dae4SAndroid Build Coastguard Worker   if(description) {
4374*6236dae4SAndroid Build Coastguard Worker     resp->description = strdup(description);
4375*6236dae4SAndroid Build Coastguard Worker     if(!resp->description)
4376*6236dae4SAndroid Build Coastguard Worker       goto out;
4377*6236dae4SAndroid Build Coastguard Worker   }
4378*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&resp->headers, 0, DYN_HTTP_REQUEST);
4379*6236dae4SAndroid Build Coastguard Worker   Curl_dynhds_init(&resp->trailers, 0, DYN_HTTP_REQUEST);
4380*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
4381*6236dae4SAndroid Build Coastguard Worker 
4382*6236dae4SAndroid Build Coastguard Worker out:
4383*6236dae4SAndroid Build Coastguard Worker   if(result && resp)
4384*6236dae4SAndroid Build Coastguard Worker     Curl_http_resp_free(resp);
4385*6236dae4SAndroid Build Coastguard Worker   *presp = result ? NULL : resp;
4386*6236dae4SAndroid Build Coastguard Worker   return result;
4387*6236dae4SAndroid Build Coastguard Worker }
4388*6236dae4SAndroid Build Coastguard Worker 
Curl_http_resp_free(struct http_resp * resp)4389*6236dae4SAndroid Build Coastguard Worker void Curl_http_resp_free(struct http_resp *resp)
4390*6236dae4SAndroid Build Coastguard Worker {
4391*6236dae4SAndroid Build Coastguard Worker   if(resp) {
4392*6236dae4SAndroid Build Coastguard Worker     free(resp->description);
4393*6236dae4SAndroid Build Coastguard Worker     Curl_dynhds_free(&resp->headers);
4394*6236dae4SAndroid Build Coastguard Worker     Curl_dynhds_free(&resp->trailers);
4395*6236dae4SAndroid Build Coastguard Worker     if(resp->prev)
4396*6236dae4SAndroid Build Coastguard Worker       Curl_http_resp_free(resp->prev);
4397*6236dae4SAndroid Build Coastguard Worker     free(resp);
4398*6236dae4SAndroid Build Coastguard Worker   }
4399*6236dae4SAndroid Build Coastguard Worker }
4400*6236dae4SAndroid Build Coastguard Worker 
4401*6236dae4SAndroid Build Coastguard Worker struct cr_exp100_ctx {
4402*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader super;
4403*6236dae4SAndroid Build Coastguard Worker   struct curltime start; /* time started waiting */
4404*6236dae4SAndroid Build Coastguard Worker   enum expect100 state;
4405*6236dae4SAndroid Build Coastguard Worker };
4406*6236dae4SAndroid Build Coastguard Worker 
4407*6236dae4SAndroid Build Coastguard Worker /* Expect: 100-continue client reader, blocking uploads */
4408*6236dae4SAndroid Build Coastguard Worker 
http_exp100_continue(struct Curl_easy * data,struct Curl_creader * reader)4409*6236dae4SAndroid Build Coastguard Worker static void http_exp100_continue(struct Curl_easy *data,
4410*6236dae4SAndroid Build Coastguard Worker                                  struct Curl_creader *reader)
4411*6236dae4SAndroid Build Coastguard Worker {
4412*6236dae4SAndroid Build Coastguard Worker   struct cr_exp100_ctx *ctx = reader->ctx;
4413*6236dae4SAndroid Build Coastguard Worker   if(ctx->state > EXP100_SEND_DATA) {
4414*6236dae4SAndroid Build Coastguard Worker     ctx->state = EXP100_SEND_DATA;
4415*6236dae4SAndroid Build Coastguard Worker     data->req.keepon |= KEEP_SEND;
4416*6236dae4SAndroid Build Coastguard Worker     data->req.keepon &= ~KEEP_SEND_TIMED;
4417*6236dae4SAndroid Build Coastguard Worker     Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4418*6236dae4SAndroid Build Coastguard Worker   }
4419*6236dae4SAndroid Build Coastguard Worker }
4420*6236dae4SAndroid Build Coastguard Worker 
cr_exp100_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * nread,bool * eos)4421*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_exp100_read(struct Curl_easy *data,
4422*6236dae4SAndroid Build Coastguard Worker                                struct Curl_creader *reader,
4423*6236dae4SAndroid Build Coastguard Worker                                char *buf, size_t blen,
4424*6236dae4SAndroid Build Coastguard Worker                                size_t *nread, bool *eos)
4425*6236dae4SAndroid Build Coastguard Worker {
4426*6236dae4SAndroid Build Coastguard Worker   struct cr_exp100_ctx *ctx = reader->ctx;
4427*6236dae4SAndroid Build Coastguard Worker   timediff_t ms;
4428*6236dae4SAndroid Build Coastguard Worker 
4429*6236dae4SAndroid Build Coastguard Worker   switch(ctx->state) {
4430*6236dae4SAndroid Build Coastguard Worker   case EXP100_SENDING_REQUEST:
4431*6236dae4SAndroid Build Coastguard Worker     if(!Curl_req_sendbuf_empty(data)) {
4432*6236dae4SAndroid Build Coastguard Worker       /* The initial request data has not been fully sent yet. Do
4433*6236dae4SAndroid Build Coastguard Worker        * not start the timer yet. */
4434*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "cr_exp100_read, request not full sent yet"));
4435*6236dae4SAndroid Build Coastguard Worker       *nread = 0;
4436*6236dae4SAndroid Build Coastguard Worker       *eos = FALSE;
4437*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
4438*6236dae4SAndroid Build Coastguard Worker     }
4439*6236dae4SAndroid Build Coastguard Worker     /* We are now waiting for a reply from the server or
4440*6236dae4SAndroid Build Coastguard Worker      * a timeout on our side IFF the request has been fully sent. */
4441*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, "
4442*6236dae4SAndroid Build Coastguard Worker            "timeout %ldms", data->set.expect_100_timeout));
4443*6236dae4SAndroid Build Coastguard Worker     ctx->state = EXP100_AWAITING_CONTINUE;
4444*6236dae4SAndroid Build Coastguard Worker     ctx->start = Curl_now();
4445*6236dae4SAndroid Build Coastguard Worker     Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
4446*6236dae4SAndroid Build Coastguard Worker     data->req.keepon &= ~KEEP_SEND;
4447*6236dae4SAndroid Build Coastguard Worker     data->req.keepon |= KEEP_SEND_TIMED;
4448*6236dae4SAndroid Build Coastguard Worker     *nread = 0;
4449*6236dae4SAndroid Build Coastguard Worker     *eos = FALSE;
4450*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
4451*6236dae4SAndroid Build Coastguard Worker   case EXP100_FAILED:
4452*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "cr_exp100_read, expectation failed, error"));
4453*6236dae4SAndroid Build Coastguard Worker     *nread = 0;
4454*6236dae4SAndroid Build Coastguard Worker     *eos = FALSE;
4455*6236dae4SAndroid Build Coastguard Worker     return CURLE_READ_ERROR;
4456*6236dae4SAndroid Build Coastguard Worker   case EXP100_AWAITING_CONTINUE:
4457*6236dae4SAndroid Build Coastguard Worker     ms = Curl_timediff(Curl_now(), ctx->start);
4458*6236dae4SAndroid Build Coastguard Worker     if(ms < data->set.expect_100_timeout) {
4459*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired"));
4460*6236dae4SAndroid Build Coastguard Worker       data->req.keepon &= ~KEEP_SEND;
4461*6236dae4SAndroid Build Coastguard Worker       data->req.keepon |= KEEP_SEND_TIMED;
4462*6236dae4SAndroid Build Coastguard Worker       *nread = 0;
4463*6236dae4SAndroid Build Coastguard Worker       *eos = FALSE;
4464*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
4465*6236dae4SAndroid Build Coastguard Worker     }
4466*6236dae4SAndroid Build Coastguard Worker     /* we have waited long enough, continue anyway */
4467*6236dae4SAndroid Build Coastguard Worker     http_exp100_continue(data, reader);
4468*6236dae4SAndroid Build Coastguard Worker     infof(data, "Done waiting for 100-continue");
4469*6236dae4SAndroid Build Coastguard Worker     FALLTHROUGH();
4470*6236dae4SAndroid Build Coastguard Worker   default:
4471*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "cr_exp100_read, pass through"));
4472*6236dae4SAndroid Build Coastguard Worker     return Curl_creader_read(data, reader->next, buf, blen, nread, eos);
4473*6236dae4SAndroid Build Coastguard Worker   }
4474*6236dae4SAndroid Build Coastguard Worker }
4475*6236dae4SAndroid Build Coastguard Worker 
cr_exp100_done(struct Curl_easy * data,struct Curl_creader * reader,int premature)4476*6236dae4SAndroid Build Coastguard Worker static void cr_exp100_done(struct Curl_easy *data,
4477*6236dae4SAndroid Build Coastguard Worker                            struct Curl_creader *reader, int premature)
4478*6236dae4SAndroid Build Coastguard Worker {
4479*6236dae4SAndroid Build Coastguard Worker   struct cr_exp100_ctx *ctx = reader->ctx;
4480*6236dae4SAndroid Build Coastguard Worker   ctx->state = premature ? EXP100_FAILED : EXP100_SEND_DATA;
4481*6236dae4SAndroid Build Coastguard Worker   data->req.keepon &= ~KEEP_SEND_TIMED;
4482*6236dae4SAndroid Build Coastguard Worker   Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4483*6236dae4SAndroid Build Coastguard Worker }
4484*6236dae4SAndroid Build Coastguard Worker 
4485*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_exp100 = {
4486*6236dae4SAndroid Build Coastguard Worker   "cr-exp100",
4487*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_init,
4488*6236dae4SAndroid Build Coastguard Worker   cr_exp100_read,
4489*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_close,
4490*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_needs_rewind,
4491*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_total_length,
4492*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_resume_from,
4493*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_rewind,
4494*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_unpause,
4495*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_is_paused,
4496*6236dae4SAndroid Build Coastguard Worker   cr_exp100_done,
4497*6236dae4SAndroid Build Coastguard Worker   sizeof(struct cr_exp100_ctx)
4498*6236dae4SAndroid Build Coastguard Worker };
4499*6236dae4SAndroid Build Coastguard Worker 
http_exp100_add_reader(struct Curl_easy * data)4500*6236dae4SAndroid Build Coastguard Worker static CURLcode http_exp100_add_reader(struct Curl_easy *data)
4501*6236dae4SAndroid Build Coastguard Worker {
4502*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *reader = NULL;
4503*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
4504*6236dae4SAndroid Build Coastguard Worker 
4505*6236dae4SAndroid Build Coastguard Worker   result = Curl_creader_create(&reader, data, &cr_exp100,
4506*6236dae4SAndroid Build Coastguard Worker                                CURL_CR_PROTOCOL);
4507*6236dae4SAndroid Build Coastguard Worker   if(!result)
4508*6236dae4SAndroid Build Coastguard Worker     result = Curl_creader_add(data, reader);
4509*6236dae4SAndroid Build Coastguard Worker   if(!result) {
4510*6236dae4SAndroid Build Coastguard Worker     struct cr_exp100_ctx *ctx = reader->ctx;
4511*6236dae4SAndroid Build Coastguard Worker     ctx->state = EXP100_SENDING_REQUEST;
4512*6236dae4SAndroid Build Coastguard Worker   }
4513*6236dae4SAndroid Build Coastguard Worker 
4514*6236dae4SAndroid Build Coastguard Worker   if(result && reader)
4515*6236dae4SAndroid Build Coastguard Worker     Curl_creader_free(data, reader);
4516*6236dae4SAndroid Build Coastguard Worker   return result;
4517*6236dae4SAndroid Build Coastguard Worker }
4518*6236dae4SAndroid Build Coastguard Worker 
Curl_http_exp100_got100(struct Curl_easy * data)4519*6236dae4SAndroid Build Coastguard Worker void Curl_http_exp100_got100(struct Curl_easy *data)
4520*6236dae4SAndroid Build Coastguard Worker {
4521*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
4522*6236dae4SAndroid Build Coastguard Worker   if(r)
4523*6236dae4SAndroid Build Coastguard Worker     http_exp100_continue(data, r);
4524*6236dae4SAndroid Build Coastguard Worker }
4525*6236dae4SAndroid Build Coastguard Worker 
http_exp100_is_waiting(struct Curl_easy * data)4526*6236dae4SAndroid Build Coastguard Worker static bool http_exp100_is_waiting(struct Curl_easy *data)
4527*6236dae4SAndroid Build Coastguard Worker {
4528*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
4529*6236dae4SAndroid Build Coastguard Worker   if(r) {
4530*6236dae4SAndroid Build Coastguard Worker     struct cr_exp100_ctx *ctx = r->ctx;
4531*6236dae4SAndroid Build Coastguard Worker     return (ctx->state == EXP100_AWAITING_CONTINUE);
4532*6236dae4SAndroid Build Coastguard Worker   }
4533*6236dae4SAndroid Build Coastguard Worker   return FALSE;
4534*6236dae4SAndroid Build Coastguard Worker }
4535*6236dae4SAndroid Build Coastguard Worker 
http_exp100_send_anyway(struct Curl_easy * data)4536*6236dae4SAndroid Build Coastguard Worker static void http_exp100_send_anyway(struct Curl_easy *data)
4537*6236dae4SAndroid Build Coastguard Worker {
4538*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
4539*6236dae4SAndroid Build Coastguard Worker   if(r)
4540*6236dae4SAndroid Build Coastguard Worker     http_exp100_continue(data, r);
4541*6236dae4SAndroid Build Coastguard Worker }
4542*6236dae4SAndroid Build Coastguard Worker 
Curl_http_exp100_is_selected(struct Curl_easy * data)4543*6236dae4SAndroid Build Coastguard Worker bool Curl_http_exp100_is_selected(struct Curl_easy *data)
4544*6236dae4SAndroid Build Coastguard Worker {
4545*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
4546*6236dae4SAndroid Build Coastguard Worker   return !!r;
4547*6236dae4SAndroid Build Coastguard Worker }
4548*6236dae4SAndroid Build Coastguard Worker 
4549*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_HTTP */
4550