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