summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpkg/common/keystore.c
diff options
context:
space:
mode:
authorPeter Tribble <peter.tribble@gmail.com>2017-03-13 20:25:34 +0000
committerGordon Ross <gwr@nexenta.com>2017-03-29 19:13:24 -0400
commit32991bedc3a6475f1401855c2318ae5b15f8a16b (patch)
tree3360e7844885746ed96019a9e3a42cd7e5e73409 /usr/src/lib/libpkg/common/keystore.c
parent4383d9578c9d399b19edc33e552a4c543ebf9468 (diff)
downloadillumos-gate-32991bedc3a6475f1401855c2318ae5b15f8a16b.tar.gz
5188 SVR4 packaging shouldn't depend on openssl or libwanboot
Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Alexander Eremin <alexander.r.eremin@gmail.com> Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src/lib/libpkg/common/keystore.c')
-rw-r--r--usr/src/lib/libpkg/common/keystore.c2474
1 files changed, 0 insertions, 2474 deletions
diff --git a/usr/src/lib/libpkg/common/keystore.c b/usr/src/lib/libpkg/common/keystore.c
deleted file mode 100644
index 633c04b58e..0000000000
--- a/usr/src/lib/libpkg/common/keystore.c
+++ /dev/null
@@ -1,2474 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Module: keystore.c
- * Description: This module contains the structure definitions for processing
- * package keystore files.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <strings.h>
-#include <libintl.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs12.h>
-#include <openssl/asn1.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/safestack.h>
-#include <openssl/stack.h>
-#include "p12lib.h"
-#include "pkgerr.h"
-#include "keystore.h"
-#include "pkglib.h"
-#include "pkglibmsgs.h"
-
-typedef struct keystore_t {
- boolean_t dirty;
- boolean_t new;
- char *path;
- char *passphrase;
- /* truststore handles */
- int cafd;
- STACK_OF(X509) *cacerts;
- char *capath;
-
- /* user certificate handles */
- STACK_OF(X509) *clcerts;
- char *clpath;
-
- /* private key handles */
- STACK_OF(EVP_PKEY) *pkeys;
- char *keypath;
-} keystore_t;
-
-/* local routines */
-static keystore_t *new_keystore(void);
-static void free_keystore(keystore_t *);
-static boolean_t verify_keystore_integrity(PKG_ERR *, keystore_t *);
-static boolean_t check_password(PKCS12 *, char *);
-static boolean_t resolve_paths(PKG_ERR *, char *, char *,
- long, keystore_t *);
-static boolean_t lock_keystore(PKG_ERR *, long, keystore_t *);
-
-static boolean_t unlock_keystore(PKG_ERR *, keystore_t *);
-static boolean_t read_keystore(PKG_ERR *, keystore_t *,
- keystore_passphrase_cb);
-static boolean_t write_keystore(PKG_ERR *, keystore_t *,
- keystore_passphrase_cb);
-static boolean_t write_keystore_file(PKG_ERR *, char *, PKCS12 *);
-static boolean_t clear_keystore_file(PKG_ERR *, char *);
-static PKCS12 *read_keystore_file(PKG_ERR *, char *);
-static char *get_time_string(ASN1_TIME *);
-
-/* locking routines */
-static boolean_t restore_keystore_file(PKG_ERR *, char *);
-static int file_lock(int, int, int);
-static int file_unlock(int);
-static boolean_t file_lock_test(int, int);
-static boolean_t file_empty(char *);
-static boolean_t get_keystore_passwd(PKG_ERR *err, PKCS12 *p12,
- keystore_passphrase_cb cb, keystore_t *keystore);
-static boolean_t wait_restore(int, char *, char *, char *);
-
-#define KEYSTORE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
-
-/* wait on other keystore access for 1 minute before giving up */
-#define LOCK_TIMEOUT 60
-
-/*
- * print_certs - prints certificates out of a keystore, to a file.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore - Keystore on which to operate
- * alias - Name of certificate to print, NULL means print all
- * format - Format in which to print certificates
- * outfile - Where to print certificates
- *
- * Returns:
- * 0 - Success
- * non-zero - Failure, errors added to err
- */
-int
-print_certs(PKG_ERR *err, keystore_handle_t keystore_h, char *alias,
- keystore_encoding_format_t format, FILE *outfile)
-{
- int i;
- X509 *cert;
- char *fname = NULL;
- boolean_t found = B_FALSE;
- keystore_t *keystore = keystore_h;
-
- if (keystore->clcerts != NULL) {
- /* print out each client cert */
- for (i = 0; i < sk_X509_num(keystore->clcerts); i++) {
- cert = sk_X509_value(keystore->clcerts, i);
- (void) sunw_get_cert_fname(GETDO_COPY, cert,
- &fname);
-
- if (fname == NULL) {
- /* no name recorded, keystore is corrupt */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_NO_ALIAS),
- get_subject_display_name(cert));
- return (1);
- }
-
- if ((alias != NULL) && (!streq(alias, fname))) {
- /* name does not match, skip it */
- (void) OPENSSL_free(fname);
- fname = NULL;
- continue;
- } else {
- found = B_TRUE;
- (void) print_cert(err, cert, format,
- fname, B_FALSE, outfile);
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- }
-
- if (fname != NULL) {
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
-
- if (keystore->cacerts != NULL) {
- /* print out each trusted cert */
- for (i = 0; i < sk_X509_num(keystore->cacerts); i++) {
- cert = sk_X509_value(keystore->cacerts, i);
- (void) sunw_get_cert_fname(GETDO_COPY,
- cert, &fname);
-
- if (fname == NULL) {
- /* no name recorded, keystore is corrupt */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_NO_ALIAS),
- get_subject_display_name(cert));
- return (1);
- }
-
- if ((alias != NULL) && (!streq(alias, fname))) {
- /* name does not match, skip it */
- (void) OPENSSL_free(fname);
- fname = NULL;
- continue;
- } else {
- found = B_TRUE;
- (void) print_cert(err, cert, format,
- fname, B_TRUE, outfile);
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- }
-
- if (fname != NULL) {
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
-
- if (found) {
- return (0);
- } else {
- /* no certs printed */
- if (alias != NULL) {
- pkgerr_add(err, PKGERR_NOALIASMATCH,
- gettext(ERR_KEYSTORE_NOCERT),
- alias, keystore->path);
- } else {
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOPUBCERTS),
- keystore->path);
- pkgerr_add(err, PKGERR_NOCACERT,
- gettext(ERR_KEYSTORE_NOCACERTS),
- keystore->path);
- }
- return (1);
- }
-}
-
-/*
- * print_cert - prints a single certificate, to a file
- *
- * Arguments:
- * err - Error object to append errors to
- * x - The certificate to print
- * alias - Name of certificate to print
- * format - Format in which to print certificate
- * outfile - Where to print certificate
- *
- * Returns:
- * 0 - Success
- * non-zero - Failure, errors added to err
- */
-int print_cert(PKG_ERR *err, X509 *x,
- keystore_encoding_format_t format, char *alias, boolean_t is_trusted,
- FILE *outfile)
-{
-
- char *vdb_str;
- char *vda_str;
- char vd_str[ATTR_MAX];
- int ret = 0;
- char *cn_str, *icn_str, *typ_str;
- char *tmp;
- char *md5_fp;
- char *sha1_fp;
- int len;
-
- /* need to localize the word "Fingerprint", hence these pointers */
- char md5_label[ATTR_MAX];
- char sha1_label[ATTR_MAX];
-
- if (is_trusted) {
- typ_str = gettext(MSG_KEYSTORE_TRUSTED);
- } else {
- typ_str = gettext(MSG_KEYSTORE_UNTRUSTED);
- }
-
- if ((cn_str = get_subject_display_name(x)) == NULL) {
- cn_str = gettext(MSG_KEYSTORE_UNKNOWN);
- }
-
- if ((icn_str = get_issuer_display_name(x)) == NULL) {
- icn_str = gettext(MSG_KEYSTORE_UNKNOWN);
- }
-
- vdb_str = xstrdup(get_time_string(X509_get_notBefore(x)));
- vda_str = xstrdup(get_time_string(X509_get_notAfter(x)));
- if (((len = snprintf(vd_str, ATTR_MAX, "<%s> - <%s>",
- vdb_str, vda_str)) < 0) || (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), vdb_str);
- ret = 1;
- goto cleanup;
- }
-
- if ((tmp = get_fingerprint(x, EVP_md5())) == NULL) {
- md5_fp = gettext(MSG_KEYSTORE_UNKNOWN);
- } else {
- /*
- * make a copy, otherwise the next call to get_fingerprint
- * will overwrite this one
- */
- md5_fp = xstrdup(tmp);
- }
-
- if ((tmp = get_fingerprint(x, EVP_sha1())) == NULL) {
- sha1_fp = gettext(MSG_KEYSTORE_UNKNOWN);
- } else {
- sha1_fp = xstrdup(tmp);
- }
-
- (void) snprintf(md5_label, ATTR_MAX, "%s %s",
- OBJ_nid2sn(EVP_MD_type(EVP_md5())),
- /* i18n: 14 characters max */
- gettext(MSG_KEYSTORE_FP));
-
- (void) snprintf(sha1_label, ATTR_MAX, "%s %s",
- OBJ_nid2sn(EVP_MD_type(EVP_sha1())),
- /* i18n: 14 characters max */
- gettext(MSG_KEYSTORE_FP));
-
- switch (format) {
- case KEYSTORE_FORMAT_PEM:
- (void) PEM_write_X509(outfile, x);
- break;
- case KEYSTORE_FORMAT_DER:
- (void) i2d_X509_fp(outfile, x);
- break;
- case KEYSTORE_FORMAT_TEXT:
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_AL), alias);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_CN), cn_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_TY), typ_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_IN), icn_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_VD), vd_str);
- (void) fprintf(outfile, "%18s: %s\n", md5_label, md5_fp);
- (void) fprintf(outfile, "%18s: %s\n", sha1_label, sha1_fp);
- (void) fprintf(outfile, "\n");
- break;
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ret = 1;
- goto cleanup;
- }
-
-cleanup:
- if (md5_fp != NULL)
- free(md5_fp);
- if (sha1_fp != NULL)
- free(sha1_fp);
- if (vda_str != NULL)
- free(vda_str);
- if (vdb_str != NULL)
- free(vdb_str);
- return (ret);
-}
-
-/*
- * open_keystore - Initialize new keystore object for
- * impending access.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore_file - Base filename or directory of keystore
- * app - Application making request
- * passwd - Password used to decrypt keystore
- * flags - Control flags used to control access mode and behavior
- * result - Resulting keystore object stored here on success
- *
- * Returns:
- * 0 - Success - result contains a pointer to the opened keystore
- * non-zero - Failure, errors added to err
- */
-int
-open_keystore(PKG_ERR *err, char *keystore_file, char *app,
- keystore_passphrase_cb cb, long flags, keystore_handle_t *result)
-{
- int ret = 0;
- keystore_t *tmpstore;
-
- tmpstore = new_keystore();
-
- tmpstore->dirty = B_FALSE;
- tmpstore->new = B_FALSE;
- tmpstore->path = xstrdup(keystore_file);
-
- if (!resolve_paths(err, keystore_file, app, flags, tmpstore)) {
- /* unable to determine keystore paths */
- pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- if (!verify_keystore_integrity(err, tmpstore)) {
- /* unable to repair keystore */
- pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- if (!lock_keystore(err, flags, tmpstore)) {
- pkgerr_add(err, PKGERR_LOCKED, gettext(ERR_KEYSTORE_LOCKED),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- /* now that we have locked the keystore, go ahead and read it */
- if (!read_keystore(err, tmpstore, cb)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_PARSE),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- *result = tmpstore;
- tmpstore = NULL;
-
-cleanup:
- if (tmpstore != NULL)
- free_keystore(tmpstore);
- return (ret);
-}
-
-/*
- * new_keystore - Allocates and initializes a Keystore object
- *
- * Arguments:
- * NONE
- *
- * Returns:
- * NULL - out of memory
- * otherwise, returns a pointer to the newly allocated object,
- * which should be freed with free_keystore() when no longer
- * needed.
- */
-static keystore_t
-*new_keystore(void)
-{
- keystore_t *tmpstore;
-
- if ((tmpstore = (keystore_t *)malloc(sizeof (keystore_t))) == NULL) {
- return (NULL);
- }
- tmpstore->dirty = B_FALSE;
- tmpstore->new = B_FALSE;
- tmpstore->path = NULL;
- tmpstore->passphrase = NULL;
- tmpstore->cafd = -1;
- tmpstore->cacerts = NULL;
- tmpstore->capath = NULL;
- tmpstore->clcerts = NULL;
- tmpstore->clpath = NULL;
- tmpstore->pkeys = NULL;
- tmpstore->keypath = NULL;
-
- return (tmpstore);
-}
-
-/*
- * free_keystore - Deallocates a Keystore object
- *
- * Arguments:
- * keystore - The keystore to deallocate
- *
- * Returns:
- * NONE
- */
-static void
-free_keystore(keystore_t *keystore)
-{
- if (keystore->path != NULL)
- free(keystore->path);
- if (keystore->capath != NULL)
- free(keystore->capath);
- if (keystore->passphrase != NULL)
- free(keystore->passphrase);
- if (keystore->clpath != NULL)
- free(keystore->clpath);
- if (keystore->keypath != NULL)
- free(keystore->keypath);
-
- if (keystore->pkeys != NULL) {
- sk_EVP_PKEY_pop_free(keystore->pkeys,
- sunw_evp_pkey_free);
- }
- if (keystore->clcerts != NULL)
- sk_X509_free(keystore->clcerts);
- if (keystore->cacerts != NULL)
- sk_X509_free(keystore->cacerts);
- free(keystore);
-}
-
-/*
- * close_keystore - Writes keystore to disk if needed, then
- * unlocks and closes keystore.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore - Keystore which should be closed
- * passwd - Password used to encrypt keystore
- *
- * Returns:
- * 0 - Success - keystore is committed to disk, and unlocked
- * non-zero - Failure, errors added to err
- */
-int
-close_keystore(PKG_ERR *err, keystore_handle_t keystore_h,
- keystore_passphrase_cb cb)
-{
- int ret = 0;
- keystore_t *keystore = keystore_h;
-
- if (keystore->dirty) {
- /* write out the keystore first */
- if (!write_keystore(err, keystore, cb)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->path);
- ret = 1;
- goto cleanup;
- }
- }
-
- if (!unlock_keystore(err, keystore)) {
- pkgerr_add(err, PKGERR_UNLOCK, gettext(ERR_KEYSTORE_UNLOCK),
- keystore->path);
- ret = 1;
- goto cleanup;
- }
-
- free_keystore(keystore);
-cleanup:
- return (ret);
-}
-
-/*
- * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
- * certificate checked for validity dates and non-duplicity.
- *
- * Arguments:
- * err - Error object to add errors to
- * cacert - Certificate which to merge into keystore
- * keystore - The keystore into which the certificate is merged
- *
- * Returns:
- * 0 - Success - Certificate passes validity, and
- * is merged into keystore
- * non-zero - Failure, errors recorded in err
- */
-int
-merge_ca_cert(PKG_ERR *err, X509 *cacert, keystore_handle_t keystore_h)
-{
-
- int ret = 0;
- X509 *existing = NULL;
- char *fname;
- keystore_t *keystore = keystore_h;
-
- /* check validity dates */
- if (check_cert(err, cacert) != 0) {
- ret = 1;
- goto cleanup;
- }
-
- /* create the certificate's friendlyName */
- fname = get_subject_display_name(cacert);
-
- if (sunw_set_fname(fname, NULL, cacert) != 0) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- /* merge certificate into the keystore */
- if (keystore->cacerts == NULL) {
- /* no existing truststore, so make a new one */
- if ((keystore->cacerts = sk_X509_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing truststore, make sure there's no duplicate */
- if (sunw_find_fname(fname, NULL, keystore->cacerts,
- NULL, &existing) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existing != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATECERT), fname);
- ret = 1;
- goto cleanup;
- }
- }
-
- (void) sk_X509_push(keystore->cacerts, cacert);
- keystore->dirty = B_TRUE;
-cleanup:
- if (existing != NULL)
- X509_free(existing);
- return (ret);
-}
-
-/*
- * find_key_cert_pair - Searches a keystore for a matching
- * public key certificate and private key, given an alias.
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * alias - Name to used to match certificate's alias
- * key - Resulting key is placed here
- * cert - Resulting cert is placed here
- *
- * Returns:
- * 0 - Success - Matching cert/key pair placed in key and cert.
- * non-zero - Failure, errors recorded in err
- */
-int
-find_key_cert_pair(PKG_ERR *err, keystore_handle_t ks_h, char *alias,
- EVP_PKEY **key, X509 **cert)
-{
- X509 *tmpcert = NULL;
- EVP_PKEY *tmpkey = NULL;
- int ret = 0;
- int items_found;
- keystore_t *ks = ks_h;
-
- if (key == NULL || cert == NULL) {
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOPUBCERTS), ks->path);
- ret = 1;
- goto cleanup;
- }
-
- if (ks->clcerts == NULL) {
- /* no public certs */
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOCERTS), ks->path);
- ret = 1;
- goto cleanup;
- }
- if (ks->pkeys == NULL) {
- /* no private keys */
- pkgerr_add(err, PKGERR_NOPRIVKEY,
- gettext(ERR_KEYSTORE_NOKEYS), ks->path);
- ret = 1;
- goto cleanup;
- }
-
- /* try the easy case first */
- if ((sk_EVP_PKEY_num(ks->pkeys) == 1) &&
- (sk_X509_num(ks->clcerts) == 1)) {
- tmpkey = sk_EVP_PKEY_value(ks->pkeys, 0);
- tmpcert = sk_X509_value(ks->clcerts, 0);
- if (sunw_check_keys(tmpcert, tmpkey)) {
- /*
- * only one private key and public key cert, and they
- * match, so use them
- */
- *key = tmpkey;
- tmpkey = NULL;
- *cert = tmpcert;
- tmpcert = NULL;
- goto cleanup;
- }
- }
-
- /* Attempt to find the right pair given the alias */
- items_found = sunw_find_fname(alias, ks->pkeys, ks->clcerts,
- &tmpkey, &tmpcert);
-
- if ((items_found < 0) ||
- (items_found & (FOUND_PKEY | FOUND_CERT)) == 0) {
- /* no key/cert pair found. bail. */
- pkgerr_add(err, PKGERR_BADALIAS,
- gettext(ERR_KEYSTORE_NOMATCH), alias);
- ret = 1;
- goto cleanup;
- }
-
- /* success */
- *key = tmpkey;
- tmpkey = NULL;
- *cert = tmpcert;
- tmpcert = NULL;
-
-cleanup:
-
- if (tmpcert != NULL)
- (void) X509_free(tmpcert);
-
- if (tmpkey != NULL)
- sunw_evp_pkey_free(tmpkey);
-
- return (ret);
-}
-
-/*
- * find_ca_certs - Searches a keystore for trusted certificates
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * cacerts - resulting set of trusted certs are placed here
- *
- * Returns:
- * 0 - Success - trusted cert list returned in cacerts
- * non-zero - Failure, errors recorded in err
- */
-int
-find_ca_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **cacerts)
-{
-
- keystore_t *ks = ks_h;
-
- /* easy */
- if (cacerts == NULL) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL), __FILE__, __LINE__);
- return (1);
- }
-
- *cacerts = ks->cacerts;
- return (0);
-}
-
-/*
- * find_cl_certs - Searches a keystore for user certificates
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * cacerts - resulting set of user certs are placed here
- *
- * No matching of any kind is performed.
- * Returns:
- * 0 - Success - trusted cert list returned in cacerts
- * non-zero - Failure, errors recorded in err
- */
-/* ARGSUSED */
-int
-find_cl_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **clcerts)
-{
- keystore_t *ks = ks_h;
-
- /* easy */
- *clcerts = ks->clcerts;
- return (0);
-}
-
-
-/*
- * merge_cert_and_key - Adds a user certificate and matching
- * private key to a keystore.
- * certificate checked for validity dates and non-duplicity.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - Certificate which to merge into keystore
- * key - matching private key to 'cert'
- * alias - Name which to store the cert and key under
- * keystore - The keystore into which the certificate is merged
- *
- * Returns:
- * 0 - Success - Certificate passes validity, and
- * is merged into keystore, along with key
- * non-zero - Failure, errors recorded in err
- */
-int
-merge_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key, char *alias,
- keystore_handle_t keystore_h)
-{
- X509 *existingcert = NULL;
- EVP_PKEY *existingkey = NULL;
- int ret = 0;
- keystore_t *keystore = keystore_h;
-
- /* check validity dates */
- if (check_cert(err, cert) != 0) {
- ret = 1;
- goto cleanup;
- }
-
- /* set the friendlyName of the key and cert to the supplied alias */
- if (sunw_set_fname(alias, key, cert) != 0) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- /* merge certificate and key into the keystore */
- if (keystore->clcerts == NULL) {
- /* no existing truststore, so make a new one */
- if ((keystore->clcerts = sk_X509_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing certstore, make sure there's no duplicate */
- if (sunw_find_fname(alias, NULL, keystore->clcerts,
- NULL, &existingcert) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existingcert != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATECERT), alias);
- ret = 1;
- goto cleanup;
- }
- }
-
- if (keystore->pkeys == NULL) {
- /* no existing keystore, so make a new one */
- if ((keystore->pkeys = sk_EVP_PKEY_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing keystore, so make sure there's no duplicate entry */
- if (sunw_find_fname(alias, keystore->pkeys, NULL,
- &existingkey, NULL) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existingkey != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATEKEY), alias);
- ret = 1;
- goto cleanup;
- }
- }
-
- (void) sk_X509_push(keystore->clcerts, cert);
- (void) sk_EVP_PKEY_push(keystore->pkeys, key);
- keystore->dirty = B_TRUE;
-cleanup:
- if (existingcert != NULL)
- (void) X509_free(existingcert);
- if (existingkey != NULL)
- (void) sunw_evp_pkey_free(existingkey);
- return (ret);
-}
-
-/*
- * delete_cert_and_keys - Deletes one or more certificates
- * and matching private keys from a keystore.
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - The keystore from which certs and keys are deleted
- * alias - Name which to search for certificates and keys
- * to delete
- *
- * Returns:
- * 0 - Success - All trusted certs which match 'alias'
- * are deleted. All user certificates
- * which match 'alias' are deleted, along
- * with the matching private key.
- * non-zero - Failure, errors recorded in err
- */
-int
-delete_cert_and_keys(PKG_ERR *err, keystore_handle_t ks_h, char *alias)
-{
- X509 *existingcert;
- EVP_PKEY *existingkey;
- int i;
- char *fname = NULL;
- boolean_t found = B_FALSE;
- keystore_t *ks = ks_h;
-
- /* delete any and all client certs with the supplied name */
- if (ks->clcerts != NULL) {
- for (i = 0; i < sk_X509_num(ks->clcerts); i++) {
- existingcert = sk_X509_value(ks->clcerts, i);
- if (sunw_get_cert_fname(GETDO_COPY,
- existingcert, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingcert =
- sk_X509_delete(ks->clcerts, i);
- X509_free(existingcert);
- existingcert = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_X509_num(ks->clcerts) <= 0) {
- /* we deleted all the client certs */
- sk_X509_free(ks->clcerts);
- ks->clcerts = NULL;
- }
- }
-
- /* and now the private keys */
- if (ks->pkeys != NULL) {
- for (i = 0; i < sk_EVP_PKEY_num(ks->pkeys); i++) {
- existingkey = sk_EVP_PKEY_value(ks->pkeys, i);
- if (sunw_get_pkey_fname(GETDO_COPY,
- existingkey, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingkey =
- sk_EVP_PKEY_delete(ks->pkeys, i);
- sunw_evp_pkey_free(existingkey);
- existingkey = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_EVP_PKEY_num(ks->pkeys) <= 0) {
- /* we deleted all the private keys */
- sk_EVP_PKEY_free(ks->pkeys);
- ks->pkeys = NULL;
- }
- }
-
- /* finally, remove any trust anchors that match */
-
- if (ks->cacerts != NULL) {
- for (i = 0; i < sk_X509_num(ks->cacerts); i++) {
- existingcert = sk_X509_value(ks->cacerts, i);
- if (sunw_get_cert_fname(GETDO_COPY,
- existingcert, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingcert =
- sk_X509_delete(ks->cacerts, i);
- X509_free(existingcert);
- existingcert = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_X509_num(ks->cacerts) <= 0) {
- /* we deleted all the CA certs */
- sk_X509_free(ks->cacerts);
- ks->cacerts = NULL;
- }
- }
-
- if (found) {
- ks->dirty = B_TRUE;
- return (0);
- } else {
- /* no certs or keys deleted */
- pkgerr_add(err, PKGERR_NOALIASMATCH,
- gettext(ERR_KEYSTORE_NOCERTKEY),
- alias, ks->path);
- return (1);
- }
-}
-
-/*
- * check_cert - Checks certificate validity. This routine
- * checks that the current time falls within the period
- * of validity for the cert.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - The certificate to check
- *
- * Returns:
- * 0 - Success - Certificate checks out
- * non-zero - Failure, errors and reasons recorded in err
- */
-int
-check_cert(PKG_ERR *err, X509 *cert)
-{
- char currtimestr[ATTR_MAX];
- time_t currtime;
- char *r;
- /* get current time */
- if ((currtime = time(NULL)) == (time_t)-1) {
- pkgerr_add(err, PKGERR_TIME, gettext(ERR_CURR_TIME));
- return (1);
- }
-
- (void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX);
-
- /* trim whitespace from end of time string */
- for (r = (currtimestr + strlen(currtimestr) - 1); isspace(*r); r--) {
- *r = '\0';
- }
- /* check validity of cert */
- switch (sunw_check_cert_times(CHK_BOTH, cert)) {
- case CHKERR_TIME_OK:
- /* Current time meets requested checks */
- break;
- case CHKERR_TIME_BEFORE_BAD:
- /* 'not before' field is invalid */
- case CHKERR_TIME_AFTER_BAD:
- /* 'not after' field is invalid */
- pkgerr_add(err, PKGERR_TIME, gettext(ERR_CERT_TIME_BAD));
- return (1);
- case CHKERR_TIME_IS_BEFORE:
- /* Current time is before 'not before' */
- case CHKERR_TIME_HAS_EXPIRED:
- /*
- * Ignore expiration time since the trust cert used to
- * verify the certs used to sign Sun patches is already
- * expired. Once the patches get resigned with the new
- * cert we will check expiration against the time the
- * patch was signed and not the time it is installed.
- */
- return (0);
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- return (1);
- }
-
- /* all checks ok */
- return (0);
-}
-
-/*
- * check_cert - Checks certificate validity. This routine
- * checks everything that check_cert checks, and additionally
- * verifies that the private key and corresponding public
- * key are indeed a pair.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - The certificate to check
- * key - the key to check
- * Returns:
- * 0 - Success - Certificate checks out
- * non-zero - Failure, errors and reasons recorded in err
- */
-int
-check_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key)
-{
-
- /* check validity dates */
- if (check_cert(err, cert) != 0) {
- return (1);
- }
-
- /* check key pair match */
- if (sunw_check_keys(cert, key) == 0) {
- pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MISMATCHED_KEYS),
- get_subject_display_name(cert));
- return (1);
- }
-
- /* all checks OK */
- return (0);
-}
-
-/* ------------------ private functions ---------------------- */
-
-/*
- * verify_keystore_integrity - Searches for the remnants
- * of a failed or aborted keystore modification, and
- * cleans up the files, retstores the keystore to a known
- * state.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - Base directory or filename of keystore
- * app - Application making request
- *
- * Returns:
- * 0 - Success - Keystore is restored, or untouched in the
- * case that cleanup was unnecessary
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-verify_keystore_integrity(PKG_ERR *err, keystore_t *keystore)
-{
- if (keystore->capath != NULL) {
- if (!restore_keystore_file(err, keystore->capath)) {
- return (B_FALSE);
- }
- }
- if (keystore->clpath != NULL) {
- if (!restore_keystore_file(err, keystore->clpath)) {
- return (B_FALSE);
- }
- }
- if (keystore->keypath != NULL) {
- if (!restore_keystore_file(err, keystore->keypath)) {
- return (B_FALSE);
- }
- }
- return (B_TRUE);
-}
-
-/*
- * restore_keystore_file - restores a keystore file to
- * a known state.
- *
- * Keystore files can possibly be corrupted by a variety
- * of error conditions during reading/writing. This
- * routine, along with write_keystore_file, tries to
- * maintain keystore integrity by writing the files
- * out in a particular order, minimizing the time period
- * that the keystore is in an indeterminate state.
- *
- * With the current implementation, there are some failures
- * that are wholly unrecoverable, such as disk corruption.
- * These routines attempt to minimize the risk, but not
- * eliminate it. When better, atomic operations are available
- * (such as a trued atabase with commit, rollback, and
- * guaranteed atomicity), this implementation should use that.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - keystore file path to restore.
- *
- * Returns:
- * 0 - Success - Keystore file is restored, or untouched in the
- * case that cleanup was unnecessary
- * non-zero - Failure, errors and reasons recorded in err
- */
-/* ARGSUSED */
-static boolean_t
-restore_keystore_file(PKG_ERR *err, char *keystore_file)
-{
- char newpath[MAXPATHLEN];
- char backuppath[MAXPATHLEN];
- int newfd;
- struct stat buf;
- int len;
-
- if (((len = snprintf(newpath, MAXPATHLEN, "%s.new",
- keystore_file)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
- return (B_FALSE);
- }
-
- if (((len = snprintf(backuppath, MAXPATHLEN, "%s.bak",
- keystore_file)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
- return (B_FALSE);
- }
-
- if ((newfd = open(newpath, O_RDWR|O_NONBLOCK, 0)) != -1) {
- if (fstat(newfd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- /*
- * restore the file, waiting on it
- * to be free for locking, or for
- * it to disappear
- */
- if (!wait_restore(newfd, keystore_file,
- newpath, backuppath)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_WRITE),
- newpath, strerror(errno));
- (void) close(newfd);
- return (B_FALSE);
- } else {
- return (B_TRUE);
- }
- } else {
- /* "new" file is not a regular file */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_NOT_REG), newpath);
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /* couldn't stat "new" file */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_WRITE), newpath,
- strerror(errno));
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /* "new" file doesn't exist */
- return (B_TRUE);
- }
-}
-
-static boolean_t
-wait_restore(int newfd, char *keystore_file,
- char *origpath, char *backuppath)
-{
- struct stat buf;
- FILE *newstream;
- PKCS12 *p12;
-
- (void) alarm(LOCK_TIMEOUT);
- if (file_lock(newfd, F_WRLCK, 1) == -1) {
- /* could not lock file */
- (void) alarm(0);
- return (B_FALSE);
- }
- (void) alarm(0);
-
- if (fstat(newfd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- /*
- * The new file still
- * exists, with no
- * owner. It must be
- * the result of an
- * aborted update.
- */
- newstream = fdopen(newfd, "r");
- if ((p12 =
- d2i_PKCS12_fp(newstream,
- NULL)) != NULL) {
- /*
- * The file
- * appears
- * complete.
- * Replace the
- * exsisting
- * keystore
- * file with
- * this one
- */
- (void) rename(keystore_file, backuppath);
- (void) rename(origpath, keystore_file);
- PKCS12_free(p12);
- } else {
- /* The file is not complete. Remove it */
- (void) remove(origpath);
- }
- /* remove backup file */
- (void) remove(backuppath);
- (void) fclose(newstream);
- (void) close(newfd);
- return (B_TRUE);
- } else {
- /*
- * new file exists, but is not a
- * regular file
- */
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /*
- * could not stat file. Unless
- * the reason was that the file
- * is now gone, this is an error
- */
- if (errno != ENOENT) {
- (void) close(newfd);
- return (B_FALSE);
- }
- /*
- * otherwise, file is gone. The process
- * that held the lock must have
- * successfully cleaned up and
- * exited with a valid keystore
- * state
- */
- (void) close(newfd);
- return (B_TRUE);
- }
-}
-
-/*
- * resolve_paths - figure out if we are dealing with a single-file
- * or multi-file keystore
- *
- * The flags tell resolve_paths how to behave:
- *
- * KEYSTORE_PATH_SOFT
- * If the keystore file does not exist at <base>/<app> then
- * use <base> as the path to the keystore. This can be used,
- * for example, to access an app-specific keystore iff it
- * exists, otherwise revert back to an app-generic keystore.
- *
- * KEYSTORE_PATH_HARD
- * Always use the keystore located at <keystore_path>/<app>.
- * In read/write mode, if the files do not exist, then
- * they will be created. This is used to avoid falling
- * back to an app-generic keystore path when the app-specific
- * one does not exist.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - base keystore file path to lock
- * app - Application making requests
- * flags - Control flags (see above description)
- * keystore - object which is being locked
- *
- * Returns:
- * B_TRUE - Success - Keystore file is locked, paths to
- * appropriate files placed in keystore.
- * B_FALSE - Failure, errors and reasons recorded in err
- */
-static boolean_t
-resolve_paths(PKG_ERR *err, char *keystore_file, char *app,
- long flags, keystore_t *keystore)
-{
- char storepath[PATH_MAX];
- struct stat buf;
- boolean_t multi = B_FALSE;
- int fd1, fd2, len;
-
- /*
- * figure out whether we are dealing with a single-file keystore
- * or a multi-file keystore
- */
- if (app != NULL) {
- if (((len = snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, app)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN),
- keystore_file);
- return (B_FALSE);
- }
-
- if (((fd1 = open(storepath, O_NONBLOCK|O_RDONLY)) == -1) ||
- (fstat(fd1, &buf) == -1) ||
- !S_ISDIR(buf.st_mode)) {
- /*
- * app-specific does not exist
- * fallback to app-generic, if flags say we can
- */
- if ((flags & KEYSTORE_PATH_MASK) ==
- KEYSTORE_PATH_SOFT) {
-
- if (((fd2 = open(keystore_file,
- O_NONBLOCK|O_RDONLY)) != -1) &&
- (fstat(fd2, &buf) != -1)) {
- if (S_ISDIR(buf.st_mode)) {
- /*
- * app-generic dir
- * exists, so use it
- * as a multi-file
- * keystore
- */
- multi = B_TRUE;
- app = NULL;
- } else if (S_ISREG(buf.st_mode)) {
- /*
- * app-generic file exists, so
- * use it as a single file ks
- */
- multi = B_FALSE;
- app = NULL;
- }
- }
- }
- }
- if (fd1 != -1)
- (void) close(fd1);
- if (fd2 != -1)
- (void) close(fd2);
- } else {
- if (((fd1 = open(keystore_file,
- O_NONBLOCK|O_RDONLY)) != -1) &&
- (fstat(fd1, &buf) != -1) &&
- S_ISDIR(buf.st_mode)) {
- /*
- * app-generic dir exists, so use
- * it as a multi-file keystore
- */
- multi = B_TRUE;
- }
- if (fd1 != -1)
- (void) close(fd1);
- }
-
- if (app != NULL) {
- /* app-specific keystore */
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, TRUSTSTORE);
- keystore->capath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, CERTSTORE);
- keystore->clpath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, KEYSTORE);
- keystore->keypath = xstrdup(storepath);
- } else {
- /* app-generic keystore */
- if (!multi) {
- /* single-file app-generic keystore */
- keystore->capath = xstrdup(keystore_file);
- keystore->keypath = NULL;
- keystore->clpath = NULL;
- } else {
- /* multi-file app-generic keystore */
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, TRUSTSTORE);
- keystore->capath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, CERTSTORE);
- keystore->clpath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, KEYSTORE);
- keystore->keypath = xstrdup(storepath);
- }
- }
-
- return (B_TRUE);
-}
-
-/*
- * lock_keystore - Locks a keystore for shared (read-only)
- * or exclusive (read-write) access.
- *
- * The flags tell lock_keystore how to behave:
- *
- * KEYSTORE_ACCESS_READONLY
- * opens keystore read-only. Attempts to modify results in an error
- *
- * KEYSTORE_ACCESS_READWRITE
- * opens keystore read-write
- *
- * KEYSTORE_PATH_SOFT
- * If the keystore file does not exist at <base>/<app> then
- * use <base> as the path to the keystore. This can be used,
- * for example, to access an app-specific keystore iff it
- * exists, otherwise revert back to an app-generic keystore.
- *
- * KEYSTORE_PATH_HARD
- * Always use the keystore located at <keystore_path>/<app>.
- * In read/write mode, if the files do not exist, then
- * they will be created. This is used to avoid falling
- * back to an app-generic keystore path when the app-specific
- * one does not exist.
- *
- * Arguments:
- * err - Error object to add errors to
- * flags - Control flags (see above description)
- * keystore - object which is being locked
- *
- * Returns:
- * 0 - Success - Keystore file is locked, paths to
- * appropriate files placed in keystore.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-lock_keystore(PKG_ERR *err, long flags, keystore_t *keystore)
-{
- boolean_t ret = B_TRUE;
- struct stat buf;
-
- switch (flags & KEYSTORE_ACCESS_MASK) {
- case KEYSTORE_ACCESS_READONLY:
- if ((keystore->cafd =
- open(keystore->capath, O_NONBLOCK|O_RDONLY)) == -1) {
- if (errno == ENOENT) {
- /*
- * no keystore. try to create an
- * empty one so we can lock on it and
- * prevent others from gaining
- * exclusive access. It will be
- * deleted when the keystore is closed.
- */
- if ((keystore->cafd =
- open(keystore->capath,
- O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NO_KEYSTORE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- }
- if (fstat(keystore->cafd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- if (file_lock(keystore->cafd, F_RDLCK,
- 0) == -1) {
- pkgerr_add(err, PKGERR_LOCKED,
- gettext(ERR_KEYSTORE_LOCKED_READ),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* ca file not a regular file! */
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NOT_REG),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- break;
- case KEYSTORE_ACCESS_READWRITE:
-
- if ((keystore->cafd = open(keystore->capath,
- O_RDWR|O_NONBLOCK)) == -1) {
- /* does not exist. try to create an empty one */
- if (errno == ENOENT) {
- if ((keystore->cafd =
- open(keystore->capath,
- O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- }
- if (fstat(keystore->cafd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- if (file_lock(keystore->cafd, F_WRLCK,
- 0) == -1) {
- pkgerr_add(err, PKGERR_LOCKED,
- gettext(ERR_KEYSTORE_LOCKED),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* ca file not a regular file! */
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NOT_REG),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- break;
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ret = B_FALSE;
- goto cleanup;
- }
-
-cleanup:
- if (!ret) {
- if (keystore->cafd > 0) {
- (void) file_unlock(keystore->cafd);
- (void) close(keystore->cafd);
- keystore->cafd = -1;
- }
-
- if (keystore->capath != NULL)
- free(keystore->capath);
- if (keystore->clpath != NULL)
- free(keystore->clpath);
- if (keystore->keypath != NULL)
- free(keystore->keypath);
- keystore->capath = NULL;
- keystore->clpath = NULL;
- keystore->keypath = NULL;
- }
-
- return (ret);
-}
-
-/*
- * unlock_keystore - Unocks a keystore
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to unlock
- * Returns:
- * 0 - Success - Keystore files are unlocked, files are closed,
- * non-zero - Failure, errors and reasons recorded in err
- */
-/* ARGSUSED */
-static boolean_t
-unlock_keystore(PKG_ERR *err, keystore_t *keystore)
-{
-
- /*
- * Release lock on the CA file.
- * Delete file if it is empty
- */
- if (file_empty(keystore->capath)) {
- (void) remove(keystore->capath);
- }
-
- (void) file_unlock(keystore->cafd);
- (void) close(keystore->cafd);
- return (B_TRUE);
-}
-
-/*
- * read_keystore - Reads keystore files of disk, parses
- * into internal structures.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to read into
- * cb - callback to get password, if required
- * Returns:
- * 0 - Success - Keystore files are read, and placed
- * into keystore structure.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-read_keystore(PKG_ERR *err, keystore_t *keystore, keystore_passphrase_cb cb)
-{
- boolean_t ret = B_TRUE;
- PKCS12 *p12 = NULL;
- boolean_t ca_empty;
- boolean_t have_passwd = B_FALSE;
- boolean_t cl_empty = B_TRUE;
- boolean_t key_empty = B_TRUE;
-
- ca_empty = file_empty(keystore->capath);
-
- if (keystore->clpath != NULL)
- cl_empty = file_empty(keystore->clpath);
- if (keystore->keypath != NULL)
- key_empty = file_empty(keystore->keypath);
-
- if (ca_empty && cl_empty && key_empty) {
- keystore->new = B_TRUE;
- }
-
- if (!ca_empty) {
- /* first read the ca file */
- if ((p12 = read_keystore_file(err,
- keystore->capath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb, keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- /* decrypt and parse keystore file */
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- &keystore->pkeys, &keystore->cacerts) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
-
- /*
- * truststore is empty, so we don't have any trusted
- * certs
- */
- keystore->cacerts = NULL;
- }
-
- /*
- * if there is no cl file or key file, use the cl's and key's found
- * in the ca file
- */
- if (keystore->clpath == NULL && !ca_empty) {
- if (sunw_split_certs(keystore->pkeys, keystore->cacerts,
- &keystore->clcerts, NULL) < 0) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * files are in separate files. read keys out of the keystore
- * certs out of the certstore, if they are not empty
- */
- if (!cl_empty) {
- if ((p12 = read_keystore_file(err,
- keystore->clpath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb,
- keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- if (check_password(p12,
- keystore->passphrase) == B_FALSE) {
- /*
- * password in client cert file
- * is different than
- * the one in the other files!
- */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_MISMATCHPASS),
- keystore->clpath,
- keystore->capath, keystore->path);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- NULL, &keystore->clcerts) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- keystore->clcerts = NULL;
- }
-
- if (!key_empty) {
- if ((p12 = read_keystore_file(err,
- keystore->keypath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb,
- keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- if (check_password(p12,
- keystore->passphrase) == B_FALSE) {
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_MISMATCHPASS),
- keystore->keypath,
- keystore->capath, keystore->path);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- &keystore->pkeys, NULL) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- keystore->pkeys = NULL;
- }
- }
-
-cleanup:
- if (p12 != NULL)
- PKCS12_free(p12);
- return (ret);
-}
-
-/*
- * get_keystore_password - retrieves pasword used to
- * decrypt PKCS12 structure.
- *
- * Arguments:
- * err - Error object to add errors to
- * p12 - PKCS12 structure which returned password should
- * decrypt
- * cb - callback to collect password.
- * keystore - The keystore in which the PKCS12 structure
- * will eventually populate.
- * Returns:
- * B_TRUE - success.
- * keystore password is set in keystore->passphrase.
- * B_FALSE - failure, errors logged
- */
-static boolean_t
-get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, keystore_passphrase_cb cb,
- keystore_t *keystore)
-{
- char *passwd;
- char passbuf[KEYSTORE_PASS_MAX + 1];
- keystore_passphrase_data data;
-
- /* see if no password is the right password */
- if (check_password(p12, "") == B_TRUE) {
- passwd = "";
- } else if (check_password(p12, NULL) == B_TRUE) {
- passwd = NULL;
- } else {
- /* oops, it's encrypted. get password */
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX, 0,
- &data) == -1) {
- /* could not get password */
- return (B_FALSE);
- }
-
- if (check_password(p12, passbuf) == B_FALSE) {
- /* wrong password */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_BADPASS));
- return (B_FALSE);
- }
-
- /*
- * make copy of password buffer, since it
- * goes away upon return
- */
- passwd = xstrdup(passbuf);
- }
- keystore->passphrase = passwd;
- return (B_TRUE);
-}
-
-/*
- * write_keystore - Writes keystore files to disk
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to write from
- * passwd - password used to encrypt keystore
- * Returns:
- * 0 - Success - Keystore contents are written out to
- * the same locations as read from
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-write_keystore(PKG_ERR *err, keystore_t *keystore,
- keystore_passphrase_cb cb)
-{
- PKCS12 *p12 = NULL;
- boolean_t ret = B_TRUE;
- keystore_passphrase_data data;
- char passbuf[KEYSTORE_PASS_MAX + 1];
-
- if (keystore->capath != NULL && keystore->clpath == NULL &&
- keystore->keypath == NULL) {
-
- /*
- * keystore is a file.
- * just write out a single file
- */
- if ((keystore->pkeys == NULL) &&
- (keystore->clcerts == NULL) &&
- (keystore->cacerts == NULL)) {
- if (!clear_keystore_file(err, keystore->capath)) {
- /*
- * no keys or certs to write out, so
- * blank the ca file. we do not
- * delete it since it is used as a
- * lock by lock_keystore() in
- * subsequent invocations
- */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * if the keystore is being created for the first time,
- * prompt for a passphrase for encryption
- */
- if (keystore->new) {
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX,
- 1, &data) == -1) {
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * use the one used when the keystore
- * was read
- */
- (void) strlcpy(passbuf, keystore->passphrase,
- KEYSTORE_PASS_MAX);
- }
-
- p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
- keystore->clcerts, keystore->cacerts);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->capath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- } else {
- /* files are seprate. Do one at a time */
-
- /*
- * if the keystore is being created for the first time,
- * prompt for a passphrase for encryption
- */
- if (keystore->new && ((keystore->pkeys != NULL) ||
- (keystore->clcerts != NULL) ||
- (keystore->cacerts != NULL))) {
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX,
- 1, &data) == -1) {
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* use the one used when the keystore was read */
- (void) strlcpy(passbuf, keystore->passphrase,
- KEYSTORE_PASS_MAX);
- }
-
- /* do private keys first */
- if (keystore->pkeys != NULL) {
- p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
- NULL, NULL);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->keypath,
- p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- } else {
- if ((remove(keystore->keypath) != 0) &&
- (errno != ENOENT)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_REMOVE),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- /* do user certs next */
- if (keystore->clcerts != NULL) {
- p12 = sunw_PKCS12_create(passbuf, NULL,
- keystore->clcerts, NULL);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->clpath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- } else {
- if ((remove(keystore->clpath) != 0) &&
- (errno != ENOENT)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_REMOVE),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
-
- /* finally do CA cert file */
- if (keystore->cacerts != NULL) {
- p12 = sunw_PKCS12_create(passbuf, NULL,
- NULL, keystore->cacerts);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->capath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- /*
- * nothing to write out, so truncate the file
- * (it will be deleted during close_keystore)
- */
- if (!clear_keystore_file(err, keystore->capath)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
- }
-
-cleanup:
- if (p12 != NULL)
- PKCS12_free(p12);
-
- return (ret);
-}
-
-/*
- * clear_keystore_file - Clears (zeros out) a keystore file.
- *
- * Arguments:
- * err - Error object to add errors to
- * dest - Path of keystore file to zero out.
- * Returns:
- * 0 - Success - Keystore file is truncated to zero length
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-clear_keystore_file(PKG_ERR *err, char *dest)
-{
- int fd;
- struct stat buf;
-
- fd = open(dest, O_RDWR|O_NONBLOCK);
- if (fd == -1) {
- /* can't open for writing */
- pkgerr_add(err, PKGERR_WRITE, gettext(MSG_OPEN),
- errno);
- return (B_FALSE);
- }
-
- if ((fstat(fd, &buf) == -1) || !S_ISREG(buf.st_mode)) {
- /* not a regular file */
- (void) close(fd);
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_NOT_REG),
- dest);
- return (B_FALSE);
- }
-
- if (ftruncate(fd, 0) == -1) {
- (void) close(fd);
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_WRITE),
- dest, strerror(errno));
- return (B_FALSE);
- }
-
- (void) close(fd);
- return (B_TRUE);
-}
-
-/*
- * write_keystore_file - Writes keystore file to disk.
- *
- * Keystore files can possibly be corrupted by a variety
- * of error conditions during reading/writing. This
- * routine, along with restore_keystore_file, tries to
- * maintain keystore integity by writing the files
- * out in a particular order, minimizing the time period
- * that the keystore is in an indeterminate state.
- *
- * With the current implementation, there are some failures
- * that are wholly unrecoverable, such as disk corruption.
- * These routines attempt to minimize the risk, but not
- * eliminate it. When better, atomic operations are available
- * (such as a true database with commit, rollback, and
- * guaranteed atomicity), this implementation should use that.
- *
- *
- * Arguments:
- * err - Error object to add errors to
- * dest - Destination filename
- * contents - Contents to write to the file
- * Returns:
- * 0 - Success - Keystore contents are written out to
- * the destination.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-write_keystore_file(PKG_ERR *err, char *dest, PKCS12 *contents)
-{
- FILE *newfile = NULL;
- boolean_t ret = B_TRUE;
- char newpath[MAXPATHLEN];
- char backuppath[MAXPATHLEN];
- struct stat buf;
- int fd;
-
- (void) snprintf(newpath, MAXPATHLEN, "%s.new", dest);
- (void) snprintf(backuppath, MAXPATHLEN, "%s.bak", dest);
-
- if ((fd = open(newpath, O_CREAT|O_EXCL|O_WRONLY|O_NONBLOCK,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
- newpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if ((newfile = fdopen(fd, "w")) == NULL) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (i2d_PKCS12_fp(newfile, contents) == 0) {
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_KEYSTORE_WRITE),
- newpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* flush, then close */
- (void) fflush(newfile);
- (void) fclose(newfile);
- newfile = NULL;
-
- /* now back up the original file */
- (void) rename(dest, backuppath);
-
- /* put new one in its place */
- (void) rename(newpath, dest);
-
- /* remove backup */
- (void) remove(backuppath);
-
-cleanup:
- if (newfile != NULL)
- (void) fclose(newfile);
- if (fd != -1)
- (void) close(fd);
-
- return (ret);
-}
-
-/*
- * read_keystore_file - Reads single keystore file
- * off disk in PKCS12 format.
- *
- * Arguments:
- * err - Error object to add errors to
- * file - File path to read
- * Returns:
- * PKCS12 contents of file, or NULL if an error occurred.
- * errors recorded in 'err'.
- */
-static PKCS12
-*read_keystore_file(PKG_ERR *err, char *file)
-{
- int fd;
- struct stat buf;
- FILE *newfile;
- PKCS12 *p12 = NULL;
-
- if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
- file);
- goto cleanup;
- }
-
- if ((newfile = fdopen(fd, "r")) == NULL) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if ((p12 = d2i_PKCS12_fp(newfile, NULL)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), file);
- goto cleanup;
- }
-
-cleanup:
- if (newfile != NULL)
- (void) fclose(newfile);
- if (fd != -1)
- (void) close(fd);
-
- return (p12);
-}
-
-
-/*
- * Locks the specified file.
- */
-static int
-file_lock(int fd, int type, int wait)
-{
- struct flock lock;
-
- lock.l_type = type;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- if (!wait) {
- if (file_lock_test(fd, type)) {
- /*
- * The caller would have to wait to get the
- * lock on this file.
- */
- return (-1);
- }
- }
-
- return (fcntl(fd, F_SETLKW, &lock));
-}
-
-/*
- * Returns FALSE if the file is not locked; TRUE
- * otherwise.
- */
-static boolean_t
-file_lock_test(int fd, int type)
-{
- struct flock lock;
-
- lock.l_type = type;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- if (fcntl(fd, F_GETLK, &lock) != -1) {
- if (lock.l_type != F_UNLCK) {
- /*
- * The caller would have to wait to get the
- * lock on this file.
- */
- return (B_TRUE);
- }
- }
-
- /*
- * The file is not locked.
- */
- return (B_FALSE);
-}
-
-/*
- * Unlocks the specified file.
- */
-static int
-file_unlock(int fd)
-{
- struct flock lock;
-
- lock.l_type = F_UNLCK;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- return (fcntl(fd, F_SETLK, &lock));
-}
-
-/*
- * Determines if file has a length of 0 or not
- */
-static boolean_t
-file_empty(char *path)
-{
- struct stat buf;
-
- /* file is empty if size = 0 or it doesn't exist */
- if (lstat(path, &buf) == 0) {
- if (buf.st_size == 0) {
- return (B_TRUE);
- }
- } else {
- if (errno == ENOENT) {
- return (B_TRUE);
- }
- }
-
- return (B_FALSE);
-}
-
-/*
- * Name: get_time_string
- * Description: Generates a human-readable string from an ASN1_TIME
- *
- * Arguments: intime - The time to convert
- *
- * Returns : A pointer to a static string representing the passed-in time.
- */
-static char
-*get_time_string(ASN1_TIME *intime)
-{
-
- static char time[ATTR_MAX];
- BIO *mem;
- char *p;
-
- if (intime == NULL) {
- return (NULL);
- }
- if ((mem = BIO_new(BIO_s_mem())) == NULL) {
- return (NULL);
- }
-
- if (ASN1_TIME_print(mem, intime) == 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- if (BIO_gets(mem, time, ATTR_MAX) <= 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- (void) BIO_free(mem);
-
- /* trim the end of the string */
- for (p = time + strlen(time) - 1; isspace(*p); p--) {
- *p = '\0';
- }
-
- return (time);
-}
-
-/*
- * check_password - do various password checks to see if the current password
- * will work or we need to prompt for a new one.
- *
- * Arguments:
- * pass - password to check
- *
- * Returns:
- * B_TRUE - Password is OK.
- * B_FALSE - Password not valid.
- */
-static boolean_t
-check_password(PKCS12 *p12, char *pass)
-{
- boolean_t ret = B_TRUE;
-
- /*
- * If password is zero length or NULL then try verifying both cases
- * to determine which password is correct. The reason for this is that
- * under PKCS#12 password based encryption no password and a zero
- * length password are two different things...
- */
-
- /* Check the mac */
- if (pass == NULL || *pass == '\0') {
- if (PKCS12_verify_mac(p12, NULL, 0) == 0 &&
- PKCS12_verify_mac(p12, "", 0) == 0)
- ret = B_FALSE;
- } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
- ret = B_FALSE;
- }
- return (ret);
-}