xref: /titanic_44/usr/src/lib/libpkg/common/keystore.c (revision be468fc6d7266e97f1330ad9a761169925f5f3f1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Module:	keystore.c
29  * Description:	This module contains the structure definitions for processing
30  *		package keystore files.
31  */
32 
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <strings.h>
37 #include <libintl.h>
38 #include <time.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <openssl/evp.h>
43 #include <openssl/x509.h>
44 #include <openssl/pkcs12.h>
45 #include <openssl/asn1.h>
46 #include <openssl/pem.h>
47 #include <openssl/err.h>
48 #include <openssl/safestack.h>
49 #include <openssl/stack.h>
50 #include "p12lib.h"
51 #include "pkgerr.h"
52 #include "keystore.h"
53 #include "pkglib.h"
54 #include "pkglibmsgs.h"
55 
56 typedef struct keystore_t {
57 	boolean_t		dirty;
58 	boolean_t		new;
59 	char			*path;
60 	char			*passphrase;
61 	/* truststore handles */
62 	int			cafd;
63 	STACK_OF(X509)		*cacerts;
64 	char			*capath;
65 
66 	/* user certificate handles */
67 	STACK_OF(X509)		*clcerts;
68 	char			*clpath;
69 
70 	/* private key handles */
71 	STACK_OF(EVP_PKEY)	*pkeys;
72 	char			*keypath;
73 } keystore_t;
74 
75 /* local routines */
76 static keystore_t	*new_keystore(void);
77 static void		free_keystore(keystore_t *);
78 static boolean_t	verify_keystore_integrity(PKG_ERR *, keystore_t *);
79 static boolean_t	check_password(PKCS12 *, char *);
80 static boolean_t	resolve_paths(PKG_ERR *, char *, char *,
81     long, keystore_t *);
82 static boolean_t	lock_keystore(PKG_ERR *, long, keystore_t *);
83 
84 static boolean_t	unlock_keystore(PKG_ERR *, keystore_t *);
85 static boolean_t	read_keystore(PKG_ERR *, keystore_t *,
86     keystore_passphrase_cb);
87 static boolean_t	write_keystore(PKG_ERR *, keystore_t *,
88     keystore_passphrase_cb);
89 static boolean_t	write_keystore_file(PKG_ERR *, char *, PKCS12 *);
90 static boolean_t	clear_keystore_file(PKG_ERR *, char *);
91 static PKCS12		*read_keystore_file(PKG_ERR *, char *);
92 static char		*get_time_string(ASN1_TIME *);
93 
94 /* locking routines */
95 static boolean_t	restore_keystore_file(PKG_ERR *, char *);
96 static int		file_lock(int, int, int);
97 static int		file_unlock(int);
98 static boolean_t	file_lock_test(int, int);
99 static boolean_t	file_empty(char *);
100 static boolean_t	get_keystore_passwd(PKG_ERR *err, PKCS12 *p12,
101     keystore_passphrase_cb cb, keystore_t *keystore);
102 static boolean_t	wait_restore(int, char *, char *, char *);
103 
104 #define	KEYSTORE_PERMS	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
105 
106 /* wait on other keystore access for 1 minute before giving up */
107 #define	LOCK_TIMEOUT	60
108 
109 /*
110  * print_certs  - prints certificates out of a keystore, to a file.
111  *
112  * Arguments:
113  * err - Error object to append errors to
114  * keystore - Keystore on which to operate
115  * alias - Name of certificate to print, NULL means print all
116  * format - Format in which to print certificates
117  * outfile - Where to print certificates
118  *
119  * Returns:
120  *   0 - Success
121  *   non-zero - Failure, errors added to err
122  */
123 int
124 print_certs(PKG_ERR *err, keystore_handle_t keystore_h, char *alias,
125     keystore_encoding_format_t format, FILE *outfile)
126 {
127 	int		i;
128 	X509		*cert;
129 	char		*fname = NULL;
130 	boolean_t	found = B_FALSE;
131 	keystore_t	*keystore = keystore_h;
132 
133 	if (keystore->clcerts != NULL) {
134 		/* print out each client cert */
135 		for (i = 0; i < sk_X509_num(keystore->clcerts); i++) {
136 			cert = sk_X509_value(keystore->clcerts, i);
137 			(void) sunw_get_cert_fname(GETDO_COPY, cert,
138 			    &fname);
139 
140 			if (fname == NULL) {
141 				/* no name recorded, keystore is corrupt */
142 				pkgerr_add(err, PKGERR_CORRUPT,
143 				    gettext(ERR_KEYSTORE_NO_ALIAS),
144 				    get_subject_display_name(cert));
145 				return (1);
146 			}
147 
148 			if ((alias != NULL) && (!streq(alias, fname))) {
149 				/* name does not match, skip it */
150 				(void) OPENSSL_free(fname);
151 				fname = NULL;
152 				continue;
153 			} else {
154 				found = B_TRUE;
155 				(void) print_cert(err, cert, format,
156 				    fname, B_FALSE, outfile);
157 				(void) OPENSSL_free(fname);
158 				fname = NULL;
159 			}
160 		}
161 	}
162 
163 	if (fname != NULL) {
164 	    (void) OPENSSL_free(fname);
165 	    fname = NULL;
166 	}
167 
168 	if (keystore->cacerts != NULL) {
169 		/* print out each trusted cert */
170 		for (i = 0; i < sk_X509_num(keystore->cacerts); i++) {
171 			cert = sk_X509_value(keystore->cacerts, i);
172 			(void) sunw_get_cert_fname(GETDO_COPY,
173 			    cert, &fname);
174 
175 			if (fname == NULL) {
176 				/* no name recorded, keystore is corrupt */
177 				pkgerr_add(err, PKGERR_CORRUPT,
178 				    gettext(ERR_KEYSTORE_NO_ALIAS),
179 				    get_subject_display_name(cert));
180 				return (1);
181 			}
182 
183 			if ((alias != NULL) && (!streq(alias, fname))) {
184 				/* name does not match, skip it */
185 				(void) OPENSSL_free(fname);
186 				fname = NULL;
187 				continue;
188 			} else {
189 				found = B_TRUE;
190 				(void) print_cert(err, cert, format,
191 				    fname, B_TRUE, outfile);
192 				(void) OPENSSL_free(fname);
193 				fname = NULL;
194 			}
195 		}
196 	}
197 
198 	if (fname != NULL) {
199 	    (void) OPENSSL_free(fname);
200 	    fname = NULL;
201 	}
202 
203 	if (found) {
204 		return (0);
205 	} else {
206 		/* no certs printed */
207 		if (alias != NULL) {
208 			pkgerr_add(err, PKGERR_NOALIASMATCH,
209 			    gettext(ERR_KEYSTORE_NOCERT),
210 			    alias, keystore->path);
211 		} else {
212 			pkgerr_add(err, PKGERR_NOPUBKEY,
213 			    gettext(ERR_KEYSTORE_NOPUBCERTS),
214 			    keystore->path);
215 			pkgerr_add(err, PKGERR_NOCACERT,
216 			    gettext(ERR_KEYSTORE_NOCACERTS),
217 			    keystore->path);
218 		}
219 		return (1);
220 	}
221 }
222 
223 /*
224  * print_cert  - prints a single certificate, to a file
225  *
226  * Arguments:
227  * err - Error object to append errors to
228  * x - The certificate to print
229  * alias - Name of certificate to print
230  * format - Format in which to print certificate
231  * outfile - Where to print certificate
232  *
233  * Returns:
234  *   0 - Success
235  *   non-zero - Failure, errors added to err
236  */
237 int print_cert(PKG_ERR *err, X509 *x,
238     keystore_encoding_format_t format, char *alias, boolean_t is_trusted,
239     FILE *outfile)
240 {
241 
242 	char *vdb_str;
243 	char *vda_str;
244 	char vd_str[ATTR_MAX];
245 	int ret = 0;
246 	char *cn_str, *icn_str, *typ_str;
247 	char *tmp;
248 	char *md5_fp;
249 	char *sha1_fp;
250 	int len;
251 
252 	/* need to localize the word "Fingerprint", hence these pointers */
253 	char md5_label[ATTR_MAX];
254 	char sha1_label[ATTR_MAX];
255 
256 	if (is_trusted) {
257 		typ_str = gettext(MSG_KEYSTORE_TRUSTED);
258 	} else {
259 		typ_str = gettext(MSG_KEYSTORE_UNTRUSTED);
260 	}
261 
262 	if ((cn_str = get_subject_display_name(x)) == NULL) {
263 		cn_str = gettext(MSG_KEYSTORE_UNKNOWN);
264 	}
265 
266 	if ((icn_str = get_issuer_display_name(x)) == NULL) {
267 		icn_str = gettext(MSG_KEYSTORE_UNKNOWN);
268 	}
269 
270 	vdb_str = xstrdup(get_time_string(X509_get_notBefore(x)));
271 	vda_str = xstrdup(get_time_string(X509_get_notAfter(x)));
272 	if (((len = snprintf(vd_str, ATTR_MAX, "<%s> - <%s>",
273 	    vdb_str, vda_str)) < 0) || (len >= ATTR_MAX)) {
274 		pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), vdb_str);
275 		ret = 1;
276 		goto cleanup;
277 	}
278 
279 	if ((tmp = get_fingerprint(x, EVP_md5())) == NULL) {
280 		md5_fp = gettext(MSG_KEYSTORE_UNKNOWN);
281 	} else {
282 		/*
283 		 * make a copy, otherwise the next call to get_fingerprint
284 		 * will overwrite this one
285 		 */
286 		md5_fp = xstrdup(tmp);
287 	}
288 
289 	if ((tmp = get_fingerprint(x, EVP_sha1())) == NULL) {
290 		sha1_fp = gettext(MSG_KEYSTORE_UNKNOWN);
291 	} else {
292 		sha1_fp = xstrdup(tmp);
293 	}
294 
295 	(void) snprintf(md5_label, ATTR_MAX, "%s %s",
296 	    OBJ_nid2sn(EVP_MD_type(EVP_md5())),
297 	    /* i18n: 14 characters max */
298 	    gettext(MSG_KEYSTORE_FP));
299 
300 	(void) snprintf(sha1_label, ATTR_MAX, "%s %s",
301 	    OBJ_nid2sn(EVP_MD_type(EVP_sha1())),
302 	    /* i18n: 14 characters max */
303 	    gettext(MSG_KEYSTORE_FP));
304 
305 	switch (format) {
306 	case KEYSTORE_FORMAT_PEM:
307 		(void) PEM_write_X509(outfile, x);
308 		break;
309 	case KEYSTORE_FORMAT_DER:
310 		(void) i2d_X509_fp(outfile, x);
311 		break;
312 	case KEYSTORE_FORMAT_TEXT:
313 		(void) fprintf(outfile, "%18s: %s\n",
314 		    /* i18n: 18 characters max */
315 		    gettext(MSG_KEYSTORE_AL), alias);
316 		(void) fprintf(outfile, "%18s: %s\n",
317 		    /* i18n: 18 characters max */
318 		    gettext(MSG_KEYSTORE_CN), cn_str);
319 		(void) fprintf(outfile, "%18s: %s\n",
320 		    /* i18n: 18 characters max */
321 		    gettext(MSG_KEYSTORE_TY), typ_str);
322 		(void) fprintf(outfile, "%18s: %s\n",
323 		    /* i18n: 18 characters max */
324 		    gettext(MSG_KEYSTORE_IN), icn_str);
325 		(void) fprintf(outfile, "%18s: %s\n",
326 		    /* i18n: 18 characters max */
327 		    gettext(MSG_KEYSTORE_VD), vd_str);
328 		(void) fprintf(outfile, "%18s: %s\n", md5_label, md5_fp);
329 		(void) fprintf(outfile, "%18s: %s\n", sha1_label, sha1_fp);
330 		(void) fprintf(outfile, "\n");
331 		break;
332 	default:
333 		pkgerr_add(err, PKGERR_INTERNAL,
334 		    gettext(ERR_KEYSTORE_INTERNAL),
335 		    __FILE__, __LINE__);
336 		ret = 1;
337 		goto cleanup;
338 	}
339 
340 cleanup:
341 	if (md5_fp != NULL)
342 		free(md5_fp);
343 	if (sha1_fp != NULL)
344 		free(sha1_fp);
345 	if (vda_str != NULL)
346 		free(vda_str);
347 	if (vdb_str != NULL)
348 		free(vdb_str);
349 	return (ret);
350 }
351 
352 /*
353  * open_keystore - Initialize new keystore object for
354  * impending access.
355  *
356  * Arguments:
357  * err - Error object to append errors to
358  * keystore_file - Base filename or directory of keystore
359  * app - Application making request
360  * passwd - Password used to decrypt keystore
361  * flags - Control flags used to control access mode and behavior
362  * result - Resulting keystore object stored here on success
363  *
364  * Returns:
365  *   0 - Success - result contains a pointer to the opened keystore
366  *   non-zero - Failure, errors added to err
367  */
368 int
369 open_keystore(PKG_ERR *err, char *keystore_file, char *app,
370     keystore_passphrase_cb cb, long flags, keystore_handle_t *result)
371 {
372 	int ret = 0;
373 	keystore_t	*tmpstore;
374 
375 	tmpstore = new_keystore();
376 
377 	tmpstore->dirty = B_FALSE;
378 	tmpstore->new = B_FALSE;
379 	tmpstore->path = xstrdup(keystore_file);
380 
381 	if (!resolve_paths(err, keystore_file, app, flags, tmpstore)) {
382 		/* unable to determine keystore paths */
383 		pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
384 		    keystore_file);
385 		ret = 1;
386 		goto cleanup;
387 	}
388 
389 	if (!verify_keystore_integrity(err, tmpstore)) {
390 		/* unable to repair keystore */
391 		pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
392 		    keystore_file);
393 		ret = 1;
394 		goto cleanup;
395 	}
396 
397 	if (!lock_keystore(err, flags, tmpstore)) {
398 		pkgerr_add(err, PKGERR_LOCKED, gettext(ERR_KEYSTORE_LOCKED),
399 		    keystore_file);
400 		ret = 1;
401 		goto cleanup;
402 	}
403 
404 	/* now that we have locked the keystore, go ahead and read it */
405 	if (!read_keystore(err, tmpstore, cb)) {
406 		pkgerr_add(err, PKGERR_READ, gettext(ERR_PARSE),
407 		    keystore_file);
408 		ret = 1;
409 		goto cleanup;
410 	}
411 
412 	*result = tmpstore;
413 	tmpstore = NULL;
414 
415 cleanup:
416 	if (tmpstore != NULL)
417 		free_keystore(tmpstore);
418 	return (ret);
419 }
420 
421 /*
422  * new_keystore - Allocates and initializes a Keystore object
423  *
424  * Arguments:
425  * NONE
426  *
427  * Returns:
428  *   NULL - out of memory
429  *   otherwise, returns a pointer to the newly allocated object,
430  *   which should be freed with free_keystore() when no longer
431  *   needed.
432  */
433 static keystore_t
434 *new_keystore(void)
435 {
436 	keystore_t *tmpstore;
437 
438 	if ((tmpstore = (keystore_t *)malloc(sizeof (keystore_t))) == NULL) {
439 		return (NULL);
440 	}
441 	tmpstore->dirty = B_FALSE;
442 	tmpstore->new = B_FALSE;
443 	tmpstore->path = NULL;
444 	tmpstore->passphrase = NULL;
445 	tmpstore->cafd = -1;
446 	tmpstore->cacerts = NULL;
447 	tmpstore->capath = NULL;
448 	tmpstore->clcerts = NULL;
449 	tmpstore->clpath = NULL;
450 	tmpstore->pkeys = NULL;
451 	tmpstore->keypath = NULL;
452 
453 	return (tmpstore);
454 }
455 
456 /*
457  * free_keystore - Deallocates a Keystore object
458  *
459  * Arguments:
460  * keystore - The keystore to deallocate
461  *
462  * Returns:
463  *   NONE
464  */
465 static void
466 free_keystore(keystore_t *keystore)
467 {
468 	if (keystore->path != NULL)
469 		free(keystore->path);
470 	if (keystore->capath != NULL)
471 		free(keystore->capath);
472 	if (keystore->passphrase != NULL)
473 		free(keystore->passphrase);
474 	if (keystore->clpath != NULL)
475 		free(keystore->clpath);
476 	if (keystore->keypath != NULL)
477 		free(keystore->keypath);
478 
479 	if (keystore->pkeys != NULL) {
480 		sk_EVP_PKEY_pop_free(keystore->pkeys,
481 		    sunw_evp_pkey_free);
482 	}
483 	if (keystore->clcerts != NULL)
484 		sk_X509_free(keystore->clcerts);
485 	if (keystore->cacerts != NULL)
486 		sk_X509_free(keystore->cacerts);
487 	free(keystore);
488 }
489 
490 /*
491  * close_keystore - Writes keystore to disk if needed, then
492  * unlocks and closes keystore.
493  *
494  * Arguments:
495  * err - Error object to append errors to
496  * keystore - Keystore which should be closed
497  * passwd - Password used to encrypt keystore
498  *
499  * Returns:
500  *   0 - Success - keystore is committed to disk, and unlocked
501  *   non-zero - Failure, errors added to err
502  */
503 int
504 close_keystore(PKG_ERR *err, keystore_handle_t keystore_h,
505     keystore_passphrase_cb cb)
506 {
507 	int ret = 0;
508 	keystore_t *keystore = keystore_h;
509 
510 	if (keystore->dirty) {
511 		/* write out the keystore first */
512 		if (!write_keystore(err, keystore, cb)) {
513 			pkgerr_add(err, PKGERR_WRITE,
514 			    gettext(ERR_KEYSTORE_WRITE),
515 			    keystore->path);
516 			ret = 1;
517 			goto cleanup;
518 		}
519 	}
520 
521 	if (!unlock_keystore(err, keystore)) {
522 		pkgerr_add(err, PKGERR_UNLOCK, gettext(ERR_KEYSTORE_UNLOCK),
523 		    keystore->path);
524 		ret = 1;
525 		goto cleanup;
526 	}
527 
528 	free_keystore(keystore);
529 cleanup:
530 	return (ret);
531 }
532 
533 /*
534  * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
535  * certificate checked for validity dates and non-duplicity.
536  *
537  * Arguments:
538  * err - Error object to add errors to
539  * cacert - Certificate which to merge into keystore
540  * keystore - The keystore into which the certificate is merged
541  *
542  * Returns:
543  *   0 - Success - Certificate passes validity, and
544  *		is merged into keystore
545  * non-zero - Failure, errors recorded in err
546  */
547 int
548 merge_ca_cert(PKG_ERR *err, X509 *cacert, keystore_handle_t keystore_h)
549 {
550 
551 	int		ret = 0;
552 	X509		*existing = NULL;
553 	char		*fname;
554 	keystore_t	*keystore = keystore_h;
555 
556 	/* check validity dates */
557 	if (check_cert(err, cacert) != 0) {
558 		ret = 1;
559 		goto cleanup;
560 	}
561 
562 	/* create the certificate's friendlyName */
563 	fname = get_subject_display_name(cacert);
564 
565 	if (sunw_set_fname(fname, NULL, cacert) != 0) {
566 		pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
567 		ret = 1;
568 		goto cleanup;
569 	}
570 
571 	/* merge certificate into the keystore */
572 	if (keystore->cacerts == NULL) {
573 		/* no existing truststore, so make a new one */
574 		if ((keystore->cacerts = sk_X509_new_null()) == NULL) {
575 			pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
576 			ret = 1;
577 			goto cleanup;
578 		}
579 	} else {
580 		/* existing truststore, make sure there's no duplicate */
581 		if (sunw_find_fname(fname, NULL, keystore->cacerts,
582 		    NULL, &existing) < 0) {
583 			pkgerr_add(err, PKGERR_INTERNAL,
584 			    gettext(ERR_KEYSTORE_INTERNAL),
585 			    __FILE__, __LINE__);
586 			ERR_print_errors_fp(stderr);
587 			ret = 1;
588 			goto cleanup;
589 			/* could not search properly! */
590 		}
591 		if (existing != NULL) {
592 			/* whoops, found one already */
593 			pkgerr_add(err, PKGERR_DUPLICATE,
594 			    gettext(ERR_KEYSTORE_DUPLICATECERT), fname);
595 			ret = 1;
596 			goto cleanup;
597 		}
598 	}
599 
600 	(void) sk_X509_push(keystore->cacerts, cacert);
601 	keystore->dirty = B_TRUE;
602 cleanup:
603 	if (existing != NULL)
604 		X509_free(existing);
605 	return (ret);
606 }
607 
608 /*
609  * find_key_cert_pair - Searches a keystore for a matching
610  * public key certificate and private key, given an alias.
611  *
612  * Arguments:
613  * err - Error object to add errors to
614  * ks - Keystore to search
615  * alias - Name to used to match certificate's alias
616  * key - Resulting key is placed here
617  * cert - Resulting cert is placed here
618  *
619  * Returns:
620  *   0 - Success - Matching cert/key pair placed in key and cert.
621  * non-zero - Failure, errors recorded in err
622  */
623 int
624 find_key_cert_pair(PKG_ERR *err, keystore_handle_t ks_h, char *alias,
625     EVP_PKEY **key, X509 **cert)
626 {
627 	X509		*tmpcert = NULL;
628 	EVP_PKEY	*tmpkey = NULL;
629 	int		ret = 0;
630 	int		items_found;
631 	keystore_t	*ks = ks_h;
632 
633 	if (key == NULL || cert == NULL) {
634 		pkgerr_add(err, PKGERR_NOPUBKEY,
635 		    gettext(ERR_KEYSTORE_NOPUBCERTS), ks->path);
636 		ret = 1;
637 		goto cleanup;
638 	}
639 
640 	if (ks->clcerts == NULL) {
641 		/* no public certs */
642 		pkgerr_add(err, PKGERR_NOPUBKEY,
643 		    gettext(ERR_KEYSTORE_NOCERTS), ks->path);
644 		ret = 1;
645 		goto cleanup;
646 	}
647 	if (ks->pkeys == NULL) {
648 		/* no private keys */
649 		pkgerr_add(err, PKGERR_NOPRIVKEY,
650 		    gettext(ERR_KEYSTORE_NOKEYS), ks->path);
651 		ret = 1;
652 		goto cleanup;
653 	}
654 
655 	/* try the easy case first */
656 	if ((sk_EVP_PKEY_num(ks->pkeys) == 1) &&
657 	    (sk_X509_num(ks->clcerts) == 1)) {
658 		tmpkey = sk_EVP_PKEY_value(ks->pkeys, 0);
659 		tmpcert = sk_X509_value(ks->clcerts, 0);
660 		if (sunw_check_keys(tmpcert, tmpkey)) {
661 			/*
662 			 * only one private key and public key cert, and they
663 			 * match, so use them
664 			 */
665 			*key = tmpkey;
666 			tmpkey = NULL;
667 			*cert = tmpcert;
668 			tmpcert = NULL;
669 			goto cleanup;
670 		}
671 	}
672 
673 	/* Attempt to find the right pair given the alias */
674 	items_found = sunw_find_fname(alias, ks->pkeys, ks->clcerts,
675 	    &tmpkey, &tmpcert);
676 
677 	if ((items_found < 0) ||
678 	    (items_found & (FOUND_PKEY | FOUND_CERT)) == 0) {
679 		/* no key/cert pair found. bail. */
680 		pkgerr_add(err, PKGERR_BADALIAS,
681 		    gettext(ERR_KEYSTORE_NOMATCH), alias);
682 		ret = 1;
683 		goto cleanup;
684 	}
685 
686 	/* success */
687 	*key = tmpkey;
688 	tmpkey = NULL;
689 	*cert = tmpcert;
690 	tmpcert = NULL;
691 
692 cleanup:
693 
694 	if (tmpcert != NULL)
695 		(void) X509_free(tmpcert);
696 
697 	if (tmpkey != NULL)
698 		sunw_evp_pkey_free(tmpkey);
699 
700 	return (ret);
701 }
702 
703 /*
704  * find_ca_certs - Searches a keystore for trusted certificates
705  *
706  * Arguments:
707  * err - Error object to add errors to
708  * ks - Keystore to search
709  * cacerts - resulting set of trusted certs are placed here
710  *
711  * Returns:
712  *   0 - Success - trusted cert list returned in cacerts
713  * non-zero - Failure, errors recorded in err
714  */
715 int
716 find_ca_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **cacerts)
717 {
718 
719 	keystore_t	*ks = ks_h;
720 
721 	/* easy */
722 	if (cacerts == NULL) {
723 		pkgerr_add(err, PKGERR_INTERNAL,
724 		    gettext(ERR_KEYSTORE_INTERNAL), __FILE__, __LINE__);
725 		return (1);
726 	}
727 
728 	*cacerts = ks->cacerts;
729 	return (0);
730 }
731 
732 /*
733  * find_cl_certs - Searches a keystore for user certificates
734  *
735  * Arguments:
736  * err - Error object to add errors to
737  * ks - Keystore to search
738  * cacerts - resulting set of user certs are placed here
739  *
740  * No matching of any kind is performed.
741  * Returns:
742  *   0 - Success - trusted cert list returned in cacerts
743  * non-zero - Failure, errors recorded in err
744  */
745 /* ARGSUSED */
746 int
747 find_cl_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **clcerts)
748 {
749 	keystore_t	*ks = ks_h;
750 
751 	/* easy */
752 	*clcerts = ks->clcerts;
753 	return (0);
754 }
755 
756 
757 /*
758  * merge_cert_and_key - Adds a user certificate and matching
759  * private key to a keystore.
760  * certificate checked for validity dates and non-duplicity.
761  *
762  * Arguments:
763  * err - Error object to add errors to
764  * cert - Certificate which to merge into keystore
765  * key - matching private key to 'cert'
766  * alias - Name which to store the cert and key under
767  * keystore - The keystore into which the certificate is merged
768  *
769  * Returns:
770  *   0 - Success - Certificate passes validity, and
771  *		is merged into keystore, along with key
772  * non-zero - Failure, errors recorded in err
773  */
774 int
775 merge_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key, char *alias,
776     keystore_handle_t keystore_h)
777 {
778 	X509		*existingcert = NULL;
779 	EVP_PKEY	*existingkey = NULL;
780 	int		ret = 0;
781 	keystore_t	*keystore = keystore_h;
782 
783 	/* check validity dates */
784 	if (check_cert(err, cert) != 0) {
785 		ret = 1;
786 		goto cleanup;
787 	}
788 
789 	/* set the friendlyName of the key and cert to the supplied alias */
790 	if (sunw_set_fname(alias, key, cert) != 0) {
791 		pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
792 		ret = 1;
793 		goto cleanup;
794 	}
795 
796 	/* merge certificate and key into the keystore */
797 	if (keystore->clcerts == NULL) {
798 		/* no existing truststore, so make a new one */
799 		if ((keystore->clcerts = sk_X509_new_null()) == NULL) {
800 			pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
801 			ret = 1;
802 			goto cleanup;
803 		}
804 	} else {
805 		/* existing certstore, make sure there's no duplicate */
806 		if (sunw_find_fname(alias, NULL, keystore->clcerts,
807 		    NULL, &existingcert) < 0) {
808 			pkgerr_add(err, PKGERR_INTERNAL,
809 			    gettext(ERR_KEYSTORE_INTERNAL),
810 			    __FILE__, __LINE__);
811 			ERR_print_errors_fp(stderr);
812 			ret = 1;
813 			goto cleanup;
814 			/* could not search properly! */
815 		}
816 		if (existingcert != NULL) {
817 			/* whoops, found one already */
818 			pkgerr_add(err, PKGERR_DUPLICATE,
819 			    gettext(ERR_KEYSTORE_DUPLICATECERT), alias);
820 			ret = 1;
821 			goto cleanup;
822 		}
823 	}
824 
825 	if (keystore->pkeys == NULL) {
826 		/* no existing keystore, so make a new one */
827 		if ((keystore->pkeys = sk_EVP_PKEY_new_null()) == NULL) {
828 			pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
829 			ret = 1;
830 			goto cleanup;
831 		}
832 	} else {
833 		/* existing keystore, so make sure there's no duplicate entry */
834 		if (sunw_find_fname(alias, keystore->pkeys, NULL,
835 		    &existingkey, NULL) < 0) {
836 			pkgerr_add(err, PKGERR_INTERNAL,
837 			    gettext(ERR_KEYSTORE_INTERNAL),
838 			    __FILE__, __LINE__);
839 			ERR_print_errors_fp(stderr);
840 			ret = 1;
841 			goto cleanup;
842 			/* could not search properly! */
843 		}
844 		if (existingkey != NULL) {
845 			/* whoops, found one already */
846 			pkgerr_add(err, PKGERR_DUPLICATE,
847 			    gettext(ERR_KEYSTORE_DUPLICATEKEY), alias);
848 			ret = 1;
849 			goto cleanup;
850 		}
851 	}
852 
853 	(void) sk_X509_push(keystore->clcerts, cert);
854 	(void) sk_EVP_PKEY_push(keystore->pkeys, key);
855 	keystore->dirty = B_TRUE;
856 cleanup:
857 	if (existingcert != NULL)
858 		(void) X509_free(existingcert);
859 	if (existingkey != NULL)
860 		(void) sunw_evp_pkey_free(existingkey);
861 	return (ret);
862 }
863 
864 /*
865  * delete_cert_and_keys - Deletes one or more certificates
866  *  and matching private keys from a keystore.
867  *
868  * Arguments:
869  * err - Error object to add errors to
870  * ks - The keystore from which certs and keys are deleted
871  * alias - Name which to search for certificates and keys
872  *	to delete
873  *
874  * Returns:
875  *   0 - Success - All trusted certs which match 'alias'
876  *		are deleted.  All user certificates
877  *		which match 'alias' are deleted, along
878  *		with the matching private key.
879  * non-zero - Failure, errors recorded in err
880  */
881 int
882 delete_cert_and_keys(PKG_ERR *err, keystore_handle_t ks_h, char *alias)
883 {
884 	X509		*existingcert;
885 	EVP_PKEY	*existingkey;
886 	int		i;
887 	char		*fname = NULL;
888 	boolean_t	found = B_FALSE;
889 	keystore_t	*ks = ks_h;
890 
891 	/* delete any and all client certs with the supplied name */
892 	if (ks->clcerts != NULL) {
893 		for (i = 0; i < sk_X509_num(ks->clcerts); i++) {
894 			existingcert = sk_X509_value(ks->clcerts, i);
895 			if (sunw_get_cert_fname(GETDO_COPY,
896 			    existingcert, &fname) >= 0) {
897 				if (streq(fname, alias)) {
898 					/* match, so nuke it */
899 					existingcert =
900 					    sk_X509_delete(ks->clcerts, i);
901 					X509_free(existingcert);
902 					existingcert = NULL;
903 					found = B_TRUE;
904 				}
905 				(void) OPENSSL_free(fname);
906 				fname = NULL;
907 			}
908 		}
909 		if (sk_X509_num(ks->clcerts) <= 0) {
910 			/* we deleted all the client certs */
911 			sk_X509_free(ks->clcerts);
912 			ks->clcerts = NULL;
913 		}
914 	}
915 
916 	/* and now the private keys */
917 	if (ks->pkeys != NULL) {
918 		for (i = 0; i < sk_EVP_PKEY_num(ks->pkeys); i++) {
919 			existingkey = sk_EVP_PKEY_value(ks->pkeys, i);
920 			if (sunw_get_pkey_fname(GETDO_COPY,
921 			    existingkey, &fname) >= 0) {
922 				if (streq(fname, alias)) {
923 					/* match, so nuke it */
924 					existingkey =
925 					    sk_EVP_PKEY_delete(ks->pkeys, i);
926 					sunw_evp_pkey_free(existingkey);
927 					existingkey = NULL;
928 					found = B_TRUE;
929 				}
930 				(void) OPENSSL_free(fname);
931 				fname = NULL;
932 			}
933 		}
934 		if (sk_EVP_PKEY_num(ks->pkeys) <= 0) {
935 			/* we deleted all the private keys */
936 			sk_EVP_PKEY_free(ks->pkeys);
937 			ks->pkeys = NULL;
938 		}
939 	}
940 
941 	/* finally, remove any trust anchors that match */
942 
943 	if (ks->cacerts != NULL) {
944 		for (i = 0; i < sk_X509_num(ks->cacerts); i++) {
945 			existingcert = sk_X509_value(ks->cacerts, i);
946 			if (sunw_get_cert_fname(GETDO_COPY,
947 			    existingcert, &fname) >= 0) {
948 				if (streq(fname, alias)) {
949 					/* match, so nuke it */
950 					existingcert =
951 					    sk_X509_delete(ks->cacerts, i);
952 					X509_free(existingcert);
953 					existingcert = NULL;
954 					found = B_TRUE;
955 				}
956 				(void) OPENSSL_free(fname);
957 				fname = NULL;
958 			}
959 		}
960 		if (sk_X509_num(ks->cacerts) <= 0) {
961 			/* we deleted all the CA certs */
962 			sk_X509_free(ks->cacerts);
963 			ks->cacerts = NULL;
964 		}
965 	}
966 
967 	if (found) {
968 		ks->dirty = B_TRUE;
969 		return (0);
970 	} else {
971 		/* no certs or keys deleted */
972 		pkgerr_add(err, PKGERR_NOALIASMATCH,
973 		    gettext(ERR_KEYSTORE_NOCERTKEY),
974 		    alias, ks->path);
975 		return (1);
976 	}
977 }
978 
979 /*
980  * check_cert - Checks certificate validity.  This routine
981  * checks that the current time falls within the period
982  * of validity for the cert.
983  *
984  * Arguments:
985  * err - Error object to add errors to
986  * cert - The certificate to check
987  *
988  * Returns:
989  *   0 - Success - Certificate checks out
990  * non-zero - Failure, errors and reasons recorded in err
991  */
992 int
993 check_cert(PKG_ERR *err, X509 *cert)
994 {
995 	char			currtimestr[ATTR_MAX];
996 	time_t			currtime;
997 	char			*r;
998 	/* get current time */
999 	if ((currtime = time(NULL)) == (time_t)-1) {
1000 		pkgerr_add(err, PKGERR_TIME, gettext(ERR_CURR_TIME));
1001 		return (1);
1002 	}
1003 
1004 	(void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX);
1005 
1006 	/* trim whitespace from end of time string */
1007 	for (r = (currtimestr + strlen(currtimestr) - 1); isspace(*r); r--) {
1008 		*r = '\0';
1009 	}
1010 	/* check  validity of cert */
1011 	switch (sunw_check_cert_times(CHK_BOTH, cert)) {
1012 	case CHKERR_TIME_OK:
1013 		/* Current time meets requested checks */
1014 		break;
1015 	case CHKERR_TIME_BEFORE_BAD:
1016 		/* 'not before' field is invalid */
1017 	case CHKERR_TIME_AFTER_BAD:
1018 		/* 'not after' field is invalid */
1019 		pkgerr_add(err, PKGERR_TIME, gettext(ERR_CERT_TIME_BAD));
1020 		return (1);
1021 	case CHKERR_TIME_IS_BEFORE:
1022 		/* Current time is before 'not before' */
1023 	case CHKERR_TIME_HAS_EXPIRED:
1024 		/*
1025 		 * Ignore expiration time since the trust cert used to
1026 		 * verify the certs used to sign Sun patches is already
1027 		 * expired. Once the patches get resigned with the new
1028 		 * cert we will check expiration against the time the
1029 		 * patch was signed and not the time it is installed.
1030 		 */
1031 		return (0);
1032 	default:
1033 		pkgerr_add(err, PKGERR_INTERNAL,
1034 		    gettext(ERR_KEYSTORE_INTERNAL),
1035 		    __FILE__, __LINE__);
1036 		return (1);
1037 	}
1038 
1039 	/* all checks ok */
1040 	return (0);
1041 }
1042 
1043 /*
1044  * check_cert - Checks certificate validity.  This routine
1045  * checks everything that check_cert checks, and additionally
1046  * verifies that the private key and corresponding public
1047  * key are indeed a pair.
1048  *
1049  * Arguments:
1050  * err - Error object to add errors to
1051  * cert - The certificate to check
1052  * key - the key to check
1053  * Returns:
1054  *   0 - Success - Certificate checks out
1055  * non-zero - Failure, errors and reasons recorded in err
1056  */
1057 int
1058 check_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key)
1059 {
1060 
1061 	/* check validity dates */
1062 	if (check_cert(err, cert) != 0) {
1063 		return (1);
1064 	}
1065 
1066 	/* check key pair match */
1067 	if (sunw_check_keys(cert, key) == 0) {
1068 		pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MISMATCHED_KEYS),
1069 		    get_subject_display_name(cert));
1070 		return (1);
1071 	}
1072 
1073 	/* all checks OK */
1074 	return (0);
1075 }
1076 
1077 /* ------------------ private functions ---------------------- */
1078 
1079 /*
1080  * verify_keystore_integrity - Searches for the remnants
1081  * of a failed or aborted keystore modification, and
1082  * cleans up the files, retstores the keystore to a known
1083  * state.
1084  *
1085  * Arguments:
1086  * err - Error object to add errors to
1087  * keystore_file - Base directory or filename of keystore
1088  * app - Application making request
1089  *
1090  * Returns:
1091  *   0 - Success - Keystore is restored, or untouched in the
1092  *		case that cleanup was unnecessary
1093  * non-zero - Failure, errors and reasons recorded in err
1094  */
1095 static boolean_t
1096 verify_keystore_integrity(PKG_ERR *err, keystore_t *keystore)
1097 {
1098 	if (keystore->capath != NULL) {
1099 		if (!restore_keystore_file(err, keystore->capath)) {
1100 			return (B_FALSE);
1101 		}
1102 	}
1103 	if (keystore->clpath != NULL) {
1104 		if (!restore_keystore_file(err, keystore->clpath)) {
1105 			return (B_FALSE);
1106 		}
1107 	}
1108 	if (keystore->keypath != NULL) {
1109 		if (!restore_keystore_file(err, keystore->keypath)) {
1110 			return (B_FALSE);
1111 		}
1112 	}
1113 	return (B_TRUE);
1114 }
1115 
1116 /*
1117  * restore_keystore_file - restores a keystore file to
1118  * a known state.
1119  *
1120  * Keystore files can possibly be corrupted by a variety
1121  * of error conditions during reading/writing.  This
1122  * routine, along with write_keystore_file, tries to
1123  * maintain keystore integrity by writing the files
1124  * out in a particular order, minimizing the time period
1125  * that the keystore is in an indeterminate state.
1126  *
1127  * With the current implementation, there are some failures
1128  * that are wholly unrecoverable, such as disk corruption.
1129  * These routines attempt to minimize the risk, but not
1130  * eliminate it.  When better, atomic operations are available
1131  * (such as a trued atabase with commit, rollback, and
1132  * guaranteed atomicity), this implementation should use that.
1133  *
1134  * Arguments:
1135  * err - Error object to add errors to
1136  * keystore_file - keystore file path to restore.
1137  *
1138  * Returns:
1139  *   0 - Success - Keystore file is restored, or untouched in the
1140  *		case that cleanup was unnecessary
1141  * non-zero - Failure, errors and reasons recorded in err
1142  */
1143 /* ARGSUSED */
1144 static boolean_t
1145 restore_keystore_file(PKG_ERR *err, char *keystore_file)
1146 {
1147 	char	newpath[MAXPATHLEN];
1148 	char	backuppath[MAXPATHLEN];
1149 	int	newfd;
1150 	struct stat buf;
1151 	int len;
1152 
1153 	if (((len = snprintf(newpath, MAXPATHLEN, "%s.new",
1154 	    keystore_file)) < 0) ||
1155 	    (len >= ATTR_MAX)) {
1156 		pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
1157 		return (B_FALSE);
1158 	}
1159 
1160 	if (((len = snprintf(backuppath, MAXPATHLEN, "%s.bak",
1161 	    keystore_file)) < 0) ||
1162 	    (len >= ATTR_MAX)) {
1163 		pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
1164 		return (B_FALSE);
1165 	}
1166 
1167 	if ((newfd = open(newpath, O_RDWR|O_NONBLOCK, 0)) != -1) {
1168 		if (fstat(newfd, &buf) != -1) {
1169 			if (S_ISREG(buf.st_mode)) {
1170 				/*
1171 				 * restore the file, waiting on it
1172 				 * to be free for locking, or for
1173 				 * it to disappear
1174 				 */
1175 				if (!wait_restore(newfd, keystore_file,
1176 				    newpath, backuppath)) {
1177 					pkgerr_add(err, PKGERR_WRITE,
1178 					    gettext(ERR_WRITE),
1179 					    newpath, strerror(errno));
1180 					(void) close(newfd);
1181 					return (B_FALSE);
1182 				} else {
1183 					return (B_TRUE);
1184 				}
1185 			} else {
1186 				/* "new" file is not a regular file */
1187 				pkgerr_add(err, PKGERR_WRITE,
1188 				    gettext(ERR_NOT_REG), newpath);
1189 				(void) close(newfd);
1190 				return (B_FALSE);
1191 			}
1192 		} else {
1193 			/* couldn't stat "new" file */
1194 			pkgerr_add(err, PKGERR_WRITE,
1195 			    gettext(ERR_WRITE), newpath,
1196 			    strerror(errno));
1197 			(void) close(newfd);
1198 			return (B_FALSE);
1199 		}
1200 	} else {
1201 		/* "new" file doesn't exist */
1202 		return (B_TRUE);
1203 	}
1204 }
1205 
1206 static boolean_t
1207 wait_restore(int newfd, char *keystore_file,
1208     char *origpath, char *backuppath)
1209 {
1210 	struct stat buf;
1211 	FILE *newstream;
1212 	PKCS12 *p12;
1213 
1214 	(void) alarm(LOCK_TIMEOUT);
1215 	if (file_lock(newfd, F_WRLCK, 1) == -1) {
1216 		/* could not lock file */
1217 		(void) alarm(0);
1218 		return (B_FALSE);
1219 	}
1220 	(void) alarm(0);
1221 
1222 	if (fstat(newfd, &buf) != -1) {
1223 		if (S_ISREG(buf.st_mode)) {
1224 			/*
1225 			 * The new file still
1226 			 * exists, with no
1227 			 * owner.  It must be
1228 			 * the result of an
1229 			 * aborted update.
1230 			 */
1231 			newstream = fdopen(newfd, "r");
1232 			if ((p12 =
1233 			    d2i_PKCS12_fp(newstream,
1234 				NULL)) != NULL) {
1235 				/*
1236 				 * The file
1237 				 * appears
1238 				 * complete.
1239 				 * Replace the
1240 				 * exsisting
1241 				 * keystore
1242 				 * file with
1243 				 * this one
1244 				 */
1245 				(void) rename(keystore_file, backuppath);
1246 				(void) rename(origpath, keystore_file);
1247 				PKCS12_free(p12);
1248 			} else {
1249 				/* The file is not complete.  Remove it */
1250 				(void) remove(origpath);
1251 			}
1252 			/* remove backup file */
1253 			(void) remove(backuppath);
1254 			(void) fclose(newstream);
1255 			(void) close(newfd);
1256 			return (B_TRUE);
1257 		} else {
1258 			/*
1259 			 * new file exists, but is not a
1260 			 * regular file
1261 			 */
1262 			(void) close(newfd);
1263 			return (B_FALSE);
1264 		}
1265 	} else {
1266 		/*
1267 		 * could not stat file.  Unless
1268 		 * the reason was that the file
1269 		 * is now gone, this is an error
1270 		 */
1271 		if (errno != ENOENT) {
1272 			(void) close(newfd);
1273 			return (B_FALSE);
1274 		}
1275 		/*
1276 		 * otherwise, file is gone.  The process
1277 		 * that held the lock must have
1278 		 * successfully cleaned up and
1279 		 * exited with a valid keystore
1280 		 * state
1281 		 */
1282 		(void) close(newfd);
1283 		return (B_TRUE);
1284 	}
1285 }
1286 
1287 /*
1288  * resolve_paths - figure out if we are dealing with a single-file
1289  * or multi-file keystore
1290  *
1291  * The flags tell resolve_paths how to behave:
1292  *
1293  * KEYSTORE_PATH_SOFT
1294  * If the keystore file does not exist at <base>/<app> then
1295  * use <base> as the path to the keystore.  This can be used,
1296  * for example, to access an app-specific keystore iff it
1297  * exists, otherwise revert back to an app-generic keystore.
1298  *
1299  * KEYSTORE_PATH_HARD
1300  * Always use the keystore located at <keystore_path>/<app>.
1301  * In read/write mode, if the files do not exist, then
1302  * they will be created.  This is used to avoid falling
1303  * back to an app-generic keystore path when the app-specific
1304  * one does not exist.
1305  *
1306  * Arguments:
1307  * err - Error object to add errors to
1308  * keystore_file - base keystore file path to lock
1309  * app - Application making requests
1310  * flags - Control flags (see above description)
1311  * keystore - object which is being locked
1312  *
1313  * Returns:
1314  *   B_TRUE - Success - Keystore file is locked, paths to
1315  *		appropriate files placed in keystore.
1316  *   B_FALSE - Failure, errors and reasons recorded in err
1317  */
1318 static boolean_t
1319 resolve_paths(PKG_ERR *err, char *keystore_file, char *app,
1320     long flags, keystore_t *keystore)
1321 {
1322 	char			storepath[PATH_MAX];
1323 	struct stat		buf;
1324 	boolean_t		multi = B_FALSE;
1325 	int			fd1, fd2, len;
1326 
1327 	/*
1328 	 * figure out whether we are dealing with a single-file keystore
1329 	 * or a multi-file keystore
1330 	 */
1331 	if (app != NULL) {
1332 		if (((len = snprintf(storepath, PATH_MAX, "%s/%s",
1333 		    keystore_file, app)) < 0) ||
1334 		    (len >= ATTR_MAX)) {
1335 			pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN),
1336 			    keystore_file);
1337 			return (B_FALSE);
1338 		}
1339 
1340 		if (((fd1 = open(storepath, O_NONBLOCK|O_RDONLY)) == -1) ||
1341 		    (fstat(fd1, &buf) == -1) ||
1342 		    !S_ISDIR(buf.st_mode)) {
1343 			/*
1344 			 * app-specific does not exist
1345 			 * fallback to app-generic, if flags say we can
1346 			 */
1347 			if ((flags & KEYSTORE_PATH_MASK) ==
1348 			    KEYSTORE_PATH_SOFT) {
1349 
1350 				if (((fd2 = open(keystore_file,
1351 				    O_NONBLOCK|O_RDONLY)) != -1) &&
1352 				    (fstat(fd2, &buf) != -1)) {
1353 					if (S_ISDIR(buf.st_mode)) {
1354 						/*
1355 						 * app-generic dir
1356 						 * exists, so use it
1357 						 * as a multi-file
1358 						 * keystore
1359 						 */
1360 						multi = B_TRUE;
1361 						app = NULL;
1362 					} else if (S_ISREG(buf.st_mode)) {
1363 						/*
1364 						 * app-generic file exists, so
1365 						 * use it as a single file ks
1366 						 */
1367 						multi = B_FALSE;
1368 						app = NULL;
1369 					}
1370 				}
1371 			}
1372 		}
1373 		if (fd1 != -1)
1374 			(void) close(fd1);
1375 		if (fd2 != -1)
1376 			(void) close(fd2);
1377 	} else {
1378 		if (((fd1 = open(keystore_file,
1379 		    O_NONBLOCK|O_RDONLY)) != -1) &&
1380 		    (fstat(fd1, &buf) != -1) &&
1381 		    S_ISDIR(buf.st_mode)) {
1382 			/*
1383 			 * app-generic dir exists, so use
1384 			 * it as a multi-file keystore
1385 			 */
1386 			multi = B_TRUE;
1387 		}
1388 		if (fd1 != -1)
1389 			(void) close(fd1);
1390 	}
1391 
1392 	if (app != NULL) {
1393 		/* app-specific keystore */
1394 		(void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
1395 		    keystore_file, app, TRUSTSTORE);
1396 		keystore->capath = xstrdup(storepath);
1397 		(void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
1398 		    keystore_file, app, CERTSTORE);
1399 		keystore->clpath = xstrdup(storepath);
1400 		(void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
1401 		    keystore_file, app, KEYSTORE);
1402 		keystore->keypath = xstrdup(storepath);
1403 	} else {
1404 		/* app-generic keystore */
1405 		if (!multi) {
1406 			/* single-file app-generic keystore */
1407 			keystore->capath = xstrdup(keystore_file);
1408 			keystore->keypath = NULL;
1409 			keystore->clpath = NULL;
1410 		} else {
1411 			/* multi-file app-generic keystore */
1412 			(void) snprintf(storepath, PATH_MAX, "%s/%s",
1413 			    keystore_file, TRUSTSTORE);
1414 			keystore->capath = xstrdup(storepath);
1415 			(void) snprintf(storepath, PATH_MAX, "%s/%s",
1416 			    keystore_file, CERTSTORE);
1417 			keystore->clpath = xstrdup(storepath);
1418 			(void) snprintf(storepath, PATH_MAX, "%s/%s",
1419 			    keystore_file, KEYSTORE);
1420 			keystore->keypath = xstrdup(storepath);
1421 		}
1422 	}
1423 
1424 	return (B_TRUE);
1425 }
1426 
1427 /*
1428  * lock_keystore - Locks a keystore for shared (read-only)
1429  * or exclusive (read-write) access.
1430  *
1431  * The flags tell lock_keystore how to behave:
1432  *
1433  * KEYSTORE_ACCESS_READONLY
1434  * opens keystore read-only.  Attempts to modify results in an error
1435  *
1436  * KEYSTORE_ACCESS_READWRITE
1437  * opens keystore read-write
1438  *
1439  * KEYSTORE_PATH_SOFT
1440  * If the keystore file does not exist at <base>/<app> then
1441  * use <base> as the path to the keystore.  This can be used,
1442  * for example, to access an app-specific keystore iff it
1443  * exists, otherwise revert back to an app-generic keystore.
1444  *
1445  * KEYSTORE_PATH_HARD
1446  * Always use the keystore located at <keystore_path>/<app>.
1447  * In read/write mode, if the files do not exist, then
1448  * they will be created.  This is used to avoid falling
1449  * back to an app-generic keystore path when the app-specific
1450  * one does not exist.
1451  *
1452  * Arguments:
1453  * err - Error object to add errors to
1454  * flags - Control flags (see above description)
1455  * keystore - object which is being locked
1456  *
1457  * Returns:
1458  *   0 - Success - Keystore file is locked, paths to
1459  *		appropriate files placed in keystore.
1460  * non-zero - Failure, errors and reasons recorded in err
1461  */
1462 static boolean_t
1463 lock_keystore(PKG_ERR *err, long flags, keystore_t *keystore)
1464 {
1465 	boolean_t		ret = B_TRUE;
1466 	struct stat		buf;
1467 
1468 	switch (flags & KEYSTORE_ACCESS_MASK) {
1469 	case KEYSTORE_ACCESS_READONLY:
1470 		if ((keystore->cafd =
1471 		    open(keystore->capath, O_NONBLOCK|O_RDONLY)) == -1) {
1472 			if (errno == ENOENT) {
1473 				/*
1474 				 * no keystore.  try to create an
1475 				 * empty one so we can lock on it and
1476 				 * prevent others from gaining
1477 				 * exclusive access.  It will be
1478 				 * deleted when the keystore is closed.
1479 				 */
1480 				if ((keystore->cafd =
1481 				    open(keystore->capath,
1482 					O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
1483 					S_IRUSR|S_IWUSR)) == -1) {
1484 					pkgerr_add(err, PKGERR_READ,
1485 					    gettext(ERR_NO_KEYSTORE),
1486 					    keystore->capath);
1487 					ret = B_FALSE;
1488 					goto cleanup;
1489 				}
1490 			} else {
1491 				pkgerr_add(err, PKGERR_READ,
1492 				    gettext(ERR_KEYSTORE_OPEN),
1493 				    keystore->capath, strerror(errno));
1494 				ret = B_FALSE;
1495 				goto cleanup;
1496 			}
1497 		}
1498 		if (fstat(keystore->cafd, &buf) != -1) {
1499 			if (S_ISREG(buf.st_mode)) {
1500 				if (file_lock(keystore->cafd, F_RDLCK,
1501 				    0) == -1) {
1502 					pkgerr_add(err, PKGERR_LOCKED,
1503 					    gettext(ERR_KEYSTORE_LOCKED_READ),
1504 					    keystore->capath);
1505 					ret = B_FALSE;
1506 					goto cleanup;
1507 				}
1508 			} else {
1509 				/* ca file not a regular file! */
1510 				pkgerr_add(err, PKGERR_READ,
1511 				    gettext(ERR_NOT_REG),
1512 				    keystore->capath);
1513 				ret = B_FALSE;
1514 				goto cleanup;
1515 			}
1516 		} else {
1517 			pkgerr_add(err, PKGERR_READ,
1518 			    gettext(ERR_KEYSTORE_OPEN),
1519 			    keystore->capath, strerror(errno));
1520 			ret = B_FALSE;
1521 			goto cleanup;
1522 		}
1523 		break;
1524 	case KEYSTORE_ACCESS_READWRITE:
1525 
1526 		if ((keystore->cafd = open(keystore->capath,
1527 		    O_RDWR|O_NONBLOCK)) == -1) {
1528 			/* does not exist.  try to create an empty one */
1529 			if (errno == ENOENT) {
1530 				if ((keystore->cafd =
1531 				    open(keystore->capath,
1532 					O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
1533 					S_IRUSR|S_IWUSR)) == -1) {
1534 					pkgerr_add(err, PKGERR_READ,
1535 					    gettext(ERR_KEYSTORE_WRITE),
1536 					    keystore->capath);
1537 					ret = B_FALSE;
1538 					goto cleanup;
1539 				}
1540 			} else {
1541 				pkgerr_add(err, PKGERR_READ,
1542 				    gettext(ERR_KEYSTORE_OPEN),
1543 				    keystore->capath, strerror(errno));
1544 				ret = B_FALSE;
1545 				goto cleanup;
1546 			}
1547 		}
1548 		if (fstat(keystore->cafd, &buf) != -1) {
1549 			if (S_ISREG(buf.st_mode)) {
1550 				if (file_lock(keystore->cafd, F_WRLCK,
1551 				    0) == -1) {
1552 					pkgerr_add(err, PKGERR_LOCKED,
1553 					    gettext(ERR_KEYSTORE_LOCKED),
1554 					    keystore->capath);
1555 					ret = B_FALSE;
1556 					goto cleanup;
1557 				}
1558 			} else {
1559 				/* ca file not a regular file! */
1560 				pkgerr_add(err, PKGERR_READ,
1561 				    gettext(ERR_NOT_REG),
1562 				    keystore->capath);
1563 				ret = B_FALSE;
1564 				goto cleanup;
1565 			}
1566 		} else {
1567 			pkgerr_add(err, PKGERR_READ,
1568 			    gettext(ERR_KEYSTORE_OPEN),
1569 			    keystore->capath, strerror(errno));
1570 			ret = B_FALSE;
1571 			goto cleanup;
1572 		}
1573 
1574 		break;
1575 	default:
1576 		pkgerr_add(err, PKGERR_INTERNAL,
1577 		    gettext(ERR_KEYSTORE_INTERNAL),
1578 		    __FILE__, __LINE__);
1579 		ret = B_FALSE;
1580 		goto cleanup;
1581 	}
1582 
1583 cleanup:
1584 	if (!ret) {
1585 		if (keystore->cafd > 0) {
1586 			(void) file_unlock(keystore->cafd);
1587 			(void) close(keystore->cafd);
1588 			keystore->cafd = -1;
1589 		}
1590 
1591 		if (keystore->capath != NULL)
1592 			free(keystore->capath);
1593 		if (keystore->clpath != NULL)
1594 			free(keystore->clpath);
1595 		if (keystore->keypath != NULL)
1596 			free(keystore->keypath);
1597 		keystore->capath = NULL;
1598 		keystore->clpath = NULL;
1599 		keystore->keypath = NULL;
1600 	}
1601 
1602 	return (ret);
1603 }
1604 
1605 /*
1606  * unlock_keystore - Unocks a keystore
1607  *
1608  * Arguments:
1609  * err - Error object to add errors to
1610  * keystore - keystore object to unlock
1611  * Returns:
1612  *   0 - Success - Keystore files are unlocked, files are closed,
1613  * non-zero - Failure, errors and reasons recorded in err
1614  */
1615 /* ARGSUSED */
1616 static boolean_t
1617 unlock_keystore(PKG_ERR *err, keystore_t *keystore)
1618 {
1619 
1620 	/*
1621 	 * Release lock on the CA file.
1622 	 * Delete file if it is empty
1623 	 */
1624 	if (file_empty(keystore->capath)) {
1625 		(void) remove(keystore->capath);
1626 	}
1627 
1628 	(void) file_unlock(keystore->cafd);
1629 	(void) close(keystore->cafd);
1630 	return (B_TRUE);
1631 }
1632 
1633 /*
1634  * read_keystore - Reads keystore files of disk, parses
1635  * into internal structures.
1636  *
1637  * Arguments:
1638  * err - Error object to add errors to
1639  * keystore - keystore object to read into
1640  * cb - callback to get password, if required
1641  * Returns:
1642  *   0 - Success - Keystore files are read, and placed
1643  * into keystore structure.
1644  * non-zero - Failure, errors and reasons recorded in err
1645  */
1646 static boolean_t
1647 read_keystore(PKG_ERR *err, keystore_t *keystore, keystore_passphrase_cb cb)
1648 {
1649 	boolean_t	ret = B_TRUE;
1650 	PKCS12		*p12 = NULL;
1651 	boolean_t	ca_empty;
1652 	boolean_t	have_passwd = B_FALSE;
1653 	boolean_t	cl_empty = B_TRUE;
1654 	boolean_t	key_empty = B_TRUE;
1655 
1656 	ca_empty = file_empty(keystore->capath);
1657 
1658 	if (keystore->clpath != NULL)
1659 		cl_empty = file_empty(keystore->clpath);
1660 	if (keystore->keypath != NULL)
1661 		key_empty = file_empty(keystore->keypath);
1662 
1663 	if (ca_empty && cl_empty && key_empty) {
1664 	    keystore->new = B_TRUE;
1665 	}
1666 
1667 	if (!ca_empty) {
1668 		/* first read the ca file */
1669 		if ((p12 = read_keystore_file(err,
1670 		    keystore->capath)) == NULL) {
1671 			pkgerr_add(err, PKGERR_CORRUPT,
1672 			    gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
1673 			ret = B_FALSE;
1674 			goto cleanup;
1675 		}
1676 
1677 		/* Get password, using callback if necessary */
1678 		if (!have_passwd) {
1679 			if (!get_keystore_passwd(err, p12, cb, keystore)) {
1680 				ret = B_FALSE;
1681 				goto cleanup;
1682 			}
1683 			have_passwd = B_TRUE;
1684 		}
1685 
1686 		/* decrypt and parse keystore file */
1687 		if (sunw_PKCS12_contents(p12, keystore->passphrase,
1688 		    &keystore->pkeys, &keystore->cacerts) < 0) {
1689 			/* could not parse the contents */
1690 			pkgerr_add(err, PKGERR_CORRUPT,
1691 			    gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
1692 			ret = B_FALSE;
1693 			goto cleanup;
1694 		}
1695 
1696 		PKCS12_free(p12);
1697 		p12 = NULL;
1698 	} else {
1699 
1700 		/*
1701 		 * truststore is empty, so we don't have any trusted
1702 		 * certs
1703 		 */
1704 		keystore->cacerts = NULL;
1705 	}
1706 
1707 	/*
1708 	 * if there is no cl file or key file, use the cl's and key's found
1709 	 * in the ca file
1710 	 */
1711 	if (keystore->clpath == NULL && !ca_empty) {
1712 		if (sunw_split_certs(keystore->pkeys, keystore->cacerts,
1713 		    &keystore->clcerts, NULL) < 0) {
1714 			pkgerr_add(err, PKGERR_CORRUPT,
1715 			    gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
1716 			ret = B_FALSE;
1717 			goto cleanup;
1718 		}
1719 	} else {
1720 		/*
1721 		 * files are in separate files.  read keys out of the keystore
1722 		 * certs out of the certstore, if they are not empty
1723 		 */
1724 		if (!cl_empty) {
1725 			if ((p12 = read_keystore_file(err,
1726 			    keystore->clpath)) == NULL) {
1727 				pkgerr_add(err, PKGERR_CORRUPT,
1728 				    gettext(ERR_KEYSTORE_CORRUPT),
1729 				    keystore->clpath);
1730 				ret = B_FALSE;
1731 				goto cleanup;
1732 			}
1733 
1734 			/* Get password, using callback if necessary */
1735 			if (!have_passwd) {
1736 				if (!get_keystore_passwd(err, p12, cb,
1737 				    keystore)) {
1738 					ret = B_FALSE;
1739 					goto cleanup;
1740 				}
1741 				have_passwd = B_TRUE;
1742 			}
1743 
1744 			if (check_password(p12,
1745 			    keystore->passphrase) == B_FALSE) {
1746 				/*
1747 				 * password in client cert file
1748 				 * is different than
1749 				 * the one in the other files!
1750 				 */
1751 				pkgerr_add(err, PKGERR_BADPASS,
1752 				    gettext(ERR_MISMATCHPASS),
1753 				    keystore->clpath,
1754 				    keystore->capath, keystore->path);
1755 				ret = B_FALSE;
1756 				goto cleanup;
1757 			}
1758 
1759 			if (sunw_PKCS12_contents(p12, keystore->passphrase,
1760 			    NULL, &keystore->clcerts) < 0) {
1761 				/* could not parse the contents */
1762 				pkgerr_add(err, PKGERR_CORRUPT,
1763 				    gettext(ERR_KEYSTORE_CORRUPT),
1764 				    keystore->clpath);
1765 				ret = B_FALSE;
1766 				goto cleanup;
1767 			}
1768 
1769 			PKCS12_free(p12);
1770 			p12 = NULL;
1771 		} else {
1772 			keystore->clcerts = NULL;
1773 		}
1774 
1775 		if (!key_empty) {
1776 			if ((p12 = read_keystore_file(err,
1777 			    keystore->keypath)) == NULL) {
1778 				pkgerr_add(err, PKGERR_CORRUPT,
1779 				    gettext(ERR_KEYSTORE_CORRUPT),
1780 				    keystore->keypath);
1781 				ret = B_FALSE;
1782 				goto cleanup;
1783 			}
1784 
1785 			/* Get password, using callback if necessary */
1786 			if (!have_passwd) {
1787 				if (!get_keystore_passwd(err, p12, cb,
1788 				    keystore)) {
1789 					ret = B_FALSE;
1790 					goto cleanup;
1791 				}
1792 				have_passwd = B_TRUE;
1793 			}
1794 
1795 			if (check_password(p12,
1796 			    keystore->passphrase) == B_FALSE) {
1797 				pkgerr_add(err, PKGERR_BADPASS,
1798 				    gettext(ERR_MISMATCHPASS),
1799 				    keystore->keypath,
1800 				    keystore->capath, keystore->path);
1801 				ret = B_FALSE;
1802 				goto cleanup;
1803 			}
1804 
1805 			if (sunw_PKCS12_contents(p12, keystore->passphrase,
1806 			    &keystore->pkeys, NULL) < 0) {
1807 				/* could not parse the contents */
1808 				pkgerr_add(err, PKGERR_CORRUPT,
1809 				    gettext(ERR_KEYSTORE_CORRUPT),
1810 				    keystore->keypath);
1811 				ret = B_FALSE;
1812 				goto cleanup;
1813 			}
1814 
1815 			PKCS12_free(p12);
1816 			p12 = NULL;
1817 		} else {
1818 			keystore->pkeys = NULL;
1819 		}
1820 	}
1821 
1822 cleanup:
1823 	if (p12 != NULL)
1824 		PKCS12_free(p12);
1825 	return (ret);
1826 }
1827 
1828 /*
1829  * get_keystore_password - retrieves pasword used to
1830  * decrypt PKCS12 structure.
1831  *
1832  * Arguments:
1833  * err - Error object to add errors to
1834  * p12 - PKCS12 structure which returned password should
1835  * decrypt
1836  * cb - callback to collect password.
1837  * keystore - The keystore in which the PKCS12 structure
1838  * will eventually populate.
1839  * Returns:
1840  *   B_TRUE - success.
1841  *     keystore password is set in keystore->passphrase.
1842  *   B_FALSE - failure, errors logged
1843  */
1844 static boolean_t
1845 get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, keystore_passphrase_cb cb,
1846     keystore_t *keystore)
1847 {
1848 	char				*passwd;
1849 	char				passbuf[KEYSTORE_PASS_MAX + 1];
1850 	keystore_passphrase_data	data;
1851 
1852 	/* see if no password is the right password */
1853 	if (check_password(p12, "") == B_TRUE) {
1854 		passwd = "";
1855 	} else if (check_password(p12, NULL) == B_TRUE) {
1856 		passwd = NULL;
1857 	} else {
1858 		/* oops, it's encrypted.  get password */
1859 		data.err = err;
1860 		if (cb(passbuf, KEYSTORE_PASS_MAX, 0,
1861 		    &data) == -1) {
1862 			/* could not get password */
1863 			return (B_FALSE);
1864 		}
1865 
1866 		if (check_password(p12, passbuf) == B_FALSE) {
1867 				/* wrong password */
1868 			pkgerr_add(err, PKGERR_BADPASS,
1869 			    gettext(ERR_BADPASS));
1870 			return (B_FALSE);
1871 		}
1872 
1873 		/*
1874 		 * make copy of password buffer, since it
1875 		 * goes away upon return
1876 		 */
1877 		passwd = xstrdup(passbuf);
1878 	}
1879 	keystore->passphrase = passwd;
1880 	return (B_TRUE);
1881 }
1882 
1883 /*
1884  * write_keystore - Writes keystore files to disk
1885  *
1886  * Arguments:
1887  * err - Error object to add errors to
1888  * keystore - keystore object to write from
1889  * passwd - password used to encrypt keystore
1890  * Returns:
1891  *   0 - Success - Keystore contents are written out to
1892  *   the same locations as read from
1893  * non-zero - Failure, errors and reasons recorded in err
1894  */
1895 static boolean_t
1896 write_keystore(PKG_ERR *err, keystore_t *keystore,
1897     keystore_passphrase_cb cb)
1898 {
1899 	PKCS12	*p12 = NULL;
1900 	boolean_t ret = B_TRUE;
1901 	keystore_passphrase_data data;
1902 	char		passbuf[KEYSTORE_PASS_MAX + 1];
1903 
1904 	if (keystore->capath != NULL && keystore->clpath == NULL &&
1905 	    keystore->keypath == NULL) {
1906 
1907 		/*
1908 		 * keystore is a file.
1909 		 * just write out a single file
1910 		 */
1911 		if ((keystore->pkeys == NULL) &&
1912 		    (keystore->clcerts == NULL) &&
1913 		    (keystore->cacerts == NULL)) {
1914 			if (!clear_keystore_file(err, keystore->capath)) {
1915 				/*
1916 				 * no keys or certs to write out, so
1917 				 * blank the ca file.  we do not
1918 				 * delete it since it is used as a
1919 				 * lock by lock_keystore() in
1920 				 * subsequent invocations
1921 				 */
1922 				pkgerr_add(err, PKGERR_WRITE,
1923 				    gettext(ERR_KEYSTORE_WRITE),
1924 				    keystore->capath);
1925 				ret = B_FALSE;
1926 				goto cleanup;
1927 			}
1928 		} else {
1929 			/*
1930 			 * if the keystore is being created for the first time,
1931 			 * prompt for a passphrase for encryption
1932 			 */
1933 			if (keystore->new) {
1934 				data.err = err;
1935 				if (cb(passbuf, KEYSTORE_PASS_MAX,
1936 				    1, &data) == -1) {
1937 					ret = B_FALSE;
1938 					goto cleanup;
1939 				}
1940 			} else {
1941 				/*
1942 				 * use the one used when the keystore
1943 				 * was read
1944 				 */
1945 				(void) strlcpy(passbuf, keystore->passphrase,
1946 				    KEYSTORE_PASS_MAX);
1947 			}
1948 
1949 			p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
1950 			    keystore->clcerts, keystore->cacerts);
1951 
1952 			if (p12 == NULL) {
1953 				pkgerr_add(err, PKGERR_WRITE,
1954 				    gettext(ERR_KEYSTORE_FORM),
1955 				    keystore->capath);
1956 				ret = B_FALSE;
1957 				goto cleanup;
1958 			}
1959 
1960 			if (!write_keystore_file(err, keystore->capath, p12)) {
1961 				pkgerr_add(err, PKGERR_WRITE,
1962 				    gettext(ERR_KEYSTORE_WRITE),
1963 				    keystore->capath);
1964 				ret = B_FALSE;
1965 				goto cleanup;
1966 			}
1967 		}
1968 
1969 	} else {
1970 		/* files are seprate. Do one at a time */
1971 
1972 		/*
1973 		 * if the keystore is being created for the first time,
1974 		 * prompt for a passphrase for encryption
1975 		 */
1976 		if (keystore->new && ((keystore->pkeys != NULL) ||
1977 		    (keystore->clcerts != NULL) ||
1978 		    (keystore->cacerts != NULL))) {
1979 			data.err = err;
1980 			if (cb(passbuf, KEYSTORE_PASS_MAX,
1981 			    1, &data) == -1) {
1982 				ret = B_FALSE;
1983 				goto cleanup;
1984 			}
1985 		} else {
1986 			/* use the one used when the keystore was read */
1987 			(void) strlcpy(passbuf, keystore->passphrase,
1988 			    KEYSTORE_PASS_MAX);
1989 		}
1990 
1991 		/* do private keys first */
1992 		if (keystore->pkeys != NULL) {
1993 			p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
1994 			    NULL, NULL);
1995 
1996 			if (p12 == NULL) {
1997 				pkgerr_add(err, PKGERR_WRITE,
1998 				    gettext(ERR_KEYSTORE_FORM),
1999 				    keystore->keypath);
2000 				ret = B_FALSE;
2001 				goto cleanup;
2002 			}
2003 
2004 			if (!write_keystore_file(err, keystore->keypath,
2005 			    p12)) {
2006 				pkgerr_add(err, PKGERR_WRITE,
2007 				    gettext(ERR_KEYSTORE_WRITE),
2008 				    keystore->keypath);
2009 				ret = B_FALSE;
2010 				goto cleanup;
2011 			}
2012 
2013 			PKCS12_free(p12);
2014 		} else {
2015 			if ((remove(keystore->keypath) != 0) &&
2016 			    (errno != ENOENT)) {
2017 				pkgerr_add(err, PKGERR_WRITE,
2018 				    gettext(ERR_KEYSTORE_REMOVE),
2019 				    keystore->keypath);
2020 				ret = B_FALSE;
2021 				goto cleanup;
2022 			}
2023 		}
2024 
2025 		/* do user certs next */
2026 		if (keystore->clcerts != NULL) {
2027 			p12 = sunw_PKCS12_create(passbuf, NULL,
2028 			    keystore->clcerts, NULL);
2029 
2030 			if (p12 == NULL) {
2031 				pkgerr_add(err, PKGERR_WRITE,
2032 				    gettext(ERR_KEYSTORE_FORM),
2033 				    keystore->clpath);
2034 				ret = B_FALSE;
2035 				goto cleanup;
2036 			}
2037 
2038 			if (!write_keystore_file(err, keystore->clpath, p12)) {
2039 				pkgerr_add(err, PKGERR_WRITE,
2040 				    gettext(ERR_KEYSTORE_WRITE),
2041 				    keystore->clpath);
2042 				ret = B_FALSE;
2043 				goto cleanup;
2044 			}
2045 
2046 			PKCS12_free(p12);
2047 		} else {
2048 			if ((remove(keystore->clpath) != 0) &&
2049 			    (errno != ENOENT)) {
2050 				pkgerr_add(err, PKGERR_WRITE,
2051 				    gettext(ERR_KEYSTORE_REMOVE),
2052 				    keystore->clpath);
2053 				ret = B_FALSE;
2054 				goto cleanup;
2055 			}
2056 		}
2057 
2058 
2059 		/* finally do CA cert file */
2060 		if (keystore->cacerts != NULL) {
2061 			p12 = sunw_PKCS12_create(passbuf, NULL,
2062 			    NULL, keystore->cacerts);
2063 
2064 			if (p12 == NULL) {
2065 				pkgerr_add(err, PKGERR_WRITE,
2066 				    gettext(ERR_KEYSTORE_FORM),
2067 				    keystore->capath);
2068 				ret = B_FALSE;
2069 				goto cleanup;
2070 			}
2071 
2072 			if (!write_keystore_file(err, keystore->capath, p12)) {
2073 				pkgerr_add(err, PKGERR_WRITE,
2074 				    gettext(ERR_KEYSTORE_WRITE),
2075 				    keystore->capath);
2076 				ret = B_FALSE;
2077 				goto cleanup;
2078 			}
2079 
2080 			PKCS12_free(p12);
2081 			p12 = NULL;
2082 		} else {
2083 			/*
2084 			 * nothing to write out, so truncate the file
2085 			 * (it will be deleted during close_keystore)
2086 			 */
2087 			if (!clear_keystore_file(err, keystore->capath)) {
2088 				pkgerr_add(err, PKGERR_WRITE,
2089 				    gettext(ERR_KEYSTORE_WRITE),
2090 				    keystore->capath);
2091 				ret = B_FALSE;
2092 				goto cleanup;
2093 			}
2094 		}
2095 	}
2096 
2097 cleanup:
2098 	if (p12 != NULL)
2099 		PKCS12_free(p12);
2100 
2101 	return (ret);
2102 }
2103 
2104 /*
2105  * clear_keystore_file - Clears (zeros out) a keystore file.
2106  *
2107  * Arguments:
2108  * err - Error object to add errors to
2109  * dest - Path of keystore file to zero out.
2110  * Returns:
2111  *   0 - Success - Keystore file is truncated to zero length
2112  * non-zero - Failure, errors and reasons recorded in err
2113  */
2114 static boolean_t
2115 clear_keystore_file(PKG_ERR *err, char *dest)
2116 {
2117 	int fd;
2118 	struct stat buf;
2119 
2120 	fd = open(dest, O_RDWR|O_NONBLOCK);
2121 	if (fd == -1) {
2122 		/* can't open for writing */
2123 		pkgerr_add(err, PKGERR_WRITE, gettext(MSG_OPEN),
2124 		    errno);
2125 		return (B_FALSE);
2126 	}
2127 
2128 	if ((fstat(fd, &buf) == -1) || !S_ISREG(buf.st_mode)) {
2129 		/* not a regular file */
2130 		(void) close(fd);
2131 		pkgerr_add(err, PKGERR_WRITE, gettext(ERR_NOT_REG),
2132 		    dest);
2133 		return (B_FALSE);
2134 	}
2135 
2136 	if (ftruncate(fd, 0) == -1) {
2137 		(void) close(fd);
2138 		pkgerr_add(err, PKGERR_WRITE, gettext(ERR_WRITE),
2139 		    dest, strerror(errno));
2140 		return (B_FALSE);
2141 	}
2142 
2143 	(void) close(fd);
2144 	return (B_TRUE);
2145 }
2146 
2147 /*
2148  * write_keystore_file - Writes keystore file to disk.
2149  *
2150  * Keystore files can possibly be corrupted by a variety
2151  * of error conditions during reading/writing.  This
2152  * routine, along with restore_keystore_file, tries to
2153  * maintain keystore integity by writing the files
2154  * out in a particular order, minimizing the time period
2155  * that the keystore is in an indeterminate state.
2156  *
2157  * With the current implementation, there are some failures
2158  * that are wholly unrecoverable, such as disk corruption.
2159  * These routines attempt to minimize the risk, but not
2160  * eliminate it.  When better, atomic operations are available
2161  * (such as a true database with commit, rollback, and
2162  * guaranteed atomicity), this implementation should use that.
2163  *
2164  *
2165  * Arguments:
2166  * err - Error object to add errors to
2167  * dest - Destination filename
2168  * contents - Contents to write to the file
2169  * Returns:
2170  *   0 - Success - Keystore contents are written out to
2171  *   the destination.
2172  * non-zero - Failure, errors and reasons recorded in err
2173  */
2174 static boolean_t
2175 write_keystore_file(PKG_ERR *err, char *dest, PKCS12 *contents)
2176 {
2177 	FILE	*newfile = NULL;
2178 	boolean_t	ret = B_TRUE;
2179 	char	newpath[MAXPATHLEN];
2180 	char	backuppath[MAXPATHLEN];
2181 	struct stat buf;
2182 	int fd;
2183 
2184 	(void) snprintf(newpath, MAXPATHLEN, "%s.new", dest);
2185 	(void) snprintf(backuppath, MAXPATHLEN, "%s.bak", dest);
2186 
2187 	if ((fd = open(newpath, O_CREAT|O_EXCL|O_WRONLY|O_NONBLOCK,
2188 	    S_IRUSR|S_IWUSR)) == -1) {
2189 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2190 		    newpath, strerror(errno));
2191 		ret = B_FALSE;
2192 		goto cleanup;
2193 	}
2194 
2195 	if (fstat(fd, &buf) == -1) {
2196 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2197 		    newpath, strerror(errno));
2198 		ret = B_FALSE;
2199 		goto cleanup;
2200 	}
2201 
2202 	if (!S_ISREG(buf.st_mode)) {
2203 		pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
2204 		    newpath);
2205 		ret = B_FALSE;
2206 		goto cleanup;
2207 	}
2208 
2209 	if ((newfile = fdopen(fd, "w")) == NULL) {
2210 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2211 		    newpath, strerror(errno));
2212 		ret = B_FALSE;
2213 		goto cleanup;
2214 	}
2215 
2216 	if (i2d_PKCS12_fp(newfile, contents) == 0) {
2217 		pkgerr_add(err, PKGERR_WRITE, gettext(ERR_KEYSTORE_WRITE),
2218 		    newpath);
2219 		ret = B_FALSE;
2220 		goto cleanup;
2221 	}
2222 
2223 	/* flush, then close */
2224 	(void) fflush(newfile);
2225 	(void) fclose(newfile);
2226 	newfile = NULL;
2227 
2228 	/* now back up the original file */
2229 	(void) rename(dest, backuppath);
2230 
2231 	/* put new one in its place */
2232 	(void) rename(newpath, dest);
2233 
2234 	/* remove backup */
2235 	(void) remove(backuppath);
2236 
2237 cleanup:
2238 	if (newfile != NULL)
2239 		(void) fclose(newfile);
2240 	if (fd != -1)
2241 		(void) close(fd);
2242 
2243 	return (ret);
2244 }
2245 
2246 /*
2247  * read_keystore_file - Reads single keystore file
2248  * off disk in PKCS12 format.
2249  *
2250  * Arguments:
2251  * err - Error object to add errors to
2252  * file - File path to read
2253  * Returns:
2254  *   PKCS12 contents of file, or NULL if an error occurred.
2255  *   errors recorded in 'err'.
2256  */
2257 static PKCS12
2258 *read_keystore_file(PKG_ERR *err, char *file)
2259 {
2260 	int fd;
2261 	struct stat buf;
2262 	FILE *newfile;
2263 	PKCS12 *p12 = NULL;
2264 
2265 	if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
2266 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2267 		    file, strerror(errno));
2268 		goto cleanup;
2269 	}
2270 
2271 	if (fstat(fd, &buf) == -1) {
2272 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2273 		    file, strerror(errno));
2274 		goto cleanup;
2275 	}
2276 
2277 	if (!S_ISREG(buf.st_mode)) {
2278 		pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
2279 		    file);
2280 		goto cleanup;
2281 	}
2282 
2283 	if ((newfile = fdopen(fd, "r")) == NULL) {
2284 		pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
2285 		    file, strerror(errno));
2286 		goto cleanup;
2287 	}
2288 
2289 	if ((p12 = d2i_PKCS12_fp(newfile, NULL)) == NULL) {
2290 		pkgerr_add(err, PKGERR_CORRUPT,
2291 		    gettext(ERR_KEYSTORE_CORRUPT), file);
2292 		goto cleanup;
2293 	}
2294 
2295 cleanup:
2296 	if (newfile != NULL)
2297 		(void) fclose(newfile);
2298 	if (fd != -1)
2299 		(void) close(fd);
2300 
2301 	return (p12);
2302 }
2303 
2304 
2305 /*
2306  * Locks the specified file.
2307  */
2308 static int
2309 file_lock(int fd, int type, int wait)
2310 {
2311 	struct flock lock;
2312 
2313 	lock.l_type = type;
2314 	lock.l_start = 0;
2315 	lock.l_whence = SEEK_SET;
2316 	lock.l_len = 0;
2317 
2318 	if (!wait) {
2319 		if (file_lock_test(fd, type)) {
2320 			/*
2321 			 * The caller would have to wait to get the
2322 			 * lock on this file.
2323 			 */
2324 			return (-1);
2325 		}
2326 	}
2327 
2328 	return (fcntl(fd, F_SETLKW, &lock));
2329 }
2330 
2331 /*
2332  * Returns FALSE if the file is not locked; TRUE
2333  * otherwise.
2334  */
2335 static boolean_t
2336 file_lock_test(int fd, int type)
2337 {
2338 	struct flock lock;
2339 
2340 	lock.l_type = type;
2341 	lock.l_start = 0;
2342 	lock.l_whence = SEEK_SET;
2343 	lock.l_len = 0;
2344 
2345 	if (fcntl(fd, F_GETLK, &lock) != -1) {
2346 		if (lock.l_type != F_UNLCK) {
2347 			/*
2348 			 * The caller would have to wait to get the
2349 			 * lock on this file.
2350 			 */
2351 			return (B_TRUE);
2352 		}
2353 	}
2354 
2355 	/*
2356 	 * The file is not locked.
2357 	 */
2358 	return (B_FALSE);
2359 }
2360 
2361 /*
2362  * Unlocks the specified file.
2363  */
2364 static int
2365 file_unlock(int fd)
2366 {
2367 	struct flock lock;
2368 
2369 	lock.l_type = F_UNLCK;
2370 	lock.l_start = 0;
2371 	lock.l_whence = SEEK_SET;
2372 	lock.l_len = 0;
2373 
2374 	return (fcntl(fd, F_SETLK, &lock));
2375 }
2376 
2377 /*
2378  * Determines if file has a length of 0 or not
2379  */
2380 static boolean_t
2381 file_empty(char *path)
2382 {
2383 	struct stat	buf;
2384 
2385 	/* file is empty if size = 0 or it doesn't exist */
2386 	if (lstat(path, &buf) == 0) {
2387 		if (buf.st_size == 0) {
2388 			return (B_TRUE);
2389 		}
2390 	} else {
2391 		if (errno == ENOENT) {
2392 			return (B_TRUE);
2393 		}
2394 	}
2395 
2396 	return (B_FALSE);
2397 }
2398 
2399 /*
2400  * Name:		get_time_string
2401  * Description:	Generates a human-readable string from an ASN1_TIME
2402  *
2403  * Arguments:	intime - The time to convert
2404  *
2405  * Returns :	A pointer to a static string representing the passed-in time.
2406  */
2407 static char
2408 *get_time_string(ASN1_TIME *intime)
2409 {
2410 
2411 	static char	time[ATTR_MAX];
2412 	BIO		*mem;
2413 	char	*p;
2414 
2415 	if (intime == NULL) {
2416 		return (NULL);
2417 	}
2418 	if ((mem = BIO_new(BIO_s_mem())) == NULL) {
2419 		return (NULL);
2420 	}
2421 
2422 	if (ASN1_TIME_print(mem, intime) == 0) {
2423 		(void) BIO_free(mem);
2424 		return (NULL);
2425 	}
2426 
2427 	if (BIO_gets(mem, time, ATTR_MAX) <= 0) {
2428 		(void) BIO_free(mem);
2429 		return (NULL);
2430 	}
2431 
2432 	(void) BIO_free(mem);
2433 
2434 	/* trim the end of the string */
2435 	for (p = time + strlen(time) - 1; isspace(*p); p--) {
2436 		*p = '\0';
2437 	}
2438 
2439 	return (time);
2440 }
2441 
2442 /*
2443  * check_password - do various password checks to see if the current password
2444  *                  will work or we need to prompt for a new one.
2445  *
2446  * Arguments:
2447  *   pass   - password to check
2448  *
2449  * Returns:
2450  *   B_TRUE  - Password is OK.
2451  *   B_FALSE - Password not valid.
2452  */
2453 static boolean_t
2454 check_password(PKCS12 *p12, char *pass)
2455 {
2456 	boolean_t ret = B_TRUE;
2457 
2458 	/*
2459 	 * If password is zero length or NULL then try verifying both cases
2460 	 * to determine which password is correct. The reason for this is that
2461 	 * under PKCS#12 password based encryption no password and a zero
2462 	 * length password are two different things...
2463 	 */
2464 
2465 	/* Check the mac */
2466 	if (pass == NULL || *pass == '\0') {
2467 		if (PKCS12_verify_mac(p12, NULL, 0) == 0 &&
2468 		    PKCS12_verify_mac(p12, "", 0) == 0)
2469 			ret = B_FALSE;
2470 	} else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
2471 		ret = B_FALSE;
2472 	}
2473 	return (ret);
2474 }
2475