Coverage Report

Created: 2022-10-16 06:45

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