summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpkg
diff options
context:
space:
mode:
authorPeter Tribble <peter.tribble@gmail.com>2017-03-13 20:25:34 +0000
committerGordon Ross <gwr@nexenta.com>2017-03-29 19:13:24 -0400
commit32991bedc3a6475f1401855c2318ae5b15f8a16b (patch)
tree3360e7844885746ed96019a9e3a42cd7e5e73409 /usr/src/lib/libpkg
parent4383d9578c9d399b19edc33e552a4c543ebf9468 (diff)
downloadillumos-gate-32991bedc3a6475f1401855c2318ae5b15f8a16b.tar.gz
5188 SVR4 packaging shouldn't depend on openssl or libwanboot
Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Alexander Eremin <alexander.r.eremin@gmail.com> Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src/lib/libpkg')
-rw-r--r--usr/src/lib/libpkg/Makefile.com22
-rw-r--r--usr/src/lib/libpkg/THIRDPARTYLICENSE51
-rw-r--r--usr/src/lib/libpkg/common/ckparam.c5
-rw-r--r--usr/src/lib/libpkg/common/dstream.c89
-rw-r--r--usr/src/lib/libpkg/common/gpkgmap.c6
-rw-r--r--usr/src/lib/libpkg/common/keystore.c2474
-rw-r--r--usr/src/lib/libpkg/common/keystore.h145
-rw-r--r--usr/src/lib/libpkg/common/llib-lpkg8
-rw-r--r--usr/src/lib/libpkg/common/mapfile-vers57
-rw-r--r--usr/src/lib/libpkg/common/p12lib.c2798
-rw-r--r--usr/src/lib/libpkg/common/p12lib.h245
-rw-r--r--usr/src/lib/libpkg/common/path_valid.c61
-rw-r--r--usr/src/lib/libpkg/common/pkgerr.c125
-rw-r--r--usr/src/lib/libpkg/common/pkgerr.h104
-rw-r--r--usr/src/lib/libpkg/common/pkglib.h51
-rw-r--r--usr/src/lib/libpkg/common/pkglibmsgs.h209
-rw-r--r--usr/src/lib/libpkg/common/pkgserv.c5
-rw-r--r--usr/src/lib/libpkg/common/pkgtrans.c592
-rw-r--r--usr/src/lib/libpkg/common/pkgweb.c3240
-rw-r--r--usr/src/lib/libpkg/common/pkgweb.h130
-rw-r--r--usr/src/lib/libpkg/common/progerr.c16
-rw-r--r--usr/src/lib/libpkg/common/security.c282
22 files changed, 134 insertions, 10581 deletions
diff --git a/usr/src/lib/libpkg/Makefile.com b/usr/src/lib/libpkg/Makefile.com
index 3e3b294c7e..a0dd3bcab5 100644
--- a/usr/src/lib/libpkg/Makefile.com
+++ b/usr/src/lib/libpkg/Makefile.com
@@ -20,6 +20,9 @@
#
#
+# Copyright 2017 Peter Tribble.
+
+#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -33,12 +36,11 @@ OBJECTS= \
devtype.o dstream.o gpkglist.o \
gpkgmap.o isdir.o logerr.o \
mappath.o ncgrpw.o nhash.o \
- pkgexecl.o pkgexecv.o pkgmount.o \
- pkgtrans.o ppkgmap.o \
+ path_valid.o pkgexecl.o pkgexecv.o \
+ pkgmount.o pkgtrans.o ppkgmap.o \
progerr.o putcfile.o rrmdir.o \
runcmd.o srchcfile.o tputcfent.o \
- verify.o security.o pkgweb.o \
- pkgerr.o keystore.o p12lib.o \
+ verify.o \
vfpops.o fmkdir.o pkgstr.o \
handlelocalfs.o pkgserv.o
@@ -52,29 +54,19 @@ POFILE = libpkg.po
MSGFILES = $(OBJECTS:%.o=../common/%.i)
CLEANFILES += $(MSGFILES)
-# This library is NOT lint clean
-
-# openssl forces us to ignore dubious pointer casts, thanks to its clever
-# use of macros for stack management.
-LINTFLAGS= -umx -errtags \
- -erroff=E_BAD_PTR_CAST_ALIGN,E_BAD_PTR_CAST
-LINTFLAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED
-LINTFLAGS64 += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED
$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -lc -lssl -lwanboot -lcrypto -lscf -ladm
+LDLIBS += -lc -lscf -ladm
CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-unused-label
CERRWARN += -_gcc=-Wno-parentheses
CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-clobbered
CERRWARN += -_gcc=-Wno-switch
-CERRWARN += -_gcc=-Wno-unused-value
CPPFLAGS += -I$(SRCDIR) -D_FILE_OFFSET_BITS=64
.KEEP_STATE:
diff --git a/usr/src/lib/libpkg/THIRDPARTYLICENSE b/usr/src/lib/libpkg/THIRDPARTYLICENSE
deleted file mode 100644
index 0051c6904d..0000000000
--- a/usr/src/lib/libpkg/THIRDPARTYLICENSE
+++ /dev/null
@@ -1,51 +0,0 @@
- * ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
diff --git a/usr/src/lib/libpkg/common/ckparam.c b/usr/src/lib/libpkg/common/ckparam.c
index 47beb1c6be..209d3b4d5d 100644
--- a/usr/src/lib/libpkg/common/ckparam.c
+++ b/usr/src/lib/libpkg/common/ckparam.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,6 +35,7 @@
#include <ctype.h>
#include <string.h>
+#include <stdlib.h>
#include <sys/types.h>
#include "pkglib.h"
#include "pkglibmsgs.h"
diff --git a/usr/src/lib/libpkg/common/dstream.c b/usr/src/lib/libpkg/common/dstream.c
index 38ca430614..6622b74361 100644
--- a/usr/src/lib/libpkg/common/dstream.c
+++ b/usr/src/lib/libpkg/common/dstream.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,7 +46,6 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fcntl.h>
-#include <openssl/err.h>
#include "pkglib.h"
#include "pkglibmsgs.h"
#include "pkglocale.h"
@@ -135,7 +138,6 @@ ds_order(char *list[])
static char *pds_header;
static char *ds_header;
-static char *ds_header_raw;
static int ds_headsize;
static char *
@@ -421,15 +423,6 @@ ds_init(char *device, char **pkg, char *norewind)
pds_header = ds_header;
- /* save raw copy of header for later use in BIO_dump_header */
- if ((ds_header_raw = (char *)malloc(header_size)) == NULL) {
- progerr(pkg_gt(ERR_UNPACK));
- logerr(pkg_gt(MSG_MEM));
- (void) ds_close(0);
- return (1);
- }
- (void) memcpy(ds_header_raw, ds_header, header_size);
-
/* read datastream table of contents */
ds_head = tail = (struct dstoc *)0;
ds_volcnt = 1;
@@ -491,16 +484,9 @@ ds_init(char *device, char **pkg, char *norewind)
}
(void) strlcat(cmd, pkg[i], CMDSIZ);
(void) strlcat(cmd, "'/*' ", CMDSIZ);
-
- /* extract signature too, if present. */
- (void) strlcat(cmd, SIGNATURE_FILENAME, CMDSIZ);
(void) strlcat(cmd, " ", CMDSIZ);
}
- /*
- * if we are extracting all packages (pkgs == NULL),
- * signature will automatically be extracted
- */
if (n = esystem(cmd, ds_fd, -1)) {
rpterr();
progerr(pkg_gt(ERR_UNPACK));
@@ -718,73 +704,6 @@ ds_next(char *device, char *instdir)
}
/*
- * Name: BIO_ds_dump
- * Description: Dumps all data from the static 'ds_fd' file handle into
- * the supplied BIO.
- *
- * Arguments: err - where to record any errors.
- * device - Description of device being dumped into,
- * for error reporting
- * bio - BIO object to dump data into
- *
- * Returns : zero - successfully dumped all data to EOF
- * non-zero - some failure occurred.
- */
-int
-BIO_ds_dump(PKG_ERR *err, char *device, BIO *bio)
-{
- int amtread;
- char readbuf[BLK_SIZE];
-
- /*
- * note this will read to the end of the device, so it won't
- * work for character devices since we don't know when the
- * end of the CPIO archive is
- */
- while ((amtread = read(ds_fd, readbuf, BLK_SIZE)) != 0) {
- if (BIO_write(bio, readbuf, amtread) != amtread) {
- pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, device,
- ERR_error_string(ERR_get_error(), NULL));
- return (1);
- }
- }
-
- return (0);
- /*NOTREACHED*/
-}
-
-
-/*
- * Name: BIO_ds_dump_header
- * Description: Dumps all ds_headsize bytes from the
- * static 'ds_header_raw' character array
- * to the supplied BIO.
- *
- * Arguments: err - where to record any errors.
- * bio - BIO object to dump data into
- *
- * Returns : zero - successfully dumped all raw
- * header characters
- * non-zero - some failure occurred.
- */
-int
-BIO_ds_dump_header(PKG_ERR *err, BIO *bio)
-{
-
- char zeros[BLK_SIZE];
-
- (void) memset(zeros, 0, BLK_SIZE);
-
- if (BIO_write(bio, ds_header_raw, ds_headsize) != ds_headsize) {
- pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, "bio",
- ERR_error_string(ERR_get_error(), NULL));
- return (1);
- }
-
- return (0);
-}
-
-/*
* ds_ginit: Determine the device being accessed, set the buffer size,
* and perform any device specific initialization.
*/
diff --git a/usr/src/lib/libpkg/common/gpkgmap.c b/usr/src/lib/libpkg/common/gpkgmap.c
index 4bbe60dfc3..a8bd01c87c 100644
--- a/usr/src/lib/libpkg/common/gpkgmap.c
+++ b/usr/src/lib/libpkg/common/gpkgmap.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -389,7 +393,6 @@ end:
return (-1);
}
-done:
return (1);
}
@@ -930,7 +933,6 @@ end:
return (-1);
}
-done:
return (1);
}
diff --git a/usr/src/lib/libpkg/common/keystore.c b/usr/src/lib/libpkg/common/keystore.c
deleted file mode 100644
index 633c04b58e..0000000000
--- a/usr/src/lib/libpkg/common/keystore.c
+++ /dev/null
@@ -1,2474 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Module: keystore.c
- * Description: This module contains the structure definitions for processing
- * package keystore files.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <strings.h>
-#include <libintl.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs12.h>
-#include <openssl/asn1.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/safestack.h>
-#include <openssl/stack.h>
-#include "p12lib.h"
-#include "pkgerr.h"
-#include "keystore.h"
-#include "pkglib.h"
-#include "pkglibmsgs.h"
-
-typedef struct keystore_t {
- boolean_t dirty;
- boolean_t new;
- char *path;
- char *passphrase;
- /* truststore handles */
- int cafd;
- STACK_OF(X509) *cacerts;
- char *capath;
-
- /* user certificate handles */
- STACK_OF(X509) *clcerts;
- char *clpath;
-
- /* private key handles */
- STACK_OF(EVP_PKEY) *pkeys;
- char *keypath;
-} keystore_t;
-
-/* local routines */
-static keystore_t *new_keystore(void);
-static void free_keystore(keystore_t *);
-static boolean_t verify_keystore_integrity(PKG_ERR *, keystore_t *);
-static boolean_t check_password(PKCS12 *, char *);
-static boolean_t resolve_paths(PKG_ERR *, char *, char *,
- long, keystore_t *);
-static boolean_t lock_keystore(PKG_ERR *, long, keystore_t *);
-
-static boolean_t unlock_keystore(PKG_ERR *, keystore_t *);
-static boolean_t read_keystore(PKG_ERR *, keystore_t *,
- keystore_passphrase_cb);
-static boolean_t write_keystore(PKG_ERR *, keystore_t *,
- keystore_passphrase_cb);
-static boolean_t write_keystore_file(PKG_ERR *, char *, PKCS12 *);
-static boolean_t clear_keystore_file(PKG_ERR *, char *);
-static PKCS12 *read_keystore_file(PKG_ERR *, char *);
-static char *get_time_string(ASN1_TIME *);
-
-/* locking routines */
-static boolean_t restore_keystore_file(PKG_ERR *, char *);
-static int file_lock(int, int, int);
-static int file_unlock(int);
-static boolean_t file_lock_test(int, int);
-static boolean_t file_empty(char *);
-static boolean_t get_keystore_passwd(PKG_ERR *err, PKCS12 *p12,
- keystore_passphrase_cb cb, keystore_t *keystore);
-static boolean_t wait_restore(int, char *, char *, char *);
-
-#define KEYSTORE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
-
-/* wait on other keystore access for 1 minute before giving up */
-#define LOCK_TIMEOUT 60
-
-/*
- * print_certs - prints certificates out of a keystore, to a file.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore - Keystore on which to operate
- * alias - Name of certificate to print, NULL means print all
- * format - Format in which to print certificates
- * outfile - Where to print certificates
- *
- * Returns:
- * 0 - Success
- * non-zero - Failure, errors added to err
- */
-int
-print_certs(PKG_ERR *err, keystore_handle_t keystore_h, char *alias,
- keystore_encoding_format_t format, FILE *outfile)
-{
- int i;
- X509 *cert;
- char *fname = NULL;
- boolean_t found = B_FALSE;
- keystore_t *keystore = keystore_h;
-
- if (keystore->clcerts != NULL) {
- /* print out each client cert */
- for (i = 0; i < sk_X509_num(keystore->clcerts); i++) {
- cert = sk_X509_value(keystore->clcerts, i);
- (void) sunw_get_cert_fname(GETDO_COPY, cert,
- &fname);
-
- if (fname == NULL) {
- /* no name recorded, keystore is corrupt */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_NO_ALIAS),
- get_subject_display_name(cert));
- return (1);
- }
-
- if ((alias != NULL) && (!streq(alias, fname))) {
- /* name does not match, skip it */
- (void) OPENSSL_free(fname);
- fname = NULL;
- continue;
- } else {
- found = B_TRUE;
- (void) print_cert(err, cert, format,
- fname, B_FALSE, outfile);
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- }
-
- if (fname != NULL) {
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
-
- if (keystore->cacerts != NULL) {
- /* print out each trusted cert */
- for (i = 0; i < sk_X509_num(keystore->cacerts); i++) {
- cert = sk_X509_value(keystore->cacerts, i);
- (void) sunw_get_cert_fname(GETDO_COPY,
- cert, &fname);
-
- if (fname == NULL) {
- /* no name recorded, keystore is corrupt */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_NO_ALIAS),
- get_subject_display_name(cert));
- return (1);
- }
-
- if ((alias != NULL) && (!streq(alias, fname))) {
- /* name does not match, skip it */
- (void) OPENSSL_free(fname);
- fname = NULL;
- continue;
- } else {
- found = B_TRUE;
- (void) print_cert(err, cert, format,
- fname, B_TRUE, outfile);
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- }
-
- if (fname != NULL) {
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
-
- if (found) {
- return (0);
- } else {
- /* no certs printed */
- if (alias != NULL) {
- pkgerr_add(err, PKGERR_NOALIASMATCH,
- gettext(ERR_KEYSTORE_NOCERT),
- alias, keystore->path);
- } else {
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOPUBCERTS),
- keystore->path);
- pkgerr_add(err, PKGERR_NOCACERT,
- gettext(ERR_KEYSTORE_NOCACERTS),
- keystore->path);
- }
- return (1);
- }
-}
-
-/*
- * print_cert - prints a single certificate, to a file
- *
- * Arguments:
- * err - Error object to append errors to
- * x - The certificate to print
- * alias - Name of certificate to print
- * format - Format in which to print certificate
- * outfile - Where to print certificate
- *
- * Returns:
- * 0 - Success
- * non-zero - Failure, errors added to err
- */
-int print_cert(PKG_ERR *err, X509 *x,
- keystore_encoding_format_t format, char *alias, boolean_t is_trusted,
- FILE *outfile)
-{
-
- char *vdb_str;
- char *vda_str;
- char vd_str[ATTR_MAX];
- int ret = 0;
- char *cn_str, *icn_str, *typ_str;
- char *tmp;
- char *md5_fp;
- char *sha1_fp;
- int len;
-
- /* need to localize the word "Fingerprint", hence these pointers */
- char md5_label[ATTR_MAX];
- char sha1_label[ATTR_MAX];
-
- if (is_trusted) {
- typ_str = gettext(MSG_KEYSTORE_TRUSTED);
- } else {
- typ_str = gettext(MSG_KEYSTORE_UNTRUSTED);
- }
-
- if ((cn_str = get_subject_display_name(x)) == NULL) {
- cn_str = gettext(MSG_KEYSTORE_UNKNOWN);
- }
-
- if ((icn_str = get_issuer_display_name(x)) == NULL) {
- icn_str = gettext(MSG_KEYSTORE_UNKNOWN);
- }
-
- vdb_str = xstrdup(get_time_string(X509_get_notBefore(x)));
- vda_str = xstrdup(get_time_string(X509_get_notAfter(x)));
- if (((len = snprintf(vd_str, ATTR_MAX, "<%s> - <%s>",
- vdb_str, vda_str)) < 0) || (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), vdb_str);
- ret = 1;
- goto cleanup;
- }
-
- if ((tmp = get_fingerprint(x, EVP_md5())) == NULL) {
- md5_fp = gettext(MSG_KEYSTORE_UNKNOWN);
- } else {
- /*
- * make a copy, otherwise the next call to get_fingerprint
- * will overwrite this one
- */
- md5_fp = xstrdup(tmp);
- }
-
- if ((tmp = get_fingerprint(x, EVP_sha1())) == NULL) {
- sha1_fp = gettext(MSG_KEYSTORE_UNKNOWN);
- } else {
- sha1_fp = xstrdup(tmp);
- }
-
- (void) snprintf(md5_label, ATTR_MAX, "%s %s",
- OBJ_nid2sn(EVP_MD_type(EVP_md5())),
- /* i18n: 14 characters max */
- gettext(MSG_KEYSTORE_FP));
-
- (void) snprintf(sha1_label, ATTR_MAX, "%s %s",
- OBJ_nid2sn(EVP_MD_type(EVP_sha1())),
- /* i18n: 14 characters max */
- gettext(MSG_KEYSTORE_FP));
-
- switch (format) {
- case KEYSTORE_FORMAT_PEM:
- (void) PEM_write_X509(outfile, x);
- break;
- case KEYSTORE_FORMAT_DER:
- (void) i2d_X509_fp(outfile, x);
- break;
- case KEYSTORE_FORMAT_TEXT:
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_AL), alias);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_CN), cn_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_TY), typ_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_IN), icn_str);
- (void) fprintf(outfile, "%18s: %s\n",
- /* i18n: 18 characters max */
- gettext(MSG_KEYSTORE_VD), vd_str);
- (void) fprintf(outfile, "%18s: %s\n", md5_label, md5_fp);
- (void) fprintf(outfile, "%18s: %s\n", sha1_label, sha1_fp);
- (void) fprintf(outfile, "\n");
- break;
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ret = 1;
- goto cleanup;
- }
-
-cleanup:
- if (md5_fp != NULL)
- free(md5_fp);
- if (sha1_fp != NULL)
- free(sha1_fp);
- if (vda_str != NULL)
- free(vda_str);
- if (vdb_str != NULL)
- free(vdb_str);
- return (ret);
-}
-
-/*
- * open_keystore - Initialize new keystore object for
- * impending access.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore_file - Base filename or directory of keystore
- * app - Application making request
- * passwd - Password used to decrypt keystore
- * flags - Control flags used to control access mode and behavior
- * result - Resulting keystore object stored here on success
- *
- * Returns:
- * 0 - Success - result contains a pointer to the opened keystore
- * non-zero - Failure, errors added to err
- */
-int
-open_keystore(PKG_ERR *err, char *keystore_file, char *app,
- keystore_passphrase_cb cb, long flags, keystore_handle_t *result)
-{
- int ret = 0;
- keystore_t *tmpstore;
-
- tmpstore = new_keystore();
-
- tmpstore->dirty = B_FALSE;
- tmpstore->new = B_FALSE;
- tmpstore->path = xstrdup(keystore_file);
-
- if (!resolve_paths(err, keystore_file, app, flags, tmpstore)) {
- /* unable to determine keystore paths */
- pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- if (!verify_keystore_integrity(err, tmpstore)) {
- /* unable to repair keystore */
- pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- if (!lock_keystore(err, flags, tmpstore)) {
- pkgerr_add(err, PKGERR_LOCKED, gettext(ERR_KEYSTORE_LOCKED),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- /* now that we have locked the keystore, go ahead and read it */
- if (!read_keystore(err, tmpstore, cb)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_PARSE),
- keystore_file);
- ret = 1;
- goto cleanup;
- }
-
- *result = tmpstore;
- tmpstore = NULL;
-
-cleanup:
- if (tmpstore != NULL)
- free_keystore(tmpstore);
- return (ret);
-}
-
-/*
- * new_keystore - Allocates and initializes a Keystore object
- *
- * Arguments:
- * NONE
- *
- * Returns:
- * NULL - out of memory
- * otherwise, returns a pointer to the newly allocated object,
- * which should be freed with free_keystore() when no longer
- * needed.
- */
-static keystore_t
-*new_keystore(void)
-{
- keystore_t *tmpstore;
-
- if ((tmpstore = (keystore_t *)malloc(sizeof (keystore_t))) == NULL) {
- return (NULL);
- }
- tmpstore->dirty = B_FALSE;
- tmpstore->new = B_FALSE;
- tmpstore->path = NULL;
- tmpstore->passphrase = NULL;
- tmpstore->cafd = -1;
- tmpstore->cacerts = NULL;
- tmpstore->capath = NULL;
- tmpstore->clcerts = NULL;
- tmpstore->clpath = NULL;
- tmpstore->pkeys = NULL;
- tmpstore->keypath = NULL;
-
- return (tmpstore);
-}
-
-/*
- * free_keystore - Deallocates a Keystore object
- *
- * Arguments:
- * keystore - The keystore to deallocate
- *
- * Returns:
- * NONE
- */
-static void
-free_keystore(keystore_t *keystore)
-{
- if (keystore->path != NULL)
- free(keystore->path);
- if (keystore->capath != NULL)
- free(keystore->capath);
- if (keystore->passphrase != NULL)
- free(keystore->passphrase);
- if (keystore->clpath != NULL)
- free(keystore->clpath);
- if (keystore->keypath != NULL)
- free(keystore->keypath);
-
- if (keystore->pkeys != NULL) {
- sk_EVP_PKEY_pop_free(keystore->pkeys,
- sunw_evp_pkey_free);
- }
- if (keystore->clcerts != NULL)
- sk_X509_free(keystore->clcerts);
- if (keystore->cacerts != NULL)
- sk_X509_free(keystore->cacerts);
- free(keystore);
-}
-
-/*
- * close_keystore - Writes keystore to disk if needed, then
- * unlocks and closes keystore.
- *
- * Arguments:
- * err - Error object to append errors to
- * keystore - Keystore which should be closed
- * passwd - Password used to encrypt keystore
- *
- * Returns:
- * 0 - Success - keystore is committed to disk, and unlocked
- * non-zero - Failure, errors added to err
- */
-int
-close_keystore(PKG_ERR *err, keystore_handle_t keystore_h,
- keystore_passphrase_cb cb)
-{
- int ret = 0;
- keystore_t *keystore = keystore_h;
-
- if (keystore->dirty) {
- /* write out the keystore first */
- if (!write_keystore(err, keystore, cb)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->path);
- ret = 1;
- goto cleanup;
- }
- }
-
- if (!unlock_keystore(err, keystore)) {
- pkgerr_add(err, PKGERR_UNLOCK, gettext(ERR_KEYSTORE_UNLOCK),
- keystore->path);
- ret = 1;
- goto cleanup;
- }
-
- free_keystore(keystore);
-cleanup:
- return (ret);
-}
-
-/*
- * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
- * certificate checked for validity dates and non-duplicity.
- *
- * Arguments:
- * err - Error object to add errors to
- * cacert - Certificate which to merge into keystore
- * keystore - The keystore into which the certificate is merged
- *
- * Returns:
- * 0 - Success - Certificate passes validity, and
- * is merged into keystore
- * non-zero - Failure, errors recorded in err
- */
-int
-merge_ca_cert(PKG_ERR *err, X509 *cacert, keystore_handle_t keystore_h)
-{
-
- int ret = 0;
- X509 *existing = NULL;
- char *fname;
- keystore_t *keystore = keystore_h;
-
- /* check validity dates */
- if (check_cert(err, cacert) != 0) {
- ret = 1;
- goto cleanup;
- }
-
- /* create the certificate's friendlyName */
- fname = get_subject_display_name(cacert);
-
- if (sunw_set_fname(fname, NULL, cacert) != 0) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- /* merge certificate into the keystore */
- if (keystore->cacerts == NULL) {
- /* no existing truststore, so make a new one */
- if ((keystore->cacerts = sk_X509_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing truststore, make sure there's no duplicate */
- if (sunw_find_fname(fname, NULL, keystore->cacerts,
- NULL, &existing) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existing != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATECERT), fname);
- ret = 1;
- goto cleanup;
- }
- }
-
- (void) sk_X509_push(keystore->cacerts, cacert);
- keystore->dirty = B_TRUE;
-cleanup:
- if (existing != NULL)
- X509_free(existing);
- return (ret);
-}
-
-/*
- * find_key_cert_pair - Searches a keystore for a matching
- * public key certificate and private key, given an alias.
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * alias - Name to used to match certificate's alias
- * key - Resulting key is placed here
- * cert - Resulting cert is placed here
- *
- * Returns:
- * 0 - Success - Matching cert/key pair placed in key and cert.
- * non-zero - Failure, errors recorded in err
- */
-int
-find_key_cert_pair(PKG_ERR *err, keystore_handle_t ks_h, char *alias,
- EVP_PKEY **key, X509 **cert)
-{
- X509 *tmpcert = NULL;
- EVP_PKEY *tmpkey = NULL;
- int ret = 0;
- int items_found;
- keystore_t *ks = ks_h;
-
- if (key == NULL || cert == NULL) {
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOPUBCERTS), ks->path);
- ret = 1;
- goto cleanup;
- }
-
- if (ks->clcerts == NULL) {
- /* no public certs */
- pkgerr_add(err, PKGERR_NOPUBKEY,
- gettext(ERR_KEYSTORE_NOCERTS), ks->path);
- ret = 1;
- goto cleanup;
- }
- if (ks->pkeys == NULL) {
- /* no private keys */
- pkgerr_add(err, PKGERR_NOPRIVKEY,
- gettext(ERR_KEYSTORE_NOKEYS), ks->path);
- ret = 1;
- goto cleanup;
- }
-
- /* try the easy case first */
- if ((sk_EVP_PKEY_num(ks->pkeys) == 1) &&
- (sk_X509_num(ks->clcerts) == 1)) {
- tmpkey = sk_EVP_PKEY_value(ks->pkeys, 0);
- tmpcert = sk_X509_value(ks->clcerts, 0);
- if (sunw_check_keys(tmpcert, tmpkey)) {
- /*
- * only one private key and public key cert, and they
- * match, so use them
- */
- *key = tmpkey;
- tmpkey = NULL;
- *cert = tmpcert;
- tmpcert = NULL;
- goto cleanup;
- }
- }
-
- /* Attempt to find the right pair given the alias */
- items_found = sunw_find_fname(alias, ks->pkeys, ks->clcerts,
- &tmpkey, &tmpcert);
-
- if ((items_found < 0) ||
- (items_found & (FOUND_PKEY | FOUND_CERT)) == 0) {
- /* no key/cert pair found. bail. */
- pkgerr_add(err, PKGERR_BADALIAS,
- gettext(ERR_KEYSTORE_NOMATCH), alias);
- ret = 1;
- goto cleanup;
- }
-
- /* success */
- *key = tmpkey;
- tmpkey = NULL;
- *cert = tmpcert;
- tmpcert = NULL;
-
-cleanup:
-
- if (tmpcert != NULL)
- (void) X509_free(tmpcert);
-
- if (tmpkey != NULL)
- sunw_evp_pkey_free(tmpkey);
-
- return (ret);
-}
-
-/*
- * find_ca_certs - Searches a keystore for trusted certificates
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * cacerts - resulting set of trusted certs are placed here
- *
- * Returns:
- * 0 - Success - trusted cert list returned in cacerts
- * non-zero - Failure, errors recorded in err
- */
-int
-find_ca_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **cacerts)
-{
-
- keystore_t *ks = ks_h;
-
- /* easy */
- if (cacerts == NULL) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL), __FILE__, __LINE__);
- return (1);
- }
-
- *cacerts = ks->cacerts;
- return (0);
-}
-
-/*
- * find_cl_certs - Searches a keystore for user certificates
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - Keystore to search
- * cacerts - resulting set of user certs are placed here
- *
- * No matching of any kind is performed.
- * Returns:
- * 0 - Success - trusted cert list returned in cacerts
- * non-zero - Failure, errors recorded in err
- */
-/* ARGSUSED */
-int
-find_cl_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **clcerts)
-{
- keystore_t *ks = ks_h;
-
- /* easy */
- *clcerts = ks->clcerts;
- return (0);
-}
-
-
-/*
- * merge_cert_and_key - Adds a user certificate and matching
- * private key to a keystore.
- * certificate checked for validity dates and non-duplicity.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - Certificate which to merge into keystore
- * key - matching private key to 'cert'
- * alias - Name which to store the cert and key under
- * keystore - The keystore into which the certificate is merged
- *
- * Returns:
- * 0 - Success - Certificate passes validity, and
- * is merged into keystore, along with key
- * non-zero - Failure, errors recorded in err
- */
-int
-merge_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key, char *alias,
- keystore_handle_t keystore_h)
-{
- X509 *existingcert = NULL;
- EVP_PKEY *existingkey = NULL;
- int ret = 0;
- keystore_t *keystore = keystore_h;
-
- /* check validity dates */
- if (check_cert(err, cert) != 0) {
- ret = 1;
- goto cleanup;
- }
-
- /* set the friendlyName of the key and cert to the supplied alias */
- if (sunw_set_fname(alias, key, cert) != 0) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- /* merge certificate and key into the keystore */
- if (keystore->clcerts == NULL) {
- /* no existing truststore, so make a new one */
- if ((keystore->clcerts = sk_X509_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing certstore, make sure there's no duplicate */
- if (sunw_find_fname(alias, NULL, keystore->clcerts,
- NULL, &existingcert) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existingcert != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATECERT), alias);
- ret = 1;
- goto cleanup;
- }
- }
-
- if (keystore->pkeys == NULL) {
- /* no existing keystore, so make a new one */
- if ((keystore->pkeys = sk_EVP_PKEY_new_null()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- } else {
- /* existing keystore, so make sure there's no duplicate entry */
- if (sunw_find_fname(alias, keystore->pkeys, NULL,
- &existingkey, NULL) < 0) {
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ERR_print_errors_fp(stderr);
- ret = 1;
- goto cleanup;
- /* could not search properly! */
- }
- if (existingkey != NULL) {
- /* whoops, found one already */
- pkgerr_add(err, PKGERR_DUPLICATE,
- gettext(ERR_KEYSTORE_DUPLICATEKEY), alias);
- ret = 1;
- goto cleanup;
- }
- }
-
- (void) sk_X509_push(keystore->clcerts, cert);
- (void) sk_EVP_PKEY_push(keystore->pkeys, key);
- keystore->dirty = B_TRUE;
-cleanup:
- if (existingcert != NULL)
- (void) X509_free(existingcert);
- if (existingkey != NULL)
- (void) sunw_evp_pkey_free(existingkey);
- return (ret);
-}
-
-/*
- * delete_cert_and_keys - Deletes one or more certificates
- * and matching private keys from a keystore.
- *
- * Arguments:
- * err - Error object to add errors to
- * ks - The keystore from which certs and keys are deleted
- * alias - Name which to search for certificates and keys
- * to delete
- *
- * Returns:
- * 0 - Success - All trusted certs which match 'alias'
- * are deleted. All user certificates
- * which match 'alias' are deleted, along
- * with the matching private key.
- * non-zero - Failure, errors recorded in err
- */
-int
-delete_cert_and_keys(PKG_ERR *err, keystore_handle_t ks_h, char *alias)
-{
- X509 *existingcert;
- EVP_PKEY *existingkey;
- int i;
- char *fname = NULL;
- boolean_t found = B_FALSE;
- keystore_t *ks = ks_h;
-
- /* delete any and all client certs with the supplied name */
- if (ks->clcerts != NULL) {
- for (i = 0; i < sk_X509_num(ks->clcerts); i++) {
- existingcert = sk_X509_value(ks->clcerts, i);
- if (sunw_get_cert_fname(GETDO_COPY,
- existingcert, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingcert =
- sk_X509_delete(ks->clcerts, i);
- X509_free(existingcert);
- existingcert = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_X509_num(ks->clcerts) <= 0) {
- /* we deleted all the client certs */
- sk_X509_free(ks->clcerts);
- ks->clcerts = NULL;
- }
- }
-
- /* and now the private keys */
- if (ks->pkeys != NULL) {
- for (i = 0; i < sk_EVP_PKEY_num(ks->pkeys); i++) {
- existingkey = sk_EVP_PKEY_value(ks->pkeys, i);
- if (sunw_get_pkey_fname(GETDO_COPY,
- existingkey, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingkey =
- sk_EVP_PKEY_delete(ks->pkeys, i);
- sunw_evp_pkey_free(existingkey);
- existingkey = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_EVP_PKEY_num(ks->pkeys) <= 0) {
- /* we deleted all the private keys */
- sk_EVP_PKEY_free(ks->pkeys);
- ks->pkeys = NULL;
- }
- }
-
- /* finally, remove any trust anchors that match */
-
- if (ks->cacerts != NULL) {
- for (i = 0; i < sk_X509_num(ks->cacerts); i++) {
- existingcert = sk_X509_value(ks->cacerts, i);
- if (sunw_get_cert_fname(GETDO_COPY,
- existingcert, &fname) >= 0) {
- if (streq(fname, alias)) {
- /* match, so nuke it */
- existingcert =
- sk_X509_delete(ks->cacerts, i);
- X509_free(existingcert);
- existingcert = NULL;
- found = B_TRUE;
- }
- (void) OPENSSL_free(fname);
- fname = NULL;
- }
- }
- if (sk_X509_num(ks->cacerts) <= 0) {
- /* we deleted all the CA certs */
- sk_X509_free(ks->cacerts);
- ks->cacerts = NULL;
- }
- }
-
- if (found) {
- ks->dirty = B_TRUE;
- return (0);
- } else {
- /* no certs or keys deleted */
- pkgerr_add(err, PKGERR_NOALIASMATCH,
- gettext(ERR_KEYSTORE_NOCERTKEY),
- alias, ks->path);
- return (1);
- }
-}
-
-/*
- * check_cert - Checks certificate validity. This routine
- * checks that the current time falls within the period
- * of validity for the cert.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - The certificate to check
- *
- * Returns:
- * 0 - Success - Certificate checks out
- * non-zero - Failure, errors and reasons recorded in err
- */
-int
-check_cert(PKG_ERR *err, X509 *cert)
-{
- char currtimestr[ATTR_MAX];
- time_t currtime;
- char *r;
- /* get current time */
- if ((currtime = time(NULL)) == (time_t)-1) {
- pkgerr_add(err, PKGERR_TIME, gettext(ERR_CURR_TIME));
- return (1);
- }
-
- (void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX);
-
- /* trim whitespace from end of time string */
- for (r = (currtimestr + strlen(currtimestr) - 1); isspace(*r); r--) {
- *r = '\0';
- }
- /* check validity of cert */
- switch (sunw_check_cert_times(CHK_BOTH, cert)) {
- case CHKERR_TIME_OK:
- /* Current time meets requested checks */
- break;
- case CHKERR_TIME_BEFORE_BAD:
- /* 'not before' field is invalid */
- case CHKERR_TIME_AFTER_BAD:
- /* 'not after' field is invalid */
- pkgerr_add(err, PKGERR_TIME, gettext(ERR_CERT_TIME_BAD));
- return (1);
- case CHKERR_TIME_IS_BEFORE:
- /* Current time is before 'not before' */
- case CHKERR_TIME_HAS_EXPIRED:
- /*
- * Ignore expiration time since the trust cert used to
- * verify the certs used to sign Sun patches is already
- * expired. Once the patches get resigned with the new
- * cert we will check expiration against the time the
- * patch was signed and not the time it is installed.
- */
- return (0);
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- return (1);
- }
-
- /* all checks ok */
- return (0);
-}
-
-/*
- * check_cert - Checks certificate validity. This routine
- * checks everything that check_cert checks, and additionally
- * verifies that the private key and corresponding public
- * key are indeed a pair.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - The certificate to check
- * key - the key to check
- * Returns:
- * 0 - Success - Certificate checks out
- * non-zero - Failure, errors and reasons recorded in err
- */
-int
-check_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key)
-{
-
- /* check validity dates */
- if (check_cert(err, cert) != 0) {
- return (1);
- }
-
- /* check key pair match */
- if (sunw_check_keys(cert, key) == 0) {
- pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MISMATCHED_KEYS),
- get_subject_display_name(cert));
- return (1);
- }
-
- /* all checks OK */
- return (0);
-}
-
-/* ------------------ private functions ---------------------- */
-
-/*
- * verify_keystore_integrity - Searches for the remnants
- * of a failed or aborted keystore modification, and
- * cleans up the files, retstores the keystore to a known
- * state.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - Base directory or filename of keystore
- * app - Application making request
- *
- * Returns:
- * 0 - Success - Keystore is restored, or untouched in the
- * case that cleanup was unnecessary
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-verify_keystore_integrity(PKG_ERR *err, keystore_t *keystore)
-{
- if (keystore->capath != NULL) {
- if (!restore_keystore_file(err, keystore->capath)) {
- return (B_FALSE);
- }
- }
- if (keystore->clpath != NULL) {
- if (!restore_keystore_file(err, keystore->clpath)) {
- return (B_FALSE);
- }
- }
- if (keystore->keypath != NULL) {
- if (!restore_keystore_file(err, keystore->keypath)) {
- return (B_FALSE);
- }
- }
- return (B_TRUE);
-}
-
-/*
- * restore_keystore_file - restores a keystore file to
- * a known state.
- *
- * Keystore files can possibly be corrupted by a variety
- * of error conditions during reading/writing. This
- * routine, along with write_keystore_file, tries to
- * maintain keystore integrity by writing the files
- * out in a particular order, minimizing the time period
- * that the keystore is in an indeterminate state.
- *
- * With the current implementation, there are some failures
- * that are wholly unrecoverable, such as disk corruption.
- * These routines attempt to minimize the risk, but not
- * eliminate it. When better, atomic operations are available
- * (such as a trued atabase with commit, rollback, and
- * guaranteed atomicity), this implementation should use that.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - keystore file path to restore.
- *
- * Returns:
- * 0 - Success - Keystore file is restored, or untouched in the
- * case that cleanup was unnecessary
- * non-zero - Failure, errors and reasons recorded in err
- */
-/* ARGSUSED */
-static boolean_t
-restore_keystore_file(PKG_ERR *err, char *keystore_file)
-{
- char newpath[MAXPATHLEN];
- char backuppath[MAXPATHLEN];
- int newfd;
- struct stat buf;
- int len;
-
- if (((len = snprintf(newpath, MAXPATHLEN, "%s.new",
- keystore_file)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
- return (B_FALSE);
- }
-
- if (((len = snprintf(backuppath, MAXPATHLEN, "%s.bak",
- keystore_file)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file);
- return (B_FALSE);
- }
-
- if ((newfd = open(newpath, O_RDWR|O_NONBLOCK, 0)) != -1) {
- if (fstat(newfd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- /*
- * restore the file, waiting on it
- * to be free for locking, or for
- * it to disappear
- */
- if (!wait_restore(newfd, keystore_file,
- newpath, backuppath)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_WRITE),
- newpath, strerror(errno));
- (void) close(newfd);
- return (B_FALSE);
- } else {
- return (B_TRUE);
- }
- } else {
- /* "new" file is not a regular file */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_NOT_REG), newpath);
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /* couldn't stat "new" file */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_WRITE), newpath,
- strerror(errno));
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /* "new" file doesn't exist */
- return (B_TRUE);
- }
-}
-
-static boolean_t
-wait_restore(int newfd, char *keystore_file,
- char *origpath, char *backuppath)
-{
- struct stat buf;
- FILE *newstream;
- PKCS12 *p12;
-
- (void) alarm(LOCK_TIMEOUT);
- if (file_lock(newfd, F_WRLCK, 1) == -1) {
- /* could not lock file */
- (void) alarm(0);
- return (B_FALSE);
- }
- (void) alarm(0);
-
- if (fstat(newfd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- /*
- * The new file still
- * exists, with no
- * owner. It must be
- * the result of an
- * aborted update.
- */
- newstream = fdopen(newfd, "r");
- if ((p12 =
- d2i_PKCS12_fp(newstream,
- NULL)) != NULL) {
- /*
- * The file
- * appears
- * complete.
- * Replace the
- * exsisting
- * keystore
- * file with
- * this one
- */
- (void) rename(keystore_file, backuppath);
- (void) rename(origpath, keystore_file);
- PKCS12_free(p12);
- } else {
- /* The file is not complete. Remove it */
- (void) remove(origpath);
- }
- /* remove backup file */
- (void) remove(backuppath);
- (void) fclose(newstream);
- (void) close(newfd);
- return (B_TRUE);
- } else {
- /*
- * new file exists, but is not a
- * regular file
- */
- (void) close(newfd);
- return (B_FALSE);
- }
- } else {
- /*
- * could not stat file. Unless
- * the reason was that the file
- * is now gone, this is an error
- */
- if (errno != ENOENT) {
- (void) close(newfd);
- return (B_FALSE);
- }
- /*
- * otherwise, file is gone. The process
- * that held the lock must have
- * successfully cleaned up and
- * exited with a valid keystore
- * state
- */
- (void) close(newfd);
- return (B_TRUE);
- }
-}
-
-/*
- * resolve_paths - figure out if we are dealing with a single-file
- * or multi-file keystore
- *
- * The flags tell resolve_paths how to behave:
- *
- * KEYSTORE_PATH_SOFT
- * If the keystore file does not exist at <base>/<app> then
- * use <base> as the path to the keystore. This can be used,
- * for example, to access an app-specific keystore iff it
- * exists, otherwise revert back to an app-generic keystore.
- *
- * KEYSTORE_PATH_HARD
- * Always use the keystore located at <keystore_path>/<app>.
- * In read/write mode, if the files do not exist, then
- * they will be created. This is used to avoid falling
- * back to an app-generic keystore path when the app-specific
- * one does not exist.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore_file - base keystore file path to lock
- * app - Application making requests
- * flags - Control flags (see above description)
- * keystore - object which is being locked
- *
- * Returns:
- * B_TRUE - Success - Keystore file is locked, paths to
- * appropriate files placed in keystore.
- * B_FALSE - Failure, errors and reasons recorded in err
- */
-static boolean_t
-resolve_paths(PKG_ERR *err, char *keystore_file, char *app,
- long flags, keystore_t *keystore)
-{
- char storepath[PATH_MAX];
- struct stat buf;
- boolean_t multi = B_FALSE;
- int fd1, fd2, len;
-
- /*
- * figure out whether we are dealing with a single-file keystore
- * or a multi-file keystore
- */
- if (app != NULL) {
- if (((len = snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, app)) < 0) ||
- (len >= ATTR_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN),
- keystore_file);
- return (B_FALSE);
- }
-
- if (((fd1 = open(storepath, O_NONBLOCK|O_RDONLY)) == -1) ||
- (fstat(fd1, &buf) == -1) ||
- !S_ISDIR(buf.st_mode)) {
- /*
- * app-specific does not exist
- * fallback to app-generic, if flags say we can
- */
- if ((flags & KEYSTORE_PATH_MASK) ==
- KEYSTORE_PATH_SOFT) {
-
- if (((fd2 = open(keystore_file,
- O_NONBLOCK|O_RDONLY)) != -1) &&
- (fstat(fd2, &buf) != -1)) {
- if (S_ISDIR(buf.st_mode)) {
- /*
- * app-generic dir
- * exists, so use it
- * as a multi-file
- * keystore
- */
- multi = B_TRUE;
- app = NULL;
- } else if (S_ISREG(buf.st_mode)) {
- /*
- * app-generic file exists, so
- * use it as a single file ks
- */
- multi = B_FALSE;
- app = NULL;
- }
- }
- }
- }
- if (fd1 != -1)
- (void) close(fd1);
- if (fd2 != -1)
- (void) close(fd2);
- } else {
- if (((fd1 = open(keystore_file,
- O_NONBLOCK|O_RDONLY)) != -1) &&
- (fstat(fd1, &buf) != -1) &&
- S_ISDIR(buf.st_mode)) {
- /*
- * app-generic dir exists, so use
- * it as a multi-file keystore
- */
- multi = B_TRUE;
- }
- if (fd1 != -1)
- (void) close(fd1);
- }
-
- if (app != NULL) {
- /* app-specific keystore */
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, TRUSTSTORE);
- keystore->capath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, CERTSTORE);
- keystore->clpath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s/%s",
- keystore_file, app, KEYSTORE);
- keystore->keypath = xstrdup(storepath);
- } else {
- /* app-generic keystore */
- if (!multi) {
- /* single-file app-generic keystore */
- keystore->capath = xstrdup(keystore_file);
- keystore->keypath = NULL;
- keystore->clpath = NULL;
- } else {
- /* multi-file app-generic keystore */
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, TRUSTSTORE);
- keystore->capath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, CERTSTORE);
- keystore->clpath = xstrdup(storepath);
- (void) snprintf(storepath, PATH_MAX, "%s/%s",
- keystore_file, KEYSTORE);
- keystore->keypath = xstrdup(storepath);
- }
- }
-
- return (B_TRUE);
-}
-
-/*
- * lock_keystore - Locks a keystore for shared (read-only)
- * or exclusive (read-write) access.
- *
- * The flags tell lock_keystore how to behave:
- *
- * KEYSTORE_ACCESS_READONLY
- * opens keystore read-only. Attempts to modify results in an error
- *
- * KEYSTORE_ACCESS_READWRITE
- * opens keystore read-write
- *
- * KEYSTORE_PATH_SOFT
- * If the keystore file does not exist at <base>/<app> then
- * use <base> as the path to the keystore. This can be used,
- * for example, to access an app-specific keystore iff it
- * exists, otherwise revert back to an app-generic keystore.
- *
- * KEYSTORE_PATH_HARD
- * Always use the keystore located at <keystore_path>/<app>.
- * In read/write mode, if the files do not exist, then
- * they will be created. This is used to avoid falling
- * back to an app-generic keystore path when the app-specific
- * one does not exist.
- *
- * Arguments:
- * err - Error object to add errors to
- * flags - Control flags (see above description)
- * keystore - object which is being locked
- *
- * Returns:
- * 0 - Success - Keystore file is locked, paths to
- * appropriate files placed in keystore.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-lock_keystore(PKG_ERR *err, long flags, keystore_t *keystore)
-{
- boolean_t ret = B_TRUE;
- struct stat buf;
-
- switch (flags & KEYSTORE_ACCESS_MASK) {
- case KEYSTORE_ACCESS_READONLY:
- if ((keystore->cafd =
- open(keystore->capath, O_NONBLOCK|O_RDONLY)) == -1) {
- if (errno == ENOENT) {
- /*
- * no keystore. try to create an
- * empty one so we can lock on it and
- * prevent others from gaining
- * exclusive access. It will be
- * deleted when the keystore is closed.
- */
- if ((keystore->cafd =
- open(keystore->capath,
- O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NO_KEYSTORE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- }
- if (fstat(keystore->cafd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- if (file_lock(keystore->cafd, F_RDLCK,
- 0) == -1) {
- pkgerr_add(err, PKGERR_LOCKED,
- gettext(ERR_KEYSTORE_LOCKED_READ),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* ca file not a regular file! */
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NOT_REG),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- break;
- case KEYSTORE_ACCESS_READWRITE:
-
- if ((keystore->cafd = open(keystore->capath,
- O_RDWR|O_NONBLOCK)) == -1) {
- /* does not exist. try to create an empty one */
- if (errno == ENOENT) {
- if ((keystore->cafd =
- open(keystore->capath,
- O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- }
- if (fstat(keystore->cafd, &buf) != -1) {
- if (S_ISREG(buf.st_mode)) {
- if (file_lock(keystore->cafd, F_WRLCK,
- 0) == -1) {
- pkgerr_add(err, PKGERR_LOCKED,
- gettext(ERR_KEYSTORE_LOCKED),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* ca file not a regular file! */
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_NOT_REG),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- pkgerr_add(err, PKGERR_READ,
- gettext(ERR_KEYSTORE_OPEN),
- keystore->capath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- break;
- default:
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_KEYSTORE_INTERNAL),
- __FILE__, __LINE__);
- ret = B_FALSE;
- goto cleanup;
- }
-
-cleanup:
- if (!ret) {
- if (keystore->cafd > 0) {
- (void) file_unlock(keystore->cafd);
- (void) close(keystore->cafd);
- keystore->cafd = -1;
- }
-
- if (keystore->capath != NULL)
- free(keystore->capath);
- if (keystore->clpath != NULL)
- free(keystore->clpath);
- if (keystore->keypath != NULL)
- free(keystore->keypath);
- keystore->capath = NULL;
- keystore->clpath = NULL;
- keystore->keypath = NULL;
- }
-
- return (ret);
-}
-
-/*
- * unlock_keystore - Unocks a keystore
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to unlock
- * Returns:
- * 0 - Success - Keystore files are unlocked, files are closed,
- * non-zero - Failure, errors and reasons recorded in err
- */
-/* ARGSUSED */
-static boolean_t
-unlock_keystore(PKG_ERR *err, keystore_t *keystore)
-{
-
- /*
- * Release lock on the CA file.
- * Delete file if it is empty
- */
- if (file_empty(keystore->capath)) {
- (void) remove(keystore->capath);
- }
-
- (void) file_unlock(keystore->cafd);
- (void) close(keystore->cafd);
- return (B_TRUE);
-}
-
-/*
- * read_keystore - Reads keystore files of disk, parses
- * into internal structures.
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to read into
- * cb - callback to get password, if required
- * Returns:
- * 0 - Success - Keystore files are read, and placed
- * into keystore structure.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-read_keystore(PKG_ERR *err, keystore_t *keystore, keystore_passphrase_cb cb)
-{
- boolean_t ret = B_TRUE;
- PKCS12 *p12 = NULL;
- boolean_t ca_empty;
- boolean_t have_passwd = B_FALSE;
- boolean_t cl_empty = B_TRUE;
- boolean_t key_empty = B_TRUE;
-
- ca_empty = file_empty(keystore->capath);
-
- if (keystore->clpath != NULL)
- cl_empty = file_empty(keystore->clpath);
- if (keystore->keypath != NULL)
- key_empty = file_empty(keystore->keypath);
-
- if (ca_empty && cl_empty && key_empty) {
- keystore->new = B_TRUE;
- }
-
- if (!ca_empty) {
- /* first read the ca file */
- if ((p12 = read_keystore_file(err,
- keystore->capath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb, keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- /* decrypt and parse keystore file */
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- &keystore->pkeys, &keystore->cacerts) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
-
- /*
- * truststore is empty, so we don't have any trusted
- * certs
- */
- keystore->cacerts = NULL;
- }
-
- /*
- * if there is no cl file or key file, use the cl's and key's found
- * in the ca file
- */
- if (keystore->clpath == NULL && !ca_empty) {
- if (sunw_split_certs(keystore->pkeys, keystore->cacerts,
- &keystore->clcerts, NULL) < 0) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * files are in separate files. read keys out of the keystore
- * certs out of the certstore, if they are not empty
- */
- if (!cl_empty) {
- if ((p12 = read_keystore_file(err,
- keystore->clpath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb,
- keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- if (check_password(p12,
- keystore->passphrase) == B_FALSE) {
- /*
- * password in client cert file
- * is different than
- * the one in the other files!
- */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_MISMATCHPASS),
- keystore->clpath,
- keystore->capath, keystore->path);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- NULL, &keystore->clcerts) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- keystore->clcerts = NULL;
- }
-
- if (!key_empty) {
- if ((p12 = read_keystore_file(err,
- keystore->keypath)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Get password, using callback if necessary */
- if (!have_passwd) {
- if (!get_keystore_passwd(err, p12, cb,
- keystore)) {
- ret = B_FALSE;
- goto cleanup;
- }
- have_passwd = B_TRUE;
- }
-
- if (check_password(p12,
- keystore->passphrase) == B_FALSE) {
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_MISMATCHPASS),
- keystore->keypath,
- keystore->capath, keystore->path);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (sunw_PKCS12_contents(p12, keystore->passphrase,
- &keystore->pkeys, NULL) < 0) {
- /* could not parse the contents */
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- keystore->pkeys = NULL;
- }
- }
-
-cleanup:
- if (p12 != NULL)
- PKCS12_free(p12);
- return (ret);
-}
-
-/*
- * get_keystore_password - retrieves pasword used to
- * decrypt PKCS12 structure.
- *
- * Arguments:
- * err - Error object to add errors to
- * p12 - PKCS12 structure which returned password should
- * decrypt
- * cb - callback to collect password.
- * keystore - The keystore in which the PKCS12 structure
- * will eventually populate.
- * Returns:
- * B_TRUE - success.
- * keystore password is set in keystore->passphrase.
- * B_FALSE - failure, errors logged
- */
-static boolean_t
-get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, keystore_passphrase_cb cb,
- keystore_t *keystore)
-{
- char *passwd;
- char passbuf[KEYSTORE_PASS_MAX + 1];
- keystore_passphrase_data data;
-
- /* see if no password is the right password */
- if (check_password(p12, "") == B_TRUE) {
- passwd = "";
- } else if (check_password(p12, NULL) == B_TRUE) {
- passwd = NULL;
- } else {
- /* oops, it's encrypted. get password */
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX, 0,
- &data) == -1) {
- /* could not get password */
- return (B_FALSE);
- }
-
- if (check_password(p12, passbuf) == B_FALSE) {
- /* wrong password */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(ERR_BADPASS));
- return (B_FALSE);
- }
-
- /*
- * make copy of password buffer, since it
- * goes away upon return
- */
- passwd = xstrdup(passbuf);
- }
- keystore->passphrase = passwd;
- return (B_TRUE);
-}
-
-/*
- * write_keystore - Writes keystore files to disk
- *
- * Arguments:
- * err - Error object to add errors to
- * keystore - keystore object to write from
- * passwd - password used to encrypt keystore
- * Returns:
- * 0 - Success - Keystore contents are written out to
- * the same locations as read from
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-write_keystore(PKG_ERR *err, keystore_t *keystore,
- keystore_passphrase_cb cb)
-{
- PKCS12 *p12 = NULL;
- boolean_t ret = B_TRUE;
- keystore_passphrase_data data;
- char passbuf[KEYSTORE_PASS_MAX + 1];
-
- if (keystore->capath != NULL && keystore->clpath == NULL &&
- keystore->keypath == NULL) {
-
- /*
- * keystore is a file.
- * just write out a single file
- */
- if ((keystore->pkeys == NULL) &&
- (keystore->clcerts == NULL) &&
- (keystore->cacerts == NULL)) {
- if (!clear_keystore_file(err, keystore->capath)) {
- /*
- * no keys or certs to write out, so
- * blank the ca file. we do not
- * delete it since it is used as a
- * lock by lock_keystore() in
- * subsequent invocations
- */
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * if the keystore is being created for the first time,
- * prompt for a passphrase for encryption
- */
- if (keystore->new) {
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX,
- 1, &data) == -1) {
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /*
- * use the one used when the keystore
- * was read
- */
- (void) strlcpy(passbuf, keystore->passphrase,
- KEYSTORE_PASS_MAX);
- }
-
- p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
- keystore->clcerts, keystore->cacerts);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->capath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- } else {
- /* files are seprate. Do one at a time */
-
- /*
- * if the keystore is being created for the first time,
- * prompt for a passphrase for encryption
- */
- if (keystore->new && ((keystore->pkeys != NULL) ||
- (keystore->clcerts != NULL) ||
- (keystore->cacerts != NULL))) {
- data.err = err;
- if (cb(passbuf, KEYSTORE_PASS_MAX,
- 1, &data) == -1) {
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* use the one used when the keystore was read */
- (void) strlcpy(passbuf, keystore->passphrase,
- KEYSTORE_PASS_MAX);
- }
-
- /* do private keys first */
- if (keystore->pkeys != NULL) {
- p12 = sunw_PKCS12_create(passbuf, keystore->pkeys,
- NULL, NULL);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->keypath,
- p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- } else {
- if ((remove(keystore->keypath) != 0) &&
- (errno != ENOENT)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_REMOVE),
- keystore->keypath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- /* do user certs next */
- if (keystore->clcerts != NULL) {
- p12 = sunw_PKCS12_create(passbuf, NULL,
- keystore->clcerts, NULL);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->clpath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- } else {
- if ((remove(keystore->clpath) != 0) &&
- (errno != ENOENT)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_REMOVE),
- keystore->clpath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
-
- /* finally do CA cert file */
- if (keystore->cacerts != NULL) {
- p12 = sunw_PKCS12_create(passbuf, NULL,
- NULL, keystore->cacerts);
-
- if (p12 == NULL) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_FORM),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!write_keystore_file(err, keystore->capath, p12)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- PKCS12_free(p12);
- p12 = NULL;
- } else {
- /*
- * nothing to write out, so truncate the file
- * (it will be deleted during close_keystore)
- */
- if (!clear_keystore_file(err, keystore->capath)) {
- pkgerr_add(err, PKGERR_WRITE,
- gettext(ERR_KEYSTORE_WRITE),
- keystore->capath);
- ret = B_FALSE;
- goto cleanup;
- }
- }
- }
-
-cleanup:
- if (p12 != NULL)
- PKCS12_free(p12);
-
- return (ret);
-}
-
-/*
- * clear_keystore_file - Clears (zeros out) a keystore file.
- *
- * Arguments:
- * err - Error object to add errors to
- * dest - Path of keystore file to zero out.
- * Returns:
- * 0 - Success - Keystore file is truncated to zero length
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-clear_keystore_file(PKG_ERR *err, char *dest)
-{
- int fd;
- struct stat buf;
-
- fd = open(dest, O_RDWR|O_NONBLOCK);
- if (fd == -1) {
- /* can't open for writing */
- pkgerr_add(err, PKGERR_WRITE, gettext(MSG_OPEN),
- errno);
- return (B_FALSE);
- }
-
- if ((fstat(fd, &buf) == -1) || !S_ISREG(buf.st_mode)) {
- /* not a regular file */
- (void) close(fd);
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_NOT_REG),
- dest);
- return (B_FALSE);
- }
-
- if (ftruncate(fd, 0) == -1) {
- (void) close(fd);
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_WRITE),
- dest, strerror(errno));
- return (B_FALSE);
- }
-
- (void) close(fd);
- return (B_TRUE);
-}
-
-/*
- * write_keystore_file - Writes keystore file to disk.
- *
- * Keystore files can possibly be corrupted by a variety
- * of error conditions during reading/writing. This
- * routine, along with restore_keystore_file, tries to
- * maintain keystore integity by writing the files
- * out in a particular order, minimizing the time period
- * that the keystore is in an indeterminate state.
- *
- * With the current implementation, there are some failures
- * that are wholly unrecoverable, such as disk corruption.
- * These routines attempt to minimize the risk, but not
- * eliminate it. When better, atomic operations are available
- * (such as a true database with commit, rollback, and
- * guaranteed atomicity), this implementation should use that.
- *
- *
- * Arguments:
- * err - Error object to add errors to
- * dest - Destination filename
- * contents - Contents to write to the file
- * Returns:
- * 0 - Success - Keystore contents are written out to
- * the destination.
- * non-zero - Failure, errors and reasons recorded in err
- */
-static boolean_t
-write_keystore_file(PKG_ERR *err, char *dest, PKCS12 *contents)
-{
- FILE *newfile = NULL;
- boolean_t ret = B_TRUE;
- char newpath[MAXPATHLEN];
- char backuppath[MAXPATHLEN];
- struct stat buf;
- int fd;
-
- (void) snprintf(newpath, MAXPATHLEN, "%s.new", dest);
- (void) snprintf(backuppath, MAXPATHLEN, "%s.bak", dest);
-
- if ((fd = open(newpath, O_CREAT|O_EXCL|O_WRONLY|O_NONBLOCK,
- S_IRUSR|S_IWUSR)) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
- newpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if ((newfile = fdopen(fd, "w")) == NULL) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- newpath, strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (i2d_PKCS12_fp(newfile, contents) == 0) {
- pkgerr_add(err, PKGERR_WRITE, gettext(ERR_KEYSTORE_WRITE),
- newpath);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* flush, then close */
- (void) fflush(newfile);
- (void) fclose(newfile);
- newfile = NULL;
-
- /* now back up the original file */
- (void) rename(dest, backuppath);
-
- /* put new one in its place */
- (void) rename(newpath, dest);
-
- /* remove backup */
- (void) remove(backuppath);
-
-cleanup:
- if (newfile != NULL)
- (void) fclose(newfile);
- if (fd != -1)
- (void) close(fd);
-
- return (ret);
-}
-
-/*
- * read_keystore_file - Reads single keystore file
- * off disk in PKCS12 format.
- *
- * Arguments:
- * err - Error object to add errors to
- * file - File path to read
- * Returns:
- * PKCS12 contents of file, or NULL if an error occurred.
- * errors recorded in 'err'.
- */
-static PKCS12
-*read_keystore_file(PKG_ERR *err, char *file)
-{
- int fd;
- struct stat buf;
- FILE *newfile;
- PKCS12 *p12 = NULL;
-
- if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG),
- file);
- goto cleanup;
- }
-
- if ((newfile = fdopen(fd, "r")) == NULL) {
- pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN),
- file, strerror(errno));
- goto cleanup;
- }
-
- if ((p12 = d2i_PKCS12_fp(newfile, NULL)) == NULL) {
- pkgerr_add(err, PKGERR_CORRUPT,
- gettext(ERR_KEYSTORE_CORRUPT), file);
- goto cleanup;
- }
-
-cleanup:
- if (newfile != NULL)
- (void) fclose(newfile);
- if (fd != -1)
- (void) close(fd);
-
- return (p12);
-}
-
-
-/*
- * Locks the specified file.
- */
-static int
-file_lock(int fd, int type, int wait)
-{
- struct flock lock;
-
- lock.l_type = type;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- if (!wait) {
- if (file_lock_test(fd, type)) {
- /*
- * The caller would have to wait to get the
- * lock on this file.
- */
- return (-1);
- }
- }
-
- return (fcntl(fd, F_SETLKW, &lock));
-}
-
-/*
- * Returns FALSE if the file is not locked; TRUE
- * otherwise.
- */
-static boolean_t
-file_lock_test(int fd, int type)
-{
- struct flock lock;
-
- lock.l_type = type;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- if (fcntl(fd, F_GETLK, &lock) != -1) {
- if (lock.l_type != F_UNLCK) {
- /*
- * The caller would have to wait to get the
- * lock on this file.
- */
- return (B_TRUE);
- }
- }
-
- /*
- * The file is not locked.
- */
- return (B_FALSE);
-}
-
-/*
- * Unlocks the specified file.
- */
-static int
-file_unlock(int fd)
-{
- struct flock lock;
-
- lock.l_type = F_UNLCK;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
-
- return (fcntl(fd, F_SETLK, &lock));
-}
-
-/*
- * Determines if file has a length of 0 or not
- */
-static boolean_t
-file_empty(char *path)
-{
- struct stat buf;
-
- /* file is empty if size = 0 or it doesn't exist */
- if (lstat(path, &buf) == 0) {
- if (buf.st_size == 0) {
- return (B_TRUE);
- }
- } else {
- if (errno == ENOENT) {
- return (B_TRUE);
- }
- }
-
- return (B_FALSE);
-}
-
-/*
- * Name: get_time_string
- * Description: Generates a human-readable string from an ASN1_TIME
- *
- * Arguments: intime - The time to convert
- *
- * Returns : A pointer to a static string representing the passed-in time.
- */
-static char
-*get_time_string(ASN1_TIME *intime)
-{
-
- static char time[ATTR_MAX];
- BIO *mem;
- char *p;
-
- if (intime == NULL) {
- return (NULL);
- }
- if ((mem = BIO_new(BIO_s_mem())) == NULL) {
- return (NULL);
- }
-
- if (ASN1_TIME_print(mem, intime) == 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- if (BIO_gets(mem, time, ATTR_MAX) <= 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- (void) BIO_free(mem);
-
- /* trim the end of the string */
- for (p = time + strlen(time) - 1; isspace(*p); p--) {
- *p = '\0';
- }
-
- return (time);
-}
-
-/*
- * check_password - do various password checks to see if the current password
- * will work or we need to prompt for a new one.
- *
- * Arguments:
- * pass - password to check
- *
- * Returns:
- * B_TRUE - Password is OK.
- * B_FALSE - Password not valid.
- */
-static boolean_t
-check_password(PKCS12 *p12, char *pass)
-{
- boolean_t ret = B_TRUE;
-
- /*
- * If password is zero length or NULL then try verifying both cases
- * to determine which password is correct. The reason for this is that
- * under PKCS#12 password based encryption no password and a zero
- * length password are two different things...
- */
-
- /* Check the mac */
- if (pass == NULL || *pass == '\0') {
- if (PKCS12_verify_mac(p12, NULL, 0) == 0 &&
- PKCS12_verify_mac(p12, "", 0) == 0)
- ret = B_FALSE;
- } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
- ret = B_FALSE;
- }
- return (ret);
-}
diff --git a/usr/src/lib/libpkg/common/keystore.h b/usr/src/lib/libpkg/common/keystore.h
deleted file mode 100644
index b48ba030aa..0000000000
--- a/usr/src/lib/libpkg/common/keystore.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _KEYSTORE_H
-#define _KEYSTORE_H
-
-
-/*
- * Module: keystore.h
- * Description: This module contains the structure definitions for processing
- * package keystore files.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include "pkgerr.h"
-
-/* keystore structures */
-
-/* this opaque type represents a keystore */
-typedef void *keystore_handle_t;
-
-/* flags passed to open_keystore */
-
-/* opens keystore read-only. Attempts to modify results in an error */
-#define KEYSTORE_ACCESS_READONLY 0x00000001L
-
-/* opens keystore read-write */
-#define KEYSTORE_ACCESS_READWRITE 0x00000002L
-
-/*
- * tells open_keystore to fall back to app-generic paths in the case that
- * the app-specific paths do not exist.
- */
-#define KEYSTORE_PATH_SOFT 0x00000010L
-
-/*
- * tells open_keystore to use the app-specific paths no matter what,
- * failing if they cannot be used for any reason.
- */
-#define KEYSTORE_PATH_HARD 0x00000020L
-
-/* masks off various types of flags */
-#define KEYSTORE_ACCESS_MASK 0x0000000FL
-#define KEYSTORE_PATH_MASK 0x000000F0L
-
-/* default is read-only, soft */
-#define KEYSTORE_DFLT_FLAGS \
- (KEYSTORE_ACCESS_READONLY|KEYSTORE_PATH_SOFT)
-
-/*
- * possible encoding formats used by the library, used
- * by print_cert
- */
-typedef enum {
- KEYSTORE_FORMAT_PEM,
- KEYSTORE_FORMAT_DER,
- KEYSTORE_FORMAT_TEXT
-} keystore_encoding_format_t;
-
-/*
- * structure passed back to password callback for determining how
- * to prompt for passphrase, and where to record errors
- */
-typedef struct {
- PKG_ERR *err;
-} keystore_passphrase_data;
-
-
-/* max length of a passphrase. One could use a short story! */
-#define KEYSTORE_PASS_MAX 1024
-
-/* callback for collecting passphrase when open_keystore() is called */
-typedef int keystore_passphrase_cb(char *, int, int, void *);
-
-/* names of the individual files within the keystore path */
-#define TRUSTSTORE "truststore"
-#define KEYSTORE "keystore"
-#define CERTSTORE "certstore"
-
-/* keystore.c */
-extern int open_keystore(PKG_ERR *, char *, char *,
- keystore_passphrase_cb, long flags, keystore_handle_t *);
-
-extern int print_certs(PKG_ERR *, keystore_handle_t, char *,
- keystore_encoding_format_t, FILE *);
-
-extern int check_cert(PKG_ERR *, X509 *);
-
-extern int check_cert_and_key(PKG_ERR *, X509 *, EVP_PKEY *);
-
-extern int print_cert(PKG_ERR *, X509 *,
- keystore_encoding_format_t, char *, boolean_t, FILE *);
-
-extern int close_keystore(PKG_ERR *, keystore_handle_t,
- keystore_passphrase_cb);
-
-extern int merge_ca_cert(PKG_ERR *, X509 *, keystore_handle_t);
-extern int merge_cert_and_key(PKG_ERR *, X509 *, EVP_PKEY *,
- char *, keystore_handle_t);
-
-extern int delete_cert_and_keys(PKG_ERR *, keystore_handle_t,
- char *);
-
-extern int find_key_cert_pair(PKG_ERR *, keystore_handle_t,
- char *, EVP_PKEY **, X509 **);
-
-extern int find_ca_certs(PKG_ERR *, keystore_handle_t,
- STACK_OF(X509) **);
-
-extern int find_cl_certs(PKG_ERR *, keystore_handle_t,
- STACK_OF(X509) **);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _KEYSTORE_H */
diff --git a/usr/src/lib/libpkg/common/llib-lpkg b/usr/src/lib/libpkg/common/llib-lpkg
index b60597a9bc..b2fdb70d75 100644
--- a/usr/src/lib/libpkg/common/llib-lpkg
+++ b/usr/src/lib/libpkg/common/llib-lpkg
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,9 +32,5 @@
/* LINTLIBRARY */
/* PROTOLIB1 */
#include <cfext.h>
-#include <keystore.h>
-#include <p12lib.h>
-#include <pkgerr.h>
#include <pkglib.h>
#include <pkglocale.h>
-#include <pkgweb.h>
diff --git a/usr/src/lib/libpkg/common/mapfile-vers b/usr/src/lib/libpkg/common/mapfile-vers
index ffdda251f7..40dcd44f49 100644
--- a/usr/src/lib/libpkg/common/mapfile-vers
+++ b/usr/src/lib/libpkg/common/mapfile-vers
@@ -20,6 +20,10 @@
#
#
+# Copyright (c) 2017 Peter Tribble.
+#
+
+#
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
@@ -45,28 +49,23 @@ SYMBOL_VERSION SUNWprivate {
attrdefault;
attrpreset;
averify;
- backoff;
basepath;
canonize;
canonize_slashes;
cgrgid;
cgrnam;
- check_cert;
- check_cert_and_key;
checksum_off;
checksum_on;
ckparam;
ckvolseq;
clgrgid;
clgrnam;
- close_keystore;
clpwnam;
clpwuid;
compute_checksum;
cpwnam;
cpwuid;
cverify;
- delete_cert_and_keys;
devtype;
disable_attribute_check;
ds_close;
@@ -81,32 +80,21 @@ SYMBOL_VERSION SUNWprivate {
ds_putinfo;
ds_readbuf;
ds_skiptoend;
- ds_validate_signature;
e_ExecCmdArray;
e_ExecCmdList;
- echo_out;
ecleanup;
enable_local_fs;
epclose;
epopen;
esystem;
- find_ca_certs;
- find_cl_certs;
- find_key_cert_pair;
fmkdir;
fverify;
getErrbufAddr;
getErrbufSize;
getErrstr;
get_categories;
- get_cert_chain;
get_disable_attribute_check;
- get_endof_string;
get_prog_name;
- get_proxy_port;
- get_signature;
- get_startof_string;
- get_subject_display_name;
getmapmode;
gpkglist;
gpkgmap;
@@ -118,7 +106,6 @@ SYMBOL_VERSION SUNWprivate {
isPathRemote;
is_not_valid_category;
is_not_valid_length;
- is_web_install;
iscpio;
isdir;
isfile;
@@ -126,22 +113,11 @@ SYMBOL_VERSION SUNWprivate {
lookup_cache;
mappath;
mapvar;
- merge_ca_cert;
- merge_cert_and_key;
nonABI_symlinks;
- open_keystore;
path_valid;
- pkg_passphrase_cb;
pkgclosefilter;
pkgcloseserver;
pkgcmd;
- pkgerr;
- pkgerr_add;
- pkgerr_clear;
- pkgerr_free;
- pkgerr_get;
- pkgerr_new;
- pkgerr_num;
pkgexecl;
pkgexecv;
pkggetentry;
@@ -176,42 +152,19 @@ SYMBOL_VERSION SUNWprivate {
pkgtrans;
pkgumount;
ppkgmap;
- print_cert;
- print_certs;
progerr;
putcfile;
putcvfpfile;
- reset_backoff;
restore_local_fs;
rpterr;
rrmdir;
- sec_init;
setErrstr;
set_memalloc_failure_func;
set_nonABI_symlinks;
- set_passphrase_passarg;
- set_passphrase_prompt;
set_prog_name;
- set_web_install;
setmapmode;
srchcfile;
- strip_port;
- sunw_PKCS12_contents;
- sunw_PKCS12_create;
- sunw_check_cert_times;
- sunw_check_keys;
- sunw_evp_pkey_free;
- sunw_find_fname;
- sunw_find_localkeyid;
- sunw_get_cert_fname;
- sunw_get_pkey_fname;
- sunw_get_pkey_localkeyid;
- sunw_set_fname;
- sunw_set_localkeyid;
- sunw_split_certs;
- sunw_PEM_contents;
tputcfent;
- validate_signature;
vfpCheckpointFile;
vfpCheckpointOpen;
vfpClearModified;
@@ -226,8 +179,6 @@ SYMBOL_VERSION SUNWprivate {
vfpSetSize;
vfpTruncate;
vfpWriteToFile;
- web_cleanup;
- web_session_control;
xmalloc;
xrealloc;
xstrdup;
diff --git a/usr/src/lib/libpkg/common/p12lib.c b/usr/src/lib/libpkg/common/p12lib.c
deleted file mode 100644
index 238aa57d54..0000000000
--- a/usr/src/lib/libpkg/common/p12lib.c
+++ /dev/null
@@ -1,2798 +0,0 @@
-/*
- * ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
- */
-
-
-#include <strings.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-
-#include <openssl/pkcs12.h>
-#include "p12lib.h"
-
-/*
- * OpenSSL provides a framework for pushing error codes onto a stack.
- * When an error occurs, the consumer may use the framework to
- * pop the errors off the stack and provide a trace of where the
- * errors occurred.
- *
- * Our PKCS12 code plugs into this framework by calling
- * ERR_load_SUNW_strings(). To push an error (which by the way, consists
- * of a function code and an error code) onto the stack our PKCS12 code
- * calls SUNWerr().
- *
- * Consumers of our PKCS12 code can then call the OpenSSL error routines
- * when an error occurs and retrieve the stack of errors.
- */
-
-#ifndef OPENSSL_NO_ERR
-
-/* Function codes and their matching strings */
-static ERR_STRING_DATA SUNW_str_functs[] = {
- { ERR_PACK(0, SUNW_F_USE_X509CERT, 0), "sunw_use_x509cert" },
- { ERR_PACK(0, SUNW_F_USE_PKEY, 0), "sunw_use_pkey" },
- { ERR_PACK(0, SUNW_F_USE_TASTORE, 0), "sunw_use_tastore" },
- { ERR_PACK(0, SUNW_F_USE_CERTFILE, 0), "sunw_p12_use_certfile" },
- { ERR_PACK(0, SUNW_F_USE_KEYFILE, 0), "sunw_p12_use_keyfile" },
- { ERR_PACK(0, SUNW_F_USE_TRUSTFILE, 0), "sunw_p12_use_trustfile" },
- { ERR_PACK(0, SUNW_F_READ_FILE, 0), "p12_read_file" },
- { ERR_PACK(0, SUNW_F_DOPARSE, 0), "p12_doparse" },
- { ERR_PACK(0, SUNW_F_PKCS12_PARSE, 0), "sunw_PKCS12_parse" },
- { ERR_PACK(0, SUNW_F_PKCS12_CONTENTS, 0), "sunw_PKCS12_contents" },
- { ERR_PACK(0, SUNW_F_PARSE_ONE_BAG, 0), "parse_one_bag" },
- { ERR_PACK(0, SUNW_F_PKCS12_CREATE, 0), "sunw_PKCS12_create" },
- { ERR_PACK(0, SUNW_F_SPLIT_CERTS, 0), "sunw_split_certs" },
- { ERR_PACK(0, SUNW_F_FIND_LOCALKEYID, 0), "sunw_find_localkeyid" },
- { ERR_PACK(0, SUNW_F_SET_LOCALKEYID, 0), "sunw_set_localkeyid" },
- { ERR_PACK(0, SUNW_F_GET_LOCALKEYID, 0), "sunw_get_localkeyid" },
- { ERR_PACK(0, SUNW_F_SET_FNAME, 0), "sunw_set_fname" },
- { ERR_PACK(0, SUNW_F_GET_PKEY_FNAME, 0), "sunw_get_pkey_fname" },
- { ERR_PACK(0, SUNW_F_APPEND_KEYS, 0), "sunw_append_keys" },
- { ERR_PACK(0, SUNW_F_PEM_CONTENTS, 0), "sunw_PEM_contents" },
- { ERR_PACK(0, SUNW_F_PEM_INFO, 0), "pem_info" },
- { ERR_PACK(0, SUNW_F_ASC2BMPSTRING, 0), "asc2bmpstring" },
- { ERR_PACK(0, SUNW_F_UTF82ASCSTR, 0), "utf82ascstr" },
- { ERR_PACK(0, SUNW_F_FINDATTR, 0), "findattr" },
- { ERR_PACK(0, SUNW_F_TYPE2ATTRIB, 0), "type2attrib" },
- { ERR_PACK(0, SUNW_F_MOVE_CERTS, 0), "move_certs" },
- { ERR_PACK(0, SUNW_F_FIND_FNAME, 0), "sunw_find_fname" },
- { ERR_PACK(0, SUNW_F_PARSE_OUTER, 0), "parse_outer" },
- { ERR_PACK(0, SUNW_F_CHECKFILE, 0), "checkfile" },
- { 0, NULL }
-};
-
-/* Error codes and their matching strings */
-static ERR_STRING_DATA SUNW_str_reasons[] = {
- { SUNW_R_INVALID_ARG, "invalid argument" },
- { SUNW_R_MEMORY_FAILURE, "memory failure" },
- { SUNW_R_MAC_VERIFY_FAILURE, "mac verify failure" },
- { SUNW_R_MAC_CREATE_FAILURE, "mac create failure" },
- { SUNW_R_BAD_FILETYPE, "bad file type" },
- { SUNW_R_BAD_PKEY, "bad or missing private key" },
- { SUNW_R_BAD_PKEYTYPE, "unsupported key type" },
- { SUNW_R_PKEY_READ_ERR, "unable to read private key" },
- { SUNW_R_NO_TRUST_ANCHOR, "no trust anchors found" },
- { SUNW_R_READ_TRUST_ERR, "unable to read trust anchor" },
- { SUNW_R_ADD_TRUST_ERR, "unable to add trust anchor" },
- { SUNW_R_PKCS12_PARSE_ERR, "PKCS12 parse error" },
- { SUNW_R_PKCS12_CREATE_ERR, "PKCS12 create error" },
- { SUNW_R_BAD_CERTTYPE, "unsupported certificate type" },
- { SUNW_R_PARSE_CERT_ERR, "error parsing PKCS12 certificate" },
- { SUNW_R_PARSE_BAG_ERR, "error parsing PKCS12 bag" },
- { SUNW_R_MAKE_BAG_ERR, "error making PKCS12 bag" },
- { SUNW_R_BAD_LKID, "bad localKeyID format" },
- { SUNW_R_SET_LKID_ERR, "error setting localKeyID" },
- { SUNW_R_BAD_FNAME, "bad friendlyName format" },
- { SUNW_R_SET_FNAME_ERR, "error setting friendlyName" },
- { SUNW_R_BAD_TRUST, "bad or missing trust anchor" },
- { SUNW_R_BAD_BAGTYPE, "unsupported bag type" },
- { SUNW_R_CERT_ERR, "certificate error" },
- { SUNW_R_PKEY_ERR, "private key error" },
- { SUNW_R_READ_ERR, "error reading file" },
- { SUNW_R_ADD_ATTR_ERR, "error adding attribute" },
- { SUNW_R_STR_CONVERT_ERR, "error converting string" },
- { SUNW_R_PKCS12_EMPTY_ERR, "empty PKCS12 structure" },
- { SUNW_R_PASSWORD_ERR, "bad password" },
- { 0, NULL }
-};
-
-/*
- * The library name that our module will be known as. This name
- * may be retrieved via OpenSSLs error APIs.
- */
-static ERR_STRING_DATA SUNW_lib_name[] = {
- { 0, SUNW_LIB_NAME },
- { 0, NULL }
-};
-#endif
-
-/*
- * The value of this variable (initialized by a call to
- * ERR_load_SUNW_strings()) is what identifies our errors
- * to OpenSSL as being ours.
- */
-static int SUNW_lib_error_code = 0;
-
-/* local routines */
-static int parse_pkcs12(PKCS12 *, const char *, int, char *, int, char *,
- EVP_PKEY **, X509 **, STACK_OF(X509) **);
-static int pem_info(FILE *, pem_password_cb, void *,
- STACK_OF(EVP_PKEY) **, STACK_OF(X509) **);
-
-static int parse_outer(PKCS12 *, const char *, STACK_OF(EVP_PKEY) *,
- STACK_OF(X509) *);
-
-static int parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *, const char *,
- STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
-
-static int parse_one_bag(PKCS12_SAFEBAG *, const char *,
- STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
-
-static X509_ATTRIBUTE *type2attrib(ASN1_TYPE *, int);
-static ASN1_TYPE *attrib2type(X509_ATTRIBUTE *);
-static uchar_t *utf82ascstr(ASN1_UTF8STRING *);
-static ASN1_BMPSTRING *asc2bmpstring(const char *, int);
-static int find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *, int);
-static int find_attr(int, ASN1_STRING *, STACK_OF(EVP_PKEY) *,
- EVP_PKEY **, STACK_OF(X509) *, X509 **);
-
-static chk_errs_t check_time(chk_actions_t, X509 *);
-static int get_key_cert(int, STACK_OF(EVP_PKEY) *, EVP_PKEY **,
- STACK_OF(X509) *, X509 **cert);
-static int move_certs(STACK_OF(X509) *, STACK_OF(X509) *);
-static int sunw_append_keys(STACK_OF(EVP_PKEY) *,
- STACK_OF(EVP_PKEY) *);
-static int set_results(STACK_OF(EVP_PKEY) **,
- STACK_OF(EVP_PKEY) **, STACK_OF(X509) **, STACK_OF(X509) **,
- STACK_OF(X509) **, STACK_OF(X509) **,
- STACK_OF(EVP_PKEY) **, STACK_OF(EVP_PKEY) **);
-
-/*
- * ----------------------------------------------------------------------------
- * Public routines
- * ----------------------------------------------------------------------------
- */
-
-/*
- * sunw_PKCS12_parse - Parse a PKCS12 structure and break it into its parts.
- *
- * Parse and decrypt a PKCS#12 structure returning user key, user cert and/or
- * other (CA) certs. Note either ca should be NULL, *ca should be NULL,
- * or it should point to a valid STACK_OF(X509) structure. pkey and cert can
- * be passed uninitialized.
- *
- * Arguments:
- * p12 - Structure with pkcs12 info to be parsed
- * pass - Pass phrase for the private key (possibly empty) or NULL if
- * there is none.
- * matchty - Info about which certs/keys to return if many are in the file.
- * keyid - If private key localkeyids friendlynames are to match a
- * predetermined value, the value to match. This value should
- * be an octet string.
- * keyid_len- Length of the keyid byte string.
- * name_str - If friendlynames are to match a predetermined value, the value
- * to match. This value should be a NULL terminated string.
- * pkey - Points to location pointing to the private key returned.
- * cert - Points to locaiton which points to the client cert returned
- * ca - Points to location that points to a stack of 'certificate
- * authority' certs/trust anchors.
- *
- * Match based on the value of 'matchty' and the contents of 'keyid'
- * and/or 'name_str', as appropriate. Go through the lists of certs and
- * private keys which were taken from the pkcs12 structure, looking for
- * matches of the requested type. This function only searches the lists of
- * matching private keys and client certificates. Kinds of matches allowed,
- * and the order in which they will be checked, are:
- *
- * 1) Find the key and/or cert whose localkeyid attributes matches
- * 'keyid'.
- * 2) Find the key and/or cert whose friendlyname attributes matches
- * 'name_str'
- * 3) Return the first matching key/cert pair found.
- * 4) Return the last matching key/cert pair found.
- * 5) Return whatever cert and/or key are available, even unmatching.
- *
- * Append to the CA list, the certs which do not have matching private
- * keys and which were not selected.
- *
- * If none of the bits are set, no client certs or private keys will be
- * returned. CA (aka trust anchor) certs can be.
- *
- * Notes: If #3 is selected, then #4 will never occur. CA certs will be
- * selected after a cert/key pairs are isolated.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - Objects were found and returned. Which objects are indicated by
- * which bits are set (FOUND_PKEY, FOUND_CERT, FOUND_CA_CERTS).
- */
-int
-sunw_PKCS12_parse(PKCS12 *p12, const char *pass, int matchty, char *keyid,
- int keyid_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
- STACK_OF(X509) **ca)
-{
- boolean_t ca_supplied;
- int retval = -1;
-
- /* If NULL PKCS12 structure, this is an error */
- if (p12 == NULL) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
- return (-1);
- }
-
- /* Set up arguments.... These will be allocated if needed */
- if (pkey)
- *pkey = NULL;
- if (cert)
- *cert = NULL;
-
- /*
- * If there is already a ca list, use it. Otherwise, allocate one
- * and free is later if an error occurs or whatever.)
- */
- ca_supplied = (ca != NULL && *ca != NULL);
- if (ca != NULL && *ca == NULL) {
- if ((*ca = sk_X509_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- }
-
- /*
- * If password is zero length or NULL then try verifying both cases
- * to determine which password is correct. The reason for this is that
- * under PKCS#12 password based encryption no password and a zero
- * length password are two different things. If the password has a
- * non-zero length and is not NULL then call PKCS12_verify_mac() with
- * a length of '-1' and let it use strlen() to figure out the length
- * of the password.
- */
- /* Check the mac */
- if (pass == NULL || *pass == '\0') {
- if (PKCS12_verify_mac(p12, NULL, 0))
- pass = NULL;
- else if (PKCS12_verify_mac(p12, "", 0))
- pass = "";
- else {
- SUNWerr(SUNW_F_PKCS12_PARSE,
- SUNW_R_MAC_VERIFY_FAILURE);
- goto err;
- }
- } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MAC_VERIFY_FAILURE);
- goto err;
- }
-
- retval = parse_pkcs12(p12, pass, matchty, keyid, keyid_len,
- name_str, pkey, cert, ca);
- if (retval < 0) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_PKCS12_PARSE_ERR);
- goto err;
- }
- return (retval);
-
-err:
- if (pkey && *pkey) {
- sunw_evp_pkey_free(*pkey);
- }
- if (cert && *cert)
- X509_free(*cert);
- if (ca_supplied == B_FALSE && ca != NULL)
- sk_X509_pop_free(*ca, X509_free);
-
- return (-1);
-
-}
-
-
-/*
- * sunw_PEM_contents() parses a PEM file and returns component parts found
- *
- * Parse and decrypt a PEM file, returning any user keys and certs.
- *
- * There are some limits to this function. It will ignore the following:
- * - certificates identified by "TRUSTED CERTIFICATE"
- * - CERTIFICATE REQUEST and NEW CERTIFICATE REQUEST records.
- * - X509 CRL
- * - DH PARAMETERS
- * - DSA PARAMETERS
- * - Any PUBLIC KEY
- * - PKCS7
- * - PRIVATE KEY or ENCRYPTED PRIVATE KEY (PKCS 8)
- *
- * Arguments:
- * fp - File pointer for file containing PEM data.
- * pass - Pass phrase for the private key or NULL if there is none.
- * pkeys - Points to address of a stack of private keys to return.
- * certs - Points to address of a stack of client certs to return.
- *
- * The pointers to stacks should either be NULL or their contents should
- * either be NULL or should point to a valid STACK_OF(X509) structure.
- * If the stacks contain information, corresponding information from the
- * file will be appended to the original contents.
- *
- * Note: Client certs and and their matching private keys will be in any
- * order.
- *
- * Certs which have no matching private key are assumed to be ca certs.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - Objects were found and returned. Which objects are indicated by
- * which bits are set (FOUND_PKEY, FOUND_CERT)
- */
-int sunw_PEM_contents(FILE *fp, pem_password_cb *cb, void *userdata,
- STACK_OF(EVP_PKEY) **pkey, STACK_OF(X509) **certs)
-{
- STACK_OF(EVP_PKEY) *work_kl = NULL;
- STACK_OF(X509) *work_ca = NULL;
- int retval = -1;
-
- /*
- * Allocate the working stacks for private key and for the
- * ca certs.
- */
- if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
- SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- if ((work_ca = sk_X509_new_null()) == NULL) {
- SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- /* Error strings are set within the following. */
- if (pem_info(fp, cb, userdata, &work_kl, &work_ca) <= 0) {
- goto cleanup;
- }
-
- /* on error, set_results() returns an error on the stack */
- retval = set_results(pkey, &work_kl, certs, &work_ca, NULL, NULL, NULL,
- NULL);
-cleanup:
- if (work_kl != NULL) {
- sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
- }
- if (work_ca != NULL)
- sk_X509_pop_free(work_ca, X509_free);
-
- return (retval);
-}
-
-
-/*
- * sunw_PKCS12_contents() parses a pkcs#12 structure and returns component
- * parts found, without evaluation.
- *
- * Parse and decrypt a PKCS#12 structure returning any user keys and/or
- * various certs. Note these should either be NULL, *whatever should
- * be NULL, or it should point to a valid STACK_OF(X509) structure.
- *
- * Arguments:
- * p12 - Structure with pkcs12 info to be parsed
- * pass - Pass phrase for the private key and entire pkcs12 wad (possibly
- * empty) or NULL if there is none.
- * pkeys - Points to address of a stack of private keys to return.
- * certs - Points to address of a stack of client certs return.
- *
- * Note: The certs and keys being returned are in random order.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - Objects were found and returned. Which objects are indicated by
- * which bits are set (FOUND_PKEY or FOUND_CERT)
- */
-int
-sunw_PKCS12_contents(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) **pkey,
- STACK_OF(X509) **certs)
-{
- STACK_OF(EVP_PKEY) *work_kl = NULL;
- STACK_OF(X509) *work_ca = NULL;
- int retval = -1;
-
- /*
- * Allocate the working stacks for private key and for the
- * ca certs.
- */
- if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- if ((work_ca = sk_X509_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- if (parse_outer(p12, pass, work_kl, work_ca) == 0) {
- /*
- * Error already on stack
- */
- goto cleanup;
- }
-
- /* on error, set_results() returns an error on the stack */
- retval = set_results(pkey, &work_kl, certs, &work_ca, NULL,
- NULL, NULL, NULL);
-
-cleanup:
- if (work_kl != NULL) {
- sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
- }
-
- return (retval);
-}
-
-
-
-/*
- * sunw_split_certs() - Given a list of certs and a list of private keys,
- * moves certs which match one of the keys to a different stack.
- *
- * Arguments:
- * allkeys - Points to a stack of private keys to search.
- * allcerts - Points to a stack of certs to be searched.
- * keycerts - Points to address of a stack of certs with matching private
- * keys. They are moved from 'allcerts'. This may not be NULL
- * when called. If *keycerts is NULL upon entry, a new stack will
- * be allocated. Otherwise, it must be a valid STACK_OF(509).
- * nocerts - Points to address of a stack for keys which have no matching
- * certs. Keys are moved from 'allkeys' here when they have no
- * matching certs. If this is NULL, matchless keys will be
- * discarded.
- *
- * Notes: If an error occurs while moving certs, the cert being move may be
- * lost. 'keycerts' may only contain part of the matching certs. The number
- * of certs successfully moved can be found by checking sk_X509_num(keycerts).
- *
- * If there is a key which does not have a matching cert, it is moved to
- * the list nocerts.
- *
- * If all certs are removed from 'certs' and/or 'pkeys', it will be the
- * caller's responsibility to free the empty stacks.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - The number of certs moved from 'cert' to 'pkcerts'.
- */
-int
-sunw_split_certs(STACK_OF(EVP_PKEY) *allkeys, STACK_OF(X509) *allcerts,
- STACK_OF(X509) **keycerts, STACK_OF(EVP_PKEY) **nocerts)
-{
- STACK_OF(X509) *matching;
- STACK_OF(EVP_PKEY) *nomatch;
- EVP_PKEY *tmpkey;
- X509 *tmpcert;
- int count = 0;
- int found;
- int res;
- int i;
- int k;
-
- *keycerts = NULL;
- if (nocerts != NULL)
- *nocerts = NULL;
- nomatch = NULL;
-
- if ((matching = sk_X509_new_null()) == NULL) {
- SUNWerr(SUNW_F_SPLIT_CERTS, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- *keycerts = matching;
-
- k = 0;
- while (k < sk_EVP_PKEY_num(allkeys)) {
- found = 0;
- tmpkey = sk_EVP_PKEY_value(allkeys, k);
-
- for (i = 0; i < sk_X509_num(allcerts); i++) {
- tmpcert = sk_X509_value(allcerts, i);
- res = X509_check_private_key(tmpcert, tmpkey);
- if (res != 0) {
- count++;
- found = 1;
- tmpcert = sk_X509_delete(allcerts, i);
- if (sk_X509_push(matching, tmpcert) == 0) {
- X509_free(tmpcert);
- SUNWerr(SUNW_F_SPLIT_CERTS,
- SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- break;
- }
- }
- if (found != 0) {
- /*
- * Found a match - keep the key & check out the next
- * one.
- */
- k++;
- } else {
- /*
- * No cert matching this key. Move the key if
- * possible or discard it. Don't increment the
- * index.
- */
- if (nocerts == NULL) {
- tmpkey = sk_EVP_PKEY_delete(allkeys, k);
- sunw_evp_pkey_free(tmpkey);
- } else {
- if (*nocerts == NULL) {
- nomatch = sk_EVP_PKEY_new_null();
- if (nomatch == NULL) {
- SUNWerr(SUNW_F_SPLIT_CERTS,
- SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- *nocerts = nomatch;
- }
- tmpkey = sk_EVP_PKEY_delete(allkeys, k);
- if (sk_EVP_PKEY_push(nomatch, tmpkey) == 0) {
- sunw_evp_pkey_free(tmpkey);
- SUNWerr(SUNW_F_SPLIT_CERTS,
- SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- }
- }
- }
-
- return (count);
-}
-
-/*
- * sunw_PKCS12_create() creates a pkcs#12 structure and given component parts.
- *
- * Given one or more of user private key, user cert and/or other (CA) certs,
- * return an encrypted PKCS12 structure containing them.
- *
- * Arguments:
- * pass - Pass phrase for the pkcs12 structure and private key (possibly
- * empty) or NULL if there is none. It will be used to encrypt
- * both the private key(s) and as the pass phrase for the whole
- * pkcs12 wad.
- * pkeys - Points to stack of private keys.
- * certs - Points to stack of client (public ke) certs
- * cacerts - Points to stack of 'certificate authority' certs (or trust
- * anchors).
- *
- * Note that any of these may be NULL.
- *
- * Returns:
- * NULL - An error occurred.
- * != NULL - Address of PKCS12 structure. The user is responsible for
- * freeing the memory when done.
- */
-PKCS12 *
-sunw_PKCS12_create(const char *pass, STACK_OF(EVP_PKEY) *pkeys,
- STACK_OF(X509) *certs, STACK_OF(X509) *cacerts)
-{
- int nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
- int nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
- STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
- STACK_OF(PKCS7) *safes = NULL;
- PKCS12_SAFEBAG *bag = NULL;
- PKCS8_PRIV_KEY_INFO *p8 = NULL;
- EVP_PKEY *pkey = NULL;
- PKCS12 *ret_p12 = NULL;
- PKCS12 *p12 = NULL;
- PKCS7 *authsafe = NULL;
- X509 *cert = NULL;
- uchar_t *str = NULL;
- int certs_there = 0;
- int keys_there = 0;
- int len;
- int i;
-
- if ((safes = sk_PKCS7_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
- return (NULL);
- }
-
- if ((bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
-
- if (certs != NULL && sk_X509_num(certs) > 0) {
-
- for (i = 0; i < sk_X509_num(certs); i++) {
- cert = sk_X509_value(certs, i);
-
- /* Add user certificate */
- if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
- goto err_ret;
- }
- if (cert->aux != NULL && cert->aux->alias != NULL &&
- cert->aux->alias->type == V_ASN1_UTF8STRING) {
- str = utf82ascstr(cert->aux->alias);
- if (str == NULL) {
- /*
- * Error already on stack
- */
- goto err_ret;
- }
- if (PKCS12_add_friendlyname_asc(bag,
- (char const *) str,
- strlen((char const *) str)) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- if (cert->aux != NULL && cert->aux->keyid != NULL &&
- cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
- str = cert->aux->keyid->data;
- len = cert->aux->keyid->length;
-
- if (str != NULL &&
- PKCS12_add_localkeyid(bag, str, len) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
- certs_there++;
- bag = NULL;
- }
- }
-
- if (cacerts != NULL && sk_X509_num(cacerts) > 0) {
-
- /* Put all certs in structure */
- for (i = 0; i < sk_X509_num(cacerts); i++) {
- cert = sk_X509_value(cacerts, i);
- if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
- goto err_ret;
- }
-
- if (cert->aux != NULL && cert->aux->alias != NULL &&
- cert->aux->alias->type == V_ASN1_UTF8STRING) {
- str = utf82ascstr(cert->aux->alias);
- if (str == NULL) {
- /*
- * Error already on stack
- */
- goto err_ret;
- }
- if (PKCS12_add_friendlyname_asc(
- bag, (char const *) str,
- strlen((char const *) str)) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- if (cert->aux != NULL && cert->aux->keyid != NULL &&
- cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
- str = cert->aux->keyid->data;
- len = cert->aux->keyid->length;
-
- if (str != NULL &&
- PKCS12_add_localkeyid(bag, str, len) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
- certs_there++;
- bag = NULL;
- }
- }
-
- if (certs != NULL || cacerts != NULL && certs_there) {
- /* Turn certbags into encrypted authsafe */
- authsafe = PKCS12_pack_p7encdata(nid_cert, pass, -1,
- NULL, 0, PKCS12_DEFAULT_ITER, bags);
- if (authsafe == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
- goto err_ret;
- }
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- bags = NULL;
-
- if (sk_PKCS7_push(safes, authsafe) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
- authsafe = NULL;
- }
-
- if (pkeys != NULL && sk_EVP_PKEY_num(pkeys) > 0) {
-
- if (bags == NULL &&
- (bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
-
- for (i = 0; i < sk_EVP_PKEY_num(pkeys); i++) {
-
- pkey = sk_EVP_PKEY_value(pkeys, i);
-
- /* Make a shrouded key bag */
- if ((p8 = EVP_PKEY2PKCS8(pkey)) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKEY_ERR);
- goto err_ret;
- }
-
- bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0,
- PKCS12_DEFAULT_ITER, p8);
- if (bag == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_MAKE_BAG_ERR);
- goto err_ret;
- }
- PKCS8_PRIV_KEY_INFO_free(p8);
- p8 = NULL;
-
- len = sunw_get_pkey_fname(GETDO_COPY, pkey,
- (char **)&str);
- if (str != NULL) {
- if (PKCS12_add_friendlyname_asc(bag,
- (const char *)str, len) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- str = NULL;
-
- len = sunw_get_pkey_localkeyid(GETDO_COPY, pkey,
- (char **)&str, &len);
- if (str != NULL) {
- if (PKCS12_add_localkeyid(bag, str, len) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_ADD_ATTR_ERR);
- goto err_ret;
- }
- }
- str = NULL;
-
- if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_MEMORY_FAILURE);
- goto err_ret;
- }
- keys_there++;
- bag = NULL;
- }
-
- if (keys_there) {
- /* Turn into unencrypted authsafe */
- authsafe = PKCS12_pack_p7data(bags);
- if (authsafe == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_PKCS12_CREATE_ERR);
- goto err_ret;
- }
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- bags = NULL;
-
- if (sk_PKCS7_push(safes, authsafe) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE,
- SUNW_R_MEMORY_FAILURE);
- }
- authsafe = NULL;
- }
- }
-
- if (certs_there == 0 && keys_there == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_EMPTY_ERR);
- goto err_ret;
- }
-
- if ((p12 = PKCS12_init(NID_pkcs7_data)) == NULL) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
- goto err_ret;
- }
-
- /*
- * Note that safes is copied by the following. Therefore, it needs
- * to be freed whether or not the following succeeds.
- */
- if (M_PKCS12_pack_authsafes(p12, safes) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
- goto err_ret;
- }
- if (PKCS12_set_mac(p12, pass, -1, NULL, 0, 2048, NULL) == 0) {
- SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MAC_CREATE_FAILURE);
- goto err_ret;
- }
-
- ret_p12 = p12;
- p12 = NULL;
-
- /* Fallthrough is intentional */
-
-err_ret:
-
- if (str != NULL)
- free(str);
-
- if (p8 != NULL)
- PKCS8_PRIV_KEY_INFO_free(p8);
-
- if (bag != NULL)
- PKCS12_SAFEBAG_free(bag);
- if (bags != NULL)
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- if (authsafe != NULL)
- PKCS7_free(authsafe);
- if (safes != NULL)
- sk_PKCS7_pop_free(safes, PKCS7_free);
- if (p12 != NULL)
- PKCS12_free(p12);
-
- return (ret_p12);
-}
-
-/*
- * sunw_evp_pkey_free() Given an EVP_PKEY structure, free any attributes
- * that are attached. Then free the EVP_PKEY itself.
- *
- * This is a replacement for EVP_PKEY_free() for the sunw stuff.
- * It should be used in places where EVP_PKEY_free would be used,
- * including calls to sk_EVP_PKEY_pop_free().
- *
- * Arguments:
- * pkey - Entry which potentially has attributes to be freed.
- *
- * Returns:
- * None.
- */
-void
-sunw_evp_pkey_free(EVP_PKEY *pkey)
-{
- if (pkey != NULL) {
- if (pkey->attributes != NULL) {
- sk_X509_ATTRIBUTE_pop_free(pkey->attributes,
- X509_ATTRIBUTE_free);
- pkey->attributes = NULL;
- }
- EVP_PKEY_free(pkey);
- }
-}
-
-/*
- * sunw_set_localkeyid() sets the localkeyid in a cert, a private key or
- * both. Any existing localkeyid will be discarded.
- *
- * Arguments:
- * keyid_str- A byte string with the localkeyid to set
- * keyid_len- Length of the keyid byte string.
- * pkey - Points to a private key to set the keyidstr in.
- * cert - Points to a cert to set the keyidstr in.
- *
- * Note that setting a keyid into a cert which will not be written out as
- * a PKCS12 cert is pointless since it will be lost.
- *
- * Returns:
- * 0 - Success.
- * < 0 - An error occurred. It was probably an error in allocating
- * memory. The error will be set in the error stack. Call
- * ERR_get_error() to get specific information.
- */
-int
-sunw_set_localkeyid(const char *keyid_str, int keyid_len, EVP_PKEY *pkey,
- X509 *cert)
-{
- X509_ATTRIBUTE *attr = NULL;
- ASN1_STRING *str = NULL;
- ASN1_TYPE *keyid = NULL;
- int retval = -1;
- int i;
-
- if (cert != NULL) {
- if (X509_keyid_set1(cert, (uchar_t *)keyid_str, keyid_len)
- == 0) {
- SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_SET_LKID_ERR);
- goto cleanup;
- }
- }
- if (pkey != NULL) {
- str = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
- if (str == NULL ||
- M_ASN1_OCTET_STRING_set(str, keyid_str, keyid_len) == 0 ||
- (keyid = ASN1_TYPE_new()) == NULL) {
- SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- ASN1_TYPE_set(keyid, V_ASN1_OCTET_STRING, str);
- str = NULL;
-
- attr = type2attrib(keyid, NID_localKeyID);
- if (attr == NULL) {
- /*
- * Error already on stack
- */
- goto cleanup;
- }
- keyid = NULL;
-
- if (pkey->attributes == NULL) {
- pkey->attributes = sk_X509_ATTRIBUTE_new_null();
- if (pkey->attributes == NULL) {
- SUNWerr(SUNW_F_SET_LOCALKEYID,
- SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
- } else {
- i = find_attr_by_nid(pkey->attributes, NID_localKeyID);
- if (i >= 0)
- sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
- }
- if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
- SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
- attr = NULL;
- }
- retval = 0;
-
-cleanup:
- if (str != NULL)
- ASN1_STRING_free(str);
- if (keyid != NULL)
- ASN1_TYPE_free(keyid);
- if (attr != NULL)
- X509_ATTRIBUTE_free(attr);
-
- return (retval);
-}
-
-/*
- * sunw_get_pkey_localkeyid() gets the localkeyid from a private key. It can
- * optionally remove the value found.
- *
- * Arguments:
- * dowhat - What to do with the attributes (remove them or copy them).
- * pkey - Points to a private key to set the keyidstr in.
- * keyid_str- Points to a location which will receive the pointer to
- * a byte string containing the binary localkeyid. Note that
- * this is a copy, and the caller must free it.
- * keyid_len- Length of keyid_str.
- *
- * Returns:
- * >= 0 - The number of characters in the keyid returned.
- * < 0 - An error occurred. It was probably an error in allocating
- * memory. The error will be set in the error stack. Call
- * ERR_get_error() to get specific information.
- */
-int
-sunw_get_pkey_localkeyid(getdo_actions_t dowhat, EVP_PKEY *pkey,
- char **keyid_str, int *keyid_len)
-{
- X509_ATTRIBUTE *attr = NULL;
- ASN1_OCTET_STRING *str = NULL;
- ASN1_TYPE *ty = NULL;
- int len = 0;
- int i;
-
- if (keyid_str != NULL)
- *keyid_str = NULL;
- if (keyid_len != NULL)
- *keyid_len = 0;
-
- if (pkey == NULL || pkey->attributes == NULL) {
- return (0);
- }
-
- if ((i = find_attr_by_nid(pkey->attributes, NID_localKeyID)) < 0) {
- return (0);
- }
- attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
-
- if ((ty = attrib2type(attr)) == NULL ||
- ty->type != V_ASN1_OCTET_STRING) {
- return (0);
- }
-
- if (dowhat == GETDO_DEL) {
- attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
- if (attr != NULL)
- X509_ATTRIBUTE_free(attr);
- return (0);
- }
-
- str = ty->value.octet_string;
- len = str->length;
- if ((*keyid_str = malloc(len)) == NULL) {
- SUNWerr(SUNW_F_GET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
-
- (void) memcpy(*keyid_str, str->data, len);
- *keyid_len = len;
-
- return (len);
-}
-
-/*
- * sunw_get_pkey_fname() gets the friendlyName from a private key. It can
- * optionally remove the value found.
- *
- * Arguments:
- * dowhat - What to do with the attributes (remove them or copy them).
- * pkey - Points to a private key to get the frientlyname from
- * fname - Points to a location which will receive the pointer to a
- * byte string with the ASCII friendlyname
- *
- * Returns:
- * >= 0 - The number of characters in the frienlyname returned.
- * < 0 - An error occurred. It was probably an error in allocating
- * memory. The error will be set in the error stack. Call
- * ERR_get_error() to get specific information.
- */
-int
-sunw_get_pkey_fname(getdo_actions_t dowhat, EVP_PKEY *pkey, char **fname)
-{
- X509_ATTRIBUTE *attr = NULL;
- ASN1_BMPSTRING *str = NULL;
- ASN1_TYPE *ty = NULL;
- int len = 0;
- int i;
-
- if (fname != NULL)
- *fname = NULL;
-
- if (pkey == NULL || pkey->attributes == NULL) {
- return (0);
- }
-
- if ((i = find_attr_by_nid(pkey->attributes, NID_friendlyName)) < 0) {
- return (0);
- }
- attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
-
- if ((ty = attrib2type(attr)) == NULL ||
- ty->type != V_ASN1_BMPSTRING) {
- return (0);
- }
-
- if (dowhat == GETDO_DEL) {
- attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
- if (attr != NULL)
- X509_ATTRIBUTE_free(attr);
- return (0);
- }
-
- str = ty->value.bmpstring;
-#if OPENSSL_VERSION_NUMBER < 0x10000000L
- *fname = uni2asc(str->data, str->length);
-#else
- *fname = OPENSSL_uni2asc(str->data, str->length);
-#endif
- if (*fname == NULL) {
- SUNWerr(SUNW_F_GET_PKEY_FNAME, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
-
- len = strlen(*fname);
-
- return (len);
-}
-
-/*
- * sunw_find_localkeyid() searches stacks of certs and private keys,
- * and returns the first matching cert/private key found.
- *
- * Look for a keyid in a stack of certs. if 'certs' is NULL and 'pkeys' is
- * not NULL, search the list of private keys. Move the matching cert to
- * 'matching_cert' and its matching private key to 'matching_pkey'. If no
- * cert or keys match, no match occurred.
- *
- * Arguments:
- * keyid_str- A byte string with the localkeyid to match
- * keyid_len- Length of the keyid byte string.
- * pkeys - Points to a stack of private keys which match the certs.
- * This may be NULL, in which case no keys are returned.
- * certs - Points to a stack of certs to search. If NULL, search the
- * stack of keys instead.
- * matching_pkey
- * - Pointer to receive address of first matching pkey found.
- * 'matching_pkey' must not be NULL; '*matching_pkey' will be
- * reset.
- * matching_cert
- * - Pointer to receive address of first matching cert found.
- * 'matching_cert' must not be NULL; '*matching_cert' will be
- * reset.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - Objects were found and returned. Which objects are indicated by
- * which bits are set (FOUND_PKEY and/or FOUND_CERT).
- */
-int
-sunw_find_localkeyid(char *keyid_str, int len, STACK_OF(EVP_PKEY) *pkeys,
-STACK_OF(X509) *certs, EVP_PKEY **matching_pkey, X509 **matching_cert)
-{
- ASN1_STRING *cmpstr = NULL;
- EVP_PKEY *tmp_pkey = NULL;
- X509 *tmp_cert = NULL;
- int retval = 0;
-
- /* If NULL arguments, this is an error */
- if (keyid_str == NULL ||
- (pkeys == NULL || certs == NULL) ||
- (pkeys != NULL && matching_pkey == NULL) ||
- (certs != NULL && matching_cert == NULL)) {
- SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_INVALID_ARG);
- return (-1);
- }
-
- if (matching_pkey != NULL)
- *matching_pkey = NULL;
- if (matching_cert != NULL)
- *matching_cert = NULL;
-
- cmpstr = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
- if (cmpstr == NULL ||
- M_ASN1_OCTET_STRING_set(cmpstr, keyid_str, len) == 0) {
- SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
-
- retval = find_attr(NID_localKeyID, cmpstr, pkeys, &tmp_pkey, certs,
- &tmp_cert);
- if (retval == 0) {
- ASN1_STRING_free(cmpstr);
- return (retval);
- }
-
- if (matching_pkey != NULL)
- *matching_pkey = tmp_pkey;
- if (matching_cert != NULL)
- *matching_cert = tmp_cert;
-
- return (retval);
-}
-
-/*
- * sunw_find_fname() searches stacks of certs and private keys for one with
- * a matching friendlyname and returns the first matching cert/private
- * key found.
- *
- * Look for a friendlyname in a stack of certs. if 'certs' is NULL and 'pkeys'
- * is not NULL, search the list of private keys. Move the matching cert to
- * 'matching_cert' and its matching private key to 'matching_pkey'. If no
- * cert or keys match, no match occurred.
- *
- * Arguments:
- * fname - Friendlyname to find (NULL-terminated ASCII string).
- * pkeys - Points to a stack of private keys which match the certs.
- * This may be NULL, in which case no keys are returned.
- * certs - Points to a stack of certs to search. If NULL, search the
- * stack of keys instead.
- * matching_pkey
- * - Pointer to receive address of first matching pkey found.
- * matching_cert
- * - Pointer to receive address of first matching cert found.
- *
- * Returns:
- * < 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * >= 0 - Objects were found and returned. Which objects are indicated by
- * which bits are set (FOUND_PKEY and/or FOUND_CERT).
- */
-int
-sunw_find_fname(char *fname, STACK_OF(EVP_PKEY) *pkeys, STACK_OF(X509) *certs,
- EVP_PKEY **matching_pkey, X509 ** matching_cert)
-{
- ASN1_STRING *cmpstr = NULL;
- EVP_PKEY *tmp_pkey = NULL;
- X509 *tmp_cert = NULL;
- int retval = 0;
-
- /* If NULL arguments, this is an error */
- if (fname == NULL ||
- (pkeys == NULL && certs == NULL) ||
- (pkeys != NULL && matching_pkey == NULL) ||
- (certs != NULL && matching_cert == NULL)) {
- SUNWerr(SUNW_F_FIND_FNAME, SUNW_R_INVALID_ARG);
- return (-1);
- }
-
- if (matching_pkey != NULL)
- *matching_pkey = NULL;
- if (matching_cert != NULL)
- *matching_cert = NULL;
-
- cmpstr = (ASN1_STRING *)asc2bmpstring(fname, strlen(fname));
- if (cmpstr == NULL) {
- /*
- * Error already on stack
- */
- return (-1);
- }
-
- retval = find_attr(NID_friendlyName, cmpstr, pkeys, &tmp_pkey, certs,
- &tmp_cert);
- if (retval == 0) {
- ASN1_STRING_free(cmpstr);
- return (retval);
- }
-
- if (matching_pkey != NULL)
- *matching_pkey = tmp_pkey;
- if (matching_cert != NULL)
- *matching_cert = tmp_cert;
-
- return (retval);
-}
-
-/*
- * sunw_get_cert_fname() gets the fiendlyname from a cert. It can
- * optionally remove the value found.
- *
- * Arguments:
- * dowhat - What to do with the attributes (remove them or copy them).
- * cert - Points to a cert to get the friendlyName from.
- * fname - Points to a location which will receive the pointer to a
- * byte string with the ASCII friendlyname
- *
- * Returns:
- * >= 0 - The number of characters in the friendlyname returned.
- * < 0 - An error occurred. It was probably an error in allocating
- * memory. The error will be set in the error stack. Call
- * ERR_get_error() to get specific information.
- */
-int
-sunw_get_cert_fname(getdo_actions_t dowhat, X509 *cert, char **fname)
-{
- int len;
-
- if (fname != NULL)
- *fname = NULL;
-
- if (cert == NULL || cert->aux == NULL || cert->aux->alias == NULL) {
- return (0);
- }
-
- if (dowhat == GETDO_DEL) {
- /* Delete the entry */
- ASN1_UTF8STRING_free(cert->aux->alias);
- cert->aux->alias = NULL;
- return (0);
- }
-
- *((uchar_t **)fname) = utf82ascstr(cert->aux->alias);
- if (*fname == NULL) {
- /*
- * Error already on stack
- */
- return (-1);
- }
-
- len = strlen(*fname);
-
- return (len);
-}
-
-/*
- * sunw_set_fname() sets the friendlyName in a cert, a private key or
- * both. Any existing friendlyname will be discarded.
- *
- * Arguments:
- * ascname - An ASCII string with the friendlyName to set
- * pkey - Points to a private key to set the fname in.
- * cert - Points to a cert to set the fname in.
- *
- * Note that setting a friendlyName into a cert which will not be written out
- * as a PKCS12 cert is pointless since it will be lost.
- *
- * Returns:
- * 0 - Success.
- * <0 - An error occurred. It was probably an error in allocating
- * memory. The error will be set in the error stack. Call
- * ERR_get_error() to get specific information.
- */
-int
-sunw_set_fname(const char *ascname, EVP_PKEY *pkey, X509 *cert)
-{
- X509_ATTRIBUTE *attr = NULL;
- ASN1_BMPSTRING *str = NULL;
- ASN1_TYPE *fname = NULL;
- unsigned char *data = NULL;
- int retval = -1;
- int len;
- int i;
-
- str = asc2bmpstring(ascname, strlen(ascname));
- if (str == NULL) {
- /*
- * Error already on stack
- */
- return (-1);
- }
-
- if (cert != NULL) {
- if (cert->aux != NULL && cert->aux->alias != NULL) {
- ASN1_UTF8STRING_free(cert->aux->alias);
- }
-
- len = ASN1_STRING_to_UTF8(&data, str);
- i = -23;
- if (len <= 0 || (i = X509_alias_set1(cert, data, len)) == 0) {
- SUNWerr(SUNW_F_SET_FNAME, SUNW_R_SET_FNAME_ERR);
- goto cleanup;
- }
- }
- if (pkey != NULL) {
- if ((fname = ASN1_TYPE_new()) == NULL) {
- SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- ASN1_TYPE_set(fname, V_ASN1_BMPSTRING, str);
- str = NULL;
-
- attr = type2attrib(fname, NID_friendlyName);
- if (attr == NULL) {
- /*
- * Error already on stack
- */
- goto cleanup;
- }
- fname = NULL;
-
- if (pkey->attributes == NULL) {
- pkey->attributes = sk_X509_ATTRIBUTE_new_null();
- if (pkey->attributes == NULL) {
- SUNWerr(SUNW_F_SET_FNAME,
- SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
- } else if ((i = find_attr_by_nid(pkey->attributes,
- NID_friendlyName)) >= 0) {
- (void) sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
- }
-
- if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
- SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
- goto cleanup;
- }
-
- attr = NULL;
- }
- retval = 0;
-
-cleanup:
- if (data != NULL)
- OPENSSL_free(data);
- if (str != NULL)
- ASN1_BMPSTRING_free(str);
- if (fname != NULL)
- ASN1_TYPE_free(fname);
- if (attr != NULL)
- X509_ATTRIBUTE_free(attr);
-
- return (retval);
-}
-
-/*
- * sunw_check_keys() compares the public key in the certificate and a
- * private key to ensure that they match.
- *
- * Arguments:
- * cert - Points to a certificate.
- * pkey - Points to a private key.
- *
- * Returns:
- * == 0 - These do not match.
- * != 0 - The cert's public key and the private key match.
- */
-int
-sunw_check_keys(X509 *cert, EVP_PKEY *pkey)
-{
- int retval = 0;
-
- if (pkey != NULL && cert != NULL)
- retval = X509_check_private_key(cert, pkey);
-
- return (retval);
-}
-
-/*
- * sunw_check_cert_times() compares the time fields in a certificate
- *
- * Compare the 'not before' and the 'not after' times in the cert
- * to the current time. Return the results of the comparison (bad time formats,
- * cert not yet in force, cert expired or in range)
- *
- * Arguments:
- * dowhat - what field(s) to check.
- * cert - Points to a cert to check
- *
- * Returns:
- * Results of the comparison.
- */
-chk_errs_t
-sunw_check_cert_times(chk_actions_t chkwhat, X509 *cert)
-{
- return (check_time(chkwhat, cert));
-}
-
-/*
- * ----------------------------------------------------------------------------
- * Local routines
- * ----------------------------------------------------------------------------
- */
-
-
-/*
- * parse_pkcs12 - Oversee parsing of the pkcs12 structure. Get it
- * parsed. After that either return what's found directly, or
- * do any required matching.
- *
- * Arguments:
- * p12 - Structure with pkcs12 info to be parsed
- * pass - Pass phrase for the private key (possibly empty) or NULL if
- * there is none.
- * matchty - Info about which certs/keys to return if many are in the file.
- * keyid - If private key localkeyids friendlynames are to match a
- * predetermined value, the value to match. This value should
- * be an octet string.
- * keyid_len- Length of the keyid byte string.
- * name_str - If friendlynames are to match a predetermined value, the value
- * to match. This value should be a NULL terminated string.
- * pkey - Points to location pointing to the private key returned.
- * cert - Points to locaiton which points to the client cert returned
- * ca - Points to location that points to a stack of 'certificate
- * authority' certs/trust anchors.
- *
- * Note about error codes: This function is an internal function, and the
- * place where it is called sets error codes. Therefore only set an error
- * code if it is something that is unique or if the function which detected
- * the error doesn't set one.
- *
- * Returns:
- * == -1 - An error occurred. Call ERR_get_error() to get error information.
- * Where possible, memory has been freed.
- * == 0 - No matching returns were found.
- * > 0 - This is the aithmetic 'or' of the FOUND_* bits that indicate which
- * of the requested entries were found.
- */
-static int
-parse_pkcs12(PKCS12 *p12, const char *pass, int matchty, char *keyid,
- int kstr_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
- STACK_OF(X509) **ca)
-{
- STACK_OF(EVP_PKEY) *work_kl = NULL; /* Head for private key list */
- STACK_OF(EVP_PKEY) *nocerts = NULL; /* Head for alt. key list */
- STACK_OF(X509) *work_ca = NULL; /* Head for cert list */
- STACK_OF(X509) *work_cl = NULL;
- int retval = 0;
- int n;
-
- retval = sunw_PKCS12_contents(p12, pass, &work_kl, &work_ca);
- if (retval < 0) {
- goto cleanup;
- } else if (retval == 0) {
- /*
- * Not really an error here - its just that nothing was found.
- */
- goto cleanup;
- }
-
- if (sk_EVP_PKEY_num(work_kl) > 0) {
-
- if (sunw_split_certs(work_kl, work_ca, &work_cl, &nocerts)
- < 0) {
- goto cleanup;
- }
- }
-
- /*
- * Go through the lists of certs and private keys which were
- * returned, looking for matches of the appropriate type. Do these
- * in the order described above.
- */
- if ((matchty & DO_FIND_KEYID) != 0) {
-
- if (keyid == NULL) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
- retval = -1;
- goto cleanup;
- }
-
- /* See if string matches localkeyid's */
- retval = sunw_find_localkeyid(keyid, kstr_len,
- work_kl, work_cl, pkey, cert);
- if (retval != 0) {
- if (retval == -1)
- goto cleanup;
- else
- goto last_part;
- }
- }
- if ((matchty & DO_FIND_FN) != 0) {
-
- if (name_str == NULL) {
- SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
- retval = -1;
- goto cleanup;
- }
-
- /* See if string matches friendly names */
- retval = sunw_find_fname(name_str, work_kl, work_cl,
- pkey, cert);
- if (retval != 0) {
- if (retval == -1)
- goto cleanup;
- else
- goto last_part;
- }
- }
-
- if (matchty & DO_FIRST_PAIR) {
-
- /* Find the first cert and private key and return them */
- retval = get_key_cert(0, work_kl, pkey, work_cl, cert);
- if (retval != 0) {
- if (retval == -1)
- goto cleanup;
- else
- goto last_part;
- }
- }
-
- if (matchty & DO_LAST_PAIR) {
-
- /*
- * Find the last matching cert and private key and return
- * them. Since keys which don't have matching client certs
- * are at the end of the list of keys, use the number of
- * client certs to compute the position of the last private
- * key which matches a client cert.
- */
- n = sk_X509_num(work_cl) - 1;
- retval = get_key_cert(n, work_kl, pkey, work_cl, cert);
- if (retval != 0) {
- if (retval == -1)
- goto cleanup;
- else
- goto last_part;
- }
- }
-
- if (matchty & DO_UNMATCHING) {
- STACK_OF(EVP_PKEY) *tmpk;
- STACK_OF(X509) *tmpc;
-
- /* Find the first cert and private key and return them */
- tmpc = work_cl;
- if (work_cl == NULL || sk_X509_num(work_cl) == 0)
- tmpc = work_ca;
- tmpk = work_kl;
- if (work_kl == NULL || sk_EVP_PKEY_num(work_kl) == 0)
- tmpk = nocerts;
- retval = get_key_cert(0, tmpk, pkey, tmpc, cert);
- if (retval != 0) {
- if (retval == -1)
- goto cleanup;
- else
- goto last_part;
- }
- }
-
-last_part:
- /* If no errors, terminate normally */
- if (retval != -1)
- retval |= set_results(NULL, NULL, NULL, NULL, ca, &work_ca,
- NULL, NULL);
- if (retval >= 0) {
- goto clean_part;
- }
-
- /* Fallthrough is intentional in error cases. */
-cleanup:
- if (pkey != NULL && *pkey != NULL) {
- sunw_evp_pkey_free(*pkey);
- *pkey = NULL;
- }
- if (cert != NULL && *cert != NULL) {
- X509_free(*cert);
- *cert = NULL;
- }
-
-clean_part:
-
- if (work_kl != NULL) {
- sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
- }
- if (work_ca != NULL)
- sk_X509_pop_free(work_ca, X509_free);
- if (work_cl != NULL)
- sk_X509_pop_free(work_cl, X509_free);
-
- return (retval);
-}
-
-/*
- * parse_outer - Unpack the outer PKCS#12 structure and go through the
- * individual bags. Return stacks of certs, private keys found and
- * CA certs found.
- *
- * Note about error codes: This function is an internal function, and the
- * place where it is called sets error codes.
- *
- * Returns:
- * 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * 1 - PKCS12 data object was parsed and lists of certs and private keys
- * were returned.
- */
-static int
-parse_outer(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) *kl,
- STACK_OF(X509) *cl)
-{
- STACK_OF(PKCS12_SAFEBAG) *bags;
- STACK_OF(PKCS7) *asafes;
- int i, bagnid;
- PKCS7 *p7;
-
- if ((asafes = M_PKCS12_unpack_authsafes(p12)) == NULL)
- return (0);
-
- for (i = 0; i < sk_PKCS7_num(asafes); i++) {
- p7 = sk_PKCS7_value(asafes, i);
- bagnid = OBJ_obj2nid(p7->type);
- if (bagnid == NID_pkcs7_data) {
- bags = M_PKCS12_unpack_p7data(p7);
- } else if (bagnid == NID_pkcs7_encrypted) {
- /*
- * A length of '-1' means strlen() can be used
- * to determine the password length.
- */
- bags = M_PKCS12_unpack_p7encdata(p7, pass, -1);
- } else {
- SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_BAD_BAGTYPE);
- return (0);
- }
-
- if (bags == NULL) {
- SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_PARSE_BAG_ERR);
- sk_PKCS7_pop_free(asafes, PKCS7_free);
- return (0);
- }
- if (parse_all_bags(bags, pass, kl, cl) == 0) {
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- sk_PKCS7_pop_free(asafes, PKCS7_free);
- return (0);
- }
- }
-
- return (1);
-}
-
-/*
- * parse_all_bags - go through the stack of bags, parsing each.
- *
- * Note about error codes: This function is an internal function, and the
- * place where it is called sets error codes.
- *
- * Returns:
- * 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * 1 - Stack of safebags was parsed and lists of certs and private keys
- * were returned.
- */
-static int
-parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
- STACK_OF(EVP_PKEY) *kl, STACK_OF(X509) *cl)
-{
- int i;
- for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
- if (parse_one_bag(sk_PKCS12_SAFEBAG_value(bags, i),
- pass, kl, cl) == 0)
- return (0);
- }
- return (1);
-}
-
-/*
- * parse_one_bag - Parse an individual bag
- *
- * i = parse_one_bag(bag, pass, kl, cl);
- *
- * Arguments:
- * bag - pkcs12 safebag to parse.
- * pass - password for use in decryption of shrouded keybag
- * kl - Stack of private keys found so far. New private keys will
- * be added here if found.
- * cl - Stack of certs found so far. New certificates will be
- * added here if found.
- *
- * Returns:
- * 0 - An error returned. Call ERR_get_error() to get errors information.
- * Where possible, memory has been freed.
- * 1 - one safebag was parsed. If it contained a cert or private key, it
- * was added to the stack of certs or private keys found, respectively.
- * localKeyId or friendlyName attributes are returned with the
- * private key or certificate.
- */
-static int
-parse_one_bag(PKCS12_SAFEBAG *bag, const char *pass, STACK_OF(EVP_PKEY) *kl,
- STACK_OF(X509) *cl)
-{
- X509_ATTRIBUTE *attr = NULL;
- ASN1_TYPE *keyid = NULL;
- ASN1_TYPE *fname = NULL;
- PKCS8_PRIV_KEY_INFO *p8;
- EVP_PKEY *pkey = NULL;
- X509 *x509 = NULL;
- uchar_t *data = NULL;
- char *str = NULL;
- int retval = 1;
-
- keyid = PKCS12_get_attr(bag, NID_localKeyID);
- fname = PKCS12_get_attr(bag, NID_friendlyName);
-
- switch (M_PKCS12_bag_type(bag)) {
- case NID_keyBag:
- if ((pkey = EVP_PKCS82PKEY(bag->value.keybag)) == NULL) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
- retval = 0;
- break;
- }
- break;
-
- case NID_pkcs8ShroudedKeyBag:
- /*
- * A length of '-1' means strlen() can be used
- * to determine the password length.
- */
- if ((p8 = M_PKCS12_decrypt_skey(bag, pass, -1)) == NULL) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
- retval = 0;
- break;
- }
- pkey = EVP_PKCS82PKEY(p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (pkey == NULL) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
- retval = 0;
- }
- break;
-
- case NID_certBag:
- if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_CERTTYPE);
- break;
- }
- if ((x509 = M_PKCS12_certbag2x509(bag)) == NULL) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_PARSE_CERT_ERR);
- retval = 0;
- break;
- }
-
- if (keyid != NULL) {
- if (keyid->type != V_ASN1_OCTET_STRING) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_BAD_LKID);
- retval = 0;
- break;
- }
- if (X509_keyid_set1(x509,
- keyid->value.octet_string->data,
- keyid->value.octet_string->length) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_SET_LKID_ERR);
- retval = 0;
- break;
- }
- }
-
- if (fname != NULL) {
- ASN1_STRING *tmpstr = NULL;
- int len;
-
- if (fname->type != V_ASN1_BMPSTRING) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_BAD_FNAME);
- retval = 0;
- break;
- }
-
- tmpstr = fname->value.asn1_string;
- len = ASN1_STRING_to_UTF8(&data, tmpstr);
- if (len < 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_SET_FNAME_ERR);
- retval = 0;
- break;
- }
-
- if (X509_alias_set1(x509, data, len) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_SET_FNAME_ERR);
- retval = 0;
- break;
- }
- }
-
- if (sk_X509_push(cl, x509) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_MEMORY_FAILURE);
- retval = 0;
- break;
- }
- x509 = NULL;
- break;
-
- case NID_safeContentsBag:
- if (keyid != NULL)
- ASN1_TYPE_free(keyid);
- if (fname != NULL)
- ASN1_TYPE_free(fname);
- if (parse_all_bags(bag->value.safes, pass, kl, cl) == 0) {
- /*
- * Error already on stack
- */
- return (0);
- }
- return (1);
-
- default:
- if (keyid != NULL)
- ASN1_TYPE_free(keyid);
- if (fname != NULL)
- ASN1_TYPE_free(fname);
- SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_BAGTYPE);
- return (0);
- }
-
-
- if (pkey != NULL) {
- if (retval != 0 && (keyid != NULL || fname != NULL) &&
- pkey->attributes == NULL) {
- pkey->attributes = sk_X509_ATTRIBUTE_new_null();
- if (pkey->attributes == NULL) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_MEMORY_FAILURE);
- retval = 0;
- }
- }
-
- if (retval != 0 && keyid != NULL) {
- attr = type2attrib(keyid, NID_localKeyID);
- if (attr == NULL)
- /*
- * Error already on stack
- */
- retval = 0;
- else {
- keyid = NULL;
- if (sk_X509_ATTRIBUTE_push(pkey->attributes,
- attr) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_MEMORY_FAILURE);
- retval = 0;
- } else {
- attr = NULL;
- }
- }
- }
-
- if (retval != 0 && fname != NULL) {
- attr = type2attrib(fname, NID_friendlyName);
- if (attr == NULL) {
- /*
- * Error already on stack
- */
- retval = 0;
- } else {
- fname = NULL;
- if (sk_X509_ATTRIBUTE_push(pkey->attributes,
- attr) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_MEMORY_FAILURE);
- retval = 0;
- } else {
- attr = NULL;
- }
- }
- }
-
- /* Save the private key */
- if (retval != 0) {
- if (sk_EVP_PKEY_push(kl, pkey) == 0) {
- SUNWerr(SUNW_F_PARSE_ONE_BAG,
- SUNW_R_MEMORY_FAILURE);
- retval = 0;
- } else {
- pkey = NULL;
- }
- }
- }
-
- if (pkey != NULL) {
- sunw_evp_pkey_free(pkey);
- }
-
- if (x509 != NULL)
- X509_free(x509);
-
- if (keyid != NULL)
- ASN1_TYPE_free(keyid);
-
- if (fname != NULL)
- ASN1_TYPE_free(fname);
-
- if (attr != NULL)
- X509_ATTRIBUTE_free(attr);
-
- if (data != NULL)
- OPENSSL_free(data);
-
- if (str != NULL)
- OPENSSL_free(str);
-
- return (retval);
-}
-
-/*
- * This function uses the only function that reads PEM files, regardless of
- * the kinds of information included (private keys, public keys, cert requests,
- * certs). Other interfaces that read files require that the application
- * specifically know what kinds of things to read next, and call different
- * interfaces for the different kinds of entities.
- *
- * There is only one aspect of this function that's a bit problematic.
- * If it finds an encrypted private key, it does not decrypt it. It returns
- * the encrypted data and other information needed to decrypt it. The caller
- * must do the decryption. This function does the decoding.
- */
-static int
-pem_info(FILE *fp, pem_password_cb cb, void *userdata,
- STACK_OF(EVP_PKEY) **pkeys, STACK_OF(X509) **certs)
-{
- STACK_OF(X509_INFO) *info;
- STACK_OF(EVP_PKEY) *work_kl;
- STACK_OF(X509) *work_cl;
- X509_INFO *x;
- int retval = 0;
- int i;
-
- info = PEM_X509_INFO_read(fp, NULL, cb, userdata);
- if (info == NULL) {
- SUNWerr(SUNW_F_PEM_INFO, SUNW_R_READ_ERR);
- return (-1);
- }
-
- /*
- * Allocate the working stacks for private key(s) and for the cert(s).
- */
- if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
- SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
- retval = -1;
- goto cleanup;
- }
-
- if ((work_cl = sk_X509_new_null()) == NULL) {
- SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
- retval = -1;
- goto cleanup;
- }
-
- /*
- * Go through the entries in the info structure.
- */
- for (i = 0; i < sk_X509_INFO_num(info); i++) {
- x = sk_X509_INFO_value(info, i);
- if (x->x509) {
- if (sk_X509_push(work_cl, x->x509) == 0) {
- retval = -1;
- break;
- }
- x->x509 = NULL;
- }
- if (x->x_pkey != NULL && x->x_pkey->dec_pkey != NULL &&
- (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA ||
- x->x_pkey->dec_pkey->type == EVP_PKEY_DSA)) {
- const uchar_t *p;
-
- /*
- * If the key was encrypted, PEM_X509_INFO_read does
- * not decrypt it. If that is the case, the 'enc_pkey'
- * field is set to point to the unencrypted key data.
- * Go through the additional steps to decode it before
- * going on.
- */
- if (x->x_pkey->enc_pkey != NULL) {
-
- if (PEM_do_header(&x->enc_cipher,
- (uchar_t *)x->enc_data,
- (long *)&x->enc_len,
- cb, userdata) == 0) {
- if (ERR_GET_REASON(ERR_peek_error()) ==
- PEM_R_BAD_PASSWORD_READ) {
- SUNWerr(SUNW_F_PEM_INFO,
- SUNW_R_PASSWORD_ERR);
- } else {
- SUNWerr(SUNW_F_PEM_INFO,
- SUNW_R_PKEY_READ_ERR);
- }
- retval = -1;
- break;
- }
- if (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA) {
- RSA **pp;
-
- pp = &(x->x_pkey->dec_pkey->pkey.rsa);
- p = (uchar_t *)x->enc_data;
- if (d2i_RSAPrivateKey(pp, &p,
- x->enc_len) == NULL) {
- SUNWerr(SUNW_F_PEM_INFO,
- SUNW_R_PKEY_READ_ERR);
- retval = -1;
- break;
- }
- } else {
- DSA **pp;
-
- pp = &(x->x_pkey->dec_pkey->pkey.dsa);
- p = (uchar_t *)x->enc_data;
- if (d2i_DSAPrivateKey(pp, &p,
- x->enc_len) == NULL) {
- SUNWerr(SUNW_F_PEM_INFO,
- SUNW_R_PKEY_READ_ERR);
- retval = -1;
- break;
- }
- }
- }
-
- /* Save the key. */
- retval = sk_EVP_PKEY_push(work_kl, x->x_pkey->dec_pkey);
- if (retval == 0) {
- retval = -1;
- break;
- }
- x->x_pkey->dec_pkey = NULL;
- } else if (x->x_pkey != NULL) {
- SUNWerr(SUNW_F_PEM_INFO, SUNW_R_BAD_PKEYTYPE);
- retval = -1;
- break;
- }
- }
- if (retval == -1)
- goto cleanup;
-
- /* If error occurs, then error already on stack */
- retval = set_results(pkeys, &work_kl, certs, &work_cl, NULL, NULL,
- NULL, NULL);
-
-cleanup:
- if (work_kl != NULL) {
- sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
- }
- if (work_cl != NULL)
- sk_X509_pop_free(work_cl, X509_free);
-
- sk_X509_INFO_pop_free(info, X509_INFO_free);
-
- return (retval);
-}
-
-/*
- * sunw_append_keys - Given two stacks of private keys, remove the keys from
- * the second stack and append them to the first. Both stacks must exist
- * at time of call.
- *
- * Arguments:
- * dst - the stack to receive the keys from 'src'
- * src - the stack whose keys are to be moved.
- *
- * Returns:
- * -1 - An error occurred. The error status is set.
- * >= 0 - The number of keys that were copied.
- */
-static int
-sunw_append_keys(STACK_OF(EVP_PKEY) *dst, STACK_OF(EVP_PKEY) *src)
-{
- EVP_PKEY *tmpk;
- int count = 0;
-
- while (sk_EVP_PKEY_num(src) > 0) {
- tmpk = sk_EVP_PKEY_delete(src, 0);
- if (sk_EVP_PKEY_push(dst, tmpk) == 0) {
- sunw_evp_pkey_free(tmpk);
- SUNWerr(SUNW_F_APPEND_KEYS, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- count ++;
- }
-
- return (count);
-}
-
-/*
- * move_certs - Given two stacks of certs, remove the certs from
- * the second stack and append them to the first.
- *
- * Arguments:
- * dst - the stack to receive the certs from 'src'
- * src - the stack whose certs are to be moved.
- *
- * Returns:
- * -1 - An error occurred. The error status is set.
- * >= 0 - The number of certs that were copied.
- */
-static int
-move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src)
-{
- X509 *tmpc;
- int count = 0;
-
- while (sk_X509_num(src) > 0) {
- tmpc = sk_X509_delete(src, 0);
- if (sk_X509_push(dst, tmpc) == 0) {
- X509_free(tmpc);
- SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE);
- return (-1);
- }
- count++;
- }
-
- return (count);
-}
-
-/*
- * get_key_cert - Get a cert and its matching key from the stacks of certs
- * and keys. They are removed from the stacks.
- *
- * Arguments:
- * n - Offset of the entries to return.
- * kl - Points to a stack of private keys that matches the list of
- * certs below.
- * pkey - Points at location where the address of the matching private
- * key will be stored.
- * cl - Points to a stack of client certs with matching private keys.
- * cert - Points to locaiton where the address of the matching client cert
- * will be returned
- *
- * The assumption is that the stacks of keys and certs contain key/cert pairs,
- * with entries in the same order and hence at the same offset. Provided
- * the key and cert selected match, each will be removed from its stack and
- * returned.
- *
- * A stack of certs can be passed in without a stack of private keys, and vise
- * versa. In that case, the indicated key/cert will be returned.
- *
- * Returns:
- * 0 - No matches were found.
- * > 0 - Bits set based on FOUND_* definitions, indicating what is returned.
- * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
- */
-static int
-get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl,
- X509 **cert)
-{
- int retval = 0;
- int nk;
- int nc;
-
- nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0;
- nc = (cl != NULL) ? sk_X509_num(cl) : 0;
-
- if (pkey != NULL && *pkey == NULL) {
- if (nk > 0 && n >= 0 || n < nk) {
- *pkey = sk_EVP_PKEY_delete(kl, n);
- if (*pkey != NULL)
- retval |= FOUND_PKEY;
- }
- }
-
- if (cert != NULL && *cert == NULL) {
- if (nc > 0 && n >= 0 && n < nc) {
- *cert = sk_X509_delete(cl, n);
- if (*cert != NULL)
- retval |= FOUND_CERT;
- }
- }
-
- return (retval);
-}
-
-
-/*
- * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in
- * ASN1_BMPSTRING format.
- *
- * Arguments:
- * str - String to be convered.
- * len - Length of the string.
- *
- * Returns:
- * == NULL - An error occurred. Error information (accessible by
- * ERR_get_error()) is set.
- * != NULL - Points to an ASN1_BMPSTRING structure with the converted
- * string as a value.
- */
-static ASN1_BMPSTRING *
-asc2bmpstring(const char *str, int len)
-{
- ASN1_BMPSTRING *bmp = NULL;
- uchar_t *uni = NULL;
- int unilen;
-
- /* Convert the character to the bmp format. */
-#if OPENSSL_VERSION_NUMBER < 0x10000000L
- if (asc2uni(str, len, &uni, &unilen) == 0) {
-#else
- if (OPENSSL_asc2uni(str, len, &uni, &unilen) == 0) {
-#endif
- SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
- return (NULL);
- }
-
- /*
- * Adjust for possible pair of NULL bytes at the end because
- * asc2uni() returns a doubly null terminated string.
- */
- if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0')
- unilen -= 2;
-
- /* Construct comparison string with correct format */
- bmp = M_ASN1_BMPSTRING_new();
- if (bmp == NULL) {
- SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
- OPENSSL_free(uni);
- return (NULL);
- }
-
- bmp->data = uni;
- bmp->length = unilen;
-
- return (bmp);
-}
-
-/*
- * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string.
- * This goes through an intermediate step with a ASN1_STRING type of
- * IA5STRING (International Alphabet 5, which is the same as ASCII).
- *
- * Arguments:
- * str - UTF8STRING to be converted.
- *
- * Returns:
- * == NULL - An error occurred. Error information (accessible by
- * ERR_get_error()) is set.
- * != NULL - Points to a NULL-termianted ASCII string. The caller must
- * free it.
- */
-static uchar_t *
-utf82ascstr(ASN1_UTF8STRING *ustr)
-{
- ASN1_STRING tmpstr;
- ASN1_STRING *astr = &tmpstr;
- uchar_t *retstr = NULL;
- int mbflag;
- int ret;
-
- if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) {
- SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG);
- return (NULL);
- }
-
- mbflag = MBSTRING_ASC;
- tmpstr.data = NULL;
- tmpstr.length = 0;
-
- ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag,
- B_ASN1_IA5STRING);
- if (ret < 0) {
- SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR);
- return (NULL);
- }
-
- retstr = OPENSSL_malloc(astr->length + 1);
- if (retstr == NULL) {
- SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE);
- return (NULL);
- }
-
- (void) memcpy(retstr, astr->data, astr->length);
- retstr[astr->length] = '\0';
- OPENSSL_free(astr->data);
-
- return (retstr);
-}
-
-
-/*
- * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type
- * specified by the given NID.
- *
- * Arguments:
- * ty - Type structure to be made into an attribute
- * nid - NID of the attribute
- *
- * Returns:
- * NULL An error occurred.
- * != NULL An X509_ATTRIBUTE structure.
- */
-X509_ATTRIBUTE *
-type2attrib(ASN1_TYPE *ty, int nid)
-{
- X509_ATTRIBUTE *a;
-
- if ((a = X509_ATTRIBUTE_new()) == NULL ||
- (a->value.set = sk_ASN1_TYPE_new_null()) == NULL ||
- sk_ASN1_TYPE_push(a->value.set, ty) == 0) {
- if (a != NULL)
- X509_ATTRIBUTE_free(a);
- SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE);
- return (NULL);
- }
- a->single = 0;
- a->object = OBJ_nid2obj(nid);
-
- return (a);
-}
-
-/*
- * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE
- * component
- *
- * Arguments:
- * attr - Attribute structure containing a type.
- *
- * Returns:
- * NULL An error occurred.
- * != NULL An ASN1_TYPE structure.
- */
-static ASN1_TYPE *
-attrib2type(X509_ATTRIBUTE *attr)
-{
- ASN1_TYPE *ty = NULL;
-
- if (attr == NULL || attr->single == 1)
- return (NULL);
-
- if (sk_ASN1_TYPE_num(attr->value.set) > 0)
- ty = sk_ASN1_TYPE_value(attr->value.set, 0);
-
- return (ty);
-}
-
-/*
- * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE
- * of the type specified by the given NID.
- *
- * Arguments:
- * attrs - Stack of attributes to search
- * nid - NID of the attribute being searched for
- *
- * Returns:
- * -1 None found
- * != -1 Offset of the matching attribute.
- */
-static int
-find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
-{
- X509_ATTRIBUTE *a;
- int i;
-
- if (attrs == NULL)
- return (-1);
-
- for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
- a = sk_X509_ATTRIBUTE_value(attrs, i);
- if (OBJ_obj2nid(a->object) == nid)
- return (i);
- }
- return (-1);
-}
-
-/*
- * Called by our PKCS12 code to read our function and error codes
- * into memory so that the OpenSSL framework can retrieve them.
- */
-void
-ERR_load_SUNW_strings(void)
-{
- assert(SUNW_lib_error_code == 0);
-#ifndef OPENSSL_NO_ERR
- /*
- * Have OpenSSL provide us with a unique ID.
- */
- SUNW_lib_error_code = ERR_get_next_error_library();
-
- ERR_load_strings(SUNW_lib_error_code, SUNW_str_functs);
- ERR_load_strings(SUNW_lib_error_code, SUNW_str_reasons);
-
- SUNW_lib_name->error = ERR_PACK(SUNW_lib_error_code, 0, 0);
- ERR_load_strings(0, SUNW_lib_name);
-#endif
-}
-
-/*
- * The SUNWerr macro resolves to this routine. So when we need
- * to push an error, this routine does it for us. Notice that
- * the SUNWerr macro provides a filename and line #.
- */
-void
-ERR_SUNW_error(int function, int reason, char *file, int line)
-{
- assert(SUNW_lib_error_code != 0);
-#ifndef OPENSSL_NO_ERR
- ERR_PUT_error(SUNW_lib_error_code, function, reason, file, line);
-#endif
-}
-
-/*
- * check_time - Given an indication of the which time(s) to check, check
- * that time or those times against the current time and return the
- * relationship.
- *
- * Arguments:
- * chkwhat - What kind of check to do.
- * cert - The cert to check.
- *
- * Returns:
- * CHKERR_* values.
- */
-static chk_errs_t
-check_time(chk_actions_t chkwhat, X509 *cert)
-{
- int i;
-
- if (chkwhat == CHK_NOT_BEFORE || chkwhat == CHK_BOTH) {
- i = X509_cmp_time(X509_get_notBefore(cert), NULL);
- if (i == 0)
- return (CHKERR_TIME_BEFORE_BAD);
- if (i > 0)
- return (CHKERR_TIME_IS_BEFORE);
-
- /* The current time is after the 'not before' time */
- }
-
- if (chkwhat == CHK_NOT_AFTER || chkwhat == CHK_BOTH) {
- i = X509_cmp_time(X509_get_notAfter(cert), NULL);
- if (i == 0)
- return (CHKERR_TIME_AFTER_BAD);
- if (i < 0)
- return (CHKERR_TIME_HAS_EXPIRED);
- }
-
- return (CHKERR_TIME_OK);
-}
-
-/*
- * find_attr - Look for a given attribute of the type associated with the NID.
- *
- * Arguments:
- * nid - NID for the attribute to be found (either NID_friendlyName or
- * NID_locakKeyId)
- * str - ASN1_STRING-type structure containing the value to be found,
- * FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a
- * ASN1_STRING.
- * kl - Points to a stack of private keys.
- * pkey - Points at a location where the address of the matching private
- * key will be stored.
- * cl - Points to a stack of client certs with matching private keys.
- * cert - Points to locaiton where the address of the matching client cert
- * will be returned
- *
- * This function is designed to process lists of certs and private keys.
- * This is made complex because these the attributes are stored differently
- * for certs and for keys. For certs, only a few attributes are retained.
- * FriendlyName is stored in the aux structure, under the name 'alias'.
- * LocalKeyId is also stored in the aux structure, under the name 'keyid'.
- * A pkey structure has a stack of attributes.
- *
- * The basic approach is:
- * - If there there is no stack of certs but a stack of private keys exists,
- * search the stack of keys for a match. Alternately, if there is a stack
- * of certs and no private keys, search the certs.
- *
- * - If there are both certs and keys, assume that the matching certs and
- * keys are in their respective stacks, with matching entries in the same
- * order. Search for the name or keyid in the stack of certs. If it is
- * not found, then this function returns 0 (nothing found).
- *
- * - Once a cert is found, verify that the key actually matches by
- * comparing the private key with the public key (in the cert).
- * If they don't match, return an error.
- *
- * A pointer to cert and/or pkey which matches the name or keyid is stored
- * in the return arguments.
- *
- * Returns:
- * 0 - No matches were found.
- * > 0 - Bits set based on FOUND_* definitions, indicating what was found.
- * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
- */
-static int
-find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey,
- STACK_OF(X509) *cl, X509 **cert)
-{
- ASN1_UTF8STRING *ustr = NULL;
- ASN1_STRING *s;
- ASN1_TYPE *t;
- EVP_PKEY *p;
- uchar_t *fname = NULL;
- X509 *x;
- int found = 0;
- int chkcerts;
- int len;
- int res;
- int c = -1;
- int k = -1;
-
- chkcerts = (cert != NULL || pkey != NULL) && cl != NULL;
- if (chkcerts && nid == NID_friendlyName &&
- str->type == V_ASN1_BMPSTRING) {
- ustr = ASN1_UTF8STRING_new();
- if (ustr == NULL) {
- SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
- return (0);
- }
- len = ASN1_STRING_to_UTF8(&fname, str);
- if (fname == NULL) {
- ASN1_UTF8STRING_free(ustr);
- SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR);
- return (0);
- }
-
- if (ASN1_STRING_set(ustr, fname, len) == 0) {
- ASN1_UTF8STRING_free(ustr);
- OPENSSL_free(fname);
- SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
- return (0);
- }
- }
-
- if (chkcerts) {
- for (c = 0; c < sk_X509_num(cl); c++) {
- res = -1;
- x = sk_X509_value(cl, c);
- if (nid == NID_friendlyName && ustr != NULL) {
- if (x->aux == NULL || x->aux->alias == NULL)
- continue;
- s = x->aux->alias;
- if (s != NULL && s->type == ustr->type &&
- s->data != NULL) {
- res = ASN1_STRING_cmp(s, ustr);
- }
- } else {
- if (x->aux == NULL || x->aux->keyid == NULL)
- continue;
- s = x->aux->keyid;
- if (s != NULL && s->type == str->type &&
- s->data != NULL) {
- res = ASN1_STRING_cmp(s, str);
- }
- }
- if (res == 0) {
- if (cert != NULL)
- *cert = sk_X509_delete(cl, c);
- found = FOUND_CERT;
- break;
- }
- }
- if (ustr != NULL) {
- ASN1_UTF8STRING_free(ustr);
- OPENSSL_free(fname);
- }
- }
-
- if (pkey != NULL && kl != NULL) {
- /*
- * Looking for pkey to match a cert? If so, assume that
- * lists of certs and their matching pkeys are in the same
- * order. Call X509_check_private_key() to verify this
- * assumption.
- */
- if (found != 0 && cert != NULL) {
- k = c;
- p = sk_EVP_PKEY_value(kl, k);
- if (X509_check_private_key(x, p) != 0) {
- if (pkey != NULL)
- *pkey = sk_EVP_PKEY_delete(kl, k);
- found |= FOUND_PKEY;
- }
- } else if (cert == NULL) {
- for (k = 0; k < sk_EVP_PKEY_num(kl); k++) {
- p = sk_EVP_PKEY_value(kl, k);
- if (p == NULL || p->attributes == NULL)
- continue;
-
- t = PKCS12_get_attr_gen(p->attributes, nid);
- if (t != NULL || ASN1_STRING_cmp(str,
- t->value.asn1_string) == 0)
- continue;
-
- found |= FOUND_PKEY;
- if (pkey != NULL)
- *pkey = sk_EVP_PKEY_delete(kl, k);
- break;
- }
- }
- }
-
- return (found);
-}
-
-/*
- * set_results - Given two pointers to stacks of private keys, certs or CA
- * CA certs, either copy the second stack to the first, or append the
- * contents of the second to the first.
- *
- * Arguments:
- * pkeys - Points to stack of pkeys
- * work_kl - Points to working stack of pkeys
- * certs - Points to stack of certs
- * work_cl - Points to working stack of certs
- * cacerts - Points to stack of CA certs
- * work_ca - Points to working stack of CA certs
- * xtrakeys - Points to stack of unmatcned pkeys
- * work_xl - Points to working stack of unmatcned pkeys
- *
- * The arguments are in pairs. The first of each pair points to a stack
- * of keys or certs. The second of the pair points at a 'working stack'
- * of the same type of entities. Actions taken are as follows:
- *
- * - If either the first or second argument is NULL, or if there are no
- * members in the second stack, there is nothing to do.
- * - If the first argument points to a pointer which is NULL, then there
- * is no existing stack for the first argument. Copy the stack pointer
- * from the second argument to the first argument and NULL out the stack
- * pointer for the second.
- * - Otherwise, go through the elements of the second stack, removing each
- * and adding it to the first stack.
- *
- * Returns:
- * == -1 - An error occurred. Call ERR_get_error() to get error information.
- * == 0 - No matching returns were found.
- * > 0 - This is the arithmetic 'or' of the FOUND_* bits that indicate which
- * of the requested entries were manipulated.
- */
-static int
-set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl,
- STACK_OF(X509) **certs, STACK_OF(X509) **work_cl,
- STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca,
- STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl)
-{
- int retval = 0;
-
- if (pkeys != NULL && work_kl != NULL && *work_kl != NULL &&
- sk_EVP_PKEY_num(*work_kl) > 0) {
- if (*pkeys == NULL) {
- *pkeys = *work_kl;
- *work_kl = NULL;
- } else {
- if (sunw_append_keys(*pkeys, *work_kl) < 0) {
- return (-1);
- }
- }
- retval |= FOUND_PKEY;
- }
- if (certs != NULL && work_cl != NULL && *work_cl != NULL &&
- sk_X509_num(*work_cl) > 0) {
- if (*certs == NULL) {
- *certs = *work_cl;
- *work_cl = NULL;
- } else {
- if (move_certs(*certs, *work_cl) < 0) {
- return (-1);
- }
- }
- retval |= FOUND_CERT;
- }
-
- if (cacerts != NULL && work_ca != NULL && *work_ca != NULL &&
- sk_X509_num(*work_ca) > 0) {
- if (*cacerts == NULL) {
- *cacerts = *work_ca;
- *work_ca = NULL;
- } else {
- if (move_certs(*cacerts, *work_ca) < 0) {
- return (-1);
- }
- }
- retval |= FOUND_CA_CERTS;
- }
-
- if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL &&
- sk_EVP_PKEY_num(*work_xl) > 0) {
- if (*xtrakeys == NULL) {
- *xtrakeys = *work_xl;
- *work_xl = NULL;
- } else {
- if (sunw_append_keys(*xtrakeys, *work_xl) < 0) {
- return (-1);
- }
- }
- retval |= FOUND_XPKEY;
- }
-
- return (retval);
-}
diff --git a/usr/src/lib/libpkg/common/p12lib.h b/usr/src/lib/libpkg/common/p12lib.h
deleted file mode 100644
index 3d80ddaa35..0000000000
--- a/usr/src/lib/libpkg/common/p12lib.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _P12LIB_H
-#define _P12LIB_H
-
-
-#include <openssl/pkcs12.h>
-#include <openssl/pem.h>
-
-/*
- * PKCS12 file routines borrowed from SNT's libwanboot.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These declarations allow us to make stacks of EVP_PKEY objects */
-DECLARE_STACK_OF(EVP_PKEY)
-#define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
-#define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
-#define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
-#define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
-#define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
-#define sk_EVP_PKEY_find(st, val) SKM_sk_find(EVP_PKEY, (st), (val))
-#define sk_EVP_PKEY_delete(st, i) SKM_sk_delete(EVP_PKEY, (st), (i))
-#define sk_EVP_PKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PKEY, (st), (ptr))
-#define sk_EVP_PKEY_insert(st, val, i) SKM_sk_insert(EVP_PKEY, (st), (val), (i))
-#define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
- (free_func))
-#define sk_EVP_PKEY_pop(st) SKM_sk_pop(EVP_PKEY, (st))
-
-/* Error reporting routines required by OpenSSL */
-#define SUNW_LIB_NAME "SUNW_PKCS12"
-#define SUNWerr(f, r) ERR_SUNW_error((f), (r), __FILE__, __LINE__)
-
-/* Error codes for the SUNW functions. */
-/* OpenSSL prefers codes to start at 100 */
-
-/* Function codes. */
-typedef enum {
- SUNW_F_USE_X509CERT = 100,
- SUNW_F_USE_PKEY,
- SUNW_F_USE_TASTORE,
- SUNW_F_USE_CERTFILE,
- SUNW_F_USE_KEYFILE,
- SUNW_F_USE_TRUSTFILE,
- SUNW_F_READ_FILE,
- SUNW_F_DOPARSE,
- SUNW_F_PKCS12_PARSE,
- SUNW_F_PKCS12_CONTENTS,
- SUNW_F_PARSE_ONE_BAG,
- SUNW_F_PKCS12_CREATE,
- SUNW_F_SPLIT_CERTS,
- SUNW_F_FIND_LOCALKEYID,
- SUNW_F_SET_LOCALKEYID,
- SUNW_F_SET_FNAME,
- SUNW_F_GET_LOCALKEYID,
- SUNW_F_GET_PKEY_FNAME,
- SUNW_F_APPEND_KEYS,
- SUNW_F_PEM_CONTENTS,
- SUNW_F_PEM_INFO,
- SUNW_F_ASC2BMPSTRING,
- SUNW_F_UTF82ASCSTR,
- SUNW_F_FINDATTR,
- SUNW_F_TYPE2ATTRIB,
- SUNW_F_MOVE_CERTS,
- SUNW_F_FIND_FNAME,
- SUNW_F_PARSE_OUTER,
- SUNW_F_CHECKFILE
-} sunw_err_func_t;
-
-/* Reason codes. */
-typedef enum {
- SUNW_R_INVALID_ARG = 100,
- SUNW_R_MEMORY_FAILURE,
- SUNW_R_MAC_VERIFY_FAILURE,
- SUNW_R_MAC_CREATE_FAILURE,
- SUNW_R_BAD_FILETYPE,
- SUNW_R_BAD_PKEY,
- SUNW_R_BAD_PKEYTYPE,
- SUNW_R_PKEY_READ_ERR,
- SUNW_R_NO_TRUST_ANCHOR,
- SUNW_R_READ_TRUST_ERR,
- SUNW_R_ADD_TRUST_ERR,
- SUNW_R_PKCS12_PARSE_ERR,
- SUNW_R_PKCS12_CREATE_ERR,
- SUNW_R_PARSE_BAG_ERR,
- SUNW_R_MAKE_BAG_ERR,
- SUNW_R_BAD_CERTTYPE,
- SUNW_R_PARSE_CERT_ERR,
- SUNW_R_BAD_LKID,
- SUNW_R_SET_LKID_ERR,
- SUNW_R_BAD_FNAME,
- SUNW_R_SET_FNAME_ERR,
- SUNW_R_BAD_TRUST,
- SUNW_R_BAD_BAGTYPE,
- SUNW_R_CERT_ERR,
- SUNW_R_PKEY_ERR,
- SUNW_R_READ_ERR,
- SUNW_R_ADD_ATTR_ERR,
- SUNW_R_STR_CONVERT_ERR,
- SUNW_R_PKCS12_EMPTY_ERR,
- SUNW_R_PASSWORD_ERR
-} sunw_err_reason_t;
-
-/*
- * Type of checking to perform when calling sunw_check_cert_times
- */
-typedef enum {
- CHK_NOT_BEFORE = 1, /* Check 'not before' date */
- CHK_NOT_AFTER, /* Check 'not after' date */
- CHK_BOTH /* Check both dates */
-} chk_actions_t;
-
-/*
- * Return type for sunw_check_cert_times
- */
-typedef enum {
- CHKERR_TIME_OK = 0, /* Current time meets requested checks */
- CHKERR_TIME_BEFORE_BAD, /* 'not before' field is invalid */
- CHKERR_TIME_AFTER_BAD, /* 'not after' field is invalid */
- CHKERR_TIME_IS_BEFORE, /* Current time is before 'not before' */
- CHKERR_TIME_HAS_EXPIRED /* Current time is after 'not after' */
-} chk_errs_t;
-
-/*
- * This type indicates what to do with an attribute being returned.
- */
-typedef enum {
- GETDO_COPY = 1, /* Simply return the value of the attribute */
- GETDO_DEL /* Delete the attribute at the same time. */
-} getdo_actions_t;
-
-/*
- * For sunw_pkcs12_parse, the following are values for bits that indicate
- * various types of searches/matching to do. Any of these values can be
- * OR'd together. However, the order in which an attempt will be made
- * to satisfy them is the order in which they are listed below. The
- * exception is DO_NONE. It should not be OR'd with any other value.
- */
-#define DO_NONE 0x00 /* Don't even try to match */
-#define DO_FIND_KEYID 0x01 /* 1st cert, key with matching localkeyid */
-#define DO_FIND_FN 0x02 /* 1st cert, key with matching friendlyname */
-#define DO_FIRST_PAIR 0x04 /* Return first matching cert/key pair found */
-#define DO_LAST_PAIR 0x08 /* Return last matching cert/key pair found */
-#define DO_UNMATCHING 0x10 /* Return first cert and/or key */
-
-/* Bits returned, which indicate what values were found. */
-#define FOUND_PKEY 0x01 /* Found one or more private key */
-#define FOUND_CERT 0x02 /* Found one or more client certificate */
-#define FOUND_CA_CERTS 0x04 /* Added at least one cert to the CA list */
-#define FOUND_XPKEY 0x08 /* Found at least one private key which does */
- /* not match a certificate in the certs list */
-
-/* p12lib.c */
-PKCS12 *sunw_PKCS12_create(const char *, STACK_OF(EVP_PKEY) *,
- STACK_OF(X509) *, STACK_OF(X509) *);
-
-int sunw_split_certs(STACK_OF(EVP_PKEY) *, STACK_OF(X509) *,
- STACK_OF(X509) **, STACK_OF(EVP_PKEY) **);
-
-void sunw_evp_pkey_free(EVP_PKEY *);
-int sunw_set_localkeyid(const char *, int, EVP_PKEY *, X509 *);
-int sunw_get_pkey_localkeyid(getdo_actions_t, EVP_PKEY *, char **, int *);
-int sunw_get_pkey_fname(getdo_actions_t, EVP_PKEY *, char **);
-int sunw_find_localkeyid(char *, int, STACK_OF(EVP_PKEY) *,
- STACK_OF(X509) *, EVP_PKEY **, X509 **);
-int sunw_find_fname(char *, STACK_OF(EVP_PKEY) *, STACK_OF(X509) *,
- EVP_PKEY **, X509 **);
-int sunw_set_fname(const char *, EVP_PKEY *, X509 *);
-int sunw_check_keys(X509 *, EVP_PKEY *);
-
-chk_errs_t sunw_check_cert_times(chk_actions_t, X509 *);
-extern void ERR_SUNW_error(int function, int reason, char *file, int line);
-extern void ERR_load_SUNW_strings(void);
-int sunw_PKCS12_contents(PKCS12 *, const char *,
- STACK_OF(EVP_PKEY) **, STACK_OF(X509) **);
-int sunw_get_cert_fname(getdo_actions_t, X509 *, char **);
-int sunw_PEM_contents(FILE *, pem_password_cb, void *,
- STACK_OF(EVP_PKEY) **, STACK_OF(X509) **);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _P12LIB_H */
diff --git a/usr/src/lib/libpkg/common/path_valid.c b/usr/src/lib/libpkg/common/path_valid.c
new file mode 100644
index 0000000000..c320685cdb
--- /dev/null
+++ b/usr/src/lib/libpkg/common/path_valid.c
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+
+/*
+ * Name: path_valid
+ * Description: Checks a string for being a valid path
+ *
+ * Arguments: path - path to validate
+ *
+ * Returns : B_TRUE - success, B_FALSE otherwise.
+ * B_FALSE means path was null, too long (>PATH_MAX),
+ * or too short (<1)
+ */
+boolean_t
+path_valid(char *path)
+{
+ if (path == NULL) {
+ return (B_FALSE);
+ } else if (strlen(path) > PATH_MAX) {
+ return (B_FALSE);
+ } else if (strlen(path) >= 1) {
+ return (B_TRUE);
+ } else {
+ /* path < 1 */
+ return (B_FALSE);
+ }
+}
diff --git a/usr/src/lib/libpkg/common/pkgerr.c b/usr/src/lib/libpkg/common/pkgerr.c
deleted file mode 100644
index 6828d88968..0000000000
--- a/usr/src/lib/libpkg/common/pkgerr.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-/*
- * Module: pkgerr.c
- * Description:
- * Module for handling error messages that come from libpkg libraries.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <locale.h>
-#include <libintl.h>
-#include <stdlib.h>
-#include <sys/varargs.h>
-#include "pkgerr.h"
-
-/* max length of any formatted error message */
-#define MAX_ERRMSGLEN 1024
-
-/* private structures (not visible outside this file) */
-struct _pkg_err_struct {
- int nerrs;
- char **msgs;
- PKG_ERR_CODE *errs;
-};
-
-/* ---------------------- public functions ----------------------- */
-
-PKG_ERR
-*pkgerr_new()
-{
- PKG_ERR *newerr;
-
- newerr = (PKG_ERR *)malloc(sizeof (PKG_ERR));
- newerr->nerrs = 0;
- newerr->msgs = NULL;
- newerr->errs = NULL;
- return (newerr);
-}
-
-/*PRINTFLIKE3*/
-void
-pkgerr_add(PKG_ERR *err, PKG_ERR_CODE code, char *fmt, ...)
-{
- char errmsgbuf[1024];
- va_list ap;
-
- va_start(ap, fmt);
- (void) vsnprintf(errmsgbuf, MAX_ERRMSGLEN, fmt, ap);
- va_end(ap);
-
- err->nerrs++;
-
- err->msgs = (char **)realloc(err->msgs,
- err->nerrs * sizeof (char *));
- err->errs = (PKG_ERR_CODE *)realloc(err->errs,
- err->nerrs * sizeof (PKG_ERR_CODE));
- err->msgs[err->nerrs - 1] = strdup(errmsgbuf);
- err->errs[err->nerrs - 1] = code;
-}
-
-void
-pkgerr_clear(PKG_ERR *err)
-{
- int i;
-
- for (i = 0; i < err->nerrs; i++) {
- free(err->msgs[i]);
- }
-
- free(err->msgs);
- free(err->errs);
- err->msgs = NULL;
- err->errs = NULL;
- err->nerrs = 0;
-}
-
-int
-pkgerr_num(PKG_ERR *err)
-{
- return (err->nerrs);
-}
-
-char
-*pkgerr_get(PKG_ERR *err, int pos)
-{
- if (pos < 0 || pos > (err->nerrs - 1)) {
- return (NULL);
- }
-
- return (err->msgs[pos]);
-}
-
-void
-pkgerr_free(PKG_ERR *err)
-{
- pkgerr_clear(err);
- free(err);
-}
diff --git a/usr/src/lib/libpkg/common/pkgerr.h b/usr/src/lib/libpkg/common/pkgerr.h
deleted file mode 100644
index 10e0e219d9..0000000000
--- a/usr/src/lib/libpkg/common/pkgerr.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKGERR_H
-#define _PKGERR_H
-
-
-/*
- * Module: pkgerr.h
- * Description:
- *
- * Implements error routines to handle the creation,
- * management, and destruction of error objects, which
- * hold error messages and codes returned from libpkg
- * routines that support the objects defined herein.
- */
-
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Public Definitions
- */
-
-typedef enum {
- PKGERR_OK = 0,
- PKGERR_EXIST,
- PKGERR_READ,
- PKGERR_CORRUPT,
- PKGERR_PARSE,
- PKGERR_BADPASS,
- PKGERR_BADALIAS,
- PKGERR_INTERNAL,
- PKGERR_UNSUP,
- PKGERR_NOALIAS,
- PKGERR_NOALIASMATCH,
- PKGERR_MULTIPLE,
- PKGERR_INCOMPLETE,
- PKGERR_NOPRIVKEY,
- PKGERR_NOPUBKEY,
- PKGERR_NOCACERT,
- PKGERR_NOMEM,
- PKGERR_CHAIN,
- PKGERR_LOCKED,
- PKGERR_WRITE,
- PKGERR_UNLOCK,
- PKGERR_TIME,
- PKGERR_DUPLICATE,
- PKGERR_WEB,
- PKGERR_VERIFY
-} PKG_ERR_CODE;
-
-/*
- * Public Structures
- */
-
-/* external reference to PKG_ERR object (contents private) */
-typedef PKG_ERR_CODE pkg_err_t;
-
-typedef struct _pkg_err_struct PKG_ERR;
-
-/*
- * Public Methods
- */
-
-PKG_ERR *pkgerr_new();
-void pkgerr_add(PKG_ERR *, PKG_ERR_CODE, char *, ...);
-void pkgerr_clear(PKG_ERR *);
-int pkgerr_dump(PKG_ERR *, FILE *);
-int pkgerr_num(PKG_ERR *);
-char *pkgerr_get(PKG_ERR *, int);
-void pkgerr_free(PKG_ERR *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKGERR_H */
diff --git a/usr/src/lib/libpkg/common/pkglib.h b/usr/src/lib/libpkg/common/pkglib.h
index 4e4bdabf91..31f392fe95 100644
--- a/usr/src/lib/libpkg/common/pkglib.h
+++ b/usr/src/lib/libpkg/common/pkglib.h
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,12 +44,6 @@ extern "C" {
#include <stdio.h>
#include <pkgdev.h>
#include <pkgstrct.h>
-#include <openssl/bio.h>
-#include <openssl/x509.h>
-#include <netdb.h>
-#include <boot_http.h>
-#include "pkgerr.h"
-#include "keystore.h"
#include "cfext.h"
/*
@@ -355,33 +353,13 @@ struct dstr {
#define SMALL_DIVISOR 4
#define MED_DIVISOR 5
#define LARGE_DIVISOR 10
-#define MED_DWNLD (10 * 1024 * 1024) /* 10 MB */
-#define LARGE_DWNLD (5 * MED_DWNLD) /* 50 MB */
-
-#define HTTP "http://"
-#define HTTPS "https://"
#define PKGADD "pkgadd"
-/* Settings for network admin defaults */
-
-#define NET_TIMEOUT_DEFAULT 60
-#define NET_RETRIES_DEFAULT 3
-#define NET_TIMEOUT_MIN 1 /* 1 second */
-#define NET_TIMEOUT_MAX (5 * 60) /* 5 minutes */
-#define NET_RETRIES_MIN 1
-#define NET_RETRIES_MAX 10
-#define AUTH_NOCHECK 0
-#define AUTH_QUIT 1
-
/* package header magic tokens */
#define HDR_PREFIX "# PaCkAgE DaTaStReAm"
#define HDR_SUFFIX "# end of header"
-/* name of security files */
-#define PKGSEC "/var/sadm/security"
-#define SIGNATURE_FILENAME "signature"
-
#define GROUP "/etc/group"
#define PASSWD "/etc/passwd"
@@ -435,9 +413,6 @@ extern int ds_getpkg(char *device, int n, char *dstdir);
extern int ds_ginit(char *device);
extern boolean_t ds_fd_open(void);
extern int ds_init(char *device, char **pkg, char *norewind);
-extern int BIO_ds_dump_header(PKG_ERR *, BIO *);
-extern int BIO_ds_dump(PKG_ERR *, char *, BIO *);
-extern int BIO_dump_cmd(char *cmd, BIO *bio);
extern int ds_next(char *, char *);
extern int ds_readbuf(char *device);
extern int epclose(FILE *pp);
@@ -464,7 +439,7 @@ extern int pkghead(char *device);
extern int pkgmount(struct pkgdev *devp, char *pkg, int part, int nparts,
int getvolflg);
extern int pkgtrans(char *device1, char *device2, char **pkg,
- int options, keystore_handle_t, char *);
+ int options);
extern int pkgumount(struct pkgdev *devp);
extern int ppkgmap(struct cfent *ept, FILE *fp);
extern int putcfile(struct cfent *ept, FILE *fp);
@@ -474,9 +449,6 @@ extern void set_memalloc_failure_func(void (*)(int));
extern void *xmalloc(size_t size);
extern void *xrealloc(void *ptr, size_t size);
extern char *xstrdup(char *str);
-extern void set_passphrase_prompt(char *);
-extern void set_passphrase_passarg(char *);
-extern int pkg_passphrase_cb(char *, int, int, void *);
extern int srchcfile(struct cfent *ept, char *path, PKGserver server);
extern struct group *cgrgid(gid_t gid);
@@ -503,7 +475,6 @@ extern int mappath(int flag, char *path);
extern int mapvar(int flag, char *varname);
/*PRINTFLIKE1*/
extern void progerr(char *fmt, ...);
-extern void pkgerr(PKG_ERR *);
extern void rpterr(void);
extern void tputcfent(struct cfent *ept, FILE *fp);
extern void set_nonABI_symlinks(void);
@@ -511,15 +482,6 @@ extern int nonABI_symlinks(void);
extern void disable_attribute_check(void);
extern int get_disable_attribute_check(void);
-/* security.c */
-extern void sec_init(void);
-extern char *get_subject_display_name(X509 *);
-extern char *get_issuer_display_name(X509 *);
-extern char *get_serial_num(X509 *);
-extern char *get_fingerprint(X509 *, const EVP_MD *);
-extern int get_cert_chain(PKG_ERR *, X509 *, STACK_OF(X509) *,
- STACK_OF(X509) *, STACK_OF(X509) **);
-
/* pkgstr.c */
void pkgstrConvertUllToTimeString_r(unsigned long long a_time,
char *a_buf, int a_bufLen);
@@ -567,6 +529,9 @@ extern int vfpWriteToFile(VFP_T *a_vfp, char *a_path);
boolean_t enable_local_fs(void);
boolean_t restore_local_fs(void);
+/* path_valid.c */
+extern boolean_t path_valid(char *);
+
/* pkgserv.c */
extern PKGserver pkgopenserver(const char *, const char *, boolean_t);
extern void pkgcloseserver(PKGserver);
diff --git a/usr/src/lib/libpkg/common/pkglibmsgs.h b/usr/src/lib/libpkg/common/pkglibmsgs.h
index 4b811ca6ae..342b836d73 100644
--- a/usr/src/lib/libpkg/common/pkglibmsgs.h
+++ b/usr/src/lib/libpkg/common/pkglibmsgs.h
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -54,8 +58,6 @@ extern "C" {
/* pkgtrans messages */
#define MSG_TRANSFER "Transferring <%s> package instance\n"
-#define MSG_STORE_ACC "Retrieving signature certificates from <%s>\n"
-#define MSG_SIGNING "Generating digital signature for signer <%s>\n"
#define MSG_RENAME "\t... instance renamed <%s> on destination\n"
#define ERR_TRANSFER "unable to complete package transfer"
@@ -90,124 +92,6 @@ extern "C" {
#define MSG_OPEN "- open of <%s> failed, errno=%d"
#define MSG_STATVFS "- statvfs(%s) failed, errno=%d"
-/* security problems */
-#define ERR_PARSE "unable to parse keystore <%s>, invalid " \
- "format or corrupt"
-#define ERR_BADPASS "Invalid password. Password does not " \
- "decrypt keystore"
-
-#define MSG_PASSWD_FILE "Password file <%s> cannot be read"
-#define MSG_PASSWD_AGAIN "For Verification"
-#define MSG_PASSWD_NOMATCH "Passwords do not match"
-#define MSG_BADPASSARG "Password retrieval method <%s> invalid"
-#define MSG_NOPASS "Cannot get passphrase using " \
- "retrieval method <%s>"
-
-#define ERR_MISMATCHPASS "<%s> encrypted with different password " \
- " than <%s>, keystore <%s> corrupt"
-
-#define MSG_CHSIGDIR "- unable to change directory to <%s/%s>"
-#define MSG_MKSIGDIR "- unable to make directory <%s/%s>"
-#define ERR_CANTSIGN "- destination device must be datastream in order to" \
- " sign contents"
-#define ERR_STORE "unable to find or use store <%s> from application " \
- "<%s>:<%s>"
-
-#define ERR_NO_KEYSTORE "unable to open keystore <%s> for reading"
-#define ERR_NOT_REG "<%s> is not a regular file"
-#define ERR_KEYSTORE_CORRUPT "Keystore file <%s> is corrupt or unparseable"
-#define ERR_KEYSTORE_REPAIR "unable to repair keystore <%s>"
-#define ERR_KEYSTORE_LOCKED_READ "unable to lock keystore file <%s> " \
- "for reading, try again later"
-#define ERR_KEYSTORE_LOCKED "unable to lock keystore <%s> for exclusive " \
- "access"
-#define ERR_KEYSTORE_UNLOCK "unable to unlock keystore <%s> for " \
- "application <%s>"
-#define ERR_KEYSTORE_WRITE "unable to open keystore <%s> for writing"
-#define ERR_KEYSTORE_REMOVE "unable to delete keystore file <%s>"
-#define ERR_KEYSTORE_READ "unable to open keystore <%s> for reading"
-#define ERR_KEYSTORE_OPEN "unable to open keystore <%s>:<%s>"
-#define ERR_KEYSTORE_FORM "unable to form PKCS12 keystore file for " \
- "writing to <%s>"
-
-#define ERR_KEYSTORE_NOPUBCERTS "unable to find any public key certificates " \
- "in keystore file <%s>"
-
-#define ERR_KEYSTORE_NOPRIVKEYS "unable to find any private keys in keystore "\
- "file <%s>"
-
-#define ERR_KEYSTORE_NOCACERTS "unable to find any trusted certificates in "\
- "file <%s>"
-
-#define ERR_KEYSTORE_NOTRUST "unable to find any trusted certificates in "\
- "keystore"
-
-#define ERR_KEYSTORE_NOMATCH "unable to find certificate and key pair " \
- "with alias <%s> in keystore"
-
-#define ERR_KEYSTORE_DUPLICATECERT "Certificate with alias <%s> " \
- "already exists in keystore"
-#define ERR_KEYSTORE_DUPLICATEKEY "Private key with alias <%s> already" \
- " exists in keystore"
-#define ERR_KEYSTORE_NO_ALIAS "Keystore certificate <%s> has no recorded " \
- "alias, must be deleted from keystore"
-#define ERR_KEYSTORE_NOCERT "No certificate with alias <%s> found in " \
- "keystore <%s>"
-#define ERR_KEYSTORE_NOCERTKEY "No certificates or private keys with alias " \
- "<%s> found in keystore <%s>"
-
-#define ERR_KEYSTORE_INTERNAL "Internal Error file %s line %d"
-
-#define ERR_CURR_TIME "Cannot determine current time from system"
-#define ERR_CERT_TIME "Certificate <%s> has expired or is not yet valid.\n" \
- "Current time: <%s>\n Certificate valid: <%s> - <%s>"
-#define ERR_MISMATCHED_KEYS "Private key does not match public key in " \
- "certificate <%s>"
-#define ERR_CERT_TIME_BAD "Certificate has corrupt validity dates, " \
- "cannot process"
-#define ERR_TRUSTSTORE "unable to find or use trusted certificate " \
- "store <%s> from application <%s>:<%s>"
-
-#define ERR_STORE_PW "unable to read password from <%s>"
-
-#define ERR_SEC "unable to sign package contents using <%s> " \
- "private key"
-
-#define ERR_NOGEN "unable to generate digital signature"
-
-#define ERR_STORE_PW "unable to read password from <%s>"
-#define ERR_CORRUPTSIG "Invalid or corrupt signature in datastream <%s>"
-#define ERR_CORRUPTSIG_TYPE "Wrong PKCS7 signature type in datastream <%s>"
-#define ERR_CORRUPTSIG_DT "Signature found but not detached in " \
- "datastream <%s>"
-#define ERR_KEYSTORE "invalid or corrupt PKCS12 file <%s>."
-#define ERR_KEYSTORE_NOCERTS "Store <%s> contains no certificates"
-#define ERR_KEYSTORE_NOKEYS "Store <%s> contains no private keys"
-#define ERR_SIG_INT "Internal error during signature verification."
-#define MSG_VERIFY "## Verifying signature for signer <%s>"
-#define MSG_VERIFY_OK "## Signature for signer <%s> verified."
-#define ERR_VERIFY "Signature verification failed."
-#define ERR_VERIFY_SIG "Signature verification failed while verifying " \
- "certificate <subject=%s, issuer=%s>:<%s>."
-#define ERR_VERIFY_ISSUER "Could not find issuer certificate for signer <%s>"
-#define ERR_OPENSIG "Signature found in datastream but cannot be " \
- " opened: <%s>"
-
-#define ERR_SIGFOUND "signature found in datastream <%s>, you must " \
- "specify a keystore with -k"
-#define ERR_DSINIT "could not process datastream from <%s>"
-
-#define MSG_KEYSTORE_AL "Keystore Alias"
-#define MSG_KEYSTORE_SN "Serial Number"
-#define MSG_KEYSTORE_FP "Fingerprint"
-#define MSG_KEYSTORE_CN "Common Name"
-#define MSG_KEYSTORE_IN "Issuer Common Name"
-#define MSG_KEYSTORE_VD "Validity Dates"
-#define MSG_KEYSTORE_TY "Certificate Type"
-#define MSG_KEYSTORE_TRUSTED "Trusted Certificate"
-#define MSG_KEYSTORE_UNTRUSTED "Signing Certificate"
-#define MSG_KEYSTORE_UNKNOWN "Unknown"
-
/* parameter errors */
#define ERR_LEN "length of parameter <%s> value exceeds limit"
#define ERR_ASCII "parameter <%s> must be ascii"
@@ -337,92 +221,7 @@ extern "C" {
#define ERR_SETUID "setuid(%d) failed."
#define ERR_EX_FAIL "exec of %s failed, errno=%d"
-/* pkgweb errors */
-#define MSG_DWNLD "\n## Downloading..."
-#define ERR_DWNLD_FAILED "\n## After %d retries, unable to complete transfer"
-#define MSG_DWNLD_TIMEOUT "\n## Timed out, retrying..."
-#define MSG_DWNLD_CONNREF "\n## Connection to <%s> refused, retrying..."
-#define MSG_DWNLD_HOSTDWN "\n## <%s> not responding, retrying..."
-#define MSG_DWNLD_PART "\n## Found partially downloaded file <%s> of " \
- "size <%ld> bytes. To force a complete " \
- "re-download, delete this file and try again"
-#define MSG_DWNLD_PREV "\n## Using previously spooled package datastream <%s>"
-#define MSG_DWNLD_CONT "\n## Continuing previously attempted download..."
-#define MSG_DWNLD_COMPLETE "## Download Complete\n"
-
-#define ERR_DWNLD_NO_CONT "unable to open partially downloaded file <%s> " \
- "for appending"
-#define ERR_BAD_PATH "unable to locate keystore."
-#define ERR_EMPTYPATH "No valid path exists for the keystore file."
-#define ERR_RETRIES "The number of server retries is not a valid " \
- "value. Please specify a value within the range of %d - %d."
-#define ERR_TIMEOUT "The network timeout value is not a valid " \
- "value. Please specify a value within the range of %d - %d."
-#define ERR_PARSE_URL "unable to parse the url <%s>."
-#define ERR_MEM "unable to allocate memory."
-#define ERR_HTTPS_PASSWD "unable set password for HTTPS connection."
-#define ERR_HTTPS_CA "unable to set CA file for HTTPS connection."
-#define ERR_HTTP "Failure occurred with http(s) negotiation: <%s>"
-#define ERR_WRITE "Cannot write to file <%s> : <%s>"
-#define ERR_READ "Cannot read from file <%s> : <%s>"
-#define ERR_SVR_RESP "unable to establish a connection with the http(s) server."
-#define ERR_INIT_CONN "unable to establish a connection with <%s>."
-#define ERR_INIT_SESS "unable to intialize download session for <%s>."
-#define ERR_INIT_CONN_PROXY "unable to establish a connection with <%s> " \
- "using <%s> as the proxy"
-#define ERR_CLOSE_CONN "unable to close the connection with <%s>."
-#define ERR_NO_HEAD_VAL "HTTP Response did not include header <%s>."
-/* CSTYLED */
-#define ERR_BAD_HEAD_VAL "HTTP Header value \"<%s>: <%s>\" unusable or " \
- "unparseable."
-#define ERR_BAD_CONTENT "The package <%s> attempting to be installed " \
- "is illegal."
-#define ERR_DWNLD "unable to download package datastream from <%s>."
-#define ERR_OPEN_TMP "unable to open temporary file for writing."
-#define ERR_WRITE_TMP "unable to write to temporary file."
-#define ERR_DISK_SPACE "Not enough disk space is available to download " \
- "package to\n%s. %llukb needed, %llukb available."
-#define ERR_CERTS "unable to find a valid certificate in <%s>."
-#define ERR_CERTCHAIN "unable to build certificate chain for subject <%s>:<%s>."
-#define ERR_ILL_ENV "The environment variable <%s=%s> is illegal"
-#define ERR_BAD_PROXY "Invalid proxy specification: <%s>"
-#define ERR_TMPDIR "unable to find temporary directory <%s>"
#define ERR_MEM "unable to allocate memory."
-#define ERR_NO_DWNLD_DIR "No download directory available."
-#define MSG_OCSP_VERIFY "## Contacting OCSP Responder <%s> for " \
- "certificate <%s> status"
-#define MSG_OCSP_VERIFY_PROXY "## Contacting OCSP Responder <%s> through " \
- "proxy <%s:%d> for certificate <%s> status"
-#define ERR_OCSP_PARSE "OCSP Responder URL <%s> invalid or unparseable"
-#define ERR_OCSP_RESP_PARSE "OCSP Response <%s> unparseable or empty"
-#define ERR_OCSP_RESP_NOTOK "OCSP Request failed. Expected status " \
- "<%d>, got <%d>, Reason=<%s>"
-#define WRN_OCSP_RESP_NONCE "WARNING: Invalid or no nonce found in " \
- "OCSP response."
-#define ERR_OCSP_RESP_TYPE "OCSP response message type invalid: <%s>, " \
- "expecting <%s>"
-#define ERR_OCSP_CONNECT "Cannot connect to OCSP Responder <%s> port <%d>"
-#define ERR_OCSP_SEND "Cannot send OCSP request to OCSP Responder <%s>"
-#define ERR_OCSP_READ "Cannot read OCSP response from OCSP Responder <%s>"
-#define ERR_OCSP_RESPONDER "OCSP Responder cannot process OCSP Request"
-#define ERR_OCSP_UNSUP "Unsupported OCSP Option <%s>"
-#define ERR_OCSP_VERIFY_NOTIME "Cannot access system time() to determine " \
- "OCSP Response validity"
-#define ERR_OCSP_VERIFY_SIG "OCSP Response, signed by <%s>, cannot be " \
- "verified: <%s>"
-#define ERR_OCSP_VERIFY_FAIL "unable to validate response from OCSP " \
- "Responder <%s>"
-#define ERR_OCSP_VERIFY_NO_STATUS "OCSP Responder did not supply validity " \
- "of certificate <%s> "
-#define ERR_OCSP_VERIFY_VALIDITY_NOTBEFORE "OCSP Response is only valid " \
- "after <%s>. Current time is <%s>."
-#define ERR_OCSP_VERIFY_VALIDITY "OCSP Response is only valid from <%s> " \
- "to <%s>. Current time is <%s>."
-#define ERR_OCSP_VERIFY_STATUS "OCSP Responder indicates certificate <%s> " \
- "status is <%s>"
-#define ERR_OCSP_VERIFY "OCSP Responder rejected certificate, or did not " \
- "recognize"
-#define ERR_OCSP_NO_URI "No OCSP Responder URL"
#define MSG_BASE_USED "Using <%s> as the package base directory."
diff --git a/usr/src/lib/libpkg/common/pkgserv.c b/usr/src/lib/libpkg/common/pkgserv.c
index 785f275dfc..7d1c3b8ad0 100644
--- a/usr/src/lib/libpkg/common/pkgserv.c
+++ b/usr/src/lib/libpkg/common/pkgserv.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -506,6 +510,7 @@ pkgcmd(PKGserver srv, void *cmd, size_t len, char **result, size_t *rlen,
}
/* Error return */
if (da.data_size == sizeof (int)) {
+ /* LINTED */
int x = *(int *)da.data_ptr;
if (x != 0) {
if (result == NULL || da.rbuf != *result)
diff --git a/usr/src/lib/libpkg/common/pkgtrans.c b/usr/src/lib/libpkg/common/pkgtrans.c
index a717360580..cfc4009b08 100644
--- a/usr/src/lib/libpkg/common/pkgtrans.c
+++ b/usr/src/lib/libpkg/common/pkgtrans.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,11 +50,6 @@
#include <dirent.h>
#include <signal.h>
#include <devmgmt.h>
-#include <openssl/pkcs12.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs7.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
#include <note.h>
#include "pkginfo.h"
#include "pkgstrct.h"
@@ -58,9 +57,7 @@
#include "pkgdev.h"
#include "pkglib.h"
#include "pkglibmsgs.h"
-#include "keystore.h"
#include "pkglocale.h"
-#include "pkgerr.h"
extern char *pkgdir; /* pkgparam.c */
@@ -113,12 +110,9 @@ static int cat_and_count(struct dm_buf *, char *);
static int ckoverwrite(char *dir, char *inst, int options);
static int pkgxfer(char *srcinst, int options);
-static int wdsheader(struct dm_buf *, char *src, char *device,
- char **pkg, PKCS7 *);
+static int wdsheader(struct dm_buf *, char *device, char **pkg);
static struct dm_buf *genheader(char *, char **);
-static int dump_hdr_and_pkgs(BIO *, struct dm_buf *, char **);
-
extern int ds_fd; /* open file descriptor for data stream WHERE? */
static char *root_names[] = {
@@ -170,8 +164,7 @@ pkghead(char *device)
}
/* check for datastream */
- if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY,
- NULL, NULL)) {
+ if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY)) {
cleanup();
return (n);
}
@@ -239,90 +232,12 @@ rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
/* will return 0, 1, 3, or 99 */
static int
-_pkgtrans(char *device1, char *device2, char **pkg, int options,
- keystore_handle_t keystore, char *keystore_alias)
+_pkgtrans(char *device1, char *device2, char **pkg, int options)
{
- BIO *p7_bio = NULL;
- EVP_PKEY *privkey = NULL;
- PKCS7 *sec_pkcs7 = NULL;
- PKCS7_SIGNER_INFO *sec_signerinfo = NULL;
- PKG_ERR *err;
- STACK_OF(X509) *cacerts = NULL;
- STACK_OF(X509) *clcerts = NULL;
- STACK_OF(X509) *sec_chain = NULL;
- X509 *pubcert = NULL;
- boolean_t making_sig = B_FALSE;
char *src, *dst;
int errflg, i, n;
struct dm_buf *hdr;
- making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;
-
- if (making_sig) {
-
- /* new error object */
- err = pkgerr_new();
-
- /* find matching cert and key */
- if (find_key_cert_pair(err, keystore,
- keystore_alias, &privkey, &pubcert) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* get CA certificates */
- if (find_ca_certs(err, keystore, &cacerts) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* get CL (aka "chain") certificates */
- if (find_cl_certs(err, keystore, &clcerts) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* initialize PKCS7 object to be filled in later */
- sec_pkcs7 = PKCS7_new();
- (void) PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
- sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
- pubcert, privkey, EVP_sha1());
-
- if (sec_signerinfo == NULL) {
- progerr(gettext(ERR_SEC), keystore_alias);
- ERR_print_errors_fp(stderr);
- pkgerr_free(err);
- return (1);
- }
-
- /* add signer cert into signature */
- (void) PKCS7_add_certificate(sec_pkcs7, pubcert);
-
- /* attempt to resolve cert chain starting at the signer cert */
- if (get_cert_chain(err, pubcert, clcerts, cacerts,
- &sec_chain) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /*
- * add the verification chain of certs into the signature.
- * The first cert is the user cert, which we don't need,
- * since it's baked in already, so skip it
- */
- for (i = 1; i < sk_X509_num(sec_chain); i++) {
- (void) PKCS7_add_certificate(sec_pkcs7,
- sk_X509_value(sec_chain, i));
- }
-
- pkgerr_free(err);
- err = NULL;
- }
-
if (signal_received > 0) {
return (1);
}
@@ -417,17 +332,6 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
logerr(pkg_gt(MSG_TWODSTREAM));
return (1);
}
- } else {
- /*
- * output device isn't a stream. If we're making a signed
- * package, then fail, since we can't make signed,
- * non-stream pkgs
- */
- if (making_sig) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(ERR_CANTSIGN));
- return (1);
- }
}
if ((srcdev.dirname && dstdev.dirname) &&
@@ -531,59 +435,13 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
cleanup();
return (1);
}
- if (making_sig) {
- /* start up signature data stream */
- (void) PKCS7_content_new(sec_pkcs7, NID_pkcs7_data);
- (void) PKCS7_set_detached(sec_pkcs7, 1);
- p7_bio = PKCS7_dataInit(sec_pkcs7, NULL);
-
- /*
- * Here we generate all the data that will go into
- * the package, and send it through the signature
- * generator, essentially calculating the signature
- * of the entire package so we can place it in the
- * header. Otherwise we'd have to place it at the end
- * of the pkg, which would break the ABI
- */
- if (!(options & PT_SILENT)) {
- (void) fprintf(stderr, pkg_gt(MSG_SIGNING),
- get_subject_display_name(pubcert));
- }
- if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) {
- progerr(gettext(ERR_NOGEN));
- logerr(pkg_gt(MSG_GETVOL));
- cleanup();
- return (1);
-
- }
-
- BIO_flush(p7_bio);
- /*
- * now generate PKCS7 signature
- */
- if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) {
- progerr(gettext(ERR_NOGEN));
- logerr(pkg_gt(MSG_GETVOL));
- cleanup();
- return (1);
- }
-
- (void) BIO_free(p7_bio);
- }
-
- /* write out header to stream, which includes signature */
- if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) {
+ /* write out header to stream */
+ if (wdsheader(hdr, ods_name, pkg)) {
cleanup();
return (1);
}
- if (sec_pkcs7 != NULL) {
- /* nuke in-memory signature for safety */
- PKCS7_free(sec_pkcs7);
- sec_pkcs7 = NULL;
- }
-
ds_volno = 1; /* number of volumes in datastream */
pinput = hdrbuf.text_buffer;
/* skip past first line in header */
@@ -630,8 +488,7 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
}
int
-pkgtrans(char *device1, char *device2, char **pkg, int options,
- keystore_handle_t keystore, char *keystore_alias)
+pkgtrans(char *device1, char *device2, char **pkg, int options)
{
int r;
struct sigaction nact;
@@ -683,7 +540,7 @@ pkgtrans(char *device1, char *device2, char **pkg, int options,
* perform the package translation
*/
- r = _pkgtrans(device1, device2, pkg, options, keystore, keystore_alias);
+ r = _pkgtrans(device1, device2, pkg, options);
/*
* reset signal handlers
@@ -922,20 +779,12 @@ genheader(char *src, char **pkg)
}
static int
-wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
+wdsheader(struct dm_buf *hdr, char *device, char **pkg)
{
- FILE *fp;
- char path[PATH_MAX], tmp_entry[ENTRY_MAX],
- tmp_file[L_tmpnam+1];
- char srcpath[PATH_MAX];
+ char tmp_entry[ENTRY_MAX], tmp_file[L_tmpnam+1];
int i, n;
int list_fd;
int block_cnt;
- int len;
- char cwd[MAXPATHLEN + 1];
- boolean_t making_sig = B_FALSE;
-
- making_sig = (sig != NULL) ? B_TRUE : B_FALSE;
(void) ds_close(0);
if (dstdev.pathname)
@@ -982,161 +831,32 @@ wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
* Create a cpio-compatible list of the requisite files in
* the temporary file.
*/
- if (!making_sig) {
- for (i = 0; pkg[i]; i++) {
- register ssize_t entry_size;
-
- /*
- * Copy pkginfo and pkgmap filenames into the
- * temporary string allowing for the first line
- * as a special case.
- */
- entry_size = sprintf(tmp_entry,
- (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
- pkg[i], PKGINFO, pkg[i], PKGMAP);
-
- if (write(list_fd, tmp_entry,
- entry_size) != entry_size) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
- (void) close(list_fd);
- ecleanup();
- return (1);
- }
- }
-
- } else {
+ for (i = 0; pkg[i]; i++) {
register ssize_t entry_size;
/*
- * if we're making a signature, we must make a
- * temporary area full of symlinks to the requisite
- * files, plus an extra entry for the signature, so
- * that cpio will put all files and signature in the
- * same archive in a single invocation of cpio.
+ * Copy pkginfo and pkgmap filenames into the
+ * temporary string allowing for the first line
+ * as a special case.
*/
- tmpsymdir = xstrdup(tmpnam(NULL));
+ entry_size = sprintf(tmp_entry,
+ (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
+ pkg[i], PKGINFO, pkg[i], PKGMAP);
- if (mkdir(tmpsymdir, S_IRWXU)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_MKDIR), tmpsymdir);
- return (1);
- }
-
- /* generate the signature */
- if (((len = snprintf(path, PATH_MAX, "%s/%s",
- tmpsymdir, SIGNATURE_FILENAME)) >= PATH_MAX) ||
- len < 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmpsymdir);
- cleanup();
- return (1);
- }
-
- if ((fp = fopen(path, "w")) == NULL) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), path);
- cleanup();
- return (1);
- }
- (void) PEM_write_PKCS7(fp, sig);
- (void) fclose(fp);
-
- for (i = 0; pkg[i]; i++) {
- (void) snprintf(path, sizeof (path),
- "%s/%s", tmpsymdir, pkg[i]);
- if (mkdir(path, 0755)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_MKDIR), path);
- cleanup();
- return (1);
- }
- (void) snprintf(path, sizeof (path),
- "%s/%s/%s", tmpsymdir, pkg[i], PKGINFO);
- (void) snprintf(srcpath, sizeof (srcpath),
- "%s/%s/%s", src, pkg[i], PKGINFO);
- if (symlink(srcpath, path) != 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
- cleanup();
- return (1);
- }
-
- (void) snprintf(path, sizeof (path),
- "%s/%s/%s", tmpsymdir, pkg[i], PKGMAP);
- (void) snprintf(srcpath, sizeof (srcpath),
- "%s/%s/%s", src, pkg[i], PKGMAP);
- if (symlink(srcpath, path) != 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
- cleanup();
- return (1);
- }
-
- /*
- * Copy pkginfo and pkgmap filenames into the
- * temporary string allowing for the first line
- * as a special case.
- */
- entry_size = snprintf(tmp_entry, sizeof (tmp_entry),
- (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
- pkg[i], PKGINFO, pkg[i], PKGMAP);
-
- if (write(list_fd, tmp_entry,
- entry_size) != entry_size) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
- (void) close(list_fd);
- ecleanup();
- cleanup();
- return (1);
- }
- }
-
- /* add signature to list of files */
- entry_size = snprintf(tmp_entry, sizeof (tmp_entry), "\n%s",
- SIGNATURE_FILENAME);
- if (write(list_fd, tmp_entry, entry_size) != entry_size) {
+ if (write(list_fd, tmp_entry,
+ entry_size) != entry_size) {
progerr(pkg_gt(ERR_TRANSFER));
logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
(void) close(list_fd);
ecleanup();
- cleanup();
return (1);
}
}
(void) lseek(list_fd, 0, SEEK_SET);
- if (!making_sig) {
- (void) snprintf(tmp_entry, sizeof (tmp_entry),
- "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
- } else {
- /*
- * when making a signature, we must make sure to follow
- * symlinks during the cpio so that we don't archive
- * the links themselves
- */
- (void) snprintf(tmp_entry, sizeof (tmp_entry),
- "%s -ocDL -C %d", CPIOPROC, (int)BLK_SIZE);
- }
-
- if (making_sig) {
- /* save cwd and change to symlink dir for cpio invocation */
- if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
- logerr(pkg_gt(ERR_GETWD));
- progerr(pkg_gt(ERR_TRANSFER));
- cleanup();
- return (1);
- }
-
- if (chdir(tmpsymdir)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), tmpsymdir);
- cleanup();
- return (1);
- }
- }
+ (void) snprintf(tmp_entry, sizeof (tmp_entry),
+ "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
if (n = esystem(tmp_entry, list_fd, ds_fd)) {
rpterr();
@@ -1151,15 +871,6 @@ wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
(void) close(list_fd);
(void) unlink(tmp_file);
- if (making_sig) {
- /* change to back to src dir for subsequent operations */
- if (chdir(cwd)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), cwd);
- cleanup();
- return (1);
- }
- }
return (0);
}
@@ -1679,135 +1390,6 @@ pkgxfer(char *srcinst, int options)
return (0);
}
-/*
- * Name: pkgdump
- * Description: Dump a cpio archive of a package's contents to a BIO.
- *
- * Arguments: srcinst - Name of package, which resides on the
- * device pointed to by the static 'srcdev' variable,
- * to dump.
- * bio - BIO object to dump data to
- *
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-static int
-pkgdump(char *srcinst, BIO *bio)
-{
- FILE *fp;
- char *src;
- char temp[MAXPATHLEN],
- srcdir[MAXPATHLEN],
- cmd[CMDSIZE];
- int i, n, part, nparts, maxpartsize, iscomp;
-
- /*
- * when this routine is entered, the entire package
- * is already available at 'src' - including the
- * pkginfo/pkgmap files and the objects as well.
- */
-
- /* read the pkgmap to get it's size information */
- if ((fp = fopen(PKGMAP, "r")) == NULL) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
- return (1);
- }
-
- nparts = 1;
- if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
- return (1);
- else
- (void) fclose(fp);
-
- /* make sure the first volume is available */
- if (srcdev.mount) {
- src = srcdev.dirname;
- (void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, srcinst);
- if (ckvolseq(srcdir, 1, nparts)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SEQUENCE));
- return (1);
- }
- }
-
- /*
- * form cpio command that will output the contents of all of
- * this package's parts
- */
- for (part = 1; part <= nparts; /* void */) {
-
- if (part == 1) {
- (void) snprintf(cmd, CMDSIZE, "find %s %s",
- PKGINFO, PKGMAP);
- if (nparts && (isdir(INSTALL) == 0)) {
- (void) strlcat(cmd, " ", sizeof (cmd));
- (void) strlcat(cmd, INSTALL, sizeof (cmd));
- }
- } else
- (void) snprintf(cmd, CMDSIZE, "find %s", PKGINFO);
-
- if (nparts > 1) {
- (void) snprintf(temp, MAXPATHLEN, "%s.%d", RELOC, part);
- if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- (void) snprintf(temp, MAXPATHLEN, "%s.%d", ROOT, part);
- if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- (void) snprintf(temp, MAXPATHLEN, "%s.%d",
- ARCHIVE, part);
- if (isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- } else if (nparts) {
- for (i = 0; reloc_names[i] != NULL; i++) {
- if (iscpio(reloc_names[i], &iscomp) ||
- isdir(reloc_names[i]) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, reloc_names[i],
- CMDSIZE);
- }
- }
- for (i = 0; root_names[i] != NULL; i++) {
- if (iscpio(root_names[i], &iscomp) ||
- isdir(root_names[i]) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, root_names[i],
- CMDSIZE);
- }
- }
- if (isdir(ARCHIVE) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, ARCHIVE, CMDSIZE);
- }
- }
-
- (void) snprintf(cmd + strlen(cmd),
- sizeof (cmd) - strlen(cmd),
- " -print | %s -ocD -C %d",
- CPIOPROC, (int)BLK_SIZE);
- /*
- * execute the command, dumping all standard output
- * to the BIO.
- */
- n = BIO_dump_cmd(cmd, bio);
- if (n != 0) {
- rpterr();
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
- return (1);
- }
-
- part++;
- }
- return (0);
-}
-
static void
sigtrap(int signo)
{
@@ -1845,129 +1427,3 @@ cleanup(void)
(void) pkgumount(&dstdev);
(void) ds_close(1);
}
-
-/*
- * Name: dump_hdr_and_pkgs
- * Description: Dumps datastream header and each package's contents
- * to the supplied BIO
- *
- * Arguments: bio - BIO object to dump data to
- * hdr - Header for the datastream being dumped
- * pkglist - NULL-terminated list of packages
- * to dump. The location of the packages are stored
- * in the static 'srcdev' variable.
- *
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-static int
-dump_hdr_and_pkgs(BIO *bio, struct dm_buf *hdr, char **pkglist)
-{
- int block_cnt, i;
- char srcdir[MAXPATHLEN];
- char cwd[MAXPATHLEN + 1];
- char *src;
-
- /* write out the header to the signature stream */
- for (block_cnt = 0; block_cnt < hdr->allocation;
- block_cnt += BLK_SIZE) {
- (void) BIO_write(bio, (hdr->text_buffer + block_cnt), BLK_SIZE);
- }
-
- /* save current directory */
- if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
- logerr(pkg_gt(ERR_GETWD));
- progerr(pkg_gt(ERR_TRANSFER));
- return (1);
- }
-
- /* now write out each package's contents */
- for (i = 0; pkglist[i]; i++) {
- /*
- * change to the source dir, so we can find and dump
- * the package(s) bits into the BIO
- *
- */
- src = srcdev.dirname;
-
- /* change to the package source directory */
- (void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, pkglist[i]);
- if (chdir(srcdir)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), srcdir);
- return (1);
- }
-
- if (pkgdump(pkglist[i], bio)) {
- pkglist[i] = NULL;
- return (1);
- }
- }
-
- /* change back to directory we were in upon entering this routine */
- if (chdir(cwd)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), cwd);
- return (1);
- }
-
- return (0);
-}
-
-/*
- * Name: BIO_dump_cmd
- * Description: Dump the output of invoking a command
- * to a BIO.
- *
- * Arguments: cmd - Command to invoke
- * bio - BIO to dump output of command to
- * only 'stdout' is dumped.
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-int
-BIO_dump_cmd(char *cmd, BIO *bio)
-{
- char buf[BLK_SIZE];
- FILE *fp;
- int rc;
-
- /* start up the process */
- if ((fp = epopen(cmd, "r")) == NULL) {
- rpterr();
- return (1);
- }
-
- /* read output in chunks, transfer to BIO */
- while (fread(buf, BLK_SIZE, 1, fp) == 1) {
- if (BIO_write(bio, buf, BLK_SIZE) != BLK_SIZE) {
- (void) sighold(SIGINT);
- (void) sighold(SIGHUP);
- (void) epclose(fp);
- (void) sigrelse(SIGINT);
- (void) sigrelse(SIGHUP);
- rpterr();
- return (1);
- }
- }
-
- /* done with stream, make sure no errors were encountered */
- if (ferror(fp)) {
- (void) epclose(fp);
- rpterr();
- return (1);
- }
-
- /* done, close stream, report any errors */
- (void) sighold(SIGINT);
- (void) sighold(SIGHUP);
- rc = epclose(fp);
- (void) sigrelse(SIGINT);
- (void) sigrelse(SIGHUP);
- if (rc != 0) {
- rpterr();
- return (1);
- }
-
- return (rc);
-}
diff --git a/usr/src/lib/libpkg/common/pkgweb.c b/usr/src/lib/libpkg/common/pkgweb.c
deleted file mode 100644
index bcda3e53f2..0000000000
--- a/usr/src/lib/libpkg/common/pkgweb.c
+++ /dev/null
@@ -1,3240 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
-
-
-#include <stdio.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <pkglocs.h>
-#include <locale.h>
-#include <libintl.h>
-#include <libgen.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <boot_http.h>
-#include <errno.h>
-#include <ctype.h>
-#include <openssl/pkcs7.h>
-#include <openssl/ocsp.h>
-#include <openssl/pkcs12.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-#include <openssl/x509v3.h>
-#include "pkglib.h"
-#include "pkglibmsgs.h"
-#include "pkglocale.h"
-#include "keystore.h"
-#include "pkgweb.h"
-#include "pkgerr.h"
-#include "p12lib.h"
-
-/* fixed format when making an OCSP request */
-#define OCSP_REQUEST_FORMAT \
- "POST %s HTTP/1.0\r\n" \
- "Content-Type: application/ocsp-request\r\n" \
- "Content-Length: %d\r\n\r\n"
-
-/*
- * no security is afforded by using this phrase to "encrypt" CA certificates,
- * but it might aid in debugging and has to be non-null
- */
-#define WEB_CA_PHRASE "schizophrenic"
-
-/* This one needs the ': ' at the end */
-#define CONTENT_TYPE_HDR "Content-Type"
-#define CONTENT_DISPOSITION_HDR "Content-Disposition"
-#define CONTENT_OCSP_RESP "application/ocsp-response"
-#define CONTENT_LENGTH_HDR "Content-Length"
-#define LAST_MODIFIED_HDR "Last-Modified"
-#define OCSP_BUFSIZ 1024
-
-/*
- * default amount of time that is allowed for error when checking
- * OCSP response validity.
- * For example, if this is set to 5 minutes, then if a response
- * is issued that is valid from 12:00 to 1:00, then we will
- * accept it if the local time is between 11:55 and 1:05.
- * This takes care of not-quite-synchronized server and client clocks.
- */
-#define OCSP_VALIDITY_PERIOD (5 * 60)
-
-/* this value is defined by getpassphrase(3c) manpage */
-#define MAX_PHRASELEN 257
-
-/* Max length of "enter password again" prompt message */
-#define MAX_VERIFY_MSGLEN 1024
-
-/* local prototypes */
-static boolean_t remove_dwnld_file(char *);
-static boolean_t get_ENV_proxyport(PKG_ERR *, ushort_t *);
-static boolean_t make_link(char *, char *);
-static WebStatus web_send_request(PKG_ERR *, int, int, int);
-static boolean_t web_eval_headers(PKG_ERR *);
-static WebStatus web_get_file(PKG_ERR *, char *, int, char **);
-static boolean_t ck_dwnld_dir_space(PKG_ERR *, char *, ulong_t);
-static WebStatus web_connect(PKG_ERR *);
-static boolean_t web_setup(PKG_ERR *);
-static boolean_t check_dwnld_dir(PKG_ERR *, char *);
-static boolean_t parse_url_proxy(PKG_ERR *, char *, char *, ushort_t);
-static boolean_t web_disconnect(void);
-static char *get_unique_filename(char *, char *);
-static boolean_t get_ENV_proxy(PKG_ERR *, char **);
-static char *condense_lastmodified(char *);
-static int web_verify(int, X509_STORE_CTX *);
-static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
-static boolean_t get_ocsp_uri(X509 *, char **);
-static OCSPStatus ocsp_verify(PKG_ERR *, X509 *, X509 *, char *, url_hport_t *,
- STACK_OF(X509) *);
-static char *get_time_string(ASN1_GENERALIZEDTIME *);
-static char *write_ca_file(PKG_ERR *, char *, STACK_OF(X509) *, char *);
-static boolean_t _get_random_info(void *, int);
-static boolean_t init_session(void);
-static void progress_setup(int, ulong_t);
-static void progress_report(int, ulong_t);
-static void progress_finish(int);
-static char *replace_token(char *, char, char);
-static void dequote(char *);
-static void trim(char *);
-
-
-/*
- * structure used to hold data passed back to the
- * X509 verify callback routine in validate_signature()
- */
-typedef struct {
- url_hport_t *proxy;
- PKG_ERR *err;
- STACK_OF(X509) *cas;
-} verify_cb_data_t;
-
-/* Progress bar variables */
-static ulong_t const_increment, const_divider, completed, const_completed;
-
-/* current network backoff wait period */
-static int cur_backoff = 0;
-
-/* download session context handle */
-static WEB_SESSION *ps;
-
-static int webpkg_install = 0;
-static char *prompt = NULL;
-static char *passarg = NULL;
-
-
-/* ~~~~~~~~~~~~~~ Public Functions ~~~~~~~~~~~~~~~~~~~ */
-
-/*
- * Name: set_prompt
- * Description: Specifies the prompt to use with the pkglib
- * passphrase callback routine.
- *
- * Arguments: newprompt - The prompt to display
- *
- * Returns : NONE
- */
-void
-set_passphrase_prompt(char *newprompt)
-{
- prompt = newprompt;
-}
-
-/*
- * Name: set_passarg
- * Description: Specifies the passphrase retrieval method
- * to use with the pkglib
- * passphrase callback routine.
- *
- * Arguments: newpassarg - The new password retrieval arg
- *
- * Returns : NONE
- */
-void
-set_passphrase_passarg(char *newpassarg)
-{
- passarg = newpassarg;
-}
-
-/*
- * Name: get_proxy_port
- * Description: Resolves proxy specification
- *
- * Arguments: err - where to record any errors.
- * proxy - Location to store result - if *proxy is not
- * null, then it will be validated, but not changed
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * on success, *proxy and *port are set to either
- * the user-supplied proxy and port, or the
- * ones found in the environment variables
- * HTTPPROXY and/or HTTPROXYPORT
- */
-boolean_t
-get_proxy_port(PKG_ERR *err, char **proxy, ushort_t *port)
-{
- if (*proxy != NULL) {
- if (!path_valid(*proxy)) {
- /* bad proxy supplied */
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_BAD_PROXY), *proxy);
- return (B_FALSE);
- }
- if (!get_ENV_proxyport(err, port)) {
- /* env set, but bad */
- return (B_FALSE);
- }
- } else {
- if (!get_ENV_proxy(err, proxy)) {
- /* environment variable set, but bad */
- return (B_FALSE);
- }
- if ((*proxy != NULL) && !path_valid(*proxy)) {
- /* env variable set, but bad */
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_BAD_PROXY), *proxy);
- return (B_FALSE);
- }
- if (!get_ENV_proxyport(err, port)) {
- /* env variable set, but bad */
- return (B_FALSE);
- }
- }
- return (B_TRUE);
-}
-
-/*
- * Name: path_valid
- * Description: Checks a string for being a valid path
- *
- * Arguments: path - path to validate
- *
- * Returns : B_TRUE - success, B_FALSE otherwise.
- * B_FALSE means path was null, too long (>PATH_MAX),
- * or too short (<1)
- */
-boolean_t
-path_valid(char *path)
-{
- if (path == NULL) {
- return (B_FALSE);
- } else if (strlen(path) > PATH_MAX) {
- return (B_FALSE);
- } else if (strlen(path) >= 1) {
- return (B_TRUE);
- } else {
- /* path < 1 */
- return (B_FALSE);
- }
-}
-
-/*
- * Name: web_cleanup
- * Description: Deletes temp files, closes, frees memory taken
- * by 'ps' static structure
- *
- * Arguments: none
- *
- * Returns : none
- */
-void
-web_cleanup(void)
-{
- PKG_ERR *err;
-
- if (ps == NULL)
- return;
-
- err = pkgerr_new();
-
- if (ps->keystore) {
- (void) close_keystore(err, ps->keystore, NULL);
- }
-
- ps->keystore = NULL;
-
- pkgerr_free(err);
-
- if (ps->uniqfile) {
- (void) remove_dwnld_file(ps->uniqfile);
- free(ps->uniqfile);
- ps->uniqfile = NULL;
- }
- if (ps->link) {
- (void) remove_dwnld_file(ps->link);
- free(ps->link);
- ps->link = NULL;
- }
- if (ps->dwnld_dir) {
- (void) rmdir(ps->dwnld_dir);
- ps->dwnld_dir = NULL;
- }
- if (ps->errstr) {
- free(ps->errstr);
- ps->errstr = NULL;
- }
-
- if (ps->content) {
- free(ps->content);
- ps->content = NULL;
- }
-
- if (ps->resp) {
- http_free_respinfo(ps->resp);
- ps->resp = NULL;
- }
-
- if (ps) {
- free(ps);
- ps = NULL;
- }
-}
-
-/*
- * Name: web_session_control
- * Description: Downloads an arbitrary URL and saves to disk.
- *
- * Arguments: err - where to record any errors.
- * url - URL pointing to content to download - can be
- * http:// or https://
- * dwnld_dir - Directory to download into
- * keystore - keystore to use for accessing trusted
- * certs when downloading using SSL
- * proxy - HTTP proxy to use, or NULL for no proxy
- * proxy_port - HTTP proxy port to use, ignored
- * if proxy is NULL
- * passarg - method to retrieve password
- * retries - # of times to retry download before
- * giving up
- * timeout - how long to wait before retrying,
- * when download is interrupted
- * nointeract - if non-zero, do not output
- * download progress to screen
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- */
-boolean_t
-web_session_control(PKG_ERR *err, char *url, char *dwnld_dir,
- keystore_handle_t keystore, char *proxy, ushort_t proxy_port,
- int retries, int timeout, int nointeract, char **fname)
-{
- int i;
- boolean_t ret = B_TRUE;
- boolean_t retrieved = B_FALSE;
-
- if (!init_session()) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!parse_url_proxy(err, url, proxy, proxy_port)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- ps->timeout = timeout;
-
- if (keystore != NULL)
- ps->keystore = keystore;
-
- if (dwnld_dir != NULL)
- ps->dwnld_dir = xstrdup(dwnld_dir);
- else {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_NO_DWNLD_DIR));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!check_dwnld_dir(err, dwnld_dir)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- for (i = 0; i < retries && !retrieved; i++) {
- if (!web_setup(err)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- switch (web_connect(err)) {
- /* time out and wait a little bit for these failures */
- case WEB_OK:
- /* were able to connect */
- reset_backoff();
- break;
- case WEB_TIMEOUT:
- echo_out(nointeract, gettext(MSG_DWNLD_TIMEOUT));
- (void) web_disconnect();
- backoff();
- continue;
-
- case WEB_CONNREFUSED:
- echo_out(nointeract, gettext(MSG_DWNLD_CONNREF),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
- case WEB_HOSTDOWN:
- echo_out(nointeract, gettext(MSG_DWNLD_HOSTDWN),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
-
- default:
- /* every other failure is a hard failure, so bail */
- ret = B_FALSE;
- goto cleanup;
- }
-
- switch (web_send_request(err, HTTP_REQ_TYPE_HEAD,
- ps->data.cur_pos, ps->data.content_length)) {
- case WEB_OK:
- /* were able to connect */
- reset_backoff();
- break;
- case WEB_TIMEOUT:
- echo_out(nointeract, gettext(MSG_DWNLD_TIMEOUT));
- (void) web_disconnect();
- backoff();
- continue;
-
- case WEB_CONNREFUSED:
- echo_out(nointeract, gettext(MSG_DWNLD_CONNREF),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
- case WEB_HOSTDOWN:
- echo_out(nointeract, gettext(MSG_DWNLD_HOSTDWN),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
- default:
- /* every other case is failure, so bail */
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!web_eval_headers(err)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- switch (web_get_file(err, dwnld_dir, nointeract, fname)) {
- case WEB_OK:
- /* were able to retrieve file */
- retrieved = B_TRUE;
- reset_backoff();
- break;
-
- case WEB_TIMEOUT:
- echo_out(nointeract, gettext(MSG_DWNLD_TIMEOUT));
- (void) web_disconnect();
- backoff();
- continue;
-
- case WEB_CONNREFUSED:
- echo_out(nointeract, gettext(MSG_DWNLD_CONNREF),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
- case WEB_HOSTDOWN:
- echo_out(nointeract, gettext(MSG_DWNLD_HOSTDWN),
- ps->url.hport.hostname);
- (void) web_disconnect();
- backoff();
- continue;
- default:
- /* every other failure is a hard failure, so bail */
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- if (!retrieved) {
- /* max retries attempted */
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_DWNLD_FAILED), retries);
- ret = B_FALSE;
- }
-cleanup:
- (void) web_disconnect();
- if (!ret) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_DWNLD), url);
- }
- return (ret);
-}
-
-/*
- * Name: get_signature
- * Description: retrieves signature from signed package.
- *
- * Arguments: err - where to record any errors.
- * ids_name - name of package stream, for error reporting
- * devp - Device on which package resides that we
- * result - where to store resulting PKCS7 signature
- *
- * Returns : B_TRUE - package is signed and signature returned OR
- * package is not signed, in which case result is NULL
- *
- * B_FALSE - there were problems accessing signature,
- * and it is unknown whether it is signed or not. Errors
- * recorded in 'err'.
- */
-boolean_t
-get_signature(PKG_ERR *err, char *ids_name, struct pkgdev *devp, PKCS7 **result)
-{
- char path[PATH_MAX];
- int len, fd = -1;
- struct stat buf;
- FILE *fp = NULL;
- boolean_t ret = B_TRUE;
- BIO *sig_in = NULL;
- PKCS7 *p7 = NULL;
-
- /*
- * look for signature. If one was in the stream,
- * it is now extracted
- */
- if (((len = snprintf(path, PATH_MAX, "%s/%s", devp->dirname,
- SIGNATURE_FILENAME)) >= PATH_MAX) || (len < 0)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), ids_name);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if ((fd = open(path, O_RDONLY|O_NONBLOCK)) == -1) {
- /*
- * only if the signature is non-existant
- * do we "pass"
- */
- if (errno != ENOENT) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_OPENSIG),
- strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
- } else {
- /* found sig file. parse it. */
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_OPENSIG), strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_OPENSIG),
- (gettext(ERR_NOT_REG)));
- ret = B_FALSE;
- goto cleanup;
- }
-
- if ((fp = fdopen(fd, "r")) == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_OPENSIG), strerror(errno));
- ret = B_FALSE;
- goto cleanup;
- }
-
- /*
- * read in signature. If it's invalid, we
- * punt, unless we're ignoring it
- */
- if ((sig_in = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_OPENSIG), strerror(errno));
- goto cleanup;
- }
-
- if ((p7 = PEM_read_bio_PKCS7(sig_in,
- NULL, NULL, NULL)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_CORRUPTSIG),
- ids_name);
- ret = B_FALSE;
- goto cleanup;
- }
- *result = p7;
- p7 = NULL;
- }
-
-cleanup:
- if (sig_in)
- (void) BIO_free(sig_in);
- if (fp)
- (void) fclose(fp);
- if (fd != -1)
- (void) close(fd);
- if (p7)
- (void) PKCS7_free(p7);
-
- return (ret);
-}
-
-/*
- * Name: echo_out
- * Description: Conditionally output a message to stdout
- *
- * Arguments: nointeract - if non-zero, do not output anything
- * fmt - print format
- * ... - print arguments
- *
- * Returns : none
- */
-/*PRINTFLIKE2*/
-void
-echo_out(int nointeract, char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-
- if (nointeract)
- return;
-
- (void) vfprintf(stdout, fmt, ap);
-
- va_end(ap);
-
- (void) putc('\n', stdout);
-}
-
-/*
- * Name: strip_port
- * Description: Returns "port" portion of a "hostname:port" string
- *
- * Arguments: proxy - full "hostname:port" string pointer
- *
- * Returns : the "port" portion of a "hostname:port" string,
- * converted to a decimal integer, or (int)0
- * if string contains no :port suffix.
- */
-ushort_t
-strip_port(char *proxy)
-{
- char *tmp_port;
-
- if ((tmp_port = strpbrk(proxy, ":")) != NULL)
- return (atoi(tmp_port));
- else
- return (0);
-}
-
-/*
- * Name: set_web_install
- * Description: Sets flag indicating we are doing a web-based install
- *
- * Arguments: none
- *
- * Returns : none
- */
-void
-set_web_install(void)
-{
- webpkg_install++;
-}
-
-/*
- * Name: is_web_install
- * Description: Determines whether we are doing a web-based install
- *
- * Arguments: none
- *
- * Returns : non-zero if we are doing a web-based install, 0 otherwise
- */
-int
-is_web_install(void)
-{
- return (webpkg_install);
-}
-
-/* ~~~~~~~~~~~~~~ Private Functions ~~~~~~~~~~~~~~~~~~~ */
-
-/*
- * Name: web_disconnect
- * Description: Disconnects connection to web server
- *
- * Arguments: none
- *
- * Returns : B_TRUE - successful disconnect, B_FALSE otherwise
- * Temp certificiate files are deleted,
- * if one was used to initiate the connection
- * (such as when using SSL)
- */
-static boolean_t
-web_disconnect(void)
-{
- if (ps->certfile) {
- (void) unlink(ps->certfile);
- }
- if (http_srv_disconnect(ps->hps) == 0)
- if (http_srv_close(ps->hps) == 0)
- return (B_TRUE);
-
- return (B_FALSE);
-}
-
-/*
- * Name: check_dwnld_dir
- * Description: Creates temp download directory
- *
- * Arguments: err - where to record any errors.
- * dwnld_dir - name of directory to create
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * on success, directory is created with
- * safe permissions
- */
-static boolean_t
-check_dwnld_dir(PKG_ERR *err, char *dwnld_dir)
-{
- DIR *dirp;
-
- /*
- * Check the directory passed in. If it doesn't exist, create it
- * with strict permissions
- */
- if ((dirp = opendir(dwnld_dir)) == NULL) {
- if (mkdir(dwnld_dir, 0744) == -1) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTEMP),
- dwnld_dir);
- return (B_FALSE);
- }
- }
- if (dirp) {
- (void) closedir(dirp);
- }
- return (B_TRUE);
-}
-
-/*
- * Name: ds_validate_signature
- * Description: Validates signature found in a package datastream
- *
- * Arguments: err - where to record any errors.
- * pkgdev - Package context handle of package to verify
- * pkgs - Null-terminated List of package name to verify
- * ids_name - Pathname to stream to validate
- * p7 - PKCS7 signature decoded from stream header
- * cas - List of trusted CA certificates
- * proxy - Proxy to use when doing online validation (OCSP)
- * nointeract - if non-zero, do not output to screen
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * success means signature was completely validated,
- * and contents of stream checked against signature.
- */
-boolean_t
-ds_validate_signature(PKG_ERR *err, struct pkgdev *pkgdev, char **pkgs,
- char *ids_name, PKCS7 *p7, STACK_OF(X509) *cas,
- url_hport_t *proxy, int nointeract)
-{
- BIO *p7_bio;
- boolean_t ret = B_TRUE;
-
- /* make sure it's a Signed PKCS7 message */
- if (!PKCS7_type_is_signed(p7)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_CORRUPTSIG_TYPE),
- ids_name);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* initialize PKCS7 object to be filled in */
- if (!PKCS7_get_detached(p7)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_CORRUPTSIG_DT),
- ids_name);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* dump header and packages into BIO to calculate the message digest */
- if ((p7_bio = PKCS7_dataInit(p7, NULL)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_CORRUPTSIG),
- ids_name);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if ((BIO_ds_dump_header(err, p7_bio) != 0) ||
- (BIO_ds_dump(err, ids_name, p7_bio) != 0)) {
- ret = B_FALSE;
- goto cleanup;
- }
- (void) BIO_flush(p7_bio);
-
- /* validate the stream and its signature */
- if (!validate_signature(err, ids_name, p7_bio, p7, cas,
- proxy, nointeract)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* reset device stream (really bad performance for tapes) */
- (void) ds_close(1);
- (void) ds_init(ids_name, pkgs, pkgdev->norewind);
-
-cleanup:
- return (ret);
-}
-
-
-/*
- * Name: validate_signature
- * Description: Validates signature of an arbitrary stream of bits
- *
- * Arguments: err - where to record any errors.
- * name - Descriptive name of object being validated,
- * for good error reporting messages
- * indata - BIO object to read stream bits from
- * p7 - PKCS7 signature of stream
- * cas - List of trusted CA certificates
- * proxy - Proxy to use when doing online validation (OCSP)
- * nointeract - if non-zero, do not output to screen
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * success means signature was completely validated,
- * and contents of stream checked against signature.
- */
-boolean_t
-validate_signature(PKG_ERR *err, char *name, BIO *indata, PKCS7 *p7,
- STACK_OF(X509) *cas, url_hport_t *proxy, int nointeract)
-{
- STACK_OF(PKCS7_SIGNER_INFO) *sec_sinfos = NULL;
-
- PKCS7_SIGNER_INFO *signer = NULL;
- X509_STORE *sec_truststore = NULL;
- X509_STORE_CTX *ctx = NULL;
- X509 *signer_cert = NULL, *issuer = NULL;
- STACK_OF(X509) *chaincerts = NULL;
- int i, k;
- unsigned long errcode;
- const char *err_data = NULL;
- const char *err_reason = NULL;
- char *err_string;
- int err_flags;
- verify_cb_data_t verify_data;
- char *signer_sname;
- char *signer_iname;
- PKCS7_ISSUER_AND_SERIAL *ias;
- boolean_t ret = B_TRUE;
-
- /* only support signed PKCS7 signatures */
- if (!PKCS7_type_is_signed(p7)) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* initialize temporary internal trust store used for verification */
- sec_truststore = X509_STORE_new();
-
- for (i = 0; i < sk_X509_num(cas); i++) {
- if (X509_STORE_add_cert(sec_truststore,
- sk_X509_value(cas, i)) == 0) {
- pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MEM));
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
- /* get signers from the signature */
- if ((sec_sinfos = PKCS7_get_signer_info(p7)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_CORRUPTSIG), name);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* verify each signer found in the PKCS7 signature */
- for (k = 0; k < sk_PKCS7_SIGNER_INFO_num(sec_sinfos); k++) {
- signer = sk_PKCS7_SIGNER_INFO_value(sec_sinfos, k);
- signer_cert = PKCS7_cert_from_signer_info(p7, signer);
- signer_sname = get_subject_display_name(signer_cert);
- signer_iname = get_issuer_display_name(signer_cert);
-
- echo_out(nointeract, gettext(MSG_VERIFY), signer_sname);
-
- /* find the issuer of the current cert */
- chaincerts = p7->d.sign->cert;
- ias = signer->issuer_and_serial;
- issuer = X509_find_by_issuer_and_serial(chaincerts,
- ias->issuer, ias->serial);
-
- /* were we not able to find the issuer cert */
- if (issuer == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_VERIFY_ISSUER),
- signer_iname, signer_sname);
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* Lets verify */
- if ((ctx = X509_STORE_CTX_new()) == NULL) {
- pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MEM));
- ret = B_FALSE;
- goto cleanup;
- }
- (void) X509_STORE_CTX_init(ctx, sec_truststore,
- issuer, chaincerts);
- (void) X509_STORE_CTX_set_purpose(ctx,
- X509_PURPOSE_ANY);
-
- /* callback will perform OCSP on certificates with OCSP data */
- X509_STORE_CTX_set_verify_cb(ctx, web_verify);
-
- /* pass needed data into callback through the app_data handle */
- verify_data.proxy = proxy;
- verify_data.cas = cas;
- verify_data.err = err;
- (void) X509_STORE_CTX_set_app_data(ctx, &verify_data);
-
- /* first verify the certificate chain */
- i = X509_verify_cert(ctx);
- if (i <= 0 && ctx->error != X509_V_ERR_CERT_HAS_EXPIRED) {
- signer_sname =
- get_subject_display_name(ctx->current_cert);
- signer_iname =
- get_issuer_display_name(ctx->current_cert);
- /* if the verify context holds an error, print it */
- if (ctx->error != X509_V_OK) {
- pkgerr_add(err, PKGERR_VERIFY,
- gettext(ERR_VERIFY_SIG), signer_sname,
- signer_iname,
- (char *)X509_verify_cert_error_string(ctx->error));
- } else {
- /* some other error. print them all. */
- while ((errcode = ERR_get_error_line_data(NULL,
- NULL, &err_data, &err_flags)) != 0) {
- size_t errsz;
- err_reason =
- ERR_reason_error_string(errcode);
- if (err_reason == NULL) {
- err_reason =
- gettext(ERR_SIG_INT);
- }
-
- if (!(err_flags & ERR_TXT_STRING)) {
- err_data =
- gettext(ERR_SIG_INT);
- }
- errsz = strlen(err_reason) +
- strlen(err_data) + 3;
- err_string = xmalloc(errsz);
- (void) snprintf(err_string, errsz,
- "%s: %s", err_reason, err_data);
- pkgerr_add(err, PKGERR_VERIFY,
- gettext(ERR_VERIFY_SIG),
- signer_sname, signer_iname,
- err_string);
- free(err_string);
- }
- }
- ret = B_FALSE;
- goto cleanup;
- }
-
- /* now verify the signature */
- i = PKCS7_signatureVerify(indata, p7, signer, issuer);
-
- if (i <= 0) {
- /* print out any OpenSSL-specific errors */
- signer_sname =
- get_subject_display_name(ctx->current_cert);
- signer_iname =
- get_subject_display_name(ctx->current_cert);
- while ((errcode = ERR_get_error_line_data(NULL,
- NULL, &err_data, &err_flags)) != 0) {
- err_reason =
- ERR_reason_error_string(errcode);
- if (err_reason == NULL) {
- err_reason =
- gettext(ERR_SIG_INT);
- }
-
- if (!(err_flags & ERR_TXT_STRING)) {
- err_data =
- gettext(ERR_SIG_INT);
- }
- pkgerr_add(err, PKGERR_VERIFY,
- gettext(ERR_VERIFY_SIG), signer_sname,
- signer_iname, err_reason);
- pkgerr_add(err, PKGERR_VERIFY,
- gettext(ERR_VERIFY_SIG), signer_sname,
- signer_iname, err_data);
- }
- ret = B_FALSE;
- goto cleanup;
- }
-
- echo_out(nointeract, gettext(MSG_VERIFY_OK), signer_sname);
- }
-
- /* signature(s) verified successfully */
-cleanup:
- if (ctx)
- X509_STORE_CTX_cleanup(ctx);
- return (ret);
-}
-
-/*
- * Name: web_verify
- * Description: Callback used by PKCS7_dataVerify when
- * verifying a certificate chain.
- *
- * Arguments: err - where to record any errors.
- * ctx - The context handle of the current verification operation
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * if it's '0' (not OK) we simply return it, since the
- * verification operation has already determined that the
- * cert is invalid. if 'ok' is non-zero, then we do our
- * checks, and return 0 or 1 based on if the cert is
- * invalid or valid.
- */
-static int
-web_verify(int ok, X509_STORE_CTX *ctx)
-{
- X509 *curr_cert;
- X509 *curr_issuer;
- char *uri;
- url_hport_t *proxy;
- PKG_ERR *err = NULL;
- STACK_OF(X509) *cas;
- if (!ok) {
- /* don't override a verify failure */
- return (ok);
- }
-
-
- /* get app data supplied through callback context */
- err = ((verify_cb_data_t *)X509_STORE_CTX_get_app_data(ctx))->err;
- proxy = ((verify_cb_data_t *)X509_STORE_CTX_get_app_data(ctx))->proxy;
- cas = ((verify_cb_data_t *)X509_STORE_CTX_get_app_data(ctx))->cas;
-
- /* Check revocation status */
- curr_cert = X509_STORE_CTX_get_current_cert(ctx);
-
- /* this shouldn't happen */
- if (curr_cert == NULL) {
- pkgerr_add(err, PKGERR_INTERNAL, gettext(ERR_PKG_INTERNAL),
- __FILE__, __LINE__);
- return (0);
- }
-
- /* don't perform OCSP unless cert has required OCSP extensions */
- if (get_ocsp_uri(curr_cert, &uri)) {
- if (get_issuer(&curr_issuer, ctx, curr_cert) <= 0) {
- /* no issuer! */
- pkgerr_add(err, PKGERR_INTERNAL,
- gettext(ERR_PKG_INTERNAL),
- __FILE__, __LINE__);
- return (0);
- }
-
- /*
- * ok we have the current cert
- * and its issuer. Do the OCSP check
- */
-
- /*
- * OCSP extensions are, by, RFC 2459, never critical
- * extensions, therefore, we only fail if we were able
- * to explicitly contact an OCSP responder, and that
- * responder did not indicate the cert was valid. We
- * also fail if user-supplied data could not be parsed
- * or we run out of memory. We succeeed for "soft"
- * failures, such as not being able to connect to the
- * OCSP responder, or trying to use if the OCSP URI
- * indicates SSL must be used (which we do not
- * support)
- */
- switch (ocsp_verify(err, curr_cert, curr_issuer,
- uri, proxy, cas)) {
- case OCSPMem: /* Ran out of memory */
- case OCSPInternal: /* Some internal error */
- case OCSPVerify: /* OCSP responder indicated fail */
- return (0);
- }
- /* all other cases are success, or soft failures */
- pkgerr_clear(err);
- }
-
- return (ok);
-}
-
-/*
- * Name: get_time_string
- * Description: Generates a human-readable string from an ASN1_GENERALIZED_TIME
- *
- * Arguments: intime - The time to convert
- *
- * Returns : A pointer to a static string representing the passed-in time.
- */
-static char
-*get_time_string(ASN1_GENERALIZEDTIME *intime)
-{
-
- static char time[ATTR_MAX];
- BIO *mem;
- char *p;
-
- if (intime == NULL) {
- return (NULL);
- }
- if ((mem = BIO_new(BIO_s_mem())) == NULL) {
- return (NULL);
- }
-
- if (ASN1_GENERALIZEDTIME_print(mem, intime) == 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- if (BIO_gets(mem, time, ATTR_MAX) <= 0) {
- (void) BIO_free(mem);
- return (NULL);
- }
-
- (void) BIO_free(mem);
-
- /* trim the end of the string */
- for (p = time + strlen(time) - 1; isspace(*p); p--) {
- *p = '\0';
- }
-
- return (time);
-}
-
-/*
- * Name: get_ocsp_uri
- * Description: Examines an X509 certificate and retrieves the embedded
- * OCSP Responder URI if one exists.
- *
- * Arguments: cert - The cert to inspect
- * uri - pointer where the newly-allocated URI is placed, if found
- *
- * Returns : Success if the URI was found. Appropriate status otherwise.
- */
-static boolean_t
-get_ocsp_uri(X509 *cert, char **uri)
-{
- AUTHORITY_INFO_ACCESS *aia;
- ACCESS_DESCRIPTION *ad;
- int i;
-
- if (getenv("PKGWEB_TEST_OCSP")) {
- *uri = xstrdup(getenv("PKGWEB_TEST_OCSP"));
- return (B_TRUE);
- }
-
- /* get the X509v3 extension holding the OCSP URI */
- if ((aia = X509_get_ext_d2i(cert, NID_info_access,
- NULL, NULL)) != NULL) {
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) {
- ad = sk_ACCESS_DESCRIPTION_value(aia, i);
- if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
- if (ad->location->type == GEN_URI) {
- *uri =
- xstrdup((char *)ASN1_STRING_data(ad->location->d.ia5));
- return (B_TRUE);
- }
- }
- }
- }
-
- /* no URI was found */
- return (B_FALSE);
-}
-
-/*
- * Name: ocsp_verify
- * Description: Attempts to contact an OCSP Responder and ascertain the validity
- * of an X509 certificate.
- *
- * Arguments: err - Error object to add error messages to
- * cert - The cert to validate
- * issuer - The certificate of the issuer of 'cert'
- * uri - The OCSP Responder URI
- * cas - The trusted CA certificates used to verify the
- * signed OCSP response
- * Returns : Success - The OCSP Responder reported a 'good'
- * status for the cert otherwise, appropriate
- * error is returned.
- */
-static OCSPStatus
-ocsp_verify(PKG_ERR *err, X509 *cert, X509 *issuer,
- char *uri, url_hport_t *proxy, STACK_OF(X509) *cas)
-{
- OCSP_CERTID *id;
- OCSP_REQUEST *req;
- OCSP_RESPONSE *resp;
- OCSP_BASICRESP *bs;
- BIO *cbio, *mem;
- char ocspbuf[OCSP_BUFSIZ];
- char *host = NULL, *portstr = NULL, *path = "/", *p, *q, *r;
- int port, status, reason;
- int len, retval, respcode, use_ssl = 0;
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
- char *subjname;
- time_t currtime;
- char currtimestr[ATTR_MAX];
- unsigned long errcode;
- const char *err_reason;
-
- subjname = get_subject_display_name(cert);
-
- /* parse the URI into its constituent parts */
- if (OCSP_parse_url(uri, &host, &portstr, &path, &use_ssl) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_PARSE), uri);
- return (OCSPParse);
- }
-
- /* we don't currently support SSL-based OCSP Responders */
- if (use_ssl) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_UNSUP), uri);
- return (OCSPUnsupported);
- }
-
- /* default port if none specified */
- if (portstr == NULL) {
- port = (int)URL_DFLT_SRVR_PORT;
- } else {
- port = (int)strtoul(portstr, &r, 10);
- if (*r != '\0') {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_PARSE), uri);
- return (OCSPParse);
- }
- }
-
- /* allocate new request structure */
- if ((req = OCSP_REQUEST_new()) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_MEM));
- return (OCSPMem);
- }
-
- /* convert cert and issuer fields into OCSP request data */
- if ((id = OCSP_cert_to_id(NULL, cert, issuer)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_PKG_INTERNAL),
- __FILE__, __LINE__);
- return (OCSPInternal);
- }
-
- /* fill out request structure with request data */
- if ((OCSP_request_add0_id(req, id)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_PKG_INTERNAL),
- __FILE__, __LINE__);
- return (OCSPInternal);
- }
-
- /* add nonce */
- (void) OCSP_request_add1_nonce(req, NULL, -1);
-
- /* connect to host, or proxy */
- if (proxy != NULL) {
- if ((cbio = BIO_new_connect(proxy->hostname)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_MEM));
- return (OCSPMem);
- }
-
- /*
- * BIO_set_conn_int_port takes an int *, so let's give it one
- * rather than an ushort_t *
- */
- port = proxy->port;
- (void) BIO_set_conn_int_port(cbio, &port);
- if (BIO_do_connect(cbio) <= 0) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_CONNECT),
- proxy->hostname, port);
- return (OCSPConnect);
- }
- } else {
- if ((cbio = BIO_new_connect(host)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_MEM));
- return (OCSPMem);
- }
-
- (void) BIO_set_conn_int_port(cbio, &port);
- if (BIO_do_connect(cbio) <= 0) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_CONNECT),
- host, port);
- return (OCSPConnect);
- }
- }
-
- /* calculate length of binary request data */
- len = i2d_OCSP_REQUEST(req, NULL);
-
- /* send the request headers */
- if (proxy != NULL) {
- retval = BIO_printf(cbio, OCSP_REQUEST_FORMAT, uri, len);
- } else {
- retval = BIO_printf(cbio, OCSP_REQUEST_FORMAT, path, len);
- }
-
- if (retval <= 0) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_SEND), host);
- return (OCSPRequest);
- }
-
- /* send the request binary data */
- if (i2d_OCSP_REQUEST_bio(cbio, req) <= 0) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_SEND), host);
- return (OCSPRequest);
- }
-
- /*
- * read the response into a memory BIO, so we can 'gets'
- * (socket bio's don't support BIO_gets)
- */
- if ((mem = BIO_new(BIO_s_mem())) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_MEM));
- return (OCSPMem);
- }
-
- while ((len = BIO_read(cbio, ocspbuf, OCSP_BUFSIZ))) {
- if (len < 0) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_READ), host);
- return (OCSPRequest);
- }
- if (BIO_write(mem, ocspbuf, len) != len) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_MEM));
- return (OCSPMem);
- }
- }
-
- /* now get the first line of the response */
- if (BIO_gets(mem, ocspbuf, OCSP_BUFSIZ) <= 0) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_RESP_PARSE));
- return (OCSPRequest);
- }
-
- /* parse the header response */
- /* it should look like "HTTP/x.x 200 OK" */
-
- /* skip past the protocol info */
- for (p = ocspbuf; (*p != '\0') && !isspace(*p); p++)
- continue;
-
- /* skip past whitespace betwen protocol and start of response code */
- while ((*p != '\0') && isspace(*p)) {
- p++;
- }
-
- if (*p == '\0') {
- /* premature end */
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_PARSE), ocspbuf);
- return (OCSPRequest);
- }
-
- /* find end of response code */
- for (q = p; (*q != NULL) && !isspace(*q); q++)
- continue;
-
- /* mark end of response code */
- *q++ = '\0';
-
- /* parse response code */
- respcode = strtoul(p, &r, 10);
- if (*r != '\0') {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_PARSE), ocspbuf);
- return (OCSPRequest);
- }
-
- /* now find beginning of the response string */
- while ((*q != NULL) && isspace(*q)) {
- q++;
- }
-
- /* trim whitespace from end of message */
- for (r = (q + strlen(q) - 1); isspace(*r); r--) {
- *r = '\0';
- }
-
- /* response must be OK */
- if (respcode != 200) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_NOTOK), 200,
- respcode, q);
- return (OCSPRequest);
- }
-
- /* read headers, looking for content-type or a blank line */
- while (BIO_gets(mem, ocspbuf, OCSP_BUFSIZ) > 0) {
-
- /* if we get a content type, make sure it's the right type */
- if (ci_strneq(ocspbuf, CONTENT_TYPE_HDR,
- strlen(CONTENT_TYPE_HDR))) {
-
- /* look for the delimiting : */
- p = strchr(ocspbuf + strlen(CONTENT_TYPE_HDR), ':');
-
- if (p == NULL) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_PARSE), ocspbuf);
- return (OCSPResponder);
- }
-
- /* skip over ':' */
- p++;
-
- /* find beginning of the content type */
- while ((*p != NULL) && isspace(*p)) {
- p++;
- }
-
- if (!ci_strneq(p, CONTENT_OCSP_RESP,
- strlen(CONTENT_OCSP_RESP))) {
- /* response is not right type */
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_TYPE),
- p, CONTENT_OCSP_RESP);
- return (OCSPResponder);
- }
-
- /* continue with next header line */
- continue;
- }
-
- /* scan looking for a character */
- for (p = ocspbuf; (*p != '\0') && isspace(*p); p++) {
- continue;
- }
- /*
- * if we got to the end of the line with
- * no chars, then this is a blank line
- */
- if (*p == '\0') {
- break;
- }
- }
-
-
- if (*p != '\0') {
- /* last line was not blank */
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_RESP_PARSE), ocspbuf);
- return (OCSPResponder);
- }
-
- /* now read in the binary response */
- if ((resp = d2i_OCSP_RESPONSE_bio(mem, NULL)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_READ), host);
- return (OCSPResponder);
- }
-
- /* free temp BIOs */
- (void) BIO_free(mem);
- (void) BIO_free_all(cbio);
- cbio = NULL;
-
- /* make sure request was successful */
- if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_RESP_NOTOK),
- OCSP_RESPONSE_STATUS_SUCCESSFUL,
- OCSP_response_status(resp),
- OCSP_response_status_str(OCSP_response_status(resp)));
- return (OCSPResponder);
- }
-
- /* parse binary response into internal structure */
- if ((bs = OCSP_response_get1_basic(resp)) == NULL) {
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_READ), host);
- return (OCSPParse);
- }
-
- /*
- * From here to the end of the code, the return values
- * should be hard failures
- */
-
- /* verify the response, warn if no nonce */
- if (OCSP_check_nonce(req, bs) <= 0) {
- logerr(pkg_gt(WRN_OCSP_RESP_NONCE));
- }
-
- if (OCSP_basic_verify(bs, cas, NULL, OCSP_TRUSTOTHER) <= 0) {
- while ((errcode = ERR_get_error()) != NULL) {
- err_reason = ERR_reason_error_string(errcode);
- if (err_reason == NULL) {
- err_reason =
- gettext(ERR_SIG_INT);
- }
- pkgerr_add(err, PKGERR_PARSE, (char *)err_reason);
- }
- pkgerr_add(err, PKGERR_PARSE, gettext(ERR_OCSP_VERIFY_FAIL),
- uri);
- return (OCSPVerify);
- }
-
- /* check the validity of our certificate */
- if (OCSP_resp_find_status(bs, id, &status, &reason,
- &rev, &thisupd, &nextupd) == NULL) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_VERIFY_NO_STATUS), subjname);
- return (OCSPVerify);
- }
-
- if ((currtime = time(NULL)) == (time_t)-1) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_VERIFY_NOTIME));
- return (OCSPVerify);
- }
-
- (void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX);
-
- /* trim end */
- for (r = currtimestr + strlen(currtimestr) - 1;
- isspace(*r); r--) {
- *r = '\0';
- }
-
- if (!OCSP_check_validity(thisupd, nextupd,
- OCSP_VALIDITY_PERIOD, -1)) {
- if (nextupd != NULL) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_VERIFY_VALIDITY),
- get_time_string(thisupd), get_time_string(nextupd),
- currtimestr);
- } else {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_VERIFY_VALIDITY),
- get_time_string(thisupd),
- currtimestr);
- }
- return (OCSPVerify);
- }
-
- if (status != V_OCSP_CERTSTATUS_GOOD) {
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_OCSP_VERIFY_STATUS), subjname,
- OCSP_cert_status_str(status));
- return (OCSPVerify);
- }
-
- /* everythign checks out */
- return (OCSPSuccess);
-}
-
-/*
- * Name: get_issuer
- * Description: Attempts to find the issuing certificate for a given certificate
- * This will look in both the list of trusted certificates found in
- * the X509_STORE_CTX structure, as well as the list of untrusted
- * chain certificates found in the X509_STORE_CTX structure.
- * Arguments:
- * issuer - The resulting issuer cert is placed here, if found
- * ctx - The current verification context
- * x - The certificate whose issuer we are looking for
- * Returns : Success - The issuer cert was found and placed in *issuer.
- * otherwise, appropriate error is returned.
- */
-static int
-get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
-{
- int i, ok;
-
- /*
- * first look in the list of trusted
- * certs, using the context's method to do so
- */
- if ((ok = ctx->get_issuer(issuer, ctx, x)) > 0) {
- return (ok);
- }
-
- if (ctx->untrusted != NULL) {
- /* didn't find it in trusted certs, look through untrusted */
- for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
- if (X509_check_issued(sk_X509_value(ctx->untrusted, i),
- x) == X509_V_OK) {
- *issuer = sk_X509_value(ctx->untrusted, i);
- return (1);
- }
- }
- }
- *issuer = NULL;
- return (0);
-}
-
-/*
- * Name: parse_url_proxy
- * Description: Parses URL and optional proxy specification, populates static
- * 'ps' structure
- *
- * Arguments: err - where to record any errors.
- * url - URL to parse
- * proxy - proxy to parse, or NULL for no proxy
- * proxy_port - Default proxy port to use if no proxy
- * port specified in 'proxy'
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * on success, 'ps->url' and 'ps->proxy' are populated
- * with parsed data.
- */
-static boolean_t
-parse_url_proxy(PKG_ERR *err, char *url, char *proxy, ushort_t proxy_port)
-{
- boolean_t ret = B_TRUE;
- if (!path_valid(url)) {
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (url_parse(url, &ps->url) != URL_PARSE_SUCCESS) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_PARSE_URL), url);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (proxy != NULL) {
- if (url_parse_hostport(proxy, &ps->proxy, proxy_port)
- != URL_PARSE_SUCCESS) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_BAD_PROXY), proxy);
- ret = B_FALSE;
- goto cleanup;
- }
- }
-
-cleanup:
- return (ret);
-}
-
-/*
- * Name: web_setup
- * Description: Initializes http library settings
- *
- * Arguments: err - where to record any errors.
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- */
-static boolean_t
-web_setup(PKG_ERR *err)
-{
- boolean_t ret = B_TRUE;
- static boolean_t keepalive = B_TRUE;
-
- if ((ps->hps = http_srv_init(&ps->url)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_INIT_SESS), ps->url);
- ret = B_FALSE;
- goto cleanup;
- }
-
- if (getenv("WEBPKG_DEBUG") != NULL) {
- http_set_verbose(B_TRUE);
- }
-
- if (ps->proxy.hostname[0] != '\0' &&
- http_set_proxy(ps->hps, &ps->proxy) != 0) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_INIT_SESS), ps->url);
- ret = B_FALSE;
- goto cleanup;
- }
- if (http_set_keepalive(ps->hps, keepalive) != 0) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_INIT_SESS), ps->url);
- ret = B_FALSE;
- goto cleanup;
- }
- if (http_set_socket_read_timeout(ps->hps, ps->timeout) != 0) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_INIT_SESS), ps->url);
- ret = B_FALSE;
- goto cleanup;
- }
- if (http_set_random_file(ps->hps, RANDOM) != 0) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_INIT_SESS), ps->url);
- ret = B_FALSE;
- goto cleanup;
- }
-
- (void) http_set_p12_format(B_TRUE);
-
-cleanup:
- return (ret);
-}
-
-/*
- * Name: web_connect
- * Description: Makes connection with URL stored in static 'ps' structure.
- *
- * Arguments: err - where to record any errors.
- *
- * Returns : WEB_OK - connection successful
- * WEB_VERIFY_SETUP - Unable to complete necessary
- * SSL setup
- * WEB_CONNREFUSED - Connection was refused to web site
- * WEB_HOSTDOWN - Host was not responding to request
- * WEB_NOCONNECT - Some other connection failure
- */
-static WebStatus
-web_connect(PKG_ERR *err)
-{
- STACK_OF(X509) *sec_cas = NULL;
- char *path;
- WebStatus ret = WEB_OK;
- ulong_t errcode;
- uint_t errsrc;
- int my_errno = 0;
- const char *libhttperr = NULL;
-
- if (ps->url.https == B_TRUE) {
- /* get CA certificates */
- if (find_ca_certs(err, ps->keystore, &sec_cas) != 0) {
- ret = WEB_VERIFY_SETUP;
- goto cleanup;
- }
-
- if (sk_X509_num(sec_cas) < 1) {
- /* no trusted websites */
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_KEYSTORE_NOTRUST));
- ret = WEB_VERIFY_SETUP;
- goto cleanup;
- }
-
- /*
- * write out all CA certs to temp file. libwanboot should
- * have an interface for giving it a list of trusted certs
- * through an in-memory structure, but currently that does
- * not exist
- */
- if ((path = write_ca_file(err, ps->dwnld_dir, sec_cas,
- WEB_CA_PHRASE)) == NULL) {
- ret = WEB_VERIFY_SETUP;
- goto cleanup;
- }
-
- ps->certfile = path;
- if (http_set_password(ps->hps, WEB_CA_PHRASE) != 0) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTPS_PASSWD));
- ret = WEB_VERIFY_SETUP;
- goto cleanup;
- }
-
- if (http_set_certificate_authority_file(path) != 0) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTPS_CA));
- ret = WEB_VERIFY_SETUP;
- goto cleanup;
- }
- }
-
- if (http_srv_connect(ps->hps) != 0) {
- while ((errcode = http_get_lasterr(ps->hps, &errsrc)) != 0) {
- /* Have an error - is it EINTR? */
- if (errsrc == ERRSRC_SYSTEM) {
- my_errno = errcode;
- break;
- } else if (libhttperr == NULL) {
- /* save the first non-system error message */
- libhttperr = http_errorstr(errsrc, errcode);
- }
- }
- switch (my_errno) {
- case EINTR:
- case ETIMEDOUT:
- /* Timed out. Try, try again */
- ret = WEB_TIMEOUT;
- break;
- case ECONNREFUSED:
- ret = WEB_CONNREFUSED;
- break;
- case EHOSTDOWN:
- ret = WEB_HOSTDOWN;
- break;
- default:
- /* some other fatal error */
- ret = WEB_NOCONNECT;
- if (libhttperr == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_INIT_CONN),
- ps->url.hport.hostname);
- } else {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTP), libhttperr);
- }
- break;
- }
- }
-cleanup:
- return (ret);
-}
-
-/*
- * Name: write_ca_file
- * Description: Writes out a PKCS12 file containing all trusted certs
- * found in keystore recorded in static 'ps' structure
- *
- * This routine is used because the libwanboot library's
- * HTTPS routines cannot accept trusted certificates
- * through an in-memory structure, when initiating an
- * SSL connection. They must be in a PKCS12, which is
- * admittedly a poor interface.
- *
- * Arguments: err - where to record any errors.
- * tmpdir - Directory to write certificate file in
- * cacerts - Certs to write out
- * passwd - password used to encrypt certs
- *
- * Returns : path to resulting file, if successfullly written,
- * otherwise NULL.
- */
-static char
-*write_ca_file(PKG_ERR *err, char *tmpdir, STACK_OF(X509) *cacerts,
- char *passwd)
-{
- int fd, len;
- FILE *fp;
- PKCS12 *p12 = NULL;
- char *ret = NULL;
- static char tmp_file[PATH_MAX] = "";
- struct stat buf;
-
- if (!path_valid(tmpdir)) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTEMP), tmpdir);
- goto cleanup;
- }
-
- /* mkstemp replaces XXXXXX with a unique string */
- if (((len = snprintf(tmp_file, PATH_MAX, "%s/%sXXXXXX", tmpdir,
- "cert")) < 0) ||
- (len >= PATH_MAX)) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTEMP), tmpdir);
- goto cleanup;
- }
-
- if ((fd = mkstemp(tmp_file)) == -1) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTMPFIL), tmp_file);
- goto cleanup;
- }
-
- if (fstat(fd, &buf) == -1) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTMPFIL), tmp_file);
- goto cleanup;
- }
-
- if (!S_ISREG(buf.st_mode)) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTMPFIL), tmp_file);
- goto cleanup;
- }
-
- if ((fp = fdopen(fd, "w")) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTMPFIL), tmp_file);
- goto cleanup;
- }
-
- if ((p12 = sunw_PKCS12_create(passwd, NULL, NULL, cacerts)) == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_KEYSTORE_FORM), tmp_file);
- goto cleanup;
- }
-
- if (i2d_PKCS12_fp(fp, p12) == 0) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_KEYSTORE_FORM), tmp_file);
- goto cleanup;
- }
-
- (void) fflush(fp);
- (void) fclose(fp);
- (void) close(fd);
- fp = NULL;
- fd = -1;
- ret = tmp_file;
-
-cleanup:
- if (p12 != NULL)
- PKCS12_free(p12);
- if (fp != NULL)
- (void) fclose(fp);
- if (fd != -1) {
- (void) close(fd);
- (void) unlink(tmp_file);
- }
-
- return (ret);
-}
-
-/*
- * Name: web_send_request
- * Description: Sends an HTTP request for a file to the
- * web server being communicated with in the static
- * 'ps' structure
- *
- * Arguments: err - where to record any errors.
- * request_type - HTTP_REQ_TYPE_HEAD to send an HTTP HEAD request,
- * or HTTP_REQ_TYPE_GET to send an HTTP GET request
- * cp -
- * Returns : WEB_OK - request sent successfully
- * WEB_CONNREFUSED - Connection was refused to web site
- * WEB_HOSTDOWN - Host was not responding to request
- * WEB_NOCONNECT - Some other connection failure
- */
-static WebStatus
-web_send_request(PKG_ERR *err, int request_type, int cp, int ep)
-{
- WebStatus ret = WEB_OK;
- ulong_t errcode;
- uint_t errsrc;
- int my_errno = 0;
- const char *libhttperr = NULL;
- switch (request_type) {
- case HTTP_REQ_TYPE_HEAD:
- if ((http_head_request(ps->hps, ps->url.abspath)) != 0) {
- while ((errcode = http_get_lasterr(ps->hps,
- &errsrc)) != 0) {
- /* Have an error - is it EINTR? */
- if (errsrc == ERRSRC_SYSTEM) {
- my_errno = errcode;
- break;
- } else if (libhttperr == NULL) {
- /* save first non-system error message */
- libhttperr =
- http_errorstr(errsrc, errcode);
- }
- }
- switch (my_errno) {
- case EINTR:
- case ETIMEDOUT:
- /* Timed out. Try, try again */
- ret = WEB_TIMEOUT;
- break;
- case ECONNREFUSED:
- ret = WEB_CONNREFUSED;
- break;
- case EHOSTDOWN:
- ret = WEB_HOSTDOWN;
- break;
- default:
- /* some other fatal error */
- ret = WEB_NOCONNECT;
- if (libhttperr == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_INIT_CONN),
- ps->url.hport.hostname);
- } else {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTP), libhttperr);
- }
- break;
- }
- goto cleanup;
- }
- break;
-
- case HTTP_REQ_TYPE_GET:
- if (cp && ep) {
- if (http_get_range_request(ps->hps, ps->url.abspath,
- cp, ep - cp) != 0) {
- while ((errcode = http_get_lasterr(ps->hps,
- &errsrc)) != 0) {
- /* Have an error - is it EINTR? */
- if (errsrc == ERRSRC_SYSTEM) {
- my_errno = errcode;
- break;
- } else {
- /*
- * save first non-system
- * error message
- */
- libhttperr =
- http_errorstr(errsrc,
- errcode);
- }
- }
- switch (my_errno) {
- case EINTR:
- case ETIMEDOUT:
- /* Timed out. Try, try again */
- ret = WEB_TIMEOUT;
- break;
- case ECONNREFUSED:
- ret = WEB_CONNREFUSED;
- break;
- case EHOSTDOWN:
- ret = WEB_HOSTDOWN;
- break;
- default:
- /* some other fatal error */
- ret = WEB_NOCONNECT;
- if (libhttperr == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_INIT_CONN),
- ps->url.hport.hostname);
- } else {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTP),
- libhttperr);
- }
- break;
- }
- goto cleanup;
- }
-
- if (!web_eval_headers(err)) {
- ret = WEB_NOCONNECT;
- goto cleanup;
- }
- } else {
- if ((http_get_request(ps->hps, ps->url.abspath))
- != 0) {
- while ((errcode = http_get_lasterr(ps->hps,
- &errsrc)) != 0) {
- /* Have an error - is it EINTR? */
- if (errsrc == ERRSRC_SYSTEM) {
- my_errno = errcode;
- break;
- } else {
- /*
- * save the first non-system
- * error message
- */
- libhttperr =
- http_errorstr(errsrc,
- errcode);
- }
- }
- switch (my_errno) {
- case EINTR:
- case ETIMEDOUT:
- /* Timed out. Try, try again */
- ret = WEB_TIMEOUT;
- break;
- case ECONNREFUSED:
- ret = WEB_CONNREFUSED;
- break;
- case EHOSTDOWN:
- ret = WEB_HOSTDOWN;
- break;
- default:
- /* some other fatal error */
- ret = WEB_NOCONNECT;
- if (libhttperr == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_INIT_CONN),
- ps->url.hport.hostname);
- } else {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTP),
- libhttperr);
- }
- break;
- }
- goto cleanup;
- }
-
- if (!web_eval_headers(err)) {
- ret = WEB_NOCONNECT;
- goto cleanup;
- }
- }
- break;
- default:
- pkgerr_add(err, PKGERR_INTERNAL, gettext(ERR_PKG_INTERNAL),
- __FILE__, __LINE__);
- }
-
-cleanup:
- return (ret);
-}
-
-/*
- * Name: web_eval_headers
- * Description: Evaluates HTTP headers returned during an HTTP request.
- * This must be called before calling
- * http_get_header_value().
- *
- * Arguments: err - where to record any errors.
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- */
-static boolean_t
-web_eval_headers(PKG_ERR *err)
-{
- const char *http_err;
- ulong_t herr;
- uint_t errsrc;
-
- if (http_process_headers(ps->hps, &ps->resp) != 0) {
- if ((ps->resp != NULL) && (ps->resp->statusmsg != NULL)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_HTTP),
- ps->resp->statusmsg);
- }
-
- herr = http_get_lasterr(ps->hps, &errsrc);
- http_err = http_errorstr(errsrc, herr);
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_HTTP),
- http_err);
- return (B_FALSE);
- }
- return (B_TRUE);
-}
-
-/*
- * Name: web_get_file
- * Description: Downloads the file URL from the website, all of
- * which are recorded in the static 'ps' struct
- *
- * Arguments: err - where to record any errors.
- * dwnld_dir - Directory to download file into
- * device - Where to store path to resulting
- * file
- * nointeract - if non-zero, do not output
- * progress
- * fname - name of downloaded file link in the dwnld_dir
- *
- * Returns : WEB_OK - download successful
- * WEB_CONNREFUSED - Connection was refused to web site
- * WEB_HOSTDOWN - Host was not responding to request
- * WEB_GET_FAIL - Unable to initialize download
- * state (temp file creation, header parsing, etc)
- * WEB_NOCONNECT - Some other connection failure
- */
-static WebStatus
-web_get_file(PKG_ERR *err, char *dwnld_dir, int nointeract, char **fname)
-{
- int i, fd;
- int n = 0;
- ulong_t abs_pos = 0;
- char *head_val = NULL;
- char *lastmod_val = NULL;
- char *bname = NULL;
- struct stat status;
- WebStatus ret = WEB_OK;
- WebStatus req_ret;
- ulong_t errcode;
- uint_t errsrc;
- int my_errno = 0;
- const char *libhttperr = NULL;
- char *disp;
- char tmp_file[PATH_MAX];
- int len;
-
- ps->data.prev_cont_length =
- ps->data.content_length =
- ps->data.cur_pos = 0;
-
- if ((head_val = http_get_header_value(ps->hps,
- CONTENT_LENGTH_HDR)) != NULL) {
- ps->data.content_length = atol(head_val);
- } else {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_NO_HEAD_VAL),
- CONTENT_LENGTH_HDR);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- free(head_val);
- head_val = NULL;
-
- if ((head_val = http_get_header_value(ps->hps,
- CONTENT_DISPOSITION_HDR)) != NULL) {
- /* "inline; parm=val; parm=val */
- if ((disp = strtok(head_val, "; \t\n\f\r")) != NULL) {
- /* disp = "inline" */
- while ((disp = strtok(NULL, "; \t\n\f\r")) != NULL) {
- /* disp = "parm=val" */
- if (ci_strneq(disp, "filename=", 9)) {
- bname = xstrdup(basename(disp + 9));
- trim(bname);
- dequote(bname);
- }
- }
- }
- free(head_val);
- head_val = NULL;
- }
-
- if (bname == NULL) {
- /*
- * couldn't determine filename from header value,
- * so take basename of URL
- */
- if ((bname = get_endof_string(ps->url.abspath, '/')) == NULL) {
- /* URL is bad */
- pkgerr_add(err, PKGERR_PARSE,
- gettext(ERR_PARSE_URL), ps->url.abspath);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
- }
-
- *fname = bname;
-
- if ((head_val = http_get_header_value(ps->hps, LAST_MODIFIED_HDR))
- != NULL) {
-
- if ((lastmod_val = condense_lastmodified(head_val)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_BAD_HEAD_VAL),
- LAST_MODIFIED_HDR, head_val);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
- free(head_val);
- head_val = NULL;
-
- if ((ps->uniqfile = get_unique_filename(dwnld_dir,
- lastmod_val)) == NULL) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_OPEN_TMP));
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- free(lastmod_val);
- lastmod_val = NULL;
-
- if ((fd = open(ps->uniqfile,
- O_NONBLOCK|O_RDWR|O_APPEND|O_CREAT|O_EXCL,
- 640)) == -1) {
-
- /*
- * A partial downloaded file
- * already exists, so open it.
- */
- if ((fd = open(ps->uniqfile,
- O_NONBLOCK|O_RDWR|O_APPEND)) != -1) {
- if (fstat(fd, &status) == -1 ||
- !S_ISREG(status.st_mode)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_DWNLD_NO_CONT),
- ps->uniqfile);
- ret = WEB_GET_FAIL;
- goto cleanup;
- } else {
- echo_out(nointeract,
- gettext(MSG_DWNLD_PART),
- ps->uniqfile,
- status.st_size);
- ps->data.prev_cont_length =
- status.st_size;
- }
- } else {
- /* unable to open partial file */
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_DWNLD_NO_CONT),
- ps->uniqfile);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
- }
- } else {
- /*
- * no "Last-Modified" header, so this file is not eligible for
- * spooling and "resuming last download" operations
- */
- ps->spool = B_FALSE;
-
- /* mkstemp replaces XXXXXX with a unique string */
- if (((len = snprintf(tmp_file, PATH_MAX,
- "%s/%sXXXXXX", dwnld_dir, "stream")) < 0) ||
- (len >= PATH_MAX)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(MSG_NOTEMP), dwnld_dir);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- if ((fd = mkstemp(tmp_file)) == -1) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(MSG_NOTMPFIL), tmp_file);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- if (fstat(fd, &status) == -1 ||
- !S_ISREG(status.st_mode)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_DWNLD_NO_CONT),
- ps->uniqfile);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- ps->data.prev_cont_length = 0;
- ps->uniqfile = xstrdup(tmp_file);
- }
-
- /* File has already been completely downloaded */
- if (ps->data.prev_cont_length == ps->data.content_length) {
- echo_out(nointeract, gettext(MSG_DWNLD_PREV), ps->uniqfile);
- ps->data.cur_pos = ps->data.prev_cont_length;
- if (!make_link(dwnld_dir, bname)) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTEMP),
- dwnld_dir);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
- /* we're done, so cleanup and return success */
- goto cleanup;
- } else if (ps->data.prev_cont_length != 0) {
- ps->data.cur_pos = ps->data.prev_cont_length;
- }
-
- if (!ck_dwnld_dir_space(err, dwnld_dir,
- (ps->data.prev_cont_length != 0) ?
- (ps->data.content_length - ps->data.cur_pos) :
- ps->data.content_length)) {
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
- if ((req_ret = web_send_request(err, HTTP_REQ_TYPE_GET,
- ps->data.cur_pos, ps->data.content_length)) != WEB_OK) {
- ret = req_ret;
- goto cleanup;
- }
-
- if (ps->data.prev_cont_length != 0)
- echo_out(nointeract, gettext(MSG_DWNLD_CONT));
- else
- echo_out(nointeract, gettext(MSG_DWNLD));
-
- progress_setup(nointeract, ps->data.content_length);
-
- /* Download the file a BLOCK at a time */
- while (ps->data.cur_pos < ps->data.content_length) {
- progress_report(nointeract, abs_pos);
- i = ((ps->data.content_length - ps->data.cur_pos) < BLOCK) ?
- (ps->data.content_length - ps->data.cur_pos)
- : BLOCK;
- if ((n = http_read_body(ps->hps, ps->content, i)) <= 0) {
- while ((errcode = http_get_lasterr(ps->hps,
- &errsrc)) != 0) {
- /* Have an error - is it EINTR? */
- if (errsrc == ERRSRC_SYSTEM) {
- my_errno = errcode;
- break;
- } else {
- /*
- * save first non-system
- * error message
- */
- libhttperr =
- http_errorstr(errsrc, errcode);
- }
- }
- switch (my_errno) {
- case EINTR:
- case ETIMEDOUT:
- /* Timed out. Try, try again */
- ret = WEB_TIMEOUT;
- break;
- case ECONNREFUSED:
- ret = WEB_CONNREFUSED;
- break;
- case EHOSTDOWN:
- ret = WEB_HOSTDOWN;
- break;
- default:
- /* some other fatal error */
- ret = WEB_NOCONNECT;
- if (libhttperr == NULL) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_INIT_CONN),
- ps->url.hport.hostname);
- } else {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_HTTP), libhttperr);
- }
- break;
- }
- goto cleanup;
- }
- if ((n = write(fd, ps->content, n)) == 0) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_WRITE),
- ps->uniqfile, strerror(errno));
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
- ps->data.cur_pos += n;
- abs_pos += n;
- }
-
- progress_finish(nointeract);
- echo_out(nointeract, gettext(MSG_DWNLD_COMPLETE));
-
- if (!make_link(dwnld_dir, bname)) {
- pkgerr_add(err, PKGERR_WEB, gettext(MSG_NOTEMP),
- dwnld_dir);
- ret = WEB_GET_FAIL;
- goto cleanup;
- }
-
-cleanup:
- sync();
- if (fd != -1) {
- (void) close(fd);
- }
-
- if (head_val != NULL)
- free(head_val);
-
- if (lastmod_val != NULL)
- free(lastmod_val);
-
- return (ret);
-}
-
-/*
- * Name: make_link
- * Description: Create new link to file being downloaded
- *
- * Arguments: dwnld_dir - directory in which downloaded file exists
- * bname - name of link
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- */
-static boolean_t
-make_link(char *dwnld_dir, char *bname)
-{
- int len;
-
- if ((ps->link = (char *)xmalloc(PATH_MAX)) == NULL)
- return (B_FALSE);
- if (((len = snprintf(ps->link, PATH_MAX, "%s/%s",
- dwnld_dir, bname)) < 0) ||
- len >= PATH_MAX)
- return (B_FALSE);
-
- (void) link(ps->uniqfile, ps->link);
-
- return (B_TRUE);
-}
-
-/*
- * Name: get_startof_string
- * Description: searches string for token, returns a newly-allocated
- * substring of the given string up to, but not
- * including, token. for example
- * get_startof_string("abcd", 'c') will return "ab"
- *
- * Arguments: path - path to split
- * token - character to split on
- *
- * Returns : substring of 'path', up to, but not including,
- * token, if token appears in path. Otherwise,
- * returns NULL.
- */
-char *
-get_startof_string(char *path, char token)
-{
- char *p, *p2;
-
- if (path == NULL)
- return (NULL);
-
- p = xstrdup(path);
-
- p2 = strchr(p, token);
- if (p2 == NULL) {
- free(p);
- return (NULL);
- } else {
- *p2 = '\0';
- return (p);
- }
-}
-
-/*
- * Name: get_endof_string
- * Description: searches string for token, returns a
- * newly-allocated substring of the given string,
- * starting at character following token, to end of
- * string.
- *
- * for example get_end_string("abcd", 'c')
- * will return "d"
- *
- * Arguments: path - path to split
- * token - character to split on
- *
- * Returns : substring of 'path', beginning at character
- * following token, to end of string, if
- * token appears in path. Otherwise,
- * returns NULL.
- */
-char *
-get_endof_string(char *path, char token)
-{
- char *p, *p2;
-
- if (path == NULL)
- return (NULL);
-
- p = xstrdup(path);
-
- if ((p2 = strrchr(p, token)) == NULL) {
- return (NULL);
- }
-
- return (p2 + 1);
-}
-
-/*
- * Name: progress_setup
- * Description: Initialize session for reporting progress
- *
- * Arguments: nointeract - if non-zero, do not do anything
- * ulong_t - size of job to report progress for
- *
- * Returns : none
- */
-static void
-progress_setup(int nointeract, ulong_t size_of_load)
-{
- ulong_t divisor;
- ulong_t term_width = TERM_WIDTH;
-
- if (nointeract)
- return;
-
- if (size_of_load > MED_DWNLD && size_of_load < LARGE_DWNLD)
- divisor = MED_DIVISOR;
- else if (size_of_load > LARGE_DWNLD) {
- term_width = TERM_WIDTH - 8;
- divisor = LARGE_DIVISOR;
- } else
- divisor = SMALL_DIVISOR;
-
- const_increment = size_of_load / term_width;
- const_divider = size_of_load / divisor;
- const_completed = 100 / divisor;
-}
-
-/*
- * Name: progress_report
- * Description: Report progress for current progress context,
- * to stderr
- *
- * Arguments: nointeract - if non-zero, do not do anything
- * position - how far along in the job to report.
- * This should be <= size used during progress_setup
- *
- * Returns : none
- */
-static void
-progress_report(int nointeract, ulong_t position)
-{
- static ulong_t increment;
- static ulong_t divider;
-
- if (nointeract)
- return;
-
- if (position == 0) {
- increment = const_increment;
- divider = const_divider;
- }
- if (position > increment && position < divider) {
- (void) putc('.', stderr);
- increment += const_increment;
- } else if (position > divider) {
- completed += const_completed;
- (void) fprintf(stderr, "%ld%c", completed, '%');
- increment += const_increment;
- divider += const_divider;
- }
-}
-
-/*
- * Name: progress_finish
- * Description: Finalize session for reporting progress.
- * "100%" is reported to screen
- *
- * Arguments: nointeract - if non-zero, do not do anything
- *
- * Returns : none
- */
-static void
-progress_finish(int nointeract)
-{
- if (nointeract)
- return;
-
- (void) fprintf(stderr, "%d%c\n", 100, '%');
-}
-
-/*
- * Name: init_session
- * Description: Initializes static 'ps' structure with default
- * values
- *
- * Arguments: none
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- */
-static boolean_t
-init_session(void)
-{
- if ((ps = (WEB_SESSION *)
- xmalloc(sizeof (WEB_SESSION))) == NULL) {
- return (B_FALSE);
- }
- (void) memset(ps, 0, sizeof (*ps));
-
- if ((ps->content = (char *)xmalloc(BLOCK)) == NULL) {
- return (B_FALSE);
- }
-
- (void) memset(ps->content, 0, BLOCK);
-
- ps->data.cur_pos = 0UL;
- ps->data.content_length = 0UL;
- ps->url.https = B_FALSE;
- ps->uniqfile = NULL;
- ps->link = NULL;
- ps->dwnld_dir = NULL;
- ps->spool = B_TRUE;
- ps->errstr = NULL;
- ps->keystore = NULL;
-
- return (B_TRUE);
-}
-
-/*
- * Name: ck_downld_dir_space
- * Description: Verify enough space exists in directory to hold file
- *
- * Arguments: err - where to record any errors.
- * dwnld_dir - Directory to check available space in
- * bytes_needed - How many bytes are need
- *
- * Returns : B_TRUE - enough space exists in dwnld_dir to hold
- * bytes_needed bytes, otherwise B_FALSE
- */
-static boolean_t
-ck_dwnld_dir_space(PKG_ERR *err, char *dwnld_dir, ulong_t bytes_needed)
-{
- u_longlong_t bytes_avail;
- u_longlong_t block_pad;
- struct statvfs64 status;
-
- if (statvfs64(dwnld_dir, &status)) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_TMPDIR), dwnld_dir);
- return (B_FALSE);
- }
-
- block_pad = (status.f_frsize ? status.f_frsize : status.f_bsize);
- bytes_avail = status.f_bavail * block_pad;
-
- if ((((u_longlong_t)bytes_needed) + block_pad) > bytes_avail) {
- pkgerr_add(err, PKGERR_WEB, gettext(ERR_DISK_SPACE),
- dwnld_dir,
- (((u_longlong_t)bytes_needed) + block_pad) / 1024ULL,
- bytes_avail / 1024ULL);
- return (B_FALSE);
- }
-
- return (B_TRUE);
-}
-
-/*
- * Description:
- * This function returns a unique file name based on the parts of the
- * URI. This is done to enable partially downloaded files to be resumed.
- * Arguments:
- * dir - The directory that should contain the filename.
- * last_modified - A string representing the date of last modification,
- * used as part of generating unique name
- * Returns:
- * A valid filename or NULL.
- */
-
-static char *
-get_unique_filename(char *dir, char *last_modified)
-{
- char *buf, *buf2, *beg_str;
- int len;
-
- if ((buf = (char *)xmalloc(PATH_MAX)) == NULL) {
- return (NULL);
- }
- if ((buf2 = (char *)xmalloc(PATH_MAX)) == NULL) {
- return (NULL);
- }
-
- /* prepare strings for being cat'ed onto */
- buf[0] = buf2[0] = '\0';
- /*
- * No validation of the path is done here. We just construct the path
- * and it must be validated later
- */
-
- if (dir) {
- if (((len = snprintf(buf2, PATH_MAX, "%s/", dir)) < 0) ||
- (len >= PATH_MAX))
- return (NULL);
- } else {
- return (NULL);
- }
-
- if (ps->url.abspath)
- if (strlcat(buf, ps->url.abspath, PATH_MAX) >= PATH_MAX)
- return (NULL);
- if (ps->url.hport.hostname)
- if (isdigit((int)ps->url.hport.hostname[0])) {
- if (strlcat(buf, ps->url.hport.hostname, PATH_MAX)
- >= PATH_MAX)
- return (NULL);
- } else {
- if ((beg_str =
- get_startof_string(ps->url.hport.hostname, '.'))
- != NULL)
- if (strlcat(buf, beg_str, PATH_MAX) >= PATH_MAX)
- return (NULL);
- }
- if (last_modified != NULL)
- if (strlcat(buf, last_modified, PATH_MAX) >= PATH_MAX)
- return (NULL);
-
- if ((buf = replace_token(buf, '/', '_')) != NULL) {
- if (strlcat(buf2, buf, PATH_MAX) >= PATH_MAX) {
- return (NULL);
- } else {
- if (buf) free(buf);
- return (buf2);
- }
- } else {
- if (buf) free(buf);
- if (buf2) free(buf2);
- return (NULL);
- }
-}
-
-/*
- * Description:
- * Removes token(s) consisting of one character from any path.
- * Arguments:
- * path - The path to search for the token in.
- * token - The token to search for
- * Returns:
- * The path with all tokens removed or NULL.
- */
-static char *
-replace_token(char *path, char oldtoken, char newtoken)
-{
- char *newpath, *p;
-
- if ((path == NULL) || (oldtoken == '\0') || (newtoken == '\0')) {
- return (NULL);
- }
-
- newpath = xstrdup(path);
-
- for (p = newpath; *p != '\0'; p++) {
- if (*p == oldtoken) {
- *p = newtoken;
- }
- }
-
- return (newpath);
-}
-
-/*
- * Name: trim
- * Description: Trims whitespace from a string
- * has been registered)
- * Scope: private
- * Arguments: string - string to trim. It is assumed
- * this string is writable up to it's entire
- * length.
- * Returns: none
- */
-static void
-trim(char *str)
-{
- int len, i;
- if (str == NULL) {
- return;
- }
-
- len = strlen(str);
- /* strip from front */
- while (isspace(*str)) {
- for (i = 0; i < len; i++) {
- str[i] = str[i+1];
- }
- }
-
- /* strip from back */
- len = strlen(str);
- while (isspace(str[len-1])) {
- len--;
- }
- str[len] = '\0';
-}
-
-/*
- * Description:
- * Resolves double quotes
- * Arguments:
- * str - The string to resolve
- * Returns:
- * None
- */
-static void
-dequote(char *str)
-{
- char *cp;
-
- if ((str == NULL) || (str[0] != '"')) {
- /* no quotes */
- return;
- }
-
- /* remove first quote */
- (void) memmove(str, str + 1, strlen(str) - 1);
-
- /*
- * scan string looking for ending quote.
- * escaped quotes like \" don't count
- */
- cp = str;
-
- while (*cp != '\0') {
- switch (*cp) {
- case '\\':
- /* found an escaped character */
- /* make sure end of string is not '\' */
- if (*++cp != '\0') {
- cp++;
- }
- break;
-
- case '"':
- *cp = '\0';
- break;
- default:
- cp++;
- }
- }
-}
-
-/*
- * Name: get_ENV_proxy
- * Description: Retrieves setting of proxy env variable
- *
- * Arguments: err - where to record any errors.
- * proxy - where to store proxy
- *
- * Returns : B_TRUE - http proxy was found and valid, stored in proxy
- * B_FALSE - error, errors recorded in err
- */
-static boolean_t
-get_ENV_proxy(PKG_ERR *err, char **proxy)
-{
- char *buf;
-
- if ((buf = getenv("HTTPPROXY")) != NULL) {
- if (!path_valid(buf)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_ILL_ENV), "HTTPPROXY", buf);
- return (B_FALSE);
- } else {
- *proxy = buf;
- return (B_TRUE);
- }
- } else {
- /* try the other env variable */
- if ((buf = getenv("http_proxy")) != NULL) {
- if (!path_valid(buf)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_ILL_ENV), "http_proxy", buf);
- return (B_FALSE);
- }
- if (!strneq(buf, "http://", 7)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_ILL_ENV), "http_proxy", buf);
- return (B_FALSE);
- }
-
- /* skip over the http:// part of the proxy "url" */
- *proxy = buf + 7;
- return (B_TRUE);
- }
- }
-
- /* either the env variable(s) were set and valid, or not set */
- return (B_TRUE);
-}
-
-/*
- * Name: get_ENV_proxyport
- * Description: Retrieves setting of PROXYPORT env variable
- *
- * Arguments: err - where to record any errors.
- * port - where to store resulting port
- *
- * Returns : B_TRUE - string found in PROXYPORT variable, converted
- * to decimal integer, if it exists
- * and is valid. Or, PROXYPORT not set, port set to 1.
- * B_FALSE - env variable set, but invalid
- * (not a number for example)
- */
-static boolean_t
-get_ENV_proxyport(PKG_ERR *err, ushort_t *port)
-{
- char *buf;
- ushort_t newport;
- buf = getenv("HTTPPROXYPORT");
- if (buf != NULL) {
- if (!path_valid(buf)) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_ILL_ENV), "HTTPPROXYPORT", buf);
- return (B_FALSE);
- }
- if ((newport = atoi(buf)) == 0) {
- pkgerr_add(err, PKGERR_WEB,
- gettext(ERR_ILL_ENV), "HTTPPROXYPORT", buf);
- return (B_FALSE);
- }
- *port = newport;
- return (B_TRUE);
- } else {
- *port = 1;
- return (B_TRUE);
- }
-}
-
-/*
- * Name: remove_dwnld_file
- * Description: Removes newly-downloaded file if completely downloaded.
- *
- * Arguments: path - path to file to remove
- *
- * Returns : B_TRUE - success, B_FALSE otherwise
- * if it's '0' (not OK) we simply return it, since the
- * verification operation has already determined that the
- * cert is invalid. if 'ok' is non-zero, then we do our
- * checks, and return 0 or 1 based on if the cert is
- * invalid or valid.
- */
-static boolean_t
-remove_dwnld_file(char *path)
-{
- if (path && path != NULL) {
- /*
- * Only remove the downloaded file if it has been completely
- * downloaded, or is not eligible for spooling
- */
- if ((!ps->spool) ||
- (ps->data.cur_pos >= ps->data.content_length)) {
- (void) unlink(path);
- }
- } else {
- return (B_FALSE);
- }
- return (B_TRUE);
-}
-
-/*
- * Name: condense_lastmodifided
- * Description: generates a substring of a last-modified string,
- * and removes colons.
- *
- * Arguments: last_modified - string of the form
- * "Wed, 23 Oct 2002 21:59:45 GMT"
- *
- * Returns :
- * new string, consisting of hours/minutes/seconds only,
- * sans any colons.
- */
-char *
-condense_lastmodified(char *last_modified)
-{
- char *p, *p2;
-
- /*
- * Last-Modified: Wed, 23 Oct 2002 21:59:45 GMT
- * Strip the hours, minutes and seconds, without the ':'s, from
- * the above string, void of the ':".
- */
-
- if (last_modified == NULL)
- return (NULL);
-
- if ((p = xstrdup(last_modified)) == NULL)
- return (NULL);
- p2 = (strstr(p, ":") - 2);
- p2[8] = '\0';
- return (replace_token(p2, ':', '_'));
-}
-
-/*
- * Name: backoff
- * Description: sleeps for a certain # of seconds after a network
- * failure.
- * Scope: public
- * Arguments: none
- * Returns: none
- */
-void
-backoff()
-{
- static boolean_t initted = B_FALSE;
- int backoff;
- long seed;
-
- if (!initted) {
- /* seed the rng */
- (void) _get_random_info(&seed, sizeof (seed));
- srand48(seed);
- initted = B_TRUE;
- }
-
- backoff = (int)(drand48() * (double)cur_backoff);
- (void) sleep(backoff);
- if (cur_backoff < MAX_BACKOFF) {
- /*
- * increase maximum time we might wait
- * next time so as to fall off over
- * time.
- */
- cur_backoff *= BACKOFF_FACTOR;
- }
-}
-
-/*
- * Name: reset_backoff
- * Description: notifies the backoff service that whatever was
- * being backoff succeeded.
- * Scope: public
- * Arguments: none
- * Returns: none
- */
-void
-reset_backoff()
-{
- cur_backoff = MIN_BACKOFF;
-}
-
-/*
- * Name: _get_random_info
- * Description: generate an amount of random bits. Currently
- * only a small amount (a long long) can be
- * generated at one time.
- * Scope: private
- * Arguments: buf - [RO, *RW] (char *)
- * Buffer to copy bits into
- * size - amount to copy
- * Returns: B_TRUE on success, B_FALSE otherwise. The buffer is filled
- * with the amount of bytes of random data specified.
- */
-static boolean_t
-_get_random_info(void *buf, int size)
-{
- struct timeval tv;
- typedef struct {
- long low_time;
- long hostid;
- } randomness;
- randomness r;
-
- /* if the RANDOM file exists, use it */
- if (access(RANDOM, R_OK) == 0) {
- if ((RAND_load_file(RANDOM, 1024 * 1024)) > 0) {
- if (RAND_bytes((uchar_t *)buf, size) == 1) {
- /* success */
- return (B_TRUE);
- }
- }
- }
-
- /* couldn't use RANDOM file, so fallback to time of day and hostid */
- (void) gettimeofday(&tv, (struct timezone *)0);
-
- /* Wouldn't it be nice if we could hash these */
- r.low_time = tv.tv_usec;
- r.hostid = gethostid();
-
- if (sizeof (r) < size) {
- /*
- * Can't copy correctly
- */
- return (B_FALSE);
- }
- (void) memcpy(buf, &r, size);
- return (B_TRUE);
-}
-
-/*
- * Name: pkg_passphrase_cb
- * Description: Default callback that applications can use when
- * a passphrase is needed. This routine collects
- * a passphrase from the user using the given
- * passphrase retrieval method set with
- * set_passphrase_passarg(). If the method
- * indicates an interactive prompt, then the
- * prompt set with set_passphrase_prompt()
- * is displayed.
- *
- * Arguments: buf - Buffer to copy passphrase into
- * size - Max amount to copy to buf
- * rw - Whether this passphrase is needed
- * to read something off disk, or
- * write something to disk. Applications
- * typically want to ask twice when getting
- * a passphrase for writing something.
- * data - application-specific data. In this
- * callback, data is a pointer to
- * a keystore_passphrase_data structure.
- *
- * Returns: Length of passphrase collected, or -1 on error.
- * Errors recorded in 'err' object in the *data.
- */
-int
-pkg_passphrase_cb(char *buf, int size, int rw, void *data)
-{
- BIO *pwdbio = NULL;
- char passphrase_copy[MAX_PHRASELEN + 1];
- PKG_ERR *err;
- int passlen;
- char *ws;
- char prompt_copy[MAX_VERIFY_MSGLEN];
- char *passphrase;
- char *arg;
-
- err = ((keystore_passphrase_data *)data)->err;
-
- if (passarg == NULL) {
- arg = "console";
- } else {
- arg = passarg;
- }
-
- /* default method of collecting password is by prompting */
- if (ci_streq(arg, "console")) {
- if ((passphrase = getpassphrase(prompt)) == NULL) {
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(MSG_NOPASS), arg);
- return (-1);
- }
-
- if (rw) {
- /*
- * if the password is being supplied for
- * writing something to disk, verify it first
- */
-
- /* make a copy (getpassphrase overwrites) */
- (void) strlcpy(passphrase_copy, passphrase,
- MAX_PHRASELEN + 1);
-
- if (((passlen = snprintf(prompt_copy,
- MAX_VERIFY_MSGLEN, "%s: %s",
- gettext(MSG_PASSWD_AGAIN),
- prompt)) < 0) ||
- (passlen >= (MAX_PHRASELEN + 1))) {
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(MSG_NOPASS), arg);
- return (-1);
- }
-
- if ((passphrase =
- getpassphrase(prompt_copy)) == NULL) {
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(MSG_NOPASS), arg);
- return (-1);
- }
-
- if (!streq(passphrase_copy, passphrase)) {
- pkgerr_add(err, PKGERR_READ,
- gettext(MSG_PASSWD_NOMATCH));
- return (-1);
- }
- }
- } else if (ci_strneq(arg, "pass:", 5)) {
- passphrase = arg + 5;
- } else if (ci_strneq(arg, "env:", 4)) {
- passphrase = getenv(arg + 4);
- } else if (ci_strneq(arg, "file:", 5)) {
-
- /* open file for reading */
- if ((pwdbio = BIO_new_file(arg + 5, "r")) == NULL) {
- pkgerr_add(err, PKGERR_EXIST,
- gettext(MSG_PASSWD_FILE), arg + 5);
- return (-1);
- }
-
- /* read first line */
- if (((passlen = BIO_gets(pwdbio, buf, size)) < 1) ||
- (passlen > size)) {
- pkgerr_add(err, PKGERR_READ, gettext(MSG_PASSWD_FILE),
- arg + 5);
- return (-1);
- }
- BIO_free_all(pwdbio);
- pwdbio = NULL;
-
- if (passlen == size) {
- /*
- * password was maximum length, so there is
- * no null terminator. null-terminate it
- */
- buf[size - 1] = '\0';
- }
-
- /* first newline found is end of passwd, so nuke it */
- if ((ws = strchr(buf, '\n')) != NULL) {
- *ws = '\0';
- }
- return (strlen(buf));
- } else {
- /* unrecognized passphrase */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(MSG_BADPASSARG), arg);
- return (-1);
- }
-
- if (passphrase == NULL) {
- /* unable to collect passwd from given source */
- pkgerr_add(err, PKGERR_BADPASS,
- gettext(MSG_NOPASS), arg);
- return (-1);
- }
-
- (void) strlcpy(buf, passphrase, size);
- return (strlen(buf));
-}
diff --git a/usr/src/lib/libpkg/common/pkgweb.h b/usr/src/lib/libpkg/common/pkgweb.h
deleted file mode 100644
index fe9dc372d9..0000000000
--- a/usr/src/lib/libpkg/common/pkgweb.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKGWEB_H
-#define _PKGWEB_H
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <netdb.h>
-#include <boot_http.h>
-
-/* shortest backoff delay possible (in seconds) */
-#define MIN_BACKOFF 1
-
-/* how much to increase backoff time after each failure */
-#define BACKOFF_FACTOR 2
-
-/* Maximum amount of backoff for a heavy network or flaky server */
-#define MAX_BACKOFF 128
-
-typedef enum {
- HTTP_REQ_TYPE_HEAD,
- HTTP_REQ_TYPE_GET
-} HTTPRequestType;
-
-typedef enum {
- OCSPSuccess,
- OCSPMem,
- OCSPParse,
- OCSPConnect,
- OCSPRequest,
- OCSPResponder,
- OCSPUnsupported,
- OCSPVerify,
- OCSPInternal,
- OCSPNoURI
-} OCSPStatus;
-
-typedef enum {
- none,
- web_http,
- web_https,
- web_ftp
-} WebScheme;
-
-typedef enum {
- WEB_OK,
- WEB_TIMEOUT,
- WEB_CONNREFUSED,
- WEB_HOSTDOWN,
- WEB_VERIFY_SETUP,
- WEB_NOCONNECT,
- WEB_GET_FAIL
-} WebStatus;
-
-typedef struct {
- ulong_t prev_cont_length;
- ulong_t content_length;
- ulong_t cur_pos;
-} DwnldData;
-
-typedef struct {
- keystore_handle_t keystore;
- char *certfile;
- char *uniqfile;
- char *link;
- char *errstr;
- char *dwnld_dir;
- boolean_t spool;
- void *content;
- int timeout;
- url_hport_t proxy;
- url_t url;
- DwnldData data;
- http_respinfo_t *resp;
- boot_http_ver_t *http_vers;
- http_handle_t *hps;
-} WEB_SESSION;
-
-extern boolean_t web_session_control(PKG_ERR *, char *, char *,
- keystore_handle_t, char *, ushort_t, int, int, int, char **);
-extern boolean_t get_signature(PKG_ERR *, char *, struct pkgdev *,
- PKCS7 **);
-extern boolean_t validate_signature(PKG_ERR *, char *, BIO *, PKCS7 *,
- STACK_OF(X509) *, url_hport_t *, int);
-extern boolean_t ds_validate_signature(PKG_ERR *, struct pkgdev *, char **,
- char *, PKCS7 *, STACK_OF(X509) *, url_hport_t *, int);
-extern boolean_t get_proxy_port(PKG_ERR *, char **, ushort_t *);
-extern boolean_t path_valid(char *);
-extern void web_cleanup(void);
-extern ushort_t strip_port(char *proxy);
-extern void set_web_install(void);
-extern int is_web_install(void);
-extern void echo_out(int, char *, ...);
-extern void backoff(void);
-extern void reset_backoff(void);
-extern char *get_endof_string(char *, char);
-extern char *get_startof_string(char *, char);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKGWEB_H */
diff --git a/usr/src/lib/libpkg/common/progerr.c b/usr/src/lib/libpkg/common/progerr.c
index e239dd8bda..567d77b581 100644
--- a/usr/src/lib/libpkg/common/progerr.c
+++ b/usr/src/lib/libpkg/common/progerr.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,7 +40,6 @@
#include <stdlib.h>
#include <errno.h>
#include "pkglocale.h"
-#include "pkgerr.h"
static char *ProgName = NULL; /* Set via set_prog_name() */
@@ -94,17 +97,6 @@ progerr(char *fmt, ...)
(void) fprintf(stderr, "\n");
}
-void
-pkgerr(PKG_ERR *err)
-{
- int i;
-
- for (i = 0; i < pkgerr_num(err); i++) {
- progerr("%s", pkgerr_get(err, i));
- }
-}
-
-
/*
* set_memalloc_failure_func()
* Allows an appliation to specify the function to be called when
diff --git a/usr/src/lib/libpkg/common/security.c b/usr/src/lib/libpkg/common/security.c
deleted file mode 100644
index 9f2070c0c6..0000000000
--- a/usr/src/lib/libpkg/common/security.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-/*
- * Module: security.c
- * Description:
- * Module for handling certificates and various
- * utilities to access their data.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <pkgstrct.h>
-#include <pkginfo.h>
-#include <locale.h>
-#include <libintl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <openssl/bio.h>
-#include <openssl/pkcs12.h>
-#include <openssl/pkcs7.h>
-#include <openssl/x509.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#include "pkgerr.h"
-#include "pkglib.h"
-#include "pkglibmsgs.h"
-#include "pkglocale.h"
-#include "p12lib.h"
-
-/* length of allowable passwords */
-#define MAX_PASSLEN 128
-
-/*
- * Name: init_security
- * Description: Initializes structures, libraries, for security operations
- * Arguments: none
- * Returns: 0 if we couldn't initialize, non-zero otherwise
- */
-void
-sec_init(void)
-{
- OpenSSL_add_all_algorithms();
- SSL_load_error_strings();
- ERR_load_SUNW_strings();
- (void) SSL_library_init();
-}
-
-/*
- * get_cert_chain - Builds a chain of certificates, from a given
- * user certificate to a trusted certificate.
- *
- * Arguments:
- * err - Error object to add errors to
- * cert - User cert to start with
- * cas - Trusted certs to use as trust anchors
- * chain - The resulting chain of certs (in the form of an
- * ordered set) is placed here.
- *
- * Returns:
- * 0 - Success - chain is stored in 'chain'.
- * non-zero - Failure, errors recorded in err
- */
-int
-get_cert_chain(PKG_ERR *err, X509 *cert, STACK_OF(X509) *clcerts,
- STACK_OF(X509) *cas, STACK_OF(X509) **chain)
-{
- X509_STORE_CTX *store_ctx = NULL;
- X509_STORE *ca_store = NULL;
- X509 *ca_cert = NULL;
- int i;
- int ret = 0;
-
- if ((ca_store = X509_STORE_new()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM,
- gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- /* add all ca certs into the store */
- for (i = 0; i < sk_X509_num(cas); i++) {
- /* LINTED pointer cast may result in improper alignment */
- ca_cert = sk_X509_value(cas, i);
- if (X509_STORE_add_cert(ca_store, ca_cert) == 0) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
- }
-
- /* initialize context object used during the chain resolution */
-
- if ((store_ctx = X509_STORE_CTX_new()) == NULL) {
- pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM));
- ret = 1;
- goto cleanup;
- }
-
- (void) X509_STORE_CTX_init(store_ctx, ca_store, cert, clcerts);
- /* attempt to verify the cert, which builds the cert chain */
- if (X509_verify_cert(store_ctx) <= 0) {
- pkgerr_add(err, PKGERR_CHAIN,
- gettext(ERR_CERTCHAIN),
- get_subject_display_name(cert),
- X509_verify_cert_error_string(store_ctx->error));
- ret = 1;
- goto cleanup;
- }
- *chain = X509_STORE_CTX_get1_chain(store_ctx);
-
-cleanup:
- if (ca_store != NULL)
- (void) X509_STORE_free(ca_store);
- if (store_ctx != NULL) {
- (void) X509_STORE_CTX_cleanup(store_ctx);
- (void) X509_STORE_CTX_free(store_ctx);
- }
-
- return (ret);
-}
-
-/*
- * Name: get_subject_name
- * Description: Retrieves a name used for identifying a certificate's subject.
- *
- * Arguments: cert - The certificate to get the name from
- *
- * Returns : A static buffer containing the common name (CN) of the
- * subject of the cert.
- *
- * if the CN is not available, returns a string with the entire
- * X509 distinguished name.
- */
-char
-*get_subject_display_name(X509 *cert)
-{
-
- X509_NAME *xname;
- static char sname[ATTR_MAX];
-
- xname = X509_get_subject_name(cert);
- if (X509_NAME_get_text_by_NID(xname,
- NID_commonName, sname,
- ATTR_MAX) <= 0) {
- (void) strncpy(sname,
- X509_NAME_oneline(xname,
- NULL, 0), ATTR_MAX);
- sname[ATTR_MAX - 1] = '\0';
- }
- return (sname);
-}
-
-/*
- * Name: get_display_name
- * Description: Retrieves a name used for identifying a certificate's issuer.
- *
- * Arguments: cert - The certificate to get the name from
- *
- * Returns : A static buffer containing the common name (CN)
- * of the issuer of the cert.
- *
- * if the CN is not available, returns a string with the entire
- * X509 distinguished name.
- */
-char
-*get_issuer_display_name(X509 *cert)
-{
-
- X509_NAME *xname;
- static char sname[ATTR_MAX];
-
- xname = X509_get_issuer_name(cert);
- if (X509_NAME_get_text_by_NID(xname,
- NID_commonName, sname,
- ATTR_MAX) <= 0) {
- (void) strncpy(sname,
- X509_NAME_oneline(xname,
- NULL, 0), ATTR_MAX);
- sname[ATTR_MAX - 1] = '\0';
- }
- return (sname);
-}
-
-
-/*
- * Name: get_serial_num
- * Description: Retrieves the serial number of an X509 cert
- *
- * Arguments: cert - The certificate to get the data from
- *
- * Returns : A static buffer containing the serial number
- * of the cert
- *
- * if the SN is not available, returns NULL
- */
-char
-*get_serial_num(X509 *cert)
-{
- static char sn_str[ATTR_MAX];
- ASN1_INTEGER *sn;
-
- if ((sn = X509_get_serialNumber(cert)) != 0) {
- return (NULL);
- } else {
- (void) snprintf(sn_str, ATTR_MAX, "%ld",
- ASN1_INTEGER_get(sn));
- }
-
- return (sn_str);
-}
-
-/*
- * Name: get_fingerprint
- * Description: Generates a fingerprint string given
- * a digest algorithm with which to calculate
- * the fingerprint
- *
- * Arguments: cert - The certificate to get the data from
- * Arguments: alg - The algorithm to use to calculate the fingerprint
- *
- * Returns : A static buffer containing the digest
- * NULL if cert is NULL, or digest cannot be calculated
- */
-char
-*get_fingerprint(X509 *cert, const EVP_MD *alg)
-{
- static char fp_str[ATTR_MAX];
- char tmp[ATTR_MAX] = "";
- unsigned int n;
- unsigned char md[EVP_MAX_MD_SIZE];
- int i;
-
- if (!X509_digest(cert, alg, md, &n)) {
- return (NULL);
- }
-
- /* start with empty string */
- fp_str[0] = '\0';
-
- for (i = 0; i < (int)n; i++) {
- /* form a byte of the fingerprint */
- (void) snprintf(tmp, ATTR_MAX, "%02X:", md[i]);
- /* cat it onto the end of the result */
- (void) strlcat(fp_str, tmp, ATTR_MAX);
- }
-
- /* nuke trailing ':' */
- fp_str[strlen(fp_str) - 1] = '\0';
-
- return (fp_str);
-}