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