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.
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.
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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
35 #include <libnvpair.h>
36 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/sysmacros.h>
42 #include <sys/socket.h>
43 #include <sys/utsname.h>
44 #include <sys/wanboot_impl.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
48 #include <openssl/crypto.h>
49 #include <openssl/x509.h>
50 #include <openssl/x509v3.h>
51 #include <openssl/pem.h>
52 #include <openssl/pkcs12.h>
53 #include <openssl/evp.h>
54 #include <openssl/err.h>
60 * These can be replaced with wanbootutil.h once the openssl interfaces
61 * are moved to libwanboot.
63 #include <wanboot/key_util.h>
64 #include <wanboot/key_xdr.h>
65 #include <hmac_sha1.h>
67 #include <netboot_paths.h>
68 #include <wanboot_conf.h>
73 #define WBCGI_STATUS_OK 0
74 #define WBCGI_STATUS_ERR 1
76 #define WBCGI_FILE_EXISTS(file, statbuf) \
77 (stat(file, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
79 #define WBCGI_DIR_EXISTS(dir, statbuf) \
80 (stat(dir, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
82 #define WBCGI_HMAC_PATH "/usr/lib/inet/wanboot/hmac"
83 #define WBCGI_ENCR_PATH "/usr/lib/inet/wanboot/encr"
84 #define WBCGI_KEYMGMT_PATH "/usr/lib/inet/wanboot/keymgmt"
85 #define WBCGI_MKISOFS_PATH "/bin/mkisofs"
87 #define WBCGI_DEV_URANDOM "/dev/urandom"
89 #define WBCGI_CONTENT_TYPE "Content-Type: "
90 #define WBCGI_CONTENT_LENGTH "Content-Length: "
91 #define WBCGI_WANBOOT_BNDTXT "WANBoot_Part_Boundary"
92 #define WBCGI_CRNL "\r\n"
94 #define WBCGI_CNSTR "CN="
95 #define WBCGI_CNSTR_LEN (sizeof (WBCGI_CNSTR) - 1)
96 #define WBCGI_NAMESEP ",/\n\r"
98 #define WBCGI_MAXBUF 256
101 * Possible return values from netboot_ftw():
103 #define WBCGI_FTW_CBOK 2 /* CB terminated walk OK */
104 #define WBCGI_FTW_CBCONT 1 /* CB wants walk should continue */
105 #define WBCGI_FTW_DONE 0 /* Walk terminated without CBERR/CBOK */
106 #define WBCGI_FTW_CBERR -1 /* CB terminated walk with err */
109 * getsubopt() is used to map one of the contents[] keywords
110 * to one of these types
112 #define WBCGI_CONTENT_ERROR -1
113 #define WBCGI_CONTENT_BOOTFILE 0
114 #define WBCGI_CONTENT_BOOTFS 1
115 #define WBCGI_CONTENT_ROOTFS 2
117 static char *contents
[] =
118 { "bootfile", "bootfs", "rootfs", NULL
};
121 * getsubopt() is used to parse the query string for
122 * the keywords defined by queryopts[]
124 #define WBCGI_QUERYOPT_CONTENT 0
125 #define WBCGI_QUERYOPT_NET 1
126 #define WBCGI_QUERYOPT_CID 2
127 #define WBCGI_QUERYOPT_NONCE 3
129 static char *queryopts
[] =
130 { "CONTENT", "IP", "CID", "NONCE", NULL
};
132 static bc_handle_t bc_handle
;
136 status_msg(int status
)
148 msg
= "Internal Server Error";
151 msg
= "Unknown status";
159 print_status(int status
, const char *spec_msg
)
161 if (spec_msg
== NULL
) {
165 (void) fprintf(stdout
, "Status: %d %s %s%s", status
,
166 status_msg(status
), spec_msg
, WBCGI_CRNL
);
170 make_path(const char *root
, const char *suffix
)
172 char path
[MAXPATHLEN
];
176 if ((chars
= snprintf(path
, sizeof (path
),
177 "%s/%s", root
, suffix
)) < 0 || chars
> sizeof (path
) ||
178 (ptr
= strdup(path
)) == NULL
) {
179 print_status(500, "(error making path)");
186 free_path(char **pathp
)
188 if (*pathp
!= NULL
) {
195 gen_tmppath(const char *prefix
, const char *net
, const char *cid
)
200 char path
[MAXPATHLEN
];
203 if ((pid
= getpid()) < 0 || (secs
= time(NULL
)) < 0 ||
204 (chars
= snprintf(path
, sizeof (path
), "/tmp/%s_%s_%s_%ld_%ld",
205 prefix
, net
, cid
, pid
, secs
)) < 0 || chars
> sizeof (path
) ||
206 (ptr
= strdup(path
)) == NULL
) {
207 print_status(500, "(error creating temporary filename)");
217 write_buffer(int fd
, const void *buffer
, size_t buflen
)
221 const char *buf
= buffer
;
223 for (nwritten
= 0; nwritten
< buflen
; nwritten
+= nbytes
) {
224 nbytes
= write(fd
, &buf
[nwritten
], buflen
- nwritten
);
234 write_file(int ofd
, const char *filename
, size_t size
)
236 boolean_t ret
= B_TRUE
;
242 if ((ifd
= open(filename
, O_RDONLY
)) < 0) {
246 for (; size
!= 0; size
-= wlen
) {
247 rlen
= (size
< sizeof (buf
)) ? size
: sizeof (buf
);
249 if ((wlen
= read(ifd
, buf
, rlen
)) < 0 ||
250 !write_buffer(ofd
, buf
, wlen
)) {
261 copy_file(const char *src
, const char *dest
)
263 boolean_t ret
= B_FALSE
;
264 char message
[WBCGI_MAXBUF
];
265 const size_t chunksize
= 16 * PAGESIZE
;
270 int mflags
= MAP_PRIVATE
;
277 if ((rfd
= open(src
, O_RDONLY
)) < 0 ||
278 (wfd
= open(dest
, O_CREAT
|O_EXCL
|O_RDWR
, S_IRUSR
|S_IWUSR
)) < 0 ||
279 fstat(rfd
, &st
) == -1) {
283 for (nbytes
= st
.st_size
, roff
= 0; nwritten
< nbytes
;
284 nwritten
+= validsize
, roff
+= validsize
) {
285 buf
= mmap(buf
, chunksize
, PROT_READ
, mflags
, rfd
, roff
);
286 if (buf
== MAP_FAILED
) {
291 validsize
= MIN(chunksize
, nbytes
- nwritten
);
292 if (!write_buffer(wfd
, buf
, validsize
)) {
293 (void) munmap(buf
, chunksize
);
299 (void) munmap(buf
, chunksize
);
304 if (ret
== B_FALSE
) {
305 if ((chars
= snprintf(message
, sizeof (message
),
306 "error copying %s to %s", src
, dest
)) > 0 &&
307 chars
<= sizeof (message
)) {
308 print_status(500, message
);
310 print_status(500, NULL
);
324 create_nonce(const char *noncepath
, const char *nonce
)
326 boolean_t ret
= B_TRUE
;
329 if ((fd
= open(noncepath
,
330 O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
331 !write_buffer(fd
, nonce
, strlen(nonce
))) {
332 print_status(500, "(error creating nonce file)");
343 create_timestamp(const char *timestamppath
, const char *timestamp
)
345 boolean_t ret
= B_TRUE
;
348 if ((fd
= open(timestamppath
,
349 O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
350 !write_buffer(fd
, timestamp
, strlen(timestamp
))) {
351 print_status(500, "(error creating timestamp file)");
362 create_urandom(const char *urandompath
)
364 boolean_t ret
= B_TRUE
;
367 if ((fd
= open(urandompath
,
368 O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
369 !write_file(fd
, WBCGI_DEV_URANDOM
, 32 * 1024)) {
370 print_status(500, "(error creating urandom file)");
381 create_null_hash(const char *hashpath
)
383 boolean_t ret
= B_TRUE
;
385 static char null_hash
[HMAC_DIGEST_LEN
];
387 if ((fd
= open(hashpath
,
388 O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
389 !write_buffer(fd
, null_hash
, sizeof (null_hash
))) {
390 print_status(500, "(error creating null hash)");
402 determine_doc_root(void)
407 * If DOCUMENT_ROOT is valid, use that.
409 if ((doc_root
= getenv("DOCUMENT_ROOT")) == NULL
||
410 strlen(doc_root
) == 0) {
412 * No DOCUMENT_ROOT - try PATH_TRANSLATED.
414 if ((doc_root
= getenv("PATH_TRANSLATED")) == NULL
||
415 strlen(doc_root
) == 0) {
417 * Can't determine the document root.
427 get_request_info(int *contentp
, char **netp
, char **cidp
, char **noncep
,
436 if ((method
= getenv("REQUEST_METHOD")) == NULL
||
437 strncasecmp(method
, "GET", strlen("GET") != 0)) {
438 print_status(403, "(GET method expected)");
442 if ((query_string
= getenv("QUERY_STRING")) == NULL
) {
443 print_status(400, "(empty query string)");
447 for (i
= 0; i
< strlen(query_string
); i
++) {
448 if (query_string
[i
] == '&') {
449 query_string
[i
] = ',';
453 *contentp
= WBCGI_CONTENT_ERROR
;
454 *netp
= *cidp
= *noncep
= NULL
;
456 if ((*docrootp
= determine_doc_root()) == NULL
) {
457 print_status(400, "(unable to determine document root)");
461 while (*query_string
!= '\0') {
462 switch (getsubopt(&query_string
, queryopts
, &value
)) {
463 case WBCGI_QUERYOPT_CONTENT
:
464 *contentp
= getsubopt(&value
, contents
, &junk
);
466 case WBCGI_QUERYOPT_NET
:
469 case WBCGI_QUERYOPT_CID
:
472 case WBCGI_QUERYOPT_NONCE
:
476 print_status(400, "(illegal query string)");
483 print_status(400, "(missing or illegal CONTENT)");
486 case WBCGI_CONTENT_BOOTFS
:
487 if (*netp
== NULL
|| *cidp
== NULL
|| *noncep
== NULL
) {
489 "(CONTENT, IP, CID and NONCE required)");
494 case WBCGI_CONTENT_BOOTFILE
:
495 case WBCGI_CONTENT_ROOTFS
:
496 if (*netp
== NULL
|| *cidp
== NULL
|| *docrootp
== NULL
) {
498 "(CONTENT, IP, CID and DOCUMENT_ROOT required)");
508 encrypt_payload(const char *payload
, const char *encr_payload
,
509 const char *keyfile
, const char *encryption_type
)
513 char cmd
[MAXPATHLEN
];
516 char msg
[WBCGI_MAXBUF
];
518 if (!WBCGI_FILE_EXISTS(payload
, sbuf
)) {
519 print_status(500, "(encrypt_payload: missing payload)");
523 if ((chars
= snprintf(cmd
, sizeof (cmd
),
524 "%s -o type=%s -k %s < %s > %s", WBCGI_ENCR_PATH
,
525 encryption_type
, keyfile
, payload
, encr_payload
)) < 0 ||
526 chars
> sizeof (cmd
)) {
527 print_status(500, "(encrypt_payload: buffer overflow)");
531 if ((fp
= popen(cmd
, "w")) == NULL
) {
532 print_status(500, "(encrypt_payload: missing/file error)");
535 if ((status
= WEXITSTATUS(pclose(fp
))) != 0) {
536 (void) snprintf(msg
, sizeof (msg
),
537 "(encrypt_payload: failed, status=%d)", status
);
538 print_status(500, msg
);
542 if (!WBCGI_FILE_EXISTS(encr_payload
, sbuf
)) {
543 print_status(500, "(encrypt_payload: bad encrypted file)");
551 hash_payload(const char *payload
, const char *payload_hash
,
556 char cmd
[MAXPATHLEN
];
559 char msg
[WBCGI_MAXBUF
];
561 if (!WBCGI_FILE_EXISTS(payload
, sbuf
)) {
562 print_status(500, "(hash_payload: missing payload)");
566 if ((chars
= snprintf(cmd
, sizeof (cmd
), "%s -i %s -k %s > %s",
567 WBCGI_HMAC_PATH
, payload
, keyfile
, payload_hash
)) < 0 ||
568 chars
> sizeof (cmd
)) {
569 print_status(500, "(hash_payload: buffer overflow)");
573 if ((fp
= popen(cmd
, "w")) == NULL
) {
574 print_status(500, "(hash_payload: missing/file error)");
577 if ((status
= WEXITSTATUS(pclose(fp
))) != 0) {
578 (void) snprintf(msg
, sizeof (msg
),
579 "(hash_payload: failed, status=%d)", status
);
580 print_status(500, msg
);
584 if (!WBCGI_FILE_EXISTS(payload_hash
, sbuf
) ||
585 sbuf
.st_size
< HMAC_DIGEST_LEN
) {
586 print_status(500, "(hash_payload: bad signature file)");
594 extract_keystore(const char *path
, const char *keystorepath
)
598 char cmd
[MAXPATHLEN
];
601 char msg
[WBCGI_MAXBUF
];
603 if (!WBCGI_FILE_EXISTS(path
, sbuf
)) {
604 print_status(500, "(extract_keystore: missing keystore)");
608 if ((chars
= snprintf(cmd
, sizeof (cmd
),
609 "%s -x -f %s -s %s -o type=rsa",
610 WBCGI_KEYMGMT_PATH
, keystorepath
, path
)) < 0 ||
611 chars
> sizeof (cmd
)) {
612 print_status(500, "(extract_keystore: buffer overflow)");
616 if ((fp
= popen(cmd
, "w")) == NULL
) {
617 print_status(500, "(extract_keystore: missing/file error)");
620 if ((status
= WEXITSTATUS(pclose(fp
))) != 0) {
621 (void) snprintf(msg
, sizeof (msg
),
622 "(extract_keystore: failed, status=%d)", status
);
623 print_status(500, msg
);
627 if (!WBCGI_FILE_EXISTS(keystorepath
, sbuf
)) {
628 print_status(500, "(extract_keystore: failed to create)");
636 mkisofs(const char *image_dir
, const char *image
)
640 char cmd
[MAXPATHLEN
];
643 char msg
[WBCGI_MAXBUF
];
645 if (!WBCGI_DIR_EXISTS(image_dir
, sbuf
)) {
646 print_status(500, "(mksiofs: missing image_dir)");
650 if ((chars
= snprintf(cmd
, sizeof (cmd
), "%s -quiet -o %s -r %s",
651 WBCGI_MKISOFS_PATH
, image
, image_dir
)) < 0 ||
652 chars
> sizeof (cmd
)) {
653 print_status(500, "(mkisofs: buffer overflow)");
657 if ((fp
= popen(cmd
, "w")) == NULL
) {
658 print_status(500, "(mkisofs: missing/file error)");
661 if ((status
= WEXITSTATUS(pclose(fp
))) != 0) {
662 (void) snprintf(msg
, sizeof (msg
),
663 "(mkisofs: failed, status=%d)", status
);
664 print_status(500, msg
);
668 if (!WBCGI_FILE_EXISTS(image
, sbuf
)) {
669 print_status(500, "(mksiofs: failed to create image)");
677 * This function, when invoked with a file name, optional network and
678 * client ID strings, and callback function will search for the file
679 * in the following locations:
681 * NB_NETBOOT_ROOT/<network>/<client id>/<file>
682 * NB_NETBOOT_ROOT/<client id>/<file>
683 * NB_NETBOOT_ROOT/<network>/<file>
684 * NB_NETBOOT_ROOT/<file>
686 * The callback function is invoked each time the file is found until
687 * we have searched all of the above locations or the callback function
688 * returns a value other than WBCGI_FTW_CBCONT.
691 * filename - Name of file to search for.
692 * net - Optional network number to include in search hierarchy.
693 * cid - Optional client ID to include in search hierarchy.
694 * cb - Callback function to be called when file is found.
695 * arg - Argument to be supplied to the callback funtion.
698 * WBCGI_FTW_DONE, WBCGI_FTW_CBOK or WBCGI_FTW_CBERR.
701 netboot_ftw(const char *filename
, const char *net
, const char *cid
,
702 int (*cb
)(const char *, void *arg
), void *arg
)
704 char ckpath
[4][MAXPATHLEN
];
709 if (snprintf(ckpath
[i
++], MAXPATHLEN
, "%s%s", NB_NETBOOT_ROOT
, filename
)
711 return (WBCGI_FTW_CBERR
);
713 if (net
!= NULL
&& snprintf(ckpath
[i
++], MAXPATHLEN
, "%s%s/%s",
714 NB_NETBOOT_ROOT
, net
, filename
) >= MAXPATHLEN
)
715 return (WBCGI_FTW_CBERR
);
718 if (snprintf(ckpath
[i
++], MAXPATHLEN
, "%s%s/%s",
719 NB_NETBOOT_ROOT
, cid
, filename
) >= MAXPATHLEN
)
720 return (WBCGI_FTW_CBERR
);
722 if (net
!= NULL
&& snprintf(ckpath
[i
++], MAXPATHLEN
,
723 "%s%s/%s/%s", NB_NETBOOT_ROOT
, net
, cid
, filename
) >=
725 return (WBCGI_FTW_CBERR
);
729 * Loop through hierarchy and check for file existence.
733 if (WBCGI_FILE_EXISTS(ckpath
[i
], buf
)) {
734 if ((ret
= cb(ckpath
[i
], arg
)) != WBCGI_FTW_CBCONT
)
738 return (WBCGI_FTW_DONE
);
743 noact_cb(const char *path
, void *arg
)
745 return (WBCGI_FTW_CBOK
);
749 set_pathname(const char *path
, void *pathname
)
751 *(char **)pathname
= strdup((char *)path
);
752 return (WBCGI_FTW_CBOK
);
756 create_keystore(const char *path
, void *keystorepath
)
758 if (!extract_keystore(path
, (char *)keystorepath
)) {
759 return (WBCGI_FTW_CBERR
);
761 return (WBCGI_FTW_CBOK
);
765 copy_certstore(const char *path
, void *certstorepath
)
767 if (!copy_file(path
, (char *)certstorepath
)) {
768 return (WBCGI_FTW_CBERR
);
770 return (WBCGI_FTW_CBOK
);
774 * Add the certs found in the trustfile found in path (a trust store) to
775 * the file found at bootfs_dir/truststore. If necessary, create the
779 build_trustfile(const char *path
, void *truststorepath
)
781 int ret
= WBCGI_FTW_CBERR
;
782 STACK_OF(X509
) *i_anchors
= NULL
;
783 STACK_OF(X509
) *o_anchors
= NULL
;
784 char message
[WBCGI_MAXBUF
];
796 if (!WBCGI_FILE_EXISTS(path
, i_st
)) {
800 if (WBCGI_FILE_EXISTS((char *)truststorepath
, o_st
)) {
802 * If we are inadvertantly writing to the input file.
804 * XXX Pete: how can this happen, and why success?
806 if (i_st
.st_ino
== o_st
.st_ino
) {
807 ret
= WBCGI_FTW_CBCONT
;
810 if ((wfp
= fopen((char *)truststorepath
, "r+")) == NULL
) {
814 * Read what's already there, so that new information
817 if ((p12
= d2i_PKCS12_fp(wfp
, NULL
)) == NULL
) {
821 i
= sunw_PKCS12_parse(p12
, WANBOOT_PASSPHRASE
, DO_NONE
, NULL
,
822 0, NULL
, NULL
, NULL
, &o_anchors
);
831 if (errno
!= ENOENT
) {
832 chars
= snprintf(message
, sizeof (message
),
833 "(error accessing file %s, error %s)",
834 path
, strerror(errno
));
835 if (chars
> 0 && chars
< sizeof (message
))
836 print_status(500, message
);
838 print_status(500, NULL
);
839 return (WBCGI_FTW_CBERR
);
843 * Note: We could copy the file to the new trustfile, but
844 * we can't verify the password that way. Therefore, copy
847 if ((wfd
= open((char *)truststorepath
,
848 O_CREAT
|O_EXCL
|O_RDWR
, 0700)) < 0) {
851 if ((wfp
= fdopen(wfd
, "w+")) == NULL
) {
854 o_anchors
= sk_X509_new_null();
855 if (o_anchors
== NULL
) {
860 if ((rfp
= fopen(path
, "r")) == NULL
) {
863 if ((p12
= d2i_PKCS12_fp(rfp
, NULL
)) == NULL
) {
867 i
= sunw_PKCS12_parse(p12
, WANBOOT_PASSPHRASE
, DO_NONE
, NULL
, 0, NULL
,
868 NULL
, NULL
, &i_anchors
);
877 * Merge the two stacks of pkcs12 certs.
879 for (i
= 0; i
< sk_X509_num(i_anchors
); i
++) {
881 x
= sk_X509_delete(i_anchors
, i
);
882 (void) sk_X509_push(o_anchors
, x
);
886 * Create the pkcs12 structure from the modified input stack and
887 * then write out that structure.
889 p12
= sunw_PKCS12_create((const char *)WANBOOT_PASSPHRASE
, NULL
, NULL
,
895 if (i2d_PKCS12_fp(wfp
, p12
) == 0) {
899 ret
= WBCGI_FTW_CBCONT
;
901 if (ret
== WBCGI_FTW_CBERR
) {
903 chars
= snprintf(message
, sizeof (message
),
904 "(internal PKCS12 error while copying %s to %s)",
905 path
, (char *)truststorepath
);
907 chars
= snprintf(message
, sizeof (message
),
908 "(error copying %s to %s)",
909 path
, (char *)truststorepath
);
911 if (chars
> 0 && chars
<= sizeof (message
)) {
912 print_status(500, message
);
914 print_status(500, NULL
);
921 /* Will also close wfd */
927 if (i_anchors
!= NULL
) {
928 sk_X509_pop_free(i_anchors
, X509_free
);
930 if (o_anchors
!= NULL
) {
931 sk_X509_pop_free(o_anchors
, X509_free
);
938 check_key_type(const char *keyfile
, const char *keytype
, int flag
)
940 boolean_t ret
= B_FALSE
;
945 * Map keytype into the ka structure
947 if (wbku_str_to_keyattr(keytype
, &ka
, flag
) != WBKU_SUCCESS
) {
952 * Open the key file for reading.
954 if ((key_fp
= fopen(keyfile
, "r")) == NULL
) {
959 * Find the valid client key, if it exists.
961 if (wbku_find_key(key_fp
, NULL
, &ka
, NULL
, B_FALSE
) != WBKU_SUCCESS
) {
967 if (key_fp
!= NULL
) {
968 (void) fclose(key_fp
);
975 resolve_hostname(const char *hostname
, nvlist_t
*nvl
, boolean_t may_be_crap
)
977 struct sockaddr_in sin
;
980 static char myname
[SYS_NMLN
] = { '\0' };
982 char msg
[WBCGI_MAXBUF
];
985 * Initialize cached nodename
987 if (strlen(myname
) == 0) {
988 if (uname(&un
) == -1) {
989 (void) snprintf(msg
, sizeof (msg
),
990 "(unable to retrieve uname, errno %d)", errno
);
991 print_status(500, msg
);
994 (void) strcpy(myname
, un
.nodename
);
998 * If hostname is local node name, return the address this
999 * request came in on, which is supplied as SERVER_ADDR in the
1000 * cgi environment. This ensures we don't send back a possible
1001 * alternate address that may be unreachable from the client's
1002 * network. Otherwise, just resolve with nameservice.
1004 if ((strcmp(hostname
, myname
) != 0) ||
1005 ((cp
= getenv("SERVER_ADDR")) == NULL
)) {
1006 if (((hp
= gethostbyname(hostname
)) == NULL
) ||
1007 (hp
->h_addrtype
!= AF_INET
) ||
1008 (hp
->h_length
!= sizeof (struct in_addr
))) {
1010 print_status(500, "(error resolving hostname)");
1012 return (may_be_crap
);
1014 (void) memcpy(&sin
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1015 cp
= inet_ntoa(sin
.sin_addr
);
1018 if (nvlist_add_string(nvl
, (char *)hostname
, cp
) != 0) {
1019 print_status(500, "(error adding hostname to nvlist)");
1027 * one_name() is called for each certificate found and is passed the string
1028 * that X509_NAME_oneline() returns. Its job is to find the common name and
1029 * determine whether it is a host name; if it is then a line suitable for
1030 * inclusion in /etc/inet/hosts is written to that file.
1033 one_name(const char *namestr
, nvlist_t
*nvl
)
1035 boolean_t ret
= B_TRUE
;
1040 if (namestr
!= NULL
&&
1041 (p
= strstr(namestr
, WBCGI_CNSTR
)) != NULL
) {
1042 p
+= WBCGI_CNSTR_LEN
;
1044 if ((q
= strpbrk(p
, WBCGI_NAMESEP
)) != NULL
) {
1047 ret
= resolve_hostname(p
, nvl
, B_TRUE
);
1050 ret
= resolve_hostname(p
, nvl
, B_TRUE
);
1058 * Loop through the certificates in a file
1061 get_hostnames(const char *path
, void *nvl
)
1063 int ret
= WBCGI_FTW_CBERR
;
1064 STACK_OF(X509
) *certs
= NULL
;
1066 char message
[WBCGI_MAXBUF
];
1067 char buf
[WBCGI_MAXBUF
+ 1];
1074 if ((rfp
= fopen(path
, "r")) == NULL
) {
1078 if ((p12
= d2i_PKCS12_fp(rfp
, NULL
)) == NULL
) {
1082 i
= sunw_PKCS12_parse(p12
, WANBOOT_PASSPHRASE
, DO_NONE
, NULL
, 0, NULL
,
1083 NULL
, NULL
, &certs
);
1092 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
1094 x
= sk_X509_value(certs
, i
);
1095 if (!one_name(sunw_issuer_attrs(x
, buf
, sizeof (buf
) - 1),
1101 ret
= WBCGI_FTW_CBCONT
;
1103 if (ret
== WBCGI_FTW_CBERR
) {
1105 chars
= snprintf(message
, sizeof (message
),
1106 "(internal PKCS12 error reading %s)", path
);
1108 chars
= snprintf(message
, sizeof (message
),
1109 "error reading %s", path
);
1111 if (chars
> 0 && chars
<= sizeof (message
)) {
1112 print_status(500, message
);
1114 print_status(500, NULL
);
1123 if (certs
!= NULL
) {
1124 sk_X509_pop_free(certs
, X509_free
);
1131 * Create a hosts file by extracting hosts from client and truststore
1132 * files. Use the CN. Then we should copy that file to the inet dir.
1135 create_hostsfile(const char *hostsfile
, const char *net
, const char *cid
)
1137 boolean_t ret
= B_FALSE
;
1140 FILE *hostfp
= NULL
;
1144 const char *bc_urls
[] = { BC_ROOT_SERVER
, BC_BOOT_LOGGER
, NULL
};
1147 * Allocate nvlist handle to store our hostname/IP pairs.
1149 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0) != 0) {
1150 print_status(500, "(error allocating hostname nvlist)");
1155 * Extract and resolve hostnames from CNs.
1157 if (netboot_ftw(NB_CLIENT_CERT
, net
, cid
,
1158 get_hostnames
, nvl
) == WBCGI_FTW_CBERR
||
1159 netboot_ftw(NB_CA_CERT
, net
, cid
,
1160 get_hostnames
, nvl
) == WBCGI_FTW_CBERR
) {
1165 * Extract and resolve hostnames from any URLs in bootconf.
1167 for (i
= 0; bc_urls
[i
] != NULL
; ++i
) {
1171 if ((urlstr
= bootconf_get(&bc_handle
, bc_urls
[i
])) != NULL
&&
1172 url_parse(urlstr
, &url
) == URL_PARSE_SUCCESS
) {
1173 if (!resolve_hostname(url
.hport
.hostname
,
1181 * If there is a resolve-hosts list in bootconf, resolve those
1184 if ((hostslist
= bootconf_get(&bc_handle
, BC_RESOLVE_HOSTS
)) != NULL
) {
1187 for (hostname
= strtok(hostslist
, ","); hostname
!= NULL
;
1188 hostname
= strtok(NULL
, ",")) {
1189 if (!resolve_hostname(hostname
, nvl
, B_FALSE
)) {
1196 * Now write the hostname/IP pairs gathered to the hosts file.
1198 if ((hostfd
= open(hostsfile
,
1199 O_RDWR
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
1200 (hostfp
= fdopen(hostfd
, "w+")) == NULL
) {
1201 print_status(500, "(error creating hosts file)");
1204 for (nvp
= nvlist_next_nvpair(nvl
, NULL
); nvp
!= NULL
;
1205 nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
1209 hostname
= nvpair_name(nvp
);
1210 if (nvpair_value_string(nvp
, &ipstr
) != 0) {
1211 print_status(500, "(nvl error writing hosts file)");
1215 if (fprintf(hostfp
, "%s\t%s\n", ipstr
, hostname
) < 0) {
1216 print_status(500, "(error writing hosts file)");
1226 if (hostfp
!= NULL
) {
1228 * hostfd is automatically closed as well.
1230 (void) fclose(hostfp
);
1237 bootfile_payload(const char *docroot
, char **bootpathp
)
1239 boolean_t ret
= B_FALSE
;
1243 if ((boot_file
= bootconf_get(&bc_handle
, BC_BOOT_FILE
)) == NULL
) {
1244 print_status(500, "(boot_file must be specified)");
1247 if ((*bootpathp
= make_path(docroot
, boot_file
)) == NULL
) {
1250 if (!WBCGI_FILE_EXISTS(*bootpathp
, sbuf
)) {
1251 print_status(500, "(boot_file missing)");
1261 * Create the wanboot file system whose contents are determined by the
1262 * security configuration specified in bootconf.
1265 wanbootfs_payload(const char *net
, const char *cid
, const char *nonce
,
1266 const char *bootconf
, char **wanbootfs_imagep
)
1270 char *server_authentication
;
1271 char *client_authentication
;
1274 char *bootfs_dir
= NULL
;
1275 char *bootfs_etc_dir
= NULL
;
1276 char *bootfs_etc_inet_dir
= NULL
;
1277 char *bootfs_dev_dir
= NULL
;
1279 char *systemconf
= NULL
;
1280 char *keystorepath
= NULL
;
1281 char *certstorepath
= NULL
;
1282 char *truststorepath
= NULL
;
1283 char *bootconfpath
= NULL
;
1284 char *systemconfpath
= NULL
;
1285 char *urandompath
= NULL
;
1286 char *noncepath
= NULL
;
1287 char *hostspath
= NULL
;
1288 char *etc_hostspath
= NULL
;
1289 char *timestamppath
= NULL
;
1291 boolean_t authenticate_client
;
1292 boolean_t authenticate_server
;
1297 * Initialize SSL stuff.
1302 * Get the security strategy values.
1304 client_authentication
= bootconf_get(&bc_handle
,
1305 BC_CLIENT_AUTHENTICATION
);
1306 authenticate_client
= (client_authentication
!= NULL
&&
1307 strcmp(client_authentication
, "yes") == 0);
1308 server_authentication
= bootconf_get(&bc_handle
,
1309 BC_SERVER_AUTHENTICATION
);
1310 authenticate_server
= (server_authentication
!= NULL
&&
1311 strcmp(server_authentication
, "yes") == 0);
1314 * Make a temporary directory structure for the wanboot file system.
1316 if ((bootfs_dir
= gen_tmppath("bootfs_dir", net
, cid
)) == NULL
||
1317 (bootfs_etc_dir
= make_path(bootfs_dir
, "etc")) == NULL
||
1318 (bootfs_etc_inet_dir
= make_path(bootfs_etc_dir
, "inet")) == NULL
||
1319 (bootfs_dev_dir
= make_path(bootfs_dir
, "dev")) == NULL
) {
1322 if (mkdirp(bootfs_dir
, 0700) ||
1323 mkdirp(bootfs_etc_dir
, 0700) ||
1324 mkdirp(bootfs_etc_inet_dir
, 0700) ||
1325 mkdirp(bootfs_dev_dir
, 0700)) {
1326 print_status(500, "(error creating wanbootfs dir structure)");
1330 if (authenticate_client
) {
1332 * Add the client private key.
1334 if ((keystorepath
= make_path(bootfs_dir
,
1335 NB_CLIENT_KEY
)) == NULL
||
1336 netboot_ftw(NB_CLIENT_KEY
, net
, cid
,
1337 create_keystore
, keystorepath
) != WBCGI_FTW_CBOK
) {
1342 * Add the client certificate.
1344 if ((certstorepath
= make_path(bootfs_dir
,
1345 NB_CLIENT_CERT
)) == NULL
||
1346 netboot_ftw(NB_CLIENT_CERT
, net
, cid
,
1347 copy_certstore
, certstorepath
) != WBCGI_FTW_CBOK
) {
1352 if (authenticate_client
|| authenticate_server
) {
1354 * Add the trustfile; at least one truststore must exist.
1356 if ((truststorepath
= make_path(bootfs_dir
,
1357 NB_CA_CERT
)) == NULL
) {
1360 if (netboot_ftw(NB_CA_CERT
, net
, cid
,
1361 noact_cb
, NULL
) != WBCGI_FTW_CBOK
) {
1362 print_status(500, "(truststore not found)");
1364 if (netboot_ftw(NB_CA_CERT
, net
, cid
,
1365 build_trustfile
, truststorepath
) == WBCGI_FTW_CBERR
) {
1370 * Create the /dev/urandom file.
1372 if ((urandompath
= make_path(bootfs_dev_dir
,
1373 "urandom")) == NULL
||
1374 !create_urandom(urandompath
)) {
1380 * Add the wanboot.conf(4) file.
1382 if ((bootconfpath
= make_path(bootfs_dir
, NB_WANBOOT_CONF
)) == NULL
||
1383 !copy_file(bootconf
, bootconfpath
)) {
1388 * Add the system_conf file if present.
1390 if ((scf
= bootconf_get(&bc_handle
, BC_SYSTEM_CONF
)) != NULL
) {
1391 if (netboot_ftw(scf
, net
, cid
,
1392 set_pathname
, &systemconf
) != WBCGI_FTW_CBOK
) {
1393 print_status(500, "(system_conf file not found)");
1396 if ((systemconfpath
= make_path(bootfs_dir
,
1397 NB_SYSTEM_CONF
)) == NULL
||
1398 !copy_file(systemconf
, systemconfpath
)) {
1404 * Create the /nonce file.
1406 if ((noncepath
= make_path(bootfs_dir
, "nonce")) == NULL
||
1407 !create_nonce(noncepath
, nonce
)) {
1412 * Create an /etc/inet/hosts file by extracting hostnames from CN,
1413 * URLs in bootconf and resolve-hosts in bootconf.
1415 if ((hostspath
= make_path(bootfs_etc_inet_dir
, "hosts")) == NULL
||
1416 !create_hostsfile(hostspath
, net
, cid
)) {
1421 * We would like to create a symbolic link etc/hosts -> etc/inet/hosts,
1422 * but unfortunately the HSFS support in the standalone doesn't handle
1425 if ((etc_hostspath
= make_path(bootfs_etc_dir
, "hosts")) == NULL
||
1426 !copy_file(hostspath
, etc_hostspath
)) {
1431 * Create the /timestamp file.
1433 if ((timestamppath
= make_path(bootfs_dir
, "timestamp")) == NULL
||
1434 !create_timestamp(timestamppath
, "timestamp")) {
1439 * Create an HSFS file system for the directory.
1441 if ((*wanbootfs_imagep
= gen_tmppath("wanbootfs", net
, cid
)) == NULL
||
1442 !mkisofs(bootfs_dir
, *wanbootfs_imagep
)) {
1449 * Clean up temporary files and directories.
1451 if (keystorepath
!= NULL
&&
1452 WBCGI_FILE_EXISTS(keystorepath
, sbuf
)) {
1453 (void) unlink(keystorepath
);
1455 if (certstorepath
!= NULL
&&
1456 WBCGI_FILE_EXISTS(certstorepath
, sbuf
)) {
1457 (void) unlink(certstorepath
);
1459 if (truststorepath
!= NULL
&&
1460 WBCGI_FILE_EXISTS(truststorepath
, sbuf
)) {
1461 (void) unlink(truststorepath
);
1463 if (bootconfpath
!= NULL
&&
1464 WBCGI_FILE_EXISTS(bootconfpath
, sbuf
)) {
1465 (void) unlink(bootconfpath
);
1467 if (systemconfpath
!= NULL
&&
1468 WBCGI_FILE_EXISTS(systemconfpath
, sbuf
)) {
1469 (void) unlink(systemconfpath
);
1471 if (urandompath
!= NULL
&&
1472 WBCGI_FILE_EXISTS(urandompath
, sbuf
)) {
1473 (void) unlink(urandompath
);
1475 if (noncepath
!= NULL
&&
1476 WBCGI_FILE_EXISTS(noncepath
, sbuf
)) {
1477 (void) unlink(noncepath
);
1479 if (hostspath
!= NULL
&&
1480 WBCGI_FILE_EXISTS(hostspath
, sbuf
)) {
1481 (void) unlink(hostspath
);
1483 if (etc_hostspath
!= NULL
&&
1484 WBCGI_FILE_EXISTS(etc_hostspath
, sbuf
)) {
1485 (void) unlink(etc_hostspath
);
1487 if (timestamppath
!= NULL
&&
1488 WBCGI_FILE_EXISTS(timestamppath
, sbuf
)) {
1489 (void) unlink(timestamppath
);
1492 if (bootfs_etc_inet_dir
!= NULL
&&
1493 WBCGI_DIR_EXISTS(bootfs_etc_inet_dir
, sbuf
)) {
1494 (void) rmdir(bootfs_etc_inet_dir
);
1496 if (bootfs_etc_dir
!= NULL
&&
1497 WBCGI_DIR_EXISTS(bootfs_etc_dir
, sbuf
)) {
1498 (void) rmdir(bootfs_etc_dir
);
1500 if (bootfs_dev_dir
!= NULL
&&
1501 WBCGI_DIR_EXISTS(bootfs_dev_dir
, sbuf
)) {
1502 (void) rmdir(bootfs_dev_dir
);
1504 if (bootfs_dir
!= NULL
&&
1505 WBCGI_DIR_EXISTS(bootfs_dir
, sbuf
)) {
1506 (void) rmdir(bootfs_dir
);
1510 * Free allocated memory.
1512 free_path(&bootfs_dir
);
1513 free_path(&bootfs_etc_dir
);
1514 free_path(&bootfs_etc_inet_dir
);
1515 free_path(&bootfs_dev_dir
);
1517 free_path(&systemconf
);
1518 free_path(&keystorepath
);
1519 free_path(&certstorepath
);
1520 free_path(&truststorepath
);
1521 free_path(&bootconfpath
);
1522 free_path(&systemconfpath
);
1523 free_path(&urandompath
);
1524 free_path(&noncepath
);
1525 free_path(&hostspath
);
1526 free_path(&etc_hostspath
);
1527 free_path(×tamppath
);
1533 miniroot_payload(const char *net
, const char *cid
, const char *docroot
,
1534 char **rootpathp
, char **rootinfop
, boolean_t
*https_rootserverp
)
1536 boolean_t ret
= B_FALSE
;
1541 char sizebuf
[WBCGI_MAXBUF
];
1545 if ((root_server
= bootconf_get(&bc_handle
, BC_ROOT_SERVER
)) == NULL
) {
1546 print_status(500, "(root_server must be specified)");
1549 if (url_parse(root_server
, &url
) != URL_PARSE_SUCCESS
) {
1550 print_status(500, "(root_server URL is invalid)");
1552 *https_rootserverp
= url
.https
;
1554 if ((root_file
= bootconf_get(&bc_handle
, BC_ROOT_FILE
)) == NULL
) {
1555 print_status(500, "(rootfile must be specified)");
1558 if ((*rootpathp
= make_path(docroot
, root_file
)) == NULL
) {
1561 if (!WBCGI_FILE_EXISTS(*rootpathp
, sbuf
)) {
1562 print_status(500, "(root filesystem image missing)");
1566 if ((*rootinfop
= gen_tmppath("mrinfo", net
, cid
)) == NULL
) {
1569 if ((chars
= snprintf(sizebuf
, sizeof (sizebuf
), "%ld",
1570 sbuf
.st_size
)) < 0 || chars
> sizeof (sizebuf
) ||
1571 (fd
= open(*rootinfop
,
1572 O_RDWR
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
)) == -1 ||
1573 !write_buffer(fd
, sizebuf
, strlen(sizebuf
))) {
1574 print_status(500, "(error creating miniroot info file)");
1588 deliver_payload(const char *payload
, const char *payload_hash
)
1590 int fd
= fileno(stdout
);
1591 struct stat payload_buf
, hash_buf
;
1593 char main_header
[WBCGI_MAXBUF
];
1594 char multi_header
[WBCGI_MAXBUF
];
1595 char multi_header1
[WBCGI_MAXBUF
];
1596 char multi_header2
[WBCGI_MAXBUF
];
1597 char multi_end
[WBCGI_MAXBUF
];
1600 if (!WBCGI_FILE_EXISTS(payload
, payload_buf
) ||
1601 !WBCGI_FILE_EXISTS(payload_hash
, hash_buf
)) {
1602 print_status(500, "(payload/hash file(s) missing)");
1607 * Multi-part header.
1609 if ((chars
= snprintf(multi_header
, sizeof (multi_header
),
1610 "%s--%s%s%sapplication/octet-stream%s%s", WBCGI_CRNL
,
1611 WBCGI_WANBOOT_BNDTXT
, WBCGI_CRNL
, WBCGI_CONTENT_TYPE
, WBCGI_CRNL
,
1612 WBCGI_CONTENT_LENGTH
)) < 0 || chars
> sizeof (multi_header
)) {
1613 print_status(500, "(error creating multi_header)");
1618 * Multi-part header for part one.
1620 if ((chars
= snprintf(multi_header1
, sizeof (multi_header1
),
1621 "%s%ld%s%s", multi_header
, payload_buf
.st_size
, WBCGI_CRNL
,
1622 WBCGI_CRNL
)) < 0 || chars
> sizeof (multi_header1
)) {
1623 print_status(500, "(error creating multi_header1)");
1628 * Multi-part header for part two.
1630 if ((chars
= snprintf(multi_header2
, sizeof (multi_header2
),
1631 "%s%ld%s%s", multi_header
, hash_buf
.st_size
, WBCGI_CRNL
,
1632 WBCGI_CRNL
)) < 0 || chars
> sizeof (multi_header2
)) {
1633 print_status(500, "(error creating multi_header2)");
1638 * End-of-parts Trailer.
1640 if ((chars
= snprintf(multi_end
, sizeof (multi_end
),
1641 "%s--%s--%s", WBCGI_CRNL
, WBCGI_WANBOOT_BNDTXT
,
1642 WBCGI_CRNL
)) < 0 || chars
> sizeof (multi_end
)) {
1643 print_status(500, "(error creating multi_end)");
1650 msglen
= payload_buf
.st_size
+ hash_buf
.st_size
+
1651 strlen(multi_header1
) + strlen(multi_header2
) + strlen(multi_end
);
1653 if ((chars
= snprintf(main_header
, sizeof (main_header
),
1654 "%s%u%s%smultipart/mixed; boundary=%s%s%s", WBCGI_CONTENT_LENGTH
,
1655 msglen
, WBCGI_CRNL
, WBCGI_CONTENT_TYPE
, WBCGI_WANBOOT_BNDTXT
,
1656 WBCGI_CRNL
, WBCGI_CRNL
)) < 0 || chars
> sizeof (main_header
)) {
1657 print_status(500, "(error creating main_header)");
1662 * Write the message out. If things fall apart during this then
1663 * there's no way to report the error back to the client.
1665 if (!write_buffer(fd
, main_header
, strlen(main_header
)) ||
1666 !write_buffer(fd
, multi_header1
, strlen(multi_header1
)) ||
1667 !write_file(fd
, payload
, payload_buf
.st_size
) ||
1668 !write_buffer(fd
, multi_header2
, strlen(multi_header2
)) ||
1669 !write_file(fd
, payload_hash
, hash_buf
.st_size
) ||
1670 !write_buffer(fileno(stdout
), multi_end
, strlen(multi_end
))) {
1680 main(int argc
, char **argv
)
1682 int ret
= WBCGI_STATUS_ERR
;
1690 char *signature_type
;
1691 char *encryption_type
;
1692 char *bootconf
= NULL
;
1693 char *keyfile
= NULL
;
1694 char *bootpath
= NULL
;
1695 char *wanbootfs_image
= NULL
;
1696 char *rootpath
= NULL
;
1697 char *miniroot_info
= NULL
;
1698 char *encr_payload
= NULL
;
1699 char *payload_hash
= NULL
;
1700 boolean_t https_rootserver
;
1703 * Process the query string.
1705 if (!get_request_info(&content
, &net
, &cid
, &nonce
, &docroot
)) {
1710 * Sanity check that the netboot directory exists.
1712 if (!WBCGI_DIR_EXISTS(NB_NETBOOT_ROOT
, sbuf
)) {
1713 print_status(500, "(" NB_NETBOOT_ROOT
" does not exist)");
1718 * Get absolute bootconf pathname.
1720 if (netboot_ftw(NB_WANBOOT_CONF
, net
, cid
,
1721 set_pathname
, &bootconf
) != WBCGI_FTW_CBOK
) {
1722 print_status(500, "(wanboot.conf not found)");
1727 * Initialize bc_handle from the given wanboot.conf file.
1729 if (bootconf_init(&bc_handle
, bootconf
) != BC_SUCCESS
) {
1730 char message
[WBCGI_MAXBUF
];
1733 chars
= snprintf(message
, sizeof (message
),
1734 "(wanboot.conf error: %s)", bootconf_errmsg(&bc_handle
));
1735 if (chars
> 0 && chars
< sizeof (message
))
1736 print_status(500, message
);
1738 print_status(500, "(wanboot.conf error)");
1743 * Get and check signature and encryption types,
1744 * presence of helper utilities, keystore, etc.
1746 if ((signature_type
= bootconf_get(&bc_handle
,
1747 BC_SIGNATURE_TYPE
)) != NULL
) {
1748 if (!WBCGI_FILE_EXISTS(WBCGI_HMAC_PATH
, sbuf
)) {
1749 print_status(500, "(hmac utility not found)");
1752 if (keyfile
== NULL
&& netboot_ftw(NB_CLIENT_KEY
, net
, cid
,
1753 set_pathname
, &keyfile
) != WBCGI_FTW_CBOK
) {
1754 print_status(500, "(keystore not found)");
1757 if (!check_key_type(keyfile
, signature_type
, WBKU_HASH_KEY
)) {
1758 print_status(500, "(hash key not found)");
1762 if ((encryption_type
= bootconf_get(&bc_handle
,
1763 BC_ENCRYPTION_TYPE
)) != NULL
) {
1764 if (signature_type
== NULL
) {
1765 print_status(500, "(encrypted but not signed)");
1768 if (!WBCGI_FILE_EXISTS(WBCGI_ENCR_PATH
, sbuf
)) {
1769 print_status(500, "(encr utility not found)");
1772 if (keyfile
== NULL
&& netboot_ftw(NB_CLIENT_KEY
, net
, cid
,
1773 set_pathname
, &keyfile
) != WBCGI_FTW_CBOK
) {
1774 print_status(500, "(keystore not found)");
1777 if (!check_key_type(keyfile
, encryption_type
, WBKU_ENCR_KEY
)) {
1778 print_status(500, "(encr key not found)");
1784 * Determine/create our payload.
1787 case WBCGI_CONTENT_BOOTFILE
:
1788 if (!bootfile_payload(docroot
, &bootpath
)) {
1795 case WBCGI_CONTENT_BOOTFS
:
1796 if (!wanbootfs_payload(net
, cid
, nonce
,
1797 bootconf
, &wanbootfs_image
)) {
1800 payload
= wanbootfs_image
;
1804 case WBCGI_CONTENT_ROOTFS
:
1805 if (!miniroot_payload(net
, cid
, docroot
,
1806 &rootpath
, &miniroot_info
, &https_rootserver
)) {
1815 * Encrypt the payload if necessary.
1817 if (content
!= WBCGI_CONTENT_BOOTFILE
&&
1818 content
!= WBCGI_CONTENT_ROOTFS
&&
1819 encryption_type
!= NULL
) {
1820 if ((encr_payload
= gen_tmppath("encr", net
, cid
)) == NULL
) {
1824 if (!encrypt_payload(payload
, encr_payload
, keyfile
,
1829 payload
= encr_payload
;
1833 * Compute the hash (actual or null).
1835 if ((payload_hash
= gen_tmppath("hash", net
, cid
)) == NULL
) {
1839 if (signature_type
!= NULL
&&
1840 (content
!= WBCGI_CONTENT_ROOTFS
|| !https_rootserver
)) {
1841 if (!hash_payload(payload
, payload_hash
, keyfile
)) {
1845 if (!create_null_hash(payload_hash
)) {
1851 * For the rootfs the actual payload transmitted is the file
1852 * containing the size of the rootfs (as a string of ascii digits);
1853 * point payload at this instead.
1855 if (content
== WBCGI_CONTENT_ROOTFS
) {
1856 payload
= miniroot_info
;
1860 * Finally, deliver the payload and hash as a multipart message.
1862 if (!deliver_payload(payload
, payload_hash
)) {
1866 ret
= WBCGI_STATUS_OK
;
1869 * Clean up temporary files.
1871 if (wanbootfs_image
!= NULL
&&
1872 WBCGI_FILE_EXISTS(wanbootfs_image
, sbuf
)) {
1873 (void) unlink(wanbootfs_image
);
1875 if (miniroot_info
!= NULL
&&
1876 WBCGI_FILE_EXISTS(miniroot_info
, sbuf
)) {
1877 (void) unlink(miniroot_info
);
1879 if (encr_payload
!= NULL
&&
1880 WBCGI_FILE_EXISTS(encr_payload
, sbuf
)) {
1881 (void) unlink(encr_payload
);
1883 if (payload_hash
!= NULL
&&
1884 WBCGI_FILE_EXISTS(payload_hash
, sbuf
)) {
1885 (void) unlink(payload_hash
);
1889 * Free up any allocated strings.
1891 free_path(&bootconf
);
1892 free_path(&keyfile
);
1893 free_path(&bootpath
);
1894 free_path(&wanbootfs_image
);
1895 free_path(&rootpath
);
1896 free_path(&miniroot_info
);
1897 free_path(&encr_payload
);
1898 free_path(&payload_hash
);
1900 bootconf_end(&bc_handle
);