4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Description: This module contains the structure definitions for processing
30 * package keystore files.
40 #include <sys/types.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>
54 #include "pkglibmsgs.h"
56 typedef struct keystore_t
{
61 /* truststore handles */
63 STACK_OF(X509
) *cacerts
;
66 /* user certificate handles */
67 STACK_OF(X509
) *clcerts
;
70 /* private key handles */
71 STACK_OF(EVP_PKEY
) *pkeys
;
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 *,
82 static boolean_t
lock_keystore(PKG_ERR
*, long, keystore_t
*);
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
*);
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 *);
104 #define KEYSTORE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
106 /* wait on other keystore access for 1 minute before giving up */
107 #define LOCK_TIMEOUT 60
110 * print_certs - prints certificates out of a keystore, to a file.
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
121 * non-zero - Failure, errors added to err
124 print_certs(PKG_ERR
*err
, keystore_handle_t keystore_h
, char *alias
,
125 keystore_encoding_format_t format
, FILE *outfile
)
130 boolean_t found
= B_FALSE
;
131 keystore_t
*keystore
= keystore_h
;
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
,
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
));
148 if ((alias
!= NULL
) && (!streq(alias
, fname
))) {
149 /* name does not match, skip it */
150 (void) OPENSSL_free(fname
);
155 (void) print_cert(err
, cert
, format
,
156 fname
, B_FALSE
, outfile
);
157 (void) OPENSSL_free(fname
);
164 (void) OPENSSL_free(fname
);
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
,
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
));
183 if ((alias
!= NULL
) && (!streq(alias
, fname
))) {
184 /* name does not match, skip it */
185 (void) OPENSSL_free(fname
);
190 (void) print_cert(err
, cert
, format
,
191 fname
, B_TRUE
, outfile
);
192 (void) OPENSSL_free(fname
);
199 (void) OPENSSL_free(fname
);
206 /* no certs printed */
208 pkgerr_add(err
, PKGERR_NOALIASMATCH
,
209 gettext(ERR_KEYSTORE_NOCERT
),
210 alias
, keystore
->path
);
212 pkgerr_add(err
, PKGERR_NOPUBKEY
,
213 gettext(ERR_KEYSTORE_NOPUBCERTS
),
215 pkgerr_add(err
, PKGERR_NOCACERT
,
216 gettext(ERR_KEYSTORE_NOCACERTS
),
224 * print_cert - prints a single certificate, to a file
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
235 * non-zero - Failure, errors added to err
237 int print_cert(PKG_ERR
*err
, X509
*x
,
238 keystore_encoding_format_t format
, char *alias
, boolean_t is_trusted
,
244 char vd_str
[ATTR_MAX
];
246 char *cn_str
, *icn_str
, *typ_str
;
252 /* need to localize the word "Fingerprint", hence these pointers */
253 char md5_label
[ATTR_MAX
];
254 char sha1_label
[ATTR_MAX
];
257 typ_str
= gettext(MSG_KEYSTORE_TRUSTED
);
259 typ_str
= gettext(MSG_KEYSTORE_UNTRUSTED
);
262 if ((cn_str
= get_subject_display_name(x
)) == NULL
) {
263 cn_str
= gettext(MSG_KEYSTORE_UNKNOWN
);
266 if ((icn_str
= get_issuer_display_name(x
)) == NULL
) {
267 icn_str
= gettext(MSG_KEYSTORE_UNKNOWN
);
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
);
279 if ((tmp
= get_fingerprint(x
, EVP_md5())) == NULL
) {
280 md5_fp
= gettext(MSG_KEYSTORE_UNKNOWN
);
283 * make a copy, otherwise the next call to get_fingerprint
284 * will overwrite this one
286 md5_fp
= xstrdup(tmp
);
289 if ((tmp
= get_fingerprint(x
, EVP_sha1())) == NULL
) {
290 sha1_fp
= gettext(MSG_KEYSTORE_UNKNOWN
);
292 sha1_fp
= xstrdup(tmp
);
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
));
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
));
306 case KEYSTORE_FORMAT_PEM
:
307 (void) PEM_write_X509(outfile
, x
);
309 case KEYSTORE_FORMAT_DER
:
310 (void) i2d_X509_fp(outfile
, x
);
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");
333 pkgerr_add(err
, PKGERR_INTERNAL
,
334 gettext(ERR_KEYSTORE_INTERNAL
),
353 * open_keystore - Initialize new keystore object for
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
365 * 0 - Success - result contains a pointer to the opened keystore
366 * non-zero - Failure, errors added to err
369 open_keystore(PKG_ERR
*err
, char *keystore_file
, char *app
,
370 keystore_passphrase_cb cb
, long flags
, keystore_handle_t
*result
)
373 keystore_t
*tmpstore
;
375 tmpstore
= new_keystore();
377 tmpstore
->dirty
= B_FALSE
;
378 tmpstore
->new = B_FALSE
;
379 tmpstore
->path
= xstrdup(keystore_file
);
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
),
389 if (!verify_keystore_integrity(err
, tmpstore
)) {
390 /* unable to repair keystore */
391 pkgerr_add(err
, PKGERR_CORRUPT
, gettext(ERR_KEYSTORE_REPAIR
),
397 if (!lock_keystore(err
, flags
, tmpstore
)) {
398 pkgerr_add(err
, PKGERR_LOCKED
, gettext(ERR_KEYSTORE_LOCKED
),
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
),
416 if (tmpstore
!= NULL
)
417 free_keystore(tmpstore
);
422 * new_keystore - Allocates and initializes a Keystore object
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
436 keystore_t
*tmpstore
;
438 if ((tmpstore
= (keystore_t
*)malloc(sizeof (keystore_t
))) == NULL
) {
441 tmpstore
->dirty
= B_FALSE
;
442 tmpstore
->new = B_FALSE
;
443 tmpstore
->path
= NULL
;
444 tmpstore
->passphrase
= NULL
;
446 tmpstore
->cacerts
= NULL
;
447 tmpstore
->capath
= NULL
;
448 tmpstore
->clcerts
= NULL
;
449 tmpstore
->clpath
= NULL
;
450 tmpstore
->pkeys
= NULL
;
451 tmpstore
->keypath
= NULL
;
457 * free_keystore - Deallocates a Keystore object
460 * keystore - The keystore to deallocate
466 free_keystore(keystore_t
*keystore
)
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
);
479 if (keystore
->pkeys
!= NULL
) {
480 sk_EVP_PKEY_pop_free(keystore
->pkeys
,
483 if (keystore
->clcerts
!= NULL
)
484 sk_X509_free(keystore
->clcerts
);
485 if (keystore
->cacerts
!= NULL
)
486 sk_X509_free(keystore
->cacerts
);
491 * close_keystore - Writes keystore to disk if needed, then
492 * unlocks and closes keystore.
495 * err - Error object to append errors to
496 * keystore - Keystore which should be closed
497 * passwd - Password used to encrypt keystore
500 * 0 - Success - keystore is committed to disk, and unlocked
501 * non-zero - Failure, errors added to err
504 close_keystore(PKG_ERR
*err
, keystore_handle_t keystore_h
,
505 keystore_passphrase_cb cb
)
508 keystore_t
*keystore
= keystore_h
;
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
),
521 if (!unlock_keystore(err
, keystore
)) {
522 pkgerr_add(err
, PKGERR_UNLOCK
, gettext(ERR_KEYSTORE_UNLOCK
),
528 free_keystore(keystore
);
534 * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
535 * certificate checked for validity dates and non-duplicity.
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
543 * 0 - Success - Certificate passes validity, and
544 * is merged into keystore
545 * non-zero - Failure, errors recorded in err
548 merge_ca_cert(PKG_ERR
*err
, X509
*cacert
, keystore_handle_t keystore_h
)
552 X509
*existing
= NULL
;
554 keystore_t
*keystore
= keystore_h
;
556 /* check validity dates */
557 if (check_cert(err
, cacert
) != 0) {
562 /* create the certificate's friendlyName */
563 fname
= get_subject_display_name(cacert
);
565 if (sunw_set_fname(fname
, NULL
, cacert
) != 0) {
566 pkgerr_add(err
, PKGERR_NOMEM
, gettext(ERR_MEM
));
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
));
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
),
586 ERR_print_errors_fp(stderr
);
589 /* could not search properly! */
591 if (existing
!= NULL
) {
592 /* whoops, found one already */
593 pkgerr_add(err
, PKGERR_DUPLICATE
,
594 gettext(ERR_KEYSTORE_DUPLICATECERT
), fname
);
600 (void) sk_X509_push(keystore
->cacerts
, cacert
);
601 keystore
->dirty
= B_TRUE
;
603 if (existing
!= NULL
)
609 * find_key_cert_pair - Searches a keystore for a matching
610 * public key certificate and private key, given an alias.
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
620 * 0 - Success - Matching cert/key pair placed in key and cert.
621 * non-zero - Failure, errors recorded in err
624 find_key_cert_pair(PKG_ERR
*err
, keystore_handle_t ks_h
, char *alias
,
625 EVP_PKEY
**key
, X509
**cert
)
627 X509
*tmpcert
= NULL
;
628 EVP_PKEY
*tmpkey
= NULL
;
631 keystore_t
*ks
= ks_h
;
633 if (key
== NULL
|| cert
== NULL
) {
634 pkgerr_add(err
, PKGERR_NOPUBKEY
,
635 gettext(ERR_KEYSTORE_NOPUBCERTS
), ks
->path
);
640 if (ks
->clcerts
== NULL
) {
641 /* no public certs */
642 pkgerr_add(err
, PKGERR_NOPUBKEY
,
643 gettext(ERR_KEYSTORE_NOCERTS
), ks
->path
);
647 if (ks
->pkeys
== NULL
) {
648 /* no private keys */
649 pkgerr_add(err
, PKGERR_NOPRIVKEY
,
650 gettext(ERR_KEYSTORE_NOKEYS
), ks
->path
);
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
)) {
662 * only one private key and public key cert, and they
673 /* Attempt to find the right pair given the alias */
674 items_found
= sunw_find_fname(alias
, ks
->pkeys
, ks
->clcerts
,
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
);
695 (void) X509_free(tmpcert
);
698 sunw_evp_pkey_free(tmpkey
);
704 * find_ca_certs - Searches a keystore for trusted certificates
707 * err - Error object to add errors to
708 * ks - Keystore to search
709 * cacerts - resulting set of trusted certs are placed here
712 * 0 - Success - trusted cert list returned in cacerts
713 * non-zero - Failure, errors recorded in err
716 find_ca_certs(PKG_ERR
*err
, keystore_handle_t ks_h
, STACK_OF(X509
) **cacerts
)
719 keystore_t
*ks
= ks_h
;
722 if (cacerts
== NULL
) {
723 pkgerr_add(err
, PKGERR_INTERNAL
,
724 gettext(ERR_KEYSTORE_INTERNAL
), __FILE__
, __LINE__
);
728 *cacerts
= ks
->cacerts
;
733 * find_cl_certs - Searches a keystore for user certificates
736 * err - Error object to add errors to
737 * ks - Keystore to search
738 * cacerts - resulting set of user certs are placed here
740 * No matching of any kind is performed.
742 * 0 - Success - trusted cert list returned in cacerts
743 * non-zero - Failure, errors recorded in err
747 find_cl_certs(PKG_ERR
*err
, keystore_handle_t ks_h
, STACK_OF(X509
) **clcerts
)
749 keystore_t
*ks
= ks_h
;
752 *clcerts
= ks
->clcerts
;
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.
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
770 * 0 - Success - Certificate passes validity, and
771 * is merged into keystore, along with key
772 * non-zero - Failure, errors recorded in err
775 merge_cert_and_key(PKG_ERR
*err
, X509
*cert
, EVP_PKEY
*key
, char *alias
,
776 keystore_handle_t keystore_h
)
778 X509
*existingcert
= NULL
;
779 EVP_PKEY
*existingkey
= NULL
;
781 keystore_t
*keystore
= keystore_h
;
783 /* check validity dates */
784 if (check_cert(err
, cert
) != 0) {
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
));
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
));
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
),
811 ERR_print_errors_fp(stderr
);
814 /* could not search properly! */
816 if (existingcert
!= NULL
) {
817 /* whoops, found one already */
818 pkgerr_add(err
, PKGERR_DUPLICATE
,
819 gettext(ERR_KEYSTORE_DUPLICATECERT
), alias
);
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
));
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
),
839 ERR_print_errors_fp(stderr
);
842 /* could not search properly! */
844 if (existingkey
!= NULL
) {
845 /* whoops, found one already */
846 pkgerr_add(err
, PKGERR_DUPLICATE
,
847 gettext(ERR_KEYSTORE_DUPLICATEKEY
), alias
);
853 (void) sk_X509_push(keystore
->clcerts
, cert
);
854 (void) sk_EVP_PKEY_push(keystore
->pkeys
, key
);
855 keystore
->dirty
= B_TRUE
;
857 if (existingcert
!= NULL
)
858 (void) X509_free(existingcert
);
859 if (existingkey
!= NULL
)
860 (void) sunw_evp_pkey_free(existingkey
);
865 * delete_cert_and_keys - Deletes one or more certificates
866 * and matching private keys from a keystore.
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
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
882 delete_cert_and_keys(PKG_ERR
*err
, keystore_handle_t ks_h
, char *alias
)
885 EVP_PKEY
*existingkey
;
888 boolean_t found
= B_FALSE
;
889 keystore_t
*ks
= ks_h
;
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 */
900 sk_X509_delete(ks
->clcerts
, i
);
901 X509_free(existingcert
);
905 (void) OPENSSL_free(fname
);
909 if (sk_X509_num(ks
->clcerts
) <= 0) {
910 /* we deleted all the client certs */
911 sk_X509_free(ks
->clcerts
);
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 */
925 sk_EVP_PKEY_delete(ks
->pkeys
, i
);
926 sunw_evp_pkey_free(existingkey
);
930 (void) OPENSSL_free(fname
);
934 if (sk_EVP_PKEY_num(ks
->pkeys
) <= 0) {
935 /* we deleted all the private keys */
936 sk_EVP_PKEY_free(ks
->pkeys
);
941 /* finally, remove any trust anchors that match */
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 */
951 sk_X509_delete(ks
->cacerts
, i
);
952 X509_free(existingcert
);
956 (void) OPENSSL_free(fname
);
960 if (sk_X509_num(ks
->cacerts
) <= 0) {
961 /* we deleted all the CA certs */
962 sk_X509_free(ks
->cacerts
);
971 /* no certs or keys deleted */
972 pkgerr_add(err
, PKGERR_NOALIASMATCH
,
973 gettext(ERR_KEYSTORE_NOCERTKEY
),
980 * check_cert - Checks certificate validity. This routine
981 * checks that the current time falls within the period
982 * of validity for the cert.
985 * err - Error object to add errors to
986 * cert - The certificate to check
989 * 0 - Success - Certificate checks out
990 * non-zero - Failure, errors and reasons recorded in err
993 check_cert(PKG_ERR
*err
, X509
*cert
)
995 char currtimestr
[ATTR_MAX
];
998 /* get current time */
999 if ((currtime
= time(NULL
)) == (time_t)-1) {
1000 pkgerr_add(err
, PKGERR_TIME
, gettext(ERR_CURR_TIME
));
1004 (void) strlcpy(currtimestr
, ctime(&currtime
), ATTR_MAX
);
1006 /* trim whitespace from end of time string */
1007 for (r
= (currtimestr
+ strlen(currtimestr
) - 1); isspace(*r
); r
--) {
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 */
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
));
1021 case CHKERR_TIME_IS_BEFORE
:
1022 /* Current time is before 'not before' */
1023 case CHKERR_TIME_HAS_EXPIRED
:
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.
1033 pkgerr_add(err
, PKGERR_INTERNAL
,
1034 gettext(ERR_KEYSTORE_INTERNAL
),
1035 __FILE__
, __LINE__
);
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.
1050 * err - Error object to add errors to
1051 * cert - The certificate to check
1052 * key - the key to check
1054 * 0 - Success - Certificate checks out
1055 * non-zero - Failure, errors and reasons recorded in err
1058 check_cert_and_key(PKG_ERR
*err
, X509
*cert
, EVP_PKEY
*key
)
1061 /* check validity dates */
1062 if (check_cert(err
, cert
) != 0) {
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
));
1077 /* ------------------ private functions ---------------------- */
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
1086 * err - Error object to add errors to
1087 * keystore_file - Base directory or filename of keystore
1088 * app - Application making request
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
1096 verify_keystore_integrity(PKG_ERR
*err
, keystore_t
*keystore
)
1098 if (keystore
->capath
!= NULL
) {
1099 if (!restore_keystore_file(err
, keystore
->capath
)) {
1103 if (keystore
->clpath
!= NULL
) {
1104 if (!restore_keystore_file(err
, keystore
->clpath
)) {
1108 if (keystore
->keypath
!= NULL
) {
1109 if (!restore_keystore_file(err
, keystore
->keypath
)) {
1117 * restore_keystore_file - restores a keystore file to
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.
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.
1135 * err - Error object to add errors to
1136 * keystore_file - keystore file path to restore.
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
1145 restore_keystore_file(PKG_ERR
*err
, char *keystore_file
)
1147 char newpath
[MAXPATHLEN
];
1148 char backuppath
[MAXPATHLEN
];
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
);
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
);
1167 if ((newfd
= open(newpath
, O_RDWR
|O_NONBLOCK
, 0)) != -1) {
1168 if (fstat(newfd
, &buf
) != -1) {
1169 if (S_ISREG(buf
.st_mode
)) {
1171 * restore the file, waiting on it
1172 * to be free for locking, or for
1175 if (!wait_restore(newfd
, keystore_file
,
1176 newpath
, backuppath
)) {
1177 pkgerr_add(err
, PKGERR_WRITE
,
1179 newpath
, strerror(errno
));
1180 (void) close(newfd
);
1186 /* "new" file is not a regular file */
1187 pkgerr_add(err
, PKGERR_WRITE
,
1188 gettext(ERR_NOT_REG
), newpath
);
1189 (void) close(newfd
);
1193 /* couldn't stat "new" file */
1194 pkgerr_add(err
, PKGERR_WRITE
,
1195 gettext(ERR_WRITE
), newpath
,
1197 (void) close(newfd
);
1201 /* "new" file doesn't exist */
1207 wait_restore(int newfd
, char *keystore_file
,
1208 char *origpath
, char *backuppath
)
1214 (void) alarm(LOCK_TIMEOUT
);
1215 if (file_lock(newfd
, F_WRLCK
, 1) == -1) {
1216 /* could not lock file */
1222 if (fstat(newfd
, &buf
) != -1) {
1223 if (S_ISREG(buf
.st_mode
)) {
1225 * The new file still
1231 newstream
= fdopen(newfd
, "r");
1233 d2i_PKCS12_fp(newstream
,
1245 (void) rename(keystore_file
, backuppath
);
1246 (void) rename(origpath
, keystore_file
);
1249 /* The file is not complete. Remove it */
1250 (void) remove(origpath
);
1252 /* remove backup file */
1253 (void) remove(backuppath
);
1254 (void) fclose(newstream
);
1255 (void) close(newfd
);
1259 * new file exists, but is not a
1262 (void) close(newfd
);
1267 * could not stat file. Unless
1268 * the reason was that the file
1269 * is now gone, this is an error
1271 if (errno
!= ENOENT
) {
1272 (void) close(newfd
);
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
1282 (void) close(newfd
);
1288 * resolve_paths - figure out if we are dealing with a single-file
1289 * or multi-file keystore
1291 * The flags tell resolve_paths how to behave:
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.
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.
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
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
1319 resolve_paths(PKG_ERR
*err
, char *keystore_file
, char *app
,
1320 long flags
, keystore_t
*keystore
)
1322 char storepath
[PATH_MAX
];
1324 boolean_t multi
= B_FALSE
;
1328 * figure out whether we are dealing with a single-file keystore
1329 * or a multi-file keystore
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
),
1340 if (((fd1
= open(storepath
, O_NONBLOCK
|O_RDONLY
)) == -1) ||
1341 (fstat(fd1
, &buf
) == -1) ||
1342 !S_ISDIR(buf
.st_mode
)) {
1344 * app-specific does not exist
1345 * fallback to app-generic, if flags say we can
1347 if ((flags
& KEYSTORE_PATH_MASK
) ==
1348 KEYSTORE_PATH_SOFT
) {
1350 if (((fd2
= open(keystore_file
,
1351 O_NONBLOCK
|O_RDONLY
)) != -1) &&
1352 (fstat(fd2
, &buf
) != -1)) {
1353 if (S_ISDIR(buf
.st_mode
)) {
1362 } else if (S_ISREG(buf
.st_mode
)) {
1364 * app-generic file exists, so
1365 * use it as a single file ks
1378 if (((fd1
= open(keystore_file
,
1379 O_NONBLOCK
|O_RDONLY
)) != -1) &&
1380 (fstat(fd1
, &buf
) != -1) &&
1381 S_ISDIR(buf
.st_mode
)) {
1383 * app-generic dir exists, so use
1384 * it as a multi-file keystore
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
);
1404 /* app-generic keystore */
1406 /* single-file app-generic keystore */
1407 keystore
->capath
= xstrdup(keystore_file
);
1408 keystore
->keypath
= NULL
;
1409 keystore
->clpath
= NULL
;
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
);
1428 * lock_keystore - Locks a keystore for shared (read-only)
1429 * or exclusive (read-write) access.
1431 * The flags tell lock_keystore how to behave:
1433 * KEYSTORE_ACCESS_READONLY
1434 * opens keystore read-only. Attempts to modify results in an error
1436 * KEYSTORE_ACCESS_READWRITE
1437 * opens keystore read-write
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.
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.
1453 * err - Error object to add errors to
1454 * flags - Control flags (see above description)
1455 * keystore - object which is being locked
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
1463 lock_keystore(PKG_ERR
*err
, long flags
, keystore_t
*keystore
)
1465 boolean_t ret
= B_TRUE
;
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
) {
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.
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
),
1491 pkgerr_add(err
, PKGERR_READ
,
1492 gettext(ERR_KEYSTORE_OPEN
),
1493 keystore
->capath
, strerror(errno
));
1498 if (fstat(keystore
->cafd
, &buf
) != -1) {
1499 if (S_ISREG(buf
.st_mode
)) {
1500 if (file_lock(keystore
->cafd
, F_RDLCK
,
1502 pkgerr_add(err
, PKGERR_LOCKED
,
1503 gettext(ERR_KEYSTORE_LOCKED_READ
),
1509 /* ca file not a regular file! */
1510 pkgerr_add(err
, PKGERR_READ
,
1511 gettext(ERR_NOT_REG
),
1517 pkgerr_add(err
, PKGERR_READ
,
1518 gettext(ERR_KEYSTORE_OPEN
),
1519 keystore
->capath
, strerror(errno
));
1524 case KEYSTORE_ACCESS_READWRITE
:
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
),
1541 pkgerr_add(err
, PKGERR_READ
,
1542 gettext(ERR_KEYSTORE_OPEN
),
1543 keystore
->capath
, strerror(errno
));
1548 if (fstat(keystore
->cafd
, &buf
) != -1) {
1549 if (S_ISREG(buf
.st_mode
)) {
1550 if (file_lock(keystore
->cafd
, F_WRLCK
,
1552 pkgerr_add(err
, PKGERR_LOCKED
,
1553 gettext(ERR_KEYSTORE_LOCKED
),
1559 /* ca file not a regular file! */
1560 pkgerr_add(err
, PKGERR_READ
,
1561 gettext(ERR_NOT_REG
),
1567 pkgerr_add(err
, PKGERR_READ
,
1568 gettext(ERR_KEYSTORE_OPEN
),
1569 keystore
->capath
, strerror(errno
));
1576 pkgerr_add(err
, PKGERR_INTERNAL
,
1577 gettext(ERR_KEYSTORE_INTERNAL
),
1578 __FILE__
, __LINE__
);
1585 if (keystore
->cafd
> 0) {
1586 (void) file_unlock(keystore
->cafd
);
1587 (void) close(keystore
->cafd
);
1588 keystore
->cafd
= -1;
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
;
1606 * unlock_keystore - Unocks a keystore
1609 * err - Error object to add errors to
1610 * keystore - keystore object to unlock
1612 * 0 - Success - Keystore files are unlocked, files are closed,
1613 * non-zero - Failure, errors and reasons recorded in err
1617 unlock_keystore(PKG_ERR
*err
, keystore_t
*keystore
)
1621 * Release lock on the CA file.
1622 * Delete file if it is empty
1624 if (file_empty(keystore
->capath
)) {
1625 (void) remove(keystore
->capath
);
1628 (void) file_unlock(keystore
->cafd
);
1629 (void) close(keystore
->cafd
);
1634 * read_keystore - Reads keystore files of disk, parses
1635 * into internal structures.
1638 * err - Error object to add errors to
1639 * keystore - keystore object to read into
1640 * cb - callback to get password, if required
1642 * 0 - Success - Keystore files are read, and placed
1643 * into keystore structure.
1644 * non-zero - Failure, errors and reasons recorded in err
1647 read_keystore(PKG_ERR
*err
, keystore_t
*keystore
, keystore_passphrase_cb cb
)
1649 boolean_t ret
= B_TRUE
;
1652 boolean_t have_passwd
= B_FALSE
;
1653 boolean_t cl_empty
= B_TRUE
;
1654 boolean_t key_empty
= B_TRUE
;
1656 ca_empty
= file_empty(keystore
->capath
);
1658 if (keystore
->clpath
!= NULL
)
1659 cl_empty
= file_empty(keystore
->clpath
);
1660 if (keystore
->keypath
!= NULL
)
1661 key_empty
= file_empty(keystore
->keypath
);
1663 if (ca_empty
&& cl_empty
&& key_empty
) {
1664 keystore
->new = B_TRUE
;
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
);
1677 /* Get password, using callback if necessary */
1679 if (!get_keystore_passwd(err
, p12
, cb
, keystore
)) {
1683 have_passwd
= B_TRUE
;
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
);
1701 * truststore is empty, so we don't have any trusted
1704 keystore
->cacerts
= NULL
;
1708 * if there is no cl file or key file, use the cl's and key's found
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
);
1721 * files are in separate files. read keys out of the keystore
1722 * certs out of the certstore, if they are not empty
1725 if ((p12
= read_keystore_file(err
,
1726 keystore
->clpath
)) == NULL
) {
1727 pkgerr_add(err
, PKGERR_CORRUPT
,
1728 gettext(ERR_KEYSTORE_CORRUPT
),
1734 /* Get password, using callback if necessary */
1736 if (!get_keystore_passwd(err
, p12
, cb
,
1741 have_passwd
= B_TRUE
;
1744 if (check_password(p12
,
1745 keystore
->passphrase
) == B_FALSE
) {
1747 * password in client cert file
1749 * the one in the other files!
1751 pkgerr_add(err
, PKGERR_BADPASS
,
1752 gettext(ERR_MISMATCHPASS
),
1754 keystore
->capath
, keystore
->path
);
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
),
1772 keystore
->clcerts
= NULL
;
1776 if ((p12
= read_keystore_file(err
,
1777 keystore
->keypath
)) == NULL
) {
1778 pkgerr_add(err
, PKGERR_CORRUPT
,
1779 gettext(ERR_KEYSTORE_CORRUPT
),
1785 /* Get password, using callback if necessary */
1787 if (!get_keystore_passwd(err
, p12
, cb
,
1792 have_passwd
= B_TRUE
;
1795 if (check_password(p12
,
1796 keystore
->passphrase
) == B_FALSE
) {
1797 pkgerr_add(err
, PKGERR_BADPASS
,
1798 gettext(ERR_MISMATCHPASS
),
1800 keystore
->capath
, keystore
->path
);
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
),
1818 keystore
->pkeys
= NULL
;
1829 * get_keystore_password - retrieves pasword used to
1830 * decrypt PKCS12 structure.
1833 * err - Error object to add errors to
1834 * p12 - PKCS12 structure which returned password should
1836 * cb - callback to collect password.
1837 * keystore - The keystore in which the PKCS12 structure
1838 * will eventually populate.
1841 * keystore password is set in keystore->passphrase.
1842 * B_FALSE - failure, errors logged
1845 get_keystore_passwd(PKG_ERR
*err
, PKCS12
*p12
, keystore_passphrase_cb cb
,
1846 keystore_t
*keystore
)
1849 char passbuf
[KEYSTORE_PASS_MAX
+ 1];
1850 keystore_passphrase_data data
;
1852 /* see if no password is the right password */
1853 if (check_password(p12
, "") == B_TRUE
) {
1855 } else if (check_password(p12
, NULL
) == B_TRUE
) {
1858 /* oops, it's encrypted. get password */
1860 if (cb(passbuf
, KEYSTORE_PASS_MAX
, 0,
1862 /* could not get password */
1866 if (check_password(p12
, passbuf
) == B_FALSE
) {
1867 /* wrong password */
1868 pkgerr_add(err
, PKGERR_BADPASS
,
1869 gettext(ERR_BADPASS
));
1874 * make copy of password buffer, since it
1875 * goes away upon return
1877 passwd
= xstrdup(passbuf
);
1879 keystore
->passphrase
= passwd
;
1884 * write_keystore - Writes keystore files to disk
1887 * err - Error object to add errors to
1888 * keystore - keystore object to write from
1889 * passwd - password used to encrypt keystore
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
1896 write_keystore(PKG_ERR
*err
, keystore_t
*keystore
,
1897 keystore_passphrase_cb cb
)
1900 boolean_t ret
= B_TRUE
;
1901 keystore_passphrase_data data
;
1902 char passbuf
[KEYSTORE_PASS_MAX
+ 1];
1904 if (keystore
->capath
!= NULL
&& keystore
->clpath
== NULL
&&
1905 keystore
->keypath
== NULL
) {
1908 * keystore is a file.
1909 * just write out a single file
1911 if ((keystore
->pkeys
== NULL
) &&
1912 (keystore
->clcerts
== NULL
) &&
1913 (keystore
->cacerts
== NULL
)) {
1914 if (!clear_keystore_file(err
, keystore
->capath
)) {
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
1922 pkgerr_add(err
, PKGERR_WRITE
,
1923 gettext(ERR_KEYSTORE_WRITE
),
1930 * if the keystore is being created for the first time,
1931 * prompt for a passphrase for encryption
1933 if (keystore
->new) {
1935 if (cb(passbuf
, KEYSTORE_PASS_MAX
,
1942 * use the one used when the keystore
1945 (void) strlcpy(passbuf
, keystore
->passphrase
,
1949 p12
= sunw_PKCS12_create(passbuf
, keystore
->pkeys
,
1950 keystore
->clcerts
, keystore
->cacerts
);
1953 pkgerr_add(err
, PKGERR_WRITE
,
1954 gettext(ERR_KEYSTORE_FORM
),
1960 if (!write_keystore_file(err
, keystore
->capath
, p12
)) {
1961 pkgerr_add(err
, PKGERR_WRITE
,
1962 gettext(ERR_KEYSTORE_WRITE
),
1970 /* files are seprate. Do one at a time */
1973 * if the keystore is being created for the first time,
1974 * prompt for a passphrase for encryption
1976 if (keystore
->new && ((keystore
->pkeys
!= NULL
) ||
1977 (keystore
->clcerts
!= NULL
) ||
1978 (keystore
->cacerts
!= NULL
))) {
1980 if (cb(passbuf
, KEYSTORE_PASS_MAX
,
1986 /* use the one used when the keystore was read */
1987 (void) strlcpy(passbuf
, keystore
->passphrase
,
1991 /* do private keys first */
1992 if (keystore
->pkeys
!= NULL
) {
1993 p12
= sunw_PKCS12_create(passbuf
, keystore
->pkeys
,
1997 pkgerr_add(err
, PKGERR_WRITE
,
1998 gettext(ERR_KEYSTORE_FORM
),
2004 if (!write_keystore_file(err
, keystore
->keypath
,
2006 pkgerr_add(err
, PKGERR_WRITE
,
2007 gettext(ERR_KEYSTORE_WRITE
),
2015 if ((remove(keystore
->keypath
) != 0) &&
2016 (errno
!= ENOENT
)) {
2017 pkgerr_add(err
, PKGERR_WRITE
,
2018 gettext(ERR_KEYSTORE_REMOVE
),
2025 /* do user certs next */
2026 if (keystore
->clcerts
!= NULL
) {
2027 p12
= sunw_PKCS12_create(passbuf
, NULL
,
2028 keystore
->clcerts
, NULL
);
2031 pkgerr_add(err
, PKGERR_WRITE
,
2032 gettext(ERR_KEYSTORE_FORM
),
2038 if (!write_keystore_file(err
, keystore
->clpath
, p12
)) {
2039 pkgerr_add(err
, PKGERR_WRITE
,
2040 gettext(ERR_KEYSTORE_WRITE
),
2048 if ((remove(keystore
->clpath
) != 0) &&
2049 (errno
!= ENOENT
)) {
2050 pkgerr_add(err
, PKGERR_WRITE
,
2051 gettext(ERR_KEYSTORE_REMOVE
),
2059 /* finally do CA cert file */
2060 if (keystore
->cacerts
!= NULL
) {
2061 p12
= sunw_PKCS12_create(passbuf
, NULL
,
2062 NULL
, keystore
->cacerts
);
2065 pkgerr_add(err
, PKGERR_WRITE
,
2066 gettext(ERR_KEYSTORE_FORM
),
2072 if (!write_keystore_file(err
, keystore
->capath
, p12
)) {
2073 pkgerr_add(err
, PKGERR_WRITE
,
2074 gettext(ERR_KEYSTORE_WRITE
),
2084 * nothing to write out, so truncate the file
2085 * (it will be deleted during close_keystore)
2087 if (!clear_keystore_file(err
, keystore
->capath
)) {
2088 pkgerr_add(err
, PKGERR_WRITE
,
2089 gettext(ERR_KEYSTORE_WRITE
),
2105 * clear_keystore_file - Clears (zeros out) a keystore file.
2108 * err - Error object to add errors to
2109 * dest - Path of keystore file to zero out.
2111 * 0 - Success - Keystore file is truncated to zero length
2112 * non-zero - Failure, errors and reasons recorded in err
2115 clear_keystore_file(PKG_ERR
*err
, char *dest
)
2120 fd
= open(dest
, O_RDWR
|O_NONBLOCK
);
2122 /* can't open for writing */
2123 pkgerr_add(err
, PKGERR_WRITE
, gettext(MSG_OPEN
),
2128 if ((fstat(fd
, &buf
) == -1) || !S_ISREG(buf
.st_mode
)) {
2129 /* not a regular file */
2131 pkgerr_add(err
, PKGERR_WRITE
, gettext(ERR_NOT_REG
),
2136 if (ftruncate(fd
, 0) == -1) {
2138 pkgerr_add(err
, PKGERR_WRITE
, gettext(ERR_WRITE
),
2139 dest
, strerror(errno
));
2148 * write_keystore_file - Writes keystore file to disk.
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.
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.
2166 * err - Error object to add errors to
2167 * dest - Destination filename
2168 * contents - Contents to write to the file
2170 * 0 - Success - Keystore contents are written out to
2172 * non-zero - Failure, errors and reasons recorded in err
2175 write_keystore_file(PKG_ERR
*err
, char *dest
, PKCS12
*contents
)
2177 FILE *newfile
= NULL
;
2178 boolean_t ret
= B_TRUE
;
2179 char newpath
[MAXPATHLEN
];
2180 char backuppath
[MAXPATHLEN
];
2184 (void) snprintf(newpath
, MAXPATHLEN
, "%s.new", dest
);
2185 (void) snprintf(backuppath
, MAXPATHLEN
, "%s.bak", dest
);
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
));
2195 if (fstat(fd
, &buf
) == -1) {
2196 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_KEYSTORE_OPEN
),
2197 newpath
, strerror(errno
));
2202 if (!S_ISREG(buf
.st_mode
)) {
2203 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_NOT_REG
),
2209 if ((newfile
= fdopen(fd
, "w")) == NULL
) {
2210 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_KEYSTORE_OPEN
),
2211 newpath
, strerror(errno
));
2216 if (i2d_PKCS12_fp(newfile
, contents
) == 0) {
2217 pkgerr_add(err
, PKGERR_WRITE
, gettext(ERR_KEYSTORE_WRITE
),
2223 /* flush, then close */
2224 (void) fflush(newfile
);
2225 (void) fclose(newfile
);
2228 /* now back up the original file */
2229 (void) rename(dest
, backuppath
);
2231 /* put new one in its place */
2232 (void) rename(newpath
, dest
);
2235 (void) remove(backuppath
);
2238 if (newfile
!= NULL
)
2239 (void) fclose(newfile
);
2247 * read_keystore_file - Reads single keystore file
2248 * off disk in PKCS12 format.
2251 * err - Error object to add errors to
2252 * file - File path to read
2254 * PKCS12 contents of file, or NULL if an error occurred.
2255 * errors recorded in 'err'.
2258 *read_keystore_file(PKG_ERR
*err
, char *file
)
2265 if ((fd
= open(file
, O_RDONLY
|O_NONBLOCK
)) == -1) {
2266 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_KEYSTORE_OPEN
),
2267 file
, strerror(errno
));
2271 if (fstat(fd
, &buf
) == -1) {
2272 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_KEYSTORE_OPEN
),
2273 file
, strerror(errno
));
2277 if (!S_ISREG(buf
.st_mode
)) {
2278 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_NOT_REG
),
2283 if ((newfile
= fdopen(fd
, "r")) == NULL
) {
2284 pkgerr_add(err
, PKGERR_READ
, gettext(ERR_KEYSTORE_OPEN
),
2285 file
, strerror(errno
));
2289 if ((p12
= d2i_PKCS12_fp(newfile
, NULL
)) == NULL
) {
2290 pkgerr_add(err
, PKGERR_CORRUPT
,
2291 gettext(ERR_KEYSTORE_CORRUPT
), file
);
2296 if (newfile
!= NULL
)
2297 (void) fclose(newfile
);
2306 * Locks the specified file.
2309 file_lock(int fd
, int type
, int wait
)
2315 lock
.l_whence
= SEEK_SET
;
2319 if (file_lock_test(fd
, type
)) {
2321 * The caller would have to wait to get the
2322 * lock on this file.
2328 return (fcntl(fd
, F_SETLKW
, &lock
));
2332 * Returns FALSE if the file is not locked; TRUE
2336 file_lock_test(int fd
, int type
)
2342 lock
.l_whence
= SEEK_SET
;
2345 if (fcntl(fd
, F_GETLK
, &lock
) != -1) {
2346 if (lock
.l_type
!= F_UNLCK
) {
2348 * The caller would have to wait to get the
2349 * lock on this file.
2356 * The file is not locked.
2362 * Unlocks the specified file.
2369 lock
.l_type
= F_UNLCK
;
2371 lock
.l_whence
= SEEK_SET
;
2374 return (fcntl(fd
, F_SETLK
, &lock
));
2378 * Determines if file has a length of 0 or not
2381 file_empty(char *path
)
2385 /* file is empty if size = 0 or it doesn't exist */
2386 if (lstat(path
, &buf
) == 0) {
2387 if (buf
.st_size
== 0) {
2391 if (errno
== ENOENT
) {
2400 * Name: get_time_string
2401 * Description: Generates a human-readable string from an ASN1_TIME
2403 * Arguments: intime - The time to convert
2405 * Returns : A pointer to a static string representing the passed-in time.
2408 *get_time_string(ASN1_TIME
*intime
)
2411 static char time
[ATTR_MAX
];
2415 if (intime
== NULL
) {
2418 if ((mem
= BIO_new(BIO_s_mem())) == NULL
) {
2422 if (ASN1_TIME_print(mem
, intime
) == 0) {
2423 (void) BIO_free(mem
);
2427 if (BIO_gets(mem
, time
, ATTR_MAX
) <= 0) {
2428 (void) BIO_free(mem
);
2432 (void) BIO_free(mem
);
2434 /* trim the end of the string */
2435 for (p
= time
+ strlen(time
) - 1; isspace(*p
); p
--) {
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.
2447 * pass - password to check
2450 * B_TRUE - Password is OK.
2451 * B_FALSE - Password not valid.
2454 check_password(PKCS12
*p12
, char *pass
)
2456 boolean_t ret
= B_TRUE
;
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...
2466 if (pass
== NULL
|| *pass
== '\0') {
2467 if (PKCS12_verify_mac(p12
, NULL
, 0) == 0 &&
2468 PKCS12_verify_mac(p12
, "", 0) == 0)
2470 } else if (PKCS12_verify_mac(p12
, pass
, -1) == 0) {