15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland * CDDL HEADER START
35c51f124SMoriah Waterland *
45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland *
85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland * See the License for the specific language governing permissions
115c51f124SMoriah Waterland * and limitations under the License.
125c51f124SMoriah Waterland *
135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland *
195c51f124SMoriah Waterland * CDDL HEADER END
205c51f124SMoriah Waterland */
215c51f124SMoriah Waterland
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
245c51f124SMoriah Waterland * Use is subject to license terms.
255c51f124SMoriah Waterland */
265c51f124SMoriah Waterland
275c51f124SMoriah Waterland /*
285c51f124SMoriah Waterland * Module: keystore.c
295c51f124SMoriah Waterland * Description: This module contains the structure definitions for processing
305c51f124SMoriah Waterland * package keystore files.
315c51f124SMoriah Waterland */
325c51f124SMoriah Waterland
335c51f124SMoriah Waterland #include <errno.h>
345c51f124SMoriah Waterland #include <fcntl.h>
355c51f124SMoriah Waterland #include <unistd.h>
365c51f124SMoriah Waterland #include <strings.h>
375c51f124SMoriah Waterland #include <libintl.h>
385c51f124SMoriah Waterland #include <time.h>
395c51f124SMoriah Waterland #include <ctype.h>
405c51f124SMoriah Waterland #include <sys/types.h>
415c51f124SMoriah Waterland #include <sys/stat.h>
425c51f124SMoriah Waterland #include <openssl/evp.h>
435c51f124SMoriah Waterland #include <openssl/x509.h>
445c51f124SMoriah Waterland #include <openssl/pkcs12.h>
455c51f124SMoriah Waterland #include <openssl/asn1.h>
465c51f124SMoriah Waterland #include <openssl/pem.h>
475c51f124SMoriah Waterland #include <openssl/err.h>
485c51f124SMoriah Waterland #include <openssl/safestack.h>
495c51f124SMoriah Waterland #include <openssl/stack.h>
505c51f124SMoriah Waterland #include "p12lib.h"
515c51f124SMoriah Waterland #include "pkgerr.h"
525c51f124SMoriah Waterland #include "keystore.h"
535c51f124SMoriah Waterland #include "pkglib.h"
545c51f124SMoriah Waterland #include "pkglibmsgs.h"
555c51f124SMoriah Waterland
565c51f124SMoriah Waterland typedef struct keystore_t {
575c51f124SMoriah Waterland boolean_t dirty;
585c51f124SMoriah Waterland boolean_t new;
595c51f124SMoriah Waterland char *path;
605c51f124SMoriah Waterland char *passphrase;
615c51f124SMoriah Waterland /* truststore handles */
625c51f124SMoriah Waterland int cafd;
635c51f124SMoriah Waterland STACK_OF(X509) *cacerts;
645c51f124SMoriah Waterland char *capath;
655c51f124SMoriah Waterland
665c51f124SMoriah Waterland /* user certificate handles */
675c51f124SMoriah Waterland STACK_OF(X509) *clcerts;
685c51f124SMoriah Waterland char *clpath;
695c51f124SMoriah Waterland
705c51f124SMoriah Waterland /* private key handles */
715c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *pkeys;
725c51f124SMoriah Waterland char *keypath;
735c51f124SMoriah Waterland } keystore_t;
745c51f124SMoriah Waterland
755c51f124SMoriah Waterland /* local routines */
765c51f124SMoriah Waterland static keystore_t *new_keystore(void);
775c51f124SMoriah Waterland static void free_keystore(keystore_t *);
785c51f124SMoriah Waterland static boolean_t verify_keystore_integrity(PKG_ERR *, keystore_t *);
795c51f124SMoriah Waterland static boolean_t check_password(PKCS12 *, char *);
805c51f124SMoriah Waterland static boolean_t resolve_paths(PKG_ERR *, char *, char *,
815c51f124SMoriah Waterland long, keystore_t *);
825c51f124SMoriah Waterland static boolean_t lock_keystore(PKG_ERR *, long, keystore_t *);
835c51f124SMoriah Waterland
845c51f124SMoriah Waterland static boolean_t unlock_keystore(PKG_ERR *, keystore_t *);
855c51f124SMoriah Waterland static boolean_t read_keystore(PKG_ERR *, keystore_t *,
865c51f124SMoriah Waterland keystore_passphrase_cb);
875c51f124SMoriah Waterland static boolean_t write_keystore(PKG_ERR *, keystore_t *,
885c51f124SMoriah Waterland keystore_passphrase_cb);
895c51f124SMoriah Waterland static boolean_t write_keystore_file(PKG_ERR *, char *, PKCS12 *);
905c51f124SMoriah Waterland static boolean_t clear_keystore_file(PKG_ERR *, char *);
915c51f124SMoriah Waterland static PKCS12 *read_keystore_file(PKG_ERR *, char *);
925c51f124SMoriah Waterland static char *get_time_string(ASN1_TIME *);
935c51f124SMoriah Waterland
945c51f124SMoriah Waterland /* locking routines */
955c51f124SMoriah Waterland static boolean_t restore_keystore_file(PKG_ERR *, char *);
965c51f124SMoriah Waterland static int file_lock(int, int, int);
975c51f124SMoriah Waterland static int file_unlock(int);
985c51f124SMoriah Waterland static boolean_t file_lock_test(int, int);
995c51f124SMoriah Waterland static boolean_t file_empty(char *);
1005c51f124SMoriah Waterland static boolean_t get_keystore_passwd(PKG_ERR *err, PKCS12 *p12,
1015c51f124SMoriah Waterland keystore_passphrase_cb cb, keystore_t *keystore);
1025c51f124SMoriah Waterland static boolean_t wait_restore(int, char *, char *, char *);
1035c51f124SMoriah Waterland
1045c51f124SMoriah Waterland #define KEYSTORE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
1055c51f124SMoriah Waterland
1065c51f124SMoriah Waterland /* wait on other keystore access for 1 minute before giving up */
1075c51f124SMoriah Waterland #define LOCK_TIMEOUT 60
1085c51f124SMoriah Waterland
1095c51f124SMoriah Waterland /*
1105c51f124SMoriah Waterland * print_certs - prints certificates out of a keystore, to a file.
1115c51f124SMoriah Waterland *
1125c51f124SMoriah Waterland * Arguments:
1135c51f124SMoriah Waterland * err - Error object to append errors to
1145c51f124SMoriah Waterland * keystore - Keystore on which to operate
1155c51f124SMoriah Waterland * alias - Name of certificate to print, NULL means print all
1165c51f124SMoriah Waterland * format - Format in which to print certificates
1175c51f124SMoriah Waterland * outfile - Where to print certificates
1185c51f124SMoriah Waterland *
1195c51f124SMoriah Waterland * Returns:
1205c51f124SMoriah Waterland * 0 - Success
1215c51f124SMoriah Waterland * non-zero - Failure, errors added to err
1225c51f124SMoriah Waterland */
1235c51f124SMoriah Waterland int
print_certs(PKG_ERR * err,keystore_handle_t keystore_h,char * alias,keystore_encoding_format_t format,FILE * outfile)1245c51f124SMoriah Waterland print_certs(PKG_ERR *err, keystore_handle_t keystore_h, char *alias,
1255c51f124SMoriah Waterland keystore_encoding_format_t format, FILE *outfile)
1265c51f124SMoriah Waterland {
1275c51f124SMoriah Waterland int i;
1285c51f124SMoriah Waterland X509 *cert;
1295c51f124SMoriah Waterland char *fname = NULL;
1305c51f124SMoriah Waterland boolean_t found = B_FALSE;
1315c51f124SMoriah Waterland keystore_t *keystore = keystore_h;
1325c51f124SMoriah Waterland
1335c51f124SMoriah Waterland if (keystore->clcerts != NULL) {
1345c51f124SMoriah Waterland /* print out each client cert */
1355c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(keystore->clcerts); i++) {
1365c51f124SMoriah Waterland cert = sk_X509_value(keystore->clcerts, i);
1375c51f124SMoriah Waterland (void) sunw_get_cert_fname(GETDO_COPY, cert,
1385c51f124SMoriah Waterland &fname);
1395c51f124SMoriah Waterland
1405c51f124SMoriah Waterland if (fname == NULL) {
1415c51f124SMoriah Waterland /* no name recorded, keystore is corrupt */
1425c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
1435c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NO_ALIAS),
1445c51f124SMoriah Waterland get_subject_display_name(cert));
1455c51f124SMoriah Waterland return (1);
1465c51f124SMoriah Waterland }
1475c51f124SMoriah Waterland
1485c51f124SMoriah Waterland if ((alias != NULL) && (!streq(alias, fname))) {
1495c51f124SMoriah Waterland /* name does not match, skip it */
1505c51f124SMoriah Waterland (void) OPENSSL_free(fname);
1515c51f124SMoriah Waterland fname = NULL;
1525c51f124SMoriah Waterland continue;
1535c51f124SMoriah Waterland } else {
1545c51f124SMoriah Waterland found = B_TRUE;
1555c51f124SMoriah Waterland (void) print_cert(err, cert, format,
1565c51f124SMoriah Waterland fname, B_FALSE, outfile);
1575c51f124SMoriah Waterland (void) OPENSSL_free(fname);
1585c51f124SMoriah Waterland fname = NULL;
1595c51f124SMoriah Waterland }
1605c51f124SMoriah Waterland }
1615c51f124SMoriah Waterland }
1625c51f124SMoriah Waterland
1635c51f124SMoriah Waterland if (fname != NULL) {
1645c51f124SMoriah Waterland (void) OPENSSL_free(fname);
1655c51f124SMoriah Waterland fname = NULL;
1665c51f124SMoriah Waterland }
1675c51f124SMoriah Waterland
1685c51f124SMoriah Waterland if (keystore->cacerts != NULL) {
1695c51f124SMoriah Waterland /* print out each trusted cert */
1705c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(keystore->cacerts); i++) {
1715c51f124SMoriah Waterland cert = sk_X509_value(keystore->cacerts, i);
1725c51f124SMoriah Waterland (void) sunw_get_cert_fname(GETDO_COPY,
1735c51f124SMoriah Waterland cert, &fname);
1745c51f124SMoriah Waterland
1755c51f124SMoriah Waterland if (fname == NULL) {
1765c51f124SMoriah Waterland /* no name recorded, keystore is corrupt */
1775c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
1785c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NO_ALIAS),
1795c51f124SMoriah Waterland get_subject_display_name(cert));
1805c51f124SMoriah Waterland return (1);
1815c51f124SMoriah Waterland }
1825c51f124SMoriah Waterland
1835c51f124SMoriah Waterland if ((alias != NULL) && (!streq(alias, fname))) {
1845c51f124SMoriah Waterland /* name does not match, skip it */
1855c51f124SMoriah Waterland (void) OPENSSL_free(fname);
1865c51f124SMoriah Waterland fname = NULL;
1875c51f124SMoriah Waterland continue;
1885c51f124SMoriah Waterland } else {
1895c51f124SMoriah Waterland found = B_TRUE;
1905c51f124SMoriah Waterland (void) print_cert(err, cert, format,
1915c51f124SMoriah Waterland fname, B_TRUE, outfile);
1925c51f124SMoriah Waterland (void) OPENSSL_free(fname);
1935c51f124SMoriah Waterland fname = NULL;
1945c51f124SMoriah Waterland }
1955c51f124SMoriah Waterland }
1965c51f124SMoriah Waterland }
1975c51f124SMoriah Waterland
1985c51f124SMoriah Waterland if (fname != NULL) {
1995c51f124SMoriah Waterland (void) OPENSSL_free(fname);
2005c51f124SMoriah Waterland fname = NULL;
2015c51f124SMoriah Waterland }
2025c51f124SMoriah Waterland
2035c51f124SMoriah Waterland if (found) {
2045c51f124SMoriah Waterland return (0);
2055c51f124SMoriah Waterland } else {
2065c51f124SMoriah Waterland /* no certs printed */
2075c51f124SMoriah Waterland if (alias != NULL) {
2085c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOALIASMATCH,
2095c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOCERT),
2105c51f124SMoriah Waterland alias, keystore->path);
2115c51f124SMoriah Waterland } else {
2125c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOPUBKEY,
2135c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOPUBCERTS),
2145c51f124SMoriah Waterland keystore->path);
2155c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOCACERT,
2165c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOCACERTS),
2175c51f124SMoriah Waterland keystore->path);
2185c51f124SMoriah Waterland }
2195c51f124SMoriah Waterland return (1);
2205c51f124SMoriah Waterland }
2215c51f124SMoriah Waterland }
2225c51f124SMoriah Waterland
2235c51f124SMoriah Waterland /*
2245c51f124SMoriah Waterland * print_cert - prints a single certificate, to a file
2255c51f124SMoriah Waterland *
2265c51f124SMoriah Waterland * Arguments:
2275c51f124SMoriah Waterland * err - Error object to append errors to
2285c51f124SMoriah Waterland * x - The certificate to print
2295c51f124SMoriah Waterland * alias - Name of certificate to print
2305c51f124SMoriah Waterland * format - Format in which to print certificate
2315c51f124SMoriah Waterland * outfile - Where to print certificate
2325c51f124SMoriah Waterland *
2335c51f124SMoriah Waterland * Returns:
2345c51f124SMoriah Waterland * 0 - Success
2355c51f124SMoriah Waterland * non-zero - Failure, errors added to err
2365c51f124SMoriah Waterland */
print_cert(PKG_ERR * err,X509 * x,keystore_encoding_format_t format,char * alias,boolean_t is_trusted,FILE * outfile)2375c51f124SMoriah Waterland int print_cert(PKG_ERR *err, X509 *x,
2385c51f124SMoriah Waterland keystore_encoding_format_t format, char *alias, boolean_t is_trusted,
2395c51f124SMoriah Waterland FILE *outfile)
2405c51f124SMoriah Waterland {
2415c51f124SMoriah Waterland
2425c51f124SMoriah Waterland char *vdb_str;
2435c51f124SMoriah Waterland char *vda_str;
2445c51f124SMoriah Waterland char vd_str[ATTR_MAX];
2455c51f124SMoriah Waterland int ret = 0;
2465c51f124SMoriah Waterland char *cn_str, *icn_str, *typ_str;
2475c51f124SMoriah Waterland char *tmp;
2485c51f124SMoriah Waterland char *md5_fp;
2495c51f124SMoriah Waterland char *sha1_fp;
2505c51f124SMoriah Waterland int len;
2515c51f124SMoriah Waterland
2525c51f124SMoriah Waterland /* need to localize the word "Fingerprint", hence these pointers */
2535c51f124SMoriah Waterland char md5_label[ATTR_MAX];
2545c51f124SMoriah Waterland char sha1_label[ATTR_MAX];
2555c51f124SMoriah Waterland
2565c51f124SMoriah Waterland if (is_trusted) {
2575c51f124SMoriah Waterland typ_str = gettext(MSG_KEYSTORE_TRUSTED);
2585c51f124SMoriah Waterland } else {
2595c51f124SMoriah Waterland typ_str = gettext(MSG_KEYSTORE_UNTRUSTED);
2605c51f124SMoriah Waterland }
2615c51f124SMoriah Waterland
2625c51f124SMoriah Waterland if ((cn_str = get_subject_display_name(x)) == NULL) {
2635c51f124SMoriah Waterland cn_str = gettext(MSG_KEYSTORE_UNKNOWN);
2645c51f124SMoriah Waterland }
2655c51f124SMoriah Waterland
2665c51f124SMoriah Waterland if ((icn_str = get_issuer_display_name(x)) == NULL) {
2675c51f124SMoriah Waterland icn_str = gettext(MSG_KEYSTORE_UNKNOWN);
2685c51f124SMoriah Waterland }
2695c51f124SMoriah Waterland
2705c51f124SMoriah Waterland vdb_str = xstrdup(get_time_string(X509_get_notBefore(x)));
2715c51f124SMoriah Waterland vda_str = xstrdup(get_time_string(X509_get_notAfter(x)));
2725c51f124SMoriah Waterland if (((len = snprintf(vd_str, ATTR_MAX, "<%s> - <%s>",
2735c51f124SMoriah Waterland vdb_str, vda_str)) < 0) || (len >= ATTR_MAX)) {
2745c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), vdb_str);
2755c51f124SMoriah Waterland ret = 1;
2765c51f124SMoriah Waterland goto cleanup;
2775c51f124SMoriah Waterland }
2785c51f124SMoriah Waterland
2795c51f124SMoriah Waterland if ((tmp = get_fingerprint(x, EVP_md5())) == NULL) {
2805c51f124SMoriah Waterland md5_fp = gettext(MSG_KEYSTORE_UNKNOWN);
2815c51f124SMoriah Waterland } else {
2825c51f124SMoriah Waterland /*
2835c51f124SMoriah Waterland * make a copy, otherwise the next call to get_fingerprint
2845c51f124SMoriah Waterland * will overwrite this one
2855c51f124SMoriah Waterland */
2865c51f124SMoriah Waterland md5_fp = xstrdup(tmp);
2875c51f124SMoriah Waterland }
2885c51f124SMoriah Waterland
2895c51f124SMoriah Waterland if ((tmp = get_fingerprint(x, EVP_sha1())) == NULL) {
2905c51f124SMoriah Waterland sha1_fp = gettext(MSG_KEYSTORE_UNKNOWN);
2915c51f124SMoriah Waterland } else {
2925c51f124SMoriah Waterland sha1_fp = xstrdup(tmp);
2935c51f124SMoriah Waterland }
2945c51f124SMoriah Waterland
2955c51f124SMoriah Waterland (void) snprintf(md5_label, ATTR_MAX, "%s %s",
2965c51f124SMoriah Waterland OBJ_nid2sn(EVP_MD_type(EVP_md5())),
2975c51f124SMoriah Waterland /* i18n: 14 characters max */
2985c51f124SMoriah Waterland gettext(MSG_KEYSTORE_FP));
2995c51f124SMoriah Waterland
3005c51f124SMoriah Waterland (void) snprintf(sha1_label, ATTR_MAX, "%s %s",
3015c51f124SMoriah Waterland OBJ_nid2sn(EVP_MD_type(EVP_sha1())),
3025c51f124SMoriah Waterland /* i18n: 14 characters max */
3035c51f124SMoriah Waterland gettext(MSG_KEYSTORE_FP));
3045c51f124SMoriah Waterland
3055c51f124SMoriah Waterland switch (format) {
3065c51f124SMoriah Waterland case KEYSTORE_FORMAT_PEM:
3075c51f124SMoriah Waterland (void) PEM_write_X509(outfile, x);
3085c51f124SMoriah Waterland break;
3095c51f124SMoriah Waterland case KEYSTORE_FORMAT_DER:
3105c51f124SMoriah Waterland (void) i2d_X509_fp(outfile, x);
3115c51f124SMoriah Waterland break;
3125c51f124SMoriah Waterland case KEYSTORE_FORMAT_TEXT:
3135c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n",
3145c51f124SMoriah Waterland /* i18n: 18 characters max */
3155c51f124SMoriah Waterland gettext(MSG_KEYSTORE_AL), alias);
3165c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n",
3175c51f124SMoriah Waterland /* i18n: 18 characters max */
3185c51f124SMoriah Waterland gettext(MSG_KEYSTORE_CN), cn_str);
3195c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n",
3205c51f124SMoriah Waterland /* i18n: 18 characters max */
3215c51f124SMoriah Waterland gettext(MSG_KEYSTORE_TY), typ_str);
3225c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n",
3235c51f124SMoriah Waterland /* i18n: 18 characters max */
3245c51f124SMoriah Waterland gettext(MSG_KEYSTORE_IN), icn_str);
3255c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n",
3265c51f124SMoriah Waterland /* i18n: 18 characters max */
3275c51f124SMoriah Waterland gettext(MSG_KEYSTORE_VD), vd_str);
3285c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n", md5_label, md5_fp);
3295c51f124SMoriah Waterland (void) fprintf(outfile, "%18s: %s\n", sha1_label, sha1_fp);
3305c51f124SMoriah Waterland (void) fprintf(outfile, "\n");
3315c51f124SMoriah Waterland break;
3325c51f124SMoriah Waterland default:
3335c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
3345c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
3355c51f124SMoriah Waterland __FILE__, __LINE__);
3365c51f124SMoriah Waterland ret = 1;
3375c51f124SMoriah Waterland goto cleanup;
3385c51f124SMoriah Waterland }
3395c51f124SMoriah Waterland
3405c51f124SMoriah Waterland cleanup:
3415c51f124SMoriah Waterland if (md5_fp != NULL)
3425c51f124SMoriah Waterland free(md5_fp);
3435c51f124SMoriah Waterland if (sha1_fp != NULL)
3445c51f124SMoriah Waterland free(sha1_fp);
3455c51f124SMoriah Waterland if (vda_str != NULL)
3465c51f124SMoriah Waterland free(vda_str);
3475c51f124SMoriah Waterland if (vdb_str != NULL)
3485c51f124SMoriah Waterland free(vdb_str);
3495c51f124SMoriah Waterland return (ret);
3505c51f124SMoriah Waterland }
3515c51f124SMoriah Waterland
3525c51f124SMoriah Waterland /*
3535c51f124SMoriah Waterland * open_keystore - Initialize new keystore object for
3545c51f124SMoriah Waterland * impending access.
3555c51f124SMoriah Waterland *
3565c51f124SMoriah Waterland * Arguments:
3575c51f124SMoriah Waterland * err - Error object to append errors to
3585c51f124SMoriah Waterland * keystore_file - Base filename or directory of keystore
3595c51f124SMoriah Waterland * app - Application making request
3605c51f124SMoriah Waterland * passwd - Password used to decrypt keystore
3615c51f124SMoriah Waterland * flags - Control flags used to control access mode and behavior
3625c51f124SMoriah Waterland * result - Resulting keystore object stored here on success
3635c51f124SMoriah Waterland *
3645c51f124SMoriah Waterland * Returns:
3655c51f124SMoriah Waterland * 0 - Success - result contains a pointer to the opened keystore
3665c51f124SMoriah Waterland * non-zero - Failure, errors added to err
3675c51f124SMoriah Waterland */
3685c51f124SMoriah Waterland int
open_keystore(PKG_ERR * err,char * keystore_file,char * app,keystore_passphrase_cb cb,long flags,keystore_handle_t * result)3695c51f124SMoriah Waterland open_keystore(PKG_ERR *err, char *keystore_file, char *app,
3705c51f124SMoriah Waterland keystore_passphrase_cb cb, long flags, keystore_handle_t *result)
3715c51f124SMoriah Waterland {
3725c51f124SMoriah Waterland int ret = 0;
3735c51f124SMoriah Waterland keystore_t *tmpstore;
3745c51f124SMoriah Waterland
3755c51f124SMoriah Waterland tmpstore = new_keystore();
3765c51f124SMoriah Waterland
3775c51f124SMoriah Waterland tmpstore->dirty = B_FALSE;
3785c51f124SMoriah Waterland tmpstore->new = B_FALSE;
3795c51f124SMoriah Waterland tmpstore->path = xstrdup(keystore_file);
3805c51f124SMoriah Waterland
3815c51f124SMoriah Waterland if (!resolve_paths(err, keystore_file, app, flags, tmpstore)) {
3825c51f124SMoriah Waterland /* unable to determine keystore paths */
3835c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
3845c51f124SMoriah Waterland keystore_file);
3855c51f124SMoriah Waterland ret = 1;
3865c51f124SMoriah Waterland goto cleanup;
3875c51f124SMoriah Waterland }
3885c51f124SMoriah Waterland
3895c51f124SMoriah Waterland if (!verify_keystore_integrity(err, tmpstore)) {
3905c51f124SMoriah Waterland /* unable to repair keystore */
3915c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
3925c51f124SMoriah Waterland keystore_file);
3935c51f124SMoriah Waterland ret = 1;
3945c51f124SMoriah Waterland goto cleanup;
3955c51f124SMoriah Waterland }
3965c51f124SMoriah Waterland
3975c51f124SMoriah Waterland if (!lock_keystore(err, flags, tmpstore)) {
3985c51f124SMoriah Waterland pkgerr_add(err, PKGERR_LOCKED, gettext(ERR_KEYSTORE_LOCKED),
3995c51f124SMoriah Waterland keystore_file);
4005c51f124SMoriah Waterland ret = 1;
4015c51f124SMoriah Waterland goto cleanup;
4025c51f124SMoriah Waterland }
4035c51f124SMoriah Waterland
4045c51f124SMoriah Waterland /* now that we have locked the keystore, go ahead and read it */
4055c51f124SMoriah Waterland if (!read_keystore(err, tmpstore, cb)) {
4065c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_PARSE),
4075c51f124SMoriah Waterland keystore_file);
4085c51f124SMoriah Waterland ret = 1;
4095c51f124SMoriah Waterland goto cleanup;
4105c51f124SMoriah Waterland }
4115c51f124SMoriah Waterland
4125c51f124SMoriah Waterland *result = tmpstore;
4135c51f124SMoriah Waterland tmpstore = NULL;
4145c51f124SMoriah Waterland
4155c51f124SMoriah Waterland cleanup:
4165c51f124SMoriah Waterland if (tmpstore != NULL)
4175c51f124SMoriah Waterland free_keystore(tmpstore);
4185c51f124SMoriah Waterland return (ret);
4195c51f124SMoriah Waterland }
4205c51f124SMoriah Waterland
4215c51f124SMoriah Waterland /*
4225c51f124SMoriah Waterland * new_keystore - Allocates and initializes a Keystore object
4235c51f124SMoriah Waterland *
4245c51f124SMoriah Waterland * Arguments:
4255c51f124SMoriah Waterland * NONE
4265c51f124SMoriah Waterland *
4275c51f124SMoriah Waterland * Returns:
4285c51f124SMoriah Waterland * NULL - out of memory
4295c51f124SMoriah Waterland * otherwise, returns a pointer to the newly allocated object,
4305c51f124SMoriah Waterland * which should be freed with free_keystore() when no longer
4315c51f124SMoriah Waterland * needed.
4325c51f124SMoriah Waterland */
4335c51f124SMoriah Waterland static keystore_t
new_keystore(void)4345c51f124SMoriah Waterland *new_keystore(void)
4355c51f124SMoriah Waterland {
4365c51f124SMoriah Waterland keystore_t *tmpstore;
4375c51f124SMoriah Waterland
4385c51f124SMoriah Waterland if ((tmpstore = (keystore_t *)malloc(sizeof (keystore_t))) == NULL) {
4395c51f124SMoriah Waterland return (NULL);
4405c51f124SMoriah Waterland }
4415c51f124SMoriah Waterland tmpstore->dirty = B_FALSE;
4425c51f124SMoriah Waterland tmpstore->new = B_FALSE;
4435c51f124SMoriah Waterland tmpstore->path = NULL;
4445c51f124SMoriah Waterland tmpstore->passphrase = NULL;
4455c51f124SMoriah Waterland tmpstore->cafd = -1;
4465c51f124SMoriah Waterland tmpstore->cacerts = NULL;
4475c51f124SMoriah Waterland tmpstore->capath = NULL;
4485c51f124SMoriah Waterland tmpstore->clcerts = NULL;
4495c51f124SMoriah Waterland tmpstore->clpath = NULL;
4505c51f124SMoriah Waterland tmpstore->pkeys = NULL;
4515c51f124SMoriah Waterland tmpstore->keypath = NULL;
4525c51f124SMoriah Waterland
4535c51f124SMoriah Waterland return (tmpstore);
4545c51f124SMoriah Waterland }
4555c51f124SMoriah Waterland
4565c51f124SMoriah Waterland /*
4575c51f124SMoriah Waterland * free_keystore - Deallocates a Keystore object
4585c51f124SMoriah Waterland *
4595c51f124SMoriah Waterland * Arguments:
4605c51f124SMoriah Waterland * keystore - The keystore to deallocate
4615c51f124SMoriah Waterland *
4625c51f124SMoriah Waterland * Returns:
4635c51f124SMoriah Waterland * NONE
4645c51f124SMoriah Waterland */
4655c51f124SMoriah Waterland static void
free_keystore(keystore_t * keystore)4665c51f124SMoriah Waterland free_keystore(keystore_t *keystore)
4675c51f124SMoriah Waterland {
4685c51f124SMoriah Waterland if (keystore->path != NULL)
4695c51f124SMoriah Waterland free(keystore->path);
4705c51f124SMoriah Waterland if (keystore->capath != NULL)
4715c51f124SMoriah Waterland free(keystore->capath);
4725c51f124SMoriah Waterland if (keystore->passphrase != NULL)
4735c51f124SMoriah Waterland free(keystore->passphrase);
4745c51f124SMoriah Waterland if (keystore->clpath != NULL)
4755c51f124SMoriah Waterland free(keystore->clpath);
4765c51f124SMoriah Waterland if (keystore->keypath != NULL)
4775c51f124SMoriah Waterland free(keystore->keypath);
4785c51f124SMoriah Waterland
4795c51f124SMoriah Waterland if (keystore->pkeys != NULL) {
4805c51f124SMoriah Waterland sk_EVP_PKEY_pop_free(keystore->pkeys,
4815c51f124SMoriah Waterland sunw_evp_pkey_free);
4825c51f124SMoriah Waterland }
4835c51f124SMoriah Waterland if (keystore->clcerts != NULL)
4845c51f124SMoriah Waterland sk_X509_free(keystore->clcerts);
4855c51f124SMoriah Waterland if (keystore->cacerts != NULL)
4865c51f124SMoriah Waterland sk_X509_free(keystore->cacerts);
4875c51f124SMoriah Waterland free(keystore);
4885c51f124SMoriah Waterland }
4895c51f124SMoriah Waterland
4905c51f124SMoriah Waterland /*
4915c51f124SMoriah Waterland * close_keystore - Writes keystore to disk if needed, then
4925c51f124SMoriah Waterland * unlocks and closes keystore.
4935c51f124SMoriah Waterland *
4945c51f124SMoriah Waterland * Arguments:
4955c51f124SMoriah Waterland * err - Error object to append errors to
4965c51f124SMoriah Waterland * keystore - Keystore which should be closed
4975c51f124SMoriah Waterland * passwd - Password used to encrypt keystore
4985c51f124SMoriah Waterland *
4995c51f124SMoriah Waterland * Returns:
5005c51f124SMoriah Waterland * 0 - Success - keystore is committed to disk, and unlocked
5015c51f124SMoriah Waterland * non-zero - Failure, errors added to err
5025c51f124SMoriah Waterland */
5035c51f124SMoriah Waterland int
close_keystore(PKG_ERR * err,keystore_handle_t keystore_h,keystore_passphrase_cb cb)5045c51f124SMoriah Waterland close_keystore(PKG_ERR *err, keystore_handle_t keystore_h,
5055c51f124SMoriah Waterland keystore_passphrase_cb cb)
5065c51f124SMoriah Waterland {
5075c51f124SMoriah Waterland int ret = 0;
5085c51f124SMoriah Waterland keystore_t *keystore = keystore_h;
5095c51f124SMoriah Waterland
5105c51f124SMoriah Waterland if (keystore->dirty) {
5115c51f124SMoriah Waterland /* write out the keystore first */
5125c51f124SMoriah Waterland if (!write_keystore(err, keystore, cb)) {
5135c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
5145c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
5155c51f124SMoriah Waterland keystore->path);
5165c51f124SMoriah Waterland ret = 1;
5175c51f124SMoriah Waterland goto cleanup;
5185c51f124SMoriah Waterland }
5195c51f124SMoriah Waterland }
5205c51f124SMoriah Waterland
5215c51f124SMoriah Waterland if (!unlock_keystore(err, keystore)) {
5225c51f124SMoriah Waterland pkgerr_add(err, PKGERR_UNLOCK, gettext(ERR_KEYSTORE_UNLOCK),
5235c51f124SMoriah Waterland keystore->path);
5245c51f124SMoriah Waterland ret = 1;
5255c51f124SMoriah Waterland goto cleanup;
5265c51f124SMoriah Waterland }
5275c51f124SMoriah Waterland
5285c51f124SMoriah Waterland free_keystore(keystore);
5295c51f124SMoriah Waterland cleanup:
5305c51f124SMoriah Waterland return (ret);
5315c51f124SMoriah Waterland }
5325c51f124SMoriah Waterland
5335c51f124SMoriah Waterland /*
5345c51f124SMoriah Waterland * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
5355c51f124SMoriah Waterland * certificate checked for validity dates and non-duplicity.
5365c51f124SMoriah Waterland *
5375c51f124SMoriah Waterland * Arguments:
5385c51f124SMoriah Waterland * err - Error object to add errors to
5395c51f124SMoriah Waterland * cacert - Certificate which to merge into keystore
5405c51f124SMoriah Waterland * keystore - The keystore into which the certificate is merged
5415c51f124SMoriah Waterland *
5425c51f124SMoriah Waterland * Returns:
5435c51f124SMoriah Waterland * 0 - Success - Certificate passes validity, and
5445c51f124SMoriah Waterland * is merged into keystore
5455c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
5465c51f124SMoriah Waterland */
5475c51f124SMoriah Waterland int
merge_ca_cert(PKG_ERR * err,X509 * cacert,keystore_handle_t keystore_h)5485c51f124SMoriah Waterland merge_ca_cert(PKG_ERR *err, X509 *cacert, keystore_handle_t keystore_h)
5495c51f124SMoriah Waterland {
5505c51f124SMoriah Waterland
5515c51f124SMoriah Waterland int ret = 0;
5525c51f124SMoriah Waterland X509 *existing = NULL;
5535c51f124SMoriah Waterland char *fname;
5545c51f124SMoriah Waterland keystore_t *keystore = keystore_h;
5555c51f124SMoriah Waterland
5565c51f124SMoriah Waterland /* check validity dates */
5575c51f124SMoriah Waterland if (check_cert(err, cacert) != 0) {
5585c51f124SMoriah Waterland ret = 1;
5595c51f124SMoriah Waterland goto cleanup;
5605c51f124SMoriah Waterland }
5615c51f124SMoriah Waterland
5625c51f124SMoriah Waterland /* create the certificate's friendlyName */
5635c51f124SMoriah Waterland fname = get_subject_display_name(cacert);
5645c51f124SMoriah Waterland
5655c51f124SMoriah Waterland if (sunw_set_fname(fname, NULL, cacert) != 0) {
5665c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
5675c51f124SMoriah Waterland ret = 1;
5685c51f124SMoriah Waterland goto cleanup;
5695c51f124SMoriah Waterland }
5705c51f124SMoriah Waterland
5715c51f124SMoriah Waterland /* merge certificate into the keystore */
5725c51f124SMoriah Waterland if (keystore->cacerts == NULL) {
5735c51f124SMoriah Waterland /* no existing truststore, so make a new one */
5745c51f124SMoriah Waterland if ((keystore->cacerts = sk_X509_new_null()) == NULL) {
5755c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
5765c51f124SMoriah Waterland ret = 1;
5775c51f124SMoriah Waterland goto cleanup;
5785c51f124SMoriah Waterland }
5795c51f124SMoriah Waterland } else {
5805c51f124SMoriah Waterland /* existing truststore, make sure there's no duplicate */
5815c51f124SMoriah Waterland if (sunw_find_fname(fname, NULL, keystore->cacerts,
5825c51f124SMoriah Waterland NULL, &existing) < 0) {
5835c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
5845c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
5855c51f124SMoriah Waterland __FILE__, __LINE__);
5865c51f124SMoriah Waterland ERR_print_errors_fp(stderr);
5875c51f124SMoriah Waterland ret = 1;
5885c51f124SMoriah Waterland goto cleanup;
5895c51f124SMoriah Waterland /* could not search properly! */
5905c51f124SMoriah Waterland }
5915c51f124SMoriah Waterland if (existing != NULL) {
5925c51f124SMoriah Waterland /* whoops, found one already */
5935c51f124SMoriah Waterland pkgerr_add(err, PKGERR_DUPLICATE,
5945c51f124SMoriah Waterland gettext(ERR_KEYSTORE_DUPLICATECERT), fname);
5955c51f124SMoriah Waterland ret = 1;
5965c51f124SMoriah Waterland goto cleanup;
5975c51f124SMoriah Waterland }
5985c51f124SMoriah Waterland }
5995c51f124SMoriah Waterland
6005c51f124SMoriah Waterland (void) sk_X509_push(keystore->cacerts, cacert);
6015c51f124SMoriah Waterland keystore->dirty = B_TRUE;
6025c51f124SMoriah Waterland cleanup:
6035c51f124SMoriah Waterland if (existing != NULL)
6045c51f124SMoriah Waterland X509_free(existing);
6055c51f124SMoriah Waterland return (ret);
6065c51f124SMoriah Waterland }
6075c51f124SMoriah Waterland
6085c51f124SMoriah Waterland /*
6095c51f124SMoriah Waterland * find_key_cert_pair - Searches a keystore for a matching
6105c51f124SMoriah Waterland * public key certificate and private key, given an alias.
6115c51f124SMoriah Waterland *
6125c51f124SMoriah Waterland * Arguments:
6135c51f124SMoriah Waterland * err - Error object to add errors to
6145c51f124SMoriah Waterland * ks - Keystore to search
6155c51f124SMoriah Waterland * alias - Name to used to match certificate's alias
6165c51f124SMoriah Waterland * key - Resulting key is placed here
6175c51f124SMoriah Waterland * cert - Resulting cert is placed here
6185c51f124SMoriah Waterland *
6195c51f124SMoriah Waterland * Returns:
6205c51f124SMoriah Waterland * 0 - Success - Matching cert/key pair placed in key and cert.
6215c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
6225c51f124SMoriah Waterland */
6235c51f124SMoriah Waterland int
find_key_cert_pair(PKG_ERR * err,keystore_handle_t ks_h,char * alias,EVP_PKEY ** key,X509 ** cert)6245c51f124SMoriah Waterland find_key_cert_pair(PKG_ERR *err, keystore_handle_t ks_h, char *alias,
6255c51f124SMoriah Waterland EVP_PKEY **key, X509 **cert)
6265c51f124SMoriah Waterland {
6275c51f124SMoriah Waterland X509 *tmpcert = NULL;
6285c51f124SMoriah Waterland EVP_PKEY *tmpkey = NULL;
6295c51f124SMoriah Waterland int ret = 0;
6305c51f124SMoriah Waterland int items_found;
6315c51f124SMoriah Waterland keystore_t *ks = ks_h;
6325c51f124SMoriah Waterland
6335c51f124SMoriah Waterland if (key == NULL || cert == NULL) {
6345c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOPUBKEY,
6355c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOPUBCERTS), ks->path);
6365c51f124SMoriah Waterland ret = 1;
6375c51f124SMoriah Waterland goto cleanup;
6385c51f124SMoriah Waterland }
6395c51f124SMoriah Waterland
6405c51f124SMoriah Waterland if (ks->clcerts == NULL) {
6415c51f124SMoriah Waterland /* no public certs */
6425c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOPUBKEY,
6435c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOCERTS), ks->path);
6445c51f124SMoriah Waterland ret = 1;
6455c51f124SMoriah Waterland goto cleanup;
6465c51f124SMoriah Waterland }
6475c51f124SMoriah Waterland if (ks->pkeys == NULL) {
6485c51f124SMoriah Waterland /* no private keys */
6495c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOPRIVKEY,
6505c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOKEYS), ks->path);
6515c51f124SMoriah Waterland ret = 1;
6525c51f124SMoriah Waterland goto cleanup;
6535c51f124SMoriah Waterland }
6545c51f124SMoriah Waterland
6555c51f124SMoriah Waterland /* try the easy case first */
6565c51f124SMoriah Waterland if ((sk_EVP_PKEY_num(ks->pkeys) == 1) &&
6575c51f124SMoriah Waterland (sk_X509_num(ks->clcerts) == 1)) {
6585c51f124SMoriah Waterland tmpkey = sk_EVP_PKEY_value(ks->pkeys, 0);
6595c51f124SMoriah Waterland tmpcert = sk_X509_value(ks->clcerts, 0);
6605c51f124SMoriah Waterland if (sunw_check_keys(tmpcert, tmpkey)) {
6615c51f124SMoriah Waterland /*
6625c51f124SMoriah Waterland * only one private key and public key cert, and they
6635c51f124SMoriah Waterland * match, so use them
6645c51f124SMoriah Waterland */
6655c51f124SMoriah Waterland *key = tmpkey;
6665c51f124SMoriah Waterland tmpkey = NULL;
6675c51f124SMoriah Waterland *cert = tmpcert;
6685c51f124SMoriah Waterland tmpcert = NULL;
6695c51f124SMoriah Waterland goto cleanup;
6705c51f124SMoriah Waterland }
6715c51f124SMoriah Waterland }
6725c51f124SMoriah Waterland
6735c51f124SMoriah Waterland /* Attempt to find the right pair given the alias */
6745c51f124SMoriah Waterland items_found = sunw_find_fname(alias, ks->pkeys, ks->clcerts,
6755c51f124SMoriah Waterland &tmpkey, &tmpcert);
6765c51f124SMoriah Waterland
6775c51f124SMoriah Waterland if ((items_found < 0) ||
6785c51f124SMoriah Waterland (items_found & (FOUND_PKEY | FOUND_CERT)) == 0) {
6795c51f124SMoriah Waterland /* no key/cert pair found. bail. */
6805c51f124SMoriah Waterland pkgerr_add(err, PKGERR_BADALIAS,
6815c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOMATCH), alias);
6825c51f124SMoriah Waterland ret = 1;
6835c51f124SMoriah Waterland goto cleanup;
6845c51f124SMoriah Waterland }
6855c51f124SMoriah Waterland
6865c51f124SMoriah Waterland /* success */
6875c51f124SMoriah Waterland *key = tmpkey;
6885c51f124SMoriah Waterland tmpkey = NULL;
6895c51f124SMoriah Waterland *cert = tmpcert;
6905c51f124SMoriah Waterland tmpcert = NULL;
6915c51f124SMoriah Waterland
6925c51f124SMoriah Waterland cleanup:
6935c51f124SMoriah Waterland
6945c51f124SMoriah Waterland if (tmpcert != NULL)
6955c51f124SMoriah Waterland (void) X509_free(tmpcert);
6965c51f124SMoriah Waterland
6975c51f124SMoriah Waterland if (tmpkey != NULL)
6985c51f124SMoriah Waterland sunw_evp_pkey_free(tmpkey);
6995c51f124SMoriah Waterland
7005c51f124SMoriah Waterland return (ret);
7015c51f124SMoriah Waterland }
7025c51f124SMoriah Waterland
7035c51f124SMoriah Waterland /*
7045c51f124SMoriah Waterland * find_ca_certs - Searches a keystore for trusted certificates
7055c51f124SMoriah Waterland *
7065c51f124SMoriah Waterland * Arguments:
7075c51f124SMoriah Waterland * err - Error object to add errors to
7085c51f124SMoriah Waterland * ks - Keystore to search
7095c51f124SMoriah Waterland * cacerts - resulting set of trusted certs are placed here
7105c51f124SMoriah Waterland *
7115c51f124SMoriah Waterland * Returns:
7125c51f124SMoriah Waterland * 0 - Success - trusted cert list returned in cacerts
7135c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
7145c51f124SMoriah Waterland */
7155c51f124SMoriah Waterland int
find_ca_certs(PKG_ERR * err,keystore_handle_t ks_h,STACK_OF (X509)** cacerts)7165c51f124SMoriah Waterland find_ca_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **cacerts)
7175c51f124SMoriah Waterland {
7185c51f124SMoriah Waterland
7195c51f124SMoriah Waterland keystore_t *ks = ks_h;
7205c51f124SMoriah Waterland
7215c51f124SMoriah Waterland /* easy */
7225c51f124SMoriah Waterland if (cacerts == NULL) {
7235c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
7245c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL), __FILE__, __LINE__);
7255c51f124SMoriah Waterland return (1);
7265c51f124SMoriah Waterland }
7275c51f124SMoriah Waterland
7285c51f124SMoriah Waterland *cacerts = ks->cacerts;
7295c51f124SMoriah Waterland return (0);
7305c51f124SMoriah Waterland }
7315c51f124SMoriah Waterland
7325c51f124SMoriah Waterland /*
7335c51f124SMoriah Waterland * find_cl_certs - Searches a keystore for user certificates
7345c51f124SMoriah Waterland *
7355c51f124SMoriah Waterland * Arguments:
7365c51f124SMoriah Waterland * err - Error object to add errors to
7375c51f124SMoriah Waterland * ks - Keystore to search
7385c51f124SMoriah Waterland * cacerts - resulting set of user certs are placed here
7395c51f124SMoriah Waterland *
7405c51f124SMoriah Waterland * No matching of any kind is performed.
7415c51f124SMoriah Waterland * Returns:
7425c51f124SMoriah Waterland * 0 - Success - trusted cert list returned in cacerts
7435c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
7445c51f124SMoriah Waterland */
7455c51f124SMoriah Waterland /* ARGSUSED */
7465c51f124SMoriah Waterland int
find_cl_certs(PKG_ERR * err,keystore_handle_t ks_h,STACK_OF (X509)** clcerts)7475c51f124SMoriah Waterland find_cl_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **clcerts)
7485c51f124SMoriah Waterland {
7495c51f124SMoriah Waterland keystore_t *ks = ks_h;
7505c51f124SMoriah Waterland
7515c51f124SMoriah Waterland /* easy */
7525c51f124SMoriah Waterland *clcerts = ks->clcerts;
7535c51f124SMoriah Waterland return (0);
7545c51f124SMoriah Waterland }
7555c51f124SMoriah Waterland
7565c51f124SMoriah Waterland
7575c51f124SMoriah Waterland /*
7585c51f124SMoriah Waterland * merge_cert_and_key - Adds a user certificate and matching
7595c51f124SMoriah Waterland * private key to a keystore.
7605c51f124SMoriah Waterland * certificate checked for validity dates and non-duplicity.
7615c51f124SMoriah Waterland *
7625c51f124SMoriah Waterland * Arguments:
7635c51f124SMoriah Waterland * err - Error object to add errors to
7645c51f124SMoriah Waterland * cert - Certificate which to merge into keystore
7655c51f124SMoriah Waterland * key - matching private key to 'cert'
7665c51f124SMoriah Waterland * alias - Name which to store the cert and key under
7675c51f124SMoriah Waterland * keystore - The keystore into which the certificate is merged
7685c51f124SMoriah Waterland *
7695c51f124SMoriah Waterland * Returns:
7705c51f124SMoriah Waterland * 0 - Success - Certificate passes validity, and
7715c51f124SMoriah Waterland * is merged into keystore, along with key
7725c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
7735c51f124SMoriah Waterland */
7745c51f124SMoriah Waterland int
merge_cert_and_key(PKG_ERR * err,X509 * cert,EVP_PKEY * key,char * alias,keystore_handle_t keystore_h)7755c51f124SMoriah Waterland merge_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key, char *alias,
7765c51f124SMoriah Waterland keystore_handle_t keystore_h)
7775c51f124SMoriah Waterland {
7785c51f124SMoriah Waterland X509 *existingcert = NULL;
7795c51f124SMoriah Waterland EVP_PKEY *existingkey = NULL;
7805c51f124SMoriah Waterland int ret = 0;
7815c51f124SMoriah Waterland keystore_t *keystore = keystore_h;
7825c51f124SMoriah Waterland
7835c51f124SMoriah Waterland /* check validity dates */
7845c51f124SMoriah Waterland if (check_cert(err, cert) != 0) {
7855c51f124SMoriah Waterland ret = 1;
7865c51f124SMoriah Waterland goto cleanup;
7875c51f124SMoriah Waterland }
7885c51f124SMoriah Waterland
7895c51f124SMoriah Waterland /* set the friendlyName of the key and cert to the supplied alias */
7905c51f124SMoriah Waterland if (sunw_set_fname(alias, key, cert) != 0) {
7915c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
7925c51f124SMoriah Waterland ret = 1;
7935c51f124SMoriah Waterland goto cleanup;
7945c51f124SMoriah Waterland }
7955c51f124SMoriah Waterland
7965c51f124SMoriah Waterland /* merge certificate and key into the keystore */
7975c51f124SMoriah Waterland if (keystore->clcerts == NULL) {
7985c51f124SMoriah Waterland /* no existing truststore, so make a new one */
7995c51f124SMoriah Waterland if ((keystore->clcerts = sk_X509_new_null()) == NULL) {
8005c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
8015c51f124SMoriah Waterland ret = 1;
8025c51f124SMoriah Waterland goto cleanup;
8035c51f124SMoriah Waterland }
8045c51f124SMoriah Waterland } else {
8055c51f124SMoriah Waterland /* existing certstore, make sure there's no duplicate */
8065c51f124SMoriah Waterland if (sunw_find_fname(alias, NULL, keystore->clcerts,
8075c51f124SMoriah Waterland NULL, &existingcert) < 0) {
8085c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
8095c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
8105c51f124SMoriah Waterland __FILE__, __LINE__);
8115c51f124SMoriah Waterland ERR_print_errors_fp(stderr);
8125c51f124SMoriah Waterland ret = 1;
8135c51f124SMoriah Waterland goto cleanup;
8145c51f124SMoriah Waterland /* could not search properly! */
8155c51f124SMoriah Waterland }
8165c51f124SMoriah Waterland if (existingcert != NULL) {
8175c51f124SMoriah Waterland /* whoops, found one already */
8185c51f124SMoriah Waterland pkgerr_add(err, PKGERR_DUPLICATE,
8195c51f124SMoriah Waterland gettext(ERR_KEYSTORE_DUPLICATECERT), alias);
8205c51f124SMoriah Waterland ret = 1;
8215c51f124SMoriah Waterland goto cleanup;
8225c51f124SMoriah Waterland }
8235c51f124SMoriah Waterland }
8245c51f124SMoriah Waterland
8255c51f124SMoriah Waterland if (keystore->pkeys == NULL) {
8265c51f124SMoriah Waterland /* no existing keystore, so make a new one */
8275c51f124SMoriah Waterland if ((keystore->pkeys = sk_EVP_PKEY_new_null()) == NULL) {
8285c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
8295c51f124SMoriah Waterland ret = 1;
8305c51f124SMoriah Waterland goto cleanup;
8315c51f124SMoriah Waterland }
8325c51f124SMoriah Waterland } else {
8335c51f124SMoriah Waterland /* existing keystore, so make sure there's no duplicate entry */
8345c51f124SMoriah Waterland if (sunw_find_fname(alias, keystore->pkeys, NULL,
8355c51f124SMoriah Waterland &existingkey, NULL) < 0) {
8365c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
8375c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
8385c51f124SMoriah Waterland __FILE__, __LINE__);
8395c51f124SMoriah Waterland ERR_print_errors_fp(stderr);
8405c51f124SMoriah Waterland ret = 1;
8415c51f124SMoriah Waterland goto cleanup;
8425c51f124SMoriah Waterland /* could not search properly! */
8435c51f124SMoriah Waterland }
8445c51f124SMoriah Waterland if (existingkey != NULL) {
8455c51f124SMoriah Waterland /* whoops, found one already */
8465c51f124SMoriah Waterland pkgerr_add(err, PKGERR_DUPLICATE,
8475c51f124SMoriah Waterland gettext(ERR_KEYSTORE_DUPLICATEKEY), alias);
8485c51f124SMoriah Waterland ret = 1;
8495c51f124SMoriah Waterland goto cleanup;
8505c51f124SMoriah Waterland }
8515c51f124SMoriah Waterland }
8525c51f124SMoriah Waterland
8535c51f124SMoriah Waterland (void) sk_X509_push(keystore->clcerts, cert);
8545c51f124SMoriah Waterland (void) sk_EVP_PKEY_push(keystore->pkeys, key);
8555c51f124SMoriah Waterland keystore->dirty = B_TRUE;
8565c51f124SMoriah Waterland cleanup:
8575c51f124SMoriah Waterland if (existingcert != NULL)
8585c51f124SMoriah Waterland (void) X509_free(existingcert);
8595c51f124SMoriah Waterland if (existingkey != NULL)
8605c51f124SMoriah Waterland (void) sunw_evp_pkey_free(existingkey);
8615c51f124SMoriah Waterland return (ret);
8625c51f124SMoriah Waterland }
8635c51f124SMoriah Waterland
8645c51f124SMoriah Waterland /*
8655c51f124SMoriah Waterland * delete_cert_and_keys - Deletes one or more certificates
8665c51f124SMoriah Waterland * and matching private keys from a keystore.
8675c51f124SMoriah Waterland *
8685c51f124SMoriah Waterland * Arguments:
8695c51f124SMoriah Waterland * err - Error object to add errors to
8705c51f124SMoriah Waterland * ks - The keystore from which certs and keys are deleted
8715c51f124SMoriah Waterland * alias - Name which to search for certificates and keys
8725c51f124SMoriah Waterland * to delete
8735c51f124SMoriah Waterland *
8745c51f124SMoriah Waterland * Returns:
8755c51f124SMoriah Waterland * 0 - Success - All trusted certs which match 'alias'
8765c51f124SMoriah Waterland * are deleted. All user certificates
8775c51f124SMoriah Waterland * which match 'alias' are deleted, along
8785c51f124SMoriah Waterland * with the matching private key.
8795c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err
8805c51f124SMoriah Waterland */
8815c51f124SMoriah Waterland int
delete_cert_and_keys(PKG_ERR * err,keystore_handle_t ks_h,char * alias)8825c51f124SMoriah Waterland delete_cert_and_keys(PKG_ERR *err, keystore_handle_t ks_h, char *alias)
8835c51f124SMoriah Waterland {
8845c51f124SMoriah Waterland X509 *existingcert;
8855c51f124SMoriah Waterland EVP_PKEY *existingkey;
8865c51f124SMoriah Waterland int i;
8875c51f124SMoriah Waterland char *fname = NULL;
8885c51f124SMoriah Waterland boolean_t found = B_FALSE;
8895c51f124SMoriah Waterland keystore_t *ks = ks_h;
8905c51f124SMoriah Waterland
8915c51f124SMoriah Waterland /* delete any and all client certs with the supplied name */
8925c51f124SMoriah Waterland if (ks->clcerts != NULL) {
8935c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(ks->clcerts); i++) {
8945c51f124SMoriah Waterland existingcert = sk_X509_value(ks->clcerts, i);
8955c51f124SMoriah Waterland if (sunw_get_cert_fname(GETDO_COPY,
8965c51f124SMoriah Waterland existingcert, &fname) >= 0) {
8975c51f124SMoriah Waterland if (streq(fname, alias)) {
8985c51f124SMoriah Waterland /* match, so nuke it */
8995c51f124SMoriah Waterland existingcert =
9005c51f124SMoriah Waterland sk_X509_delete(ks->clcerts, i);
9015c51f124SMoriah Waterland X509_free(existingcert);
9025c51f124SMoriah Waterland existingcert = NULL;
9035c51f124SMoriah Waterland found = B_TRUE;
9045c51f124SMoriah Waterland }
9055c51f124SMoriah Waterland (void) OPENSSL_free(fname);
9065c51f124SMoriah Waterland fname = NULL;
9075c51f124SMoriah Waterland }
9085c51f124SMoriah Waterland }
9095c51f124SMoriah Waterland if (sk_X509_num(ks->clcerts) <= 0) {
9105c51f124SMoriah Waterland /* we deleted all the client certs */
9115c51f124SMoriah Waterland sk_X509_free(ks->clcerts);
9125c51f124SMoriah Waterland ks->clcerts = NULL;
9135c51f124SMoriah Waterland }
9145c51f124SMoriah Waterland }
9155c51f124SMoriah Waterland
9165c51f124SMoriah Waterland /* and now the private keys */
9175c51f124SMoriah Waterland if (ks->pkeys != NULL) {
9185c51f124SMoriah Waterland for (i = 0; i < sk_EVP_PKEY_num(ks->pkeys); i++) {
9195c51f124SMoriah Waterland existingkey = sk_EVP_PKEY_value(ks->pkeys, i);
9205c51f124SMoriah Waterland if (sunw_get_pkey_fname(GETDO_COPY,
9215c51f124SMoriah Waterland existingkey, &fname) >= 0) {
9225c51f124SMoriah Waterland if (streq(fname, alias)) {
9235c51f124SMoriah Waterland /* match, so nuke it */
9245c51f124SMoriah Waterland existingkey =
9255c51f124SMoriah Waterland sk_EVP_PKEY_delete(ks->pkeys, i);
9265c51f124SMoriah Waterland sunw_evp_pkey_free(existingkey);
9275c51f124SMoriah Waterland existingkey = NULL;
9285c51f124SMoriah Waterland found = B_TRUE;
9295c51f124SMoriah Waterland }
9305c51f124SMoriah Waterland (void) OPENSSL_free(fname);
9315c51f124SMoriah Waterland fname = NULL;
9325c51f124SMoriah Waterland }
9335c51f124SMoriah Waterland }
9345c51f124SMoriah Waterland if (sk_EVP_PKEY_num(ks->pkeys) <= 0) {
9355c51f124SMoriah Waterland /* we deleted all the private keys */
9365c51f124SMoriah Waterland sk_EVP_PKEY_free(ks->pkeys);
9375c51f124SMoriah Waterland ks->pkeys = NULL;
9385c51f124SMoriah Waterland }
9395c51f124SMoriah Waterland }
9405c51f124SMoriah Waterland
9415c51f124SMoriah Waterland /* finally, remove any trust anchors that match */
9425c51f124SMoriah Waterland
9435c51f124SMoriah Waterland if (ks->cacerts != NULL) {
9445c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(ks->cacerts); i++) {
9455c51f124SMoriah Waterland existingcert = sk_X509_value(ks->cacerts, i);
9465c51f124SMoriah Waterland if (sunw_get_cert_fname(GETDO_COPY,
9475c51f124SMoriah Waterland existingcert, &fname) >= 0) {
9485c51f124SMoriah Waterland if (streq(fname, alias)) {
9495c51f124SMoriah Waterland /* match, so nuke it */
9505c51f124SMoriah Waterland existingcert =
9515c51f124SMoriah Waterland sk_X509_delete(ks->cacerts, i);
9525c51f124SMoriah Waterland X509_free(existingcert);
9535c51f124SMoriah Waterland existingcert = NULL;
9545c51f124SMoriah Waterland found = B_TRUE;
9555c51f124SMoriah Waterland }
9565c51f124SMoriah Waterland (void) OPENSSL_free(fname);
9575c51f124SMoriah Waterland fname = NULL;
9585c51f124SMoriah Waterland }
9595c51f124SMoriah Waterland }
9605c51f124SMoriah Waterland if (sk_X509_num(ks->cacerts) <= 0) {
9615c51f124SMoriah Waterland /* we deleted all the CA certs */
9625c51f124SMoriah Waterland sk_X509_free(ks->cacerts);
9635c51f124SMoriah Waterland ks->cacerts = NULL;
9645c51f124SMoriah Waterland }
9655c51f124SMoriah Waterland }
9665c51f124SMoriah Waterland
9675c51f124SMoriah Waterland if (found) {
9685c51f124SMoriah Waterland ks->dirty = B_TRUE;
9695c51f124SMoriah Waterland return (0);
9705c51f124SMoriah Waterland } else {
9715c51f124SMoriah Waterland /* no certs or keys deleted */
9725c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOALIASMATCH,
9735c51f124SMoriah Waterland gettext(ERR_KEYSTORE_NOCERTKEY),
9745c51f124SMoriah Waterland alias, ks->path);
9755c51f124SMoriah Waterland return (1);
9765c51f124SMoriah Waterland }
9775c51f124SMoriah Waterland }
9785c51f124SMoriah Waterland
9795c51f124SMoriah Waterland /*
9805c51f124SMoriah Waterland * check_cert - Checks certificate validity. This routine
9815c51f124SMoriah Waterland * checks that the current time falls within the period
9825c51f124SMoriah Waterland * of validity for the cert.
9835c51f124SMoriah Waterland *
9845c51f124SMoriah Waterland * Arguments:
9855c51f124SMoriah Waterland * err - Error object to add errors to
9865c51f124SMoriah Waterland * cert - The certificate to check
9875c51f124SMoriah Waterland *
9885c51f124SMoriah Waterland * Returns:
9895c51f124SMoriah Waterland * 0 - Success - Certificate checks out
9905c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
9915c51f124SMoriah Waterland */
9925c51f124SMoriah Waterland int
check_cert(PKG_ERR * err,X509 * cert)9935c51f124SMoriah Waterland check_cert(PKG_ERR *err, X509 *cert)
9945c51f124SMoriah Waterland {
9955c51f124SMoriah Waterland char currtimestr[ATTR_MAX];
9965c51f124SMoriah Waterland time_t currtime;
997*4656d474SGarrett D'Amore char *r;
9985c51f124SMoriah Waterland /* get current time */
9995c51f124SMoriah Waterland if ((currtime = time(NULL)) == (time_t)-1) {
10005c51f124SMoriah Waterland pkgerr_add(err, PKGERR_TIME, gettext(ERR_CURR_TIME));
10015c51f124SMoriah Waterland return (1);
10025c51f124SMoriah Waterland }
10035c51f124SMoriah Waterland
10045c51f124SMoriah Waterland (void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX);
10055c51f124SMoriah Waterland
10065c51f124SMoriah Waterland /* trim whitespace from end of time string */
10075c51f124SMoriah Waterland for (r = (currtimestr + strlen(currtimestr) - 1); isspace(*r); r--) {
10085c51f124SMoriah Waterland *r = '\0';
10095c51f124SMoriah Waterland }
10105c51f124SMoriah Waterland /* check validity of cert */
10115c51f124SMoriah Waterland switch (sunw_check_cert_times(CHK_BOTH, cert)) {
10125c51f124SMoriah Waterland case CHKERR_TIME_OK:
10135c51f124SMoriah Waterland /* Current time meets requested checks */
10145c51f124SMoriah Waterland break;
10155c51f124SMoriah Waterland case CHKERR_TIME_BEFORE_BAD:
10165c51f124SMoriah Waterland /* 'not before' field is invalid */
10175c51f124SMoriah Waterland case CHKERR_TIME_AFTER_BAD:
10185c51f124SMoriah Waterland /* 'not after' field is invalid */
10195c51f124SMoriah Waterland pkgerr_add(err, PKGERR_TIME, gettext(ERR_CERT_TIME_BAD));
10205c51f124SMoriah Waterland return (1);
10215c51f124SMoriah Waterland case CHKERR_TIME_IS_BEFORE:
10225c51f124SMoriah Waterland /* Current time is before 'not before' */
10235c51f124SMoriah Waterland case CHKERR_TIME_HAS_EXPIRED:
10245c51f124SMoriah Waterland /*
10255c51f124SMoriah Waterland * Ignore expiration time since the trust cert used to
10265c51f124SMoriah Waterland * verify the certs used to sign Sun patches is already
10275c51f124SMoriah Waterland * expired. Once the patches get resigned with the new
10285c51f124SMoriah Waterland * cert we will check expiration against the time the
10295c51f124SMoriah Waterland * patch was signed and not the time it is installed.
10305c51f124SMoriah Waterland */
10315c51f124SMoriah Waterland return (0);
10325c51f124SMoriah Waterland default:
10335c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
10345c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
10355c51f124SMoriah Waterland __FILE__, __LINE__);
10365c51f124SMoriah Waterland return (1);
10375c51f124SMoriah Waterland }
10385c51f124SMoriah Waterland
10395c51f124SMoriah Waterland /* all checks ok */
10405c51f124SMoriah Waterland return (0);
10415c51f124SMoriah Waterland }
10425c51f124SMoriah Waterland
10435c51f124SMoriah Waterland /*
10445c51f124SMoriah Waterland * check_cert - Checks certificate validity. This routine
10455c51f124SMoriah Waterland * checks everything that check_cert checks, and additionally
10465c51f124SMoriah Waterland * verifies that the private key and corresponding public
10475c51f124SMoriah Waterland * key are indeed a pair.
10485c51f124SMoriah Waterland *
10495c51f124SMoriah Waterland * Arguments:
10505c51f124SMoriah Waterland * err - Error object to add errors to
10515c51f124SMoriah Waterland * cert - The certificate to check
10525c51f124SMoriah Waterland * key - the key to check
10535c51f124SMoriah Waterland * Returns:
10545c51f124SMoriah Waterland * 0 - Success - Certificate checks out
10555c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
10565c51f124SMoriah Waterland */
10575c51f124SMoriah Waterland int
check_cert_and_key(PKG_ERR * err,X509 * cert,EVP_PKEY * key)10585c51f124SMoriah Waterland check_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key)
10595c51f124SMoriah Waterland {
10605c51f124SMoriah Waterland
10615c51f124SMoriah Waterland /* check validity dates */
10625c51f124SMoriah Waterland if (check_cert(err, cert) != 0) {
10635c51f124SMoriah Waterland return (1);
10645c51f124SMoriah Waterland }
10655c51f124SMoriah Waterland
10665c51f124SMoriah Waterland /* check key pair match */
10675c51f124SMoriah Waterland if (sunw_check_keys(cert, key) == 0) {
10685c51f124SMoriah Waterland pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MISMATCHED_KEYS),
10695c51f124SMoriah Waterland get_subject_display_name(cert));
10705c51f124SMoriah Waterland return (1);
10715c51f124SMoriah Waterland }
10725c51f124SMoriah Waterland
10735c51f124SMoriah Waterland /* all checks OK */
10745c51f124SMoriah Waterland return (0);
10755c51f124SMoriah Waterland }
10765c51f124SMoriah Waterland
10775c51f124SMoriah Waterland /* ------------------ private functions ---------------------- */
10785c51f124SMoriah Waterland
10795c51f124SMoriah Waterland /*
10805c51f124SMoriah Waterland * verify_keystore_integrity - Searches for the remnants
10815c51f124SMoriah Waterland * of a failed or aborted keystore modification, and
10825c51f124SMoriah Waterland * cleans up the files, retstores the keystore to a known
10835c51f124SMoriah Waterland * state.
10845c51f124SMoriah Waterland *
10855c51f124SMoriah Waterland * Arguments:
10865c51f124SMoriah Waterland * err - Error object to add errors to
10875c51f124SMoriah Waterland * keystore_file - Base directory or filename of keystore
10885c51f124SMoriah Waterland * app - Application making request
10895c51f124SMoriah Waterland *
10905c51f124SMoriah Waterland * Returns:
10915c51f124SMoriah Waterland * 0 - Success - Keystore is restored, or untouched in the
10925c51f124SMoriah Waterland * case that cleanup was unnecessary
10935c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
10945c51f124SMoriah Waterland */
10955c51f124SMoriah Waterland static boolean_t
verify_keystore_integrity(PKG_ERR * err,keystore_t * keystore)10965c51f124SMoriah Waterland verify_keystore_integrity(PKG_ERR *err, keystore_t *keystore)
10975c51f124SMoriah Waterland {
10985c51f124SMoriah Waterland if (keystore->capath != NULL) {
10995c51f124SMoriah Waterland if (!restore_keystore_file(err, keystore->capath)) {
11005c51f124SMoriah Waterland return (B_FALSE);
11015c51f124SMoriah Waterland }
11025c51f124SMoriah Waterland }
11035c51f124SMoriah Waterland if (keystore->clpath != NULL) {
11045c51f124SMoriah Waterland if (!restore_keystore_file(err, keystore->clpath)) {
11055c51f124SMoriah Waterland return (B_FALSE);
11065c51f124SMoriah Waterland }
11075c51f124SMoriah Waterland }
11085c51f124SMoriah Waterland if (keystore->keypath != NULL) {
11095c51f124SMoriah Waterland if (!restore_keystore_file(err, keystore->keypath)) {
11105c51f124SMoriah Waterland return (B_FALSE);
11115c51f124SMoriah Waterland }
11125c51f124SMoriah Waterland }
11135c51f124SMoriah Waterland return (B_TRUE);
11145c51f124SMoriah Waterland }
11155c51f124SMoriah Waterland
11165c51f124SMoriah Waterland /*
11175c51f124SMoriah Waterland * restore_keystore_file - restores a keystore file to
11185c51f124SMoriah Waterland * a known state.
11195c51f124SMoriah Waterland *
11205c51f124SMoriah Waterland * Keystore files can possibly be corrupted by a variety
11215c51f124SMoriah Waterland * of error conditions during reading/writing. This
11225c51f124SMoriah Waterland * routine, along with write_keystore_file, tries to
11235c51f124SMoriah Waterland * maintain keystore integrity by writing the files
11245c51f124SMoriah Waterland * out in a particular order, minimizing the time period
11255c51f124SMoriah Waterland * that the keystore is in an indeterminate state.
11265c51f124SMoriah Waterland *
11275c51f124SMoriah Waterland * With the current implementation, there are some failures
11285c51f124SMoriah Waterland * that are wholly unrecoverable, such as disk corruption.
11295c51f124SMoriah Waterland * These routines attempt to minimize the risk, but not
11305c51f124SMoriah Waterland * eliminate it. When better, atomic operations are available
11315c51f124SMoriah Waterland * (such as a trued atabase with commit, rollback, and
11325c51f124SMoriah Waterland * guaranteed atomicity), this implementation should use that.
11335c51f124SMoriah Waterland *
11345c51f124SMoriah Waterland * Arguments:
11355c51f124SMoriah Waterland * err - Error object to add errors to
11365c51f124SMoriah Waterland * keystore_file - keystore file path to restore.
11375c51f124SMoriah Waterland *
11385c51f124SMoriah Waterland * Returns:
11395c51f124SMoriah Waterland * 0 - Success - Keystore file is restored, or untouched in the
11405c51f124SMoriah Waterland * case that cleanup was unnecessary
11415c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
11425c51f124SMoriah Waterland */
11435c51f124SMoriah Waterland /* ARGSUSED */
11445c51f124SMoriah Waterland static boolean_t
restore_keystore_file(PKG_ERR * err,char * keystore_file)11455c51f124SMoriah Waterland restore_keystore_file(PKG_ERR *err, char *keystore_file)
11465c51f124SMoriah Waterland {
11475c51f124SMoriah Waterland char newpath[MAXPATHLEN];
11485c51f124SMoriah Waterland char backuppath[MAXPATHLEN];
11495c51f124SMoriah Waterland int newfd;
11505c51f124SMoriah Waterland struct stat buf;
11515c51f124SMoriah Waterland int len;
11525c51f124SMoriah Waterland
11535c51f124SMoriah Waterland if (((len = snprintf(newpath, MAXPATHLEN, "%s.new",
11545c51f124SMoriah Waterland keystore_file)) < 0) ||
11555c51f124SMoriah Waterland (len >= ATTR_MAX)) {
11565c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
11575c51f124SMoriah Waterland return (B_FALSE);
11585c51f124SMoriah Waterland }
11595c51f124SMoriah Waterland
11605c51f124SMoriah Waterland if (((len = snprintf(backuppath, MAXPATHLEN, "%s.bak",
11615c51f124SMoriah Waterland keystore_file)) < 0) ||
11625c51f124SMoriah Waterland (len >= ATTR_MAX)) {
11635c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
11645c51f124SMoriah Waterland return (B_FALSE);
11655c51f124SMoriah Waterland }
11665c51f124SMoriah Waterland
11675c51f124SMoriah Waterland if ((newfd = open(newpath, O_RDWR|O_NONBLOCK, 0)) != -1) {
11685c51f124SMoriah Waterland if (fstat(newfd, &buf) != -1) {
11695c51f124SMoriah Waterland if (S_ISREG(buf.st_mode)) {
11705c51f124SMoriah Waterland /*
11715c51f124SMoriah Waterland * restore the file, waiting on it
11725c51f124SMoriah Waterland * to be free for locking, or for
11735c51f124SMoriah Waterland * it to disappear
11745c51f124SMoriah Waterland */
11755c51f124SMoriah Waterland if (!wait_restore(newfd, keystore_file,
11765c51f124SMoriah Waterland newpath, backuppath)) {
11775c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
11785c51f124SMoriah Waterland gettext(ERR_WRITE),
11795c51f124SMoriah Waterland newpath, strerror(errno));
11805c51f124SMoriah Waterland (void) close(newfd);
11815c51f124SMoriah Waterland return (B_FALSE);
11825c51f124SMoriah Waterland } else {
11835c51f124SMoriah Waterland return (B_TRUE);
11845c51f124SMoriah Waterland }
11855c51f124SMoriah Waterland } else {
11865c51f124SMoriah Waterland /* "new" file is not a regular file */
11875c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
11885c51f124SMoriah Waterland gettext(ERR_NOT_REG), newpath);
11895c51f124SMoriah Waterland (void) close(newfd);
11905c51f124SMoriah Waterland return (B_FALSE);
11915c51f124SMoriah Waterland }
11925c51f124SMoriah Waterland } else {
11935c51f124SMoriah Waterland /* couldn't stat "new" file */
11945c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
11955c51f124SMoriah Waterland gettext(ERR_WRITE), newpath,
11965c51f124SMoriah Waterland strerror(errno));
11975c51f124SMoriah Waterland (void) close(newfd);
11985c51f124SMoriah Waterland return (B_FALSE);
11995c51f124SMoriah Waterland }
12005c51f124SMoriah Waterland } else {
12015c51f124SMoriah Waterland /* "new" file doesn't exist */
12025c51f124SMoriah Waterland return (B_TRUE);
12035c51f124SMoriah Waterland }
12045c51f124SMoriah Waterland }
12055c51f124SMoriah Waterland
12065c51f124SMoriah Waterland static boolean_t
wait_restore(int newfd,char * keystore_file,char * origpath,char * backuppath)12075c51f124SMoriah Waterland wait_restore(int newfd, char *keystore_file,
12085c51f124SMoriah Waterland char *origpath, char *backuppath)
12095c51f124SMoriah Waterland {
12105c51f124SMoriah Waterland struct stat buf;
12115c51f124SMoriah Waterland FILE *newstream;
12125c51f124SMoriah Waterland PKCS12 *p12;
12135c51f124SMoriah Waterland
12145c51f124SMoriah Waterland (void) alarm(LOCK_TIMEOUT);
12155c51f124SMoriah Waterland if (file_lock(newfd, F_WRLCK, 1) == -1) {
12165c51f124SMoriah Waterland /* could not lock file */
12175c51f124SMoriah Waterland (void) alarm(0);
12185c51f124SMoriah Waterland return (B_FALSE);
12195c51f124SMoriah Waterland }
12205c51f124SMoriah Waterland (void) alarm(0);
12215c51f124SMoriah Waterland
12225c51f124SMoriah Waterland if (fstat(newfd, &buf) != -1) {
12235c51f124SMoriah Waterland if (S_ISREG(buf.st_mode)) {
12245c51f124SMoriah Waterland /*
12255c51f124SMoriah Waterland * The new file still
12265c51f124SMoriah Waterland * exists, with no
12275c51f124SMoriah Waterland * owner. It must be
12285c51f124SMoriah Waterland * the result of an
12295c51f124SMoriah Waterland * aborted update.
12305c51f124SMoriah Waterland */
12315c51f124SMoriah Waterland newstream = fdopen(newfd, "r");
12325c51f124SMoriah Waterland if ((p12 =
12335c51f124SMoriah Waterland d2i_PKCS12_fp(newstream,
12345c51f124SMoriah Waterland NULL)) != NULL) {
12355c51f124SMoriah Waterland /*
12365c51f124SMoriah Waterland * The file
12375c51f124SMoriah Waterland * appears
12385c51f124SMoriah Waterland * complete.
12395c51f124SMoriah Waterland * Replace the
12405c51f124SMoriah Waterland * exsisting
12415c51f124SMoriah Waterland * keystore
12425c51f124SMoriah Waterland * file with
12435c51f124SMoriah Waterland * this one
12445c51f124SMoriah Waterland */
12455c51f124SMoriah Waterland (void) rename(keystore_file, backuppath);
12465c51f124SMoriah Waterland (void) rename(origpath, keystore_file);
12475c51f124SMoriah Waterland PKCS12_free(p12);
12485c51f124SMoriah Waterland } else {
12495c51f124SMoriah Waterland /* The file is not complete. Remove it */
12505c51f124SMoriah Waterland (void) remove(origpath);
12515c51f124SMoriah Waterland }
12525c51f124SMoriah Waterland /* remove backup file */
12535c51f124SMoriah Waterland (void) remove(backuppath);
12545c51f124SMoriah Waterland (void) fclose(newstream);
12555c51f124SMoriah Waterland (void) close(newfd);
12565c51f124SMoriah Waterland return (B_TRUE);
12575c51f124SMoriah Waterland } else {
12585c51f124SMoriah Waterland /*
12595c51f124SMoriah Waterland * new file exists, but is not a
12605c51f124SMoriah Waterland * regular file
12615c51f124SMoriah Waterland */
12625c51f124SMoriah Waterland (void) close(newfd);
12635c51f124SMoriah Waterland return (B_FALSE);
12645c51f124SMoriah Waterland }
12655c51f124SMoriah Waterland } else {
12665c51f124SMoriah Waterland /*
12675c51f124SMoriah Waterland * could not stat file. Unless
12685c51f124SMoriah Waterland * the reason was that the file
12695c51f124SMoriah Waterland * is now gone, this is an error
12705c51f124SMoriah Waterland */
12715c51f124SMoriah Waterland if (errno != ENOENT) {
12725c51f124SMoriah Waterland (void) close(newfd);
12735c51f124SMoriah Waterland return (B_FALSE);
12745c51f124SMoriah Waterland }
12755c51f124SMoriah Waterland /*
12765c51f124SMoriah Waterland * otherwise, file is gone. The process
12775c51f124SMoriah Waterland * that held the lock must have
12785c51f124SMoriah Waterland * successfully cleaned up and
12795c51f124SMoriah Waterland * exited with a valid keystore
12805c51f124SMoriah Waterland * state
12815c51f124SMoriah Waterland */
12825c51f124SMoriah Waterland (void) close(newfd);
12835c51f124SMoriah Waterland return (B_TRUE);
12845c51f124SMoriah Waterland }
12855c51f124SMoriah Waterland }
12865c51f124SMoriah Waterland
12875c51f124SMoriah Waterland /*
12885c51f124SMoriah Waterland * resolve_paths - figure out if we are dealing with a single-file
12895c51f124SMoriah Waterland * or multi-file keystore
12905c51f124SMoriah Waterland *
12915c51f124SMoriah Waterland * The flags tell resolve_paths how to behave:
12925c51f124SMoriah Waterland *
12935c51f124SMoriah Waterland * KEYSTORE_PATH_SOFT
12945c51f124SMoriah Waterland * If the keystore file does not exist at <base>/<app> then
12955c51f124SMoriah Waterland * use <base> as the path to the keystore. This can be used,
12965c51f124SMoriah Waterland * for example, to access an app-specific keystore iff it
12975c51f124SMoriah Waterland * exists, otherwise revert back to an app-generic keystore.
12985c51f124SMoriah Waterland *
12995c51f124SMoriah Waterland * KEYSTORE_PATH_HARD
13005c51f124SMoriah Waterland * Always use the keystore located at <keystore_path>/<app>.
13015c51f124SMoriah Waterland * In read/write mode, if the files do not exist, then
13025c51f124SMoriah Waterland * they will be created. This is used to avoid falling
13035c51f124SMoriah Waterland * back to an app-generic keystore path when the app-specific
13045c51f124SMoriah Waterland * one does not exist.
13055c51f124SMoriah Waterland *
13065c51f124SMoriah Waterland * Arguments:
13075c51f124SMoriah Waterland * err - Error object to add errors to
13085c51f124SMoriah Waterland * keystore_file - base keystore file path to lock
13095c51f124SMoriah Waterland * app - Application making requests
13105c51f124SMoriah Waterland * flags - Control flags (see above description)
13115c51f124SMoriah Waterland * keystore - object which is being locked
13125c51f124SMoriah Waterland *
13135c51f124SMoriah Waterland * Returns:
13145c51f124SMoriah Waterland * B_TRUE - Success - Keystore file is locked, paths to
13155c51f124SMoriah Waterland * appropriate files placed in keystore.
13165c51f124SMoriah Waterland * B_FALSE - Failure, errors and reasons recorded in err
13175c51f124SMoriah Waterland */
13185c51f124SMoriah Waterland static boolean_t
resolve_paths(PKG_ERR * err,char * keystore_file,char * app,long flags,keystore_t * keystore)13195c51f124SMoriah Waterland resolve_paths(PKG_ERR *err, char *keystore_file, char *app,
13205c51f124SMoriah Waterland long flags, keystore_t *keystore)
13215c51f124SMoriah Waterland {
13225c51f124SMoriah Waterland char storepath[PATH_MAX];
13235c51f124SMoriah Waterland struct stat buf;
13245c51f124SMoriah Waterland boolean_t multi = B_FALSE;
13255c51f124SMoriah Waterland int fd1, fd2, len;
13265c51f124SMoriah Waterland
13275c51f124SMoriah Waterland /*
13285c51f124SMoriah Waterland * figure out whether we are dealing with a single-file keystore
13295c51f124SMoriah Waterland * or a multi-file keystore
13305c51f124SMoriah Waterland */
13315c51f124SMoriah Waterland if (app != NULL) {
13325c51f124SMoriah Waterland if (((len = snprintf(storepath, PATH_MAX, "%s/%s",
13335c51f124SMoriah Waterland keystore_file, app)) < 0) ||
13345c51f124SMoriah Waterland (len >= ATTR_MAX)) {
13355c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN),
13365c51f124SMoriah Waterland keystore_file);
13375c51f124SMoriah Waterland return (B_FALSE);
13385c51f124SMoriah Waterland }
13395c51f124SMoriah Waterland
13405c51f124SMoriah Waterland if (((fd1 = open(storepath, O_NONBLOCK|O_RDONLY)) == -1) ||
13415c51f124SMoriah Waterland (fstat(fd1, &buf) == -1) ||
13425c51f124SMoriah Waterland !S_ISDIR(buf.st_mode)) {
13435c51f124SMoriah Waterland /*
13445c51f124SMoriah Waterland * app-specific does not exist
13455c51f124SMoriah Waterland * fallback to app-generic, if flags say we can
13465c51f124SMoriah Waterland */
13475c51f124SMoriah Waterland if ((flags & KEYSTORE_PATH_MASK) ==
13485c51f124SMoriah Waterland KEYSTORE_PATH_SOFT) {
13495c51f124SMoriah Waterland
13505c51f124SMoriah Waterland if (((fd2 = open(keystore_file,
13515c51f124SMoriah Waterland O_NONBLOCK|O_RDONLY)) != -1) &&
13525c51f124SMoriah Waterland (fstat(fd2, &buf) != -1)) {
13535c51f124SMoriah Waterland if (S_ISDIR(buf.st_mode)) {
13545c51f124SMoriah Waterland /*
13555c51f124SMoriah Waterland * app-generic dir
13565c51f124SMoriah Waterland * exists, so use it
13575c51f124SMoriah Waterland * as a multi-file
13585c51f124SMoriah Waterland * keystore
13595c51f124SMoriah Waterland */
13605c51f124SMoriah Waterland multi = B_TRUE;
13615c51f124SMoriah Waterland app = NULL;
13625c51f124SMoriah Waterland } else if (S_ISREG(buf.st_mode)) {
13635c51f124SMoriah Waterland /*
13645c51f124SMoriah Waterland * app-generic file exists, so
13655c51f124SMoriah Waterland * use it as a single file ks
13665c51f124SMoriah Waterland */
13675c51f124SMoriah Waterland multi = B_FALSE;
13685c51f124SMoriah Waterland app = NULL;
13695c51f124SMoriah Waterland }
13705c51f124SMoriah Waterland }
13715c51f124SMoriah Waterland }
13725c51f124SMoriah Waterland }
13735c51f124SMoriah Waterland if (fd1 != -1)
13745c51f124SMoriah Waterland (void) close(fd1);
13755c51f124SMoriah Waterland if (fd2 != -1)
13765c51f124SMoriah Waterland (void) close(fd2);
13775c51f124SMoriah Waterland } else {
13785c51f124SMoriah Waterland if (((fd1 = open(keystore_file,
13795c51f124SMoriah Waterland O_NONBLOCK|O_RDONLY)) != -1) &&
13805c51f124SMoriah Waterland (fstat(fd1, &buf) != -1) &&
13815c51f124SMoriah Waterland S_ISDIR(buf.st_mode)) {
13825c51f124SMoriah Waterland /*
13835c51f124SMoriah Waterland * app-generic dir exists, so use
13845c51f124SMoriah Waterland * it as a multi-file keystore
13855c51f124SMoriah Waterland */
13865c51f124SMoriah Waterland multi = B_TRUE;
13875c51f124SMoriah Waterland }
13885c51f124SMoriah Waterland if (fd1 != -1)
13895c51f124SMoriah Waterland (void) close(fd1);
13905c51f124SMoriah Waterland }
13915c51f124SMoriah Waterland
13925c51f124SMoriah Waterland if (app != NULL) {
13935c51f124SMoriah Waterland /* app-specific keystore */
13945c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
13955c51f124SMoriah Waterland keystore_file, app, TRUSTSTORE);
13965c51f124SMoriah Waterland keystore->capath = xstrdup(storepath);
13975c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
13985c51f124SMoriah Waterland keystore_file, app, CERTSTORE);
13995c51f124SMoriah Waterland keystore->clpath = xstrdup(storepath);
14005c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
14015c51f124SMoriah Waterland keystore_file, app, KEYSTORE);
14025c51f124SMoriah Waterland keystore->keypath = xstrdup(storepath);
14035c51f124SMoriah Waterland } else {
14045c51f124SMoriah Waterland /* app-generic keystore */
14055c51f124SMoriah Waterland if (!multi) {
14065c51f124SMoriah Waterland /* single-file app-generic keystore */
14075c51f124SMoriah Waterland keystore->capath = xstrdup(keystore_file);
14085c51f124SMoriah Waterland keystore->keypath = NULL;
14095c51f124SMoriah Waterland keystore->clpath = NULL;
14105c51f124SMoriah Waterland } else {
14115c51f124SMoriah Waterland /* multi-file app-generic keystore */
14125c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s",
14135c51f124SMoriah Waterland keystore_file, TRUSTSTORE);
14145c51f124SMoriah Waterland keystore->capath = xstrdup(storepath);
14155c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s",
14165c51f124SMoriah Waterland keystore_file, CERTSTORE);
14175c51f124SMoriah Waterland keystore->clpath = xstrdup(storepath);
14185c51f124SMoriah Waterland (void) snprintf(storepath, PATH_MAX, "%s/%s",
14195c51f124SMoriah Waterland keystore_file, KEYSTORE);
14205c51f124SMoriah Waterland keystore->keypath = xstrdup(storepath);
14215c51f124SMoriah Waterland }
14225c51f124SMoriah Waterland }
14235c51f124SMoriah Waterland
14245c51f124SMoriah Waterland return (B_TRUE);
14255c51f124SMoriah Waterland }
14265c51f124SMoriah Waterland
14275c51f124SMoriah Waterland /*
14285c51f124SMoriah Waterland * lock_keystore - Locks a keystore for shared (read-only)
14295c51f124SMoriah Waterland * or exclusive (read-write) access.
14305c51f124SMoriah Waterland *
14315c51f124SMoriah Waterland * The flags tell lock_keystore how to behave:
14325c51f124SMoriah Waterland *
14335c51f124SMoriah Waterland * KEYSTORE_ACCESS_READONLY
14345c51f124SMoriah Waterland * opens keystore read-only. Attempts to modify results in an error
14355c51f124SMoriah Waterland *
14365c51f124SMoriah Waterland * KEYSTORE_ACCESS_READWRITE
14375c51f124SMoriah Waterland * opens keystore read-write
14385c51f124SMoriah Waterland *
14395c51f124SMoriah Waterland * KEYSTORE_PATH_SOFT
14405c51f124SMoriah Waterland * If the keystore file does not exist at <base>/<app> then
14415c51f124SMoriah Waterland * use <base> as the path to the keystore. This can be used,
14425c51f124SMoriah Waterland * for example, to access an app-specific keystore iff it
14435c51f124SMoriah Waterland * exists, otherwise revert back to an app-generic keystore.
14445c51f124SMoriah Waterland *
14455c51f124SMoriah Waterland * KEYSTORE_PATH_HARD
14465c51f124SMoriah Waterland * Always use the keystore located at <keystore_path>/<app>.
14475c51f124SMoriah Waterland * In read/write mode, if the files do not exist, then
14485c51f124SMoriah Waterland * they will be created. This is used to avoid falling
14495c51f124SMoriah Waterland * back to an app-generic keystore path when the app-specific
14505c51f124SMoriah Waterland * one does not exist.
14515c51f124SMoriah Waterland *
14525c51f124SMoriah Waterland * Arguments:
14535c51f124SMoriah Waterland * err - Error object to add errors to
14545c51f124SMoriah Waterland * flags - Control flags (see above description)
14555c51f124SMoriah Waterland * keystore - object which is being locked
14565c51f124SMoriah Waterland *
14575c51f124SMoriah Waterland * Returns:
14585c51f124SMoriah Waterland * 0 - Success - Keystore file is locked, paths to
14595c51f124SMoriah Waterland * appropriate files placed in keystore.
14605c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
14615c51f124SMoriah Waterland */
14625c51f124SMoriah Waterland static boolean_t
lock_keystore(PKG_ERR * err,long flags,keystore_t * keystore)14635c51f124SMoriah Waterland lock_keystore(PKG_ERR *err, long flags, keystore_t *keystore)
14645c51f124SMoriah Waterland {
14655c51f124SMoriah Waterland boolean_t ret = B_TRUE;
14665c51f124SMoriah Waterland struct stat buf;
14675c51f124SMoriah Waterland
14685c51f124SMoriah Waterland switch (flags & KEYSTORE_ACCESS_MASK) {
14695c51f124SMoriah Waterland case KEYSTORE_ACCESS_READONLY:
14705c51f124SMoriah Waterland if ((keystore->cafd =
14715c51f124SMoriah Waterland open(keystore->capath, O_NONBLOCK|O_RDONLY)) == -1) {
14725c51f124SMoriah Waterland if (errno == ENOENT) {
14735c51f124SMoriah Waterland /*
14745c51f124SMoriah Waterland * no keystore. try to create an
14755c51f124SMoriah Waterland * empty one so we can lock on it and
14765c51f124SMoriah Waterland * prevent others from gaining
14775c51f124SMoriah Waterland * exclusive access. It will be
14785c51f124SMoriah Waterland * deleted when the keystore is closed.
14795c51f124SMoriah Waterland */
14805c51f124SMoriah Waterland if ((keystore->cafd =
14815c51f124SMoriah Waterland open(keystore->capath,
14825c51f124SMoriah Waterland O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
14835c51f124SMoriah Waterland S_IRUSR|S_IWUSR)) == -1) {
14845c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
14855c51f124SMoriah Waterland gettext(ERR_NO_KEYSTORE),
14865c51f124SMoriah Waterland keystore->capath);
14875c51f124SMoriah Waterland ret = B_FALSE;
14885c51f124SMoriah Waterland goto cleanup;
14895c51f124SMoriah Waterland }
14905c51f124SMoriah Waterland } else {
14915c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
14925c51f124SMoriah Waterland gettext(ERR_KEYSTORE_OPEN),
14935c51f124SMoriah Waterland keystore->capath, strerror(errno));
14945c51f124SMoriah Waterland ret = B_FALSE;
14955c51f124SMoriah Waterland goto cleanup;
14965c51f124SMoriah Waterland }
14975c51f124SMoriah Waterland }
14985c51f124SMoriah Waterland if (fstat(keystore->cafd, &buf) != -1) {
14995c51f124SMoriah Waterland if (S_ISREG(buf.st_mode)) {
15005c51f124SMoriah Waterland if (file_lock(keystore->cafd, F_RDLCK,
15015c51f124SMoriah Waterland 0) == -1) {
15025c51f124SMoriah Waterland pkgerr_add(err, PKGERR_LOCKED,
15035c51f124SMoriah Waterland gettext(ERR_KEYSTORE_LOCKED_READ),
15045c51f124SMoriah Waterland keystore->capath);
15055c51f124SMoriah Waterland ret = B_FALSE;
15065c51f124SMoriah Waterland goto cleanup;
15075c51f124SMoriah Waterland }
15085c51f124SMoriah Waterland } else {
15095c51f124SMoriah Waterland /* ca file not a regular file! */
15105c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15115c51f124SMoriah Waterland gettext(ERR_NOT_REG),
15125c51f124SMoriah Waterland keystore->capath);
15135c51f124SMoriah Waterland ret = B_FALSE;
15145c51f124SMoriah Waterland goto cleanup;
15155c51f124SMoriah Waterland }
15165c51f124SMoriah Waterland } else {
15175c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15185c51f124SMoriah Waterland gettext(ERR_KEYSTORE_OPEN),
15195c51f124SMoriah Waterland keystore->capath, strerror(errno));
15205c51f124SMoriah Waterland ret = B_FALSE;
15215c51f124SMoriah Waterland goto cleanup;
15225c51f124SMoriah Waterland }
15235c51f124SMoriah Waterland break;
15245c51f124SMoriah Waterland case KEYSTORE_ACCESS_READWRITE:
15255c51f124SMoriah Waterland
15265c51f124SMoriah Waterland if ((keystore->cafd = open(keystore->capath,
15275c51f124SMoriah Waterland O_RDWR|O_NONBLOCK)) == -1) {
15285c51f124SMoriah Waterland /* does not exist. try to create an empty one */
15295c51f124SMoriah Waterland if (errno == ENOENT) {
15305c51f124SMoriah Waterland if ((keystore->cafd =
15315c51f124SMoriah Waterland open(keystore->capath,
15325c51f124SMoriah Waterland O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
15335c51f124SMoriah Waterland S_IRUSR|S_IWUSR)) == -1) {
15345c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15355c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
15365c51f124SMoriah Waterland keystore->capath);
15375c51f124SMoriah Waterland ret = B_FALSE;
15385c51f124SMoriah Waterland goto cleanup;
15395c51f124SMoriah Waterland }
15405c51f124SMoriah Waterland } else {
15415c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15425c51f124SMoriah Waterland gettext(ERR_KEYSTORE_OPEN),
15435c51f124SMoriah Waterland keystore->capath, strerror(errno));
15445c51f124SMoriah Waterland ret = B_FALSE;
15455c51f124SMoriah Waterland goto cleanup;
15465c51f124SMoriah Waterland }
15475c51f124SMoriah Waterland }
15485c51f124SMoriah Waterland if (fstat(keystore->cafd, &buf) != -1) {
15495c51f124SMoriah Waterland if (S_ISREG(buf.st_mode)) {
15505c51f124SMoriah Waterland if (file_lock(keystore->cafd, F_WRLCK,
15515c51f124SMoriah Waterland 0) == -1) {
15525c51f124SMoriah Waterland pkgerr_add(err, PKGERR_LOCKED,
15535c51f124SMoriah Waterland gettext(ERR_KEYSTORE_LOCKED),
15545c51f124SMoriah Waterland keystore->capath);
15555c51f124SMoriah Waterland ret = B_FALSE;
15565c51f124SMoriah Waterland goto cleanup;
15575c51f124SMoriah Waterland }
15585c51f124SMoriah Waterland } else {
15595c51f124SMoriah Waterland /* ca file not a regular file! */
15605c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15615c51f124SMoriah Waterland gettext(ERR_NOT_REG),
15625c51f124SMoriah Waterland keystore->capath);
15635c51f124SMoriah Waterland ret = B_FALSE;
15645c51f124SMoriah Waterland goto cleanup;
15655c51f124SMoriah Waterland }
15665c51f124SMoriah Waterland } else {
15675c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ,
15685c51f124SMoriah Waterland gettext(ERR_KEYSTORE_OPEN),
15695c51f124SMoriah Waterland keystore->capath, strerror(errno));
15705c51f124SMoriah Waterland ret = B_FALSE;
15715c51f124SMoriah Waterland goto cleanup;
15725c51f124SMoriah Waterland }
15735c51f124SMoriah Waterland
15745c51f124SMoriah Waterland break;
15755c51f124SMoriah Waterland default:
15765c51f124SMoriah Waterland pkgerr_add(err, PKGERR_INTERNAL,
15775c51f124SMoriah Waterland gettext(ERR_KEYSTORE_INTERNAL),
15785c51f124SMoriah Waterland __FILE__, __LINE__);
15795c51f124SMoriah Waterland ret = B_FALSE;
15805c51f124SMoriah Waterland goto cleanup;
15815c51f124SMoriah Waterland }
15825c51f124SMoriah Waterland
15835c51f124SMoriah Waterland cleanup:
15845c51f124SMoriah Waterland if (!ret) {
15855c51f124SMoriah Waterland if (keystore->cafd > 0) {
15865c51f124SMoriah Waterland (void) file_unlock(keystore->cafd);
15875c51f124SMoriah Waterland (void) close(keystore->cafd);
15885c51f124SMoriah Waterland keystore->cafd = -1;
15895c51f124SMoriah Waterland }
15905c51f124SMoriah Waterland
15915c51f124SMoriah Waterland if (keystore->capath != NULL)
15925c51f124SMoriah Waterland free(keystore->capath);
15935c51f124SMoriah Waterland if (keystore->clpath != NULL)
15945c51f124SMoriah Waterland free(keystore->clpath);
15955c51f124SMoriah Waterland if (keystore->keypath != NULL)
15965c51f124SMoriah Waterland free(keystore->keypath);
15975c51f124SMoriah Waterland keystore->capath = NULL;
15985c51f124SMoriah Waterland keystore->clpath = NULL;
15995c51f124SMoriah Waterland keystore->keypath = NULL;
16005c51f124SMoriah Waterland }
16015c51f124SMoriah Waterland
16025c51f124SMoriah Waterland return (ret);
16035c51f124SMoriah Waterland }
16045c51f124SMoriah Waterland
16055c51f124SMoriah Waterland /*
16065c51f124SMoriah Waterland * unlock_keystore - Unocks a keystore
16075c51f124SMoriah Waterland *
16085c51f124SMoriah Waterland * Arguments:
16095c51f124SMoriah Waterland * err - Error object to add errors to
16105c51f124SMoriah Waterland * keystore - keystore object to unlock
16115c51f124SMoriah Waterland * Returns:
16125c51f124SMoriah Waterland * 0 - Success - Keystore files are unlocked, files are closed,
16135c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
16145c51f124SMoriah Waterland */
16155c51f124SMoriah Waterland /* ARGSUSED */
16165c51f124SMoriah Waterland static boolean_t
unlock_keystore(PKG_ERR * err,keystore_t * keystore)16175c51f124SMoriah Waterland unlock_keystore(PKG_ERR *err, keystore_t *keystore)
16185c51f124SMoriah Waterland {
16195c51f124SMoriah Waterland
16205c51f124SMoriah Waterland /*
16215c51f124SMoriah Waterland * Release lock on the CA file.
16225c51f124SMoriah Waterland * Delete file if it is empty
16235c51f124SMoriah Waterland */
16245c51f124SMoriah Waterland if (file_empty(keystore->capath)) {
16255c51f124SMoriah Waterland (void) remove(keystore->capath);
16265c51f124SMoriah Waterland }
16275c51f124SMoriah Waterland
16285c51f124SMoriah Waterland (void) file_unlock(keystore->cafd);
16295c51f124SMoriah Waterland (void) close(keystore->cafd);
16305c51f124SMoriah Waterland return (B_TRUE);
16315c51f124SMoriah Waterland }
16325c51f124SMoriah Waterland
16335c51f124SMoriah Waterland /*
16345c51f124SMoriah Waterland * read_keystore - Reads keystore files of disk, parses
16355c51f124SMoriah Waterland * into internal structures.
16365c51f124SMoriah Waterland *
16375c51f124SMoriah Waterland * Arguments:
16385c51f124SMoriah Waterland * err - Error object to add errors to
16395c51f124SMoriah Waterland * keystore - keystore object to read into
16405c51f124SMoriah Waterland * cb - callback to get password, if required
16415c51f124SMoriah Waterland * Returns:
16425c51f124SMoriah Waterland * 0 - Success - Keystore files are read, and placed
16435c51f124SMoriah Waterland * into keystore structure.
16445c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
16455c51f124SMoriah Waterland */
16465c51f124SMoriah Waterland static boolean_t
read_keystore(PKG_ERR * err,keystore_t * keystore,keystore_passphrase_cb cb)16475c51f124SMoriah Waterland read_keystore(PKG_ERR *err, keystore_t *keystore, keystore_passphrase_cb cb)
16485c51f124SMoriah Waterland {
16495c51f124SMoriah Waterland boolean_t ret = B_TRUE;
16505c51f124SMoriah Waterland PKCS12 *p12 = NULL;
16515c51f124SMoriah Waterland boolean_t ca_empty;
16525c51f124SMoriah Waterland boolean_t have_passwd = B_FALSE;
16535c51f124SMoriah Waterland boolean_t cl_empty = B_TRUE;
16545c51f124SMoriah Waterland boolean_t key_empty = B_TRUE;
16555c51f124SMoriah Waterland
16565c51f124SMoriah Waterland ca_empty = file_empty(keystore->capath);
16575c51f124SMoriah Waterland
16585c51f124SMoriah Waterland if (keystore->clpath != NULL)
16595c51f124SMoriah Waterland cl_empty = file_empty(keystore->clpath);
16605c51f124SMoriah Waterland if (keystore->keypath != NULL)
16615c51f124SMoriah Waterland key_empty = file_empty(keystore->keypath);
16625c51f124SMoriah Waterland
16635c51f124SMoriah Waterland if (ca_empty && cl_empty && key_empty) {
16645c51f124SMoriah Waterland keystore->new = B_TRUE;
16655c51f124SMoriah Waterland }
16665c51f124SMoriah Waterland
16675c51f124SMoriah Waterland if (!ca_empty) {
16685c51f124SMoriah Waterland /* first read the ca file */
16695c51f124SMoriah Waterland if ((p12 = read_keystore_file(err,
16705c51f124SMoriah Waterland keystore->capath)) == NULL) {
16715c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
16725c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
16735c51f124SMoriah Waterland ret = B_FALSE;
16745c51f124SMoriah Waterland goto cleanup;
16755c51f124SMoriah Waterland }
16765c51f124SMoriah Waterland
16775c51f124SMoriah Waterland /* Get password, using callback if necessary */
16785c51f124SMoriah Waterland if (!have_passwd) {
16795c51f124SMoriah Waterland if (!get_keystore_passwd(err, p12, cb, keystore)) {
16805c51f124SMoriah Waterland ret = B_FALSE;
16815c51f124SMoriah Waterland goto cleanup;
16825c51f124SMoriah Waterland }
16835c51f124SMoriah Waterland have_passwd = B_TRUE;
16845c51f124SMoriah Waterland }
16855c51f124SMoriah Waterland
16865c51f124SMoriah Waterland /* decrypt and parse keystore file */
16875c51f124SMoriah Waterland if (sunw_PKCS12_contents(p12, keystore->passphrase,
16885c51f124SMoriah Waterland &keystore->pkeys, &keystore->cacerts) < 0) {
16895c51f124SMoriah Waterland /* could not parse the contents */
16905c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
16915c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
16925c51f124SMoriah Waterland ret = B_FALSE;
16935c51f124SMoriah Waterland goto cleanup;
16945c51f124SMoriah Waterland }
16955c51f124SMoriah Waterland
16965c51f124SMoriah Waterland PKCS12_free(p12);
16975c51f124SMoriah Waterland p12 = NULL;
16985c51f124SMoriah Waterland } else {
16995c51f124SMoriah Waterland
17005c51f124SMoriah Waterland /*
17015c51f124SMoriah Waterland * truststore is empty, so we don't have any trusted
17025c51f124SMoriah Waterland * certs
17035c51f124SMoriah Waterland */
17045c51f124SMoriah Waterland keystore->cacerts = NULL;
17055c51f124SMoriah Waterland }
17065c51f124SMoriah Waterland
17075c51f124SMoriah Waterland /*
17085c51f124SMoriah Waterland * if there is no cl file or key file, use the cl's and key's found
17095c51f124SMoriah Waterland * in the ca file
17105c51f124SMoriah Waterland */
17115c51f124SMoriah Waterland if (keystore->clpath == NULL && !ca_empty) {
17125c51f124SMoriah Waterland if (sunw_split_certs(keystore->pkeys, keystore->cacerts,
17135c51f124SMoriah Waterland &keystore->clcerts, NULL) < 0) {
17145c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
17155c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
17165c51f124SMoriah Waterland ret = B_FALSE;
17175c51f124SMoriah Waterland goto cleanup;
17185c51f124SMoriah Waterland }
17195c51f124SMoriah Waterland } else {
17205c51f124SMoriah Waterland /*
17215c51f124SMoriah Waterland * files are in separate files. read keys out of the keystore
17225c51f124SMoriah Waterland * certs out of the certstore, if they are not empty
17235c51f124SMoriah Waterland */
17245c51f124SMoriah Waterland if (!cl_empty) {
17255c51f124SMoriah Waterland if ((p12 = read_keystore_file(err,
17265c51f124SMoriah Waterland keystore->clpath)) == NULL) {
17275c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
17285c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT),
17295c51f124SMoriah Waterland keystore->clpath);
17305c51f124SMoriah Waterland ret = B_FALSE;
17315c51f124SMoriah Waterland goto cleanup;
17325c51f124SMoriah Waterland }
17335c51f124SMoriah Waterland
17345c51f124SMoriah Waterland /* Get password, using callback if necessary */
17355c51f124SMoriah Waterland if (!have_passwd) {
17365c51f124SMoriah Waterland if (!get_keystore_passwd(err, p12, cb,
17375c51f124SMoriah Waterland keystore)) {
17385c51f124SMoriah Waterland ret = B_FALSE;
17395c51f124SMoriah Waterland goto cleanup;
17405c51f124SMoriah Waterland }
17415c51f124SMoriah Waterland have_passwd = B_TRUE;
17425c51f124SMoriah Waterland }
17435c51f124SMoriah Waterland
17445c51f124SMoriah Waterland if (check_password(p12,
17455c51f124SMoriah Waterland keystore->passphrase) == B_FALSE) {
17465c51f124SMoriah Waterland /*
17475c51f124SMoriah Waterland * password in client cert file
17485c51f124SMoriah Waterland * is different than
17495c51f124SMoriah Waterland * the one in the other files!
17505c51f124SMoriah Waterland */
17515c51f124SMoriah Waterland pkgerr_add(err, PKGERR_BADPASS,
17525c51f124SMoriah Waterland gettext(ERR_MISMATCHPASS),
17535c51f124SMoriah Waterland keystore->clpath,
17545c51f124SMoriah Waterland keystore->capath, keystore->path);
17555c51f124SMoriah Waterland ret = B_FALSE;
17565c51f124SMoriah Waterland goto cleanup;
17575c51f124SMoriah Waterland }
17585c51f124SMoriah Waterland
17595c51f124SMoriah Waterland if (sunw_PKCS12_contents(p12, keystore->passphrase,
17605c51f124SMoriah Waterland NULL, &keystore->clcerts) < 0) {
17615c51f124SMoriah Waterland /* could not parse the contents */
17625c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
17635c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT),
17645c51f124SMoriah Waterland keystore->clpath);
17655c51f124SMoriah Waterland ret = B_FALSE;
17665c51f124SMoriah Waterland goto cleanup;
17675c51f124SMoriah Waterland }
17685c51f124SMoriah Waterland
17695c51f124SMoriah Waterland PKCS12_free(p12);
17705c51f124SMoriah Waterland p12 = NULL;
17715c51f124SMoriah Waterland } else {
17725c51f124SMoriah Waterland keystore->clcerts = NULL;
17735c51f124SMoriah Waterland }
17745c51f124SMoriah Waterland
17755c51f124SMoriah Waterland if (!key_empty) {
17765c51f124SMoriah Waterland if ((p12 = read_keystore_file(err,
17775c51f124SMoriah Waterland keystore->keypath)) == NULL) {
17785c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
17795c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT),
17805c51f124SMoriah Waterland keystore->keypath);
17815c51f124SMoriah Waterland ret = B_FALSE;
17825c51f124SMoriah Waterland goto cleanup;
17835c51f124SMoriah Waterland }
17845c51f124SMoriah Waterland
17855c51f124SMoriah Waterland /* Get password, using callback if necessary */
17865c51f124SMoriah Waterland if (!have_passwd) {
17875c51f124SMoriah Waterland if (!get_keystore_passwd(err, p12, cb,
17885c51f124SMoriah Waterland keystore)) {
17895c51f124SMoriah Waterland ret = B_FALSE;
17905c51f124SMoriah Waterland goto cleanup;
17915c51f124SMoriah Waterland }
17925c51f124SMoriah Waterland have_passwd = B_TRUE;
17935c51f124SMoriah Waterland }
17945c51f124SMoriah Waterland
17955c51f124SMoriah Waterland if (check_password(p12,
17965c51f124SMoriah Waterland keystore->passphrase) == B_FALSE) {
17975c51f124SMoriah Waterland pkgerr_add(err, PKGERR_BADPASS,
17985c51f124SMoriah Waterland gettext(ERR_MISMATCHPASS),
17995c51f124SMoriah Waterland keystore->keypath,
18005c51f124SMoriah Waterland keystore->capath, keystore->path);
18015c51f124SMoriah Waterland ret = B_FALSE;
18025c51f124SMoriah Waterland goto cleanup;
18035c51f124SMoriah Waterland }
18045c51f124SMoriah Waterland
18055c51f124SMoriah Waterland if (sunw_PKCS12_contents(p12, keystore->passphrase,
18065c51f124SMoriah Waterland &keystore->pkeys, NULL) < 0) {
18075c51f124SMoriah Waterland /* could not parse the contents */
18085c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
18095c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT),
18105c51f124SMoriah Waterland keystore->keypath);
18115c51f124SMoriah Waterland ret = B_FALSE;
18125c51f124SMoriah Waterland goto cleanup;
18135c51f124SMoriah Waterland }
18145c51f124SMoriah Waterland
18155c51f124SMoriah Waterland PKCS12_free(p12);
18165c51f124SMoriah Waterland p12 = NULL;
18175c51f124SMoriah Waterland } else {
18185c51f124SMoriah Waterland keystore->pkeys = NULL;
18195c51f124SMoriah Waterland }
18205c51f124SMoriah Waterland }
18215c51f124SMoriah Waterland
18225c51f124SMoriah Waterland cleanup:
18235c51f124SMoriah Waterland if (p12 != NULL)
18245c51f124SMoriah Waterland PKCS12_free(p12);
18255c51f124SMoriah Waterland return (ret);
18265c51f124SMoriah Waterland }
18275c51f124SMoriah Waterland
18285c51f124SMoriah Waterland /*
18295c51f124SMoriah Waterland * get_keystore_password - retrieves pasword used to
18305c51f124SMoriah Waterland * decrypt PKCS12 structure.
18315c51f124SMoriah Waterland *
18325c51f124SMoriah Waterland * Arguments:
18335c51f124SMoriah Waterland * err - Error object to add errors to
18345c51f124SMoriah Waterland * p12 - PKCS12 structure which returned password should
18355c51f124SMoriah Waterland * decrypt
18365c51f124SMoriah Waterland * cb - callback to collect password.
18375c51f124SMoriah Waterland * keystore - The keystore in which the PKCS12 structure
18385c51f124SMoriah Waterland * will eventually populate.
18395c51f124SMoriah Waterland * Returns:
18405c51f124SMoriah Waterland * B_TRUE - success.
18415c51f124SMoriah Waterland * keystore password is set in keystore->passphrase.
18425c51f124SMoriah Waterland * B_FALSE - failure, errors logged
18435c51f124SMoriah Waterland */
18445c51f124SMoriah Waterland static boolean_t
get_keystore_passwd(PKG_ERR * err,PKCS12 * p12,keystore_passphrase_cb cb,keystore_t * keystore)18455c51f124SMoriah Waterland get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, keystore_passphrase_cb cb,
18465c51f124SMoriah Waterland keystore_t *keystore)
18475c51f124SMoriah Waterland {
18485c51f124SMoriah Waterland char *passwd;
18495c51f124SMoriah Waterland char passbuf[KEYSTORE_PASS_MAX + 1];
18505c51f124SMoriah Waterland keystore_passphrase_data data;
18515c51f124SMoriah Waterland
18525c51f124SMoriah Waterland /* see if no password is the right password */
18535c51f124SMoriah Waterland if (check_password(p12, "") == B_TRUE) {
18545c51f124SMoriah Waterland passwd = "";
18555c51f124SMoriah Waterland } else if (check_password(p12, NULL) == B_TRUE) {
18565c51f124SMoriah Waterland passwd = NULL;
18575c51f124SMoriah Waterland } else {
18585c51f124SMoriah Waterland /* oops, it's encrypted. get password */
18595c51f124SMoriah Waterland data.err = err;
18605c51f124SMoriah Waterland if (cb(passbuf, KEYSTORE_PASS_MAX, 0,
18615c51f124SMoriah Waterland &data) == -1) {
18625c51f124SMoriah Waterland /* could not get password */
18635c51f124SMoriah Waterland return (B_FALSE);
18645c51f124SMoriah Waterland }
18655c51f124SMoriah Waterland
18665c51f124SMoriah Waterland if (check_password(p12, passbuf) == B_FALSE) {
18675c51f124SMoriah Waterland /* wrong password */
18685c51f124SMoriah Waterland pkgerr_add(err, PKGERR_BADPASS,
18695c51f124SMoriah Waterland gettext(ERR_BADPASS));
18705c51f124SMoriah Waterland return (B_FALSE);
18715c51f124SMoriah Waterland }
18725c51f124SMoriah Waterland
18735c51f124SMoriah Waterland /*
18745c51f124SMoriah Waterland * make copy of password buffer, since it
18755c51f124SMoriah Waterland * goes away upon return
18765c51f124SMoriah Waterland */
18775c51f124SMoriah Waterland passwd = xstrdup(passbuf);
18785c51f124SMoriah Waterland }
18795c51f124SMoriah Waterland keystore->passphrase = passwd;
18805c51f124SMoriah Waterland return (B_TRUE);
18815c51f124SMoriah Waterland }
18825c51f124SMoriah Waterland
18835c51f124SMoriah Waterland /*
18845c51f124SMoriah Waterland * write_keystore - Writes keystore files to disk
18855c51f124SMoriah Waterland *
18865c51f124SMoriah Waterland * Arguments:
18875c51f124SMoriah Waterland * err - Error object to add errors to
18885c51f124SMoriah Waterland * keystore - keystore object to write from
18895c51f124SMoriah Waterland * passwd - password used to encrypt keystore
18905c51f124SMoriah Waterland * Returns:
18915c51f124SMoriah Waterland * 0 - Success - Keystore contents are written out to
18925c51f124SMoriah Waterland * the same locations as read from
18935c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
18945c51f124SMoriah Waterland */
18955c51f124SMoriah Waterland static boolean_t
write_keystore(PKG_ERR * err,keystore_t * keystore,keystore_passphrase_cb cb)18965c51f124SMoriah Waterland write_keystore(PKG_ERR *err, keystore_t *keystore,
18975c51f124SMoriah Waterland keystore_passphrase_cb cb)
18985c51f124SMoriah Waterland {
18995c51f124SMoriah Waterland PKCS12 *p12 = NULL;
19005c51f124SMoriah Waterland boolean_t ret = B_TRUE;
19015c51f124SMoriah Waterland keystore_passphrase_data data;
19025c51f124SMoriah Waterland char passbuf[KEYSTORE_PASS_MAX + 1];
19035c51f124SMoriah Waterland
19045c51f124SMoriah Waterland if (keystore->capath != NULL && keystore->clpath == NULL &&
19055c51f124SMoriah Waterland keystore->keypath == NULL) {
19065c51f124SMoriah Waterland
19075c51f124SMoriah Waterland /*
19085c51f124SMoriah Waterland * keystore is a file.
19095c51f124SMoriah Waterland * just write out a single file
19105c51f124SMoriah Waterland */
19115c51f124SMoriah Waterland if ((keystore->pkeys == NULL) &&
19125c51f124SMoriah Waterland (keystore->clcerts == NULL) &&
19135c51f124SMoriah Waterland (keystore->cacerts == NULL)) {
19145c51f124SMoriah Waterland if (!clear_keystore_file(err, keystore->capath)) {
19155c51f124SMoriah Waterland /*
19165c51f124SMoriah Waterland * no keys or certs to write out, so
19175c51f124SMoriah Waterland * blank the ca file. we do not
19185c51f124SMoriah Waterland * delete it since it is used as a
19195c51f124SMoriah Waterland * lock by lock_keystore() in
19205c51f124SMoriah Waterland * subsequent invocations
19215c51f124SMoriah Waterland */
19225c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
19235c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
19245c51f124SMoriah Waterland keystore->capath);
19255c51f124SMoriah Waterland ret = B_FALSE;
19265c51f124SMoriah Waterland goto cleanup;
19275c51f124SMoriah Waterland }
19285c51f124SMoriah Waterland } else {
19295c51f124SMoriah Waterland /*
19305c51f124SMoriah Waterland * if the keystore is being created for the first time,
19315c51f124SMoriah Waterland * prompt for a passphrase for encryption
19325c51f124SMoriah Waterland */
19335c51f124SMoriah Waterland if (keystore->new) {
19345c51f124SMoriah Waterland data.err = err;
19355c51f124SMoriah Waterland if (cb(passbuf, KEYSTORE_PASS_MAX,
19365c51f124SMoriah Waterland 1, &data) == -1) {
19375c51f124SMoriah Waterland ret = B_FALSE;
19385c51f124SMoriah Waterland goto cleanup;
19395c51f124SMoriah Waterland }
19405c51f124SMoriah Waterland } else {
19415c51f124SMoriah Waterland /*
19425c51f124SMoriah Waterland * use the one used when the keystore
19435c51f124SMoriah Waterland * was read
19445c51f124SMoriah Waterland */
1945*4656d474SGarrett D'Amore (void) strlcpy(passbuf, keystore->passphrase,
19465c51f124SMoriah Waterland KEYSTORE_PASS_MAX);
19475c51f124SMoriah Waterland }
19485c51f124SMoriah Waterland
19495c51f124SMoriah Waterland p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
19505c51f124SMoriah Waterland keystore->clcerts, keystore->cacerts);
19515c51f124SMoriah Waterland
19525c51f124SMoriah Waterland if (p12 == NULL) {
19535c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
19545c51f124SMoriah Waterland gettext(ERR_KEYSTORE_FORM),
19555c51f124SMoriah Waterland keystore->capath);
19565c51f124SMoriah Waterland ret = B_FALSE;
19575c51f124SMoriah Waterland goto cleanup;
19585c51f124SMoriah Waterland }
19595c51f124SMoriah Waterland
19605c51f124SMoriah Waterland if (!write_keystore_file(err, keystore->capath, p12)) {
19615c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
19625c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
19635c51f124SMoriah Waterland keystore->capath);
19645c51f124SMoriah Waterland ret = B_FALSE;
19655c51f124SMoriah Waterland goto cleanup;
19665c51f124SMoriah Waterland }
19675c51f124SMoriah Waterland }
19685c51f124SMoriah Waterland
19695c51f124SMoriah Waterland } else {
19705c51f124SMoriah Waterland /* files are seprate. Do one at a time */
19715c51f124SMoriah Waterland
19725c51f124SMoriah Waterland /*
19735c51f124SMoriah Waterland * if the keystore is being created for the first time,
19745c51f124SMoriah Waterland * prompt for a passphrase for encryption
19755c51f124SMoriah Waterland */
19765c51f124SMoriah Waterland if (keystore->new && ((keystore->pkeys != NULL) ||
19775c51f124SMoriah Waterland (keystore->clcerts != NULL) ||
19785c51f124SMoriah Waterland (keystore->cacerts != NULL))) {
19795c51f124SMoriah Waterland data.err = err;
19805c51f124SMoriah Waterland if (cb(passbuf, KEYSTORE_PASS_MAX,
19815c51f124SMoriah Waterland 1, &data) == -1) {
19825c51f124SMoriah Waterland ret = B_FALSE;
19835c51f124SMoriah Waterland goto cleanup;
19845c51f124SMoriah Waterland }
19855c51f124SMoriah Waterland } else {
19865c51f124SMoriah Waterland /* use the one used when the keystore was read */
1987*4656d474SGarrett D'Amore (void) strlcpy(passbuf, keystore->passphrase,
19885c51f124SMoriah Waterland KEYSTORE_PASS_MAX);
19895c51f124SMoriah Waterland }
19905c51f124SMoriah Waterland
19915c51f124SMoriah Waterland /* do private keys first */
19925c51f124SMoriah Waterland if (keystore->pkeys != NULL) {
19935c51f124SMoriah Waterland p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
19945c51f124SMoriah Waterland NULL, NULL);
19955c51f124SMoriah Waterland
19965c51f124SMoriah Waterland if (p12 == NULL) {
19975c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
19985c51f124SMoriah Waterland gettext(ERR_KEYSTORE_FORM),
19995c51f124SMoriah Waterland keystore->keypath);
20005c51f124SMoriah Waterland ret = B_FALSE;
20015c51f124SMoriah Waterland goto cleanup;
20025c51f124SMoriah Waterland }
20035c51f124SMoriah Waterland
20045c51f124SMoriah Waterland if (!write_keystore_file(err, keystore->keypath,
20055c51f124SMoriah Waterland p12)) {
20065c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20075c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
20085c51f124SMoriah Waterland keystore->keypath);
20095c51f124SMoriah Waterland ret = B_FALSE;
20105c51f124SMoriah Waterland goto cleanup;
20115c51f124SMoriah Waterland }
20125c51f124SMoriah Waterland
20135c51f124SMoriah Waterland PKCS12_free(p12);
20145c51f124SMoriah Waterland } else {
20155c51f124SMoriah Waterland if ((remove(keystore->keypath) != 0) &&
20165c51f124SMoriah Waterland (errno != ENOENT)) {
20175c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20185c51f124SMoriah Waterland gettext(ERR_KEYSTORE_REMOVE),
20195c51f124SMoriah Waterland keystore->keypath);
20205c51f124SMoriah Waterland ret = B_FALSE;
20215c51f124SMoriah Waterland goto cleanup;
20225c51f124SMoriah Waterland }
20235c51f124SMoriah Waterland }
20245c51f124SMoriah Waterland
20255c51f124SMoriah Waterland /* do user certs next */
20265c51f124SMoriah Waterland if (keystore->clcerts != NULL) {
20275c51f124SMoriah Waterland p12 = sunw_PKCS12_create(passbuf, NULL,
20285c51f124SMoriah Waterland keystore->clcerts, NULL);
20295c51f124SMoriah Waterland
20305c51f124SMoriah Waterland if (p12 == NULL) {
20315c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20325c51f124SMoriah Waterland gettext(ERR_KEYSTORE_FORM),
20335c51f124SMoriah Waterland keystore->clpath);
20345c51f124SMoriah Waterland ret = B_FALSE;
20355c51f124SMoriah Waterland goto cleanup;
20365c51f124SMoriah Waterland }
20375c51f124SMoriah Waterland
20385c51f124SMoriah Waterland if (!write_keystore_file(err, keystore->clpath, p12)) {
20395c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20405c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
20415c51f124SMoriah Waterland keystore->clpath);
20425c51f124SMoriah Waterland ret = B_FALSE;
20435c51f124SMoriah Waterland goto cleanup;
20445c51f124SMoriah Waterland }
20455c51f124SMoriah Waterland
20465c51f124SMoriah Waterland PKCS12_free(p12);
20475c51f124SMoriah Waterland } else {
20485c51f124SMoriah Waterland if ((remove(keystore->clpath) != 0) &&
20495c51f124SMoriah Waterland (errno != ENOENT)) {
20505c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20515c51f124SMoriah Waterland gettext(ERR_KEYSTORE_REMOVE),
20525c51f124SMoriah Waterland keystore->clpath);
20535c51f124SMoriah Waterland ret = B_FALSE;
20545c51f124SMoriah Waterland goto cleanup;
20555c51f124SMoriah Waterland }
20565c51f124SMoriah Waterland }
20575c51f124SMoriah Waterland
20585c51f124SMoriah Waterland
20595c51f124SMoriah Waterland /* finally do CA cert file */
20605c51f124SMoriah Waterland if (keystore->cacerts != NULL) {
20615c51f124SMoriah Waterland p12 = sunw_PKCS12_create(passbuf, NULL,
20625c51f124SMoriah Waterland NULL, keystore->cacerts);
20635c51f124SMoriah Waterland
20645c51f124SMoriah Waterland if (p12 == NULL) {
20655c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20665c51f124SMoriah Waterland gettext(ERR_KEYSTORE_FORM),
20675c51f124SMoriah Waterland keystore->capath);
20685c51f124SMoriah Waterland ret = B_FALSE;
20695c51f124SMoriah Waterland goto cleanup;
20705c51f124SMoriah Waterland }
20715c51f124SMoriah Waterland
20725c51f124SMoriah Waterland if (!write_keystore_file(err, keystore->capath, p12)) {
20735c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20745c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
20755c51f124SMoriah Waterland keystore->capath);
20765c51f124SMoriah Waterland ret = B_FALSE;
20775c51f124SMoriah Waterland goto cleanup;
20785c51f124SMoriah Waterland }
20795c51f124SMoriah Waterland
20805c51f124SMoriah Waterland PKCS12_free(p12);
20815c51f124SMoriah Waterland p12 = NULL;
20825c51f124SMoriah Waterland } else {
20835c51f124SMoriah Waterland /*
20845c51f124SMoriah Waterland * nothing to write out, so truncate the file
20855c51f124SMoriah Waterland * (it will be deleted during close_keystore)
20865c51f124SMoriah Waterland */
20875c51f124SMoriah Waterland if (!clear_keystore_file(err, keystore->capath)) {
20885c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE,
20895c51f124SMoriah Waterland gettext(ERR_KEYSTORE_WRITE),
20905c51f124SMoriah Waterland keystore->capath);
20915c51f124SMoriah Waterland ret = B_FALSE;
20925c51f124SMoriah Waterland goto cleanup;
20935c51f124SMoriah Waterland }
20945c51f124SMoriah Waterland }
20955c51f124SMoriah Waterland }
20965c51f124SMoriah Waterland
20975c51f124SMoriah Waterland cleanup:
20985c51f124SMoriah Waterland if (p12 != NULL)
20995c51f124SMoriah Waterland PKCS12_free(p12);
21005c51f124SMoriah Waterland
21015c51f124SMoriah Waterland return (ret);
21025c51f124SMoriah Waterland }
21035c51f124SMoriah Waterland
21045c51f124SMoriah Waterland /*
21055c51f124SMoriah Waterland * clear_keystore_file - Clears (zeros out) a keystore file.
21065c51f124SMoriah Waterland *
21075c51f124SMoriah Waterland * Arguments:
21085c51f124SMoriah Waterland * err - Error object to add errors to
21095c51f124SMoriah Waterland * dest - Path of keystore file to zero out.
21105c51f124SMoriah Waterland * Returns:
21115c51f124SMoriah Waterland * 0 - Success - Keystore file is truncated to zero length
21125c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
21135c51f124SMoriah Waterland */
21145c51f124SMoriah Waterland static boolean_t
clear_keystore_file(PKG_ERR * err,char * dest)21155c51f124SMoriah Waterland clear_keystore_file(PKG_ERR *err, char *dest)
21165c51f124SMoriah Waterland {
21175c51f124SMoriah Waterland int fd;
21185c51f124SMoriah Waterland struct stat buf;
21195c51f124SMoriah Waterland
21205c51f124SMoriah Waterland fd = open(dest, O_RDWR|O_NONBLOCK);
21215c51f124SMoriah Waterland if (fd == -1) {
21225c51f124SMoriah Waterland /* can't open for writing */
21235c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE, gettext(MSG_OPEN),
21245c51f124SMoriah Waterland errno);
21255c51f124SMoriah Waterland return (B_FALSE);
21265c51f124SMoriah Waterland }
21275c51f124SMoriah Waterland
21285c51f124SMoriah Waterland if ((fstat(fd, &buf) == -1) || !S_ISREG(buf.st_mode)) {
21295c51f124SMoriah Waterland /* not a regular file */
21305c51f124SMoriah Waterland (void) close(fd);
21315c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE, gettext(ERR_NOT_REG),
21325c51f124SMoriah Waterland dest);
21335c51f124SMoriah Waterland return (B_FALSE);
21345c51f124SMoriah Waterland }
21355c51f124SMoriah Waterland
21365c51f124SMoriah Waterland if (ftruncate(fd, 0) == -1) {
21375c51f124SMoriah Waterland (void) close(fd);
21385c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE, gettext(ERR_WRITE),
21395c51f124SMoriah Waterland dest, strerror(errno));
21405c51f124SMoriah Waterland return (B_FALSE);
21415c51f124SMoriah Waterland }
21425c51f124SMoriah Waterland
21435c51f124SMoriah Waterland (void) close(fd);
21445c51f124SMoriah Waterland return (B_TRUE);
21455c51f124SMoriah Waterland }
21465c51f124SMoriah Waterland
21475c51f124SMoriah Waterland /*
21485c51f124SMoriah Waterland * write_keystore_file - Writes keystore file to disk.
21495c51f124SMoriah Waterland *
21505c51f124SMoriah Waterland * Keystore files can possibly be corrupted by a variety
21515c51f124SMoriah Waterland * of error conditions during reading/writing. This
21525c51f124SMoriah Waterland * routine, along with restore_keystore_file, tries to
21535c51f124SMoriah Waterland * maintain keystore integity by writing the files
21545c51f124SMoriah Waterland * out in a particular order, minimizing the time period
21555c51f124SMoriah Waterland * that the keystore is in an indeterminate state.
21565c51f124SMoriah Waterland *
21575c51f124SMoriah Waterland * With the current implementation, there are some failures
21585c51f124SMoriah Waterland * that are wholly unrecoverable, such as disk corruption.
21595c51f124SMoriah Waterland * These routines attempt to minimize the risk, but not
21605c51f124SMoriah Waterland * eliminate it. When better, atomic operations are available
21615c51f124SMoriah Waterland * (such as a true database with commit, rollback, and
21625c51f124SMoriah Waterland * guaranteed atomicity), this implementation should use that.
21635c51f124SMoriah Waterland *
21645c51f124SMoriah Waterland *
21655c51f124SMoriah Waterland * Arguments:
21665c51f124SMoriah Waterland * err - Error object to add errors to
21675c51f124SMoriah Waterland * dest - Destination filename
21685c51f124SMoriah Waterland * contents - Contents to write to the file
21695c51f124SMoriah Waterland * Returns:
21705c51f124SMoriah Waterland * 0 - Success - Keystore contents are written out to
21715c51f124SMoriah Waterland * the destination.
21725c51f124SMoriah Waterland * non-zero - Failure, errors and reasons recorded in err
21735c51f124SMoriah Waterland */
21745c51f124SMoriah Waterland static boolean_t
write_keystore_file(PKG_ERR * err,char * dest,PKCS12 * contents)21755c51f124SMoriah Waterland write_keystore_file(PKG_ERR *err, char *dest, PKCS12 *contents)
21765c51f124SMoriah Waterland {
21775c51f124SMoriah Waterland FILE *newfile = NULL;
21785c51f124SMoriah Waterland boolean_t ret = B_TRUE;
21795c51f124SMoriah Waterland char newpath[MAXPATHLEN];
21805c51f124SMoriah Waterland char backuppath[MAXPATHLEN];
21815c51f124SMoriah Waterland struct stat buf;
21825c51f124SMoriah Waterland int fd;
21835c51f124SMoriah Waterland
21845c51f124SMoriah Waterland (void) snprintf(newpath, MAXPATHLEN, "%s.new", dest);
21855c51f124SMoriah Waterland (void) snprintf(backuppath, MAXPATHLEN, "%s.bak", dest);
21865c51f124SMoriah Waterland
21875c51f124SMoriah Waterland if ((fd = open(newpath, O_CREAT|O_EXCL|O_WRONLY|O_NONBLOCK,
21885c51f124SMoriah Waterland S_IRUSR|S_IWUSR)) == -1) {
21895c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
21905c51f124SMoriah Waterland newpath, strerror(errno));
21915c51f124SMoriah Waterland ret = B_FALSE;
21925c51f124SMoriah Waterland goto cleanup;
21935c51f124SMoriah Waterland }
21945c51f124SMoriah Waterland
21955c51f124SMoriah Waterland if (fstat(fd, &buf) == -1) {
21965c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
21975c51f124SMoriah Waterland newpath, strerror(errno));
21985c51f124SMoriah Waterland ret = B_FALSE;
21995c51f124SMoriah Waterland goto cleanup;
22005c51f124SMoriah Waterland }
22015c51f124SMoriah Waterland
22025c51f124SMoriah Waterland if (!S_ISREG(buf.st_mode)) {
22035c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
22045c51f124SMoriah Waterland newpath);
22055c51f124SMoriah Waterland ret = B_FALSE;
22065c51f124SMoriah Waterland goto cleanup;
22075c51f124SMoriah Waterland }
22085c51f124SMoriah Waterland
22095c51f124SMoriah Waterland if ((newfile = fdopen(fd, "w")) == NULL) {
22105c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
22115c51f124SMoriah Waterland newpath, strerror(errno));
22125c51f124SMoriah Waterland ret = B_FALSE;
22135c51f124SMoriah Waterland goto cleanup;
22145c51f124SMoriah Waterland }
22155c51f124SMoriah Waterland
22165c51f124SMoriah Waterland if (i2d_PKCS12_fp(newfile, contents) == 0) {
22175c51f124SMoriah Waterland pkgerr_add(err, PKGERR_WRITE, gettext(ERR_KEYSTORE_WRITE),
22185c51f124SMoriah Waterland newpath);
22195c51f124SMoriah Waterland ret = B_FALSE;
22205c51f124SMoriah Waterland goto cleanup;
22215c51f124SMoriah Waterland }
22225c51f124SMoriah Waterland
22235c51f124SMoriah Waterland /* flush, then close */
22245c51f124SMoriah Waterland (void) fflush(newfile);
22255c51f124SMoriah Waterland (void) fclose(newfile);
22265c51f124SMoriah Waterland newfile = NULL;
22275c51f124SMoriah Waterland
22285c51f124SMoriah Waterland /* now back up the original file */
22295c51f124SMoriah Waterland (void) rename(dest, backuppath);
22305c51f124SMoriah Waterland
22315c51f124SMoriah Waterland /* put new one in its place */
22325c51f124SMoriah Waterland (void) rename(newpath, dest);
22335c51f124SMoriah Waterland
22345c51f124SMoriah Waterland /* remove backup */
22355c51f124SMoriah Waterland (void) remove(backuppath);
22365c51f124SMoriah Waterland
22375c51f124SMoriah Waterland cleanup:
22385c51f124SMoriah Waterland if (newfile != NULL)
22395c51f124SMoriah Waterland (void) fclose(newfile);
22405c51f124SMoriah Waterland if (fd != -1)
22415c51f124SMoriah Waterland (void) close(fd);
22425c51f124SMoriah Waterland
22435c51f124SMoriah Waterland return (ret);
22445c51f124SMoriah Waterland }
22455c51f124SMoriah Waterland
22465c51f124SMoriah Waterland /*
22475c51f124SMoriah Waterland * read_keystore_file - Reads single keystore file
22485c51f124SMoriah Waterland * off disk in PKCS12 format.
22495c51f124SMoriah Waterland *
22505c51f124SMoriah Waterland * Arguments:
22515c51f124SMoriah Waterland * err - Error object to add errors to
22525c51f124SMoriah Waterland * file - File path to read
22535c51f124SMoriah Waterland * Returns:
22545c51f124SMoriah Waterland * PKCS12 contents of file, or NULL if an error occurred.
22555c51f124SMoriah Waterland * errors recorded in 'err'.
22565c51f124SMoriah Waterland */
22575c51f124SMoriah Waterland static PKCS12
read_keystore_file(PKG_ERR * err,char * file)22585c51f124SMoriah Waterland *read_keystore_file(PKG_ERR *err, char *file)
22595c51f124SMoriah Waterland {
22605c51f124SMoriah Waterland int fd;
22615c51f124SMoriah Waterland struct stat buf;
22625c51f124SMoriah Waterland FILE *newfile;
22635c51f124SMoriah Waterland PKCS12 *p12 = NULL;
22645c51f124SMoriah Waterland
22655c51f124SMoriah Waterland if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
22665c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
22675c51f124SMoriah Waterland file, strerror(errno));
22685c51f124SMoriah Waterland goto cleanup;
22695c51f124SMoriah Waterland }
22705c51f124SMoriah Waterland
22715c51f124SMoriah Waterland if (fstat(fd, &buf) == -1) {
22725c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
22735c51f124SMoriah Waterland file, strerror(errno));
22745c51f124SMoriah Waterland goto cleanup;
22755c51f124SMoriah Waterland }
22765c51f124SMoriah Waterland
22775c51f124SMoriah Waterland if (!S_ISREG(buf.st_mode)) {
22785c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
22795c51f124SMoriah Waterland file);
22805c51f124SMoriah Waterland goto cleanup;
22815c51f124SMoriah Waterland }
22825c51f124SMoriah Waterland
22835c51f124SMoriah Waterland if ((newfile = fdopen(fd, "r")) == NULL) {
22845c51f124SMoriah Waterland pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
22855c51f124SMoriah Waterland file, strerror(errno));
22865c51f124SMoriah Waterland goto cleanup;
22875c51f124SMoriah Waterland }
22885c51f124SMoriah Waterland
22895c51f124SMoriah Waterland if ((p12 = d2i_PKCS12_fp(newfile, NULL)) == NULL) {
22905c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CORRUPT,
22915c51f124SMoriah Waterland gettext(ERR_KEYSTORE_CORRUPT), file);
22925c51f124SMoriah Waterland goto cleanup;
22935c51f124SMoriah Waterland }
22945c51f124SMoriah Waterland
22955c51f124SMoriah Waterland cleanup:
22965c51f124SMoriah Waterland if (newfile != NULL)
22975c51f124SMoriah Waterland (void) fclose(newfile);
22985c51f124SMoriah Waterland if (fd != -1)
22995c51f124SMoriah Waterland (void) close(fd);
23005c51f124SMoriah Waterland
23015c51f124SMoriah Waterland return (p12);
23025c51f124SMoriah Waterland }
23035c51f124SMoriah Waterland
23045c51f124SMoriah Waterland
23055c51f124SMoriah Waterland /*
23065c51f124SMoriah Waterland * Locks the specified file.
23075c51f124SMoriah Waterland */
23085c51f124SMoriah Waterland static int
file_lock(int fd,int type,int wait)23095c51f124SMoriah Waterland file_lock(int fd, int type, int wait)
23105c51f124SMoriah Waterland {
23115c51f124SMoriah Waterland struct flock lock;
23125c51f124SMoriah Waterland
23135c51f124SMoriah Waterland lock.l_type = type;
23145c51f124SMoriah Waterland lock.l_start = 0;
23155c51f124SMoriah Waterland lock.l_whence = SEEK_SET;
23165c51f124SMoriah Waterland lock.l_len = 0;
23175c51f124SMoriah Waterland
23185c51f124SMoriah Waterland if (!wait) {
23195c51f124SMoriah Waterland if (file_lock_test(fd, type)) {
23205c51f124SMoriah Waterland /*
23215c51f124SMoriah Waterland * The caller would have to wait to get the
23225c51f124SMoriah Waterland * lock on this file.
23235c51f124SMoriah Waterland */
23245c51f124SMoriah Waterland return (-1);
23255c51f124SMoriah Waterland }
23265c51f124SMoriah Waterland }
23275c51f124SMoriah Waterland
23285c51f124SMoriah Waterland return (fcntl(fd, F_SETLKW, &lock));
23295c51f124SMoriah Waterland }
23305c51f124SMoriah Waterland
23315c51f124SMoriah Waterland /*
23325c51f124SMoriah Waterland * Returns FALSE if the file is not locked; TRUE
23335c51f124SMoriah Waterland * otherwise.
23345c51f124SMoriah Waterland */
23355c51f124SMoriah Waterland static boolean_t
file_lock_test(int fd,int type)23365c51f124SMoriah Waterland file_lock_test(int fd, int type)
23375c51f124SMoriah Waterland {
23385c51f124SMoriah Waterland struct flock lock;
23395c51f124SMoriah Waterland
23405c51f124SMoriah Waterland lock.l_type = type;
23415c51f124SMoriah Waterland lock.l_start = 0;
23425c51f124SMoriah Waterland lock.l_whence = SEEK_SET;
23435c51f124SMoriah Waterland lock.l_len = 0;
23445c51f124SMoriah Waterland
23455c51f124SMoriah Waterland if (fcntl(fd, F_GETLK, &lock) != -1) {
23465c51f124SMoriah Waterland if (lock.l_type != F_UNLCK) {
23475c51f124SMoriah Waterland /*
23485c51f124SMoriah Waterland * The caller would have to wait to get the
23495c51f124SMoriah Waterland * lock on this file.
23505c51f124SMoriah Waterland */
23515c51f124SMoriah Waterland return (B_TRUE);
23525c51f124SMoriah Waterland }
23535c51f124SMoriah Waterland }
23545c51f124SMoriah Waterland
23555c51f124SMoriah Waterland /*
23565c51f124SMoriah Waterland * The file is not locked.
23575c51f124SMoriah Waterland */
23585c51f124SMoriah Waterland return (B_FALSE);
23595c51f124SMoriah Waterland }
23605c51f124SMoriah Waterland
23615c51f124SMoriah Waterland /*
23625c51f124SMoriah Waterland * Unlocks the specified file.
23635c51f124SMoriah Waterland */
23645c51f124SMoriah Waterland static int
file_unlock(int fd)23655c51f124SMoriah Waterland file_unlock(int fd)
23665c51f124SMoriah Waterland {
23675c51f124SMoriah Waterland struct flock lock;
23685c51f124SMoriah Waterland
23695c51f124SMoriah Waterland lock.l_type = F_UNLCK;
23705c51f124SMoriah Waterland lock.l_start = 0;
23715c51f124SMoriah Waterland lock.l_whence = SEEK_SET;
23725c51f124SMoriah Waterland lock.l_len = 0;
23735c51f124SMoriah Waterland
23745c51f124SMoriah Waterland return (fcntl(fd, F_SETLK, &lock));
23755c51f124SMoriah Waterland }
23765c51f124SMoriah Waterland
23775c51f124SMoriah Waterland /*
23785c51f124SMoriah Waterland * Determines if file has a length of 0 or not
23795c51f124SMoriah Waterland */
23805c51f124SMoriah Waterland static boolean_t
file_empty(char * path)23815c51f124SMoriah Waterland file_empty(char *path)
23825c51f124SMoriah Waterland {
23835c51f124SMoriah Waterland struct stat buf;
23845c51f124SMoriah Waterland
23855c51f124SMoriah Waterland /* file is empty if size = 0 or it doesn't exist */
23865c51f124SMoriah Waterland if (lstat(path, &buf) == 0) {
23875c51f124SMoriah Waterland if (buf.st_size == 0) {
23885c51f124SMoriah Waterland return (B_TRUE);
23895c51f124SMoriah Waterland }
23905c51f124SMoriah Waterland } else {
23915c51f124SMoriah Waterland if (errno == ENOENT) {
23925c51f124SMoriah Waterland return (B_TRUE);
23935c51f124SMoriah Waterland }
23945c51f124SMoriah Waterland }
23955c51f124SMoriah Waterland
23965c51f124SMoriah Waterland return (B_FALSE);
23975c51f124SMoriah Waterland }
23985c51f124SMoriah Waterland
23995c51f124SMoriah Waterland /*
24005c51f124SMoriah Waterland * Name: get_time_string
24015c51f124SMoriah Waterland * Description: Generates a human-readable string from an ASN1_TIME
24025c51f124SMoriah Waterland *
24035c51f124SMoriah Waterland * Arguments: intime - The time to convert
24045c51f124SMoriah Waterland *
24055c51f124SMoriah Waterland * Returns : A pointer to a static string representing the passed-in time.
24065c51f124SMoriah Waterland */
24075c51f124SMoriah Waterland static char
get_time_string(ASN1_TIME * intime)24085c51f124SMoriah Waterland *get_time_string(ASN1_TIME *intime)
24095c51f124SMoriah Waterland {
24105c51f124SMoriah Waterland
24115c51f124SMoriah Waterland static char time[ATTR_MAX];
24125c51f124SMoriah Waterland BIO *mem;
24135c51f124SMoriah Waterland char *p;
24145c51f124SMoriah Waterland
24155c51f124SMoriah Waterland if (intime == NULL) {
24165c51f124SMoriah Waterland return (NULL);
24175c51f124SMoriah Waterland }
24185c51f124SMoriah Waterland if ((mem = BIO_new(BIO_s_mem())) == NULL) {
24195c51f124SMoriah Waterland return (NULL);
24205c51f124SMoriah Waterland }
24215c51f124SMoriah Waterland
24225c51f124SMoriah Waterland if (ASN1_TIME_print(mem, intime) == 0) {
24235c51f124SMoriah Waterland (void) BIO_free(mem);
24245c51f124SMoriah Waterland return (NULL);
24255c51f124SMoriah Waterland }
24265c51f124SMoriah Waterland
24275c51f124SMoriah Waterland if (BIO_gets(mem, time, ATTR_MAX) <= 0) {
24285c51f124SMoriah Waterland (void) BIO_free(mem);
24295c51f124SMoriah Waterland return (NULL);
24305c51f124SMoriah Waterland }
24315c51f124SMoriah Waterland
24325c51f124SMoriah Waterland (void) BIO_free(mem);
24335c51f124SMoriah Waterland
24345c51f124SMoriah Waterland /* trim the end of the string */
24355c51f124SMoriah Waterland for (p = time + strlen(time) - 1; isspace(*p); p--) {
24365c51f124SMoriah Waterland *p = '\0';
24375c51f124SMoriah Waterland }
24385c51f124SMoriah Waterland
24395c51f124SMoriah Waterland return (time);
24405c51f124SMoriah Waterland }
24415c51f124SMoriah Waterland
24425c51f124SMoriah Waterland /*
24435c51f124SMoriah Waterland * check_password - do various password checks to see if the current password
24445c51f124SMoriah Waterland * will work or we need to prompt for a new one.
24455c51f124SMoriah Waterland *
24465c51f124SMoriah Waterland * Arguments:
24475c51f124SMoriah Waterland * pass - password to check
24485c51f124SMoriah Waterland *
24495c51f124SMoriah Waterland * Returns:
24505c51f124SMoriah Waterland * B_TRUE - Password is OK.
24515c51f124SMoriah Waterland * B_FALSE - Password not valid.
24525c51f124SMoriah Waterland */
24535c51f124SMoriah Waterland static boolean_t
check_password(PKCS12 * p12,char * pass)24545c51f124SMoriah Waterland check_password(PKCS12 *p12, char *pass)
24555c51f124SMoriah Waterland {
24565c51f124SMoriah Waterland boolean_t ret = B_TRUE;
24575c51f124SMoriah Waterland
24585c51f124SMoriah Waterland /*
24595c51f124SMoriah Waterland * If password is zero length or NULL then try verifying both cases
24605c51f124SMoriah Waterland * to determine which password is correct. The reason for this is that
24615c51f124SMoriah Waterland * under PKCS#12 password based encryption no password and a zero
24625c51f124SMoriah Waterland * length password are two different things...
24635c51f124SMoriah Waterland */
24645c51f124SMoriah Waterland
24655c51f124SMoriah Waterland /* Check the mac */
24665c51f124SMoriah Waterland if (pass == NULL || *pass == '\0') {
24675c51f124SMoriah Waterland if (PKCS12_verify_mac(p12, NULL, 0) == 0 &&
24685c51f124SMoriah Waterland PKCS12_verify_mac(p12, "", 0) == 0)
24695c51f124SMoriah Waterland ret = B_FALSE;
24705c51f124SMoriah Waterland } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
24715c51f124SMoriah Waterland ret = B_FALSE;
24725c51f124SMoriah Waterland }
24735c51f124SMoriah Waterland return (ret);
24745c51f124SMoriah Waterland }
2475