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