diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-10-04 12:00:08 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-10-04 12:00:08 +0000 |
| commit | 0cd103a9ea5572c37d728a7d26701a18dc9e3a7f (patch) | |
| tree | bca6ea57ba1ec3bd68be293a7f0230f45aff5e6c /usr/src/lib/libkmf | |
| parent | eee2da8296e69bdb47747ea36f4d186e6a133c96 (diff) | |
| parent | aa9ef484c6f8ecee85dfefdb4970c50cfa2db302 (diff) | |
| download | illumos-joyent-0cd103a9ea5572c37d728a7d26701a18dc9e3a7f.tar.gz | |
[illumos-gate merge]
commit aa9ef484c6f8ecee85dfefdb4970c50cfa2db302
9128 cw(1onbld) should be able to run multiple shadows
9129 file-locking tests shouldn't build multiple source files in one compiler invocation
9130 DTrace tst.gcc.d isn't useful
9132 cw(1onbld) shouldn't shadow pure preprocessing
commit bdc560ab289d67ddebad9a2146fd36c2662d88b1
5159 ipsec_libssl_setup.c loads libcrypto
commit 15aeb4d1148772724cf568e1f7a13fbb99f11ab8
9848 libi386: pxe.h cstyle cleanup
Diffstat (limited to 'usr/src/lib/libkmf')
| -rw-r--r-- | usr/src/lib/libkmf/include/kmfapi.h | 2 | ||||
| -rw-r--r-- | usr/src/lib/libkmf/libkmf/Makefile.com | 5 | ||||
| -rw-r--r-- | usr/src/lib/libkmf/libkmf/common/mapfile-vers | 2 | ||||
| -rw-r--r-- | usr/src/lib/libkmf/libkmf/common/rdn_parser.c | 218 |
4 files changed, 225 insertions, 2 deletions
diff --git a/usr/src/lib/libkmf/include/kmfapi.h b/usr/src/lib/libkmf/include/kmfapi.h index 9aeb0ca202..dbe09b2db6 100644 --- a/usr/src/lib/libkmf/include/kmfapi.h +++ b/usr/src/lib/libkmf/include/kmfapi.h @@ -19,6 +19,7 @@ * CDDL HEADER END * * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018, Joyent, Inc. * * Constant definitions and function prototypes for the KMF library. * Commonly used data types are defined in "kmftypes.h". @@ -275,6 +276,7 @@ extern KMF_RETURN kmf_get_kmf_error_str(KMF_RETURN, char **); * Miscellaneous */ extern KMF_RETURN kmf_dn_parser(char *, KMF_X509_NAME *); +extern KMF_RETURN kmf_dn_to_string(KMF_X509_NAME *, char **); extern KMF_RETURN kmf_read_input_file(KMF_HANDLE_T, char *, KMF_DATA *); extern KMF_RETURN kmf_der_to_pem(KMF_OBJECT_TYPE, unsigned char *, int, unsigned char **, int *); diff --git a/usr/src/lib/libkmf/libkmf/Makefile.com b/usr/src/lib/libkmf/libkmf/Makefile.com index a704d1e5a8..43de43cb1d 100644 --- a/usr/src/lib/libkmf/libkmf/Makefile.com +++ b/usr/src/lib/libkmf/libkmf/Makefile.com @@ -19,6 +19,7 @@ # CDDL HEADER END # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2018, Joyent, Inc. # LIBRARY= libkmf.a @@ -56,8 +57,8 @@ LIBS= $(DYNLIB) $(LINTLIB) $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) -LDLIBS += $(BERDERLIB) $(CRYPTOUTILLIB) -lmd -lpkcs11 -lnsl -lsocket -lc -LDLIBS6 += $(BERDERLIB64) $(CRYPTOUTILLIB64) -lmd -lpkcs11 -lnsl -lsocket -lc +LDLIBS += $(BERDERLIB) $(CRYPTOUTILLIB) -lmd -lpkcs11 -lnsl -lsocket -lc +LDLIBS += -lcustr # DYNLIB libraries do not have lint libs and are not linted $(DYNLIB) := LDLIBS += -lxml2 diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers index 4e8d0d848d..977112d733 100644 --- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers +++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers @@ -19,6 +19,7 @@ # CDDL HEADER END # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2018, Joyent, Inc. # # # MAPFILE HEADER START @@ -401,6 +402,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { GetIDFromSPKI; IsEqualOid; kmf_create_pk11_session; + kmf_dn_to_string; kmf_select_token; parsePolicyElement; PKCS_DigestData; diff --git a/usr/src/lib/libkmf/libkmf/common/rdn_parser.c b/usr/src/lib/libkmf/libkmf/common/rdn_parser.c index 5cc22146d8..3e23c0ac56 100644 --- a/usr/src/lib/libkmf/libkmf/common/rdn_parser.c +++ b/usr/src/lib/libkmf/libkmf/common/rdn_parser.c @@ -33,6 +33,8 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * + * Copyright 2018, Joyent, Inc. + * * File: rdn_parser.c */ @@ -44,6 +46,7 @@ #include <rdn_parser.h> #include <stdio.h> #include <values.h> +#include <libcustr.h> /* * The order here is important. The OIDs are arranged in order of @@ -535,3 +538,218 @@ kmf_dn_parser(char *string, KMF_X509_NAME *name) err = ParseDistinguishedName(string, (int)strlen(string), name); return (err); } + +static const char hexdigits[] = "0123456789abcdef"; + +static KMF_RETURN +binvalue_to_string(KMF_DATA *data, custr_t *str) +{ + size_t i; + uchar_t c; + + if (custr_appendc(str, '#') != 0) + return (KMF_ERR_MEMORY); + + for (i = 0; i < data->Length; i++) { + c = data->Data[i]; + if (custr_appendc(str, hexdigits[(c >> 4) & 0xf]) != 0 || + custr_appendc(str, hexdigits[(c & 0xf)]) != 0) { + return (KMF_ERR_MEMORY); + } + } + + return (KMF_OK); +} + +/* + * Convert an RDN value into a printable name with appropriate escaping. + * The rules are taken from RFC4514. While it is dealing with LDAP + * distinguished names, both LDAP and x509 certificates are based on the + * same underlying ITU standards, and as far as I can determine, the same + * rules apply (or at least the rules for LDAP DNs apply the same to x509 + * DNs). + */ +static KMF_RETURN +value_to_string(KMF_DATA *data, custr_t *str) +{ + size_t i; + uchar_t c; + + for (i = 0; i < data->Length; i++) { + c = data->Data[i]; + + /* + * While technically not required, it is suggested that + * printable non-ascii characters (e.g. multi-byte UTF-8 + * characters) are converted as escaped hex (as well as + * unprintable characters). AFAIK there is no one canonical + * string representation (e.g. attribute names are case + * insensitive, so 'CN=foo' and 'cn=foo' convert to the same + * binary representation, but there is nothing to say if + * either string form is canonical), so this shouldn't + * pose a problem. + */ + if (c < ' ' || c >= 0x7f) { + /* + * RFC4514 specifies the hex form in a DN string as + * \{hex}{hex}. OpenSSL uses capitals for A-F so we + * do the same. + */ + if (custr_append_printf(str, "\\%02hhX", c) != 0) + return (KMF_ERR_MEMORY); + continue; + } + + switch (c) { + case '#': + /* Escape # if at the start of a value */ + if (i != 0) + break; + /* FALLTHROUGH */ + case ' ': + /* Escape ' ' if at the start or end of a value */ + if (i != 0 && i + 1 != data->Length) + break; + /* FALLTHROUGH */ + case '"': + case '+': + case ',': + case ';': + case '<': + case '>': + case '\\': + /* Escape these */ + if (custr_appendc(str, '\\') != 0) + return (KMF_ERR_MEMORY); + } + + if (custr_appendc(str, c) != 0) + return (KMF_ERR_MEMORY); + } + + return (KMF_OK); +} + +/* + * Translate an attribute/value pair into a string. If the attribute OID + * is a well known OID (in name2kinds) we use the name instead of the OID. + */ +static KMF_RETURN +ava_to_string(KMF_X509_TYPE_VALUE_PAIR *tvp, custr_t *str) +{ + KMF_OID *kind_oid; + KMF_OID *rdn_oid = &tvp->type; + const char *attr = NULL; + size_t i; + KMF_RETURN ret = KMF_OK; + boolean_t found = B_FALSE; + + for (i = 0; name2kinds[i].name != NULL; i++) { + kind_oid = name2kinds[i].OID; + + if (!IsEqualOid(kind_oid, rdn_oid)) + continue; + + attr = name2kinds[i].name; + found = B_TRUE; + break; + } + + if (!found && (attr = kmf_oid_to_string(rdn_oid)) == NULL) { + ret = KMF_ERR_MEMORY; + goto done; + } + if (custr_append(str, attr) != 0) { + ret = KMF_ERR_MEMORY; + goto done; + } + if (custr_appendc(str, '=') != 0) { + ret = KMF_ERR_MEMORY; + goto done; + } + + /* + * RFC4514 indicates that an oid=value pair should have the value + * printed as #xxxxxx. In addition, we also print as a binary + * value if the BER tag does not indicate the value is some sort + * of printable string. + */ + switch (tvp->valueType) { + case BER_UTF8_STRING: + case BER_PRINTABLE_STRING: + case BER_T61STRING: + case BER_IA5STRING: + if (found) { + ret = value_to_string(&tvp->value, str); + break; + } + /*FALLTHROUGH*/ + default: + ret = binvalue_to_string(&tvp->value, str); + break; + } + +done: + if (!found) + free((void *)attr); + + return (ret); +} + +static KMF_RETURN +rdn_to_string(KMF_X509_RDN *rdn, custr_t *str) +{ + KMF_RETURN ret; + size_t i; + + for (i = 0; i < rdn->numberOfPairs; i++) { + if (i > 0 && custr_appendc(str, '+') != 0) + return (KMF_ERR_MEMORY); + + ret = ava_to_string(&rdn->AttributeTypeAndValue[i], str); + if (ret != KMF_OK) + return (ret); + } + + return (KMF_OK); +} + +/* + * kmf_dn_to_string + * + * Take a binary KMF_X509_NAME and convert it into a human readable string. + */ +KMF_RETURN +kmf_dn_to_string(KMF_X509_NAME *name, char **string) +{ + custr_t *str = NULL; + KMF_RETURN err = KMF_OK; + size_t i; + + if (name == NULL || string == NULL) + return (KMF_ERR_BAD_PARAMETER); + + *string = NULL; + + if (custr_alloc(&str) != 0) + return (KMF_ERR_MEMORY); + + for (i = 0; i < name->numberOfRDNs; i++) { + KMF_X509_RDN *rdn = &name->RelativeDistinguishedName[i]; + + if (i > 0 && custr_append(str, ", ") != 0) { + err = KMF_ERR_MEMORY; + goto done; + } + + if ((err = rdn_to_string(rdn, str)) != KMF_OK) + goto done; + } + + if ((*string = strdup(custr_cstr(str))) == NULL) + err = KMF_ERR_MEMORY; + +done: + custr_free(str); + return (err); +} |
