xref: /titanic_44/usr/src/cmd/cmd-inet/usr.lib/wanboot/wanboot-cgi/wanboot-cgi.c (revision d7141854234c22ab8fe0547bf51a2f3a30781870)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
522ce47f7SDavid Miner  * Common Development and Distribution License (the "License").
622ce47f7SDavid Miner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2222ce47f7SDavid Miner  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2333f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <libgen.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <netdb.h>
357c478bd9Sstevel@tonic-gate #include <libnvpair.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/wait.h>
387c478bd9Sstevel@tonic-gate #include <sys/stat.h>
397c478bd9Sstevel@tonic-gate #include <sys/param.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include <sys/mman.h>
427c478bd9Sstevel@tonic-gate #include <sys/socket.h>
4322ce47f7SDavid Miner #include <sys/utsname.h>
447c478bd9Sstevel@tonic-gate #include <sys/wanboot_impl.h>
457c478bd9Sstevel@tonic-gate #include <netinet/in.h>
467c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include <openssl/crypto.h>
497c478bd9Sstevel@tonic-gate #include <openssl/x509.h>
507c478bd9Sstevel@tonic-gate #include <openssl/x509v3.h>
517c478bd9Sstevel@tonic-gate #include <openssl/pem.h>
527c478bd9Sstevel@tonic-gate #include <openssl/pkcs12.h>
537c478bd9Sstevel@tonic-gate #include <openssl/evp.h>
547c478bd9Sstevel@tonic-gate #include <openssl/err.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <p12aux.h>
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include <parseURL.h>
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * These can be replaced with wanbootutil.h once the openssl interfaces
617c478bd9Sstevel@tonic-gate  * are moved to libwanboot.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate #include <wanboot/key_util.h>
647c478bd9Sstevel@tonic-gate #include <wanboot/key_xdr.h>
657c478bd9Sstevel@tonic-gate #include <hmac_sha1.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #include <netboot_paths.h>
687c478bd9Sstevel@tonic-gate #include <wanboot_conf.h>
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * Exit status:
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate #define	WBCGI_STATUS_OK		0
747c478bd9Sstevel@tonic-gate #define	WBCGI_STATUS_ERR	1
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define	WBCGI_FILE_EXISTS(file, statbuf) \
777c478bd9Sstevel@tonic-gate 	(stat(file, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define	WBCGI_DIR_EXISTS(dir, statbuf) \
807c478bd9Sstevel@tonic-gate 	(stat(dir, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #define	WBCGI_HMAC_PATH		"/usr/lib/inet/wanboot/hmac"
837c478bd9Sstevel@tonic-gate #define	WBCGI_ENCR_PATH		"/usr/lib/inet/wanboot/encr"
847c478bd9Sstevel@tonic-gate #define	WBCGI_KEYMGMT_PATH	"/usr/lib/inet/wanboot/keymgmt"
857c478bd9Sstevel@tonic-gate #define	WBCGI_MKISOFS_PATH	"/bin/mkisofs"
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #define	WBCGI_DEV_URANDOM	"/dev/urandom"
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_TYPE	"Content-Type: "
907c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_LENGTH	"Content-Length: "
917c478bd9Sstevel@tonic-gate #define	WBCGI_WANBOOT_BNDTXT	"WANBoot_Part_Boundary"
927c478bd9Sstevel@tonic-gate #define	WBCGI_CRNL		"\r\n"
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #define	WBCGI_CNSTR		"CN="
957c478bd9Sstevel@tonic-gate #define	WBCGI_CNSTR_LEN		(sizeof (WBCGI_CNSTR) - 1)
967c478bd9Sstevel@tonic-gate #define	WBCGI_NAMESEP		",/\n\r"
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	WBCGI_MAXBUF		256
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * Possible return values from netboot_ftw():
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate #define	WBCGI_FTW_CBOK		2	/* CB terminated walk OK */
1047c478bd9Sstevel@tonic-gate #define	WBCGI_FTW_CBCONT	1	/* CB wants walk should continue */
1057c478bd9Sstevel@tonic-gate #define	WBCGI_FTW_DONE		0	/* Walk terminated without CBERR/CBOK */
1067c478bd9Sstevel@tonic-gate #define	WBCGI_FTW_CBERR		-1	/* CB terminated walk with err */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * getsubopt() is used to map one of the contents[] keywords
1107c478bd9Sstevel@tonic-gate  * to one of these types
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_ERROR	-1
1137c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_BOOTFILE	0
1147c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_BOOTFS	1
1157c478bd9Sstevel@tonic-gate #define	WBCGI_CONTENT_ROOTFS	2
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static char *contents[] =
1187c478bd9Sstevel@tonic-gate 	{ "bootfile", "bootfs", "rootfs", NULL };
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * getsubopt() is used to parse the query string for
1227c478bd9Sstevel@tonic-gate  * the keywords defined by queryopts[]
1237c478bd9Sstevel@tonic-gate  */
1247c478bd9Sstevel@tonic-gate #define	WBCGI_QUERYOPT_CONTENT	0
1257c478bd9Sstevel@tonic-gate #define	WBCGI_QUERYOPT_NET	1
1267c478bd9Sstevel@tonic-gate #define	WBCGI_QUERYOPT_CID	2
1277c478bd9Sstevel@tonic-gate #define	WBCGI_QUERYOPT_NONCE	3
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static char *queryopts[] =
1307c478bd9Sstevel@tonic-gate 	{ "CONTENT", "IP", "CID", "NONCE", NULL };
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate static bc_handle_t	bc_handle;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate static char *
status_msg(int status)1367c478bd9Sstevel@tonic-gate status_msg(int status)
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	char	*msg;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	switch (status) {
1417c478bd9Sstevel@tonic-gate 	case 400:
1427c478bd9Sstevel@tonic-gate 		msg = "Bad Request";
1437c478bd9Sstevel@tonic-gate 		break;
1447c478bd9Sstevel@tonic-gate 	case 403:
1457c478bd9Sstevel@tonic-gate 		msg = "Forbidden";
1467c478bd9Sstevel@tonic-gate 		break;
1477c478bd9Sstevel@tonic-gate 	case 500:
1487c478bd9Sstevel@tonic-gate 		msg = "Internal Server Error";
1497c478bd9Sstevel@tonic-gate 		break;
1507c478bd9Sstevel@tonic-gate 	default:
1517c478bd9Sstevel@tonic-gate 		msg = "Unknown status";
1527c478bd9Sstevel@tonic-gate 		break;
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	return (msg);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate static void
print_status(int status,const char * spec_msg)1597c478bd9Sstevel@tonic-gate print_status(int status, const char *spec_msg)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	if (spec_msg == NULL) {
1627c478bd9Sstevel@tonic-gate 		spec_msg = "";
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "Status: %d %s %s%s", status,
1667c478bd9Sstevel@tonic-gate 	    status_msg(status), spec_msg, WBCGI_CRNL);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate static char *
make_path(const char * root,const char * suffix)1707c478bd9Sstevel@tonic-gate make_path(const char *root, const char *suffix)
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate 	char	path[MAXPATHLEN];
1737c478bd9Sstevel@tonic-gate 	char	*ptr = NULL;
1747c478bd9Sstevel@tonic-gate 	int	chars;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(path, sizeof (path),
1777c478bd9Sstevel@tonic-gate 	    "%s/%s", root, suffix)) < 0 || chars > sizeof (path) ||
1787c478bd9Sstevel@tonic-gate 	    (ptr = strdup(path)) == NULL) {
1797c478bd9Sstevel@tonic-gate 		print_status(500, "(error making path)");
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	return (ptr);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate static void
free_path(char ** pathp)1867c478bd9Sstevel@tonic-gate free_path(char **pathp)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	if (*pathp != NULL) {
1897c478bd9Sstevel@tonic-gate 		free(*pathp);
1907c478bd9Sstevel@tonic-gate 		*pathp = NULL;
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate static char *
gen_tmppath(const char * prefix,const char * net,const char * cid)1957c478bd9Sstevel@tonic-gate gen_tmppath(const char *prefix, const char *net, const char *cid)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	pid_t	pid;
1987c478bd9Sstevel@tonic-gate 	time_t	secs;
1997c478bd9Sstevel@tonic-gate 	int	chars;
2007c478bd9Sstevel@tonic-gate 	char	path[MAXPATHLEN];
2017c478bd9Sstevel@tonic-gate 	char	*ptr = NULL;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if ((pid = getpid()) < 0 || (secs = time(NULL)) < 0 ||
2047c478bd9Sstevel@tonic-gate 	    (chars = snprintf(path, sizeof (path), "/tmp/%s_%s_%s_%ld_%ld",
2057c478bd9Sstevel@tonic-gate 	    prefix, net, cid, pid, secs)) < 0 || chars > sizeof (path) ||
2067c478bd9Sstevel@tonic-gate 	    (ptr = strdup(path)) == NULL) {
2077c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating temporary filename)");
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	return (ptr);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * File I/O stuff:
2157c478bd9Sstevel@tonic-gate  */
2167c478bd9Sstevel@tonic-gate static boolean_t
write_buffer(int fd,const void * buffer,size_t buflen)2177c478bd9Sstevel@tonic-gate write_buffer(int fd, const void *buffer, size_t buflen)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	size_t		nwritten;
2207c478bd9Sstevel@tonic-gate 	ssize_t		nbytes;
2217c478bd9Sstevel@tonic-gate 	const char	*buf = buffer;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	for (nwritten = 0; nwritten < buflen; nwritten += nbytes) {
2247c478bd9Sstevel@tonic-gate 		nbytes = write(fd, &buf[nwritten], buflen - nwritten);
2257c478bd9Sstevel@tonic-gate 		if (nbytes <= 0) {
2267c478bd9Sstevel@tonic-gate 			return (B_FALSE);
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	return (B_TRUE);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate static boolean_t
write_file(int ofd,const char * filename,size_t size)2347c478bd9Sstevel@tonic-gate write_file(int ofd, const char *filename, size_t size)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
2377c478bd9Sstevel@tonic-gate 	int		ifd;
2387c478bd9Sstevel@tonic-gate 	char		buf[1024];
2397c478bd9Sstevel@tonic-gate 	size_t		rlen;
2407c478bd9Sstevel@tonic-gate 	ssize_t		wlen;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	if ((ifd = open(filename, O_RDONLY)) < 0) {
2437c478bd9Sstevel@tonic-gate 		return (B_FALSE);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	for (; size != 0; size -= wlen) {
2477c478bd9Sstevel@tonic-gate 		rlen = (size < sizeof (buf)) ? size : sizeof (buf);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		if ((wlen = read(ifd, buf, rlen)) < 0 ||
2507c478bd9Sstevel@tonic-gate 		    !write_buffer(ofd, buf, wlen)) {
2517c478bd9Sstevel@tonic-gate 			ret = B_FALSE;
2527c478bd9Sstevel@tonic-gate 			break;
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 	(void) close(ifd);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	return (ret);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate static boolean_t
copy_file(const char * src,const char * dest)2617c478bd9Sstevel@tonic-gate copy_file(const char *src, const char *dest)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
2647c478bd9Sstevel@tonic-gate 	char		message[WBCGI_MAXBUF];
2657c478bd9Sstevel@tonic-gate 	const size_t	chunksize = 16 * PAGESIZE;
2667c478bd9Sstevel@tonic-gate 	size_t		validsize;
2677c478bd9Sstevel@tonic-gate 	size_t		nwritten = 0;
2687c478bd9Sstevel@tonic-gate 	size_t		nbytes = 0;
2697c478bd9Sstevel@tonic-gate 	off_t		roff;
2707c478bd9Sstevel@tonic-gate 	int		mflags = MAP_PRIVATE;
2717c478bd9Sstevel@tonic-gate 	char		*buf = NULL;
2727c478bd9Sstevel@tonic-gate 	struct stat	st;
2737c478bd9Sstevel@tonic-gate 	int		rfd = -1;
2747c478bd9Sstevel@tonic-gate 	int		wfd = -1;
2757c478bd9Sstevel@tonic-gate 	int		chars;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if ((rfd = open(src, O_RDONLY)) < 0 ||
2787c478bd9Sstevel@tonic-gate 	    (wfd = open(dest, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR)) < 0 ||
2797c478bd9Sstevel@tonic-gate 	    fstat(rfd, &st) == -1) {
2807c478bd9Sstevel@tonic-gate 		goto cleanup;
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	for (nbytes = st.st_size, roff = 0; nwritten < nbytes;
2847c478bd9Sstevel@tonic-gate 	    nwritten += validsize, roff += validsize) {
2857c478bd9Sstevel@tonic-gate 		buf = mmap(buf, chunksize, PROT_READ, mflags, rfd, roff);
2867c478bd9Sstevel@tonic-gate 		if (buf == MAP_FAILED) {
2877c478bd9Sstevel@tonic-gate 			goto cleanup;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		mflags |= MAP_FIXED;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		validsize = MIN(chunksize, nbytes - nwritten);
2927c478bd9Sstevel@tonic-gate 		if (!write_buffer(wfd, buf, validsize)) {
2937c478bd9Sstevel@tonic-gate 			(void) munmap(buf, chunksize);
2947c478bd9Sstevel@tonic-gate 			goto cleanup;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 	if (buf != NULL) {
2997c478bd9Sstevel@tonic-gate 		(void) munmap(buf, chunksize);
3007c478bd9Sstevel@tonic-gate 	}
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
3037c478bd9Sstevel@tonic-gate cleanup:
3047c478bd9Sstevel@tonic-gate 	if (ret == B_FALSE) {
3057c478bd9Sstevel@tonic-gate 		if ((chars = snprintf(message, sizeof (message),
3067c478bd9Sstevel@tonic-gate 		    "error copying %s to %s", src, dest)) > 0 &&
3077c478bd9Sstevel@tonic-gate 		    chars <= sizeof (message)) {
3087c478bd9Sstevel@tonic-gate 			print_status(500, message);
3097c478bd9Sstevel@tonic-gate 		} else {
3107c478bd9Sstevel@tonic-gate 			print_status(500, NULL);
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 	if (rfd != -1) {
3147c478bd9Sstevel@tonic-gate 		(void) close(rfd);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 	if (wfd != -1) {
3177c478bd9Sstevel@tonic-gate 		(void) close(wfd);
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	return (ret);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate static boolean_t
create_nonce(const char * noncepath,const char * nonce)3247c478bd9Sstevel@tonic-gate create_nonce(const char *noncepath, const char *nonce)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
3277c478bd9Sstevel@tonic-gate 	int		fd;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	if ((fd = open(noncepath,
3307c478bd9Sstevel@tonic-gate 	    O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
3317c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, nonce, strlen(nonce))) {
3327c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating nonce file)");
3337c478bd9Sstevel@tonic-gate 		ret = B_FALSE;
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3367c478bd9Sstevel@tonic-gate 		(void) close(fd);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	return (ret);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate static boolean_t
create_timestamp(const char * timestamppath,const char * timestamp)3437c478bd9Sstevel@tonic-gate create_timestamp(const char *timestamppath, const char *timestamp)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
3467c478bd9Sstevel@tonic-gate 	int		fd;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if ((fd = open(timestamppath,
3497c478bd9Sstevel@tonic-gate 	    O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
3507c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, timestamp, strlen(timestamp))) {
3517c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating timestamp file)");
3527c478bd9Sstevel@tonic-gate 		ret = B_FALSE;
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3557c478bd9Sstevel@tonic-gate 		(void) close(fd);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	return (ret);
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate static boolean_t
create_urandom(const char * urandompath)3627c478bd9Sstevel@tonic-gate create_urandom(const char *urandompath)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
3657c478bd9Sstevel@tonic-gate 	int		fd;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	if ((fd = open(urandompath,
3687c478bd9Sstevel@tonic-gate 	    O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
3697c478bd9Sstevel@tonic-gate 	    !write_file(fd, WBCGI_DEV_URANDOM, 32 * 1024)) {
3707c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating urandom file)");
3717c478bd9Sstevel@tonic-gate 		ret = B_FALSE;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3747c478bd9Sstevel@tonic-gate 		(void) close(fd);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	return (ret);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate static boolean_t
create_null_hash(const char * hashpath)3817c478bd9Sstevel@tonic-gate create_null_hash(const char *hashpath)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
3847c478bd9Sstevel@tonic-gate 	int		fd;
3857c478bd9Sstevel@tonic-gate 	static char	null_hash[HMAC_DIGEST_LEN];
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if ((fd = open(hashpath,
3887c478bd9Sstevel@tonic-gate 	    O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
3897c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, null_hash, sizeof (null_hash))) {
3907c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating null hash)");
3917c478bd9Sstevel@tonic-gate 		ret = B_FALSE;
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3947c478bd9Sstevel@tonic-gate 		(void) close(fd);
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	return (ret);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate static char *
determine_doc_root(void)4027c478bd9Sstevel@tonic-gate determine_doc_root(void)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate 	char	*doc_root;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	/*
4077c478bd9Sstevel@tonic-gate 	 * If DOCUMENT_ROOT is valid, use that.
4087c478bd9Sstevel@tonic-gate 	 */
4097c478bd9Sstevel@tonic-gate 	if ((doc_root = getenv("DOCUMENT_ROOT")) == NULL ||
4107c478bd9Sstevel@tonic-gate 	    strlen(doc_root) == 0) {
4117c478bd9Sstevel@tonic-gate 		/*
4127c478bd9Sstevel@tonic-gate 		 * No DOCUMENT_ROOT - try PATH_TRANSLATED.
4137c478bd9Sstevel@tonic-gate 		 */
4147c478bd9Sstevel@tonic-gate 		if ((doc_root = getenv("PATH_TRANSLATED")) == NULL ||
4157c478bd9Sstevel@tonic-gate 		    strlen(doc_root) == 0) {
4167c478bd9Sstevel@tonic-gate 			/*
4177c478bd9Sstevel@tonic-gate 			 * Can't determine the document root.
4187c478bd9Sstevel@tonic-gate 			 */
4197c478bd9Sstevel@tonic-gate 			return (NULL);
4207c478bd9Sstevel@tonic-gate 		}
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	return (doc_root);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate static boolean_t
get_request_info(int * contentp,char ** netp,char ** cidp,char ** noncep,char ** docrootp)4277c478bd9Sstevel@tonic-gate get_request_info(int *contentp, char **netp, char **cidp, char **noncep,
4287c478bd9Sstevel@tonic-gate     char **docrootp)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate 	char	*method;
4317c478bd9Sstevel@tonic-gate 	char	*query_string;
4327c478bd9Sstevel@tonic-gate 	char	*value;
4337c478bd9Sstevel@tonic-gate 	char	*junk;
4347c478bd9Sstevel@tonic-gate 	int	i;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if ((method = getenv("REQUEST_METHOD")) == NULL ||
4377c478bd9Sstevel@tonic-gate 	    strncasecmp(method, "GET", strlen("GET") != 0)) {
4387c478bd9Sstevel@tonic-gate 		print_status(403, "(GET method expected)");
4397c478bd9Sstevel@tonic-gate 		return (B_FALSE);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	if ((query_string = getenv("QUERY_STRING")) == NULL) {
4437c478bd9Sstevel@tonic-gate 		print_status(400, "(empty query string)");
4447c478bd9Sstevel@tonic-gate 		return (B_FALSE);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	for (i = 0; i < strlen(query_string); i++) {
4487c478bd9Sstevel@tonic-gate 		if (query_string[i] == '&') {
4497c478bd9Sstevel@tonic-gate 			query_string[i] = ',';
4507c478bd9Sstevel@tonic-gate 		}
4517c478bd9Sstevel@tonic-gate 	}
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	*contentp = WBCGI_CONTENT_ERROR;
4547c478bd9Sstevel@tonic-gate 	*netp = *cidp = *noncep = NULL;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if ((*docrootp = determine_doc_root()) == NULL) {
4577c478bd9Sstevel@tonic-gate 		print_status(400, "(unable to determine document root)");
4587c478bd9Sstevel@tonic-gate 		return (B_FALSE);
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	while (*query_string != '\0') {
4627c478bd9Sstevel@tonic-gate 		switch (getsubopt(&query_string, queryopts, &value)) {
4637c478bd9Sstevel@tonic-gate 		case WBCGI_QUERYOPT_CONTENT:
4647c478bd9Sstevel@tonic-gate 			*contentp = getsubopt(&value, contents, &junk);
4657c478bd9Sstevel@tonic-gate 			break;
4667c478bd9Sstevel@tonic-gate 		case WBCGI_QUERYOPT_NET:
4677c478bd9Sstevel@tonic-gate 			*netp = value;
4687c478bd9Sstevel@tonic-gate 			break;
4697c478bd9Sstevel@tonic-gate 		case WBCGI_QUERYOPT_CID:
4707c478bd9Sstevel@tonic-gate 			*cidp = value;
4717c478bd9Sstevel@tonic-gate 			break;
4727c478bd9Sstevel@tonic-gate 		case WBCGI_QUERYOPT_NONCE:
4737c478bd9Sstevel@tonic-gate 			*noncep = value;
4747c478bd9Sstevel@tonic-gate 			break;
4757c478bd9Sstevel@tonic-gate 		default:
4767c478bd9Sstevel@tonic-gate 			print_status(400, "(illegal query string)");
4777c478bd9Sstevel@tonic-gate 			return (B_FALSE);
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	switch (*contentp) {
4827c478bd9Sstevel@tonic-gate 	default:
4837c478bd9Sstevel@tonic-gate 		print_status(400, "(missing or illegal CONTENT)");
4847c478bd9Sstevel@tonic-gate 		return (B_FALSE);
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_BOOTFS:
4877c478bd9Sstevel@tonic-gate 		if (*netp == NULL || *cidp == NULL || *noncep == NULL) {
4887c478bd9Sstevel@tonic-gate 			print_status(400,
4897c478bd9Sstevel@tonic-gate 			    "(CONTENT, IP, CID and NONCE required)");
4907c478bd9Sstevel@tonic-gate 			return (B_FALSE);
4917c478bd9Sstevel@tonic-gate 		}
4927c478bd9Sstevel@tonic-gate 		break;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_BOOTFILE:
4957c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_ROOTFS:
4967c478bd9Sstevel@tonic-gate 		if (*netp == NULL || *cidp == NULL || *docrootp == NULL) {
4977c478bd9Sstevel@tonic-gate 			print_status(400,
4987c478bd9Sstevel@tonic-gate 			    "(CONTENT, IP, CID and DOCUMENT_ROOT required)");
4997c478bd9Sstevel@tonic-gate 			return (B_FALSE);
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 		break;
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	return (B_TRUE);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate static boolean_t
encrypt_payload(const char * payload,const char * encr_payload,const char * keyfile,const char * encryption_type)5087c478bd9Sstevel@tonic-gate encrypt_payload(const char *payload, const char *encr_payload,
5097c478bd9Sstevel@tonic-gate     const char *keyfile, const char *encryption_type)
5107c478bd9Sstevel@tonic-gate {
5117c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
5127c478bd9Sstevel@tonic-gate 	int		chars;
5137c478bd9Sstevel@tonic-gate 	char		cmd[MAXPATHLEN];
5147c478bd9Sstevel@tonic-gate 	FILE		*fp;
5157c478bd9Sstevel@tonic-gate 	int		status;
5167c478bd9Sstevel@tonic-gate 	char		msg[WBCGI_MAXBUF];
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(payload, sbuf)) {
5197c478bd9Sstevel@tonic-gate 		print_status(500, "(encrypt_payload: missing payload)");
5207c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5217c478bd9Sstevel@tonic-gate 	}
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(cmd, sizeof (cmd),
5247c478bd9Sstevel@tonic-gate 	    "%s -o type=%s -k %s < %s > %s", WBCGI_ENCR_PATH,
5257c478bd9Sstevel@tonic-gate 	    encryption_type, keyfile, payload, encr_payload)) < 0 ||
5267c478bd9Sstevel@tonic-gate 	    chars > sizeof (cmd)) {
5277c478bd9Sstevel@tonic-gate 		print_status(500, "(encrypt_payload: buffer overflow)");
5287c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	if ((fp = popen(cmd, "w")) == NULL) {
5327c478bd9Sstevel@tonic-gate 		print_status(500, "(encrypt_payload: missing/file error)");
5337c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate 	if ((status = WEXITSTATUS(pclose(fp))) != 0) {
5367c478bd9Sstevel@tonic-gate 		(void) snprintf(msg, sizeof (msg),
5377c478bd9Sstevel@tonic-gate 		    "(encrypt_payload: failed, status=%d)", status);
5387c478bd9Sstevel@tonic-gate 		print_status(500, msg);
5397c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5407c478bd9Sstevel@tonic-gate 	}
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(encr_payload, sbuf)) {
5437c478bd9Sstevel@tonic-gate 		print_status(500, "(encrypt_payload: bad encrypted file)");
5447c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	return (B_TRUE);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate static boolean_t
hash_payload(const char * payload,const char * payload_hash,const char * keyfile)5517c478bd9Sstevel@tonic-gate hash_payload(const char *payload, const char *payload_hash,
5527c478bd9Sstevel@tonic-gate     const char *keyfile)
5537c478bd9Sstevel@tonic-gate {
5547c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
5557c478bd9Sstevel@tonic-gate 	int		chars;
5567c478bd9Sstevel@tonic-gate 	char		cmd[MAXPATHLEN];
5577c478bd9Sstevel@tonic-gate 	FILE		*fp;
5587c478bd9Sstevel@tonic-gate 	int		status;
5597c478bd9Sstevel@tonic-gate 	char		msg[WBCGI_MAXBUF];
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(payload, sbuf)) {
5627c478bd9Sstevel@tonic-gate 		print_status(500, "(hash_payload: missing payload)");
5637c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(cmd, sizeof (cmd), "%s -i %s -k %s > %s",
5677c478bd9Sstevel@tonic-gate 	    WBCGI_HMAC_PATH, payload, keyfile, payload_hash)) < 0 ||
5687c478bd9Sstevel@tonic-gate 	    chars > sizeof (cmd)) {
5697c478bd9Sstevel@tonic-gate 		print_status(500, "(hash_payload: buffer overflow)");
5707c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	if ((fp = popen(cmd, "w")) == NULL) {
5747c478bd9Sstevel@tonic-gate 		print_status(500, "(hash_payload: missing/file error)");
5757c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 	if ((status = WEXITSTATUS(pclose(fp))) != 0) {
5787c478bd9Sstevel@tonic-gate 		(void) snprintf(msg, sizeof (msg),
5797c478bd9Sstevel@tonic-gate 		    "(hash_payload: failed, status=%d)", status);
5807c478bd9Sstevel@tonic-gate 		print_status(500, msg);
5817c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(payload_hash, sbuf) ||
5857c478bd9Sstevel@tonic-gate 	    sbuf.st_size < HMAC_DIGEST_LEN) {
5867c478bd9Sstevel@tonic-gate 		print_status(500, "(hash_payload: bad signature file)");
5877c478bd9Sstevel@tonic-gate 		return (B_FALSE);
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	return (B_TRUE);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate static boolean_t
extract_keystore(const char * path,const char * keystorepath)5947c478bd9Sstevel@tonic-gate extract_keystore(const char *path, const char *keystorepath)
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
5977c478bd9Sstevel@tonic-gate 	int		chars;
5987c478bd9Sstevel@tonic-gate 	char		cmd[MAXPATHLEN];
5997c478bd9Sstevel@tonic-gate 	FILE		*fp;
6007c478bd9Sstevel@tonic-gate 	int		status;
6017c478bd9Sstevel@tonic-gate 	char		msg[WBCGI_MAXBUF];
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(path, sbuf)) {
6047c478bd9Sstevel@tonic-gate 		print_status(500, "(extract_keystore: missing keystore)");
6057c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(cmd, sizeof (cmd),
6097c478bd9Sstevel@tonic-gate 	    "%s -x -f %s -s %s -o type=rsa",
6107c478bd9Sstevel@tonic-gate 	    WBCGI_KEYMGMT_PATH, keystorepath, path)) < 0 ||
6117c478bd9Sstevel@tonic-gate 	    chars > sizeof (cmd)) {
6127c478bd9Sstevel@tonic-gate 		print_status(500, "(extract_keystore: buffer overflow)");
6137c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	if ((fp = popen(cmd, "w")) == NULL) {
6177c478bd9Sstevel@tonic-gate 		print_status(500, "(extract_keystore: missing/file error)");
6187c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 	if ((status = WEXITSTATUS(pclose(fp))) != 0) {
6217c478bd9Sstevel@tonic-gate 		(void) snprintf(msg, sizeof (msg),
6227c478bd9Sstevel@tonic-gate 		    "(extract_keystore: failed, status=%d)", status);
6237c478bd9Sstevel@tonic-gate 		print_status(500, msg);
6247c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(keystorepath, sbuf)) {
6287c478bd9Sstevel@tonic-gate 		print_status(500, "(extract_keystore: failed to create)");
6297c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	return (B_TRUE);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate static boolean_t
mkisofs(const char * image_dir,const char * image)6367c478bd9Sstevel@tonic-gate mkisofs(const char *image_dir, const char *image)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
6397c478bd9Sstevel@tonic-gate 	int		chars;
6407c478bd9Sstevel@tonic-gate 	char		cmd[MAXPATHLEN];
6417c478bd9Sstevel@tonic-gate 	FILE		*fp;
6427c478bd9Sstevel@tonic-gate 	int		status;
6437c478bd9Sstevel@tonic-gate 	char		msg[WBCGI_MAXBUF];
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	if (!WBCGI_DIR_EXISTS(image_dir, sbuf)) {
6467c478bd9Sstevel@tonic-gate 		print_status(500, "(mksiofs: missing image_dir)");
6477c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(cmd, sizeof (cmd), "%s -quiet -o %s -r %s",
6517c478bd9Sstevel@tonic-gate 	    WBCGI_MKISOFS_PATH, image, image_dir)) < 0 ||
6527c478bd9Sstevel@tonic-gate 	    chars > sizeof (cmd)) {
6537c478bd9Sstevel@tonic-gate 		print_status(500, "(mkisofs: buffer overflow)");
6547c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	if ((fp = popen(cmd, "w")) == NULL) {
6587c478bd9Sstevel@tonic-gate 		print_status(500, "(mkisofs: missing/file error)");
6597c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 	if ((status = WEXITSTATUS(pclose(fp))) != 0) {
6627c478bd9Sstevel@tonic-gate 		(void) snprintf(msg, sizeof (msg),
6637c478bd9Sstevel@tonic-gate 		    "(mkisofs: failed, status=%d)", status);
6647c478bd9Sstevel@tonic-gate 		print_status(500, msg);
6657c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6667c478bd9Sstevel@tonic-gate 	}
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(image, sbuf)) {
6697c478bd9Sstevel@tonic-gate 		print_status(500, "(mksiofs: failed to create image)");
6707c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	return (B_TRUE);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate  * This function, when invoked with a file name, optional network and
67822ce47f7SDavid Miner  * client ID strings, and callback function will search for the file
67922ce47f7SDavid Miner  * in the following locations:
68022ce47f7SDavid Miner  *
68122ce47f7SDavid Miner  * NB_NETBOOT_ROOT/<network>/<client id>/<file>
68222ce47f7SDavid Miner  * NB_NETBOOT_ROOT/<client id>/<file>
68322ce47f7SDavid Miner  * NB_NETBOOT_ROOT/<network>/<file>
68422ce47f7SDavid Miner  * NB_NETBOOT_ROOT/<file>
68522ce47f7SDavid Miner  *
68622ce47f7SDavid Miner  * The callback function is invoked each time the file is found until
68722ce47f7SDavid Miner  * we have searched all of the above locations or the callback function
68822ce47f7SDavid Miner  * returns a value other than WBCGI_FTW_CBCONT.
6897c478bd9Sstevel@tonic-gate  *
6907c478bd9Sstevel@tonic-gate  * Arguments:
6917c478bd9Sstevel@tonic-gate  *	filename - Name of file to search for.
6927c478bd9Sstevel@tonic-gate  *	net      - Optional network number to include in search hierarchy.
6937c478bd9Sstevel@tonic-gate  *	cid      - Optional client ID to include in search hierarchy.
6947c478bd9Sstevel@tonic-gate  *	cb       - Callback function to be called when file is found.
6957c478bd9Sstevel@tonic-gate  *	arg	 - Argument to be supplied to the callback funtion.
6967c478bd9Sstevel@tonic-gate  *
6977c478bd9Sstevel@tonic-gate  * Returns:
6987c478bd9Sstevel@tonic-gate  *	WBCGI_FTW_DONE, WBCGI_FTW_CBOK or WBCGI_FTW_CBERR.
6997c478bd9Sstevel@tonic-gate  */
7007c478bd9Sstevel@tonic-gate static int
netboot_ftw(const char * filename,const char * net,const char * cid,int (* cb)(const char *,void * arg),void * arg)7017c478bd9Sstevel@tonic-gate netboot_ftw(const char *filename, const char *net, const char *cid,
7027c478bd9Sstevel@tonic-gate     int (*cb)(const char *, void *arg), void *arg)
7037c478bd9Sstevel@tonic-gate {
70422ce47f7SDavid Miner 	char		ckpath[4][MAXPATHLEN];
7057c478bd9Sstevel@tonic-gate 	int		ret;
7067c478bd9Sstevel@tonic-gate 	struct		stat buf;
70722ce47f7SDavid Miner 	int		i = 0;
7087c478bd9Sstevel@tonic-gate 
70922ce47f7SDavid Miner 	if (snprintf(ckpath[i++], MAXPATHLEN, "%s%s", NB_NETBOOT_ROOT, filename)
71022ce47f7SDavid Miner 	    >= MAXPATHLEN)
7117c478bd9Sstevel@tonic-gate 		return (WBCGI_FTW_CBERR);
7127c478bd9Sstevel@tonic-gate 
71322ce47f7SDavid Miner 	if (net != NULL && snprintf(ckpath[i++], MAXPATHLEN, "%s%s/%s",
71422ce47f7SDavid Miner 	    NB_NETBOOT_ROOT, net, filename) >= MAXPATHLEN)
7157c478bd9Sstevel@tonic-gate 		return (WBCGI_FTW_CBERR);
71622ce47f7SDavid Miner 
7177c478bd9Sstevel@tonic-gate 	if (cid != NULL) {
71822ce47f7SDavid Miner 		if (snprintf(ckpath[i++], MAXPATHLEN, "%s%s/%s",
71922ce47f7SDavid Miner 		    NB_NETBOOT_ROOT, cid, filename) >= MAXPATHLEN)
7207c478bd9Sstevel@tonic-gate 			return (WBCGI_FTW_CBERR);
72122ce47f7SDavid Miner 
72222ce47f7SDavid Miner 		if (net != NULL && snprintf(ckpath[i++], MAXPATHLEN,
72322ce47f7SDavid Miner 		    "%s%s/%s/%s", NB_NETBOOT_ROOT, net, cid, filename) >=
72422ce47f7SDavid Miner 		    MAXPATHLEN)
72522ce47f7SDavid Miner 			return (WBCGI_FTW_CBERR);
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	/*
7297c478bd9Sstevel@tonic-gate 	 * Loop through hierarchy and check for file existence.
7307c478bd9Sstevel@tonic-gate 	 */
73122ce47f7SDavid Miner 	while (i > 0) {
73222ce47f7SDavid Miner 		--i;
73322ce47f7SDavid Miner 		if (WBCGI_FILE_EXISTS(ckpath[i], buf)) {
73422ce47f7SDavid Miner 			if ((ret = cb(ckpath[i], arg)) != WBCGI_FTW_CBCONT)
7357c478bd9Sstevel@tonic-gate 				return (ret);
7367c478bd9Sstevel@tonic-gate 		}
7377c478bd9Sstevel@tonic-gate 	}
7387c478bd9Sstevel@tonic-gate 	return (WBCGI_FTW_DONE);
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7427c478bd9Sstevel@tonic-gate static int
noact_cb(const char * path,void * arg)7437c478bd9Sstevel@tonic-gate noact_cb(const char *path, void *arg)
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate 	return (WBCGI_FTW_CBOK);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate static int
set_pathname(const char * path,void * pathname)7497c478bd9Sstevel@tonic-gate set_pathname(const char *path, void *pathname)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate 	*(char **)pathname = strdup((char *)path);
7527c478bd9Sstevel@tonic-gate 	return (WBCGI_FTW_CBOK);
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate static int
create_keystore(const char * path,void * keystorepath)7567c478bd9Sstevel@tonic-gate create_keystore(const char *path, void *keystorepath)
7577c478bd9Sstevel@tonic-gate {
7587c478bd9Sstevel@tonic-gate 	if (!extract_keystore(path, (char *)keystorepath)) {
7597c478bd9Sstevel@tonic-gate 		return (WBCGI_FTW_CBERR);
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 	return (WBCGI_FTW_CBOK);
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate static int
copy_certstore(const char * path,void * certstorepath)7657c478bd9Sstevel@tonic-gate copy_certstore(const char *path, void *certstorepath)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	if (!copy_file(path, (char *)certstorepath)) {
7687c478bd9Sstevel@tonic-gate 		return (WBCGI_FTW_CBERR);
7697c478bd9Sstevel@tonic-gate 	}
7707c478bd9Sstevel@tonic-gate 	return (WBCGI_FTW_CBOK);
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate /*
7747c478bd9Sstevel@tonic-gate  * Add the certs found in the trustfile found in path (a trust store) to
7757c478bd9Sstevel@tonic-gate  * the file found at bootfs_dir/truststore.  If necessary, create the
7767c478bd9Sstevel@tonic-gate  * output file.
7777c478bd9Sstevel@tonic-gate  */
7787c478bd9Sstevel@tonic-gate static int
build_trustfile(const char * path,void * truststorepath)7797c478bd9Sstevel@tonic-gate build_trustfile(const char *path, void *truststorepath)
7807c478bd9Sstevel@tonic-gate {
7817c478bd9Sstevel@tonic-gate 	int		ret = WBCGI_FTW_CBERR;
7827c478bd9Sstevel@tonic-gate 	STACK_OF(X509)	*i_anchors = NULL;
7837c478bd9Sstevel@tonic-gate 	STACK_OF(X509)	*o_anchors = NULL;
7847c478bd9Sstevel@tonic-gate 	char		message[WBCGI_MAXBUF];
7857c478bd9Sstevel@tonic-gate 	PKCS12		*p12 = NULL;
7867c478bd9Sstevel@tonic-gate 	FILE		*rfp = NULL;
7877c478bd9Sstevel@tonic-gate 	FILE		*wfp = NULL;
7887c478bd9Sstevel@tonic-gate 	struct stat	i_st;
7897c478bd9Sstevel@tonic-gate 	struct stat	o_st;
7907c478bd9Sstevel@tonic-gate 	X509		*x = NULL;
7917c478bd9Sstevel@tonic-gate 	int		errtype = 0;
7927c478bd9Sstevel@tonic-gate 	int		wfd = -1;
7937c478bd9Sstevel@tonic-gate 	int		chars;
7947c478bd9Sstevel@tonic-gate 	int		i;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(path, i_st)) {
7977c478bd9Sstevel@tonic-gate 		goto cleanup;
7987c478bd9Sstevel@tonic-gate 	}
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 	if (WBCGI_FILE_EXISTS((char *)truststorepath, o_st)) {
8017c478bd9Sstevel@tonic-gate 		/*
8027c478bd9Sstevel@tonic-gate 		 * If we are inadvertantly writing to the input file.
8037c478bd9Sstevel@tonic-gate 		 * return success.
8047c478bd9Sstevel@tonic-gate 		 * XXX Pete: how can this happen, and why success?
8057c478bd9Sstevel@tonic-gate 		 */
8067c478bd9Sstevel@tonic-gate 		if (i_st.st_ino == o_st.st_ino) {
8077c478bd9Sstevel@tonic-gate 			ret = WBCGI_FTW_CBCONT;
8087c478bd9Sstevel@tonic-gate 			goto cleanup;
8097c478bd9Sstevel@tonic-gate 		}
8107c478bd9Sstevel@tonic-gate 		if ((wfp = fopen((char *)truststorepath, "r+")) == NULL) {
8117c478bd9Sstevel@tonic-gate 			goto cleanup;
8127c478bd9Sstevel@tonic-gate 		}
8137c478bd9Sstevel@tonic-gate 		/*
8147c478bd9Sstevel@tonic-gate 		 * Read what's already there, so that new information
8157c478bd9Sstevel@tonic-gate 		 * can be added.
8167c478bd9Sstevel@tonic-gate 		 */
8177c478bd9Sstevel@tonic-gate 		if ((p12 = d2i_PKCS12_fp(wfp, NULL)) == NULL) {
8187c478bd9Sstevel@tonic-gate 			errtype = 1;
8197c478bd9Sstevel@tonic-gate 			goto cleanup;
8207c478bd9Sstevel@tonic-gate 		}
8217c478bd9Sstevel@tonic-gate 		i = sunw_PKCS12_parse(p12, WANBOOT_PASSPHRASE, DO_NONE, NULL,
8227c478bd9Sstevel@tonic-gate 		    0, NULL, NULL, NULL, &o_anchors);
8237c478bd9Sstevel@tonic-gate 		if (i <= 0) {
8247c478bd9Sstevel@tonic-gate 			errtype = 1;
8257c478bd9Sstevel@tonic-gate 			goto cleanup;
8267c478bd9Sstevel@tonic-gate 		}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 		PKCS12_free(p12);
8297c478bd9Sstevel@tonic-gate 		p12 = NULL;
8307c478bd9Sstevel@tonic-gate 	} else {
8317c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
8327c478bd9Sstevel@tonic-gate 			chars = snprintf(message, sizeof (message),
8337c478bd9Sstevel@tonic-gate 			    "(error accessing file %s, error %s)",
8347c478bd9Sstevel@tonic-gate 			    path, strerror(errno));
8357c478bd9Sstevel@tonic-gate 			if (chars > 0 && chars < sizeof (message))
8367c478bd9Sstevel@tonic-gate 				print_status(500, message);
8377c478bd9Sstevel@tonic-gate 			else
8387c478bd9Sstevel@tonic-gate 				print_status(500, NULL);
8397c478bd9Sstevel@tonic-gate 			return (WBCGI_FTW_CBERR);
8407c478bd9Sstevel@tonic-gate 		}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 		/*
8437c478bd9Sstevel@tonic-gate 		 * Note: We could copy the file to the new trustfile, but
8447c478bd9Sstevel@tonic-gate 		 * we can't verify the password that way.  Therefore, copy
8457c478bd9Sstevel@tonic-gate 		 * it by reading it.
8467c478bd9Sstevel@tonic-gate 		 */
8477c478bd9Sstevel@tonic-gate 		if ((wfd = open((char *)truststorepath,
8487c478bd9Sstevel@tonic-gate 		    O_CREAT|O_EXCL|O_RDWR, 0700)) < 0) {
8497c478bd9Sstevel@tonic-gate 			goto cleanup;
8507c478bd9Sstevel@tonic-gate 		}
8517c478bd9Sstevel@tonic-gate 		if ((wfp = fdopen(wfd, "w+")) == NULL) {
8527c478bd9Sstevel@tonic-gate 			goto cleanup;
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 		o_anchors = sk_X509_new_null();
8557c478bd9Sstevel@tonic-gate 		if (o_anchors == NULL) {
8567c478bd9Sstevel@tonic-gate 			goto cleanup;
8577c478bd9Sstevel@tonic-gate 		}
8587c478bd9Sstevel@tonic-gate 	}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	if ((rfp = fopen(path, "r")) == NULL) {
8617c478bd9Sstevel@tonic-gate 		goto cleanup;
8627c478bd9Sstevel@tonic-gate 	}
8637c478bd9Sstevel@tonic-gate 	if ((p12 = d2i_PKCS12_fp(rfp, NULL)) == NULL) {
8647c478bd9Sstevel@tonic-gate 		errtype = 1;
8657c478bd9Sstevel@tonic-gate 		goto cleanup;
8667c478bd9Sstevel@tonic-gate 	}
8677c478bd9Sstevel@tonic-gate 	i = sunw_PKCS12_parse(p12, WANBOOT_PASSPHRASE, DO_NONE, NULL, 0, NULL,
8687c478bd9Sstevel@tonic-gate 	    NULL, NULL, &i_anchors);
8697c478bd9Sstevel@tonic-gate 	if (i <= 0) {
8707c478bd9Sstevel@tonic-gate 		errtype = 1;
8717c478bd9Sstevel@tonic-gate 		goto cleanup;
8727c478bd9Sstevel@tonic-gate 	}
8737c478bd9Sstevel@tonic-gate 	PKCS12_free(p12);
8747c478bd9Sstevel@tonic-gate 	p12 = NULL;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	/*
8777c478bd9Sstevel@tonic-gate 	 * Merge the two stacks of pkcs12 certs.
8787c478bd9Sstevel@tonic-gate 	 */
8797c478bd9Sstevel@tonic-gate 	for (i = 0; i < sk_X509_num(i_anchors); i++) {
880*d7141854SRobert Mustacchi 		/* LINTED */
8817c478bd9Sstevel@tonic-gate 		x = sk_X509_delete(i_anchors, i);
8827c478bd9Sstevel@tonic-gate 		(void) sk_X509_push(o_anchors, x);
8837c478bd9Sstevel@tonic-gate 	}
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	/*
8867c478bd9Sstevel@tonic-gate 	 * Create the pkcs12 structure from the modified input stack and
8877c478bd9Sstevel@tonic-gate 	 * then write out that structure.
8887c478bd9Sstevel@tonic-gate 	 */
8897c478bd9Sstevel@tonic-gate 	p12 = sunw_PKCS12_create((const char *)WANBOOT_PASSPHRASE, NULL, NULL,
8907c478bd9Sstevel@tonic-gate 	    o_anchors);
8917c478bd9Sstevel@tonic-gate 	if (p12 == NULL) {
8927c478bd9Sstevel@tonic-gate 		goto cleanup;
8937c478bd9Sstevel@tonic-gate 	}
8947c478bd9Sstevel@tonic-gate 	rewind(wfp);
8957c478bd9Sstevel@tonic-gate 	if (i2d_PKCS12_fp(wfp, p12) == 0) {
8967c478bd9Sstevel@tonic-gate 		goto cleanup;
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	ret = WBCGI_FTW_CBCONT;
9007c478bd9Sstevel@tonic-gate cleanup:
9017c478bd9Sstevel@tonic-gate 	if (ret == WBCGI_FTW_CBERR) {
9027c478bd9Sstevel@tonic-gate 		if (errtype == 1) {
9037c478bd9Sstevel@tonic-gate 			chars = snprintf(message, sizeof (message),
9047c478bd9Sstevel@tonic-gate 			    "(internal PKCS12 error while copying %s to %s)",
9057c478bd9Sstevel@tonic-gate 			    path, (char *)truststorepath);
9067c478bd9Sstevel@tonic-gate 		} else {
9077c478bd9Sstevel@tonic-gate 			chars = snprintf(message, sizeof (message),
9087c478bd9Sstevel@tonic-gate 			    "(error copying %s to %s)",
9097c478bd9Sstevel@tonic-gate 			    path, (char *)truststorepath);
9107c478bd9Sstevel@tonic-gate 		}
9117c478bd9Sstevel@tonic-gate 		if (chars > 0 && chars <= sizeof (message)) {
9127c478bd9Sstevel@tonic-gate 			print_status(500, message);
9137c478bd9Sstevel@tonic-gate 		} else {
9147c478bd9Sstevel@tonic-gate 			print_status(500, NULL);
9157c478bd9Sstevel@tonic-gate 		}
9167c478bd9Sstevel@tonic-gate 	}
9177c478bd9Sstevel@tonic-gate 	if (rfp != NULL) {
9187c478bd9Sstevel@tonic-gate 		(void) fclose(rfp);
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 	if (wfp != NULL) {
9217c478bd9Sstevel@tonic-gate 		/* Will also close wfd */
9227c478bd9Sstevel@tonic-gate 		(void) fclose(wfp);
9237c478bd9Sstevel@tonic-gate 	}
9247c478bd9Sstevel@tonic-gate 	if (p12 != NULL) {
9257c478bd9Sstevel@tonic-gate 		PKCS12_free(p12);
9267c478bd9Sstevel@tonic-gate 	}
9277c478bd9Sstevel@tonic-gate 	if (i_anchors != NULL) {
9287c478bd9Sstevel@tonic-gate 		sk_X509_pop_free(i_anchors, X509_free);
9297c478bd9Sstevel@tonic-gate 	}
9307c478bd9Sstevel@tonic-gate 	if (o_anchors != NULL) {
9317c478bd9Sstevel@tonic-gate 		sk_X509_pop_free(o_anchors, X509_free);
9327c478bd9Sstevel@tonic-gate 	}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	return (ret);
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate static boolean_t
check_key_type(const char * keyfile,const char * keytype,int flag)9387c478bd9Sstevel@tonic-gate check_key_type(const char *keyfile, const char *keytype, int flag)
9397c478bd9Sstevel@tonic-gate {
9407c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
9417c478bd9Sstevel@tonic-gate 	FILE		*key_fp = NULL;
9427c478bd9Sstevel@tonic-gate 	wbku_key_attr_t	ka;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Map keytype into the ka structure
9467c478bd9Sstevel@tonic-gate 	 */
9477c478bd9Sstevel@tonic-gate 	if (wbku_str_to_keyattr(keytype, &ka, flag) != WBKU_SUCCESS) {
9487c478bd9Sstevel@tonic-gate 		goto cleanup;
9497c478bd9Sstevel@tonic-gate 	}
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	/*
9527c478bd9Sstevel@tonic-gate 	 * Open the key file for reading.
9537c478bd9Sstevel@tonic-gate 	 */
9547c478bd9Sstevel@tonic-gate 	if ((key_fp = fopen(keyfile, "r")) == NULL) {
9557c478bd9Sstevel@tonic-gate 		goto cleanup;
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	/*
9597c478bd9Sstevel@tonic-gate 	 * Find the valid client key, if it exists.
9607c478bd9Sstevel@tonic-gate 	 */
9617c478bd9Sstevel@tonic-gate 	if (wbku_find_key(key_fp, NULL, &ka, NULL, B_FALSE) != WBKU_SUCCESS) {
9627c478bd9Sstevel@tonic-gate 		goto cleanup;
9637c478bd9Sstevel@tonic-gate 	}
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
9667c478bd9Sstevel@tonic-gate cleanup:
9677c478bd9Sstevel@tonic-gate 	if (key_fp != NULL) {
9687c478bd9Sstevel@tonic-gate 		(void) fclose(key_fp);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	return (ret);
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate static boolean_t
resolve_hostname(const char * hostname,nvlist_t * nvl,boolean_t may_be_crap)9757c478bd9Sstevel@tonic-gate resolve_hostname(const char *hostname, nvlist_t *nvl, boolean_t may_be_crap)
9767c478bd9Sstevel@tonic-gate {
9777c478bd9Sstevel@tonic-gate 	struct sockaddr_in	sin;
9787c478bd9Sstevel@tonic-gate 	struct hostent		*hp;
97922ce47f7SDavid Miner 	struct utsname		un;
98022ce47f7SDavid Miner 	static char 		myname[SYS_NMLN] = { '\0' };
98122ce47f7SDavid Miner 	char			*cp = NULL;
98222ce47f7SDavid Miner 	char			msg[WBCGI_MAXBUF];
9837c478bd9Sstevel@tonic-gate 
98422ce47f7SDavid Miner 	/*
98522ce47f7SDavid Miner 	 *  Initialize cached nodename
98622ce47f7SDavid Miner 	 */
98722ce47f7SDavid Miner 	if (strlen(myname) == 0) {
98822ce47f7SDavid Miner 		if (uname(&un) == -1) {
98922ce47f7SDavid Miner 			(void) snprintf(msg, sizeof (msg),
99022ce47f7SDavid Miner 			    "(unable to retrieve uname, errno %d)", errno);
99122ce47f7SDavid Miner 			print_status(500, msg);
99222ce47f7SDavid Miner 			return (B_FALSE);
99322ce47f7SDavid Miner 		}
99422ce47f7SDavid Miner 		(void) strcpy(myname, un.nodename);
99522ce47f7SDavid Miner 	}
99622ce47f7SDavid Miner 
99722ce47f7SDavid Miner 	/*
99822ce47f7SDavid Miner 	 * If hostname is local node name, return the address this
99922ce47f7SDavid Miner 	 * request came in on, which is supplied as SERVER_ADDR in the
100022ce47f7SDavid Miner 	 * cgi environment.  This ensures we don't send back a possible
100122ce47f7SDavid Miner 	 * alternate address that may be unreachable from the client's
100222ce47f7SDavid Miner 	 * network.  Otherwise, just resolve with nameservice.
100322ce47f7SDavid Miner 	 */
100422ce47f7SDavid Miner 	if ((strcmp(hostname, myname) != 0) ||
100522ce47f7SDavid Miner 	    ((cp = getenv("SERVER_ADDR")) == NULL)) {
10067c478bd9Sstevel@tonic-gate 		if (((hp = gethostbyname(hostname)) == NULL) ||
10077c478bd9Sstevel@tonic-gate 		    (hp->h_addrtype != AF_INET) ||
10087c478bd9Sstevel@tonic-gate 		    (hp->h_length != sizeof (struct in_addr))) {
10097c478bd9Sstevel@tonic-gate 			if (!may_be_crap) {
10107c478bd9Sstevel@tonic-gate 				print_status(500, "(error resolving hostname)");
10117c478bd9Sstevel@tonic-gate 			}
10127c478bd9Sstevel@tonic-gate 			return (may_be_crap);
10137c478bd9Sstevel@tonic-gate 		}
10147c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
101522ce47f7SDavid Miner 		cp = inet_ntoa(sin.sin_addr);
101622ce47f7SDavid Miner 	}
10177c478bd9Sstevel@tonic-gate 
101822ce47f7SDavid Miner 	if (nvlist_add_string(nvl, (char *)hostname, cp) != 0) {
10197c478bd9Sstevel@tonic-gate 		print_status(500, "(error adding hostname to nvlist)");
10207c478bd9Sstevel@tonic-gate 		return (B_FALSE);
10217c478bd9Sstevel@tonic-gate 	}
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	return (B_TRUE);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate /*
10277c478bd9Sstevel@tonic-gate  * one_name() is called for each certificate found and is passed the string
10287c478bd9Sstevel@tonic-gate  * that X509_NAME_oneline() returns.  Its job is to find the common name and
10297c478bd9Sstevel@tonic-gate  * determine whether it is a host name; if it is then a line suitable for
10307c478bd9Sstevel@tonic-gate  * inclusion in /etc/inet/hosts is written to that file.
10317c478bd9Sstevel@tonic-gate  */
10327c478bd9Sstevel@tonic-gate static boolean_t
one_name(const char * namestr,nvlist_t * nvl)10337c478bd9Sstevel@tonic-gate one_name(const char *namestr, nvlist_t *nvl)
10347c478bd9Sstevel@tonic-gate {
10357c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_TRUE;
10367c478bd9Sstevel@tonic-gate 	char		*p;
10377c478bd9Sstevel@tonic-gate 	char		*q;
10387c478bd9Sstevel@tonic-gate 	char		c;
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	if (namestr != NULL &&
10417c478bd9Sstevel@tonic-gate 	    (p = strstr(namestr, WBCGI_CNSTR)) != NULL) {
10427c478bd9Sstevel@tonic-gate 		p += WBCGI_CNSTR_LEN;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 		if ((q = strpbrk(p, WBCGI_NAMESEP)) != NULL) {
10457c478bd9Sstevel@tonic-gate 			c = *q;
10467c478bd9Sstevel@tonic-gate 			*q = '\0';
10477c478bd9Sstevel@tonic-gate 			ret = resolve_hostname(p, nvl, B_TRUE);
10487c478bd9Sstevel@tonic-gate 			*q = c;
10497c478bd9Sstevel@tonic-gate 		} else {
10507c478bd9Sstevel@tonic-gate 			ret = resolve_hostname(p, nvl, B_TRUE);
10517c478bd9Sstevel@tonic-gate 		}
10527c478bd9Sstevel@tonic-gate 	}
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	return (ret);
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate /*
10587c478bd9Sstevel@tonic-gate  * Loop through the certificates in a file
10597c478bd9Sstevel@tonic-gate  */
10607c478bd9Sstevel@tonic-gate static int
get_hostnames(const char * path,void * nvl)10617c478bd9Sstevel@tonic-gate get_hostnames(const char *path, void *nvl)
10627c478bd9Sstevel@tonic-gate {
10637c478bd9Sstevel@tonic-gate 	int		ret = WBCGI_FTW_CBERR;
10647c478bd9Sstevel@tonic-gate 	STACK_OF(X509)	*certs = NULL;
10657c478bd9Sstevel@tonic-gate 	PKCS12		*p12 = NULL;
10667c478bd9Sstevel@tonic-gate 	char		message[WBCGI_MAXBUF];
10677c478bd9Sstevel@tonic-gate 	char		buf[WBCGI_MAXBUF + 1];
10687c478bd9Sstevel@tonic-gate 	FILE		*rfp = NULL;
10697c478bd9Sstevel@tonic-gate 	X509		*x = NULL;
10707c478bd9Sstevel@tonic-gate 	int		errtype = 0;
10717c478bd9Sstevel@tonic-gate 	int		chars;
10727c478bd9Sstevel@tonic-gate 	int		i;
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	if ((rfp = fopen(path, "r")) == NULL) {
10757c478bd9Sstevel@tonic-gate 		goto cleanup;
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	if ((p12 = d2i_PKCS12_fp(rfp, NULL)) == NULL) {
10797c478bd9Sstevel@tonic-gate 		errtype = 1;
10807c478bd9Sstevel@tonic-gate 		goto cleanup;
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 	i = sunw_PKCS12_parse(p12, WANBOOT_PASSPHRASE, DO_NONE, NULL, 0, NULL,
10837c478bd9Sstevel@tonic-gate 	    NULL, NULL, &certs);
10847c478bd9Sstevel@tonic-gate 	if (i <= 0) {
10857c478bd9Sstevel@tonic-gate 		errtype = 1;
10867c478bd9Sstevel@tonic-gate 		goto cleanup;
10877c478bd9Sstevel@tonic-gate 	}
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	PKCS12_free(p12);
10907c478bd9Sstevel@tonic-gate 	p12 = NULL;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	for (i = 0; i < sk_X509_num(certs); i++) {
1093*d7141854SRobert Mustacchi 		/* LINTED */
10947c478bd9Sstevel@tonic-gate 		x = sk_X509_value(certs, i);
10957c478bd9Sstevel@tonic-gate 		if (!one_name(sunw_issuer_attrs(x, buf, sizeof (buf) - 1),
10967c478bd9Sstevel@tonic-gate 		    nvl)) {
10977c478bd9Sstevel@tonic-gate 			goto cleanup;
10987c478bd9Sstevel@tonic-gate 		}
10997c478bd9Sstevel@tonic-gate 	}
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	ret = WBCGI_FTW_CBCONT;
11027c478bd9Sstevel@tonic-gate cleanup:
11037c478bd9Sstevel@tonic-gate 	if (ret == WBCGI_FTW_CBERR) {
11047c478bd9Sstevel@tonic-gate 		if (errtype == 1) {
11057c478bd9Sstevel@tonic-gate 			chars = snprintf(message, sizeof (message),
11067c478bd9Sstevel@tonic-gate 			    "(internal PKCS12 error reading %s)", path);
11077c478bd9Sstevel@tonic-gate 		} else {
11087c478bd9Sstevel@tonic-gate 			chars = snprintf(message, sizeof (message),
11097c478bd9Sstevel@tonic-gate 			    "error reading %s", path);
11107c478bd9Sstevel@tonic-gate 		}
11117c478bd9Sstevel@tonic-gate 		if (chars > 0 && chars <= sizeof (message)) {
11127c478bd9Sstevel@tonic-gate 			print_status(500, message);
11137c478bd9Sstevel@tonic-gate 		} else {
11147c478bd9Sstevel@tonic-gate 			print_status(500, NULL);
11157c478bd9Sstevel@tonic-gate 		}
11167c478bd9Sstevel@tonic-gate 	}
11177c478bd9Sstevel@tonic-gate 	if (rfp != NULL) {
11187c478bd9Sstevel@tonic-gate 		(void) fclose(rfp);
11197c478bd9Sstevel@tonic-gate 	}
11207c478bd9Sstevel@tonic-gate 	if (p12 != NULL) {
11217c478bd9Sstevel@tonic-gate 		PKCS12_free(p12);
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 	if (certs != NULL) {
11247c478bd9Sstevel@tonic-gate 		sk_X509_pop_free(certs, X509_free);
11257c478bd9Sstevel@tonic-gate 	}
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	return (ret);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate /*
11317c478bd9Sstevel@tonic-gate  * Create a hosts file by extracting hosts from client and truststore
11327c478bd9Sstevel@tonic-gate  * files.  Use the CN. Then we should copy that file to the inet dir.
11337c478bd9Sstevel@tonic-gate  */
11347c478bd9Sstevel@tonic-gate static boolean_t
create_hostsfile(const char * hostsfile,const char * net,const char * cid)11357c478bd9Sstevel@tonic-gate create_hostsfile(const char *hostsfile, const char *net, const char *cid)
11367c478bd9Sstevel@tonic-gate {
11377c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
11387c478bd9Sstevel@tonic-gate 	nvlist_t	*nvl;
11397c478bd9Sstevel@tonic-gate 	nvpair_t	*nvp;
11407c478bd9Sstevel@tonic-gate 	FILE		*hostfp = NULL;
11417c478bd9Sstevel@tonic-gate 	int		hostfd = -1;
11427c478bd9Sstevel@tonic-gate 	int		i;
11437c478bd9Sstevel@tonic-gate 	char		*hostslist;
11447c478bd9Sstevel@tonic-gate 	const char	*bc_urls[] = { BC_ROOT_SERVER, BC_BOOT_LOGGER, NULL };
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	/*
11477c478bd9Sstevel@tonic-gate 	 * Allocate nvlist handle to store our hostname/IP pairs.
11487c478bd9Sstevel@tonic-gate 	 */
11497c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
11507c478bd9Sstevel@tonic-gate 		print_status(500, "(error allocating hostname nvlist)");
11517c478bd9Sstevel@tonic-gate 		goto cleanup;
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	/*
11557c478bd9Sstevel@tonic-gate 	 * Extract and resolve hostnames from CNs.
11567c478bd9Sstevel@tonic-gate 	 */
11577c478bd9Sstevel@tonic-gate 	if (netboot_ftw(NB_CLIENT_CERT, net, cid,
11587c478bd9Sstevel@tonic-gate 	    get_hostnames, nvl) == WBCGI_FTW_CBERR ||
11597c478bd9Sstevel@tonic-gate 	    netboot_ftw(NB_CA_CERT, net, cid,
11607c478bd9Sstevel@tonic-gate 	    get_hostnames, nvl) == WBCGI_FTW_CBERR) {
11617c478bd9Sstevel@tonic-gate 		goto cleanup;
11627c478bd9Sstevel@tonic-gate 	}
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	/*
11657c478bd9Sstevel@tonic-gate 	 * Extract and resolve hostnames from any URLs in bootconf.
11667c478bd9Sstevel@tonic-gate 	 */
11677c478bd9Sstevel@tonic-gate 	for (i = 0; bc_urls[i] != NULL; ++i) {
11687c478bd9Sstevel@tonic-gate 		char	*urlstr;
11697c478bd9Sstevel@tonic-gate 		url_t	url;
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate 		if ((urlstr = bootconf_get(&bc_handle, bc_urls[i])) != NULL &&
11727c478bd9Sstevel@tonic-gate 		    url_parse(urlstr, &url) == URL_PARSE_SUCCESS) {
11737c478bd9Sstevel@tonic-gate 			if (!resolve_hostname(url.hport.hostname,
11747c478bd9Sstevel@tonic-gate 			    nvl, B_FALSE)) {
11757c478bd9Sstevel@tonic-gate 				goto cleanup;
11767c478bd9Sstevel@tonic-gate 			}
11777c478bd9Sstevel@tonic-gate 		}
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	/*
11817c478bd9Sstevel@tonic-gate 	 * If there is a resolve-hosts list in bootconf, resolve those
11827c478bd9Sstevel@tonic-gate 	 * hostnames too.
11837c478bd9Sstevel@tonic-gate 	 */
11847c478bd9Sstevel@tonic-gate 	if ((hostslist = bootconf_get(&bc_handle, BC_RESOLVE_HOSTS)) != NULL) {
11857c478bd9Sstevel@tonic-gate 		char	*hostname;
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 		for (hostname = strtok(hostslist, ","); hostname != NULL;
11887c478bd9Sstevel@tonic-gate 		    hostname = strtok(NULL, ",")) {
11897c478bd9Sstevel@tonic-gate 			if (!resolve_hostname(hostname, nvl, B_FALSE)) {
11907c478bd9Sstevel@tonic-gate 				goto cleanup;
11917c478bd9Sstevel@tonic-gate 			}
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	/*
11967c478bd9Sstevel@tonic-gate 	 * Now write the hostname/IP pairs gathered to the hosts file.
11977c478bd9Sstevel@tonic-gate 	 */
11987c478bd9Sstevel@tonic-gate 	if ((hostfd = open(hostsfile,
11997c478bd9Sstevel@tonic-gate 	    O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
12007c478bd9Sstevel@tonic-gate 	    (hostfp = fdopen(hostfd, "w+")) == NULL) {
12017c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating hosts file)");
12027c478bd9Sstevel@tonic-gate 		goto cleanup;
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 	for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
12057c478bd9Sstevel@tonic-gate 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
12067c478bd9Sstevel@tonic-gate 		char	*hostname;
12077c478bd9Sstevel@tonic-gate 		char	*ipstr;
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 		hostname = nvpair_name(nvp);
12107c478bd9Sstevel@tonic-gate 		if (nvpair_value_string(nvp, &ipstr) != 0) {
12117c478bd9Sstevel@tonic-gate 			print_status(500, "(nvl error writing hosts file)");
12127c478bd9Sstevel@tonic-gate 			goto cleanup;
12137c478bd9Sstevel@tonic-gate 		}
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 		if (fprintf(hostfp, "%s\t%s\n", ipstr, hostname) < 0) {
12167c478bd9Sstevel@tonic-gate 			print_status(500, "(error writing hosts file)");
12177c478bd9Sstevel@tonic-gate 			goto cleanup;
12187c478bd9Sstevel@tonic-gate 		}
12197c478bd9Sstevel@tonic-gate 	}
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
12227c478bd9Sstevel@tonic-gate cleanup:
12237c478bd9Sstevel@tonic-gate 	if (nvl != NULL) {
12247c478bd9Sstevel@tonic-gate 		nvlist_free(nvl);
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate 	if (hostfp != NULL) {
12277c478bd9Sstevel@tonic-gate 		/*
12287c478bd9Sstevel@tonic-gate 		 * hostfd is automatically closed as well.
12297c478bd9Sstevel@tonic-gate 		 */
12307c478bd9Sstevel@tonic-gate 		(void) fclose(hostfp);
12317c478bd9Sstevel@tonic-gate 	}
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 	return (ret);
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate static boolean_t
bootfile_payload(const char * docroot,char ** bootpathp)12377c478bd9Sstevel@tonic-gate bootfile_payload(const char *docroot, char **bootpathp)
12387c478bd9Sstevel@tonic-gate {
12397c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
12407c478bd9Sstevel@tonic-gate 	char		*boot_file;
12417c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	if ((boot_file = bootconf_get(&bc_handle, BC_BOOT_FILE)) == NULL) {
12447c478bd9Sstevel@tonic-gate 		print_status(500, "(boot_file must be specified)");
12457c478bd9Sstevel@tonic-gate 		goto cleanup;
12467c478bd9Sstevel@tonic-gate 	}
12477c478bd9Sstevel@tonic-gate 	if ((*bootpathp = make_path(docroot, boot_file)) == NULL) {
12487c478bd9Sstevel@tonic-gate 		goto cleanup;
12497c478bd9Sstevel@tonic-gate 	}
12507c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(*bootpathp, sbuf)) {
12517c478bd9Sstevel@tonic-gate 		print_status(500, "(boot_file missing)");
12527c478bd9Sstevel@tonic-gate 		goto cleanup;
12537c478bd9Sstevel@tonic-gate 	}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
12567c478bd9Sstevel@tonic-gate cleanup:
12577c478bd9Sstevel@tonic-gate 	return (ret);
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate /*
12617c478bd9Sstevel@tonic-gate  * Create the wanboot file system whose contents are determined by the
12627c478bd9Sstevel@tonic-gate  * security configuration specified in bootconf.
12637c478bd9Sstevel@tonic-gate  */
12647c478bd9Sstevel@tonic-gate static boolean_t
wanbootfs_payload(const char * net,const char * cid,const char * nonce,const char * bootconf,char ** wanbootfs_imagep)12657c478bd9Sstevel@tonic-gate wanbootfs_payload(const char *net, const char *cid, const char *nonce,
12667c478bd9Sstevel@tonic-gate     const char *bootconf, char **wanbootfs_imagep)
12677c478bd9Sstevel@tonic-gate {
12687c478bd9Sstevel@tonic-gate 	int		ret = B_FALSE;
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	char		*server_authentication;
12717c478bd9Sstevel@tonic-gate 	char		*client_authentication;
12727c478bd9Sstevel@tonic-gate 	char		*scf;
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate 	char		*bootfs_dir = NULL;
12757c478bd9Sstevel@tonic-gate 	char		*bootfs_etc_dir = NULL;
12767c478bd9Sstevel@tonic-gate 	char		*bootfs_etc_inet_dir = NULL;
12777c478bd9Sstevel@tonic-gate 	char		*bootfs_dev_dir = NULL;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	char		*systemconf = NULL;
12807c478bd9Sstevel@tonic-gate 	char		*keystorepath = NULL;
12817c478bd9Sstevel@tonic-gate 	char		*certstorepath = NULL;
12827c478bd9Sstevel@tonic-gate 	char		*truststorepath = NULL;
12837c478bd9Sstevel@tonic-gate 	char		*bootconfpath = NULL;
12847c478bd9Sstevel@tonic-gate 	char		*systemconfpath = NULL;
12857c478bd9Sstevel@tonic-gate 	char		*urandompath = NULL;
12867c478bd9Sstevel@tonic-gate 	char		*noncepath = NULL;
12877c478bd9Sstevel@tonic-gate 	char		*hostspath = NULL;
12887c478bd9Sstevel@tonic-gate 	char		*etc_hostspath = NULL;
12897c478bd9Sstevel@tonic-gate 	char		*timestamppath = NULL;
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	boolean_t	authenticate_client;
12927c478bd9Sstevel@tonic-gate 	boolean_t	authenticate_server;
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	/*
12977c478bd9Sstevel@tonic-gate 	 * Initialize SSL stuff.
12987c478bd9Sstevel@tonic-gate 	 */
12997c478bd9Sstevel@tonic-gate 	sunw_crypto_init();
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	/*
13027c478bd9Sstevel@tonic-gate 	 * Get the security strategy values.
13037c478bd9Sstevel@tonic-gate 	 */
13047c478bd9Sstevel@tonic-gate 	client_authentication = bootconf_get(&bc_handle,
13057c478bd9Sstevel@tonic-gate 	    BC_CLIENT_AUTHENTICATION);
13067c478bd9Sstevel@tonic-gate 	authenticate_client = (client_authentication != NULL &&
13077c478bd9Sstevel@tonic-gate 	    strcmp(client_authentication, "yes") == 0);
13087c478bd9Sstevel@tonic-gate 	server_authentication = bootconf_get(&bc_handle,
13097c478bd9Sstevel@tonic-gate 	    BC_SERVER_AUTHENTICATION);
13107c478bd9Sstevel@tonic-gate 	authenticate_server = (server_authentication != NULL &&
13117c478bd9Sstevel@tonic-gate 	    strcmp(server_authentication, "yes") == 0);
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate 	/*
13147c478bd9Sstevel@tonic-gate 	 * Make a temporary directory structure for the wanboot file system.
13157c478bd9Sstevel@tonic-gate 	 */
13167c478bd9Sstevel@tonic-gate 	if ((bootfs_dir = gen_tmppath("bootfs_dir", net, cid)) == NULL ||
13177c478bd9Sstevel@tonic-gate 	    (bootfs_etc_dir = make_path(bootfs_dir, "etc")) == NULL ||
13187c478bd9Sstevel@tonic-gate 	    (bootfs_etc_inet_dir = make_path(bootfs_etc_dir, "inet")) == NULL ||
13197c478bd9Sstevel@tonic-gate 	    (bootfs_dev_dir = make_path(bootfs_dir, "dev")) == NULL) {
13207c478bd9Sstevel@tonic-gate 		goto cleanup;
13217c478bd9Sstevel@tonic-gate 	}
13227c478bd9Sstevel@tonic-gate 	if (mkdirp(bootfs_dir, 0700) ||
13237c478bd9Sstevel@tonic-gate 	    mkdirp(bootfs_etc_dir, 0700) ||
13247c478bd9Sstevel@tonic-gate 	    mkdirp(bootfs_etc_inet_dir, 0700) ||
13257c478bd9Sstevel@tonic-gate 	    mkdirp(bootfs_dev_dir, 0700)) {
13267c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating wanbootfs dir structure)");
13277c478bd9Sstevel@tonic-gate 		goto cleanup;
13287c478bd9Sstevel@tonic-gate 	}
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 	if (authenticate_client) {
13317c478bd9Sstevel@tonic-gate 		/*
13327c478bd9Sstevel@tonic-gate 		 * Add the client private key.
13337c478bd9Sstevel@tonic-gate 		 */
13347c478bd9Sstevel@tonic-gate 		if ((keystorepath = make_path(bootfs_dir,
13357c478bd9Sstevel@tonic-gate 		    NB_CLIENT_KEY)) == NULL ||
13367c478bd9Sstevel@tonic-gate 		    netboot_ftw(NB_CLIENT_KEY, net, cid,
13377c478bd9Sstevel@tonic-gate 		    create_keystore, keystorepath) != WBCGI_FTW_CBOK) {
13387c478bd9Sstevel@tonic-gate 			goto cleanup;
13397c478bd9Sstevel@tonic-gate 		}
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 		/*
13427c478bd9Sstevel@tonic-gate 		 * Add the client certificate.
13437c478bd9Sstevel@tonic-gate 		 */
13447c478bd9Sstevel@tonic-gate 		if ((certstorepath = make_path(bootfs_dir,
13457c478bd9Sstevel@tonic-gate 		    NB_CLIENT_CERT)) == NULL ||
13467c478bd9Sstevel@tonic-gate 		    netboot_ftw(NB_CLIENT_CERT, net, cid,
13477c478bd9Sstevel@tonic-gate 		    copy_certstore, certstorepath) != WBCGI_FTW_CBOK) {
13487c478bd9Sstevel@tonic-gate 			goto cleanup;
13497c478bd9Sstevel@tonic-gate 		}
13507c478bd9Sstevel@tonic-gate 	}
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	if (authenticate_client || authenticate_server) {
13537c478bd9Sstevel@tonic-gate 		/*
13547c478bd9Sstevel@tonic-gate 		 * Add the trustfile; at least one truststore must exist.
13557c478bd9Sstevel@tonic-gate 		 */
13567c478bd9Sstevel@tonic-gate 		if ((truststorepath = make_path(bootfs_dir,
13577c478bd9Sstevel@tonic-gate 		    NB_CA_CERT)) == NULL) {
13587c478bd9Sstevel@tonic-gate 			goto cleanup;
13597c478bd9Sstevel@tonic-gate 		}
13607c478bd9Sstevel@tonic-gate 		if (netboot_ftw(NB_CA_CERT, net, cid,
13617c478bd9Sstevel@tonic-gate 		    noact_cb, NULL) != WBCGI_FTW_CBOK) {
13627c478bd9Sstevel@tonic-gate 			print_status(500, "(truststore not found)");
13637c478bd9Sstevel@tonic-gate 		}
13647c478bd9Sstevel@tonic-gate 		if (netboot_ftw(NB_CA_CERT, net, cid,
13657c478bd9Sstevel@tonic-gate 		    build_trustfile, truststorepath) == WBCGI_FTW_CBERR) {
13667c478bd9Sstevel@tonic-gate 			goto cleanup;
13677c478bd9Sstevel@tonic-gate 		}
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 		/*
13707c478bd9Sstevel@tonic-gate 		 * Create the /dev/urandom file.
13717c478bd9Sstevel@tonic-gate 		 */
13727c478bd9Sstevel@tonic-gate 		if ((urandompath = make_path(bootfs_dev_dir,
13737c478bd9Sstevel@tonic-gate 		    "urandom")) == NULL ||
13747c478bd9Sstevel@tonic-gate 		    !create_urandom(urandompath)) {
13757c478bd9Sstevel@tonic-gate 			goto cleanup;
13767c478bd9Sstevel@tonic-gate 		}
13777c478bd9Sstevel@tonic-gate 	}
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 	/*
13807c478bd9Sstevel@tonic-gate 	 * Add the wanboot.conf(4) file.
13817c478bd9Sstevel@tonic-gate 	 */
13827c478bd9Sstevel@tonic-gate 	if ((bootconfpath = make_path(bootfs_dir, NB_WANBOOT_CONF)) == NULL ||
13837c478bd9Sstevel@tonic-gate 	    !copy_file(bootconf, bootconfpath)) {
13847c478bd9Sstevel@tonic-gate 		goto cleanup;
13857c478bd9Sstevel@tonic-gate 	}
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	/*
13887c478bd9Sstevel@tonic-gate 	 * Add the system_conf file if present.
13897c478bd9Sstevel@tonic-gate 	 */
13907c478bd9Sstevel@tonic-gate 	if ((scf = bootconf_get(&bc_handle, BC_SYSTEM_CONF)) != NULL) {
13917c478bd9Sstevel@tonic-gate 		if (netboot_ftw(scf, net, cid,
13927c478bd9Sstevel@tonic-gate 		    set_pathname, &systemconf) != WBCGI_FTW_CBOK) {
13937c478bd9Sstevel@tonic-gate 			print_status(500, "(system_conf file not found)");
13947c478bd9Sstevel@tonic-gate 			goto cleanup;
13957c478bd9Sstevel@tonic-gate 		}
13967c478bd9Sstevel@tonic-gate 		if ((systemconfpath = make_path(bootfs_dir,
13977c478bd9Sstevel@tonic-gate 		    NB_SYSTEM_CONF)) == NULL ||
13987c478bd9Sstevel@tonic-gate 		    !copy_file(systemconf, systemconfpath)) {
13997c478bd9Sstevel@tonic-gate 			goto cleanup;
14007c478bd9Sstevel@tonic-gate 		}
14017c478bd9Sstevel@tonic-gate 	}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	/*
14047c478bd9Sstevel@tonic-gate 	 * Create the /nonce file.
14057c478bd9Sstevel@tonic-gate 	 */
14067c478bd9Sstevel@tonic-gate 	if ((noncepath = make_path(bootfs_dir, "nonce")) == NULL ||
14077c478bd9Sstevel@tonic-gate 	    !create_nonce(noncepath, nonce)) {
14087c478bd9Sstevel@tonic-gate 		goto cleanup;
14097c478bd9Sstevel@tonic-gate 	}
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	/*
14127c478bd9Sstevel@tonic-gate 	 * Create an /etc/inet/hosts file by extracting hostnames from CN,
14137c478bd9Sstevel@tonic-gate 	 * URLs in bootconf and resolve-hosts in bootconf.
14147c478bd9Sstevel@tonic-gate 	 */
14157c478bd9Sstevel@tonic-gate 	if ((hostspath = make_path(bootfs_etc_inet_dir, "hosts")) == NULL ||
14167c478bd9Sstevel@tonic-gate 	    !create_hostsfile(hostspath, net, cid)) {
14177c478bd9Sstevel@tonic-gate 		goto cleanup;
14187c478bd9Sstevel@tonic-gate 	}
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	/*
14217c478bd9Sstevel@tonic-gate 	 * We would like to create a symbolic link etc/hosts -> etc/inet/hosts,
14227c478bd9Sstevel@tonic-gate 	 * but unfortunately the HSFS support in the standalone doesn't handle
14237c478bd9Sstevel@tonic-gate 	 * symlinks.
14247c478bd9Sstevel@tonic-gate 	 */
14257c478bd9Sstevel@tonic-gate 	if ((etc_hostspath = make_path(bootfs_etc_dir, "hosts")) == NULL ||
14267c478bd9Sstevel@tonic-gate 	    !copy_file(hostspath, etc_hostspath)) {
14277c478bd9Sstevel@tonic-gate 		goto cleanup;
14287c478bd9Sstevel@tonic-gate 	}
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate 	/*
14317c478bd9Sstevel@tonic-gate 	 * Create the /timestamp file.
14327c478bd9Sstevel@tonic-gate 	 */
14337c478bd9Sstevel@tonic-gate 	if ((timestamppath = make_path(bootfs_dir, "timestamp")) == NULL ||
14347c478bd9Sstevel@tonic-gate 	    !create_timestamp(timestamppath, "timestamp")) {
14357c478bd9Sstevel@tonic-gate 		goto cleanup;
14367c478bd9Sstevel@tonic-gate 	}
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	/*
14397c478bd9Sstevel@tonic-gate 	 * Create an HSFS file system for the directory.
14407c478bd9Sstevel@tonic-gate 	 */
14417c478bd9Sstevel@tonic-gate 	if ((*wanbootfs_imagep = gen_tmppath("wanbootfs", net, cid)) == NULL ||
14427c478bd9Sstevel@tonic-gate 	    !mkisofs(bootfs_dir, *wanbootfs_imagep)) {
14437c478bd9Sstevel@tonic-gate 		goto cleanup;
14447c478bd9Sstevel@tonic-gate 	}
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
14477c478bd9Sstevel@tonic-gate cleanup:
14487c478bd9Sstevel@tonic-gate 	/*
14497c478bd9Sstevel@tonic-gate 	 * Clean up temporary files and directories.
14507c478bd9Sstevel@tonic-gate 	 */
14517c478bd9Sstevel@tonic-gate 	if (keystorepath != NULL &&
14527c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(keystorepath, sbuf)) {
14537c478bd9Sstevel@tonic-gate 		(void) unlink(keystorepath);
14547c478bd9Sstevel@tonic-gate 	}
14557c478bd9Sstevel@tonic-gate 	if (certstorepath != NULL &&
14567c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(certstorepath, sbuf)) {
14577c478bd9Sstevel@tonic-gate 		(void) unlink(certstorepath);
14587c478bd9Sstevel@tonic-gate 	}
14597c478bd9Sstevel@tonic-gate 	if (truststorepath != NULL &&
14607c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(truststorepath, sbuf)) {
14617c478bd9Sstevel@tonic-gate 		(void) unlink(truststorepath);
14627c478bd9Sstevel@tonic-gate 	}
14637c478bd9Sstevel@tonic-gate 	if (bootconfpath != NULL &&
14647c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(bootconfpath, sbuf)) {
14657c478bd9Sstevel@tonic-gate 		(void) unlink(bootconfpath);
14667c478bd9Sstevel@tonic-gate 	}
14677c478bd9Sstevel@tonic-gate 	if (systemconfpath != NULL &&
14687c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(systemconfpath, sbuf)) {
14697c478bd9Sstevel@tonic-gate 		(void) unlink(systemconfpath);
14707c478bd9Sstevel@tonic-gate 	}
14717c478bd9Sstevel@tonic-gate 	if (urandompath != NULL &&
14727c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(urandompath, sbuf)) {
14737c478bd9Sstevel@tonic-gate 		(void) unlink(urandompath);
14747c478bd9Sstevel@tonic-gate 	}
14757c478bd9Sstevel@tonic-gate 	if (noncepath != NULL &&
14767c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(noncepath, sbuf)) {
14777c478bd9Sstevel@tonic-gate 		(void) unlink(noncepath);
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 	if (hostspath != NULL &&
14807c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(hostspath, sbuf)) {
14817c478bd9Sstevel@tonic-gate 		(void) unlink(hostspath);
14827c478bd9Sstevel@tonic-gate 	}
14837c478bd9Sstevel@tonic-gate 	if (etc_hostspath != NULL &&
14847c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(etc_hostspath, sbuf)) {
14857c478bd9Sstevel@tonic-gate 		(void) unlink(etc_hostspath);
14867c478bd9Sstevel@tonic-gate 	}
14877c478bd9Sstevel@tonic-gate 	if (timestamppath != NULL &&
14887c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(timestamppath, sbuf)) {
14897c478bd9Sstevel@tonic-gate 		(void) unlink(timestamppath);
14907c478bd9Sstevel@tonic-gate 	}
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 	if (bootfs_etc_inet_dir != NULL &&
14937c478bd9Sstevel@tonic-gate 	    WBCGI_DIR_EXISTS(bootfs_etc_inet_dir, sbuf)) {
14947c478bd9Sstevel@tonic-gate 		(void) rmdir(bootfs_etc_inet_dir);
14957c478bd9Sstevel@tonic-gate 	}
14967c478bd9Sstevel@tonic-gate 	if (bootfs_etc_dir != NULL &&
14977c478bd9Sstevel@tonic-gate 	    WBCGI_DIR_EXISTS(bootfs_etc_dir, sbuf)) {
14987c478bd9Sstevel@tonic-gate 		(void) rmdir(bootfs_etc_dir);
14997c478bd9Sstevel@tonic-gate 	}
15007c478bd9Sstevel@tonic-gate 	if (bootfs_dev_dir != NULL &&
15017c478bd9Sstevel@tonic-gate 	    WBCGI_DIR_EXISTS(bootfs_dev_dir, sbuf)) {
15027c478bd9Sstevel@tonic-gate 		(void) rmdir(bootfs_dev_dir);
15037c478bd9Sstevel@tonic-gate 	}
15047c478bd9Sstevel@tonic-gate 	if (bootfs_dir != NULL &&
15057c478bd9Sstevel@tonic-gate 	    WBCGI_DIR_EXISTS(bootfs_dir, sbuf)) {
15067c478bd9Sstevel@tonic-gate 		(void) rmdir(bootfs_dir);
15077c478bd9Sstevel@tonic-gate 	}
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 	/*
15107c478bd9Sstevel@tonic-gate 	 * Free allocated memory.
15117c478bd9Sstevel@tonic-gate 	 */
15127c478bd9Sstevel@tonic-gate 	free_path(&bootfs_dir);
15137c478bd9Sstevel@tonic-gate 	free_path(&bootfs_etc_dir);
15147c478bd9Sstevel@tonic-gate 	free_path(&bootfs_etc_inet_dir);
15157c478bd9Sstevel@tonic-gate 	free_path(&bootfs_dev_dir);
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 	free_path(&systemconf);
15187c478bd9Sstevel@tonic-gate 	free_path(&keystorepath);
15197c478bd9Sstevel@tonic-gate 	free_path(&certstorepath);
15207c478bd9Sstevel@tonic-gate 	free_path(&truststorepath);
15217c478bd9Sstevel@tonic-gate 	free_path(&bootconfpath);
15227c478bd9Sstevel@tonic-gate 	free_path(&systemconfpath);
15237c478bd9Sstevel@tonic-gate 	free_path(&urandompath);
15247c478bd9Sstevel@tonic-gate 	free_path(&noncepath);
15257c478bd9Sstevel@tonic-gate 	free_path(&hostspath);
15267c478bd9Sstevel@tonic-gate 	free_path(&etc_hostspath);
15277c478bd9Sstevel@tonic-gate 	free_path(&timestamppath);
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 	return (ret);
15307c478bd9Sstevel@tonic-gate }
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate static boolean_t
miniroot_payload(const char * net,const char * cid,const char * docroot,char ** rootpathp,char ** rootinfop,boolean_t * https_rootserverp)15337c478bd9Sstevel@tonic-gate miniroot_payload(const char *net, const char *cid, const char *docroot,
15347c478bd9Sstevel@tonic-gate     char **rootpathp, char **rootinfop, boolean_t *https_rootserverp)
15357c478bd9Sstevel@tonic-gate {
15367c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
15377c478bd9Sstevel@tonic-gate 	char		*root_server;
15387c478bd9Sstevel@tonic-gate 	char		*root_file;
15397c478bd9Sstevel@tonic-gate 	url_t		url;
15407c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
15417c478bd9Sstevel@tonic-gate 	char		sizebuf[WBCGI_MAXBUF];
15427c478bd9Sstevel@tonic-gate 	int		chars;
15437c478bd9Sstevel@tonic-gate 	int		fd = -1;
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	if ((root_server = bootconf_get(&bc_handle, BC_ROOT_SERVER)) == NULL) {
15467c478bd9Sstevel@tonic-gate 		print_status(500, "(root_server must be specified)");
15477c478bd9Sstevel@tonic-gate 		goto cleanup;
15487c478bd9Sstevel@tonic-gate 	}
15497c478bd9Sstevel@tonic-gate 	if (url_parse(root_server, &url) != URL_PARSE_SUCCESS) {
15507c478bd9Sstevel@tonic-gate 		print_status(500, "(root_server URL is invalid)");
15517c478bd9Sstevel@tonic-gate 	}
15527c478bd9Sstevel@tonic-gate 	*https_rootserverp = url.https;
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 	if ((root_file = bootconf_get(&bc_handle, BC_ROOT_FILE)) == NULL) {
15557c478bd9Sstevel@tonic-gate 		print_status(500, "(rootfile must be specified)");
15567c478bd9Sstevel@tonic-gate 		goto cleanup;
15577c478bd9Sstevel@tonic-gate 	}
15587c478bd9Sstevel@tonic-gate 	if ((*rootpathp = make_path(docroot, root_file)) == NULL) {
15597c478bd9Sstevel@tonic-gate 		goto cleanup;
15607c478bd9Sstevel@tonic-gate 	}
15617c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(*rootpathp, sbuf)) {
15627c478bd9Sstevel@tonic-gate 		print_status(500, "(root filesystem image missing)");
15637c478bd9Sstevel@tonic-gate 		goto cleanup;
15647c478bd9Sstevel@tonic-gate 	}
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	if ((*rootinfop = gen_tmppath("mrinfo", net, cid)) == NULL) {
15677c478bd9Sstevel@tonic-gate 		goto cleanup;
15687c478bd9Sstevel@tonic-gate 	}
15697c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(sizebuf, sizeof (sizebuf), "%ld",
15707c478bd9Sstevel@tonic-gate 	    sbuf.st_size)) < 0 || chars > sizeof (sizebuf) ||
15717c478bd9Sstevel@tonic-gate 	    (fd = open(*rootinfop,
15727c478bd9Sstevel@tonic-gate 	    O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) == -1 ||
15737c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, sizebuf, strlen(sizebuf))) {
15747c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating miniroot info file)");
15757c478bd9Sstevel@tonic-gate 		goto cleanup;
15767c478bd9Sstevel@tonic-gate 	}
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 	ret = B_TRUE;
15797c478bd9Sstevel@tonic-gate cleanup:
15807c478bd9Sstevel@tonic-gate 	if (fd != -1) {
15817c478bd9Sstevel@tonic-gate 		(void) close(fd);
15827c478bd9Sstevel@tonic-gate 	}
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 	return (ret);
15857c478bd9Sstevel@tonic-gate }
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate static boolean_t
deliver_payload(const char * payload,const char * payload_hash)15887c478bd9Sstevel@tonic-gate deliver_payload(const char *payload, const char *payload_hash)
15897c478bd9Sstevel@tonic-gate {
15907c478bd9Sstevel@tonic-gate 	int		fd = fileno(stdout);
15917c478bd9Sstevel@tonic-gate 	struct stat	payload_buf, hash_buf;
15927c478bd9Sstevel@tonic-gate 	int		chars;
15937c478bd9Sstevel@tonic-gate 	char		main_header[WBCGI_MAXBUF];
15947c478bd9Sstevel@tonic-gate 	char		multi_header[WBCGI_MAXBUF];
15957c478bd9Sstevel@tonic-gate 	char		multi_header1[WBCGI_MAXBUF];
15967c478bd9Sstevel@tonic-gate 	char		multi_header2[WBCGI_MAXBUF];
15977c478bd9Sstevel@tonic-gate 	char		multi_end[WBCGI_MAXBUF];
15987c478bd9Sstevel@tonic-gate 	size_t		msglen;
15997c478bd9Sstevel@tonic-gate 
16007c478bd9Sstevel@tonic-gate 	if (!WBCGI_FILE_EXISTS(payload, payload_buf) ||
16017c478bd9Sstevel@tonic-gate 	    !WBCGI_FILE_EXISTS(payload_hash, hash_buf)) {
16027c478bd9Sstevel@tonic-gate 		print_status(500, "(payload/hash file(s) missing)");
16037c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16047c478bd9Sstevel@tonic-gate 	}
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	/*
16077c478bd9Sstevel@tonic-gate 	 * Multi-part header.
16087c478bd9Sstevel@tonic-gate 	 */
16097c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(multi_header, sizeof (multi_header),
16107c478bd9Sstevel@tonic-gate 	    "%s--%s%s%sapplication/octet-stream%s%s", WBCGI_CRNL,
16117c478bd9Sstevel@tonic-gate 	    WBCGI_WANBOOT_BNDTXT, WBCGI_CRNL, WBCGI_CONTENT_TYPE, WBCGI_CRNL,
16127c478bd9Sstevel@tonic-gate 	    WBCGI_CONTENT_LENGTH)) < 0 || chars > sizeof (multi_header)) {
16137c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating multi_header)");
16147c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16157c478bd9Sstevel@tonic-gate 	}
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	/*
16187c478bd9Sstevel@tonic-gate 	 * Multi-part header for part one.
16197c478bd9Sstevel@tonic-gate 	 */
16207c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(multi_header1, sizeof (multi_header1),
16217c478bd9Sstevel@tonic-gate 	    "%s%ld%s%s", multi_header, payload_buf.st_size, WBCGI_CRNL,
16227c478bd9Sstevel@tonic-gate 	    WBCGI_CRNL)) < 0 || chars > sizeof (multi_header1)) {
16237c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating multi_header1)");
16247c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 	/*
16287c478bd9Sstevel@tonic-gate 	 * Multi-part header for part two.
16297c478bd9Sstevel@tonic-gate 	 */
16307c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(multi_header2, sizeof (multi_header2),
16317c478bd9Sstevel@tonic-gate 	    "%s%ld%s%s", multi_header, hash_buf.st_size, WBCGI_CRNL,
16327c478bd9Sstevel@tonic-gate 	    WBCGI_CRNL)) < 0 || chars > sizeof (multi_header2)) {
16337c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating multi_header2)");
16347c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 
16377c478bd9Sstevel@tonic-gate 	/*
16387c478bd9Sstevel@tonic-gate 	 * End-of-parts Trailer.
16397c478bd9Sstevel@tonic-gate 	 */
16407c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(multi_end, sizeof (multi_end),
16417c478bd9Sstevel@tonic-gate 	    "%s--%s--%s", WBCGI_CRNL, WBCGI_WANBOOT_BNDTXT,
16427c478bd9Sstevel@tonic-gate 	    WBCGI_CRNL)) < 0 || chars > sizeof (multi_end)) {
16437c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating multi_end)");
16447c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16457c478bd9Sstevel@tonic-gate 	}
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 	/*
16487c478bd9Sstevel@tonic-gate 	 * Message header.
16497c478bd9Sstevel@tonic-gate 	 */
16507c478bd9Sstevel@tonic-gate 	msglen = payload_buf.st_size +  hash_buf.st_size +
16517c478bd9Sstevel@tonic-gate 	    strlen(multi_header1) + strlen(multi_header2) + strlen(multi_end);
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 	if ((chars = snprintf(main_header, sizeof (main_header),
16547c478bd9Sstevel@tonic-gate 	    "%s%u%s%smultipart/mixed; boundary=%s%s%s", WBCGI_CONTENT_LENGTH,
16557c478bd9Sstevel@tonic-gate 	    msglen, WBCGI_CRNL, WBCGI_CONTENT_TYPE, WBCGI_WANBOOT_BNDTXT,
16567c478bd9Sstevel@tonic-gate 	    WBCGI_CRNL, WBCGI_CRNL)) < 0 || chars > sizeof (main_header)) {
16577c478bd9Sstevel@tonic-gate 		print_status(500, "(error creating main_header)");
16587c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16597c478bd9Sstevel@tonic-gate 	}
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 	/*
16627c478bd9Sstevel@tonic-gate 	 * Write the message out.  If things fall apart during this then
16637c478bd9Sstevel@tonic-gate 	 * there's no way to report the error back to the client.
16647c478bd9Sstevel@tonic-gate 	 */
16657c478bd9Sstevel@tonic-gate 	if (!write_buffer(fd, main_header, strlen(main_header)) ||
16667c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, multi_header1, strlen(multi_header1)) ||
16677c478bd9Sstevel@tonic-gate 	    !write_file(fd, payload, payload_buf.st_size) ||
16687c478bd9Sstevel@tonic-gate 	    !write_buffer(fd, multi_header2, strlen(multi_header2)) ||
16697c478bd9Sstevel@tonic-gate 	    !write_file(fd, payload_hash, hash_buf.st_size) ||
16707c478bd9Sstevel@tonic-gate 	    !write_buffer(fileno(stdout), multi_end, strlen(multi_end))) {
16717c478bd9Sstevel@tonic-gate 		return (B_FALSE);
16727c478bd9Sstevel@tonic-gate 	}
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate 	return (B_TRUE);
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16797c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)16807c478bd9Sstevel@tonic-gate main(int argc, char **argv)
16817c478bd9Sstevel@tonic-gate {
16827c478bd9Sstevel@tonic-gate 	int		ret = WBCGI_STATUS_ERR;
16837c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
16847c478bd9Sstevel@tonic-gate 	int		content;
16857c478bd9Sstevel@tonic-gate 	char		*net;
16867c478bd9Sstevel@tonic-gate 	char		*cid;
16877c478bd9Sstevel@tonic-gate 	char		*nonce;
16887c478bd9Sstevel@tonic-gate 	char		*docroot;
16897c478bd9Sstevel@tonic-gate 	char		*payload;
16907c478bd9Sstevel@tonic-gate 	char		*signature_type;
16917c478bd9Sstevel@tonic-gate 	char		*encryption_type;
16927c478bd9Sstevel@tonic-gate 	char		*bootconf = NULL;
16937c478bd9Sstevel@tonic-gate 	char		*keyfile = NULL;
16947c478bd9Sstevel@tonic-gate 	char		*bootpath = NULL;
16957c478bd9Sstevel@tonic-gate 	char		*wanbootfs_image = NULL;
16967c478bd9Sstevel@tonic-gate 	char		*rootpath = NULL;
16977c478bd9Sstevel@tonic-gate 	char		*miniroot_info = NULL;
16987c478bd9Sstevel@tonic-gate 	char		*encr_payload = NULL;
16997c478bd9Sstevel@tonic-gate 	char		*payload_hash = NULL;
17007c478bd9Sstevel@tonic-gate 	boolean_t	https_rootserver;
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	/*
17037c478bd9Sstevel@tonic-gate 	 * Process the query string.
17047c478bd9Sstevel@tonic-gate 	 */
17057c478bd9Sstevel@tonic-gate 	if (!get_request_info(&content, &net, &cid, &nonce, &docroot)) {
17067c478bd9Sstevel@tonic-gate 		goto cleanup;
17077c478bd9Sstevel@tonic-gate 	}
17087c478bd9Sstevel@tonic-gate 
17097c478bd9Sstevel@tonic-gate 	/*
17107c478bd9Sstevel@tonic-gate 	 * Sanity check that the netboot directory exists.
17117c478bd9Sstevel@tonic-gate 	 */
17127c478bd9Sstevel@tonic-gate 	if (!WBCGI_DIR_EXISTS(NB_NETBOOT_ROOT, sbuf)) {
17137c478bd9Sstevel@tonic-gate 		print_status(500, "(" NB_NETBOOT_ROOT " does not exist)");
17147c478bd9Sstevel@tonic-gate 		goto cleanup;
17157c478bd9Sstevel@tonic-gate 	}
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 	/*
17187c478bd9Sstevel@tonic-gate 	 * Get absolute bootconf pathname.
17197c478bd9Sstevel@tonic-gate 	 */
17207c478bd9Sstevel@tonic-gate 	if (netboot_ftw(NB_WANBOOT_CONF, net, cid,
17217c478bd9Sstevel@tonic-gate 	    set_pathname, &bootconf) != WBCGI_FTW_CBOK) {
17227c478bd9Sstevel@tonic-gate 		print_status(500, "(wanboot.conf not found)");
17237c478bd9Sstevel@tonic-gate 		goto cleanup;
17247c478bd9Sstevel@tonic-gate 	}
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 	/*
17277c478bd9Sstevel@tonic-gate 	 * Initialize bc_handle from the given wanboot.conf file.
17287c478bd9Sstevel@tonic-gate 	 */
17297c478bd9Sstevel@tonic-gate 	if (bootconf_init(&bc_handle, bootconf) != BC_SUCCESS) {
17307c478bd9Sstevel@tonic-gate 		char	message[WBCGI_MAXBUF];
17317c478bd9Sstevel@tonic-gate 		int	chars;
17327c478bd9Sstevel@tonic-gate 
17337c478bd9Sstevel@tonic-gate 		chars = snprintf(message, sizeof (message),
17347c478bd9Sstevel@tonic-gate 		    "(wanboot.conf error: %s)", bootconf_errmsg(&bc_handle));
17357c478bd9Sstevel@tonic-gate 		if (chars > 0 && chars < sizeof (message))
17367c478bd9Sstevel@tonic-gate 			print_status(500, message);
17377c478bd9Sstevel@tonic-gate 		else
17387c478bd9Sstevel@tonic-gate 			print_status(500, "(wanboot.conf error)");
17397c478bd9Sstevel@tonic-gate 		goto cleanup;
17407c478bd9Sstevel@tonic-gate 	}
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	/*
17437c478bd9Sstevel@tonic-gate 	 * Get and check signature and encryption types,
17447c478bd9Sstevel@tonic-gate 	 * presence of helper utilities, keystore, etc.
17457c478bd9Sstevel@tonic-gate 	 */
17467c478bd9Sstevel@tonic-gate 	if ((signature_type = bootconf_get(&bc_handle,
17477c478bd9Sstevel@tonic-gate 	    BC_SIGNATURE_TYPE)) != NULL) {
17487c478bd9Sstevel@tonic-gate 		if (!WBCGI_FILE_EXISTS(WBCGI_HMAC_PATH, sbuf)) {
17497c478bd9Sstevel@tonic-gate 			print_status(500, "(hmac utility not found)");
17507c478bd9Sstevel@tonic-gate 			goto cleanup;
17517c478bd9Sstevel@tonic-gate 		}
175222ce47f7SDavid Miner 		if (keyfile == NULL && netboot_ftw(NB_CLIENT_KEY, net, cid,
17537c478bd9Sstevel@tonic-gate 		    set_pathname, &keyfile) != WBCGI_FTW_CBOK) {
17547c478bd9Sstevel@tonic-gate 			print_status(500, "(keystore not found)");
17557c478bd9Sstevel@tonic-gate 			goto cleanup;
17567c478bd9Sstevel@tonic-gate 		}
17577c478bd9Sstevel@tonic-gate 		if (!check_key_type(keyfile, signature_type, WBKU_HASH_KEY)) {
17587c478bd9Sstevel@tonic-gate 			print_status(500, "(hash key not found)");
17597c478bd9Sstevel@tonic-gate 			goto cleanup;
17607c478bd9Sstevel@tonic-gate 		}
17617c478bd9Sstevel@tonic-gate 	}
17627c478bd9Sstevel@tonic-gate 	if ((encryption_type = bootconf_get(&bc_handle,
17637c478bd9Sstevel@tonic-gate 	    BC_ENCRYPTION_TYPE)) != NULL) {
17647c478bd9Sstevel@tonic-gate 		if (signature_type == NULL) {
17657c478bd9Sstevel@tonic-gate 			print_status(500, "(encrypted but not signed)");
17667c478bd9Sstevel@tonic-gate 			goto cleanup;
17677c478bd9Sstevel@tonic-gate 		}
17687c478bd9Sstevel@tonic-gate 		if (!WBCGI_FILE_EXISTS(WBCGI_ENCR_PATH, sbuf)) {
17697c478bd9Sstevel@tonic-gate 			print_status(500, "(encr utility not found)");
17707c478bd9Sstevel@tonic-gate 			goto cleanup;
17717c478bd9Sstevel@tonic-gate 		}
177222ce47f7SDavid Miner 		if (keyfile == NULL && netboot_ftw(NB_CLIENT_KEY, net, cid,
17737c478bd9Sstevel@tonic-gate 		    set_pathname, &keyfile) != WBCGI_FTW_CBOK) {
17747c478bd9Sstevel@tonic-gate 			print_status(500, "(keystore not found)");
17757c478bd9Sstevel@tonic-gate 			goto cleanup;
17767c478bd9Sstevel@tonic-gate 		}
17777c478bd9Sstevel@tonic-gate 		if (!check_key_type(keyfile, encryption_type, WBKU_ENCR_KEY)) {
17787c478bd9Sstevel@tonic-gate 			print_status(500, "(encr key not found)");
17797c478bd9Sstevel@tonic-gate 			goto cleanup;
17807c478bd9Sstevel@tonic-gate 		}
17817c478bd9Sstevel@tonic-gate 	}
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	/*
17847c478bd9Sstevel@tonic-gate 	 * Determine/create our payload.
17857c478bd9Sstevel@tonic-gate 	 */
17867c478bd9Sstevel@tonic-gate 	switch (content) {
17877c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_BOOTFILE:
17887c478bd9Sstevel@tonic-gate 		if (!bootfile_payload(docroot, &bootpath)) {
17897c478bd9Sstevel@tonic-gate 			goto cleanup;
17907c478bd9Sstevel@tonic-gate 		}
17917c478bd9Sstevel@tonic-gate 		payload = bootpath;
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate 		break;
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_BOOTFS:
17967c478bd9Sstevel@tonic-gate 		if (!wanbootfs_payload(net, cid, nonce,
17977c478bd9Sstevel@tonic-gate 		    bootconf, &wanbootfs_image)) {
17987c478bd9Sstevel@tonic-gate 			goto cleanup;
17997c478bd9Sstevel@tonic-gate 		}
18007c478bd9Sstevel@tonic-gate 		payload = wanbootfs_image;
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate 		break;
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 	case WBCGI_CONTENT_ROOTFS:
18057c478bd9Sstevel@tonic-gate 		if (!miniroot_payload(net, cid, docroot,
18067c478bd9Sstevel@tonic-gate 		    &rootpath, &miniroot_info, &https_rootserver)) {
18077c478bd9Sstevel@tonic-gate 			goto cleanup;
18087c478bd9Sstevel@tonic-gate 		}
18097c478bd9Sstevel@tonic-gate 		payload = rootpath;
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 		break;
18127c478bd9Sstevel@tonic-gate 	}
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 	/*
18157c478bd9Sstevel@tonic-gate 	 * Encrypt the payload if necessary.
18167c478bd9Sstevel@tonic-gate 	 */
18177c478bd9Sstevel@tonic-gate 	if (content != WBCGI_CONTENT_BOOTFILE &&
18187c478bd9Sstevel@tonic-gate 	    content != WBCGI_CONTENT_ROOTFS &&
18197c478bd9Sstevel@tonic-gate 	    encryption_type != NULL) {
18207c478bd9Sstevel@tonic-gate 		if ((encr_payload = gen_tmppath("encr", net, cid)) == NULL) {
18217c478bd9Sstevel@tonic-gate 			goto cleanup;
18227c478bd9Sstevel@tonic-gate 		}
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 		if (!encrypt_payload(payload, encr_payload, keyfile,
18257c478bd9Sstevel@tonic-gate 		    encryption_type)) {
18267c478bd9Sstevel@tonic-gate 			goto cleanup;
18277c478bd9Sstevel@tonic-gate 		}
18287c478bd9Sstevel@tonic-gate 
18297c478bd9Sstevel@tonic-gate 		payload = encr_payload;
18307c478bd9Sstevel@tonic-gate 	}
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 	/*
18337c478bd9Sstevel@tonic-gate 	 * Compute the hash (actual or null).
18347c478bd9Sstevel@tonic-gate 	 */
18357c478bd9Sstevel@tonic-gate 	if ((payload_hash = gen_tmppath("hash", net, cid)) == NULL) {
18367c478bd9Sstevel@tonic-gate 		goto cleanup;
18377c478bd9Sstevel@tonic-gate 	}
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 	if (signature_type != NULL &&
18407c478bd9Sstevel@tonic-gate 	    (content != WBCGI_CONTENT_ROOTFS || !https_rootserver)) {
18417c478bd9Sstevel@tonic-gate 		if (!hash_payload(payload, payload_hash, keyfile)) {
18427c478bd9Sstevel@tonic-gate 			goto cleanup;
18437c478bd9Sstevel@tonic-gate 		}
18447c478bd9Sstevel@tonic-gate 	} else {
18457c478bd9Sstevel@tonic-gate 		if (!create_null_hash(payload_hash)) {
18467c478bd9Sstevel@tonic-gate 			goto cleanup;
18477c478bd9Sstevel@tonic-gate 		}
18487c478bd9Sstevel@tonic-gate 	}
18497c478bd9Sstevel@tonic-gate 
18507c478bd9Sstevel@tonic-gate 	/*
18517c478bd9Sstevel@tonic-gate 	 * For the rootfs the actual payload transmitted is the file
18527c478bd9Sstevel@tonic-gate 	 * containing the size of the rootfs (as a string of ascii digits);
18537c478bd9Sstevel@tonic-gate 	 * point payload at this instead.
18547c478bd9Sstevel@tonic-gate 	 */
18557c478bd9Sstevel@tonic-gate 	if (content == WBCGI_CONTENT_ROOTFS) {
18567c478bd9Sstevel@tonic-gate 		payload = miniroot_info;
18577c478bd9Sstevel@tonic-gate 	}
18587c478bd9Sstevel@tonic-gate 
18597c478bd9Sstevel@tonic-gate 	/*
18607c478bd9Sstevel@tonic-gate 	 * Finally, deliver the payload and hash as a multipart message.
18617c478bd9Sstevel@tonic-gate 	 */
18627c478bd9Sstevel@tonic-gate 	if (!deliver_payload(payload, payload_hash)) {
18637c478bd9Sstevel@tonic-gate 		goto cleanup;
18647c478bd9Sstevel@tonic-gate 	}
18657c478bd9Sstevel@tonic-gate 
18667c478bd9Sstevel@tonic-gate 	ret = WBCGI_STATUS_OK;
18677c478bd9Sstevel@tonic-gate cleanup:
18687c478bd9Sstevel@tonic-gate 	/*
18697c478bd9Sstevel@tonic-gate 	 * Clean up temporary files.
18707c478bd9Sstevel@tonic-gate 	 */
18717c478bd9Sstevel@tonic-gate 	if (wanbootfs_image != NULL &&
18727c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(wanbootfs_image, sbuf)) {
18737c478bd9Sstevel@tonic-gate 		(void) unlink(wanbootfs_image);
18747c478bd9Sstevel@tonic-gate 	}
18757c478bd9Sstevel@tonic-gate 	if (miniroot_info != NULL &&
18767c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(miniroot_info, sbuf)) {
18777c478bd9Sstevel@tonic-gate 		(void) unlink(miniroot_info);
18787c478bd9Sstevel@tonic-gate 	}
18797c478bd9Sstevel@tonic-gate 	if (encr_payload != NULL &&
18807c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(encr_payload, sbuf)) {
18817c478bd9Sstevel@tonic-gate 		(void) unlink(encr_payload);
18827c478bd9Sstevel@tonic-gate 	}
18837c478bd9Sstevel@tonic-gate 	if (payload_hash != NULL &&
18847c478bd9Sstevel@tonic-gate 	    WBCGI_FILE_EXISTS(payload_hash, sbuf)) {
18857c478bd9Sstevel@tonic-gate 		(void) unlink(payload_hash);
18867c478bd9Sstevel@tonic-gate 	}
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	/*
18897c478bd9Sstevel@tonic-gate 	 * Free up any allocated strings.
18907c478bd9Sstevel@tonic-gate 	 */
18917c478bd9Sstevel@tonic-gate 	free_path(&bootconf);
18927c478bd9Sstevel@tonic-gate 	free_path(&keyfile);
18937c478bd9Sstevel@tonic-gate 	free_path(&bootpath);
18947c478bd9Sstevel@tonic-gate 	free_path(&wanbootfs_image);
18957c478bd9Sstevel@tonic-gate 	free_path(&rootpath);
18967c478bd9Sstevel@tonic-gate 	free_path(&miniroot_info);
18977c478bd9Sstevel@tonic-gate 	free_path(&encr_payload);
18987c478bd9Sstevel@tonic-gate 	free_path(&payload_hash);
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 	bootconf_end(&bc_handle);
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 	return (ret);
19037c478bd9Sstevel@tonic-gate }
1904