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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/promif.h> 28 #include <sys/obpdefs.h> 29 #include <sys/bootvfs.h> 30 #include <sys/bootconf.h> 31 #include <netinet/in.h> 32 #include <sys/wanboot_impl.h> 33 #include <boot_http.h> 34 #include <aes.h> 35 #include <des3.h> 36 #include <cbc.h> 37 #include <hmac_sha1.h> 38 #include <sys/sha1.h> 39 #include <sys/sha1_consts.h> 40 #include <bootlog.h> 41 #include <parseURL.h> 42 #include <netboot_paths.h> 43 #include <netinet/inetutil.h> 44 #include <sys/salib.h> 45 #include <inet/mac.h> 46 #include <inet/ipv4.h> 47 #include <dhcp_impl.h> 48 #include <inet/dhcpv4.h> 49 #include <bootinfo.h> 50 #include <wanboot_conf.h> 51 #include "boot_plat.h" 52 #include "ramdisk.h" 53 #include "wbcli.h" 54 55 /* 56 * Types of downloads 57 */ 58 #define MINIINFO "miniinfo" 59 #define MINIROOT "miniroot" 60 #define WANBOOTFS "wanbootfs" 61 62 #define WANBOOT_RETRY_NOMAX -1 63 #define WANBOOT_RETRY_ROOT_MAX 50 64 #define WANBOOT_RETRY_MAX 5 65 #define WANBOOT_RETRY_SECS 5 66 #define WANBOOT_RETRY_MAX_SECS 30 67 68 /* 69 * Our read requests should timeout after 25 seconds 70 */ 71 #define SOCKET_READ_TIMEOUT 25 72 73 /* 74 * Experimentation has shown that an 8K download buffer is optimal 75 */ 76 #define HTTP_XFER_SIZE 8192 77 static char buffer[HTTP_XFER_SIZE]; 78 79 bc_handle_t bc_handle; 80 81 extern int determine_fstype_and_mountroot(char *); 82 extern uint64_t get_ticks(void); 83 84 /* 85 * The following is used to determine whether the certs and private key 86 * files will be in PEM format or PKCS12 format. 'use_p12' is zero 87 * to use PEM format, and 1 when PKCS12 format is to be used. It is 88 * done this way, as a global, so that it can be patched if needs be 89 * using the OBP debugger. 90 */ 91 uint32_t use_p12 = 1; 92 93 #define CONTENT_LENGTH "Content-Length" 94 95 #define NONCELEN (2 * HMAC_DIGEST_LEN) /* two hex nibbles/byte */ 96 #define WANBOOTFS_NONCE_FILE "/nonce" 97 98 static char nonce[NONCELEN + 1]; 99 100 enum URLtype { 101 URLtype_wanbootfs = 0, 102 URLtype_miniroot = 1 103 }; 104 105 static char *URLtoCGIcontent[] = { 106 "bootfs", 107 "rootfs" 108 }; 109 #define CGIcontent(urltype) URLtoCGIcontent[urltype] 110 111 /* Encryption algorithms */ 112 typedef enum { 113 ENCR_NONE, 114 ENCR_3DES, 115 ENCR_AES 116 } encr_type_t; 117 118 /* Hash algorithms */ 119 typedef enum { 120 HASH_NONE, 121 HASH_HMAC_SHA1 122 } hash_type_t; 123 124 /* 125 * Keys ... 126 */ 127 static encr_type_t encr_type = ENCR_NONE; 128 static unsigned char *g_encr_key = NULL; 129 130 static hash_type_t hash_type = HASH_NONE; 131 static unsigned char *g_hash_key = NULL; 132 133 void 134 print_errors(const char *func, http_handle_t handle) 135 { 136 char const *msg; 137 ulong_t err; 138 uint_t src; 139 140 while ((err = http_get_lasterr(handle, &src)) != 0) { 141 msg = http_errorstr(src, err); 142 bootlog("wanboot", BOOTLOG_ALERT, 143 "%s: errsrc %u, err %lu (0x%lx)", func, src, err, err); 144 bootlog("wanboot", BOOTLOG_ALERT, "%s", msg); 145 } 146 } 147 148 /* 149 * This routine is called by a consumer to determine whether or not a 150 * retry should be attempted. If a retry is in order (depends upon the 151 * 'retry_cnt' and 'retry_max' arguments), then this routine will print a 152 * message indicating this is the case and will determine an appropriate 153 * "sleep" time before retrying. The "sleep" time will depend upon the 154 * 'retry_cnt' and will max out at WANBOOT_RETRY_MAX_SECS. 155 * 156 * Returns: 157 * B_TRUE = retry is in order 158 * B_FALSE = retry limit exceeded 159 */ 160 boolean_t 161 wanboot_retry(int retry_cnt, int retry_max) 162 { 163 unsigned int seconds; 164 165 if (retry_max == WANBOOT_RETRY_NOMAX || retry_cnt <= retry_max) { 166 seconds = WANBOOT_RETRY_SECS * retry_cnt; 167 if (seconds > WANBOOT_RETRY_MAX_SECS) { 168 seconds = WANBOOT_RETRY_MAX_SECS; 169 } 170 bootlog("wanboot", BOOTLOG_INFO, 171 "Will retry in %d seconds ...", seconds); 172 (void) sleep(seconds); 173 return (B_TRUE); 174 } else { 175 bootlog("wanboot", BOOTLOG_INFO, 176 "Maximum retries exceeded."); 177 return (B_FALSE); 178 } 179 } 180 181 /* 182 * Determine which encryption algorithm the client is configured to use. 183 * WAN boot determines which key to use by order of priority. That is 184 * multiple encryption keys may exist in the PROM, but the first one found 185 * (while searching in a preferred order) is the one that will be used. 186 */ 187 static void 188 init_encryption(void) 189 { 190 static unsigned char key[WANBOOT_MAXKEYLEN]; 191 size_t len = sizeof (key); 192 193 if (bootinfo_get(BI_AES_KEY, (char *)&key, &len, NULL) == 194 BI_E_SUCCESS) { 195 encr_type = ENCR_AES; 196 g_encr_key = key; 197 } else if (bootinfo_get(BI_3DES_KEY, (char *)&key, &len, NULL) == 198 BI_E_SUCCESS) { 199 encr_type = ENCR_3DES; 200 g_encr_key = key; 201 } 202 } 203 204 /* 205 * Determine whether the client is configured to use hashing. 206 */ 207 static void 208 init_hashing(void) 209 { 210 static unsigned char key[WANBOOT_HMAC_KEY_SIZE]; 211 size_t len = sizeof (key); 212 213 if (bootinfo_get(BI_SHA1_KEY, (char *)&key, &len, NULL) == 214 BI_E_SUCCESS) { 215 hash_type = HASH_HMAC_SHA1; 216 g_hash_key = key; 217 } 218 } 219 220 /* 221 * Read some CPU-specific rapidly-varying data (assumed to be of length 222 * sizeof (hrtime_t) in the non-SPARC case), and digestify it to further 223 * randomize the output. 224 */ 225 char * 226 generate_nonce(void) 227 { 228 uint64_t t; 229 SHA1_CTX c; 230 unsigned char digest[HMAC_DIGEST_LEN]; 231 uint_t nlen = sizeof (nonce); 232 233 int err; 234 235 /* 236 * Read SPARC %tick register or x86 TSC 237 */ 238 t = get_ticks(); 239 SHA1Init(&c); 240 SHA1Update(&c, (const uint8_t *)&t, sizeof (t)); 241 SHA1Final(digest, &c); 242 243 err = octet_to_hexascii(digest, sizeof (digest), nonce, &nlen); 244 if (err != 0) { 245 bootlog("wanboot", BOOTLOG_CRIT, 246 "cannot convert nonce to ASCII: error %d", err); 247 return (NULL); 248 } 249 nonce[NONCELEN] = '\0'; 250 return (nonce); 251 } 252 253 /* 254 * Given a server URL, builds a URL to request one of the wanboot 255 * datastreams. 256 * 257 * Returns: 258 * -1 = Non-recoverable error 259 * 0 = Success 260 */ 261 static int 262 build_request_url(url_t *req_url, enum URLtype ut, const url_t *server_url) 263 { 264 char clid[WB_MAX_CID_LEN]; 265 size_t clen; 266 char wid[WB_MAX_CID_LEN * 2 + 1]; 267 uint_t wlen; 268 struct in_addr ip; 269 struct in_addr mask; 270 char *netstr; 271 char *ppath; 272 size_t plen; 273 const char reqstr[] = "/?CONTENT=%s&IP=%s&CID=%s"; 274 275 /* 276 * Initialize the request 277 */ 278 *req_url = *server_url; 279 280 /* 281 * Build the network number string 282 */ 283 ipv4_getipaddr(&ip); 284 ipv4_getnetmask(&mask); 285 ip.s_addr = ip.s_addr & mask.s_addr; 286 netstr = inet_ntoa(ip); 287 288 /* 289 * Get the wan id 290 */ 291 clen = sizeof (clid); 292 if (bootinfo_get(BI_CLIENT_ID, clid, &clen, NULL) != BI_E_SUCCESS) { 293 bootlog("wanboot", BOOTLOG_CRIT, 294 "Cannot retrieve the client ID"); 295 return (-1); 296 } 297 wlen = sizeof (wid); 298 (void) octet_to_hexascii(clid, clen, wid, &wlen); 299 300 /* 301 * Build the request, making sure that the length of the 302 * constructed URL falls within the supported maximum. 303 */ 304 plen = strlen(req_url->abspath); 305 ppath = req_url->abspath + plen; 306 if (snprintf(ppath, URL_MAX_PATHLEN - plen, reqstr, 307 CGIcontent(ut), netstr, wid) >= URL_MAX_PATHLEN - plen) { 308 bootlog("wanboot", BOOTLOG_CRIT, 309 "The URL path length of the %s request is greater than " 310 "the maximum of %d", CGIcontent(ut), URL_MAX_PATHLEN); 311 return (-1); 312 } 313 314 /* 315 * If the URL type requires a nonce, then supply it. 316 * It will be returned in the reply to detect attempted 317 * replays. 318 */ 319 if (ut == URLtype_wanbootfs) { 320 char *n = generate_nonce(); 321 322 if (n != NULL) { 323 plen += strlen("&NONCE=") + NONCELEN; 324 if (plen > URL_MAX_PATHLEN) 325 return (-1); 326 (void) strcat(req_url->abspath, "&NONCE="); 327 (void) strcat(req_url->abspath, n); 328 } 329 } 330 331 return (0); 332 } 333 334 /* 335 * This routine reads data from an HTTP connection into a buffer. 336 * 337 * Returns: 338 * 0 = Success 339 * 1 = HTTP download error 340 */ 341 static int 342 read_bytes(http_handle_t handle, char *buffer, size_t cnt) 343 { 344 int len; 345 size_t i; 346 347 for (i = 0; i < cnt; i += len) { 348 len = http_read_body(handle, &buffer[i], cnt - i); 349 if (len <= 0) { 350 print_errors("http_read_body", handle); 351 return (1); 352 } 353 } 354 return (0); 355 } 356 357 /* 358 * This routine compares two hash digests, one computed by the server and 359 * the other computed by the client to verify that a transmitted message 360 * was received without corruption. 361 * 362 * Notes: 363 * The client only computes a digest if it is configured with a 364 * hash key. If it is not, then the server should not have a hash 365 * key for the client either and therefore should have sent a 366 * zero filled digest. 367 * 368 * Returns: 369 * B_TRUE = digest was verified 370 * B_FALSE = digest did not verify 371 */ 372 static boolean_t 373 verify_digests(const char *what, unsigned char *cdigest, unsigned char *sdigest) 374 { 375 static char null_digest[HMAC_DIGEST_LEN]; 376 377 if (bcmp(sdigest, cdigest, HMAC_DIGEST_LEN) != 0) { 378 bootlog("wanboot", BOOTLOG_CRIT, 379 "%s: invalid hash digest", what); 380 bootlog("wanboot", BOOTLOG_CRIT, 381 "This may signify a client/server key mismatch"); 382 if (bcmp(sdigest, null_digest, HMAC_DIGEST_LEN) == 0) { 383 bootlog("wanboot", BOOTLOG_CRIT, 384 "(client has key but wrong signature_type?)"); 385 } else if (bcmp(cdigest, null_digest, HMAC_DIGEST_LEN) == 0) { 386 bootlog("wanboot", BOOTLOG_CRIT, 387 "(signature_type specified but no client key?)"); 388 } 389 bootlog("wanboot", BOOTLOG_CRIT, 390 "or possible corruption of the image in transit"); 391 return (B_FALSE); 392 } 393 394 return (B_TRUE); 395 } 396 397 /* 398 * This routine reads the part of a multipart message that contains a 399 * hash digest. Errors in reading the digest are differentiated from 400 * other kinds of errors so that the caller can decide whether or 401 * not a retry is worthwhile. 402 * 403 * Note: 404 * The hash digest can either be an HMAC digest or it can be 405 * a zero length message (representing no hash digest). 406 * 407 * Returns: 408 * -1 = Non-recoverable error 409 * 0 = Success 410 * 1 = HTTP download error 411 */ 412 static int 413 read_digest(const char *what, http_handle_t handle, unsigned char *sdigest) 414 { 415 char *lenstr; 416 size_t digest_size; 417 418 /* 419 * Process the HMAC digest header. 420 */ 421 if (http_process_part_headers(handle, NULL) != 0) { 422 print_errors("http_process_part_headers", handle); 423 return (1); 424 } 425 lenstr = http_get_header_value(handle, CONTENT_LENGTH); 426 if (lenstr == NULL) { 427 bootlog("wanboot", BOOTLOG_ALERT, 428 "%s: error getting digest length", what); 429 return (1); 430 } 431 digest_size = (size_t)strtol(lenstr, NULL, 10); 432 free(lenstr); 433 434 /* 435 * Validate the HMAC digest length. 436 */ 437 if (digest_size != HMAC_DIGEST_LEN) { 438 bootlog("wanboot", BOOTLOG_CRIT, 439 "%s: error validating response - invalid digest size", 440 what); 441 return (-1); 442 } 443 444 /* 445 * Read the HMAC digest. 446 */ 447 if (read_bytes(handle, (char *)sdigest, digest_size) != 0) { 448 bootlog("wanboot", BOOTLOG_ALERT, 449 "%s: error reading digest", what); 450 return (1); 451 } 452 453 return (0); 454 } 455 456 /* 457 * This routine reads data from an HTTP connection and writes the data 458 * to a ramdisk. It also, optionally computes a hash digest of the processed 459 * data. This routine may be called to continue writing a previously aborted 460 * write. If this is the case, then the offset will be non-zero and the write 461 * pointer into the ramdisk will be positioned correctly by the caller. 462 * 463 * Returns: 464 * -1 = Non-recoverable error 465 * 0 = Success 466 * 1 = HTTP download error 467 */ 468 static int 469 write_msg_to_ramdisk(const char *what, caddr_t addr, http_handle_t handle, 470 size_t ramdisk_size, off_t *offset, SHA1_CTX *sha) 471 { 472 int len; 473 long nleft; 474 static int bootlog_message_interval; 475 static int bootlog_progress; 476 int ret; 477 478 /* 479 * Read the data and write it to the ramdisk. 480 */ 481 if (*offset == 0) { 482 bootlog_progress = 0; 483 bootlog_message_interval = ramdisk_size / sizeof (buffer); 484 if (bootlog_message_interval < 500) 485 bootlog_message_interval /= 5; 486 else 487 bootlog_message_interval /= 50; 488 489 bootlog("wanboot", BOOTLOG_VERBOSE, 490 "Reading %s file system (%ld kB)", 491 what, ramdisk_size / 1024); 492 } else { 493 bootlog("wanboot", BOOTLOG_VERBOSE, 494 "Continuing read of %s file system (%ld kB)", 495 what, ramdisk_size / 1024); 496 } 497 for (ret = 0; ret == 0 && *offset < ramdisk_size; 498 *offset += len, addr += len) { 499 nleft = ramdisk_size - *offset; 500 501 if (nleft > sizeof (buffer)) 502 nleft = sizeof (buffer); 503 504 len = http_read_body(handle, addr, nleft); 505 if (len <= 0) { 506 print_errors("http_read_body", handle); 507 /* 508 * In the case of a partial failure, http_read_body() 509 * returns into 'len', 1 - the number of bytes read. 510 * So, a -65 means 64 bytes read and an error occurred. 511 */ 512 if (len != 0) { 513 len = -(len + 1); 514 } 515 ret = 1; 516 } 517 if (sha != NULL) { 518 HMACUpdate(sha, (uchar_t *)addr, (size_t)len); 519 } 520 if (bootlog_progress == bootlog_message_interval) { 521 bootlog("wanboot", BOOTLOG_PROGRESS, 522 "%s: Read %ld of %ld kB (%ld%%)", what, 523 *offset / 1024, ramdisk_size / 1024, 524 *offset * 100 / ramdisk_size); 525 bootlog_progress = 0; 526 } else { 527 bootlog_progress++; 528 } 529 } 530 if (ret == 0) { 531 bootlog("wanboot", BOOTLOG_PROGRESS, 532 "%s: Read %ld of %ld kB (%ld%%)", what, 533 *offset / 1024, ramdisk_size / 1024, 534 *offset * 100 / ramdisk_size); 535 bootlog("wanboot", BOOTLOG_INFO, "%s: Download complete", what); 536 } 537 return (ret); 538 } 539 540 /* 541 * This routine is called with a bootinfo parameter name. If the parameter 542 * has a value it should be a URL, and this will be used to initialize the 543 * http_url structure. 544 * 545 * Returns: 546 * -1 = Non-recoverable error 547 * 0 = Success 548 * 1 = DHCP option not set 549 */ 550 static int 551 get_url(char *name, url_t *url) 552 { 553 char buf[URL_MAX_STRLEN]; 554 size_t len; 555 int ret; 556 557 bzero(buf, sizeof (buf)); 558 len = sizeof (buf) - 1; 559 if (bootinfo_get(name, buf, &len, NULL) != BI_E_SUCCESS || len == 0) { 560 return (1); 561 } 562 563 /* 564 * Parse the URL. 565 */ 566 ret = url_parse(buf, url); 567 if (ret != URL_PARSE_SUCCESS) { 568 bootlog("wanboot", BOOTLOG_CRIT, 569 "Unable to parse URL %s", buf); 570 return (-1); 571 } 572 573 return (0); 574 } 575 576 /* 577 * This routine initiates an HTTP request and returns a handle so that 578 * the caller can process the response. 579 * 580 * Notes: 581 * Requests may be either secure or not. If the request is secure, then 582 * this routine assumes that a wanboot file system exists and 583 * uses its contents to provide the HTTP library with the information 584 * that will be required by SSL. 585 * 586 * In order to facilitate transmission retries, this routine supports 587 * range requests. A caller may request a range by providing a non-zero 588 * offset. In which case, a range request is made that ranges from the 589 * offet to the end of the file. 590 * 591 * If the client is configured to use an HTTP proxy, then this routine 592 * will make the HTTP library aware of the proxy. 593 * 594 * Any HTTP errors encountered in downloading or processing the message 595 * are not deemed unrecoverable errors. The caller can simply try the 596 * request once again. 597 * 598 * Returns: 599 * -1 = Non-recoverable error 600 * 0 = Success 601 * 1 = HTTP download error 602 */ 603 static int 604 establish_http_connection(const char *what, http_handle_t *handlep, 605 url_t *url, offset_t offset) 606 { 607 static boolean_t is_auth_file_init = B_FALSE; 608 static boolean_t is_proxy_init = B_FALSE; 609 static boolean_t proxy_exists = B_FALSE; 610 static url_hport_t proxy_hp; 611 http_respinfo_t *resp; 612 char buf[URL_MAX_STRLEN]; 613 size_t len = sizeof (buf) - 1; 614 int ret; 615 616 /* Check for HTTP proxy */ 617 if (!is_proxy_init && 618 bootinfo_get(BI_HTTP_PROXY, buf, &len, NULL) == BI_E_SUCCESS && 619 strlen(buf) > 0) { 620 /* 621 * Parse the hostport. 622 */ 623 ret = url_parse_hostport(buf, &proxy_hp, URL_DFLT_PROXY_PORT); 624 if (ret == URL_PARSE_SUCCESS) { 625 proxy_exists = B_TRUE; 626 } else { 627 bootlog("wanboot", BOOTLOG_CRIT, 628 "%s is not set to a valid hostport value", 629 BI_HTTP_PROXY); 630 return (-1); 631 } 632 is_proxy_init = B_TRUE; 633 } 634 635 http_set_p12_format(use_p12); 636 637 /* 638 * Initialize the handle that will be used for the request. 639 */ 640 *handlep = http_srv_init(url); 641 if (*handlep == NULL) { 642 print_errors("http_srv_init", NULL); 643 return (-1); 644 } 645 646 /* 647 * Is the request a secure one? If it is, then we need to do further 648 * setup. Search the wanboot file system for files that will be 649 * needed by SSL. 650 */ 651 if (url->https) { 652 char *cas; 653 boolean_t client_authentication = B_FALSE; 654 655 if (http_set_random_file(*handlep, "/dev/urandom") < 0) { 656 print_errors("http_set_random_file", *handlep); 657 (void) http_srv_close(*handlep); 658 return (-1); 659 } 660 661 /* 662 * We only need to initialize the CA once as it is not handle 663 * specific. 664 */ 665 if (!is_auth_file_init) { 666 if (http_set_certificate_authority_file(NB_CA_CERT_PATH) 667 < 0) { 668 print_errors( 669 "http_set_certificate_authority_file", 670 *handlep); 671 (void) http_srv_close(*handlep); 672 return (-1); 673 } 674 675 is_auth_file_init = B_TRUE; 676 } 677 678 /* 679 * The client certificate and key will not exist unless 680 * client authentication has been configured. If it is 681 * configured then the webserver will have added these 682 * files to the wanboot file system and the HTTP library 683 * needs to be made aware of their existence. 684 */ 685 if ((cas = bootconf_get(&bc_handle, 686 BC_CLIENT_AUTHENTICATION)) != NULL && 687 strcmp(cas, "yes") == 0) { 688 client_authentication = B_TRUE; 689 690 if (http_set_client_certificate_file(*handlep, 691 NB_CLIENT_CERT_PATH) < 0) { 692 print_errors("http_set_client_certificate_file", 693 *handlep); 694 (void) http_srv_close(*handlep); 695 return (-1); 696 } 697 698 if (http_set_private_key_file(*handlep, 699 NB_CLIENT_KEY_PATH) < 0) { 700 print_errors("http_set_private_key_file", 701 *handlep); 702 (void) http_srv_close(*handlep); 703 return (-1); 704 } 705 } 706 707 /* 708 * We do not really need to set this unless client 709 * authentication is configured or unless pkcs12 files 710 * are used. 711 */ 712 if ((client_authentication || use_p12) && 713 http_set_password(*handlep, WANBOOT_PASSPHRASE) < 0) { 714 print_errors("http_set_password", *handlep); 715 (void) http_srv_close(*handlep); 716 return (-1); 717 } 718 } 719 720 /* 721 * If the client is using a proxy, tell the library. 722 */ 723 if (proxy_exists) { 724 if (http_set_proxy(*handlep, &proxy_hp) != 0) { 725 print_errors("http_set_proxy", *handlep); 726 (void) http_srv_close(*handlep); 727 return (-1); 728 } 729 } 730 731 (void) http_set_socket_read_timeout(*handlep, SOCKET_READ_TIMEOUT); 732 733 /* 734 * Ok, connect to the webserver. 735 */ 736 if (http_srv_connect(*handlep) == -1) { 737 print_errors("http_srv_connect", *handlep); 738 (void) http_srv_close(*handlep); 739 return (1); 740 } 741 742 /* 743 * If the offset is 0, then we assume that we want the entire 744 * message. If the offset is not 0, then we assume that we are 745 * retrying a previously interrupted transfer and thus we make 746 * a range request. 747 */ 748 if (offset == 0) { 749 if ((ret = http_get_request(*handlep, url->abspath)) == 0) { 750 bootlog("wanboot", BOOTLOG_VERBOSE, 751 "%s: http_get_request: sent", what); 752 } else { 753 print_errors("http_get_request", *handlep); 754 (void) http_srv_close(*handlep); 755 return (1); 756 } 757 } else { 758 if ((ret = http_get_range_request(*handlep, url->abspath, 759 offset, 0)) == 0) { 760 bootlog("wanboot", BOOTLOG_VERBOSE, 761 "%s: http_get_range_request: sent", what); 762 } else { 763 print_errors("http_get_range_request", *handlep); 764 (void) http_srv_close(*handlep); 765 return (1); 766 } 767 } 768 769 /* 770 * Tell the library to read in the response headers. 771 */ 772 ret = http_process_headers(*handlep, &resp); 773 if (ret == -1) { 774 print_errors("http_process_headers", *handlep); 775 (void) http_srv_close(*handlep); 776 return (1); 777 } 778 779 /* 780 * Check for a valid response code. 781 */ 782 if ((offset == 0 && resp->code != 200) || 783 (offset != 0 && resp->code != 206)) { 784 bootlog("wanboot", BOOTLOG_ALERT, 785 "%s: Request returned code %d", what, resp->code); 786 if (resp->statusmsg != NULL && resp->statusmsg[0] != '\0') 787 bootlog("wanboot", BOOTLOG_ALERT, 788 "%s", resp->statusmsg); 789 http_free_respinfo(resp); 790 (void) http_srv_close(*handlep); 791 return (1); 792 } 793 http_free_respinfo(resp); 794 795 /* 796 * Success. 797 */ 798 return (0); 799 } 800 801 /* 802 * This routine is called by get_miniinfo() to receive the reply 803 * to the request for the miniroot metadata. The reply is a two 804 * part multipart message. The first part of the message contains 805 * the miniroot file size. The second part of the message contains 806 * a hash digest of the miniroot as computed by the server. This 807 * routine receives both message parts and returns them to the caller. 808 * 809 * Notes: 810 * If the miniroot is going to be downloaded securely or if the 811 * the server has no hash key for the client, then the hash digest 812 * downloaded contains all zeros. 813 * 814 * Any HTTP errors encountered in downloading or processing the message 815 * are not deemed unrecoverable errors. That is, get_miniinfo() 816 * tries re-requesting the message and tries processing it again. 817 * 818 * Returns: 819 * -1 = Non-recoverable error 820 * 0 = Success 821 * 1 = HTTP download error 822 */ 823 static int 824 process_miniinfo(http_handle_t handle, size_t *mini_size, 825 unsigned char *sdigest) 826 { 827 char *lenstr; 828 size_t cnt; 829 830 /* 831 * Process the file size header. 832 */ 833 if (http_process_part_headers(handle, NULL) != 0) { 834 print_errors("http_process_part_headers", handle); 835 return (1); 836 } 837 lenstr = http_get_header_value(handle, CONTENT_LENGTH); 838 if (lenstr == NULL) { 839 bootlog("wanboot", BOOTLOG_ALERT, "%s: error getting length " 840 "of first part of multipart message", MINIINFO); 841 return (1); 842 } 843 cnt = (size_t)strtol(lenstr, NULL, 10); 844 free(lenstr); 845 if (cnt == 0 || cnt >= sizeof (buffer)) { 846 bootlog("wanboot", BOOTLOG_ALERT, "%s: length of first part " 847 "of multipart message not a legal size", MINIINFO); 848 return (1); 849 } 850 851 if (read_bytes(handle, buffer, cnt) != 0) { 852 bootlog("wanboot", BOOTLOG_ALERT, 853 "%s: error reading miniroot size", MINIINFO); 854 return (1); 855 } 856 buffer[cnt] = '\0'; 857 858 *mini_size = (size_t)strtol(buffer, NULL, 10); 859 if (*mini_size == 0) { 860 bootlog("wanboot", BOOTLOG_ALERT, "%s: body of first part " 861 "of multipart message not a legal size", MINIINFO); 862 return (1); 863 } 864 865 return (read_digest(MINIINFO, handle, sdigest)); 866 } 867 868 /* 869 * This routine is called by get_miniroot() to retrieve the miniroot 870 * metadata (miniroot size and a hash digest). This routine sends an 871 * HTTP GET request to the webserver to request the download of the 872 * miniroot metadata and relies on process_miniinfo() to receive the 873 * reply, process it and ultimately return to it the miniroot size and 874 * the hash digest. 875 * 876 * Note: 877 * Any HTTP errors encountered in downloading or processing the message 878 * are not deemed unrecoverable errors. That is, get_miniinfo() should 879 * try re-requesting the message and try processing again. 880 * 881 * Returns: 882 * -1 = Non-recoverable error 883 * 0 = Success 884 */ 885 int 886 get_miniinfo(const url_t *server_url, size_t *mini_size, 887 unsigned char *sdigest) 888 { 889 http_handle_t handle; 890 url_t req_url; 891 int retry_cnt = 0; 892 int retry_max = WANBOOT_RETRY_MAX; 893 int ret; 894 895 /* 896 * Build the URL to request the miniroot info. 897 */ 898 if (build_request_url(&req_url, URLtype_miniroot, server_url) == -1) { 899 bootlog("wanboot", BOOTLOG_CRIT, 900 "Can't build the URL to make the %s request", 901 CGIcontent(URLtype_miniroot)); 902 return (-1); 903 } 904 905 /* 906 * Go get the miniroot info. If we fail reading the 907 * response we re-request the info in its entirety. 908 */ 909 bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading miniroot info"); 910 911 do { 912 if ((ret = establish_http_connection(MINIINFO, &handle, 913 &req_url, 0)) < 0) { 914 break; 915 } else if (ret > 0) { 916 if (wanboot_retry(++retry_cnt, retry_max)) { 917 continue; 918 } else { 919 break; 920 } 921 } 922 923 if ((ret = process_miniinfo(handle, mini_size, 924 sdigest)) > 0) { 925 if (!wanboot_retry(++retry_cnt, retry_max)) { 926 (void) http_srv_close(handle); 927 break; 928 } 929 } 930 931 (void) http_srv_close(handle); 932 933 } while (ret > 0); 934 935 /* 936 * Success. 937 */ 938 if (ret == 0) { 939 bootlog("wanboot", BOOTLOG_VERBOSE, 940 "Miniroot info download successful"); 941 return (0); 942 } else { 943 bootlog("wanboot", BOOTLOG_CRIT, 944 "Miniroot info download aborted"); 945 return (-1); 946 } 947 } 948 949 /* 950 * This routine is called by get_miniroot() to receive the reply to 951 * the request for the miniroot download. The miniroot is written 952 * to ramdisk as it is received and a hash digest is optionally computed 953 * as it does so. The miniroot is downloaded as one large message. 954 * Because the message is so large, this routine is prepared to deal 955 * with errors in the middle of download. If an error occurs during 956 * download, then this message processes all received data up to the 957 * point of the error and returns to get_miniroot() an error signifying 958 * that a download error has occurred. Presumably, get_miniroot() 959 * re-requests the remaining part of the miniroot not yet processed and 960 * calls this routine back to process the reply. When this routine 961 * returns succesfully, it returns a devpath to the ramdisk and the 962 * computed hash (if computed). 963 * 964 * Note: 965 * In order to facilitate reentry, the ramdisk is left open 966 * and the original miniroot_size and HMAC handle are kept 967 * static. 968 * 969 * Returns: 970 * -1 = Non-recoverable error 971 * 0 = Success 972 * 1 = HTTP download error 973 */ 974 static int 975 process_miniroot(http_handle_t handle, hash_type_t htype, 976 size_t length, char **devpath, off_t *offset, unsigned char *cdigest) 977 { 978 static SHA1_CTX sha; 979 static size_t miniroot_size; 980 static caddr_t miniroot_vaddr = NULL; 981 int ret; 982 983 if (miniroot_vaddr == NULL) { 984 if (htype == HASH_HMAC_SHA1) { 985 bootlog("wanboot", BOOTLOG_INFO, 986 "%s: Authentication will use HMAC-SHA1", MINIROOT); 987 HMACInit(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE); 988 } 989 990 miniroot_size = length; 991 992 miniroot_vaddr = create_ramdisk(RD_ROOTFS, miniroot_size, 993 devpath); 994 } 995 996 miniroot_vaddr += *offset; 997 998 if ((ret = write_msg_to_ramdisk(MINIROOT, miniroot_vaddr, handle, 999 miniroot_size, offset, (htype == HASH_NONE) ? NULL : &sha)) != 0) { 1000 return (ret); 1001 } 1002 1003 if (htype != HASH_NONE) { 1004 HMACFinal(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE, cdigest); 1005 } 1006 1007 return (0); 1008 } 1009 1010 /* 1011 * This routine retrieves the miniroot from the webserver. The miniroot 1012 * is retrieved in two steps. First a request is made to the server 1013 * to retrieve miniroot metadata (miniroot size and a hash digest). 1014 * The second request actually results in the download of the miniroot. 1015 * 1016 * This routine relies on get_miniinfo() to make and process 1017 * the request for the miniroot metadata and returns the 1018 * miniroot size and the hash digest of the miniroot as computed by 1019 * the server. 1020 * 1021 * If get_miniinfo() returns successfully, then this routine sends 1022 * an HTTP GET request to the webserver to request download of the 1023 * miniroot. This routine relies on process_miniroot() to receive 1024 * the reply, process it and ultimately return to it a device path to 1025 * a ramdisk containing the miniroot and a client computed hash digest. 1026 * This routine verifies that the client computed hash digest matches 1027 * the one retrieved by get_miniinfo(). 1028 * 1029 * If an error occurs in the transfer of the miniroot from the server 1030 * to the client, then the client re-requests the download of the 1031 * miniroot using a range request and only requests the part of the 1032 * miniroot not previously downloaded and written to ramdisk. The 1033 * process_miniroot() routine has the intelligence to recognize that 1034 * it is processing a range request. Errors not related to the actual 1035 * message download are deemed unrecoverable. 1036 * 1037 * Note: 1038 * If the client request for the miniroot is a secure request or 1039 * if the server is not configured with a hash key for the client, 1040 * then the hash digest downloaded from the server will contain 1041 * all zeros. This routine verifies that the server and client are 1042 * in-sync with respect to the need for hash verification. 1043 * 1044 * Returns: 1045 * -1 = Non-recoverable error 1046 * 0 = Success 1047 */ 1048 int 1049 get_miniroot(char **devpath) 1050 { 1051 http_handle_t handle; 1052 unsigned char cdigest[HMAC_DIGEST_LEN]; 1053 unsigned char sdigest[HMAC_DIGEST_LEN]; 1054 char *urlstr; 1055 url_t server_url; 1056 size_t mini_size; 1057 off_t offset; 1058 int plen; 1059 int retry_cnt = 0; 1060 int retry_max = WANBOOT_RETRY_ROOT_MAX; 1061 int ret; 1062 1063 /* 1064 * Get the miniroot URL. 1065 */ 1066 if ((urlstr = bootconf_get(&bc_handle, BC_ROOT_SERVER)) == NULL) { 1067 bootlog("wanboot", BOOTLOG_CRIT, 1068 "Missing root_server URL"); 1069 return (-1); 1070 } else if (url_parse(urlstr, &server_url) != URL_PARSE_SUCCESS) { 1071 bootlog("wanboot", BOOTLOG_CRIT, 1072 "Unable to parse URL %s", urlstr); 1073 return (-1); 1074 } 1075 1076 /* 1077 * We must get the miniroot info before we can request 1078 * the miniroot itself. 1079 */ 1080 if (get_miniinfo(&server_url, &mini_size, sdigest) != 0) { 1081 return (-1); 1082 } 1083 1084 plen = sizeof (server_url.abspath); 1085 if ((urlstr = bootconf_get(&bc_handle, BC_ROOT_FILE)) == NULL || 1086 strlcpy(server_url.abspath, urlstr, plen) >= plen) { 1087 bootlog("wanboot", BOOTLOG_CRIT, 1088 "Cannot retrieve the miniroot path"); 1089 return (-1); 1090 } 1091 1092 /* 1093 * Go get the miniroot. If we fail reading the response 1094 * then we re-request only the range we have yet to read, 1095 * unless the error was "unrecoverable" in which case we 1096 * re-request the entire file system. 1097 */ 1098 bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading miniroot"); 1099 1100 bzero(cdigest, sizeof (cdigest)); 1101 offset = 0; 1102 do { 1103 if ((ret = establish_http_connection(MINIROOT, &handle, 1104 &server_url, offset)) < 0) { 1105 break; 1106 } else if (ret > 0) { 1107 if (wanboot_retry(++retry_cnt, retry_max)) { 1108 continue; 1109 } else { 1110 break; 1111 } 1112 } 1113 1114 if ((ret = process_miniroot(handle, 1115 server_url.https ? HASH_NONE : hash_type, 1116 mini_size, devpath, &offset, cdigest)) > 0) { 1117 if (!wanboot_retry(++retry_cnt, retry_max)) { 1118 (void) http_srv_close(handle); 1119 break; 1120 } 1121 } 1122 1123 (void) http_srv_close(handle); 1124 1125 } while (ret > 0); 1126 1127 /* 1128 * Validate the computed digest against the one received. 1129 */ 1130 if (ret != 0 || !verify_digests(MINIROOT, cdigest, sdigest)) { 1131 bootlog("wanboot", BOOTLOG_CRIT, 1132 "Miniroot download aborted"); 1133 return (-1); 1134 } 1135 1136 bootlog("wanboot", BOOTLOG_VERBOSE, "Miniroot download successful"); 1137 return (0); 1138 } 1139 1140 /* 1141 * This routine is called to finish the decryption process. 1142 * Its purpose is to free the resources allocated by the 1143 * encryption init routines. 1144 */ 1145 static void 1146 encr_fini(encr_type_t etype, void *eh) 1147 { 1148 switch (etype) { 1149 case ENCR_3DES: 1150 des3_fini(eh); 1151 break; 1152 case ENCR_AES: 1153 aes_fini(eh); 1154 break; 1155 default: 1156 break; 1157 } 1158 } 1159 1160 /* 1161 * This routine is called by process_wanbootfs() to decrypt the encrypted 1162 * file system from ramdisk in place. The method of decryption 1163 * (algorithm) will have already been determined by process_wanbootfs() 1164 * and the cbc_handle passed to this routine will already have been 1165 * initialized appropriately. 1166 * 1167 * Returns: 1168 * -1 = Non-recoverable error 1169 * 0 = Success 1170 */ 1171 static int 1172 decrypt_wanbootfs(caddr_t addr, cbc_handle_t *ch, uint8_t *iv, 1173 size_t wanbootfs_size) 1174 { 1175 if (!cbc_decrypt(ch, (uint8_t *)addr, wanbootfs_size, iv)) { 1176 bootlog("wanboot", BOOTLOG_CRIT, 1177 "%s: cbc decrypt error", WANBOOTFS); 1178 return (-1); 1179 } 1180 return (0); 1181 } 1182 1183 /* 1184 * This routine is called by get_wanbootfs() to receive the reply to 1185 * the request for the wanboot file system. The reply is a multipart message. 1186 * The first part of the message is the file system (which may or may 1187 * not be encrypted). If encrypted, then the first block of the message 1188 * part is the CBC IV value used by the server to encrypt the remaining 1189 * part of the message part and is used by the client to decrypt it. The 1190 * second message part is a hash digest of the first part (the file 1191 * system) as computed by the server. If no hash key is configured 1192 * for the client, then the hash digest simply contains all zeros. This 1193 * routine receives both message parts. The file system is written to ramdisk 1194 * as it is received and simultaneously computes a hash digest (if a hash 1195 * key exists). Once the entire part is received, if the file system is 1196 * encrypted, it is read from ramdisk, decrypted and rewritten back to 1197 * ramdisk. The server computed hash digest is then read and along with the 1198 * ramdisk device path and the client computed hash digest is returned to the 1199 * caller. 1200 * 1201 * Notes: 1202 * In order to decrypt the file system and to compute the client 1203 * hash digest, an encryption key and a hash key is retrieved from 1204 * the PROM (or the wanboot interpreter). The non-existence of these 1205 * keys has implications on how the message response is processed and 1206 * it is assumed that the server is configured identically. 1207 * 1208 * Any HTTP errors encountered in downloading or processing the message 1209 * are not deemed unrecoverable errors. That is, get_wanbootfs() will 1210 * try re-requesting the message and will try processing it again. 1211 * 1212 * Returns: 1213 * -1 = Non-recoverable error 1214 * 0 = Success 1215 * 1 = HTTP download error 1216 */ 1217 static int 1218 process_wanbootfs(http_handle_t handle, char **devpath, 1219 unsigned char *cdigest, unsigned char *sdigest) 1220 { 1221 /* iv[] must be sized to store the largest possible encryption block */ 1222 uint8_t iv[WANBOOT_MAXBLOCKLEN]; 1223 cbc_handle_t ch; 1224 void *eh; 1225 SHA1_CTX sha; 1226 char *lenstr; 1227 size_t wanbootfs_size; 1228 size_t block_size; 1229 off_t offset; 1230 static caddr_t bootfs_vaddr = NULL; 1231 int ret; 1232 1233 switch (hash_type) { 1234 case HASH_HMAC_SHA1: 1235 bootlog("wanboot", BOOTLOG_INFO, 1236 "%s: Authentication will use HMAC-SHA1", WANBOOTFS); 1237 HMACInit(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE); 1238 break; 1239 case HASH_NONE: 1240 break; 1241 default: 1242 bootlog("wanboot", BOOTLOG_CRIT, 1243 "%s: unrecognized hash type", WANBOOTFS); 1244 return (-1); 1245 } 1246 1247 switch (encr_type) { 1248 case ENCR_3DES: 1249 bootlog("wanboot", 1250 BOOTLOG_INFO, "%s: Decryption will use 3DES", WANBOOTFS); 1251 if (des3_init(&eh) != 0) { 1252 return (-1); 1253 } 1254 block_size = DES3_BLOCK_SIZE; 1255 des3_key(eh, g_encr_key); 1256 cbc_makehandle(&ch, eh, DES3_KEY_SIZE, block_size, 1257 DES3_IV_SIZE, des3_encrypt, des3_decrypt); 1258 1259 break; 1260 case ENCR_AES: 1261 bootlog("wanboot", 1262 BOOTLOG_INFO, "%s: Decryption will use AES", WANBOOTFS); 1263 if (aes_init(&eh) != 0) { 1264 return (-1); 1265 } 1266 block_size = AES_BLOCK_SIZE; 1267 aes_key(eh, g_encr_key, AES_128_KEY_SIZE); 1268 cbc_makehandle(&ch, eh, AES_128_KEY_SIZE, block_size, 1269 AES_IV_SIZE, aes_encrypt, aes_decrypt); 1270 break; 1271 case ENCR_NONE: 1272 break; 1273 default: 1274 bootlog("wanboot", BOOTLOG_CRIT, 1275 "%s: unrecognized encryption type", WANBOOTFS); 1276 return (-1); 1277 } 1278 1279 /* 1280 * Process the header. 1281 */ 1282 if (http_process_part_headers(handle, NULL) != 0) { 1283 print_errors("http_process_part_headers", handle); 1284 return (1); 1285 } 1286 lenstr = http_get_header_value(handle, CONTENT_LENGTH); 1287 if (lenstr == NULL) { 1288 bootlog("wanboot", BOOTLOG_ALERT, "%s: error getting length " 1289 "of first part of multipart message", WANBOOTFS); 1290 return (1); 1291 } 1292 wanbootfs_size = (size_t)strtol(lenstr, NULL, 10); 1293 free(lenstr); 1294 if (wanbootfs_size == 0) { 1295 bootlog("wanboot", BOOTLOG_ALERT, "%s: length of first part " 1296 "of multipart message not a legal size", WANBOOTFS); 1297 return (1); 1298 } 1299 1300 /* 1301 * If encrypted, then read the iv. 1302 */ 1303 if (encr_type != ENCR_NONE) { 1304 if (read_bytes(handle, (char *)iv, block_size) != 0) { 1305 bootlog("wanboot", BOOTLOG_ALERT, 1306 "%s: error reading hash iv", WANBOOTFS); 1307 return (1); 1308 } 1309 wanbootfs_size -= block_size; 1310 if (hash_type != HASH_NONE) { 1311 HMACUpdate(&sha, (uchar_t *)iv, block_size); 1312 } 1313 } 1314 1315 /* 1316 * We can only create the ramdisk once. So, if we've 1317 * already created it, then it means we've re-entered 1318 * this routine from an earlier partial failure. Use 1319 * the already existing ramdisk and seek back to the 1320 * beginning of the file. 1321 */ 1322 if (bootfs_vaddr == NULL) { 1323 bootfs_vaddr = create_ramdisk(RD_BOOTFS, wanbootfs_size, 1324 devpath); 1325 } 1326 1327 offset = 0; 1328 1329 if ((ret = write_msg_to_ramdisk(WANBOOTFS, bootfs_vaddr, handle, 1330 wanbootfs_size, &offset, (hash_type == HASH_NONE) ? NULL : &sha)) 1331 != 0) { 1332 return (ret); 1333 } 1334 1335 if (hash_type != HASH_NONE) { 1336 HMACFinal(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE, cdigest); 1337 } 1338 1339 /* 1340 * If encrypted, then decrypt it. 1341 */ 1342 if (encr_type != ENCR_NONE) { 1343 ret = decrypt_wanbootfs(bootfs_vaddr, &ch, iv, wanbootfs_size); 1344 if (ret != 0) { 1345 encr_fini(encr_type, eh); 1346 return (-1); 1347 } 1348 encr_fini(encr_type, eh); 1349 } 1350 1351 return (read_digest(WANBOOTFS, handle, sdigest)); 1352 } 1353 1354 /* 1355 * This routine sends an HTTP GET request to the webserver to 1356 * request the wanboot file system for the client. The server 1357 * will reply by sending a multipart message. This routine will rely 1358 * on process_wanbootfs() to receive the multipart message, process it 1359 * and ultimately return to it a device path to a ramdisk containing 1360 * the wanboot file system, a client computed hash digest and a 1361 * server computed hash digest. This routine will verify that the 1362 * client computed hash digest matches the one sent by the server. This 1363 * routine will also verify that the nonce received in the reply matches 1364 * the one sent in the request. 1365 * 1366 * If an error occurs in the transfer of the message from the server 1367 * to the client, then the client re-requests the download in its 1368 * entirety. Errors not related to the actual message download are 1369 * deemed unrecoverable. 1370 * 1371 * Returns: 1372 * -1 = Non-recoverable error 1373 * 0 = Success 1374 */ 1375 int 1376 get_wanbootfs(const url_t *server_url) 1377 { 1378 http_handle_t handle; 1379 unsigned char cdigest[HMAC_DIGEST_LEN]; 1380 unsigned char sdigest[HMAC_DIGEST_LEN]; 1381 url_t req_url; 1382 char *devpath; 1383 int ret; 1384 int fd; 1385 char buf[NONCELEN + 1]; 1386 int retry_cnt = 0; 1387 int retry_max = WANBOOT_RETRY_MAX; 1388 1389 /* 1390 * Build the URL to request the wanboot file system. This URL 1391 * will include the CGI script name and the IP, CID, and 1392 * NONCE parameters. 1393 */ 1394 if (build_request_url(&req_url, URLtype_wanbootfs, server_url) == -1) { 1395 bootlog("wanboot", BOOTLOG_CRIT, 1396 "Can't build the URL to make the %s request", 1397 CGIcontent(URLtype_wanbootfs)); 1398 return (-1); 1399 } 1400 1401 /* 1402 * Go get the wanboot file system. If we fail reading the 1403 * response we re-request the entire file system. 1404 */ 1405 bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading wanboot file system"); 1406 1407 bzero(cdigest, sizeof (cdigest)); 1408 do { 1409 if ((ret = establish_http_connection(WANBOOTFS, &handle, 1410 &req_url, 0)) < 0) { 1411 break; 1412 } else if (ret > 0) { 1413 if (wanboot_retry(++retry_cnt, retry_max)) { 1414 continue; 1415 } else { 1416 break; 1417 } 1418 } 1419 1420 if ((ret = process_wanbootfs(handle, &devpath, 1421 cdigest, sdigest)) > 0) { 1422 if (!wanboot_retry(++retry_cnt, retry_max)) { 1423 (void) http_srv_close(handle); 1424 break; 1425 } 1426 } 1427 1428 (void) http_srv_close(handle); 1429 1430 } while (ret > 0); 1431 1432 /* 1433 * Validate the computed digest against the one received. 1434 */ 1435 if (ret != 0 || 1436 !verify_digests(WANBOOTFS, cdigest, sdigest)) { 1437 bootlog("wanboot", BOOTLOG_CRIT, 1438 "The wanboot file system download aborted"); 1439 return (-1); 1440 } 1441 1442 /* 1443 * Mount the wanboot file system. 1444 */ 1445 if (determine_fstype_and_mountroot(devpath) != VFS_SUCCESS) { 1446 bootlog("wanboot", BOOTLOG_CRIT, 1447 "Could not mount the wanboot filesystem."); 1448 bootlog("wanboot", BOOTLOG_CRIT, 1449 "This may signify a client/server key mismatch"); 1450 if (encr_type != ENCR_NONE) { 1451 bootlog("wanboot", BOOTLOG_CRIT, 1452 "(client has key but wrong encryption_type?)"); 1453 } else { 1454 bootlog("wanboot", BOOTLOG_CRIT, 1455 "(encryption_type specified but no client key?)"); 1456 } 1457 return (-1); 1458 } 1459 bootlog("wanboot", BOOTLOG_VERBOSE, 1460 "The wanboot file system has been mounted"); 1461 1462 /* 1463 * The wanboot file system should contain a nonce. Read it 1464 * and compare it against the nonce sent in the request. 1465 */ 1466 if ((fd = open(WANBOOTFS_NONCE_FILE, O_RDONLY)) == -1) { 1467 bootlog("wanboot", BOOTLOG_CRIT, 1468 "No nonce found in the wanboot file system"); 1469 bootlog("wanboot", BOOTLOG_CRIT, 1470 "The wanboot file system download aborted"); 1471 return (-1); 1472 } 1473 1474 if (read(fd, buf, NONCELEN) != NONCELEN || 1475 bcmp(nonce, buf, NONCELEN) != 0) { 1476 (void) close(fd); 1477 bootlog("wanboot", BOOTLOG_CRIT, 1478 "Invalid nonce found in the wanboot file system"); 1479 bootlog("wanboot", BOOTLOG_CRIT, 1480 "The wanboot file system download aborted"); 1481 return (-1); 1482 } 1483 1484 (void) close(fd); 1485 1486 bootlog("wanboot", BOOTLOG_VERBOSE, 1487 "The wanboot file system download was successful"); 1488 return (0); 1489 } 1490 1491 static boolean_t 1492 init_netdev(char *bpath) 1493 { 1494 pnode_t anode; 1495 int proplen; 1496 char netalias[OBP_MAXPATHLEN]; 1497 static char devpath[OBP_MAXPATHLEN]; 1498 char *p; 1499 1500 bzero(netalias, sizeof (netalias)); 1501 bzero(devpath, sizeof (devpath)); 1502 1503 /* 1504 * Wanboot will either have loaded over the network (in which case 1505 * bpath will name a network device), or from CD-ROM or disk. In 1506 * either case ensure that the 'net' alias corresponds to a network 1507 * device, and that if a network boot was performed that it is 1508 * identical to bpath. This is so that the interface name can always 1509 * be determined for CD-ROM or disk boots, and for manually-configured 1510 * network boots. The latter restriction may be relaxed in the future. 1511 */ 1512 anode = prom_alias_node(); 1513 if ((proplen = prom_getproplen(anode, "net")) <= 0 || 1514 proplen > sizeof (netalias)) { 1515 goto error; 1516 } 1517 (void) prom_getprop(anode, "net", (caddr_t)netalias); 1518 1519 /* 1520 * Strip boot arguments from the net device to form 1521 * the boot device path, returned as netdev_path. 1522 */ 1523 if (strlcpy(devpath, netalias, sizeof (devpath)) >= sizeof (devpath)) 1524 goto error; 1525 if ((p = strchr(devpath, ':')) != NULL) { 1526 *p = '\0'; 1527 } 1528 1529 if (!is_netdev(netalias)) { 1530 bootlog("wanboot", BOOTLOG_CRIT, "'net'=%s\n", netalias); 1531 goto error; 1532 } 1533 1534 if (is_netdev(bpath)) { 1535 /* 1536 * If bpath is a network device path, then v2path 1537 * will be a copy of this sans device arguments. 1538 */ 1539 if (strcmp(v2path, devpath) != 0) { 1540 bootlog("wanboot", BOOTLOG_CRIT, 1541 "'net'=%s\n", netalias); 1542 bootlog("wanboot", BOOTLOG_CRIT, 1543 "wanboot requires that the 'net' alias refers to "); 1544 bootlog("wanboot", BOOTLOG_CRIT, 1545 "the network device path from which it loaded"); 1546 return (B_FALSE); 1547 } 1548 } else { 1549 bpath = netalias; 1550 } 1551 1552 /* 1553 * Configure the network and return the network device. 1554 */ 1555 bootlog("wanboot", BOOTLOG_INFO, "configuring %s\n", bpath); 1556 netdev_path = devpath; 1557 mac_init(bpath); 1558 return (B_TRUE); 1559 1560 error: 1561 /* 1562 * If we haven't established a device path for a network interface, 1563 * then we're doomed. 1564 */ 1565 bootlog("wanboot", BOOTLOG_CRIT, 1566 "No network device available for wanboot!"); 1567 bootlog("wanboot", BOOTLOG_CRIT, 1568 "(Ensure that the 'net' alias is set correctly)"); 1569 return (B_FALSE); 1570 } 1571 1572 /* 1573 * This implementation of bootprog() is used solely by wanboot. 1574 * 1575 * The basic algorithm is as follows: 1576 * 1577 * - The wanboot options (those specified using the "-o" flag) are processed, 1578 * and if necessary the wanboot interpreter is invoked to collect other 1579 * options. 1580 * 1581 * - The wanboot filesystem (containing certificates, wanboot.conf file, etc.) 1582 * is then downloaded into the bootfs ramdisk, which is mounted for use 1583 * by OpenSSL, access to wanboot.conf, etc. 1584 * 1585 * - The wanboot miniroot is downloaded over http/https into the rootfs 1586 * ramdisk. The bootfs filesystem is unmounted, and the rootfs filesystem 1587 * is booted. 1588 */ 1589 /*ARGSUSED*/ 1590 int 1591 bootprog(char *bpath, char *bargs, boolean_t user_specified_filename) 1592 { 1593 char *miniroot_path; 1594 url_t server_url; 1595 int ret; 1596 1597 if (!init_netdev(bpath)) { 1598 return (-1); 1599 } 1600 1601 if (!bootinfo_init()) { 1602 bootlog("wanboot", BOOTLOG_CRIT, "Cannot initialize bootinfo"); 1603 return (-1); 1604 } 1605 1606 /* 1607 * Get default values from PROM, etc., process any boot arguments 1608 * (specified with the "-o" option), and initialize the interface. 1609 */ 1610 if (!wanboot_init_interface(wanboot_arguments)) { 1611 return (-1); 1612 } 1613 1614 /* 1615 * Determine which encryption and hashing algorithms the client 1616 * is configured to use. 1617 */ 1618 init_encryption(); 1619 init_hashing(); 1620 1621 /* 1622 * Get the bootserver value. Should be of the form: 1623 * http://host[:port]/abspath. 1624 */ 1625 ret = get_url(BI_BOOTSERVER, &server_url); 1626 if (ret != 0) { 1627 bootlog("wanboot", BOOTLOG_CRIT, 1628 "Unable to retrieve the bootserver URL"); 1629 return (-1); 1630 } 1631 1632 /* 1633 * Get the wanboot file system and mount it. Contains metdata 1634 * needed by wanboot. 1635 */ 1636 if (get_wanbootfs(&server_url) != 0) { 1637 return (-1); 1638 } 1639 1640 /* 1641 * Check that there is a valid wanboot.conf file in the wanboot 1642 * file system. 1643 */ 1644 if (bootconf_init(&bc_handle, NULL) != BC_E_NOERROR) { 1645 bootlog("wanboot", BOOTLOG_CRIT, 1646 "wanboot.conf error (code=%d)", bc_handle.bc_error_code); 1647 return (-1); 1648 } 1649 1650 /* 1651 * Set the time 1652 */ 1653 init_boot_time(); 1654 1655 /* 1656 * Verify that URLs in wanboot.conf can be reached, etc. 1657 */ 1658 if (!wanboot_verify_config()) { 1659 return (-1); 1660 } 1661 1662 /* 1663 * Retrieve the miniroot. 1664 */ 1665 if (get_miniroot(&miniroot_path) != 0) { 1666 return (-1); 1667 } 1668 1669 /* 1670 * We don't need the wanboot file system mounted anymore and 1671 * should unmount it so that we can mount the miniroot. 1672 */ 1673 (void) unmountroot(); 1674 1675 boot_ramdisk(RD_ROOTFS); 1676 1677 return (0); 1678 } 1679