1 /* 2 * Copyright 2001-2026 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright Siemens AG 2018-2020 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11 #include "internal/e_os.h" 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include "crypto/ctype.h" 15 #include <string.h> 16 #include <openssl/asn1.h> 17 #include <openssl/evp.h> 18 #include <openssl/err.h> 19 #include <openssl/httperr.h> 20 #include <openssl/cmperr.h> 21 #include <openssl/buffer.h> 22 #include <openssl/http.h> 23 #include <openssl/trace.h> 24 #include "internal/sockets.h" 25 #include "internal/common.h" /* for ossl_assert() */ 26 27 #define HTTP_PREFIX "HTTP/" 28 #define HTTP_VERSION_PATT "1." /* allow 1.x */ 29 #define HTTP_VERSION_STR_LEN sizeof(HTTP_VERSION_PATT) /* == strlen("1.0") */ 30 #define HTTP_PREFIX_VERSION HTTP_PREFIX "" HTTP_VERSION_PATT 31 #define HTTP_1_0 HTTP_PREFIX_VERSION "0" /* "HTTP/1.0" */ 32 #define HTTP_LINE1_MINLEN (sizeof(HTTP_PREFIX_VERSION "x 200\n") - 1) 33 #define HTTP_VERSION_MAX_REDIRECTIONS 50 34 35 #define HTTP_STATUS_CODE_OK 200 36 #define HTTP_STATUS_CODE_MOVED_PERMANENTLY 301 37 #define HTTP_STATUS_CODE_FOUND 302 38 #define HTTP_STATUS_CODES_NONFATAL_ERROR 400 39 #define HTTP_STATUS_CODE_NOT_FOUND 404 40 41 /* Stateful HTTP request code, supporting blocking and non-blocking I/O */ 42 43 /* Opaque HTTP request status structure */ 44 45 struct ossl_http_req_ctx_st { 46 int state; /* Current I/O state */ 47 unsigned char *buf; /* Buffer to write request or read response */ 48 int buf_size; /* Buffer size */ 49 int free_wbio; /* wbio allocated internally, free with ctx */ 50 BIO *wbio; /* BIO to write/send request to */ 51 BIO *rbio; /* BIO to read/receive response from */ 52 OSSL_HTTP_bio_cb_t upd_fn; /* Optional BIO update callback used for TLS */ 53 void *upd_arg; /* Optional arg for update callback function */ 54 int use_ssl; /* Use HTTPS */ 55 char *proxy; /* Optional proxy name or URI */ 56 char *server; /* Optional server hostname */ 57 char *port; /* Optional server port */ 58 BIO *mem; /* Mem BIO holding request header or response */ 59 BIO *req; /* BIO holding the request provided by caller */ 60 int method_POST; /* HTTP method is POST (else GET) */ 61 int text; /* Request content type is (likely) text */ 62 char *expected_ct; /* Optional expected Content-Type */ 63 int expect_asn1; /* Response content must be ASN.1-encoded */ 64 unsigned char *pos; /* Current position sending data */ 65 long len_to_send; /* Number of bytes still to send */ 66 size_t resp_len; /* Length of response */ 67 size_t max_resp_len; /* Maximum length of response, or 0 */ 68 int keep_alive; /* Persistent conn. 0=no, 1=prefer, 2=require */ 69 time_t max_time; /* Maximum end time of current transfer, or 0 */ 70 time_t max_total_time; /* Maximum end time of total transfer, or 0 */ 71 char *redirection_url; /* Location obtained from HTTP status 301/302 */ 72 size_t max_hdr_lines; /* Max. number of response header lines, or 0 */ 73 }; 74 75 /* HTTP client OSSL_HTTP_REQ_CTX_nbio() internal states, in typical order */ 76 77 #define OHS_NOREAD 0x1000 /* If set no reading should be performed */ 78 #define OHS_ERROR (0 | OHS_NOREAD) /* Error condition */ 79 #define OHS_ADD_HEADERS (1 | OHS_NOREAD) /* Adding header lines to request */ 80 #define OHS_WRITE_INIT (2 | OHS_NOREAD) /* 1st call: ready to start send */ 81 #define OHS_WRITE_HDR1 (3 | OHS_NOREAD) /* Request header to be sent */ 82 #define OHS_WRITE_HDR (4 | OHS_NOREAD) /* Request header being sent */ 83 #define OHS_WRITE_REQ (5 | OHS_NOREAD) /* Request content (body) being sent */ 84 #define OHS_FLUSH (6 | OHS_NOREAD) /* Request being flushed */ 85 86 #define OHS_FIRSTLINE 1 /* First line of response being read */ 87 #define OHS_HEADERS 2 /* MIME headers of response being read */ 88 #define OHS_HEADERS_ERROR 3 /* MIME headers of response being read after fatal error */ 89 #define OHS_REDIRECT 4 /* MIME headers being read, expecting Location */ 90 #define OHS_ASN1_HEADER 5 /* ASN1 sequence header (tag+length) being read */ 91 #define OHS_ASN1_CONTENT 6 /* ASN1 content octets being read */ 92 #define OHS_ASN1_DONE 7 /* ASN1 content read completed */ 93 #define OHS_STREAM 8 /* HTTP content stream to be read by caller */ 94 #define OHS_ERROR_CONTENT 9 /* response content (body) being read after fatal error */ 95 96 /* Low-level HTTP API implementation */ 97 98 static int no_crlf(const char *component, const char *value) 99 { 100 if (value != NULL && strpbrk(value, "\r\n") != NULL) { 101 ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT, 102 "CR or LF character in %s", component); 103 return 0; 104 } 105 return 1; 106 } 107 108 OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size) 109 { 110 OSSL_HTTP_REQ_CTX *rctx; 111 112 if (wbio == NULL || rbio == NULL) { 113 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 114 return NULL; 115 } 116 117 if ((rctx = OPENSSL_zalloc(sizeof(*rctx))) == NULL) 118 return NULL; 119 rctx->state = OHS_ERROR; 120 rctx->buf_size = buf_size > 0 ? buf_size : OSSL_HTTP_DEFAULT_MAX_LINE_LEN; 121 rctx->buf = OPENSSL_malloc(rctx->buf_size); 122 rctx->wbio = wbio; 123 rctx->rbio = rbio; 124 rctx->max_hdr_lines = OSSL_HTTP_DEFAULT_MAX_RESP_HDR_LINES; 125 if (rctx->buf == NULL) { 126 OPENSSL_free(rctx); 127 return NULL; 128 } 129 rctx->max_resp_len = OSSL_HTTP_DEFAULT_MAX_RESP_LEN; 130 /* everything else is 0, e.g. rctx->len_to_send, or NULL, e.g. rctx->mem */ 131 return rctx; 132 } 133 134 void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx) 135 { 136 if (rctx == NULL) 137 return; 138 /* 139 * Use BIO_free_all() because bio_update_fn may prepend or append to cbio. 140 * This also frees any (e.g., SSL/TLS) BIOs linked with bio and, 141 * like BIO_reset(bio), calls SSL_shutdown() to notify/alert the peer. 142 */ 143 if (rctx->free_wbio) 144 BIO_free_all(rctx->wbio); 145 /* do not free rctx->rbio */ 146 BIO_free(rctx->mem); 147 BIO_free(rctx->req); 148 OPENSSL_free(rctx->buf); 149 OPENSSL_free(rctx->proxy); 150 OPENSSL_free(rctx->server); 151 OPENSSL_free(rctx->port); 152 OPENSSL_free(rctx->expected_ct); 153 OPENSSL_free(rctx); 154 } 155 156 BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx) 157 { 158 if (rctx == NULL) { 159 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 160 return NULL; 161 } 162 return rctx->mem; 163 } 164 165 size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx) 166 { 167 if (rctx == NULL) { 168 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 169 return 0; 170 } 171 return rctx->resp_len; 172 } 173 174 void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx, 175 unsigned long len) 176 { 177 if (rctx == NULL) { 178 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 179 return; 180 } 181 rctx->max_resp_len = len != 0 ? (size_t)len : OSSL_HTTP_DEFAULT_MAX_RESP_LEN; 182 } 183 184 /* 185 * Create request line using |rctx| and |path| (or "/" in case |path| is NULL). 186 * Server name (and optional port) must be given if and only if 187 * a plain HTTP proxy is used and |path| does not begin with 'http://'. 188 */ 189 int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST, 190 const char *server, const char *port, 191 const char *path) 192 { 193 if (rctx == NULL) { 194 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 195 return 0; 196 } 197 if (!no_crlf("server", server) 198 || !no_crlf("port", port) 199 || !no_crlf("path", path)) 200 return 0; 201 BIO_free(rctx->mem); 202 if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL) 203 return 0; 204 205 rctx->method_POST = method_POST != 0; 206 if (BIO_printf(rctx->mem, "%s ", rctx->method_POST ? "POST" : "GET") <= 0) 207 return 0; 208 209 if (server != NULL) { /* HTTP (but not HTTPS) proxy is used */ 210 /* 211 * Section 5.1.2 of RFC 1945 states that the absoluteURI form is only 212 * allowed when using a proxy 213 */ 214 if (BIO_printf(rctx->mem, OSSL_HTTP_PREFIX "%s", server) <= 0) 215 return 0; 216 if (port != NULL && BIO_printf(rctx->mem, ":%s", port) <= 0) 217 return 0; 218 } 219 220 /* Make sure path includes a forward slash (abs_path) */ 221 if (path == NULL) { 222 path = "/"; 223 } else if (HAS_PREFIX(path, "http://")) { /* absoluteURI for proxy use */ 224 if (server != NULL) { 225 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT); 226 return 0; 227 } 228 } else if (path[0] != '/' && BIO_printf(rctx->mem, "/") <= 0) { 229 return 0; 230 } 231 /* 232 * Add (the rest of) the path and the HTTP version, 233 * which is fixed to 1.0 for straightforward implementation of keep-alive 234 */ 235 if (BIO_printf(rctx->mem, "%s " HTTP_1_0 "\r\n", path) <= 0) 236 return 0; 237 238 rctx->resp_len = 0; 239 rctx->state = OHS_ADD_HEADERS; 240 return 1; 241 } 242 243 int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx, 244 const char *name, const char *value) 245 { 246 if (rctx == NULL || name == NULL) { 247 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 248 return 0; 249 } 250 if (rctx->mem == NULL) { 251 ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 252 return 0; 253 } 254 if (!no_crlf("header name", name) 255 || !no_crlf("header value", value)) 256 return 0; 257 258 if (BIO_puts(rctx->mem, name) <= 0) 259 return 0; 260 if (value != NULL) { 261 if (BIO_write(rctx->mem, ": ", 2) != 2) 262 return 0; 263 if (BIO_puts(rctx->mem, value) <= 0) 264 return 0; 265 } 266 return BIO_write(rctx->mem, "\r\n", 2) == 2; 267 } 268 269 int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx, 270 const char *content_type, int asn1, 271 int timeout, int keep_alive) 272 { 273 if (rctx == NULL) { 274 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 275 return 0; 276 } 277 if (keep_alive != 0 278 && rctx->state != OHS_ERROR && rctx->state != OHS_ADD_HEADERS) { 279 /* Cannot anymore set keep-alive in request header */ 280 ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 281 return 0; 282 } 283 284 OPENSSL_free(rctx->expected_ct); 285 rctx->expected_ct = NULL; 286 if (content_type != NULL 287 && (rctx->expected_ct = OPENSSL_strdup(content_type)) == NULL) 288 return 0; 289 290 rctx->expect_asn1 = asn1; 291 if (timeout >= 0) 292 rctx->max_time = timeout > 0 ? time(NULL) + timeout : 0; 293 else /* take over any |overall_timeout| arg of OSSL_HTTP_open(), else 0 */ 294 rctx->max_time = rctx->max_total_time; 295 rctx->keep_alive = keep_alive; 296 return 1; 297 } 298 299 static int set1_content(OSSL_HTTP_REQ_CTX *rctx, 300 const char *content_type, BIO *req) 301 { 302 long req_len = 0; 303 #ifndef OPENSSL_NO_STDIO 304 FILE *fp = NULL; 305 #endif 306 307 if (rctx == NULL || (req == NULL && content_type != NULL)) { 308 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 309 return 0; 310 } 311 312 if (rctx->keep_alive != 0 313 && !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Connection", "keep-alive")) 314 return 0; 315 316 BIO_free(rctx->req); 317 rctx->req = NULL; 318 if (req == NULL) 319 return 1; 320 if (!rctx->method_POST) { 321 ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 322 return 0; 323 } 324 325 if (content_type == NULL) { 326 rctx->text = 1; /* assuming request to be text by default, used just for tracing */ 327 } else { 328 if (HAS_CASE_PREFIX(content_type, "text/")) 329 rctx->text = 1; 330 if (!OSSL_HTTP_REQ_CTX_add1_header(rctx, "Content-Type", content_type)) 331 return 0; 332 } 333 334 /* 335 * BIO_CTRL_INFO yields the data length at least for memory BIOs, but for 336 * file-based BIOs it gives the current position, which is not what we need. 337 */ 338 if (BIO_method_type(req) == BIO_TYPE_FILE) { 339 #ifndef OPENSSL_NO_STDIO 340 if (BIO_get_fp(req, &fp) == 1 && fseek(fp, 0, SEEK_END) == 0) { 341 req_len = ftell(fp); 342 (void)fseek(fp, 0, SEEK_SET); 343 } else { 344 fp = NULL; 345 } 346 #endif 347 } else { 348 req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL); 349 /* 350 * Streaming BIOs likely will not support querying the size at all, 351 * and we assume we got a correct value if req_len > 0. 352 */ 353 } 354 if (( 355 #ifndef OPENSSL_NO_STDIO 356 fp != NULL /* definitely correct req_len */ || 357 #endif 358 req_len > 0) 359 && BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) < 0) 360 return 0; 361 362 if (!BIO_up_ref(req)) 363 return 0; 364 rctx->req = req; 365 return 1; 366 } 367 368 int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type, 369 const ASN1_ITEM *it, const ASN1_VALUE *req) 370 { 371 BIO *mem = NULL; 372 int res = 1; 373 374 if (req != NULL) 375 res = (mem = ASN1_item_i2d_mem_bio(it, req)) != NULL; 376 res = res && set1_content(rctx, content_type, mem); 377 BIO_free(mem); 378 return res; 379 } 380 381 void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx, 382 size_t count) 383 { 384 if (rctx == NULL) { 385 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 386 return; 387 } 388 rctx->max_hdr_lines = count; 389 } 390 391 static int add1_headers(OSSL_HTTP_REQ_CTX *rctx, 392 const STACK_OF(CONF_VALUE) *headers, const char *host) 393 { 394 int i; 395 int add_host = host != NULL && *host != '\0'; 396 CONF_VALUE *hdr; 397 398 for (i = 0; i < sk_CONF_VALUE_num(headers); i++) { 399 hdr = sk_CONF_VALUE_value(headers, i); 400 if (add_host && OPENSSL_strcasecmp("host", hdr->name) == 0) 401 add_host = 0; 402 if (!OSSL_HTTP_REQ_CTX_add1_header(rctx, hdr->name, hdr->value)) 403 return 0; 404 } 405 406 if (add_host && !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Host", host)) 407 return 0; 408 return 1; 409 } 410 411 /* Create OSSL_HTTP_REQ_CTX structure using the values provided. */ 412 static OSSL_HTTP_REQ_CTX *http_req_ctx_new(int free_wbio, BIO *wbio, BIO *rbio, 413 OSSL_HTTP_bio_cb_t bio_update_fn, 414 void *arg, int use_ssl, 415 const char *proxy, 416 const char *server, const char *port, 417 int buf_size, int overall_timeout) 418 { 419 OSSL_HTTP_REQ_CTX *rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, buf_size); 420 421 if (rctx == NULL) 422 return NULL; 423 rctx->free_wbio = free_wbio; 424 rctx->upd_fn = bio_update_fn; 425 rctx->upd_arg = arg; 426 rctx->use_ssl = use_ssl; 427 if (proxy != NULL 428 && (rctx->proxy = OPENSSL_strdup(proxy)) == NULL) 429 goto err; 430 if (server != NULL 431 && (rctx->server = OPENSSL_strdup(server)) == NULL) 432 goto err; 433 if (port != NULL 434 && (rctx->port = OPENSSL_strdup(port)) == NULL) 435 goto err; 436 rctx->max_total_time = overall_timeout > 0 ? time(NULL) + overall_timeout : 0; 437 return rctx; 438 439 err: 440 OSSL_HTTP_REQ_CTX_free(rctx); 441 return NULL; 442 } 443 444 /* 445 * Parse first HTTP response line. This should be like this: "HTTP/1.0 200 OK". 446 * We need to obtain the status code and (optional) informational message. 447 * Return any received HTTP response status code, or 0 on fatal error. 448 */ 449 450 static int parse_http_line1(char *line, int *found_keep_alive) 451 { 452 int i, retcode; 453 char *code, *reason, *end; 454 455 if (!CHECK_AND_SKIP_PREFIX(line, HTTP_PREFIX_VERSION)) 456 goto err; 457 /* above HTTP 1.0, connection persistence is the default */ 458 *found_keep_alive = *line > '0'; 459 460 /* Skip to first whitespace (past protocol info) */ 461 for (code = line; *code != '\0' && !ossl_isspace(*code); code++) 462 continue; 463 if (*code == '\0') 464 goto err; 465 466 /* Skip past whitespace to start of response code */ 467 while (*code != '\0' && ossl_isspace(*code)) 468 code++; 469 if (*code == '\0') 470 goto err; 471 472 /* Find end of response code: first whitespace after start of code */ 473 for (reason = code; *reason != '\0' && !ossl_isspace(*reason); reason++) 474 continue; 475 476 if (*reason == '\0') 477 goto err; 478 479 /* Set end of response code and start of message */ 480 *reason++ = '\0'; 481 482 /* Attempt to parse numeric code */ 483 retcode = strtoul(code, &end, 10); 484 if (*end != '\0') 485 goto err; 486 487 /* Skip over any leading whitespace in message */ 488 while (*reason != '\0' && ossl_isspace(*reason)) 489 reason++; 490 491 if (*reason != '\0') { 492 /* 493 * Finally zap any trailing whitespace in message (include CRLF) 494 */ 495 496 /* chop any trailing whitespace from reason */ 497 /* We know reason has a non-whitespace character so this is OK */ 498 for (end = reason + strlen(reason) - 1; ossl_isspace(*end); end--) 499 *end = '\0'; 500 } 501 502 switch (retcode) { 503 case HTTP_STATUS_CODE_OK: 504 case HTTP_STATUS_CODE_MOVED_PERMANENTLY: 505 case HTTP_STATUS_CODE_FOUND: 506 return retcode; 507 default: 508 if (retcode == HTTP_STATUS_CODE_NOT_FOUND 509 || retcode < HTTP_STATUS_CODES_NONFATAL_ERROR) { 510 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_STATUS_CODE_UNSUPPORTED, "code=%s", code); 511 if (*reason != '\0') 512 ERR_add_error_data(2, ", reason=", reason); 513 } /* must return content normally if status >= 400, still tentatively raised error on 404 */ 514 return retcode; 515 } 516 517 err: 518 for (i = 0; i < 60 && line[i] != '\0'; i++) 519 if (!ossl_isprint(line[i])) 520 line[i] = ' '; 521 line[i] = '\0'; 522 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR, "content=%s", line); 523 return 0; 524 } 525 526 static int check_max_len(const char *desc, size_t max_len, size_t len) 527 { 528 if (max_len != 0 && len > max_len) { 529 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED, 530 "%s length=%zu, max=%zu", desc, len, max_len); 531 return 0; 532 } 533 return 1; 534 } 535 536 static int check_set_resp_len(const char *desc, OSSL_HTTP_REQ_CTX *rctx, size_t len) 537 { 538 if (!check_max_len(desc, rctx->max_resp_len, len)) 539 return 0; 540 if (rctx->resp_len != 0 && rctx->resp_len != len) { 541 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH, 542 "%s length=%zu, Content-Length=%zu", desc, len, rctx->resp_len); 543 return 0; 544 } 545 rctx->resp_len = len; 546 return 1; 547 } 548 549 static int may_still_retry(time_t max_time, int *ptimeout) 550 { 551 time_t time_diff, now = time(NULL); 552 553 if (max_time != 0) { 554 if (max_time < now) { 555 ERR_raise(ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT); 556 return 0; 557 } 558 time_diff = max_time - now; 559 *ptimeout = time_diff > INT_MAX ? INT_MAX : (int)time_diff; 560 } 561 return 1; 562 } 563 564 /* 565 * Try exchanging request and response via HTTP on (non-)blocking BIO in rctx. 566 * Returns 1 on success, 0 on error or redirection, -1 on BIO_should_retry. 567 */ 568 int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) 569 { 570 int i, found_expected_ct = 0, found_keep_alive = 0; 571 int status_code = 0; 572 int got_text = 1; 573 long n; 574 size_t resp_len = 0; 575 const unsigned char *p; 576 char *buf, *key, *value, *line_end = NULL; 577 size_t resp_hdr_lines = 0; 578 579 if (rctx == NULL) { 580 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 581 return 0; 582 } 583 if (rctx->mem == NULL || rctx->wbio == NULL || rctx->rbio == NULL) { 584 ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 585 return 0; 586 } 587 588 rctx->redirection_url = NULL; 589 next_io: 590 buf = (char *)rctx->buf; 591 if ((rctx->state & OHS_NOREAD) == 0) { 592 if (rctx->expect_asn1 && (rctx->state == OHS_ASN1_HEADER || rctx->state == OHS_ASN1_CONTENT)) { 593 n = BIO_read(rctx->rbio, buf, rctx->buf_size); 594 } else { /* read one text line */ 595 (void)ERR_set_mark(); 596 n = BIO_gets(rctx->rbio, buf, rctx->buf_size); 597 if (n == -2) { /* some BIOs, such as SSL, do not support "gets" */ 598 (void)ERR_pop_to_mark(); 599 n = BIO_get_line(rctx->rbio, buf, rctx->buf_size); 600 } else { 601 (void)ERR_clear_last_mark(); 602 } 603 } 604 if (n <= 0) { 605 if (rctx->state == OHS_ERROR_CONTENT) { 606 if (OSSL_TRACE_ENABLED(HTTP)) 607 OSSL_TRACE(HTTP, "]\n"); /* end of error response content */ 608 /* in addition, throw error on inconsistent length: */ 609 (void)check_set_resp_len("error response content", rctx, resp_len); 610 return 0; 611 } 612 if (BIO_should_retry(rctx->rbio)) 613 return -1; 614 ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA); 615 return 0; 616 } 617 618 /* Write data to memory BIO */ 619 if (BIO_write(rctx->mem, buf, n) != n) 620 return 0; 621 } 622 623 switch (rctx->state) { 624 case OHS_ERROR: 625 default: 626 return 0; 627 628 case OHS_ADD_HEADERS: 629 /* Last operation was adding headers: need a final \r\n */ 630 if (BIO_write(rctx->mem, "\r\n", 2) != 2) { 631 rctx->state = OHS_ERROR; 632 return 0; 633 } 634 rctx->state = OHS_WRITE_INIT; 635 636 /* fall through */ 637 case OHS_WRITE_INIT: 638 rctx->len_to_send = BIO_get_mem_data(rctx->mem, &rctx->pos); 639 rctx->state = OHS_WRITE_HDR1; 640 641 /* fall through */ 642 case OHS_WRITE_HDR1: 643 case OHS_WRITE_HDR: 644 /* Copy some chunk of data from rctx->mem to rctx->wbio */ 645 case OHS_WRITE_REQ: 646 /* Copy some chunk of data from rctx->req to rctx->wbio */ 647 648 if (rctx->len_to_send > 0) { 649 size_t sz; 650 651 if (!BIO_write_ex(rctx->wbio, rctx->pos, rctx->len_to_send, &sz)) { 652 if (BIO_should_retry(rctx->wbio)) 653 return -1; 654 rctx->state = OHS_ERROR; 655 return 0; 656 } 657 if (OSSL_TRACE_ENABLED(HTTP)) { 658 if (rctx->state == OHS_WRITE_HDR1) 659 OSSL_TRACE(HTTP, "Sending request header: [\n"); 660 /* for request headers, this usually traces several lines at once: */ 661 OSSL_TRACE_STRING(HTTP, rctx->state != OHS_WRITE_REQ || rctx->text, 662 rctx->state != OHS_WRITE_REQ, rctx->pos, sz); 663 OSSL_TRACE(HTTP, "]\n"); /* end of request header or content */ 664 } 665 if (rctx->state == OHS_WRITE_HDR1) 666 rctx->state = OHS_WRITE_HDR; 667 rctx->pos += sz; 668 rctx->len_to_send -= sz; 669 goto next_io; 670 } 671 if (rctx->state == OHS_WRITE_HDR) { 672 (void)BIO_reset(rctx->mem); 673 rctx->state = OHS_WRITE_REQ; 674 } 675 if (rctx->req != NULL && !BIO_eof(rctx->req)) { 676 if (OSSL_TRACE_ENABLED(HTTP)) 677 OSSL_TRACE1(HTTP, "Sending request content (likely %s)\n", 678 rctx->text ? "text" : "ASN.1"); 679 n = BIO_read(rctx->req, rctx->buf, rctx->buf_size); 680 if (n <= 0) { 681 if (BIO_should_retry(rctx->req)) 682 return -1; 683 ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA); 684 return 0; 685 } 686 rctx->pos = rctx->buf; 687 rctx->len_to_send = n; 688 goto next_io; 689 } 690 rctx->state = OHS_FLUSH; 691 692 /* fall through */ 693 case OHS_FLUSH: 694 695 i = BIO_flush(rctx->wbio); 696 697 if (i > 0) { 698 rctx->state = OHS_FIRSTLINE; 699 goto next_io; 700 } 701 702 if (BIO_should_retry(rctx->wbio)) 703 return -1; 704 705 rctx->state = OHS_ERROR; 706 return 0; 707 708 /* State machine could be broken up at this point and bulky code sections factorized out. */ 709 710 case OHS_FIRSTLINE: 711 case OHS_HEADERS: 712 case OHS_HEADERS_ERROR: 713 case OHS_REDIRECT: 714 case OHS_ERROR_CONTENT: 715 716 /* Attempt to read a line in */ 717 next_line: 718 /* 719 * Due to strange memory BIO behavior with BIO_gets we have to check 720 * there's a complete line in there before calling BIO_gets or we'll 721 * just get a partial read. 722 */ 723 n = BIO_get_mem_data(rctx->mem, &p); 724 if (n <= 0 || memchr(p, '\n', n) == 0) { 725 if (n >= rctx->buf_size) { 726 rctx->state = OHS_ERROR; 727 return 0; 728 } 729 goto next_io; 730 } 731 n = BIO_gets(rctx->mem, buf, rctx->buf_size); 732 733 if (n <= 0) { 734 if (BIO_should_retry(rctx->mem)) 735 goto next_io; 736 rctx->state = OHS_ERROR; 737 return 0; 738 } 739 740 if (rctx->state == OHS_ERROR_CONTENT) { 741 resp_len += n; 742 if (!check_max_len("error response content", rctx->max_resp_len, resp_len)) 743 return 0; 744 if (OSSL_TRACE_ENABLED(HTTP)) /* dump response content line */ 745 OSSL_TRACE_STRING(HTTP, got_text, 1, (unsigned char *)buf, n); 746 goto next_line; 747 } 748 749 resp_hdr_lines++; 750 if (rctx->max_hdr_lines != 0 && rctx->max_hdr_lines < resp_hdr_lines) { 751 ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES); 752 rctx->state = OHS_ERROR; 753 return 0; 754 } 755 756 /* Don't allow excessive lines */ 757 if (n == rctx->buf_size) { 758 ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG); 759 rctx->state = OHS_ERROR; 760 return 0; 761 } 762 763 if (OSSL_TRACE_ENABLED(HTTP)) { 764 /* dump all response header line */ 765 if (rctx->state == OHS_FIRSTLINE) 766 OSSL_TRACE(HTTP, "Receiving response header: [\n"); 767 OSSL_TRACE_STRING(HTTP, 1, 1, (unsigned char *)buf, n); 768 } 769 770 /* First line in response header */ 771 if (rctx->state == OHS_FIRSTLINE) { 772 status_code = parse_http_line1(buf, &found_keep_alive); 773 switch (status_code) { 774 case HTTP_STATUS_CODE_OK: 775 rctx->state = OHS_HEADERS; 776 goto next_line; 777 case HTTP_STATUS_CODE_MOVED_PERMANENTLY: 778 case HTTP_STATUS_CODE_FOUND: /* i.e., moved temporarily */ 779 if (!rctx->method_POST) { /* method is GET */ 780 rctx->state = OHS_REDIRECT; 781 goto next_line; 782 } 783 ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED); 784 /* redirection is not supported/recommended for POST */ 785 /* fall through */ 786 default: 787 /* must return content if status >= 400 */ 788 rctx->state = status_code < HTTP_STATUS_CODES_NONFATAL_ERROR 789 ? OHS_HEADERS_ERROR 790 : OHS_HEADERS; 791 goto next_line; /* continue parsing, also on HTTP error */ 792 } 793 } 794 key = buf; 795 value = strchr(key, ':'); 796 if (value != NULL) { 797 *(value++) = '\0'; 798 while (ossl_isspace(*value)) 799 value++; 800 line_end = strchr(value, '\r'); 801 if (line_end == NULL) 802 line_end = strchr(value, '\n'); 803 if (line_end != NULL) 804 *line_end = '\0'; 805 } 806 if (value != NULL && line_end != NULL) { 807 if (rctx->state == OHS_REDIRECT 808 && OPENSSL_strcasecmp(key, "Location") == 0) { 809 rctx->redirection_url = value; 810 if (OSSL_TRACE_ENABLED(HTTP)) 811 OSSL_TRACE(HTTP, "]\n"); 812 /* stop reading due to redirect */ 813 (void)BIO_reset(rctx->rbio); 814 return 0; 815 } 816 if (OPENSSL_strcasecmp(key, "Content-Type") == 0) { 817 got_text = HAS_CASE_PREFIX(value, "text/"); 818 if (got_text 819 && rctx->state == OHS_HEADERS 820 && rctx->expect_asn1 821 && (status_code >= HTTP_STATUS_CODES_NONFATAL_ERROR 822 || status_code == HTTP_STATUS_CODE_OK)) { 823 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_CONTENT_TYPE_MISMATCH, 824 "expected ASN.1 content but got http code %d with Content-Type: %s", 825 status_code, value); 826 rctx->state = OHS_HEADERS_ERROR; 827 goto next_line; 828 } 829 if (rctx->state == OHS_HEADERS 830 && rctx->expected_ct != NULL) { 831 const char *semicolon; 832 833 if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0 834 /* ignore past ';' unless expected_ct contains ';' */ 835 && (strchr(rctx->expected_ct, ';') != NULL 836 || (semicolon = strchr(value, ';')) == NULL 837 || (size_t)(semicolon - value) != strlen(rctx->expected_ct) 838 || OPENSSL_strncasecmp(rctx->expected_ct, value, 839 semicolon - value) 840 != 0)) { 841 ERR_raise_data(ERR_LIB_HTTP, 842 HTTP_R_UNEXPECTED_CONTENT_TYPE, 843 "expected=%s, actual=%s", 844 rctx->expected_ct, value); 845 return 0; 846 } 847 found_expected_ct = 1; 848 } 849 } 850 851 /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */ 852 if (OPENSSL_strcasecmp(key, "Connection") == 0) { 853 if (OPENSSL_strcasecmp(value, "keep-alive") == 0) 854 found_keep_alive = 1; 855 else if (OPENSSL_strcasecmp(value, "close") == 0) 856 found_keep_alive = 0; 857 } else if (OPENSSL_strcasecmp(key, "Content-Length") == 0) { 858 size_t content_len = (size_t)strtoul(value, &line_end, 10); 859 860 if (line_end == value || *line_end != '\0') { 861 ERR_raise_data(ERR_LIB_HTTP, 862 HTTP_R_ERROR_PARSING_CONTENT_LENGTH, 863 "input=%s", value); 864 return 0; 865 } 866 if (!check_set_resp_len("response content-length", rctx, content_len)) 867 return 0; 868 } 869 } 870 871 /* Look for blank line indicating end of headers */ 872 for (p = rctx->buf; *p != '\0'; p++) { 873 if (*p != '\r' && *p != '\n') 874 break; 875 } 876 if (*p != '\0') /* not end of headers or not end of error response content */ 877 goto next_line; 878 879 /* Found blank line(s) indicating end of headers */ 880 if (OSSL_TRACE_ENABLED(HTTP)) 881 OSSL_TRACE(HTTP, "]\n"); /* end of response header */ 882 883 if (rctx->keep_alive != 0 /* do not let server initiate keep_alive */ 884 && !found_keep_alive /* otherwise there is no change */) { 885 if (rctx->keep_alive == 2) { 886 rctx->keep_alive = 0; 887 ERR_raise(ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION); 888 return 0; 889 } 890 rctx->keep_alive = 0; 891 } 892 893 if (rctx->state == OHS_HEADERS_ERROR) { 894 rctx->state = OHS_ERROR_CONTENT; 895 if (OSSL_TRACE_ENABLED(HTTP)) { 896 OSSL_TRACE1(HTTP, "Receiving error response content (likely %s): [\n", 897 got_text ? "text" : "ASN.1"); 898 goto next_line; 899 } 900 /* discard response content when trace not enabled */ 901 (void)BIO_reset(rctx->rbio); 902 return 0; 903 } 904 905 if (rctx->expected_ct != NULL && !found_expected_ct) { 906 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE, 907 "expected=%s", rctx->expected_ct); 908 return 0; 909 } 910 if (rctx->state == OHS_REDIRECT) { 911 /* http status code indicated redirect but there was no Location */ 912 ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_REDIRECT_LOCATION); 913 return 0; 914 } 915 916 /* Note: in non-error situations cannot trace response content */ 917 if (!rctx->expect_asn1) { 918 if (OSSL_TRACE_ENABLED(HTTP)) 919 OSSL_TRACE(HTTP, "Receiving response text content\n"); 920 rctx->state = OHS_STREAM; 921 return 1; 922 } 923 924 if (OSSL_TRACE_ENABLED(HTTP)) 925 OSSL_TRACE(HTTP, "Receiving response ASN.1 content\n"); 926 rctx->state = OHS_ASN1_HEADER; 927 928 /* Fall thru */ 929 case OHS_ASN1_HEADER: 930 /* 931 * Now reading ASN1 header: can read at least 2 bytes which is enough 932 * for ASN1 SEQUENCE header and either length field or at least the 933 * length of the length field. 934 */ 935 n = BIO_get_mem_data(rctx->mem, &p); 936 if (n < 2) 937 goto next_io; 938 939 /* Check it is an ASN1 SEQUENCE */ 940 if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) { 941 ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_ASN1_ENCODING); 942 return 0; 943 } 944 945 /* Check out length field */ 946 if ((*p & 0x80) != 0) { 947 /* 948 * If MSB set on initial length octet we can now always read 6 949 * octets: make sure we have them. 950 */ 951 if (n < 6) 952 goto next_io; 953 n = *p & 0x7F; 954 /* Not NDEF or excessive length */ 955 if (n == 0 || (n > 4)) { 956 ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_ASN1_LENGTH); 957 return 0; 958 } 959 p++; 960 resp_len = 0; 961 for (i = 0; i < n; i++) { 962 resp_len <<= 8; 963 resp_len |= *p++; 964 } 965 resp_len += n + 2; 966 } else { 967 resp_len = *p + 2; 968 } 969 if (!check_set_resp_len("ASN.1 DER content", rctx, resp_len)) 970 return 0; 971 972 if (OSSL_TRACE_ENABLED(HTTP)) 973 OSSL_TRACE1(HTTP, "Expected response ASN.1 DER content length: %zd\n", resp_len); 974 rctx->state = OHS_ASN1_CONTENT; 975 976 /* Fall thru */ 977 case OHS_ASN1_CONTENT: 978 n = BIO_get_mem_data(rctx->mem, NULL); 979 if (n < 0 || (size_t)n < rctx->resp_len) 980 goto next_io; 981 982 if (OSSL_TRACE_ENABLED(HTTP)) 983 OSSL_TRACE(HTTP, "Finished receiving response ASN.1 content\n"); 984 rctx->state = OHS_ASN1_DONE; 985 return 1; 986 } 987 } 988 989 int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx, 990 ASN1_VALUE **pval, const ASN1_ITEM *it) 991 { 992 const unsigned char *p; 993 int rv; 994 995 *pval = NULL; 996 if ((rv = OSSL_HTTP_REQ_CTX_nbio(rctx)) != 1) 997 return rv; 998 *pval = ASN1_item_d2i(NULL, &p, BIO_get_mem_data(rctx->mem, &p), it); 999 return *pval != NULL; 1000 } 1001 1002 #ifndef OPENSSL_NO_SOCK 1003 1004 static const char *explict_or_default_port(const char *hostserv, const char *port, int use_ssl) 1005 { 1006 if (port == NULL) { 1007 char *service = NULL; 1008 1009 if (!BIO_parse_hostserv(hostserv, NULL, &service, BIO_PARSE_PRIO_HOST)) 1010 return NULL; 1011 if (service == NULL) /* implicit port */ 1012 port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT; 1013 OPENSSL_free(service); 1014 } /* otherwise take the explicitly given port */ 1015 return port; 1016 } 1017 1018 /* set up a new connection BIO, to HTTP server or to HTTP(S) proxy if given */ 1019 static BIO *http_new_bio(const char *server /* optionally includes ":port" */, 1020 const char *server_port /* explicit server port */, 1021 int use_ssl, 1022 const char *proxy /* optionally includes ":port" */, 1023 const char *proxy_port /* explicit proxy port */) 1024 { 1025 const char *host = server; 1026 const char *port = server_port; 1027 BIO *cbio; 1028 1029 if (!ossl_assert(server != NULL)) 1030 return NULL; 1031 1032 if (proxy != NULL) { 1033 host = proxy; 1034 port = proxy_port; 1035 } 1036 1037 port = explict_or_default_port(host, port, use_ssl); 1038 1039 cbio = BIO_new_connect(host /* optionally includes ":port" */); 1040 if (cbio == NULL) 1041 goto end; 1042 if (port != NULL) 1043 (void)BIO_set_conn_port(cbio, port); 1044 1045 end: 1046 return cbio; 1047 } 1048 #endif /* OPENSSL_NO_SOCK */ 1049 1050 /* Exchange request and response via HTTP on (non-)blocking BIO */ 1051 BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx) 1052 { 1053 int rv; 1054 1055 if (rctx == NULL) { 1056 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1057 return NULL; 1058 } 1059 1060 for (;;) { 1061 rv = OSSL_HTTP_REQ_CTX_nbio(rctx); 1062 if (rv != -1) 1063 break; 1064 /* BIO_should_retry was true */ 1065 /* will not actually wait if rctx->max_time == 0 */ 1066 if (BIO_wait(rctx->rbio, rctx->max_time, 100 /* milliseconds */) <= 0) 1067 return NULL; 1068 } 1069 1070 if (rv == 0) { 1071 if (rctx->redirection_url == NULL) { /* an error occurred */ 1072 if (rctx->len_to_send > 0) 1073 ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_SENDING); 1074 else 1075 ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_RECEIVING); 1076 } 1077 return NULL; 1078 } 1079 return rctx->state == OHS_STREAM ? rctx->rbio : rctx->mem; 1080 } 1081 1082 int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx) 1083 { 1084 return rctx != NULL && rctx->keep_alive != 0; 1085 } 1086 1087 /* High-level HTTP API implementation */ 1088 1089 /* Initiate an HTTP session using bio, else use given server, proxy, etc. */ 1090 OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port, 1091 const char *proxy, const char *no_proxy, 1092 int use_ssl, BIO *bio, BIO *rbio, 1093 OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, 1094 int buf_size, int overall_timeout) 1095 { 1096 BIO *cbio; /* == bio if supplied, used as connection BIO if rbio is NULL */ 1097 OSSL_HTTP_REQ_CTX *rctx = NULL; 1098 1099 if (use_ssl && bio_update_fn == NULL) { 1100 ERR_raise(ERR_LIB_HTTP, HTTP_R_TLS_NOT_ENABLED); 1101 return NULL; 1102 } 1103 if (rbio != NULL && (bio == NULL || bio_update_fn != NULL)) { 1104 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT); 1105 return NULL; 1106 } 1107 1108 if (bio != NULL) { 1109 cbio = bio; 1110 if (proxy != NULL || no_proxy != NULL) { 1111 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT); 1112 return NULL; 1113 } 1114 } else { 1115 #ifndef OPENSSL_NO_SOCK 1116 char *proxy_host = NULL, *proxy_port = NULL; 1117 1118 if (server == NULL) { 1119 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1120 return NULL; 1121 } 1122 if (port != NULL && *port == '\0') 1123 port = NULL; 1124 proxy = OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl); 1125 if (proxy != NULL 1126 && !OSSL_HTTP_parse_url(proxy, NULL /* use_ssl */, NULL /* user */, 1127 &proxy_host, &proxy_port, NULL /* num */, 1128 NULL /* path */, NULL, NULL)) 1129 return NULL; 1130 cbio = http_new_bio(server, port, use_ssl, proxy_host, proxy_port); 1131 OPENSSL_free(proxy_host); 1132 OPENSSL_free(proxy_port); 1133 if (cbio == NULL) 1134 return NULL; 1135 #else 1136 ERR_raise(ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED); 1137 return NULL; 1138 #endif 1139 } 1140 1141 (void)ERR_set_mark(); /* prepare removing any spurious libssl errors */ 1142 if (rbio == NULL && BIO_do_connect_retry(cbio, overall_timeout, -1) <= 0) { 1143 if (bio == NULL) /* cbio was not provided by caller */ 1144 BIO_free_all(cbio); 1145 goto end; 1146 } 1147 /* now overall_timeout is guaranteed to be >= 0 */ 1148 1149 /* adapt in order to fix callback design flaw, see #17088 */ 1150 /* callback can be used to wrap or prepend TLS session */ 1151 if (bio_update_fn != NULL) { 1152 BIO *orig_bio = cbio; 1153 1154 cbio = (*bio_update_fn)(cbio, arg, 1 /* connect */, use_ssl != 0); 1155 if (cbio == NULL) { 1156 if (bio == NULL) /* cbio was not provided by caller */ 1157 BIO_free_all(orig_bio); 1158 goto end; 1159 } 1160 } 1161 1162 rctx = http_req_ctx_new(bio == NULL, cbio, rbio != NULL ? rbio : cbio, 1163 bio_update_fn, arg, use_ssl, proxy, server, port, 1164 buf_size, overall_timeout); 1165 1166 end: 1167 if (rctx != NULL) 1168 /* remove any spurious error queue entries by ssl_add_cert_chain() */ 1169 (void)ERR_pop_to_mark(); 1170 else 1171 (void)ERR_clear_last_mark(); 1172 1173 return rctx; 1174 } 1175 1176 int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path, 1177 const STACK_OF(CONF_VALUE) *headers, 1178 const char *content_type, BIO *req, 1179 const char *expected_content_type, int expect_asn1, 1180 size_t max_resp_len, int timeout, int keep_alive) 1181 { 1182 int use_http_proxy; 1183 1184 if (rctx == NULL) { 1185 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1186 return 0; 1187 } 1188 use_http_proxy = rctx->proxy != NULL && !rctx->use_ssl; 1189 if (use_http_proxy && rctx->server == NULL) { 1190 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT); 1191 return 0; 1192 } 1193 rctx->max_resp_len = max_resp_len; /* allows for 0: indefinite */ 1194 1195 return OSSL_HTTP_REQ_CTX_set_request_line(rctx, req != NULL, 1196 use_http_proxy ? rctx->server 1197 : NULL, 1198 rctx->port, path) 1199 && add1_headers(rctx, headers, rctx->server) 1200 && OSSL_HTTP_REQ_CTX_set_expected(rctx, expected_content_type, 1201 expect_asn1, timeout, keep_alive) 1202 && set1_content(rctx, content_type, req); 1203 } 1204 1205 /*- 1206 * Exchange single HTTP request and response according to rctx. 1207 * If rctx->method_POST then use POST, else use GET and ignore content_type. 1208 * The redirection_url output (freed by caller) parameter is used only for GET. 1209 */ 1210 BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url) 1211 { 1212 BIO *resp; 1213 1214 if (rctx == NULL) { 1215 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1216 return NULL; 1217 } 1218 1219 if (redirection_url != NULL) 1220 *redirection_url = NULL; /* do this beforehand to prevent dbl free */ 1221 1222 resp = OSSL_HTTP_REQ_CTX_exchange(rctx); 1223 if (resp == NULL) { 1224 if (rctx->redirection_url != NULL) { 1225 if (redirection_url == NULL) 1226 ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED); 1227 else 1228 /* may be NULL if out of memory: */ 1229 *redirection_url = OPENSSL_strdup(rctx->redirection_url); 1230 } else { 1231 char buf[200]; 1232 unsigned long err = ERR_peek_error(); 1233 int lib = ERR_GET_LIB(err); 1234 int reason = ERR_GET_REASON(err); 1235 1236 if (lib == ERR_LIB_SSL || lib == ERR_LIB_HTTP 1237 || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_TIMEOUT) 1238 || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_ERROR) 1239 #ifndef OPENSSL_NO_CMP 1240 || (lib == ERR_LIB_CMP 1241 && reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE) 1242 #endif 1243 ) { 1244 if (rctx->server != NULL && *rctx->server != '\0') { 1245 BIO_snprintf(buf, sizeof(buf), "server=http%s://%s%s%s", 1246 rctx->use_ssl ? "s" : "", rctx->server, 1247 rctx->port != NULL ? ":" : "", 1248 rctx->port != NULL ? rctx->port : ""); 1249 ERR_add_error_data(1, buf); 1250 } 1251 if (rctx->proxy != NULL) 1252 ERR_add_error_data(2, " proxy=", rctx->proxy); 1253 if (err == 0) { 1254 BIO_snprintf(buf, sizeof(buf), " peer has disconnected%s", 1255 rctx->use_ssl ? " violating the protocol" : ", likely because it requires the use of TLS"); 1256 ERR_add_error_data(1, buf); 1257 } 1258 } 1259 } 1260 } 1261 1262 if (resp != NULL && !BIO_up_ref(resp)) 1263 resp = NULL; 1264 return resp; 1265 } 1266 1267 static int redirection_ok(int n_redir, const char *old_url, const char *new_url) 1268 { 1269 if (n_redir >= HTTP_VERSION_MAX_REDIRECTIONS) { 1270 ERR_raise(ERR_LIB_HTTP, HTTP_R_TOO_MANY_REDIRECTIONS); 1271 return 0; 1272 } 1273 if (*new_url == '/') /* redirection to same server => same protocol */ 1274 return 1; 1275 if (HAS_PREFIX(old_url, OSSL_HTTPS_NAME ":") && !HAS_PREFIX(new_url, OSSL_HTTPS_NAME ":")) { 1276 ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP); 1277 return 0; 1278 } 1279 return 1; 1280 } 1281 1282 /* Get data via HTTP from server at given URL, potentially with redirection */ 1283 BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, 1284 BIO *bio, BIO *rbio, 1285 OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, 1286 int buf_size, const STACK_OF(CONF_VALUE) *headers, 1287 const char *expected_ct, int expect_asn1, 1288 size_t max_resp_len, int timeout) 1289 { 1290 char *current_url; 1291 int n_redirs = 0; 1292 char *host; 1293 char *port; 1294 char *path; 1295 int use_ssl; 1296 BIO *resp = NULL; 1297 time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; 1298 1299 if (url == NULL) { 1300 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1301 return NULL; 1302 } 1303 if ((current_url = OPENSSL_strdup(url)) == NULL) 1304 return NULL; 1305 1306 for (;;) { 1307 OSSL_HTTP_REQ_CTX *rctx; 1308 char *redirection_url; 1309 1310 if (!OSSL_HTTP_parse_url(current_url, &use_ssl, NULL /* user */, &host, 1311 &port, NULL /* port_num */, &path, NULL, NULL)) 1312 break; 1313 1314 rctx = OSSL_HTTP_open(host, port, proxy, no_proxy, 1315 use_ssl, bio, rbio, bio_update_fn, arg, 1316 buf_size, timeout); 1317 new_rpath: 1318 redirection_url = NULL; 1319 if (rctx != NULL) { 1320 if (!OSSL_HTTP_set1_request(rctx, path, headers, 1321 NULL /* content_type */, 1322 NULL /* req */, 1323 expected_ct, expect_asn1, max_resp_len, 1324 -1 /* use same max time (timeout) */, 1325 0 /* no keep_alive */)) { 1326 OSSL_HTTP_REQ_CTX_free(rctx); 1327 rctx = NULL; 1328 } else { 1329 resp = OSSL_HTTP_exchange(rctx, &redirection_url); 1330 } 1331 } 1332 OPENSSL_free(path); 1333 if (resp == NULL && redirection_url != NULL) { 1334 if (redirection_ok(++n_redirs, current_url, redirection_url) 1335 && may_still_retry(max_time, &timeout)) { 1336 (void)BIO_reset(bio); 1337 OPENSSL_free(current_url); 1338 current_url = redirection_url; 1339 if (*redirection_url == '/') { /* redirection to same server */ 1340 path = OPENSSL_strdup(redirection_url); 1341 if (path == NULL) { 1342 OPENSSL_free(host); 1343 OPENSSL_free(port); 1344 (void)OSSL_HTTP_close(rctx, 1); 1345 BIO_free(resp); 1346 OPENSSL_free(current_url); 1347 return NULL; 1348 } 1349 goto new_rpath; 1350 } 1351 OPENSSL_free(host); 1352 OPENSSL_free(port); 1353 (void)OSSL_HTTP_close(rctx, 1); 1354 continue; 1355 } 1356 /* if redirection not allowed, ignore it */ 1357 OPENSSL_free(redirection_url); 1358 } 1359 OPENSSL_free(host); 1360 OPENSSL_free(port); 1361 if (!OSSL_HTTP_close(rctx, resp != NULL)) { 1362 BIO_free(resp); 1363 resp = NULL; 1364 } 1365 break; 1366 } 1367 OPENSSL_free(current_url); 1368 return resp; 1369 } 1370 1371 /* Exchange request and response over a connection managed via |prctx| */ 1372 BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx, 1373 const char *server, const char *port, 1374 const char *path, int use_ssl, 1375 const char *proxy, const char *no_proxy, 1376 BIO *bio, BIO *rbio, 1377 OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, 1378 int buf_size, const STACK_OF(CONF_VALUE) *headers, 1379 const char *content_type, BIO *req, 1380 const char *expected_ct, int expect_asn1, 1381 size_t max_resp_len, int timeout, int keep_alive) 1382 { 1383 OSSL_HTTP_REQ_CTX *rctx = prctx == NULL ? NULL : *prctx; 1384 BIO *resp = NULL; 1385 1386 if (rctx == NULL) { 1387 rctx = OSSL_HTTP_open(server, port, proxy, no_proxy, 1388 use_ssl, bio, rbio, bio_update_fn, arg, 1389 buf_size, timeout); 1390 timeout = -1; /* Already set during opening the connection */ 1391 } 1392 if (rctx != NULL) { 1393 if (OSSL_HTTP_set1_request(rctx, path, headers, content_type, req, 1394 expected_ct, expect_asn1, 1395 max_resp_len, timeout, keep_alive)) 1396 resp = OSSL_HTTP_exchange(rctx, NULL); 1397 if (resp == NULL || !OSSL_HTTP_is_alive(rctx)) { 1398 if (!OSSL_HTTP_close(rctx, resp != NULL)) { 1399 BIO_free(resp); 1400 resp = NULL; 1401 } 1402 rctx = NULL; 1403 } 1404 } 1405 if (prctx != NULL) 1406 *prctx = rctx; 1407 return resp; 1408 } 1409 1410 int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok) 1411 { 1412 BIO *wbio; 1413 int ret = 1; 1414 1415 /* callback can be used to finish TLS session and free its BIO */ 1416 if (rctx != NULL && rctx->upd_fn != NULL) { 1417 wbio = (*rctx->upd_fn)(rctx->wbio, rctx->upd_arg, 1418 0 /* disconnect */, ok); 1419 ret = wbio != NULL; 1420 if (ret) 1421 rctx->wbio = wbio; 1422 } 1423 OSSL_HTTP_REQ_CTX_free(rctx); 1424 return ret; 1425 } 1426 1427 /* BASE64 encoder used for encoding basic proxy authentication credentials */ 1428 static char *base64encode(const void *buf, size_t len) 1429 { 1430 int i; 1431 size_t outl; 1432 char *out; 1433 1434 /* Calculate size of encoded data */ 1435 outl = (len / 3); 1436 if (len % 3 > 0) 1437 outl++; 1438 outl <<= 2; 1439 out = OPENSSL_malloc(outl + 1); 1440 if (out == NULL) 1441 return 0; 1442 1443 i = EVP_EncodeBlock((unsigned char *)out, buf, len); 1444 if (!ossl_assert(0 <= i && (size_t)i <= outl)) { 1445 OPENSSL_free(out); 1446 return NULL; 1447 } 1448 return out; 1449 } 1450 1451 /* 1452 * Promote the given connection BIO using the CONNECT method for a TLS proxy. 1453 * This is typically called by an app, so bio_err and prog are used unless NULL 1454 * to print additional diagnostic information in a user-oriented way. 1455 */ 1456 int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, 1457 const char *proxyuser, const char *proxypass, 1458 int timeout, BIO *bio_err, const char *prog) 1459 { 1460 #undef BUF_SIZE 1461 #define BUF_SIZE (8 * 1024) 1462 char *mbuf = NULL; 1463 char *mbufp; 1464 int read_len = 0; 1465 int ret = 0; 1466 BIO *fbio = NULL; 1467 int rv; 1468 time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; 1469 1470 if (bio == NULL || server == NULL 1471 || (bio_err != NULL && prog == NULL)) { 1472 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 1473 goto end; 1474 } 1475 if (port == NULL || *port == '\0') 1476 port = OSSL_HTTPS_PORT; 1477 if (!no_crlf("server", server) || !no_crlf("port", port)) 1478 goto end; 1479 1480 if ((mbuf = OPENSSL_malloc(BUF_SIZE)) == NULL 1481 || (fbio = BIO_new(BIO_f_buffer())) == NULL) { 1482 BIO_printf(bio_err /* may be NULL */, "%s: out of memory", prog); 1483 goto end; 1484 } 1485 BIO_push(fbio, bio); 1486 1487 /* Add square brackets around a naked IPv6 address */ 1488 if (server[0] != '[' && strchr(server, ':') != NULL) 1489 BIO_printf(fbio, "CONNECT [%s]:%s " HTTP_1_0 "\r\n", server, port); 1490 else 1491 BIO_printf(fbio, "CONNECT %s:%s " HTTP_1_0 "\r\n", server, port); 1492 1493 /* 1494 * Workaround for broken proxies which would otherwise close 1495 * the connection when entering tunnel mode (e.g., Squid 2.6) 1496 */ 1497 BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n"); 1498 1499 /* Support for basic (base64) proxy authentication */ 1500 if (proxyuser != NULL) { 1501 size_t len = strlen(proxyuser) + 1; 1502 char *proxyauth, *proxyauthenc = NULL; 1503 1504 if (proxypass != NULL) 1505 len += strlen(proxypass); 1506 proxyauth = OPENSSL_malloc(len + 1); 1507 if (proxyauth == NULL) 1508 goto end; 1509 if (BIO_snprintf(proxyauth, len + 1, "%s:%s", proxyuser, 1510 proxypass != NULL ? proxypass : "") 1511 != (int)len) 1512 goto proxy_end; 1513 proxyauthenc = base64encode(proxyauth, len); 1514 if (proxyauthenc != NULL) { 1515 BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", proxyauthenc); 1516 OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc)); 1517 } 1518 proxy_end: 1519 OPENSSL_clear_free(proxyauth, len); 1520 if (proxyauthenc == NULL) 1521 goto end; 1522 } 1523 1524 /* Terminate the HTTP CONNECT request */ 1525 BIO_printf(fbio, "\r\n"); 1526 1527 for (;;) { 1528 if (BIO_flush(fbio) != 0) 1529 break; 1530 /* potentially needs to be retried if BIO is non-blocking */ 1531 if (!BIO_should_retry(fbio)) 1532 break; 1533 } 1534 1535 for (;;) { 1536 /* will not actually wait if timeout == 0 */ 1537 rv = BIO_wait(fbio, max_time, 100 /* milliseconds */); 1538 if (rv <= 0) { 1539 BIO_printf(bio_err, "%s: HTTP CONNECT %s\n", prog, 1540 rv == 0 ? "timed out" : "failed waiting for data"); 1541 goto end; 1542 } 1543 1544 /*- 1545 * The first line is the HTTP response. 1546 * According to RFC 7230, it is formatted exactly like this: 1547 * HTTP/d.d ddd reason text\r\n 1548 */ 1549 read_len = BIO_gets(fbio, mbuf, BUF_SIZE); 1550 /* the BIO may not block, so we must wait for the 1st line to come in */ 1551 if (read_len < (int)HTTP_LINE1_MINLEN) 1552 continue; 1553 1554 /* Check for HTTP/1.x */ 1555 mbufp = mbuf; 1556 if (!CHECK_AND_SKIP_PREFIX(mbufp, HTTP_PREFIX)) { 1557 ERR_raise(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR); 1558 BIO_printf(bio_err, "%s: HTTP CONNECT failed, non-HTTP response\n", 1559 prog); 1560 /* Wrong protocol, not even HTTP, so stop reading headers */ 1561 goto end; 1562 } 1563 if (!HAS_PREFIX(mbufp, HTTP_VERSION_PATT)) { 1564 ERR_raise(ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION); 1565 BIO_printf(bio_err, 1566 "%s: HTTP CONNECT failed, bad HTTP version %.*s\n", 1567 prog, (int)HTTP_VERSION_STR_LEN, mbufp); 1568 goto end; 1569 } 1570 mbufp += HTTP_VERSION_STR_LEN; 1571 1572 /* RFC 7231 4.3.6: any 2xx status code is valid */ 1573 if (!HAS_PREFIX(mbufp, " 2")) { 1574 if (ossl_isspace(*mbufp)) 1575 mbufp++; 1576 /* chop any trailing whitespace */ 1577 while (read_len > 0 && ossl_isspace(mbuf[read_len - 1])) 1578 read_len--; 1579 mbuf[read_len] = '\0'; 1580 ERR_raise_data(ERR_LIB_HTTP, HTTP_R_CONNECT_FAILURE, 1581 "reason=%s", mbufp); 1582 BIO_printf(bio_err, "%s: HTTP CONNECT failed, reason=%s\n", 1583 prog, mbufp); 1584 goto end; 1585 } 1586 ret = 1; 1587 break; 1588 } 1589 1590 /* Read past all following headers */ 1591 do { 1592 /* 1593 * This does not necessarily catch the case when the full 1594 * HTTP response came in more than a single TCP message. 1595 */ 1596 read_len = BIO_gets(fbio, mbuf, BUF_SIZE); 1597 } while (read_len > 2); 1598 1599 end: 1600 if (fbio != NULL) { 1601 (void)BIO_flush(fbio); 1602 BIO_pop(fbio); 1603 BIO_free(fbio); 1604 } 1605 OPENSSL_free(mbuf); 1606 return ret; 1607 #undef BUF_SIZE 1608 } 1609