keystore.c revision 9781:ccf49524d5dc
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
56typedef 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 */
76static keystore_t	*new_keystore(void);
77static void		free_keystore(keystore_t *);
78static boolean_t	verify_keystore_integrity(PKG_ERR *, keystore_t *);
79static boolean_t	check_password(PKCS12 *, char *);
80static boolean_t	resolve_paths(PKG_ERR *, char *, char *,
81    long, keystore_t *);
82static boolean_t	lock_keystore(PKG_ERR *, long, keystore_t *);
83
84static boolean_t	unlock_keystore(PKG_ERR *, keystore_t *);
85static boolean_t	read_keystore(PKG_ERR *, keystore_t *,
86    keystore_passphrase_cb);
87static boolean_t	write_keystore(PKG_ERR *, keystore_t *,
88    keystore_passphrase_cb);
89static boolean_t	write_keystore_file(PKG_ERR *, char *, PKCS12 *);
90static boolean_t	clear_keystore_file(PKG_ERR *, char *);
91static PKCS12		*read_keystore_file(PKG_ERR *, char *);
92static char		*get_time_string(ASN1_TIME *);
93
94/* locking routines */
95static boolean_t	restore_keystore_file(PKG_ERR *, char *);
96static int		file_lock(int, int, int);
97static int		file_unlock(int);
98static boolean_t	file_lock_test(int, int);
99static boolean_t	file_empty(char *);
100static boolean_t	get_keystore_passwd(PKG_ERR *err, PKCS12 *p12,
101    keystore_passphrase_cb cb, keystore_t *keystore);
102static 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 */
123int
124print_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 */
237int 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
340cleanup:
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 */
368int
369open_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
415cleanup:
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 */
433static 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 */
465static void
466free_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 */
503int
504close_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);
529cleanup:
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 */
547int
548merge_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;
602cleanup:
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 */
623int
624find_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
692cleanup:
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 */
715int
716find_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 */
746int
747find_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 */
774int
775merge_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;
856cleanup:
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 */
881int
882delete_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 */
992int
993check_cert(PKG_ERR *err, X509 *cert)
994{
995	char			currtimestr[ATTR_MAX];
996	time_t			currtime;
997	char			*r, *before_str, *after_str;
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 */
1057int
1058check_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 */
1095static boolean_t
1096verify_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 */
1144static boolean_t
1145restore_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
1206static boolean_t
1207wait_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 */
1318static boolean_t
1319resolve_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 */
1462static boolean_t
1463lock_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
1583cleanup:
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 */
1616static boolean_t
1617unlock_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 */
1646static boolean_t
1647read_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
1822cleanup:
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 */
1844static boolean_t
1845get_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 */
1895static boolean_t
1896write_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				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			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
2097cleanup:
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 */
2114static boolean_t
2115clear_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 */
2174static boolean_t
2175write_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
2237cleanup:
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 */
2257static 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
2295cleanup:
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 */
2308static int
2309file_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 */
2335static boolean_t
2336file_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 */
2364static int
2365file_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 */
2380static boolean_t
2381file_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 */
2407static 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 */
2453static boolean_t
2454check_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