Bug 285208: certutil when given arguments for both -7 and -8 would create two
authorneil.williams%sun.com
Mon, 14 Mar 2005 18:55:46 +0000
changeset 5533 c0425afa72e91ed9ecfea3468fde8879bd16eefd
parent 5532 8917c8b497d0039a6091798828cefae37daeafef
child 5534 a8d982f772d0b8821793ea50b9e994eb0a23475e
push idunknown
push userunknown
push dateunknown
bugs285208
Bug 285208: certutil when given arguments for both -7 and -8 would create two subjAltName extensions. Now a list single extension with both name types in created. r=nelson
security/nss/cmd/certutil/certutil.c
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -444,18 +444,18 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 	return SECFailure;
     }
     
     extHandle = CERT_StartCertificateRequestAttributes(cr);
     if (extHandle == NULL) {
         PORT_FreeArena (arena, PR_FALSE);
 	return SECFailure;
     }
-    if (AddExtensions(extHandle, emailAddrs, PR_FALSE, PR_FALSE, PR_FALSE,
-                      PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE)
+    if (AddExtensions(extHandle, emailAddrs, dnsNames, keyUsage, extKeyUsage,
+                      basicConstraint, authKeyID, crlDistPoints, nscpCertType)
                   != SECSuccess) {
         PORT_FreeArena (arena, PR_FALSE);
         return SECFailure;
     }
     CERT_FinishExtensions(extHandle);
     CERT_FinishCertificateRequestAttributes(cr);
 
     /* Der encode the request */
@@ -1699,31 +1699,26 @@ AddNscpCertType (void *extHandle)
 
     return (CERT_EncodeAndAddBitStrExtension
 	    (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
 	     (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE));
 
 }
 
 static SECStatus 
-AddSubjectAltNames(void *extHandle, const char *names, CERTGeneralNameType type)
+AddSubjectAltNames(PRArenaPool *arena, CERTGeneralName **existingListp,
+                    const char *names, CERTGeneralNameType type)
 {
-    SECItem item = { 0, NULL, 0 };
     CERTGeneralName *nameList = NULL;
     CERTGeneralName *current = NULL;
     PRCList *prev = NULL;
-    PRArenaPool *arena;
     const char *cp;
     char *tbuf;
     SECStatus rv = SECSuccess;
 
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) {
-	return SECFailure;
-    }
 	
     /*
      * walk down the comma separated list of names. NOTE: there is
      * no sanity checks to see if the email address look like email addresses.
      */
     for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
 	int len;
 	char *end;
@@ -1750,47 +1745,50 @@ AddSubjectAltNames(void *extHandle, cons
 	} else {
 	    nameList = current;
 	}
 	current->type = type;
 	current->name.other.data = (unsigned char *)tbuf;
 	current->name.other.len = PORT_Strlen(tbuf);
 	prev = &(current->l);
     }
-    if (rv != SECSuccess) {
-	goto loser;
-    }
-    /* no email address */
-    if (!nameList) {
-	/*rv=SECSuccess; We know rv is SECSuccess because of the previous if*/
-	goto done; 
+    /* at this point nameList points to the head of a doubly linked, but not yet 
+       circular, list and current points to its tail. */
+    if (rv == SECSuccess && nameList) {
+        if (*existingListp != NULL) {
+            PRCList *existingprev;
+            /* add nameList to the end of the existing list */
+            existingprev = (*existingListp)->l.prev;
+            (*existingListp)->l.prev = &(current->l);
+            nameList->l.prev = existingprev;
+            existingprev->next = &(nameList->l);
+            current->l.next = &((*existingListp)->l);
+        }
+        else {
+            /* make nameList circular and set it as the new existingList */
+            nameList->l.prev = prev;
+            current->l.next = &(nameList->l);
+            *existingListp = nameList;
+        }
     }
-    nameList->l.prev = prev;
-    current->l.next = &(nameList->l);
-
-    CERT_EncodeAltNameExtension(arena, nameList, &item);
-    rv = CERT_AddExtension (extHandle, SEC_OID_X509_SUBJECT_ALT_NAME, &item, 
-							PR_FALSE, PR_TRUE);
-done:
-loser:
-    PORT_FreeArena(arena, PR_FALSE);
     return rv;
-
 }
 
 static SECStatus 
-AddEmailSubjectAlt(void *extHandle, const char *emailAddrs)
+AddEmailSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
+                    const char *emailAddrs)
 {
-    return AddSubjectAltNames(extHandle, emailAddrs, certRFC822Name);
+    return AddSubjectAltNames(arena, existingListp, emailAddrs, certRFC822Name);
 }
 
 static SECStatus 
-AddDNSSubjectAlt(void *extHandle, const char *dnsNames)
+AddDNSSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
+                    const char *dnsNames)
 {
-    return AddSubjectAltNames(extHandle, dnsNames, certDNSName);
+    return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
 }
 
 
 typedef SECStatus (* EXTEN_VALUE_ENCODER)
 		(PRArenaPool *extHandle, void *value, SECItem *encodedValue);
 
 static SECStatus 
 EncodeAndAddExtensionValue(
@@ -2151,26 +2149,40 @@ AddExtensions(void *extHandle, const cha
 	}
 	
 	if (nscpCertType) {
 	    rv = AddNscpCertType(extHandle);
 	    if (rv)
 		break;
 	}
 
-	if (emailAddrs != NULL) {
-	    rv = AddEmailSubjectAlt(extHandle,emailAddrs);
-	    if (rv)
-		break;
-	}
+	if (emailAddrs || dnsNames) {
+            PRArenaPool *arena;
+            CERTGeneralName *namelist = NULL;
+            SECItem item = { 0, NULL, 0 };
+            
+            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+            if (arena == NULL) {
+                rv = SECFailure;
+                break;
+            }
 
-	if (dnsNames != NULL) {
-	    rv = AddDNSSubjectAlt(extHandle,dnsNames);
-	    if (rv)
-		break;
+	    rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs);
+
+	    rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
+
+            if (rv == SECSuccess) {
+                rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
+                if (rv == SECSuccess) {
+                   rv = CERT_AddExtension(extHandle,
+                                           SEC_OID_X509_SUBJECT_ALT_NAME,
+                                           &item, PR_FALSE, PR_TRUE);
+                }
+            }
+            PORT_FreeArena(arena, PR_FALSE);
 	}
     } while (0);
     return rv;
 }
 
 static SECStatus
 CreateCert(
 	CERTCertDBHandle *handle,