changeset 10818:89e8703947be

6889197 libkmf uses realloc incorrectly 6889730 pktool fails to add EKUs to CSR and Cert requests 6889224 pktool incorrectly generates SAN
author Wyllys Ingersoll <wyllys.ingersoll@sun.com>
date Tue, 20 Oct 2009 09:39:20 -0700
parents 7dfde45252f0
children d41e0e73a69e
files usr/src/cmd/cmd-crypto/pktool/common.c usr/src/lib/libkmf/ber_der/common/encode.c usr/src/lib/libkmf/ber_der/common/io.c usr/src/lib/libkmf/ber_der/common/mapfile-vers usr/src/lib/libkmf/ber_der/inc/ber_der.h usr/src/lib/libkmf/libkmf/common/generalop.c
diffstat 6 files changed, 154 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/pktool/common.c	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/common.c	Tue Oct 20 09:39:20 2009 -0700
@@ -1128,6 +1128,7 @@
 		}
 		free(ekus->ekulist);
 		free(ekus->critlist);
+		free(ekus);
 	}
 }
 
@@ -1166,6 +1167,10 @@
 	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.
 	 */
--- a/usr/src/lib/libkmf/ber_der/common/encode.c	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/lib/libkmf/ber_der/common/encode.c	Tue Oct 20 09:39:20 2009 -0700
@@ -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->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);
 }
--- a/usr/src/lib/libkmf/ber_der/common/io.c	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/lib/libkmf/ber_der/common/io.c	Tue Oct 20 09:39:20 2009 -0700
@@ -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 @@
  * 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 @@
 	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 @@
 			/* 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 @@
 	 * 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 @@
 			s->sos_ptr = ber->ber_buf + off;
 		}
 	}
+	if (freeold && oldbuf != NULL)
+		free(oldbuf);
 
 	return (0);
 }
@@ -162,11 +164,10 @@
 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 @@
 		/* 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 @@
 		/* 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);
 		}
--- a/usr/src/lib/libkmf/ber_der/common/mapfile-vers	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/lib/libkmf/ber_der/common/mapfile-vers	Tue Oct 20 09:39:20 2009 -0700
@@ -63,6 +63,7 @@
 	ExtractX509CertParts;
 	GetKeyFromSpki;
 	kmfber_alloc;
+	kmfber_bvfree;
 	kmfber_first_element;
 	kmfber_flatten;
 	kmfber_free;
@@ -70,6 +71,7 @@
 	kmfber_next_element;
 	kmfber_printf;
 	kmfber_read;
+	kmfber_realloc;
 	kmfber_scanf;
 	kmfber_write;
 	kmfder_alloc;
--- a/usr/src/lib/libkmf/ber_der/inc/ber_der.h	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/lib/libkmf/ber_der/inc/ber_der.h	Tue Oct 20 09:39:20 2009 -0700
@@ -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 @@
  */
 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
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c	Tue Oct 20 09:30:12 2009 -0700
+++ b/usr/src/lib/libkmf/libkmf/common/generalop.c	Tue Oct 20 09:39:20 2009 -0700
@@ -1699,6 +1699,7 @@
 {
 	KMF_RETURN rv = KMF_OK;
 	char *at, *realm;
+	char *slash, *inst = NULL;
 	BerElement *asn1 = NULL;
 	BerValue *extdata = NULL;
 
@@ -1706,42 +1707,149 @@
 	if (at == NULL)
 		return (KMF_ERR_ENCODING);
 
-	realm = at+1;
+	realm = at + 1;
 	*at = 0;
 
-	if ((asn1 = kmfder_alloc()) == NULL)
-		return (KMF_ERR_MEMORY);
-
-	if (kmfber_printf(asn1, "{D{", &KMFOID_PKINIT_san) == -1)
+	/*
+	 * 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, "l", strlen(realm)) == -1)
-		goto cleanup;
-	if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm))
+	}
+	if (kmfber_printf(asn1, "{Tli", 0xa0, 3, 0x01) == -1)
 		goto cleanup;
-	if (kmfber_printf(asn1, "l", strlen(name)) == -1)
-		goto cleanup;
-	if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name))
-		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, "}}") == -1)
 		goto cleanup;
-
 	if (kmfber_flatten(asn1, &extdata) == -1) {
 		rv = KMF_ERR_ENCODING;
 		goto cleanup;
 	}
+	kmfber_free(asn1, 1);
+	asn1 = NULL;
+
+	/* 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, "Tl", 0xA1, extdata->bv_len) == -1)
+		goto cleanup;
+	if (kmfber_write(asn1, extdata->bv_val,
+	    extdata->bv_len, 0) != extdata->bv_len)
+		goto cleanup;
+	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 @@
 				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: