1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <errno.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <strings.h> 34 #include <stdlib.h> 35 #include <netdb.h> 36 37 #include <openssl/ssl.h> 38 #include <openssl/err.h> 39 #include <openssl/rand.h> 40 #include <openssl/pkcs12.h> 41 42 /* this must be included after ssl.h to avoid re-defining 'offsetof' */ 43 #include <sys/sysmacros.h> 44 45 #include <boot_http.h> 46 #include <socket_inet.h> 47 #include <p12access.h> 48 49 #include "bootlog.h" 50 51 #define BOOT_HTTP_MAJOR_VERSION 1 52 #define BOOT_HTTP_MINOR_VERSION 0 53 #define BOOT_HTTP_MICRO_VERSION 0 54 55 static boot_http_ver_t boot_http_ver = { 56 BOOT_HTTP_MAJOR_VERSION, 57 BOOT_HTTP_MINOR_VERSION, 58 BOOT_HTTP_MICRO_VERSION 59 }; 60 61 static int early_err; /* Error from before error occurred */ 62 63 static boolean_t verbosemode = B_FALSE; 64 static char *cipher_list = NULL; /* Ciphers supported (if not default) */ 65 66 typedef struct { 67 int i; /* current position in buffer */ 68 int n; /* number of bytes in buffer */ 69 char buf[512]; /* buffer */ 70 } buf_struct_t; 71 72 typedef struct { 73 uint_t errsrc; /* Source of this error */ 74 ulong_t error; /* Which error? */ 75 } errent_t; 76 77 78 typedef enum { 79 HTTP_REQ_TYPE_HEAD = 1, 80 HTTP_REQ_TYPE_GET 81 } http_req_t; 82 83 #define FAILSAFE 20 /* Max # empty lines to accept */ 84 #define DEFAULT_TIMEOUT 10 /* Default socket read timeout value */ 85 #define HTTP_CONN_INFO 0x90919293 /* Identifies a http_conn_t struct */ 86 #define ESTACK_SIZE 20 /* Size of the stack */ 87 88 typedef struct http_conn_t { 89 uint_t signature; /* Cookie indicating this is a handle */ 90 int fd; /* Connection's fd... */ 91 SSL_CTX *ctx; 92 void *ssl; /* Handle to ssl data structure */ 93 int read_timeout; /* Timeout to use on read requests in sec */ 94 char *basic_auth_userid; /* Basic authentication user ID */ 95 char *basic_auth_password; /* and password */ 96 char is_multipart; /* B_TRUE if doing multipart/mixed download */ 97 char is_firstpart; /* B_TRUE if first part in a multipart xfer */ 98 char is_firstchunk; /* B_TRUE if first chunk in chunked xfer */ 99 char is_chunked; /* B_TRUE if message body is chunked */ 100 boolean_t keepalive; 101 struct sockaddr_in host_addr; /* Address of host */ 102 url_t uri; /* The current URI */ 103 url_hport_t proxy; /* The proxy info */ 104 boolean_t proxied; /* Connection is proxied */ 105 char *random_file; /* File with seed info for pseudo random */ 106 /* number generator */ 107 char *client_cert_file; /* File holding client's certificate */ 108 char *private_key_file; /* File with the private key */ 109 char *file_password; /* file with password to key or pkcs12 file. */ 110 http_respinfo_t resp; /* Response summary info */ 111 char **resphdr; /* Array of header response lines */ 112 buf_struct_t inbuf; 113 char *boundary; /* Boundary text (multipart downloads only) */ 114 uint_t boundary_len; /* Length of boundary string */ 115 uint_t numerrs; 116 uint_t nexterr; /* Next error to return */ 117 ssize_t body_size; /* Size of message body or chunk */ 118 ssize_t body_read; /* # of bytes of body_size processed */ 119 ssize_t body_size_tot; /* Total message body size */ 120 ssize_t body_read_tot; /* # of bytes of body_size_tot processed */ 121 errent_t errs[ESTACK_SIZE]; /* stack of errors on the last request */ 122 /* (libssl can return multiple errors on one */ 123 /* operation) */ 124 } http_conn_t; 125 126 /* 127 * Convenient macros for accessing fields in connection structure. 128 */ 129 #define CONN_HOSTNAME c_id->uri.hport.hostname 130 #define CONN_PORT c_id->uri.hport.port 131 #define CONN_ABSPATH c_id->uri.abspath 132 #define CONN_HTTPS c_id->uri.https 133 #define CONN_PROXY_HOSTNAME c_id->proxy.hostname 134 #define CONN_PROXY_PORT c_id->proxy.port 135 136 #define RESET_ERR(c_id) (c_id)->numerrs = 0, (c_id)->nexterr = 0 137 #define SET_ERR(c_id, src, err) if ((c_id)->numerrs < ESTACK_SIZE) \ 138 (c_id)->errs[(c_id)->numerrs].errsrc = (src), \ 139 (c_id)->errs[(c_id)->numerrs ++].error = (err) 140 141 #define GET_ERR(c_id, e_src, e_code) \ 142 if ((c_id)->nexterr < (c_id)->numerrs) \ 143 (e_src) = (c_id)->errs[((c_id)->nexterr)].errsrc, \ 144 (e_code) = (c_id)->errs[((c_id)->nexterr)++].error; \ 145 else \ 146 (e_src) = 0, (e_code) = 0 147 148 /* 149 * Macro used to increment message body read counters 150 */ 151 #define INC_BREAD_CNT(bool, bcnt) \ 152 if (bool) { \ 153 bcnt--; \ 154 c_id->body_read++;\ 155 c_id->body_read_tot++; \ 156 } 157 158 static int ssl_init = 0; /* 1 when ssl has been initialized */ 159 static char *ca_verify_file; /* List of trusted CA's */ 160 static int verify_depth = 16; /* Certificate chain depth to verify */ 161 static int p12_format = 0; /* Default to PEM format */ 162 163 164 /* prototypes for local functions */ 165 static int http_req(http_handle_t, const char *, http_req_t, offset_t, 166 offset_t); 167 static boolean_t http_check_conn(http_conn_t *); 168 static SSL_CTX *initialize_ctx(http_conn_t *); 169 static int tcp_connect(http_conn_t *, const char *, uint16_t); 170 static int readline(http_conn_t *, int, char *, int); 171 static int proxy_connect(http_conn_t *); 172 static int check_cert_chain(http_conn_t *, char *); 173 static void print_ciphers(SSL *); 174 static int read_headerlines(http_conn_t *, boolean_t); 175 static void free_response(http_conn_t *, int); 176 static int free_ctx_ssl(http_conn_t *); 177 static int get_chunk_header(http_conn_t *); 178 static int init_bread(http_conn_t *); 179 static int get_msgcnt(http_conn_t *, ssize_t *); 180 static int getaline(http_conn_t *, char *, int, boolean_t); 181 static int getbytes(http_conn_t *, char *, int); 182 static int http_srv_send(http_conn_t *, const void *, size_t); 183 static int http_srv_recv(http_conn_t *, void *, size_t); 184 static void handle_ssl_error(http_conn_t *, int); 185 static int count_digits(int); 186 static int hexdigit(char); 187 static char *eat_ws(const char *); 188 static boolean_t startswith(const char **strp, const char *starts); 189 190 /* ---------------------- public functions ----------------------- */ 191 192 /* 193 * http_set_p12_format - Set flag indicating that certs & keys will be in 194 * pkcs12 format. 195 * 196 * Default is PEM certs. When this is called, the default can be changed to 197 * pcs12 format. 198 */ 199 void 200 http_set_p12_format(int on_off) 201 { 202 p12_format = on_off; 203 } 204 205 /* 206 * http_get_version - Get current boot http support version 207 * 208 * pVer = http_get_version(); 209 * 210 * Arguments: 211 * None. 212 * 213 * Returns: 214 * Pointer to struct with version information. 215 * 216 * Returns the version of the http support in the current library. This 217 * is a struct with unsigned integsrs for <major>, <minor> and 218 * <micro> version numbers. <major> changes when an incompatible change 219 * is made. <minor> changes when an upwardly-compatible API change is 220 * made. <micro> consists of bug fixes, etc. 221 */ 222 boot_http_ver_t const * 223 http_get_version(void) 224 { 225 return (&boot_http_ver); 226 } 227 228 /* 229 * http_set_verbose - Turn verbose on/off 230 * 231 * http_set_verbose(on_off); 232 * 233 * Arguments: 234 * on_off - When TRUE, turn verbose mode one. When FALSE, turn 235 * verbose off. 236 * 237 * Returns: 238 * None. 239 * 240 * When enabled, information is logged to bootlog (or the Solaris equivalent). 241 */ 242 void 243 http_set_verbose(boolean_t on_off) 244 { 245 verbosemode = on_off; 246 } 247 248 /* 249 * http_set_cipher_list - Change the list of ciphers that can be used. 250 * 251 * ret = http_set_cipher_list(handle, list); 252 * 253 * Arguments: 254 * list - List of ciphers that can be used. 255 * 256 * Returns: 257 * 0 - Success 258 * -1 - An error occurred. Check http_get_lasterr(). 259 */ 260 int 261 http_set_cipher_list(const char *list) 262 { 263 early_err = 0; 264 265 if (list != NULL) { 266 list = strdup(list); 267 if (list == NULL) { 268 early_err = EHTTP_NOMEM; 269 return (-1); 270 } 271 } 272 273 free(cipher_list); 274 cipher_list = (char *)list; 275 return (0); 276 } 277 278 /* 279 * http_srv_init - Set up a structure for a connection. 280 * 281 * handle = http_srv_init(url); 282 * 283 * Arguments: 284 * url - the structure that contains the URI. 285 * 286 * Returns: 287 * != NULL - A handle for referring to this connection. 288 * == NULL - An error occurred. Get the exact error from 289 * http_get_lasterr(). 290 */ 291 http_handle_t 292 http_srv_init(const url_t *url) 293 { 294 http_conn_t *c_id; 295 296 early_err = 0; 297 if (url == NULL) { 298 early_err = EHTTP_BADARG; 299 return (NULL); 300 } 301 302 if ((c_id = malloc(sizeof (*c_id))) == NULL) { 303 early_err = EHTTP_NOMEM; 304 return (NULL); 305 } 306 307 bzero(c_id, sizeof (*c_id)); 308 c_id->uri = *url; 309 c_id->proxied = B_FALSE; 310 c_id->read_timeout = DEFAULT_TIMEOUT; 311 c_id->keepalive = B_TRUE; 312 c_id->fd = -1; 313 314 /* Do this at the end, just in case.... */ 315 c_id->signature = HTTP_CONN_INFO; 316 317 return (c_id); 318 } 319 320 /* 321 * http_conn_is_https - Determine whether the scheme is http or https. 322 * 323 * B_TRUE - Connection is an SSL connection. 324 * B_FALSE - Connection isn't SSL. 325 * 326 * ret = http_conn_is_https(handle, boolean_t *bool); 327 * 328 * Arguments: 329 * handle - Handle associated with the desired connection 330 * bool - Ptr to boolean in which to place result 331 * 332 * Returns: 333 * 0 - Success 334 * -1 - Some error occurred. 335 */ 336 int 337 http_conn_is_https(http_handle_t handle, boolean_t *bool) 338 { 339 http_conn_t *c_id = handle; 340 341 if (!http_check_conn(c_id)) 342 return (-1); 343 344 *bool = CONN_HTTPS; 345 return (0); 346 } 347 348 /* 349 * http_set_proxy - Establish the proxy name/port. 350 * 351 * ret = http_set_proxy(handle, proxy); 352 * 353 * Arguments: 354 * handle - Handle associated with the desired connection 355 * proxy - The hostport definition for the proxy. If NULL, 356 * The next connect will not use a proxy. 357 * 358 * Returns: 359 * 0 - Success 360 * -1 - An error occurred. Check http_get_lasterr(). 361 */ 362 int 363 http_set_proxy(http_handle_t handle, const url_hport_t *proxy) 364 { 365 http_conn_t *c_id = handle; 366 367 if (!http_check_conn(c_id)) 368 return (-1); 369 370 if (proxy != NULL) { 371 c_id->proxy = *proxy; 372 c_id->proxied = B_TRUE; 373 } else { 374 CONN_PROXY_HOSTNAME[0] = '\0'; 375 c_id->proxied = B_FALSE; 376 } 377 378 return (0); 379 } 380 381 /* 382 * http_set_keepalive - Set keepalive for this connection. 383 * 384 * http_set_keepalive(handle, on_off); 385 * 386 * Arguments: 387 * handle - Handle associated with the desired connection 388 * on_off - Boolean turning keepalive on (TRUE) or off (FALSE) 389 * 390 * Returns: 391 * 0 - Success. 392 * -1 - An error occurred. Check http_get_lasterr(). 393 * 394 * This setting takes effect next time a connection is opened using this 395 * handle. 396 */ 397 int 398 http_set_keepalive(http_handle_t handle, boolean_t on_off) 399 { 400 http_conn_t *c_id = handle; 401 402 if (!http_check_conn(c_id)) 403 return (-1); 404 405 c_id->keepalive = on_off; 406 return (0); 407 } 408 409 /* 410 * http_set_socket_read_timeout - Set the timeout reads 411 * 412 * http_set_socket_read_timeout(handle, timeout); 413 * 414 * Arguments: 415 * handle - Handle associated with the desired connection 416 * timeout - Timeout, in seconds. Zero will default to 10 second 417 * timeouts. 418 * 419 * Returns: 420 * 0 - Success. 421 * -1 - An error occurred. Check http_get_lasterr(). 422 * 423 * This setting takes effect beginning with the next read operation on this 424 * connection. 425 */ 426 int 427 http_set_socket_read_timeout(http_handle_t handle, uint_t timout) 428 { 429 http_conn_t *c_id = handle; 430 431 if (!http_check_conn(c_id)) 432 return (-1); 433 434 c_id->read_timeout = (timout) ? timout : DEFAULT_TIMEOUT; 435 return (0); 436 } 437 438 /* 439 * http_set_basic_auth - Set the basic authorization user ID and password 440 * 441 * ret = http_set_basic_auth(handle, userid, password); 442 * 443 * Arguments: 444 * handle - Handle associated with the desired connection 445 * userid - ID to pass as part of http/https request 446 * password- Password which goes with the user ID 447 * 448 * Returns: 449 * 0 - Success 450 * -1 - An error occurred. Check http_get_lasterr(). 451 * 452 * This must be set before a https connection is made. 453 */ 454 int 455 http_set_basic_auth(http_handle_t handle, const char *userid, 456 const char *password) 457 { 458 http_conn_t *c_id = handle; 459 460 if (!http_check_conn(c_id)) 461 return (-1); 462 463 if (password == NULL || userid == NULL || userid[0] == '\0') { 464 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 465 return (-1); 466 } 467 468 userid = strdup(userid); 469 password = strdup(password); 470 if (userid == NULL || password == NULL) { 471 free((void *)userid); 472 free((void *)password); 473 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 474 return (-1); 475 } 476 477 free(c_id->basic_auth_userid); 478 c_id->basic_auth_userid = (char *)userid; 479 free(c_id->basic_auth_password); 480 c_id->basic_auth_password = (char *)password; 481 return (0); 482 } 483 484 /* 485 * http_set_random_file - See the pseudo random number generator with file data 486 * 487 * ret = http_set_random_file(handle, filename); 488 * 489 * Arguments: 490 * handle - Handle associated with the desired connection 491 * filename 492 * - filename (including path) with random number seed. 493 * 494 * Returns: 495 * 0 - Success 496 * -1 - An error occurred. Check http_get_lasterr(). 497 * 498 * This must be set before a https connection is made. 499 */ 500 int 501 http_set_random_file(http_handle_t handle, const char *fname) 502 { 503 http_conn_t *c_id = handle; 504 505 if (!http_check_conn(c_id)) 506 return (-1); 507 508 if (fname != NULL) { 509 fname = strdup(fname); 510 if (fname == NULL) { 511 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 512 return (-1); 513 } 514 } 515 516 free(c_id->random_file); 517 c_id->random_file = (char *)fname; 518 return (0); 519 } 520 521 /* 522 * http_set_certificate_authority_file - Set the CA file. 523 * 524 * ret = http_set_certificate_authority_file(filename); 525 * 526 * Arguments: 527 * filename- File with the certificate authority certs 528 * 529 * Returns: 530 * 0 - Success 531 * -1 - An error occurred. Check http_get_lasterr(). 532 * 533 * This must be set before https connections to the servers is done. 534 */ 535 int 536 http_set_certificate_authority_file(const char *fname) 537 { 538 early_err = 0; 539 540 if (fname != NULL) { 541 fname = strdup(fname); 542 if (fname == NULL) { 543 early_err = EHTTP_NOMEM; 544 return (-1); 545 } 546 } 547 548 free(ca_verify_file); 549 ca_verify_file = (char *)fname; 550 return (0); 551 } 552 553 /* 554 * http_set_client_certificate_file - Set the file containing the PKCS#12 555 * client certificate and optionally its certificate chain. 556 * 557 * ret = http_set_client_certificate_file(handle, filename); 558 * 559 * Arguments: 560 * handle - Handle associated with the desired connection 561 * filename- File (including path) containing certificate, etc. 562 * 563 * Returns: 564 * 0 - Success 565 * -1 - An error occurred. Check http_get_lasterr(). 566 * 567 * This must be set before the handle is used to make a https connection 568 * which will require a client certificate. 569 */ 570 int 571 http_set_client_certificate_file(http_handle_t handle, const char *fname) 572 { 573 http_conn_t *c_id = handle; 574 575 if (!http_check_conn(c_id)) 576 return (-1); 577 578 if (fname != NULL) { 579 fname = strdup(fname); 580 if (fname == NULL) { 581 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 582 return (-1); 583 } 584 } 585 586 free(c_id->client_cert_file); 587 c_id->client_cert_file = (char *)fname; 588 return (0); 589 } 590 591 /* 592 * http_set_password - Set the password for the private key or pkcs12 file. 593 * 594 * ret = http_set_password(handle, password); 595 * 596 * Arguments: 597 * handle - Handle associated with the desired connection 598 * password- Password for the client's private key file or pkcs12 file. 599 * 600 * Returns: 601 * 0 - Success 602 * -1 - An error occurred. Check http_get_lasterr(). 603 * 604 * This must be set before the handle is used to make a https connection. 605 */ 606 int 607 http_set_password(http_handle_t handle, const char *password) 608 { 609 http_conn_t *c_id = handle; 610 611 if (!http_check_conn(c_id)) 612 return (-1); 613 614 if (password != NULL) { 615 password = strdup(password); 616 if (password == NULL) { 617 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 618 return (-1); 619 } 620 } 621 622 free(c_id->file_password); 623 c_id->file_password = (char *)password; 624 return (0); 625 } 626 627 /* 628 * http_set_key_file_password - Set the password for the private key 629 * file. 630 * 631 * ret = http_set_key_file_password(handle, password); 632 * 633 * Arguments: 634 * handle - Handle associated with the desired connection 635 * password- Password for the client's private key file. 636 * 637 * Returns: 638 * 0 - Success 639 * -1 - An error occurred. Check http_get_lasterr(). 640 * 641 * This must be set before the handle is used to make a https connection. 642 */ 643 int 644 http_set_key_file_password(http_handle_t handle, const char *password) 645 { 646 return (http_set_password(handle, password)); 647 } 648 649 /* 650 * http_set_private_key_file - Set the file containing the PKCS#12 651 * private key for this client. 652 * 653 * ret = http_set_private_key_file(handle, filename); 654 * 655 * Arguments: 656 * handle - Handle associated with the desired connection 657 * filename- File (including path) containing the private key. 658 * 659 * Returns: 660 * 0 - Success 661 * -1 - An error occurred. Check http_get_lasterr(). 662 * 663 * This must be set before the handle is used to make a https connection. 664 */ 665 int 666 http_set_private_key_file(http_handle_t handle, const char *fname) 667 { 668 http_conn_t *c_id = handle; 669 670 if (!http_check_conn(c_id)) 671 return (-1); 672 673 if (fname != NULL) { 674 fname = strdup(fname); 675 if (fname == NULL) { 676 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 677 return (-1); 678 } 679 } 680 681 free(c_id->private_key_file); 682 c_id->private_key_file = (char *)fname; 683 return (0); 684 } 685 686 /* 687 * http_srv_connect - Establish a connection to the server 688 * 689 * ret = http_srv_connect(handle); 690 * 691 * Arguments: 692 * handle - Handle associated with the desired connection 693 * 694 * Returns: 695 * 0 - Success 696 * -1 - An error occurred. Check http_get_lasterr() for specifics. 697 */ 698 int 699 http_srv_connect(http_handle_t handle) 700 { 701 http_conn_t *c_id = handle; 702 SSL_CTX *ctx = NULL; 703 int retval; 704 705 ERR_clear_error(); 706 if (!http_check_conn(c_id)) 707 return (-1); 708 709 if (CONN_HTTPS) { 710 /* Build our SSL context (this function sets any errors) */ 711 ctx = initialize_ctx(c_id); 712 if (ctx == NULL) { 713 libbootlog(BOOTLOG_CRIT, 714 "http_srv_connect: initialize_ctx returned NULL"); 715 return (-1); 716 } 717 } 718 719 /* Connect the TCP socket */ 720 if (c_id->proxied) { 721 c_id->fd = proxy_connect(c_id); 722 } else { 723 c_id->fd = tcp_connect(c_id, CONN_HOSTNAME, CONN_PORT); 724 } 725 726 if (c_id->fd < 0) { 727 if (ctx != NULL) 728 SSL_CTX_free(ctx); 729 libbootlog(BOOTLOG_CRIT, 730 "http_srv_connect: %s returned %d", 731 (c_id->proxied) ? "proxy_connect" : "tcp_connect", 732 c_id->fd); 733 return (-1); 734 } 735 736 if (CONN_HTTPS) { 737 /* Connect the SSL socket */ 738 if ((c_id->ssl = SSL_new(ctx)) == NULL) { 739 ulong_t err; 740 while ((err = ERR_get_error()) != 0) 741 SET_ERR(c_id, ERRSRC_LIBSSL, err); 742 libbootlog(BOOTLOG_CRIT, 743 "http_srv_connect: SSL_new returned " 744 "NULL"); 745 (void) free_ctx_ssl(c_id); 746 return (-1); 747 } 748 if (verbosemode) 749 print_ciphers(c_id->ssl); 750 751 /* Ensure automatic negotiations will do things right */ 752 SSL_set_connect_state(c_id->ssl); 753 754 if (SSL_set_fd(c_id->ssl, c_id->fd) == 0) { 755 ulong_t err; 756 while ((err = ERR_get_error()) != 0) 757 SET_ERR(c_id, ERRSRC_LIBSSL, err); 758 libbootlog(BOOTLOG_CRIT, 759 "http_srv_connect: SSL_set_fd returned 0"); 760 (void) free_ctx_ssl(c_id); 761 return (-1); 762 } 763 764 if ((retval = SSL_connect(c_id->ssl)) <= 0) { 765 handle_ssl_error(c_id, retval); 766 libbootlog(BOOTLOG_CRIT, 767 "http_srv_connect: SSL_connect"); 768 (void) free_ctx_ssl(c_id); 769 return (-1); 770 } 771 772 if (check_cert_chain(c_id, CONN_HOSTNAME) != 0) { 773 (void) free_ctx_ssl(c_id); 774 return (-1); 775 } 776 777 if (verbosemode) 778 print_ciphers(c_id->ssl); 779 } 780 781 return (0); 782 } 783 784 /* 785 * http_head_request - Issue http HEAD request 786 * 787 * ret = http_head_request(handle, abs_path); 788 * 789 * Arguments: 790 * handle - Handle associated with the desired connection 791 * abs_path- File name portion of the URI, beginning with a /. Query, 792 * segment, etc are allowed. 793 * 794 * Returns: 795 * 0 - Success 796 * -1 - An error occurred. Check http_get_lasterr(). 797 */ 798 int 799 http_head_request(http_handle_t handle, const char *abs_path) 800 { 801 return (http_req(handle, abs_path, HTTP_REQ_TYPE_HEAD, 0, 0)); 802 } 803 804 /* 805 * http_get_request - Issue http GET request without a range. 806 * 807 * ret = http_get_request(handle, abs_path); 808 * 809 * Arguments: 810 * handle - Handle associated with the desired connection 811 * abs_path- File name portion of the URI, beginning with a /. Query, 812 * segment, etc are allowed. 813 * 814 * Returns: 815 * 0 - Success 816 * -1 - An error occurred. Check http_get_lasterr(). 817 */ 818 int 819 http_get_request(http_handle_t handle, const char *abs_path) 820 { 821 return (http_req(handle, abs_path, HTTP_REQ_TYPE_GET, -1, 0)); 822 } 823 824 /* 825 * http_get_range_request - Issue http GET request using a range. 826 * 827 * ret = http_get_range_request(handle, abs_path, curpos, len); 828 * 829 * Arguments: 830 * handle - Handle associated with the desired connection 831 * abs_path- File name portion of the URI, beginning with a /. Query, 832 * segment, etc are allowed. 833 * curpos - >=0 - Beginning of range 834 * len - = 0 - Range ends at the end of the file 835 * > 0 - Length of range. 836 * 837 * Returns: 838 * 0 - Success 839 * -1 - An error occurred. Check http_get_lasterr(). 840 */ 841 int 842 http_get_range_request(http_handle_t handle, const char *abs_path, 843 offset_t curpos, offset_t len) 844 { 845 http_conn_t *c_id = handle; 846 847 if (!http_check_conn(c_id)) 848 return (-1); 849 850 if (curpos < 0) { 851 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 852 return (-1); 853 } 854 855 return (http_req(handle, abs_path, HTTP_REQ_TYPE_GET, curpos, len)); 856 } 857 858 /* 859 * http_free_respinfo - Free a respinfo structure 860 * 861 * ret = http_free_respinfo(resp); 862 * 863 * Arguments: 864 * resp - respinfo structure presumably allocated by 865 * http_process_headers() or http_process_part_headers() 866 * 867 * Note that if resp is NULL, then this results in a NOOP. 868 * 869 */ 870 void 871 http_free_respinfo(http_respinfo_t *resp) 872 { 873 if (resp == NULL) { 874 return; 875 } 876 877 if (resp->statusmsg != NULL) { 878 free(resp->statusmsg); 879 } 880 free(resp); 881 } 882 883 /* 884 * http_process_headers - Read in the header lines from the response 885 * 886 * ret = http_process_headers(handle, resp); 887 * 888 * Arguments: 889 * handle - Handle associated with the connection where the request 890 * was made. 891 * resp - Summary information about the response. 892 * 893 * Returns: 894 * 0 - Success 895 * < 0 - An error occurred. Specifics of the error can 896 * be gotten using http_get_lasterr(). 897 * 898 * Process the HTTP headers in the response. Check for a valid response 899 * status line. Allocate and return response information via the 'resp' 900 * argument. Header lines are stored locally, are are returned using calls 901 * to http_get_response_header() and http_get_header_value(). 902 * 903 * Note that the errors will be set in the http_conn_t struct before the 904 * function which detected the error returns. 905 * 906 * Note that if resp is non-NULL, then upon a successful return, information 907 * about the status line, the code in the status line and the number of 908 * header lines are returned in the http_respinfo_t structure. The caller is 909 * responsible for freeing the resources allocated to this structure via 910 * http_free_respinfo(). 911 * 912 * Note that the counters used to read message bodies are initialized here. 913 * 914 * Calling this function replaces the header information which is 915 * queried using http_get_response_header() and http_get_header_value(). 916 * Once this function is called, headers read by the previous call 917 * to http_process_headers() or http_process_part_headers() is lost. 918 */ 919 int 920 http_process_headers(http_handle_t handle, http_respinfo_t **resp) 921 { 922 http_conn_t *c_id = handle; 923 http_respinfo_t *lresp; 924 char line[MAXHOSTNAMELEN]; 925 char *ptr; 926 int i; 927 928 ERR_clear_error(); 929 if (!http_check_conn(c_id)) 930 return (-1); 931 932 if (resp != NULL) { 933 if ((lresp = malloc(sizeof (http_respinfo_t))) == NULL) { 934 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 935 return (-1); 936 } 937 938 bzero(lresp, sizeof (http_respinfo_t)); 939 } 940 941 /* 942 * check the response status line, expecting 943 * HTTP/1.1 200 OK 944 */ 945 i = getaline(c_id, line, sizeof (line), B_FALSE); 946 if (i == 0) { 947 if (resp != NULL) { 948 *resp = lresp; 949 } 950 return (0); 951 } 952 953 if (i < 0) { 954 /* 955 * Cause of I/O error was already put into 956 * error stack. This is an additional error. 957 */ 958 http_free_respinfo(lresp); 959 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NODATA); 960 return (-1); 961 } 962 963 free_response(c_id, B_TRUE); 964 965 if (verbosemode) 966 libbootlog(BOOTLOG_VERBOSE, "http_process_headers: %s", line); 967 968 ptr = line; 969 if (strncmp(ptr, "HTTP/1.1", 8) != 0) { 970 http_free_respinfo(lresp); 971 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOT_1_1); 972 return (-1); 973 } 974 975 /* skip to the code */ 976 ptr += 8; 977 while (isspace(*ptr)) 978 ptr++; 979 980 /* make sure it's three digits */ 981 i = 0; 982 while (isdigit(ptr[i])) 983 i++; 984 if (i != 3) { 985 http_free_respinfo(lresp); 986 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADHDR); 987 return (-1); 988 } 989 c_id->resp.code = strtol(ptr, NULL, 10); 990 991 /* skip to the message */ 992 ptr += 3; 993 while (isspace(*ptr)) 994 ptr++; 995 996 /* save the message */ 997 c_id->resp.statusmsg = malloc(strlen(ptr) + 1); 998 if (c_id->resp.statusmsg == NULL) { 999 http_free_respinfo(lresp); 1000 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1001 return (-1); 1002 } 1003 (void) strcpy(c_id->resp.statusmsg, ptr); 1004 1005 if ((i = read_headerlines(c_id, B_FALSE)) < 0) { 1006 /* 1007 * Error stack was already set at a lower level. 1008 * 'statusmsg' will be cleaned up next time 1009 * headers are read. 1010 */ 1011 http_free_respinfo(lresp); 1012 return (-1); 1013 } 1014 1015 /* 1016 * See if there is a 'content-type: multipart/mixed' line in the 1017 * headers. If so, get the boundary string. 1018 */ 1019 ptr = http_get_header_value(handle, "Content-Type"); 1020 if (ptr != NULL) { 1021 char *ptr2; 1022 1023 ptr2 = ptr; 1024 while (isspace(*ptr2)) 1025 ptr2 ++; 1026 if (startswith((const char **)&ptr2, "Multipart/Mixed;")) { 1027 while (isspace(*ptr2)) 1028 ptr2 ++; 1029 if (startswith((const char **)&ptr2, "Boundary=")) { 1030 if (ptr2[0] == '"') { 1031 ptr2 ++; 1032 if (ptr2[strlen(ptr2) - 1] == '"') 1033 ptr2[strlen(ptr2) - 1] = '\0'; 1034 } 1035 c_id->boundary = strdup(ptr2); 1036 if (c_id->boundary == NULL) { 1037 free(ptr); 1038 http_free_respinfo(lresp); 1039 SET_ERR(c_id, ERRSRC_LIBHTTP, 1040 EHTTP_NOMEM); 1041 return (-1); 1042 } 1043 c_id->boundary_len = strlen(c_id->boundary); 1044 c_id->is_multipart = B_TRUE; 1045 c_id->is_firstpart = B_TRUE; 1046 } 1047 } 1048 free(ptr); 1049 } 1050 1051 /* 1052 * Initialize the counters used to process message bodies. 1053 */ 1054 if (init_bread(c_id) != 0) { 1055 /* 1056 * Error stack was already set at a lower level. 1057 */ 1058 http_free_respinfo(lresp); 1059 return (-1); 1060 } 1061 1062 /* Copy fields to the caller's structure */ 1063 if (resp != NULL) { 1064 lresp->code = c_id->resp.code; 1065 lresp->nresphdrs = c_id->resp.nresphdrs; 1066 lresp->statusmsg = strdup(c_id->resp.statusmsg); 1067 if (lresp->statusmsg == NULL) { 1068 http_free_respinfo(lresp); 1069 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1070 return (-1); 1071 } 1072 *resp = lresp; 1073 } 1074 1075 return (0); 1076 } 1077 1078 /* 1079 * http_process_part_headers - Read in part boundary and header lines for the 1080 * next part of a multipart message. 1081 * 1082 * ret = http_process_part_headers(handle, resp); 1083 * 1084 * Arguments: 1085 * handle - Handle associated with the connection where the request 1086 * was made. 1087 * resp - Return address for summary information about the 1088 * header block. 1089 * 1090 * Returns: 1091 * = 1 - The end part was found. 1092 * = 0 - Success, with header info returned in 'resp' 1093 * = -1 - An error occurred. Specifics of the error can 1094 * be gotten using http_get_lasterr(). 1095 * 1096 * This function reads any \r\n sequences (empty lines) and expects to get 1097 * a boundary line as the next non-empty line. It then reads header lines 1098 * (content-length, etc) until it gets another empty lines, which ends the 1099 * header section. 1100 * 1101 * Note that if resp is non-NULL, then upon a successful return, information 1102 * about the the number of header lines is returned in the http_respinfo_t 1103 * structure. The caller is responsible for freeing the resources allocated 1104 * to this structure via http_free_respinfo(). 1105 * 1106 * Headers values can be returned using http_get_response_header() and 1107 * http_get_header_value(). 1108 * 1109 * Calling this function replaces the header information which is 1110 * queried using http_get_response_header() and http_get_header_value(). 1111 * Once this function is called, information returned by the previous call 1112 * to http_process_headers() or http_process_part_headers() is gone. 1113 */ 1114 int 1115 http_process_part_headers(http_handle_t handle, http_respinfo_t **resp) 1116 { 1117 http_conn_t *c_id = handle; 1118 char line[MAXHOSTNAMELEN]; 1119 int count; 1120 int limit; 1121 int i; 1122 1123 ERR_clear_error(); 1124 if (!http_check_conn(c_id)) 1125 return (-1); 1126 1127 if (c_id->is_multipart == 0) { 1128 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOTMULTI); 1129 return (-1); 1130 } 1131 1132 /* 1133 * Figure out how many empty lines to allow. Before the first 1134 * boundary of the transmission, there can be any number of 1135 * empty lines (from 0 up). Limit these to some reasonable 1136 * failsafe. 1137 * 1138 * For the 2nd and later boundaries, there is supposed to be 1139 * one crlf pair. However, many implementations don't require 1140 * it. So don't require it. 1141 */ 1142 if (c_id->is_firstpart) { 1143 limit = FAILSAFE; 1144 c_id->is_firstpart = B_FALSE; 1145 } else 1146 limit = 1; 1147 1148 /* Look for the boundary line. */ 1149 count = 0; 1150 while ((i = getaline(c_id, line, sizeof (line), B_TRUE)) == 0 && 1151 count < FAILSAFE) 1152 count ++; 1153 if (i < 0 || count > limit) { 1154 /* 1155 * If I/O error, cause was already put into 1156 * error stack. This is an additional error. 1157 */ 1158 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOBOUNDARY); 1159 return (-1); 1160 } 1161 1162 free_response(c_id, B_FALSE); 1163 1164 if (verbosemode) 1165 libbootlog(BOOTLOG_VERBOSE, 1166 "http_process_part_headers: %s", line); 1167 1168 /* Look for boundary line - '--<boundary text> */ 1169 if (line[0] != '-' || line[1] != '-' || 1170 strncmp(&line[2], c_id->boundary, c_id->boundary_len) != 0) { 1171 /* No boundary line.... */ 1172 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOBOUNDARY); 1173 return (-1); 1174 } 1175 1176 /* Is this the end-of-parts boundary (ends with a trailing '--') */ 1177 if (strcmp(&line[c_id->boundary_len + 2], "--") == 0) { 1178 return (1); 1179 } 1180 1181 free_response(c_id, B_FALSE); 1182 if (read_headerlines(c_id, B_TRUE) < 0) { 1183 /* Error stack was already set at a lower level. */ 1184 return (-1); 1185 } 1186 1187 /* Copy fields to the caller's structure */ 1188 if (resp != NULL) { 1189 if ((*resp = malloc(sizeof (http_respinfo_t))) == NULL) { 1190 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1191 return (-1); 1192 } 1193 bzero(*resp, sizeof (http_respinfo_t)); 1194 (*resp)->code = ' '; 1195 (*resp)->nresphdrs = c_id->resp.nresphdrs; 1196 } 1197 1198 return (0); 1199 } 1200 1201 /* 1202 * http_get_response_header - Get a line from the response header 1203 * 1204 * ret = http_get_response_header(handle, whichline); 1205 * 1206 * Arguments: 1207 * handle - Handle associated with the desired connection 1208 * whichline - Which line of the header to return. This must be between 1209 * zero and resp.nresphdrs which was returned by the call to 1210 * http_process_headers(). 1211 * 1212 * Returns: 1213 * ptr - Points to a copy of the header line. 1214 * NULL - An error occurred. Check http_get_lasterr(). 1215 */ 1216 char * 1217 http_get_response_header(http_handle_t handle, uint_t which) 1218 { 1219 http_conn_t *c_id = handle; 1220 char *res; 1221 1222 if (!http_check_conn(c_id)) 1223 return (NULL); 1224 1225 if (which >= c_id->resp.nresphdrs) { 1226 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_OORANGE); 1227 return (NULL); 1228 } 1229 1230 res = strdup(c_id->resphdr[which]); 1231 if (res == NULL) { 1232 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1233 return (NULL); 1234 } 1235 return (res); 1236 } 1237 1238 /* 1239 * http_get_header_value - Get the value of a header line. 1240 * 1241 * ret = http_get_header_value(handle, what); 1242 * 1243 * Arguments: 1244 * handle - Handle associated with the desired connection 1245 * what - The field name to look up. 1246 * 1247 * Returns: 1248 * ptr - Points to a copy of the header value. 1249 * NULL - An error occurred. Check http_get_lasterr(). 1250 */ 1251 char * 1252 http_get_header_value(http_handle_t handle, const char *field_name) 1253 { 1254 http_conn_t *c_id = handle; 1255 char *ptr; 1256 char *res; 1257 int i; 1258 int n; 1259 1260 if (!http_check_conn(c_id)) 1261 return (NULL); 1262 1263 if (field_name == NULL || field_name[0] == '\0') { 1264 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1265 return (NULL); 1266 } 1267 1268 for (i = 0; i < c_id->resp.nresphdrs; i++) { 1269 ptr = c_id->resphdr[i]; 1270 n = strlen(field_name); 1271 if (strncasecmp(field_name, ptr, n) == 0 && ptr[n] == ':') { 1272 ptr += n + 1; 1273 1274 while (isspace(*ptr)) 1275 ptr++; 1276 1277 res = strdup(ptr); 1278 if (res == NULL) { 1279 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1280 return (NULL); 1281 } 1282 return (res); 1283 } 1284 } 1285 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMATCH); 1286 return (NULL); 1287 } 1288 1289 /* 1290 * http_read_body - Read the HTTP response body. 1291 * 1292 * ret = http_read_body(handle, recv_buf_ptr, recv_buf_size); 1293 * 1294 * Arguments: 1295 * handle - Handle associated with the relevant connection 1296 * recv_buf_ptr - Points to buffer to receive buffer 1297 * recv_buf_size - Length in bytes of buffer. 1298 * 1299 * Returns: 1300 * n - Number of bytes read.. 1301 * < 0 - An error occurred. This is (the number of bytes gotten + 1), 1302 * negated. In other words, if 'n' bytes were read and then an 1303 * error occurred, this will return (-(n+1)). So zero bytes 1304 * were read and then an error occurs, this will return -1. If 1305 * 1 byte was read, it will return -2, etc. Specifics of the 1306 * error can be gotten using http_get_lasterr(). 1307 * 1308 * Note that the errors will be set in the http_conn_t struct before the 1309 * function which detected the error returns. 1310 */ 1311 int 1312 http_read_body(http_handle_t handle, char *recv_buf_ptr, size_t recv_buf_size) 1313 { 1314 http_conn_t *c_id = handle; 1315 1316 ERR_clear_error(); 1317 if (!http_check_conn(c_id)) 1318 return (-1); 1319 1320 if (recv_buf_ptr == NULL || recv_buf_size == 0) { 1321 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1322 return (-1); 1323 } 1324 1325 return (getbytes(c_id, recv_buf_ptr, recv_buf_size)); 1326 } 1327 1328 /* 1329 * http_srv_disconnect - Get rid of the connection to the server without 1330 * freeing the http_conn_t structure. 1331 * 1332 * ret = http_srv_disconnect(handle); 1333 * 1334 * Arguments: 1335 * handle - Handle associated with the connection 1336 * 1337 * Returns: 1338 * 0 - Success 1339 * -1 - An error occurred. Specifics of the error can 1340 * be gotten using http_get_lasterr(). 1341 */ 1342 int 1343 http_srv_disconnect(http_handle_t handle) 1344 { 1345 http_conn_t *c_id = handle; 1346 int err_ret; 1347 1348 ERR_clear_error(); 1349 if (!http_check_conn(c_id)) 1350 return (-1); 1351 1352 err_ret = free_ctx_ssl(c_id); 1353 bzero(&c_id->inbuf, sizeof (c_id->inbuf)); 1354 free_response(c_id, B_TRUE); 1355 1356 return (err_ret); 1357 } 1358 1359 /* 1360 * http_srv_close - Close the connection and clean up the http_conn_t 1361 * structure. 1362 * 1363 * http_srv_close(handle); 1364 * 1365 * Arguments: 1366 * handle - Handle associated with the desired connection 1367 * 1368 * Returns: 1369 * 0 - Success 1370 * -1 - An error occurred. Specifics of the error can 1371 * be gotten using http_get_lasterr(). 1372 */ 1373 int 1374 http_srv_close(http_handle_t handle) 1375 { 1376 http_conn_t *c_id = handle; 1377 int err_ret = 0; 1378 1379 if (!http_check_conn(c_id)) 1380 return (-1); 1381 1382 if (c_id->ctx != NULL || c_id->ssl != NULL || c_id->fd != -1) 1383 err_ret = http_srv_disconnect(handle); 1384 1385 free(c_id->basic_auth_userid); 1386 free(c_id->basic_auth_password); 1387 free(c_id->resp.statusmsg); 1388 free(c_id->client_cert_file); 1389 free(c_id->private_key_file); 1390 free(c_id->random_file); 1391 free(c_id->file_password); 1392 c_id->signature = 0; 1393 1394 free(c_id); 1395 return (err_ret); 1396 } 1397 1398 /* 1399 * http_get_conn_info - Return current information about the connection 1400 * 1401 * err = http_get_conn_info(handle); 1402 * 1403 * Arguments: 1404 * handle - Handle associated with the connection in question 1405 * 1406 * Returns: 1407 * non_NULL- Points to structure 1408 * NULL - An error exists. Check http_get_lasterr(). 1409 */ 1410 http_conninfo_t * 1411 http_get_conn_info(http_handle_t handle) 1412 { 1413 http_conn_t *c_id = handle; 1414 http_conninfo_t *info; 1415 1416 if (!http_check_conn(c_id)) 1417 return (NULL); 1418 1419 info = malloc(sizeof (*info)); 1420 if (info == NULL) { 1421 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1422 return (NULL); 1423 } 1424 1425 bzero(info, sizeof (*info)); 1426 1427 info->uri = c_id->uri; 1428 info->proxy = c_id->proxy; 1429 info->keepalive = c_id->keepalive; 1430 info->read_timeout = c_id->read_timeout; 1431 1432 return (info); 1433 } 1434 1435 /* 1436 * http_get_lasterr - Return the next error on the last operation 1437 * 1438 * err = http_get_lasterr(handle, errsrc); 1439 * 1440 * Arguments: 1441 * handle - Handle associated with the connection in question 1442 * If no valid handle exists yet, this can be NULL. 1443 * However, it must be checked with the very next call. 1444 * errsrc - Returns the Sources of errors (ERRSRC_* values). 1445 * 1446 * Returns: 1447 * 0 - No error exists 1448 * <> 0 - The error. 1449 */ 1450 ulong_t 1451 http_get_lasterr(http_handle_t handle, uint_t *errsrc) 1452 { 1453 http_conn_t *c_id = handle; 1454 ulong_t src; 1455 ulong_t err; 1456 1457 if (c_id == NULL || c_id->signature != HTTP_CONN_INFO) { 1458 if (errsrc) 1459 *errsrc = ERRSRC_LIBHTTP; 1460 err = early_err; 1461 early_err = 0; 1462 return (err); 1463 } 1464 1465 GET_ERR(c_id, src, err); 1466 if (src == 0 && err == 0) { 1467 if (errsrc) 1468 *errsrc = ERRSRC_LIBHTTP; 1469 err = early_err; 1470 early_err = 0; 1471 return (err); 1472 } 1473 if (errsrc) 1474 *errsrc = src; 1475 return (err); 1476 } 1477 1478 /* 1479 * http_decode_err - Decode a libssl error 1480 * 1481 * err = http_decode_err(err, errlib, errfunc, errcode); 1482 * 1483 * Arguments: 1484 * err - libssl/libcrypto error returned. 1485 * errlib - returns libssl/libcrypto sublibrary that caused the error 1486 * errfunc - returns function in that library 1487 * errcode - returns error code 1488 * 1489 * Returns: 1490 * None other than the above. 1491 */ 1492 void 1493 http_decode_err(ulong_t err, int *errlib, int *errfunc, int *errcode) 1494 { 1495 if (errlib) 1496 *errlib = ERR_GET_LIB(err); 1497 if (errfunc) 1498 *errfunc = ERR_GET_FUNC(err); 1499 if (errcode) 1500 *errcode = ERR_GET_REASON(err); 1501 } 1502 1503 /* ---------------------- private functions ----------------------- */ 1504 1505 /* 1506 * http_req - Issue http request (either HEAD or GET) 1507 * 1508 * ret = http_req(handle, abs_path, reqtype, curpos, len); 1509 * 1510 * Arguments: 1511 * handle - Handle associated with the desired connection 1512 * abs_path- File name portion of the URI, beginning with a /. Query, 1513 * segment, etc are allowed. 1514 * type - HTTP_REQ_TYPE_HEAD or HTTP_REQ_TYPE_GET 1515 * 1516 * In the case of GET requests, 1517 * curpos- -1 - Range not used 1518 * >=0 - Beginning of range 1519 * len - 0 - Range ends at the end of the file 1520 * >0 - Length of range. 1521 * 1522 * Returns: 1523 * 0 - Success 1524 * -1 - An error occurred. Check http_get_lasterr(). 1525 */ 1526 static int 1527 http_req(http_handle_t handle, const char *abs_path, http_req_t type, 1528 offset_t curpos, offset_t len) 1529 { 1530 http_conn_t *c_id = handle; 1531 char *request; 1532 char *reqtypename; 1533 char *newreq; 1534 int requestlen; 1535 int retval; 1536 int j; 1537 1538 ERR_clear_error(); 1539 if (!http_check_conn(c_id)) 1540 return (-1); 1541 1542 if (abs_path == NULL || abs_path[0] == '\0') { 1543 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1544 return (-1); 1545 } 1546 1547 /* Determine the name for the request type */ 1548 switch (type) { 1549 case HTTP_REQ_TYPE_GET: 1550 reqtypename = "GET"; 1551 if (curpos < 0 && curpos != -1) { 1552 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1553 return (-1); 1554 } 1555 break; 1556 1557 case HTTP_REQ_TYPE_HEAD: 1558 reqtypename = "HEAD"; 1559 break; 1560 1561 default: 1562 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1563 return (-1); 1564 } 1565 1566 /* Do rudimentary checks on the absolute path */ 1567 if (abs_path == NULL || *abs_path != '/') { 1568 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADARG); 1569 libbootlog(BOOTLOG_CRIT, "http_req: invalid file path"); 1570 if (abs_path != NULL) 1571 libbootlog(BOOTLOG_CRIT, " %s", abs_path); 1572 return (-1); 1573 } 1574 (void) strlcpy(CONN_ABSPATH, abs_path, MAXHOSTNAMELEN); 1575 1576 /* 1577 * Size the request. 1578 * 1579 * With proxy: 1580 * reqtypename + " http://" + host + ":" + port + path + 1581 * " HTTP/1.1\r\n" + 1582 * Without proxy: 1583 * reqtypename + " " + path + " HTTP/1.1\r\n" + 1584 */ 1585 requestlen = strlen(reqtypename) + 8 + strlen(CONN_HOSTNAME) + 1 + 1586 count_digits(CONN_PORT) + strlen(CONN_ABSPATH) + 11; 1587 1588 /* 1589 * Plus the rest: 1590 * "Host: " + targethost + ":" + count_digits(port) + "\r\n" + 1591 * "Connection: Keep-Alive\r\n" plus trailing "\r\n\0" 1592 */ 1593 requestlen += 6 + strlen(CONN_HOSTNAME) + 1 + 1594 count_digits(CONN_PORT) + 2 + 24 + 3; 1595 if ((request = malloc(requestlen)) == NULL) { 1596 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1597 return (-1); 1598 } 1599 1600 /* The request line */ 1601 if (c_id->proxied && c_id->ssl == NULL) { 1602 j = snprintf(request, requestlen, 1603 "%s http://%s:%d%s HTTP/1.1\r\n", 1604 reqtypename, CONN_HOSTNAME, CONN_PORT, 1605 CONN_ABSPATH); 1606 } else { 1607 j = snprintf(request, requestlen, "%s %s HTTP/1.1\r\n", 1608 reqtypename, CONN_ABSPATH); 1609 } 1610 1611 /* Ancillary headers */ 1612 j += snprintf(&request[j], requestlen - j, "Host: %s:%d\r\n", 1613 CONN_HOSTNAME, CONN_PORT); 1614 if (!c_id->keepalive) 1615 j += snprintf(&request[j], requestlen - j, 1616 "Connection: close\r\n"); 1617 else 1618 j += snprintf(&request[j], requestlen - j, 1619 "Connection: Keep-Alive\r\n"); 1620 /* 1621 * We only send the range header on GET requests 1622 * 1623 * "Range: bytes=" + from + "-" + end + "\r\n" or 1624 * "Range: bytes=" + from + "-" "\r\n" 1625 */ 1626 if (type == HTTP_REQ_TYPE_GET && curpos >= 0) { 1627 offset_t endpos; 1628 1629 requestlen += 13 + count_digits(curpos) + 1 + 2; 1630 if (len > 0) { 1631 endpos = curpos + len - 1; 1632 requestlen += count_digits(endpos); 1633 } 1634 1635 if ((newreq = realloc(request, requestlen)) == NULL) { 1636 free(request); 1637 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1638 return (-1); 1639 } 1640 request = newreq; 1641 1642 j += sprintf(&request[j], "Range: bytes=%lld-", curpos); 1643 if (len > 0) 1644 j += sprintf(&request[j], "%lld", endpos); 1645 j += sprintf(&request[j], "\r\n"); 1646 } 1647 1648 /* 1649 * Authorization is added only if provided (RFC 2617, Section 2) 1650 * 1651 * "Authorization: Basic " + authencstr + "\r\n" 1652 */ 1653 if (c_id->basic_auth_userid && c_id->basic_auth_password) { 1654 char *authstr; 1655 char *authencstr; 1656 int authlen; 1657 1658 /* 1659 * Allow for concat(basic_auth_userid ":" basic_auth_password) 1660 */ 1661 authlen = strlen(c_id->basic_auth_userid) + 2 + 1662 strlen(c_id->basic_auth_password); 1663 if ((authstr = malloc(authlen + 1)) == NULL) { 1664 free(request); 1665 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1666 return (-1); 1667 } 1668 (void) snprintf(authstr, authlen + 1, "%s:%s", 1669 c_id->basic_auth_userid, c_id->basic_auth_password); 1670 1671 /* 3 bytes encoded as 4 (round up) with null termination */ 1672 if ((authencstr = malloc((authlen + 2) / 3 * 4 + 1)) == NULL) { 1673 free(authstr); 1674 free(request); 1675 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1676 return (-1); 1677 } 1678 1679 (void) EVP_EncodeBlock((unsigned char *)authencstr, 1680 (unsigned char *)authstr, authlen); 1681 1682 /* 1683 * Finally do concat(Authorization: Basic " authencstr "\r\n") 1684 */ 1685 requestlen += 21 + strlen(authencstr) + 2; 1686 if ((newreq = realloc(request, requestlen)) == NULL) { 1687 free(authencstr); 1688 free(authstr); 1689 free(request); 1690 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 1691 return (-1); 1692 } 1693 request = newreq; 1694 1695 j += snprintf(&request[j], requestlen - j, 1696 "Authorization: Basic %s\r\n", authencstr); 1697 1698 free(authencstr); 1699 free(authstr); 1700 } 1701 1702 j += sprintf(&request[j], "\r\n"); 1703 1704 if (verbosemode) 1705 libbootlog(BOOTLOG_VERBOSE, "%s", request); 1706 1707 /* send the HTTP request */ 1708 retval = http_srv_send(c_id, request, j); 1709 1710 free(request); 1711 if (retval != j) { 1712 /* Assume error in was set by send request. */ 1713 return (-1); 1714 } 1715 1716 return (0); 1717 } 1718 1719 /* 1720 * password_cb - Callback to get private key password and return it 1721 * to SSL. (Used for PEM certificates only.) 1722 * 1723 * len = passwd_cb(buf, buflen, rwflag, userdata); 1724 * 1725 * Arguments: 1726 * buf - Buffer for the password 1727 * buflen - Length of 'buf' 1728 * rwflag - password will be used for reading/decryption (== 0) 1729 * or writing/encryption (== 1). 1730 * userdata - Points to connection-specific information. 1731 * 1732 * Returns: 1733 * > 0 - Length of password that was put into 'buf'. 1734 * 0 - No password was returned (usually error occurred) 1735 * 1736 * NOTE: The password code is not thread safe 1737 */ 1738 /* ARGSUSED */ 1739 static int 1740 password_cb(char *buf, int buflen, int rwflag, void *userdata) 1741 { 1742 http_conn_t *c_id = userdata; 1743 1744 if (c_id == NULL || c_id->signature != HTTP_CONN_INFO) 1745 return (0); 1746 1747 if (c_id->file_password == NULL || 1748 buflen < strlen(c_id->file_password) + 1) 1749 return (0); 1750 1751 return (strlcpy(buf, c_id->file_password, buflen)); 1752 } 1753 1754 /* 1755 * initialize_ctx - Initialize the context for a connection. 1756 * 1757 * ctx = initialize_ctx(c_id); 1758 * 1759 * Arguments: 1760 * None. 1761 * 1762 * Returns: 1763 * non-NULL - Points to ctx structure. 1764 * NULL - An error occurred. Any cleanup is done and error 1765 * information is in the error stack. 1766 */ 1767 static SSL_CTX * 1768 initialize_ctx(http_conn_t *c_id) 1769 { 1770 SSL_METHOD *meth; 1771 SSL_CTX *ctx; 1772 1773 ERR_clear_error(); 1774 1775 /* Global system initialization */ 1776 if (ssl_init == 0) { 1777 sunw_crypto_init(); 1778 SSL_load_error_strings(); 1779 ssl_init = 1; 1780 } 1781 1782 /* Create our context */ 1783 meth = SSLv3_client_method(); 1784 if ((ctx = SSL_CTX_new(meth)) == NULL) { 1785 ulong_t err; 1786 while ((err = ERR_get_error()) != 0) 1787 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1788 libbootlog(BOOTLOG_CRIT, 1789 "initialize_ctx: SSL_CTX_new returned NULL"); 1790 return (NULL); 1791 } 1792 1793 /* 1794 * Ensure that any renegotiations for blocking connections will 1795 * be done automatically. (The alternative is to return partial 1796 * reads to the caller and let it oversee the renegotiations.) 1797 */ 1798 if (SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY) == 0) { 1799 ulong_t err; 1800 while ((err = ERR_get_error()) != 0) 1801 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1802 libbootlog(BOOTLOG_CRIT, 1803 "initialize_ctx: SSL_CTX_set_mode returned 0"); 1804 (void) SSL_CTX_free(ctx); 1805 return (NULL); 1806 } 1807 1808 /* set cipher list if provided */ 1809 if (cipher_list != NULL) { 1810 if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { 1811 ulong_t err; 1812 while ((err = ERR_get_error()) != 0) 1813 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1814 libbootlog(BOOTLOG_CRIT, 1815 "initialize_ctx: Error in cipher list"); 1816 SSL_CTX_free(ctx); 1817 return (NULL); 1818 } 1819 } 1820 1821 /* 1822 * We attempt to use the client_certificate_file for the private 1823 * key input scheme *only* in the absence of private_key_file. In 1824 * this instance the scheme will be the same as that used for the 1825 * certificate input. 1826 */ 1827 1828 /* Load our certificates */ 1829 if (c_id->client_cert_file != NULL) { 1830 if (p12_format) { 1831 /* Load pkcs12-formated files */ 1832 if (sunw_p12_use_certfile(ctx, c_id->client_cert_file, 1833 c_id->file_password) 1834 <= 0) { 1835 ulong_t err; 1836 while ((err = ERR_get_error()) != 0) 1837 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1838 libbootlog(BOOTLOG_CRIT, 1839 "initialize_ctx: Couldn't read " 1840 "PKCS12 certificate file"); 1841 SSL_CTX_free(ctx); 1842 return (NULL); 1843 } 1844 } else { 1845 /* Load PEM-formated files */ 1846 if (SSL_CTX_use_certificate_file(ctx, 1847 c_id->client_cert_file, SSL_FILETYPE_PEM) <= 0) { 1848 ulong_t err; 1849 while ((err = ERR_get_error()) != 0) 1850 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1851 libbootlog(BOOTLOG_CRIT, 1852 "initialize_ctx: Couldn't read " 1853 "PEM certificate file"); 1854 SSL_CTX_free(ctx); 1855 return (NULL); 1856 } 1857 } 1858 if (c_id->private_key_file == NULL) 1859 c_id->private_key_file = c_id->client_cert_file; 1860 } 1861 1862 /* Load our keys */ 1863 if (p12_format) { 1864 /* Load pkcs12-formated files */ 1865 if (c_id->private_key_file != NULL) { 1866 if (sunw_p12_use_keyfile(ctx, c_id->private_key_file, 1867 c_id->file_password) 1868 <= 0) { 1869 ulong_t err; 1870 while ((err = ERR_get_error()) != 0) 1871 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1872 libbootlog(BOOTLOG_CRIT, 1873 "initialize_ctx: Couldn't read " 1874 "PKCS12 key file"); 1875 SSL_CTX_free(ctx); 1876 return (NULL); 1877 } 1878 } 1879 } else { 1880 /* Load PEM-formated files */ 1881 SSL_CTX_set_default_passwd_cb(ctx, password_cb); 1882 SSL_CTX_set_default_passwd_cb_userdata(ctx, c_id); 1883 if (c_id->private_key_file != NULL) { 1884 if (SSL_CTX_use_PrivateKey_file(ctx, 1885 c_id->private_key_file, SSL_FILETYPE_PEM) <= 0) { 1886 ulong_t err; 1887 while ((err = ERR_get_error()) != 0) 1888 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1889 libbootlog(BOOTLOG_CRIT, 1890 "initialize_ctx: Couldn't read " 1891 "PEM key file"); 1892 SSL_CTX_free(ctx); 1893 return (NULL); 1894 } 1895 } 1896 } 1897 1898 /* Load the CAs we trust */ 1899 if (ca_verify_file != NULL) { 1900 if (p12_format) { 1901 if (sunw_p12_use_trustfile(ctx, ca_verify_file, 1902 c_id->file_password) 1903 <= 0) { 1904 ulong_t err; 1905 while ((err = ERR_get_error()) != 0) 1906 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1907 libbootlog(BOOTLOG_CRIT, 1908 "initialize_ctx: Couldn't read " 1909 "PKCS12 CA list file"); 1910 SSL_CTX_free(ctx); 1911 return (NULL); 1912 } 1913 } else { 1914 if (SSL_CTX_load_verify_locations(ctx, ca_verify_file, 1915 NULL) == 0) { 1916 ulong_t err; 1917 while ((err = ERR_get_error()) != 0) 1918 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1919 libbootlog(BOOTLOG_CRIT, 1920 "initialize_ctx: Couldn't read PEM" 1921 " CA list file"); 1922 SSL_CTX_free(ctx); 1923 return (NULL); 1924 } 1925 } 1926 } 1927 1928 SSL_CTX_set_verify_depth(ctx, verify_depth); 1929 1930 /* Load randomness */ 1931 if (c_id->random_file != NULL && 1932 RAND_load_file(c_id->random_file, 1024 * 1024) <= 0) { 1933 ulong_t err; 1934 while ((err = ERR_get_error()) != 0) 1935 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1936 libbootlog(BOOTLOG_CRIT, 1937 "initialize_ctx: Couldn't load random file"); 1938 SSL_CTX_free(ctx); 1939 return (NULL); 1940 } 1941 if (RAND_status() <= 0) { 1942 ulong_t err; 1943 while ((err = ERR_get_error()) != 0) 1944 SET_ERR(c_id, ERRSRC_LIBSSL, err); 1945 libbootlog(BOOTLOG_CRIT, 1946 "initialize_ctx: PRNG not seeded"); 1947 SSL_CTX_free(ctx); 1948 return (NULL); 1949 } 1950 1951 return (ctx); 1952 } 1953 1954 /* 1955 * tcp_connect - Set up a TCP connection. 1956 * 1957 * sock = tcp_connect(c_id, hostname, port); 1958 * 1959 * Arguments: 1960 * c_id - Structure associated with the desired connection 1961 * hostname - the host to connect to 1962 * port - the port to connect to 1963 * 1964 * Returns: 1965 * >= 0 - Socket number. 1966 * -1 - Error occurred. Error information is set in the 1967 * error stack. Any cleanup is done. 1968 * 1969 * This function established a connection to the target host. When 1970 * it returns, the connection is ready for a HEAD or GET request. 1971 */ 1972 static int 1973 tcp_connect(http_conn_t *c_id, const char *hostname, uint16_t port) 1974 { 1975 struct hostent *hp; 1976 struct sockaddr_in addr; 1977 int sock; 1978 int status; 1979 1980 if ((hp = gethostbyname(hostname)) == NULL) { 1981 SET_ERR(c_id, ERRSRC_RESOLVE, h_errno); 1982 return (-1); 1983 } 1984 1985 bzero(&addr, sizeof (addr)); 1986 /* LINTED */ 1987 addr.sin_addr = *(struct in_addr *)hp->h_addr; 1988 addr.sin_family = AF_INET; 1989 addr.sin_port = htons(port); 1990 1991 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 1992 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 1993 return (-1); 1994 } 1995 1996 status = connect(sock, (struct sockaddr *)&addr, sizeof (addr)); 1997 if (status < 0) { 1998 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 1999 (void) socket_close(sock); 2000 return (-1); 2001 } 2002 2003 c_id->host_addr = addr; /* save for future sendto calls */ 2004 c_id->fd = sock; 2005 2006 return (sock); 2007 } 2008 2009 /* 2010 * readline - Get a line from the socket. Discard the end-of-line 2011 * (CR or CR/LF or LF). 2012 * 2013 * ret = readline(c_id, sock, buf, len); 2014 * 2015 * Arguments: 2016 * c_id - Structure associated with the desired connection 2017 * sock - Socket to read 2018 * buf - Buffer for the line 2019 * len - Length of the buffer 2020 * 2021 * Returns: 2022 * 0 - Success. 'buf' contains the line. 2023 * -1 - Error occurred. Error information is set in the 2024 * error stack. 2025 */ 2026 static int 2027 readline(http_conn_t *c_id, int sock, char *buf, int len) 2028 { 2029 int n, r; 2030 char *ptr = buf; 2031 2032 for (n = 0; n < len; n++) { 2033 r = socket_read(sock, ptr, 1, c_id->read_timeout); 2034 2035 if (r < 0) { 2036 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2037 return (-1); 2038 } else if (r == 0) { 2039 libbootlog(BOOTLOG_WARNING, "Readline: no data"); 2040 return (0); 2041 } 2042 2043 if (*ptr == '\n') { 2044 *ptr = '\0'; 2045 2046 /* Strip off the CR if it's there */ 2047 if (buf[n-1] == '\r') { 2048 buf[n-1] = '\0'; 2049 n--; 2050 } 2051 2052 return (n); 2053 } 2054 2055 ptr++; 2056 } 2057 2058 libbootlog(BOOTLOG_WARNING, "readline: Buffer too short\n"); 2059 return (0); 2060 } 2061 2062 /* 2063 * proxy_connect - Set up a proxied TCP connection to the target host. 2064 * 2065 * sock = proxy_connect(c_id); 2066 * 2067 * Arguments: 2068 * c_id - Structure associated with the desired connection 2069 * 2070 * Returns: 2071 * >= 0 - Socket number. 2072 * -1 - Error occurred. Error information is set in the 2073 * error stack. Any cleanup is done. 2074 * 2075 * This function established a connection to the proxy and then sends 2076 * the request to connect to the target host. It reads the response 2077 * (the status line and any headers). When it returns, the connection 2078 * is ready for a HEAD or GET request. 2079 */ 2080 static int 2081 proxy_connect(http_conn_t *c_id) 2082 { 2083 struct sockaddr_in addr; 2084 int sock; 2085 char buf[1024]; 2086 char *ptr; 2087 int i; 2088 2089 if ((sock = tcp_connect(c_id, CONN_PROXY_HOSTNAME, 2090 CONN_PROXY_PORT)) < 0) { 2091 return (-1); 2092 } 2093 2094 if (!CONN_HTTPS) { 2095 return (sock); 2096 } 2097 2098 /* Now that we're connected, do the proxy request */ 2099 (void) snprintf(buf, sizeof (buf), 2100 "CONNECT %s:%d HTTP/1.0\r\n\r\n", CONN_HOSTNAME, CONN_PORT); 2101 2102 /* socket_write sets the errors */ 2103 if (socket_write(sock, buf, strlen(buf), &addr) <= 0) { 2104 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2105 (void) socket_close(sock); 2106 return (-1); 2107 } 2108 2109 /* And read the response */ 2110 i = readline(c_id, sock, buf, sizeof (buf)); 2111 if (i <= 0) { 2112 if (i == 0) 2113 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NORESP); 2114 libbootlog(BOOTLOG_CRIT, 2115 "proxy_connect: Empty response from proxy"); 2116 (void) socket_close(sock); 2117 return (-1); 2118 } 2119 2120 ptr = buf; 2121 if (strncmp(ptr, "HTTP", 4) != 0) { 2122 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOT_1_1); 2123 libbootlog(BOOTLOG_CRIT, 2124 "proxy_connect: Unrecognized protocol"); 2125 (void) socket_close(sock); 2126 return (-1); 2127 } 2128 2129 /* skip to the code */ 2130 ptr += 4; 2131 while (*ptr != ' ' && *ptr != '\0') 2132 ptr++; 2133 while (*ptr == ' ' && *ptr != '\0') 2134 ptr++; 2135 2136 /* make sure it's three digits */ 2137 if (strncmp(ptr, "200", 3) != 0) { 2138 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADRESP); 2139 libbootlog(BOOTLOG_CRIT, 2140 "proxy_connect: Received error from proxy server"); 2141 (void) socket_close(sock); 2142 return (-1); 2143 } 2144 ptr += 3; 2145 if (isdigit(*ptr)) { 2146 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADRESP); 2147 (void) socket_close(sock); 2148 return (-1); 2149 } 2150 2151 /* Look for the blank line that signals end of proxy header */ 2152 while ((i = readline(c_id, sock, buf, sizeof (buf))) > 0) 2153 ; 2154 2155 if (i < 0) { 2156 (void) socket_close(sock); 2157 return (-1); 2158 } 2159 2160 return (sock); 2161 } 2162 2163 /* 2164 * check_cert_chain - Check if we have a valid certificate chain. 2165 * 2166 * ret = check_cert_chain(c_id, host); 2167 * 2168 * Arguments: 2169 * c_id - Connection info. 2170 * host - Name to compare with the common name in the certificate. 2171 * 2172 * Returns: 2173 * 0 - Certificate chain and common name are both OK. 2174 * -1 - Certificate chain and/or common name is not valid. 2175 */ 2176 static int 2177 check_cert_chain(http_conn_t *c_id, char *host) 2178 { 2179 X509 *peer; 2180 char peer_CN[256]; 2181 long verify_err; 2182 2183 if ((verify_err = SSL_get_verify_result(c_id->ssl)) != X509_V_OK) { 2184 SET_ERR(c_id, ERRSRC_VERIFERR, verify_err); 2185 libbootlog(BOOTLOG_CRIT, 2186 "check_cert_chain: Certificate doesn't verify"); 2187 return (-1); 2188 } 2189 2190 /* 2191 * Check the cert chain. The chain length 2192 * is automatically checked by OpenSSL when we 2193 * set the verify depth in the ctx 2194 * 2195 * All we need to do here is check that the CN 2196 * matches 2197 */ 2198 2199 /* Check the common name */ 2200 if ((peer = SSL_get_peer_certificate(c_id->ssl)) == NULL) { 2201 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOCERT); 2202 libbootlog(BOOTLOG_CRIT, 2203 "check_cert_chain: Peer did not present a certificate"); 2204 return (-1); 2205 } 2206 (void) X509_NAME_get_text_by_NID(X509_get_subject_name(peer), 2207 NID_commonName, peer_CN, 256); 2208 2209 if (verbosemode) 2210 libbootlog(BOOTLOG_VERBOSE, 2211 "server cert's peer_CN is %s, host is %s", peer_CN, host); 2212 2213 if (strcasecmp(peer_CN, host)) { 2214 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMATCH); 2215 libbootlog(BOOTLOG_CRIT, 2216 "check_cert_chain: Common name doesn't match host name"); 2217 libbootlog(BOOTLOG_CRIT, 2218 "peer_CN = %s, host = %s", peer_CN, host); 2219 return (-1); 2220 } 2221 2222 return (0); 2223 } 2224 2225 /* 2226 * print_ciphers - Print the list of ciphers for debugging. 2227 * 2228 * print_ciphers(ssl); 2229 * 2230 * Arguments: 2231 * ssl - SSL connection. 2232 * 2233 * Returns: 2234 * none 2235 */ 2236 static void 2237 print_ciphers(SSL *ssl) 2238 { 2239 SSL_CIPHER *c; 2240 STACK_OF(SSL_CIPHER) *sk; 2241 int i; 2242 const char *name; 2243 2244 if (ssl == NULL) 2245 return; 2246 2247 sk = SSL_get_ciphers(ssl); 2248 if (sk == NULL) 2249 return; 2250 2251 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { 2252 /* LINTED */ 2253 c = sk_SSL_CIPHER_value(sk, i); 2254 libbootlog(BOOTLOG_VERBOSE, "%08lx %s", c->id, c->name); 2255 } 2256 name = SSL_get_cipher_name(ssl); 2257 if (name == NULL) 2258 name = ""; 2259 libbootlog(BOOTLOG_VERBOSE, "Current cipher = %s", name); 2260 } 2261 2262 /* 2263 * read_headerlines - Get the header lines from the server. This reads 2264 * lines until it gets a empty line indicating end of headers. 2265 * 2266 * ret = read_headerlines(c_id); 2267 * 2268 * Arguments: 2269 * c_id - Info about the connection being read. 2270 * bread - TRUE if the headerlines are part of the message body. 2271 * 2272 * Returns: 2273 * 0 - Header lines were read. 2274 * -1 - Error occurred. The errors information is already in 2275 * the error stack. 2276 * 2277 * Read the lines. If the current line begins with a space or tab, it is 2278 * a continuation. Take the new line and append it to the end of the 2279 * previous line rather than making an entry for another line in 2280 * c_id->resphdr. 2281 * 2282 * Note that I/O errors are put into the error stack by http_srv_recv(), 2283 * which is called by getaline(). 2284 */ 2285 static int 2286 read_headerlines(http_conn_t *c_id, boolean_t bread) 2287 { 2288 char line[MAXHOSTNAMELEN]; 2289 char **new_buf; 2290 char *ptr; 2291 int next; 2292 int cur; 2293 int n; 2294 2295 /* process headers, stop when we get to an empty line */ 2296 cur = 0; 2297 next = 0; 2298 while ((n = getaline(c_id, line, sizeof (line), bread)) > 0) { 2299 2300 if (verbosemode) 2301 libbootlog(BOOTLOG_VERBOSE, 2302 "read_headerlines: %s", line); 2303 /* 2304 * See if this is a continuation line (first col is a 2305 * space or a tab) 2306 */ 2307 if (line[0] != ' ' && line[0] != ' ') { 2308 cur = next; 2309 next ++; 2310 new_buf = 2311 realloc(c_id->resphdr, (cur + 1) * sizeof (void *)); 2312 if (new_buf == NULL) { 2313 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 2314 return (-1); 2315 } 2316 c_id->resphdr = new_buf; 2317 2318 c_id->resphdr[cur] = strdup(line); 2319 if (c_id->resphdr[cur] == NULL) { 2320 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 2321 return (-1); 2322 } 2323 } else { 2324 ptr = line; 2325 while (isspace(*ptr)) 2326 ptr ++; 2327 c_id->resphdr[cur] = realloc(c_id->resphdr[cur], 2328 strlen(c_id->resphdr[cur]) + strlen(ptr) + 1); 2329 if (c_id->resphdr[cur] == NULL) { 2330 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOMEM); 2331 return (-1); 2332 } 2333 (void) strcat(c_id->resphdr[cur], ptr); 2334 } 2335 ptr = &(c_id->resphdr[cur][strlen(c_id->resphdr[cur]) - 1]); 2336 while (ptr > c_id->resphdr[cur] && isspace(*ptr)) 2337 ptr --; 2338 } 2339 c_id->resp.nresphdrs = next; 2340 2341 /* Cause of any I/O error was already put into error stack. */ 2342 return (n >= 0 ? 0 : -1); 2343 } 2344 2345 static void 2346 free_response(http_conn_t *c_id, int free_boundary) 2347 { 2348 int i; 2349 2350 /* free memory from previous calls */ 2351 if (c_id->resp.statusmsg != NULL) { 2352 free(c_id->resp.statusmsg); 2353 c_id->resp.statusmsg = NULL; 2354 } 2355 for (i = 0; i < c_id->resp.nresphdrs; i++) { 2356 free(c_id->resphdr[i]); 2357 c_id->resphdr[i] = NULL; 2358 } 2359 c_id->resp.nresphdrs = 0; 2360 if (c_id->resphdr != NULL) { 2361 free(c_id->resphdr); 2362 c_id->resphdr = NULL; 2363 } 2364 2365 if (free_boundary && c_id->boundary) { 2366 free(c_id->boundary); 2367 c_id->boundary = NULL; 2368 c_id->is_multipart = B_FALSE; 2369 } 2370 } 2371 2372 static int 2373 free_ctx_ssl(http_conn_t *c_id) 2374 { 2375 int err_ret = 0; 2376 2377 if (c_id->ssl != NULL) { 2378 if (SSL_shutdown(c_id->ssl) <= 0) { 2379 ulong_t err; 2380 while ((err = ERR_get_error()) != 0) 2381 SET_ERR(c_id, ERRSRC_LIBSSL, err); 2382 err_ret = -1; 2383 } 2384 SSL_free(c_id->ssl); 2385 c_id->ssl = NULL; 2386 } 2387 2388 if (c_id->fd != -1 && socket_close(c_id->fd) < 0) { 2389 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2390 err_ret = -1; 2391 } 2392 c_id->fd = -1; 2393 2394 if (c_id->ctx != NULL) { 2395 SSL_CTX_free(c_id->ctx); 2396 c_id->ctx = NULL; 2397 } 2398 2399 return (err_ret); 2400 } 2401 2402 /* 2403 * get_chunk_header - Get a chunk header line 2404 * 2405 * Arguments: 2406 * c_id - Structure describing the connection in question. 2407 * 2408 * Returns: 2409 * >=0 - Length of next chunk 2410 * -1 - Error occurred. The error information is in the error stack. 2411 */ 2412 static int 2413 get_chunk_header(http_conn_t *c_id) 2414 { 2415 char line[MAXHOSTNAMELEN]; 2416 char *ptr; 2417 int value; 2418 int ok; 2419 int i; 2420 2421 /* 2422 * Determine whether an extra crlf pair will precede the 2423 * chunk header. For the first one, there is no preceding 2424 * crlf. For later chunks, there is one crlf. 2425 */ 2426 if (c_id->is_firstchunk) { 2427 ok = 1; 2428 c_id->is_firstchunk = B_FALSE; 2429 } else { 2430 ok = ((i = getaline(c_id, line, sizeof (line), B_FALSE)) == 0); 2431 } 2432 2433 if (ok) 2434 i = getaline(c_id, line, sizeof (line), B_FALSE); 2435 if (!ok || i < 0) { 2436 /* 2437 * If I/O error, the Cause was already put into 2438 * error stack. This is an additional error. 2439 */ 2440 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_NOHEADER); 2441 return (-1); 2442 } 2443 2444 if (verbosemode) 2445 libbootlog(BOOTLOG_VERBOSE, "get_chunk_header: <%s>", line); 2446 2447 2448 /* 2449 * The first (and probably only) field in the line is the hex 2450 * length of the chunk. 2451 */ 2452 ptr = line; 2453 value = 0; 2454 while (*ptr != '\0' && (i = hexdigit(*ptr)) >= 0) { 2455 value = (value << 4) + i; 2456 ptr ++; 2457 } 2458 2459 return (value); 2460 } 2461 2462 /* 2463 * init_bread - Initialize the counters used to read message bodies. 2464 * 2465 * Arguments: 2466 * c_id - Structure describing the connection in question. 2467 * 2468 * Returns: 2469 * 0 - Success 2470 * -1 - Error occurred. The error information is in the error stack. 2471 * 2472 * This routine will determine whether the message body being received is 2473 * chunked or non-chunked. Once determined, the counters used to read 2474 * message bodies will be initialized. 2475 */ 2476 static int 2477 init_bread(http_conn_t *c_id) 2478 { 2479 char *hdr; 2480 char *ptr; 2481 boolean_t sized = B_FALSE; 2482 2483 /* 2484 * Assume non-chunked reads until proven otherwise. 2485 */ 2486 c_id->is_chunked = B_FALSE; 2487 c_id->is_firstchunk = B_FALSE; 2488 hdr = http_get_header_value(c_id, "Content-Length"); 2489 if (hdr != NULL) { 2490 c_id->body_size = strtol(hdr, NULL, 10); 2491 if (c_id->body_size == 0 && errno != 0) { 2492 free(hdr); 2493 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADSIZE); 2494 return (-1); 2495 } 2496 free(hdr); 2497 sized = B_TRUE; 2498 } 2499 2500 /* 2501 * If size was not determined above, then see if this is a 2502 * chunked message. Keep in mind that the first chunk size is 2503 * "special". 2504 */ 2505 if (!sized) { 2506 hdr = http_get_header_value(c_id, "Transfer-Encoding"); 2507 if (hdr != NULL) { 2508 ptr = eat_ws(hdr); 2509 if (startswith((const char **)&ptr, "chunked;") || 2510 strcasecmp(ptr, "chunked") == 0) { 2511 c_id->is_firstchunk = B_TRUE; 2512 c_id->is_chunked = B_TRUE; 2513 } 2514 free(hdr); 2515 if (c_id->is_chunked) { 2516 c_id->body_size = get_chunk_header(c_id); 2517 if (c_id->body_size == -1) { 2518 /* 2519 * Error stack was already set at a 2520 * lower level. 2521 */ 2522 return (-1); 2523 } 2524 sized = B_TRUE; 2525 } 2526 } 2527 } 2528 2529 /* 2530 * Well, isn't this a fine predicament? It wasn't chunked or 2531 * non-chunked as far as we can tell. 2532 */ 2533 if (!sized) { 2534 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_BADSIZE); 2535 return (-1); 2536 } 2537 2538 c_id->body_read = 0; 2539 c_id->body_size_tot = c_id->body_size; 2540 c_id->body_read_tot = 0; 2541 2542 return (0); 2543 } 2544 2545 /* 2546 * get_msgcnt - Get the number of bytes left in the message body or chunk. 2547 * 2548 * Arguments: 2549 * c_id - Structure describing the connection in question. 2550 * msgcnt - Where to store the message count. 2551 * 2552 * Returns: 2553 * 0 - Success 2554 * -1 - Error occurred. The error information is in the error stack. 2555 * 2556 * Note that if the message being read is not chunked, then the byte count 2557 * is simply the message size minus the bytes read thus far. In the case of 2558 * chunked messages, the byte count returned will be the number of bytes 2559 * left in the chunk. If the current chunk has been exhausted, then this 2560 * routine will determine the size of the next chunk. When the next chunk 2561 * size is zero, the message has been read in its entirety. 2562 */ 2563 static int 2564 get_msgcnt(http_conn_t *c_id, ssize_t *msgcnt) 2565 { 2566 /* 2567 * If there are more bytes in the message, then return. 2568 */ 2569 *msgcnt = c_id->body_size - c_id->body_read; 2570 if (*msgcnt != 0) { 2571 return (0); 2572 } 2573 /* 2574 * If this is not a chunked message and the body has been 2575 * read, then we're done. 2576 */ 2577 if (!c_id->is_chunked) { 2578 return (0); 2579 } 2580 2581 /* 2582 * We're looking at a chunked message whose immediate 2583 * chunk has been totally processed. See if there is 2584 * another chunk. 2585 */ 2586 c_id->body_size = get_chunk_header(c_id); 2587 if (c_id->body_size == -1) { 2588 /* 2589 * Error stack was already set at a 2590 * lower level. 2591 */ 2592 return (-1); 2593 } 2594 2595 /* 2596 * No bytes of this chunk have been processed yet. 2597 */ 2598 c_id->body_read = 0; 2599 2600 /* 2601 * A zero length chunk signals the end of the 2602 * message body and chunking. 2603 */ 2604 if (c_id->body_size == 0) { 2605 c_id->is_chunked = B_FALSE; 2606 return (0); 2607 } 2608 2609 /* 2610 * There is another chunk. 2611 */ 2612 c_id->body_size_tot += c_id->body_size; 2613 *msgcnt = c_id->body_size - c_id->body_read; 2614 2615 return (0); 2616 } 2617 2618 /* 2619 * getaline - Get lines of data from the HTTP response, up to 'len' bytes. 2620 * NOTE: the line will not end with a NULL if all 'len' bytes 2621 * were read. 2622 * 2623 * Arguments: 2624 * c_id - Structure describing the connection in question. 2625 * line - Where to store the data. 2626 * len - Maximum number of bytes in the line. 2627 * bread - TRUE if the lines are part of the message body. 2628 * 2629 * Returns: 2630 * >=0 - The number of bytes successfully read. 2631 * <0 - An error occurred. This is (the number of bytes gotten + 1), 2632 * negated. In other words, if 'n' bytes were read and then an 2633 * error occurred, this will return (-(n+1)). So zero bytes read 2634 * and then an error occurs, this will return -1. If 1 bytes 2635 * was read, it will return -2, etc. 2636 * 2637 * Specifics of the error can be gotten using http_get_lasterr(); 2638 * 2639 * Note that I/O errors are put into the error stack by http_srv_recv().1 2640 */ 2641 static int 2642 getaline(http_conn_t *c_id, char *line, int len, boolean_t bread) 2643 { 2644 int i = 0; 2645 ssize_t msgcnt = 0; 2646 ssize_t cnt; 2647 2648 while (i < len) { 2649 /* 2650 * Special processing required for message body reads. 2651 */ 2652 if (bread) { 2653 /* 2654 * See if there is another chunk. Obviously, in the 2655 * case of non-chunked messages, there won't be. 2656 * But in either case, chunked or not, if msgcnt 2657 * is still zero after the call to get_msgcnt(), 2658 * then we're done. 2659 */ 2660 if (msgcnt == 0) { 2661 if (get_msgcnt(c_id, &msgcnt) == -1) { 2662 return (-(i+1)); 2663 } 2664 if (msgcnt == 0) { 2665 break; 2666 } 2667 } 2668 cnt = MIN(msgcnt, sizeof (c_id->inbuf.buf)); 2669 } else { 2670 cnt = sizeof (c_id->inbuf.buf); 2671 } 2672 2673 /* read more data if buffer empty */ 2674 if (c_id->inbuf.i == c_id->inbuf.n) { 2675 c_id->inbuf.i = 0; 2676 c_id->inbuf.n = http_srv_recv(c_id, c_id->inbuf.buf, 2677 cnt); 2678 if (c_id->inbuf.n == 0) { 2679 return (i); 2680 } 2681 if (c_id->inbuf.n < 0) { 2682 return (-(i+1)); 2683 } 2684 } 2685 /* skip CR */ 2686 if (c_id->inbuf.buf[c_id->inbuf.i] == '\r') { 2687 INC_BREAD_CNT(bread, msgcnt); 2688 c_id->inbuf.i++; 2689 continue; 2690 } 2691 if (c_id->inbuf.buf[c_id->inbuf.i] == '\n') { 2692 INC_BREAD_CNT(bread, msgcnt); 2693 c_id->inbuf.i++; 2694 line[i] = '\0'; 2695 return (i); 2696 } 2697 /* copy buf from internal buffer */ 2698 INC_BREAD_CNT(bread, msgcnt); 2699 line[i++] = c_id->inbuf.buf[c_id->inbuf.i++]; 2700 } 2701 return (i); 2702 } 2703 2704 /* 2705 * getbytes - Get a block from the HTTP response. Used for the HTTP body. 2706 * 2707 * Arguments: 2708 * c_id - Structure describing the connection in question. 2709 * line - Where to store the data. 2710 * len - Maximum number of bytes in the block. 2711 * 2712 * Returns: 2713 * >=0 - The number of bytes successfully read. 2714 * <0 - An error occurred. This is (the number of bytes gotten + 1), 2715 * negated. In other words, if 'n' bytes were read and then an 2716 * error occurred, this will return (-(n+1)). So zero bytes read 2717 * and then an error occurs, this will return -1. If 1 bytes 2718 * was read, it will return -2, etc. 2719 * 2720 * Specifics of the error can be gotten using http_get_lasterr(); 2721 * 2722 * Note that all reads performed here assume that a message body is being 2723 * read. If this changes in the future, then the logic should more closely 2724 * resemble getaline(). 2725 * 2726 * Note that I/O errors are put into the error stack by http_srv_recv(). 2727 */ 2728 static int 2729 getbytes(http_conn_t *c_id, char *line, int len) 2730 { 2731 int i = 0; 2732 ssize_t msgcnt = 0; 2733 ssize_t cnt; 2734 int nbytes; 2735 2736 while (i < len) { 2737 /* 2738 * See if there is another chunk. Obviously, in the 2739 * case of non-chunked messages, there won't be. 2740 * But in either case, chunked or not, if msgcnt 2741 * is still zero after the call to get_msgcnt(), then 2742 * we're done. 2743 */ 2744 if (msgcnt == 0) { 2745 if (get_msgcnt(c_id, &msgcnt) == -1) { 2746 return (-(i+1)); 2747 } 2748 if (msgcnt == 0) { 2749 break; 2750 } 2751 } 2752 2753 cnt = MIN(msgcnt, len - i); 2754 2755 if (c_id->inbuf.n != c_id->inbuf.i) { 2756 nbytes = (int)MIN(cnt, c_id->inbuf.n - c_id->inbuf.i); 2757 (void) memcpy(line, &c_id->inbuf.buf[c_id->inbuf.i], 2758 nbytes); 2759 c_id->inbuf.i += nbytes; 2760 } else { 2761 nbytes = http_srv_recv(c_id, line, cnt); 2762 if (nbytes == 0) { 2763 return (i); 2764 } 2765 if (nbytes < 0) { 2766 return (-(i+1)); 2767 } 2768 } 2769 2770 i += nbytes; 2771 line += nbytes; 2772 msgcnt -= nbytes; 2773 c_id->body_read += nbytes; 2774 c_id->body_read_tot += nbytes; 2775 } 2776 2777 return (i); 2778 } 2779 2780 static int 2781 http_srv_send(http_conn_t *c_id, const void *buf, size_t nbyte) 2782 { 2783 int retval; 2784 2785 if (c_id->ssl != NULL) { 2786 if ((retval = SSL_write(c_id->ssl, buf, nbyte)) <= 0) { 2787 handle_ssl_error(c_id, retval); 2788 } 2789 return (retval); 2790 } else { 2791 retval = socket_write(c_id->fd, buf, nbyte, &c_id->host_addr); 2792 if (retval < 0) { 2793 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2794 return (-1); 2795 } 2796 return (retval); 2797 } 2798 } 2799 2800 static int 2801 http_srv_recv(http_conn_t *c_id, void *buf, size_t nbyte) 2802 { 2803 int retval; 2804 2805 if (c_id->ssl != NULL) { 2806 if ((retval = SSL_read(c_id->ssl, buf, nbyte)) <= 0) { 2807 handle_ssl_error(c_id, retval); 2808 } 2809 return (retval); 2810 } else { 2811 retval = socket_read(c_id->fd, buf, nbyte, c_id->read_timeout); 2812 if (retval < 0) { 2813 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2814 return (-1); 2815 } 2816 return (retval); 2817 } 2818 } 2819 2820 static boolean_t 2821 http_check_conn(http_conn_t *c_id) 2822 { 2823 early_err = 0; 2824 if (c_id == NULL || c_id->signature != HTTP_CONN_INFO) { 2825 early_err = EHTTP_BADARG; 2826 return (B_FALSE); 2827 } 2828 RESET_ERR(c_id); 2829 return (B_TRUE); 2830 } 2831 2832 static void 2833 handle_ssl_error(http_conn_t *c_id, int retval) 2834 { 2835 ulong_t err; 2836 2837 err = SSL_get_error(c_id->ssl, retval); 2838 2839 switch (err) { 2840 case SSL_ERROR_NONE: 2841 return; 2842 2843 case SSL_ERROR_ZERO_RETURN: 2844 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_CONCLOSED); 2845 return; 2846 2847 case SSL_ERROR_WANT_READ: 2848 case SSL_ERROR_WANT_WRITE: 2849 case SSL_ERROR_WANT_CONNECT: 2850 case SSL_ERROR_WANT_X509_LOOKUP: 2851 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_UNEXPECTED); 2852 return; 2853 2854 case SSL_ERROR_SYSCALL: 2855 err = ERR_get_error(); 2856 if (err == 0) 2857 SET_ERR(c_id, ERRSRC_LIBHTTP, EHTTP_EOFERR); 2858 else if (err == (ulong_t)-1) 2859 SET_ERR(c_id, ERRSRC_SYSTEM, errno); 2860 else { 2861 SET_ERR(c_id, ERRSRC_LIBSSL, err); 2862 while ((err = ERR_get_error()) != 0) 2863 SET_ERR(c_id, ERRSRC_LIBSSL, err); 2864 } 2865 return; 2866 2867 case SSL_ERROR_SSL: 2868 while ((err = ERR_get_error()) != 0) { 2869 SET_ERR(c_id, ERRSRC_LIBSSL, err); 2870 } 2871 return; 2872 } 2873 } 2874 2875 static int 2876 count_digits(int value) 2877 { 2878 int count = 1; 2879 2880 if (value < 0) { 2881 count++; 2882 value = -value; 2883 } 2884 2885 while (value > 9) { 2886 value /= 10; 2887 count++; 2888 } 2889 return (count); 2890 } 2891 2892 static int 2893 hexdigit(char ch) 2894 { 2895 if (ch >= '0' && ch <= '9') 2896 return (ch - '0'); 2897 if (ch >= 'A' && ch <= 'F') 2898 return (ch - 'A' + 10); 2899 if (ch >= 'a' && ch <= 'f') 2900 return (ch - 'a' + 10); 2901 return (-1); 2902 } 2903 2904 static char * 2905 eat_ws(const char *buf) 2906 { 2907 char *ptr = (char *)buf; 2908 2909 while (isspace(*ptr)) 2910 ptr++; 2911 2912 return (ptr); 2913 } 2914 2915 static boolean_t 2916 startswith(const char **strp, const char *starts) 2917 { 2918 int len = strlen(starts); 2919 2920 if (strncasecmp(*strp, starts, len) == 0) { 2921 *strp += len; 2922 return (B_TRUE); 2923 } 2924 return (B_FALSE); 2925 } 2926