diff options
author | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2009-10-20 09:39:20 -0700 |
---|---|---|
committer | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2009-10-20 09:39:20 -0700 |
commit | 56664548661c43ae04de4a32bce3510ed36aeaf9 (patch) | |
tree | f23bd96c130e11e5b94c31a26273a2001020b565 /usr/src | |
parent | 069f55e237020c4a4907b235fc38fafc6442ce94 (diff) | |
download | illumos-gate-56664548661c43ae04de4a32bce3510ed36aeaf9.tar.gz |
6889197 libkmf uses realloc incorrectly
6889730 pktool fails to add EKUs to CSR and Cert requests
6889224 pktool incorrectly generates SAN
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/common.c | 5 | ||||
-rw-r--r-- | usr/src/lib/libkmf/ber_der/common/encode.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libkmf/ber_der/common/io.c | 27 | ||||
-rw-r--r-- | usr/src/lib/libkmf/ber_der/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libkmf/ber_der/inc/ber_der.h | 6 | ||||
-rw-r--r-- | usr/src/lib/libkmf/libkmf/common/generalop.c | 132 |
6 files changed, 148 insertions, 32 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.c b/usr/src/cmd/cmd-crypto/pktool/common.c index a6c649a120..8c95c2e480 100644 --- a/usr/src/cmd/cmd-crypto/pktool/common.c +++ b/usr/src/cmd/cmd-crypto/pktool/common.c @@ -1128,6 +1128,7 @@ free_eku_list(EKU_LIST *ekus) } free(ekus->ekulist); free(ekus->critlist); + free(ekus); } } @@ -1166,6 +1167,10 @@ verify_ekunames(char *ekuliststr, EKU_LIST **ekulist) if (ekuliststr == NULL || strlen(ekuliststr) == 0) return (0); + ekus = calloc(sizeof (EKU_LIST), 1); + if (ekus == NULL) + return (KMF_ERR_MEMORY); + /* * The list should be comma separated list of EKU Names. */ diff --git a/usr/src/lib/libkmf/ber_der/common/encode.c b/usr/src/lib/libkmf/ber_der/common/encode.c index 50e89d7c2f..73fe1b0ddf 100644 --- a/usr/src/lib/libkmf/ber_der/common/encode.c +++ b/usr/src/lib/libkmf/ber_der/common/encode.c @@ -30,12 +30,10 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <netinet/in.h> #include <inttypes.h> @@ -455,7 +453,9 @@ ber_start_seqorset(BerElement *ber, ber_tag_t tag) ber->ber_sos = new_sos; if (ber->ber_sos->sos_ptr > ber->ber_end) { - (void) realloc(ber, ber->ber_sos->sos_ptr - ber->ber_end); + if (kmfber_realloc(ber, ber->ber_sos->sos_ptr - + ber->ber_end) != 0) + return (-1); } return (0); } diff --git a/usr/src/lib/libkmf/ber_der/common/io.c b/usr/src/lib/libkmf/ber_der/common/io.c index e946252e2b..e0a16141da 100644 --- a/usr/src/lib/libkmf/ber_der/common/io.c +++ b/usr/src/lib/libkmf/ber_der/common/io.c @@ -29,13 +29,10 @@ * is provided ``as is'' without express or implied warranty. */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - - #include <stdlib.h> #include <ber_der.h> #include "kmfber_int.h" @@ -69,7 +66,7 @@ kmfber_read(BerElement *ber, char *buf, ber_len_t len) * enlarge the ber buffer. * return 0 on success, -1 on error. */ -static int +int kmfber_realloc(BerElement *ber, ber_len_t len) { ber_uint_t need, have, total; @@ -77,6 +74,7 @@ kmfber_realloc(BerElement *ber, ber_len_t len) Seqorset *s; size_t off; char *oldbuf; + boolean_t freeold = B_FALSE; have_bytes = ber->ber_end - ber->ber_buf; have = have_bytes / EXBUFSIZ; @@ -96,16 +94,19 @@ kmfber_realloc(BerElement *ber, ber_len_t len) /* transition to malloc'd buffer */ if ((ber->ber_buf = (char *)malloc( (size_t)total)) == NULL) { + free(oldbuf); return (-1); } ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER; /* copy existing data into new malloc'd buffer */ (void) memmove(ber->ber_buf, oldbuf, have_bytes); + freeold = B_TRUE; } else { if ((ber->ber_buf = (char *)realloc( ber->ber_buf, (size_t)total)) == NULL) { return (-1); } + freeold = B_FALSE; /* it was just realloced */ } } @@ -116,7 +117,6 @@ kmfber_realloc(BerElement *ber, ber_len_t len) * reset all the sos and ber pointers. Offsets would've been * a better idea... oh well. */ - if (ber->ber_buf != oldbuf) { ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); @@ -128,6 +128,8 @@ kmfber_realloc(BerElement *ber, ber_len_t len) s->sos_ptr = ber->ber_buf + off; } } + if (freeold && oldbuf != NULL) + free(oldbuf); return (0); } @@ -162,11 +164,10 @@ void kmfber_free(BerElement *ber, int freebuf) { if (ber != NULL) { - if (freebuf && - !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) { - free(ber->ber_buf); - } - free((char *)ber); + if (freebuf && + !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) + free(ber->ber_buf); + free((char *)ber); } } @@ -351,7 +352,7 @@ kmfder_init(const struct berval *bv) /* copy data from the bv argument into BerElement */ /* XXXmcs: had to cast unsigned long bv_len to long */ if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != - (ber_slen_t)bv->bv_len) { + (ber_slen_t)bv->bv_len) { kmfber_free(ber, 1); return (NULL); } @@ -379,7 +380,7 @@ kmfber_init(const struct berval *bv) /* copy data from the bv argument into BerElement */ /* XXXmcs: had to cast unsigned long bv_len to long */ if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != - (ber_slen_t)bv->bv_len) { + (ber_slen_t)bv->bv_len) { kmfber_free(ber, 1); return (NULL); } diff --git a/usr/src/lib/libkmf/ber_der/common/mapfile-vers b/usr/src/lib/libkmf/ber_der/common/mapfile-vers index 591db3eb67..0a97cd2eab 100644 --- a/usr/src/lib/libkmf/ber_der/common/mapfile-vers +++ b/usr/src/lib/libkmf/ber_der/common/mapfile-vers @@ -63,6 +63,7 @@ SUNWprivate_1.1 { ExtractX509CertParts; GetKeyFromSpki; kmfber_alloc; + kmfber_bvfree; kmfber_first_element; kmfber_flatten; kmfber_free; @@ -70,6 +71,7 @@ SUNWprivate_1.1 { kmfber_next_element; kmfber_printf; kmfber_read; + kmfber_realloc; kmfber_scanf; kmfber_write; kmfder_alloc; diff --git a/usr/src/lib/libkmf/ber_der/inc/ber_der.h b/usr/src/lib/libkmf/ber_der/inc/ber_der.h index 72a98e665c..abf112351d 100644 --- a/usr/src/lib/libkmf/ber_der/inc/ber_der.h +++ b/usr/src/lib/libkmf/ber_der/inc/ber_der.h @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -22,8 +22,6 @@ * Reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * This is the header file for some Basic Encoding Rules and Distinguished * Encoding Rules (BER/DER) routines. @@ -49,6 +47,7 @@ #define BER_IA5STRING 22 #define BER_UTCTIME 23 #define BER_GENTIME 24 +#define BER_GENERALSTRING 27 #define BER_UNIVERSAL_STRING 28 #define BER_BMP_STRING 30 @@ -114,6 +113,7 @@ struct berval *kmfber_bvdup(const struct berval *); */ extern int kmfber_printf(BerElement *, const char *, ...); extern int kmfber_flatten(BerElement *, struct berval **); +extern int kmfber_realloc(BerElement *, ber_len_t); /* * miscellaneous public routines diff --git a/usr/src/lib/libkmf/libkmf/common/generalop.c b/usr/src/lib/libkmf/libkmf/common/generalop.c index bbfdf152b0..f2a179b026 100644 --- a/usr/src/lib/libkmf/libkmf/common/generalop.c +++ b/usr/src/lib/libkmf/libkmf/common/generalop.c @@ -1699,6 +1699,7 @@ encode_krb5(char *name, KMF_DATA *derdata) { KMF_RETURN rv = KMF_OK; char *at, *realm; + char *slash, *inst = NULL; BerElement *asn1 = NULL; BerValue *extdata = NULL; @@ -1706,42 +1707,149 @@ encode_krb5(char *name, KMF_DATA *derdata) if (at == NULL) return (KMF_ERR_ENCODING); - realm = at+1; + realm = at + 1; *at = 0; - if ((asn1 = kmfder_alloc()) == NULL) - return (KMF_ERR_MEMORY); + /* + * KRB5PrincipalName ::= SEQUENCE { + * realm [0] Realm, + * principalName [1] PrincipalName + * } + * + * KerberosString ::= GeneralString (IA5String) + * Realm ::= KerberosString + * PrincipalName ::= SEQUENCE { + * name-type [0] Int32, + * name-string [1] SEQUENCE OF KerberosString + * } + */ + + /* + * Construct the "principalName" first. + * + * The name may be split with a "/" to indicate a new instance. + * This must be separated in the ASN.1 + */ + slash = strchr(name, '/'); + if (slash != NULL) { + inst = name; + name = slash + 1; + *slash = 0; + } + if ((asn1 = kmfder_alloc()) == NULL) { + rv = KMF_ERR_MEMORY; + goto cleanup; + } + if (kmfber_printf(asn1, "{Tli", 0xa0, 3, 0x01) == -1) + goto cleanup; + + if (inst != NULL) { + if (kmfber_printf(asn1, "Tl{Tl", 0xA1, + strlen(inst) + strlen(name) + 6, + BER_GENERALSTRING, strlen(inst)) == -1) + goto cleanup; + if (kmfber_write(asn1, inst, strlen(inst), 0) != strlen(inst)) + goto cleanup; + if (kmfber_printf(asn1, "Tl", BER_GENERALSTRING, + strlen(name)) == -1) + goto cleanup; + if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) + goto cleanup; + } else { + if (kmfber_printf(asn1, "Tl{Tl", 0xA1, + strlen(name) + 4, BER_GENERALSTRING, strlen(name)) == -1) + goto cleanup; + if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) + goto cleanup; + } - if (kmfber_printf(asn1, "{D{", &KMFOID_PKINIT_san) == -1) + if (kmfber_printf(asn1, "}}") == -1) goto cleanup; + if (kmfber_flatten(asn1, &extdata) == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + kmfber_free(asn1, 1); + asn1 = NULL; - if (kmfber_printf(asn1, "l", strlen(realm)) == -1) + /* Next construct the KRB5PrincipalNameSeq */ + if ((asn1 = kmfder_alloc()) == NULL) { + kmfber_bvfree(extdata); + rv = KMF_ERR_MEMORY; + goto cleanup; + } + if (kmfber_printf(asn1, "{TlTl", 0xA0, strlen(realm) + 2, + BER_GENERALSTRING, strlen(realm)) == -1) goto cleanup; if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm)) goto cleanup; - if (kmfber_printf(asn1, "l", strlen(name)) == -1) + if (kmfber_printf(asn1, "Tl", 0xA1, extdata->bv_len) == -1) goto cleanup; - if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) + if (kmfber_write(asn1, extdata->bv_val, + extdata->bv_len, 0) != extdata->bv_len) goto cleanup; - if (kmfber_printf(asn1, "}}") == -1) + if (kmfber_printf(asn1, "}") == -1) + goto cleanup; + kmfber_bvfree(extdata); + extdata = NULL; + if (kmfber_flatten(asn1, &extdata) == -1) { + rv = KMF_ERR_ENCODING; goto cleanup; + } + kmfber_free(asn1, 1); + asn1 = NULL; + + /* + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * ... + * } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id + * } + */ + /* Now construct the SAN: OID + typed data. */ + if ((asn1 = kmfder_alloc()) == NULL) { + kmfber_bvfree(extdata); + rv = KMF_ERR_MEMORY; + goto cleanup; + } + if (kmfber_printf(asn1, "D", &KMFOID_PKINIT_san) == -1) + goto cleanup; + if (kmfber_printf(asn1, "Tl", 0xA0, extdata->bv_len) == -1) + goto cleanup; + if (kmfber_write(asn1, extdata->bv_val, + extdata->bv_len, 0) != extdata->bv_len) + goto cleanup; + kmfber_bvfree(extdata); + extdata = NULL; if (kmfber_flatten(asn1, &extdata) == -1) { rv = KMF_ERR_ENCODING; goto cleanup; } + kmfber_free(asn1, 1); + asn1 = NULL; derdata->Data = (uchar_t *)extdata->bv_val; + extdata->bv_val = NULL; /* clear it so it is not freed later */ derdata->Length = extdata->bv_len; - free(extdata); cleanup: if (asn1 != NULL) kmfber_free(asn1, 1); + if (extdata != NULL) + kmfber_bvfree(extdata); + if (*at == 0) *at = '@'; + if (inst != NULL) + *slash = '/'; + return (rv); } @@ -1864,14 +1972,14 @@ encode_altname(char *namedata, ret = DerEncodeName(&dnname, encodedname); } (void) kmf_free_dn(&dnname); - tagval = (0xA0 | nametype); + tagval = (0x80 | nametype); break; case GENNAME_KRB5PRINC: - tagval = (0x80 | GENNAME_OTHERNAME); + tagval = (0xA0 | GENNAME_OTHERNAME); ret = encode_krb5(namedata, encodedname); break; case GENNAME_SCLOGON_UPN: - tagval = (0x80 | GENNAME_OTHERNAME); + tagval = (0xA0 | GENNAME_OTHERNAME); ret = encode_sclogon(namedata, encodedname); break; default: |