summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpkg/common/security.c
diff options
context:
space:
mode:
authorMoriah Waterland <Moriah.Waterland@Sun.COM>2009-06-03 20:16:25 -0600
committerMoriah Waterland <Moriah.Waterland@Sun.COM>2009-06-03 20:16:25 -0600
commit5c51f1241dbbdf2656d0e10011981411ed0c9673 (patch)
tree0f30a2e38fe4e5d53a5a67264ba548577d82a86f /usr/src/lib/libpkg/common/security.c
parent2b79d384d32b4ea1e278466cd9b0f3bb56daae22 (diff)
downloadillumos-joyent-5c51f1241dbbdf2656d0e10011981411ed0c9673.tar.gz
6739234 move SVR4 packaging to ONNV gate
Diffstat (limited to 'usr/src/lib/libpkg/common/security.c')
-rw-r--r--usr/src/lib/libpkg/common/security.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/usr/src/lib/libpkg/common/security.c b/usr/src/lib/libpkg/common/security.c
new file mode 100644
index 0000000000..9f2070c0c6
--- /dev/null
+++ b/usr/src/lib/libpkg/common/security.c
@@ -0,0 +1,282 @@
+/*
+ * 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);
+}