security/nss/cmd/certutil/certext.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6 ** certext.c
     7 **
     8 ** part of certutil for managing certificates extensions
     9 **
    10 */
    11 #include <stdio.h>
    12 #include <string.h>
    13 #include <stdlib.h>
    15 #if defined(WIN32)
    16 #include "fcntl.h"
    17 #include "io.h"
    18 #endif
    20 #include "secutil.h"
    22 #if defined(XP_UNIX)
    23 #include <unistd.h>
    24 #endif
    26 #include "cert.h"
    27 #include "xconst.h"
    28 #include "prprf.h"
    29 #include "certutil.h"
    30 #include "genname.h"
    31 #include "prnetdb.h"
    33 #define GEN_BREAK(e) rv=e; break;
    35 static char *
    36 Gets_s(char *buff, size_t size) {
    37     char *str;
    39     if (buff == NULL || size < 1) {
    40         PORT_Assert(0);
    41         return NULL;
    42     }
    43     if ((str = fgets(buff, size, stdin)) != NULL) {
    44         int len = PORT_Strlen(str);
    45         /*
    46          * fgets() automatically converts native text file
    47          * line endings to '\n'.  As defensive programming
    48          * (just in case fgets has a bug or we put stdin in
    49          * binary mode by mistake), we handle three native 
    50          * text file line endings here:
    51          *   '\n'      Unix (including Linux and Mac OS X)
    52          *   '\r''\n'  DOS/Windows & OS/2
    53          *   '\r'      Mac OS Classic
    54          * len can not be less then 1, since in case with
    55          * empty string it has at least '\n' in the buffer
    56          */
    57         if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
    58             buff[len - 1] = '\0';
    59             if (len > 1 && buff[len - 2] == '\r')
    60                 buff[len - 2] = '\0';
    61         }
    62     } else {
    63         buff[0] = '\0';
    64     }
    65     return str;
    66 }
    69 static SECStatus
    70 PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize)
    71 {
    72     fputs(str, stdout);
    73     fputs(" > ", stdout);
    74     fflush (stdout);
    75     if (Gets_s(rBuff, rSize) == NULL) {
    76         PORT_SetError(SEC_ERROR_INPUT_LEN);
    77         return SECFailure;
    78     }
    79     return SECSuccess;
    80 }
    82 static CERTGeneralName *
    83 GetGeneralName(PLArenaPool *arena, CERTGeneralName *useExistingName, PRBool onlyOne)
    84 {
    85     CERTGeneralName *namesList = NULL;
    86     CERTGeneralName *current;
    87     CERTGeneralName *tail = NULL;
    88     SECStatus rv = SECSuccess;
    89     int intValue;
    90     char buffer[512];
    91     void *mark;
    93     PORT_Assert (arena);
    94     mark = PORT_ArenaMark (arena);
    95     do {
    96         if (PrintChoicesAndGetAnswer(
    97 		"\nSelect one of the following general name type: \n"
    98 		"\t2 - rfc822Name\n"
    99 		"\t3 - dnsName\n"
   100 		"\t5 - directoryName\n"
   101 		"\t7 - uniformResourceidentifier\n"
   102 		"\t8 - ipAddress\n"
   103 		"\t9 - registerID\n"
   104 		"\tAny other number to finish\n"
   105 		"\t\tChoice:", buffer, sizeof(buffer)) == SECFailure) {
   106             GEN_BREAK (SECFailure);
   107         }
   108         intValue = PORT_Atoi (buffer);
   109         /*
   110          * Should use ZAlloc instead of Alloc to avoid problem with garbage
   111          * initialized pointers in CERT_CopyName
   112          */
   113         switch (intValue) {
   114         case certRFC822Name:
   115         case certDNSName:
   116         case certDirectoryName:
   117         case certURI:
   118         case certIPAddress:
   119         case certRegisterID:
   120 	    break;
   121 	default:
   122 	    intValue = 0;   /* force a break for anything else */
   123 	}
   125         if (intValue == 0)
   126 	    break;
   128 	if (namesList == NULL) {
   129             if (useExistingName) {
   130                 namesList = current = tail = useExistingName;
   131             } else {
   132                 namesList = current = tail =
   133                     PORT_ArenaZNew(arena, CERTGeneralName);
   134             }
   135 	} else {
   136 	    current = PORT_ArenaZNew(arena, CERTGeneralName);
   137 	}
   138 	if (current == NULL) {
   139 	    GEN_BREAK (SECFailure);
   140 	}
   142         current->type = intValue;
   143         puts ("\nEnter data:");
   144         fflush (stdout);
   145         if (Gets_s (buffer, sizeof(buffer)) == NULL) {
   146             PORT_SetError(SEC_ERROR_INPUT_LEN);
   147             GEN_BREAK (SECFailure);
   148         }
   149         switch (current->type) {
   150         case certURI:
   151         case certDNSName:
   152         case certRFC822Name:
   153             current->name.other.data =
   154                 PORT_ArenaAlloc (arena, strlen (buffer));
   155             if (current->name.other.data == NULL) {
   156                 GEN_BREAK (SECFailure);
   157             }
   158             PORT_Memcpy(current->name.other.data, buffer,
   159                         current->name.other.len = strlen(buffer));
   160             break;
   162         case certEDIPartyName:
   163         case certIPAddress:
   164         case certOtherName:
   165         case certRegisterID:
   166         case certX400Address: {
   168             current->name.other.data =
   169                 PORT_ArenaAlloc (arena, strlen (buffer) + 2);
   170             if (current->name.other.data == NULL) {
   171                 GEN_BREAK (SECFailure);
   172             }
   174             PORT_Memcpy (current->name.other.data + 2, buffer,
   175                          strlen (buffer));
   176             /* This may not be accurate for all cases.  For now,
   177              * use this tag type */
   178             current->name.other.data[0] =
   179                 (char)(((current->type - 1) & 0x1f)| 0x80);
   180             current->name.other.data[1] = (char)strlen (buffer);
   181             current->name.other.len = strlen (buffer) + 2;
   182             break;
   183         }
   185         case certDirectoryName: {
   186             CERTName *directoryName = NULL;
   188             directoryName = CERT_AsciiToName (buffer);
   189             if (!directoryName) {
   190                 fprintf(stderr, "certutil: improperly formatted name: "
   191                         "\"%s\"\n", buffer);
   192                 break;
   193             }
   195             rv = CERT_CopyName (arena, &current->name.directoryName,
   196                                 directoryName);
   197             CERT_DestroyName (directoryName);
   199             break;
   200         }
   201         }
   202         if (rv != SECSuccess)
   203             break;
   204         current->l.next = &(namesList->l);
   205         current->l.prev = &(tail->l);
   206         tail->l.next = &(current->l);
   207         tail = current;
   209     }while (!onlyOne);
   211     if (rv != SECSuccess) {
   212         PORT_ArenaRelease (arena, mark);
   213         namesList = NULL;
   214     }
   215     return (namesList);
   216 }
   218 static CERTGeneralName *
   219 CreateGeneralName(PLArenaPool *arena)
   220 {
   221   return GetGeneralName(arena, NULL, PR_FALSE);
   222 }
   224 static SECStatus 
   225 GetString(PLArenaPool *arena, char *prompt, SECItem *value)
   226 {
   227     char buffer[251];
   228     char *buffPrt;
   230     buffer[0] = '\0';
   231     value->data = NULL;
   232     value->len = 0;
   234     puts (prompt);
   235     buffPrt = Gets_s (buffer, sizeof(buffer));
   236     /* returned NULL here treated the same way as empty string */
   237     if (buffPrt && strlen (buffer) > 0) {
   238         value->data = PORT_ArenaAlloc (arena, strlen (buffer));
   239         if (value->data == NULL) {
   240             PORT_SetError (SEC_ERROR_NO_MEMORY);
   241             return (SECFailure);
   242         }
   243         PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
   244     }
   245     return (SECSuccess);
   246 }
   248 static PRBool 
   249 GetYesNo(char *prompt) 
   250 {
   251     char buf[3];
   252     char *buffPrt;
   254     buf[0] = 'n';
   255     puts(prompt);
   256     buffPrt = Gets_s(buf, sizeof(buf));
   257     return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE;
   258 }
   260 /* Parses comma separated values out of the string pointed by nextPos.
   261  * Parsed value is compared to an array of possible values(valueArray).
   262  * If match is found, a value index is returned, otherwise returns SECFailue.
   263  * nextPos is set to the token after found comma separator or to NULL.
   264  * NULL in nextPos should be used as indication of the last parsed token.
   265  * A special value "critical" can be parsed out from the supplied sting.*/
   267 static SECStatus
   268 parseNextCmdInput(const char * const *valueArray, int *value,  char **nextPos,
   269                   PRBool *critical)
   270 {
   271     char *thisPos = *nextPos;
   272     int keyLen = 0;
   273     int arrIndex = 0;
   275     if (!valueArray || !value || !nextPos || !critical) {
   276         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   277         return SECFailure;
   278     }
   279     while (1) {
   280         if ((*nextPos = strchr(thisPos, ',')) == NULL) {
   281             keyLen = strlen(thisPos);
   282         } else {
   283             keyLen = *nextPos - thisPos;
   284             *nextPos += 1;
   285         }
   286         /* if critical keyword is found, go for another loop,
   287          * but check, if it is the last keyword of
   288          * the string.*/
   289         if (!strncmp("critical", thisPos, keyLen)) {
   290             *critical = PR_TRUE;
   291             if (*nextPos == NULL) {
   292                 return SECSuccess;
   293             }
   294             thisPos = *nextPos;
   295             continue;
   296         }
   297         break;
   298     }
   299     for (arrIndex = 0; valueArray[arrIndex]; arrIndex++) {
   300         if (!strncmp(valueArray[arrIndex], thisPos, keyLen)) {
   301             *value = arrIndex;
   302             return SECSuccess;
   303         }
   304     }
   305     PORT_SetError(SEC_ERROR_INVALID_ARGS);
   306     return SECFailure;
   307 }
   309 static const char * const
   310 keyUsageKeyWordArray[] = { "digitalSignature",
   311                            "nonRepudiation",
   312                            "keyEncipherment",
   313                            "dataEncipherment",
   314                            "keyAgreement",
   315                            "certSigning",
   316                            "crlSigning",
   317                            NULL};
   319 static SECStatus 
   320 AddKeyUsage (void *extHandle, const char *userSuppliedValue)
   321 {
   322     SECItem bitStringValue;
   323     unsigned char keyUsage = 0x0;
   324     char buffer[5];
   325     int value;
   326     char *nextPos = (char*)userSuppliedValue;
   327     PRBool isCriticalExt = PR_FALSE;
   329     if (!userSuppliedValue) {
   330         while (1) {
   331             if (PrintChoicesAndGetAnswer(
   332                     "\t\t0 - Digital Signature\n"
   333                     "\t\t1 - Non-repudiation\n"
   334                     "\t\t2 - Key encipherment\n"
   335                     "\t\t3 - Data encipherment\n"   
   336                     "\t\t4 - Key agreement\n"
   337                     "\t\t5 - Cert signing key\n"   
   338                     "\t\t6 - CRL signing key\n"
   339                     "\t\tOther to finish\n",
   340                     buffer, sizeof(buffer)) == SECFailure) {
   341                 return SECFailure;
   342             }
   343             value = PORT_Atoi (buffer);
   344             if (value < 0 || value > 6)
   345                 break;
   346             if (value == 0) {
   347                 /* Checking that zero value of variable 'value'
   348                  * corresponds to '0' input made by user */
   349                 char *chPtr = strchr(buffer, '0');
   350                 if (chPtr == NULL) {
   351                     continue;
   352                 }
   353             }
   354             keyUsage |= (0x80 >> value);
   355         }
   356         isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
   357     } else {
   358         while (1) {
   359             if (parseNextCmdInput(keyUsageKeyWordArray, &value, &nextPos,
   360                                   &isCriticalExt) == SECFailure) {
   361                 return SECFailure;
   362             }
   363             keyUsage |= (0x80 >> value);
   364             if (!nextPos)
   365                 break;
   366         }
   367     }
   369     bitStringValue.data = &keyUsage;
   370     bitStringValue.len = 1;
   372     return (CERT_EncodeAndAddBitStrExtension
   373             (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
   374              isCriticalExt));
   376 }
   379 static CERTOidSequence *
   380 CreateOidSequence(void)
   381 {
   382     CERTOidSequence *rv = (CERTOidSequence *)NULL;
   383     PLArenaPool *arena = (PLArenaPool *)NULL;
   385     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   386     if( (PLArenaPool *)NULL == arena ) {
   387         goto loser;
   388     }
   390     rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
   391     if( (CERTOidSequence *)NULL == rv ) {
   392         goto loser;
   393     }
   395     rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
   396     if( (SECItem **)NULL == rv->oids ) {
   397         goto loser;
   398     }
   400     rv->arena = arena;
   401     return rv;
   403 loser:
   404     if( (PLArenaPool *)NULL != arena ) {
   405         PORT_FreeArena(arena, PR_FALSE);
   406     }
   408     return (CERTOidSequence *)NULL;
   409 }
   411 static void
   412 DestroyOidSequence(CERTOidSequence *os)
   413 {
   414     if (os->arena) {
   415         PORT_FreeArena(os->arena, PR_FALSE);
   416     }
   417 }
   419 static SECStatus
   420 AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
   421 {
   422     SECItem **oids;
   423     PRUint32 count = 0;
   424     SECOidData *od;
   426     od = SECOID_FindOIDByTag(oidTag);
   427     if( (SECOidData *)NULL == od ) {
   428         return SECFailure;
   429     }
   431     for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
   432         if (*oids == &od->oid) {
   433             /* We already have this oid */
   434             return SECSuccess;
   435         }
   436         count++;
   437     }
   439     /* ArenaZRealloc */
   441     {
   442         PRUint32 i;
   444         oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
   445         if( (SECItem **)NULL == oids ) {
   446             return SECFailure;
   447         }
   449         for( i = 0; i < count; i++ ) {
   450             oids[i] = os->oids[i];
   451         }
   453         /* ArenaZFree(os->oids); */
   454     }
   456     os->oids = oids;
   457     os->oids[count] = &od->oid;
   459     return SECSuccess;
   460 }
   462 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
   464 const SEC_ASN1Template CERT_OidSeqTemplate[] = {
   465     { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
   466       SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
   467 };
   470 static SECItem *
   471 EncodeOidSequence(CERTOidSequence *os)
   472 {
   473     SECItem *rv;
   475     rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
   476     if( (SECItem *)NULL == rv ) {
   477         goto loser;
   478     }
   480     if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
   481         goto loser;
   482     }
   484     return rv;
   486 loser:
   487     return (SECItem *)NULL;
   488 }
   490 static const char * const 
   491 extKeyUsageKeyWordArray[] = { "serverAuth",
   492                               "clientAuth",
   493                               "codeSigning",
   494                               "emailProtection",
   495                               "timeStamp",
   496                               "ocspResponder",
   497                               "stepUp",
   498                               "msTrustListSigning",
   499                               NULL};
   501 static SECStatus 
   502 AddExtKeyUsage (void *extHandle, const char *userSuppliedValue)
   503 {
   504     char buffer[5];
   505     int value;
   506     CERTOidSequence *os;
   507     SECStatus rv;
   508     SECItem *item;
   509     PRBool isCriticalExt = PR_FALSE;
   510     char *nextPos = (char*)userSuppliedValue;
   512     os = CreateOidSequence();
   513     if( (CERTOidSequence *)NULL == os ) {
   514         return SECFailure;
   515     }
   517     while (1) {
   518         if (!userSuppliedValue) {
   519             if (PrintChoicesAndGetAnswer(
   520                     "\t\t0 - Server Auth\n"
   521                     "\t\t1 - Client Auth\n"
   522                     "\t\t2 - Code Signing\n"
   523                     "\t\t3 - Email Protection\n"
   524                     "\t\t4 - Timestamp\n"
   525                     "\t\t5 - OCSP Responder\n"
   526                     "\t\t6 - Step-up\n"
   527                     "\t\t7 - Microsoft Trust List Signing\n"
   528                     "\t\tOther to finish\n",
   529                     buffer, sizeof(buffer)) == SECFailure) {
   530                 GEN_BREAK(SECFailure);
   531             }
   532             value = PORT_Atoi(buffer);
   534             if (value == 0) {
   535                 /* Checking that zero value of variable 'value'
   536                  * corresponds to '0' input made by user */
   537                 char *chPtr = strchr(buffer, '0');
   538                 if (chPtr == NULL) {
   539                     continue;
   540                 }
   541             }
   542         } else {
   543             if (parseNextCmdInput(extKeyUsageKeyWordArray, &value, &nextPos,
   544                                   &isCriticalExt) == SECFailure) {
   545                 return SECFailure;
   546             }
   547         }
   549         switch( value ) {
   550         case 0:
   551             rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
   552             break;
   553         case 1:
   554             rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
   555             break;
   556         case 2:
   557             rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
   558             break;
   559         case 3:
   560             rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
   561             break;
   562         case 4:
   563             rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
   564             break;
   565         case 5:
   566             rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
   567             break;
   568         case 6:
   569             rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
   570             break;
   571         case 7:
   572             rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
   573             break;
   574         default:
   575             goto endloop;
   576         }
   578         if (userSuppliedValue && !nextPos)
   579             break;
   580         if( SECSuccess != rv )
   581             goto loser;
   582     }
   584 endloop:
   585     item = EncodeOidSequence(os);
   587     if (!userSuppliedValue) {
   588         isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
   589     }
   591     rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
   592                            isCriticalExt, PR_TRUE);
   593     /*FALLTHROUGH*/
   594 loser:
   595     DestroyOidSequence(os);
   596     return rv;
   597 }
   599 static const char * const
   600 nsCertTypeKeyWordArray[] = { "sslClient",
   601                              "sslServer",
   602                              "smime",
   603                              "objectSigning",
   604                              "Not!Used",
   605                              "sslCA",
   606                              "smimeCA",
   607                              "objectSigningCA",
   608                             NULL };
   610 static SECStatus 
   611 AddNscpCertType (void *extHandle, const char *userSuppliedValue)
   612 {
   613     SECItem bitStringValue;
   614     unsigned char keyUsage = 0x0;
   615     char buffer[5];
   616     int value;
   617     char *nextPos = (char*)userSuppliedValue;
   618     PRBool isCriticalExt = PR_FALSE;
   620     if (!userSuppliedValue) {
   621         while (1) {
   622             if (PrintChoicesAndGetAnswer(
   623                     "\t\t0 - SSL Client\n"
   624                     "\t\t1 - SSL Server\n"
   625                     "\t\t2 - S/MIME\n"
   626                     "\t\t3 - Object Signing\n"   
   627                     "\t\t4 - Reserved for future use\n"
   628                     "\t\t5 - SSL CA\n"   
   629                     "\t\t6 - S/MIME CA\n"
   630                     "\t\t7 - Object Signing CA\n"
   631                     "\t\tOther to finish\n",
   632                     buffer, sizeof(buffer)) == SECFailure) {
   633                 return SECFailure;
   634             }
   635             value = PORT_Atoi (buffer);
   636             if (value < 0 || value > 7)
   637                 break;
   638             if (value == 0) {
   639                 /* Checking that zero value of variable 'value'
   640                  * corresponds to '0' input made by user */
   641                 char *chPtr = strchr(buffer, '0');
   642                 if (chPtr == NULL) {
   643                     continue;
   644                 }
   645             }
   646             keyUsage |= (0x80 >> value);
   647         }
   648         isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
   649     } else {
   650         while (1) {
   651             if (parseNextCmdInput(nsCertTypeKeyWordArray, &value, &nextPos,
   652                                   &isCriticalExt) == SECFailure) {
   653                 return SECFailure;
   654             }
   655             keyUsage |= (0x80 >> value);
   656             if (!nextPos)
   657                 break;
   658         }
   659     }
   661     bitStringValue.data = &keyUsage;
   662     bitStringValue.len = 1;
   664     return (CERT_EncodeAndAddBitStrExtension
   665             (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
   666              isCriticalExt));
   668 }
   670 SECStatus
   671 GetOidFromString(PLArenaPool *arena, SECItem *to,
   672                  const char *from, size_t fromLen)
   673 {
   674     SECStatus rv;
   675     SECOidTag tag;
   676     SECOidData *coid;
   678     /* try dotted form first */
   679     rv = SEC_StringToOID(arena, to, from, fromLen);
   680     if (rv == SECSuccess) {
   681         return rv;
   682     }
   684     /* Check to see if it matches a name in our oid table.
   685      * SECOID_FindOIDByTag returns NULL if tag is out of bounds.
   686      */
   687     tag = SEC_OID_UNKNOWN;
   688     coid = SECOID_FindOIDByTag(tag);
   689     for ( ; coid; coid = SECOID_FindOIDByTag(++tag)) {
   690         if (PORT_Strncasecmp(from, coid->desc, fromLen) == 0) {
   691             break;
   692         }
   693     }
   694     if (coid == NULL) {
   695         /* none found */
   696         return SECFailure;
   697     }
   698     return SECITEM_CopyItem(arena, to, &coid->oid);
   699 }
   701 static SECStatus 
   702 AddSubjectAltNames(PLArenaPool *arena, CERTGeneralName **existingListp,
   703                    const char *constNames, CERTGeneralNameType type)
   704 {
   705     CERTGeneralName *nameList = NULL;
   706     CERTGeneralName *current = NULL;
   707     PRCList *prev = NULL;
   708     char *cp, *nextName = NULL;
   709     SECStatus rv = SECSuccess;
   710     PRBool readTypeFromName = (PRBool) (type == 0);
   711     char *names = NULL;
   713     if (constNames)
   714         names = PORT_Strdup(constNames);
   716     if (names == NULL) {
   717         return SECFailure;
   718     }
   720     /*
   721      * walk down the comma separated list of names. NOTE: there is
   722      * no sanity checks to see if the email address look like
   723      * email addresses.
   724      *
   725      * Each name may optionally be prefixed with a type: string.
   726      * If it isn't, the type from the previous name will be used.
   727      * If there wasn't a previous name yet, the type given
   728      * as a parameter to this function will be used.
   729      * If the type value is zero (undefined), we'll fail.
   730      */
   731     for (cp=names; cp; cp=nextName) {
   732         int len;
   733         char *oidString;
   734         char *nextComma;
   735         CERTName *name;
   736         PRStatus status;
   737         unsigned char *data;
   738         PRNetAddr addr;
   740         nextName = NULL;
   741         if (*cp == ',') {
   742             cp++;
   743         }
   744         nextComma = PORT_Strchr(cp, ',');
   745         if (nextComma) {
   746             *nextComma = 0;
   747             nextName = nextComma+1;
   748         }
   749         if ((*cp) == 0) {
   750             continue;
   751         }
   752         if (readTypeFromName) {
   753             char *save=cp;
   754             /* Because we already replaced nextComma with end-of-string,
   755              * a found colon belongs to the current name */
   756             cp = PORT_Strchr(cp, ':');
   757             if (cp) {
   758                 *cp = 0;
   759                 cp++;
   760                 type = CERT_GetGeneralNameTypeFromString(save);
   761                 if (*cp == 0) {
   762                     continue;
   763                 }
   764             } else {
   765                 if (type == 0) {
   766                     /* no type known yet */
   767                     rv = SECFailure;
   768                     break;
   769                 }
   770                 cp = save;
   771             }
   772         }
   774         current = PORT_ArenaZNew(arena, CERTGeneralName);
   775         if (!current) {
   776             rv = SECFailure;
   777             break;
   778         }
   780         current->type = type;
   781         switch (type) {
   782         /* string types */
   783         case certRFC822Name:
   784         case certDNSName:
   785         case certURI:
   786             current->name.other.data =
   787                 (unsigned char *) PORT_ArenaStrdup(arena,cp);
   788             current->name.other.len = PORT_Strlen(cp);
   789             break;
   790         /* unformated data types */
   791         case certX400Address:
   792         case certEDIPartyName:
   793             /* turn a string into a data and len */
   794             rv = SECFailure; /* punt on these for now */
   795             fprintf(stderr,"EDI Party Name and X.400 Address not supported\n");
   796             break;
   797         case certDirectoryName:
   798             /* certDirectoryName */
   799             name = CERT_AsciiToName(cp);
   800             if (name == NULL) {
   801                 rv = SECFailure;
   802                 fprintf(stderr, "Invalid Directory Name (\"%s\")\n", cp);
   803                 break;
   804             }
   805             rv = CERT_CopyName(arena,&current->name.directoryName,name);
   806             CERT_DestroyName(name);
   807             break;
   808         /* types that require more processing */
   809         case certIPAddress:
   810             /* convert the string to an ip address */
   811             status = PR_StringToNetAddr(cp, &addr);
   812             if (status != PR_SUCCESS) {
   813                 rv = SECFailure;
   814                 fprintf(stderr, "Invalid IP Address (\"%s\")\n", cp);
   815                 break;
   816             }
   818             if (PR_NetAddrFamily(&addr) == PR_AF_INET) {
   819                 len = sizeof(addr.inet.ip);
   820                 data = (unsigned char *)&addr.inet.ip;
   821             } else if (PR_NetAddrFamily(&addr) == PR_AF_INET6) {
   822                 len = sizeof(addr.ipv6.ip);
   823                 data = (unsigned char *)&addr.ipv6.ip;
   824             } else {
   825                 fprintf(stderr, "Invalid IP Family\n");
   826                 rv = SECFailure;
   827                 break;
   828             }
   829             current->name.other.data =  PORT_ArenaAlloc(arena, len);
   830             if (current->name.other.data == NULL) {
   831                 rv = SECFailure;
   832                 break;
   833             }
   834             current->name.other.len = len;
   835             PORT_Memcpy(current->name.other.data,data, len);
   836             break;
   837         case certRegisterID:
   838             rv = GetOidFromString(arena, &current->name.other, cp, strlen(cp));
   839             break;
   840         case certOtherName:
   841             oidString = cp;
   842             cp = PORT_Strchr(cp,';');
   843             if (cp == NULL) {
   844                 rv = SECFailure;
   845                 fprintf(stderr, "missing name in other name\n");
   846                 break;
   847             }
   848             *cp++ = 0;
   849             current->name.OthName.name.data =
   850                 (unsigned char *) PORT_ArenaStrdup(arena,cp);
   851             if (current->name.OthName.name.data == NULL) {
   852                 rv = SECFailure;
   853                 break;
   854             }
   855             current->name.OthName.name.len = PORT_Strlen(cp);
   856             rv = GetOidFromString(arena, &current->name.OthName.oid,
   857                                   oidString, strlen(oidString));
   858             break;
   859         default:
   860             rv = SECFailure;
   861             fprintf(stderr, "Missing or invalid Subject Alternate Name type\n");
   862             break;
   863         }
   864         if (rv == SECFailure) {
   865             break;
   866         }
   868         if (prev) {
   869             current->l.prev = prev;
   870             prev->next = &(current->l);
   871         } else {
   872             nameList = current;
   873         }
   874         prev = &(current->l);
   875     }
   876     PORT_Free(names);
   877     /* at this point nameList points to the head of a doubly linked,
   878      * but not yet circular, list and current points to its tail. */
   879     if (rv == SECSuccess && nameList) {
   880         if (*existingListp != NULL) {
   881             PRCList *existingprev;
   882             /* add nameList to the end of the existing list */
   883             existingprev = (*existingListp)->l.prev;
   884             (*existingListp)->l.prev = &(current->l);
   885             nameList->l.prev = existingprev;
   886             existingprev->next = &(nameList->l);
   887             current->l.next = &((*existingListp)->l);
   888         }
   889         else {
   890             /* make nameList circular and set it as the new existingList */
   891             nameList->l.prev = prev;
   892             current->l.next = &(nameList->l);
   893             *existingListp = nameList;
   894         }
   895     }
   896     return rv;
   897 }
   899 static SECStatus 
   900 AddEmailSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
   901                    const char *emailAddrs)
   902 {
   903     return AddSubjectAltNames(arena, existingListp, emailAddrs, 
   904                               certRFC822Name);
   905 }
   907 static SECStatus 
   908 AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
   909                  const char *dnsNames)
   910 {
   911     return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
   912 }
   914 static SECStatus 
   915 AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
   916                      const char *altNames)
   917 {
   918     return AddSubjectAltNames(arena, existingListp, altNames, 0);
   919 }
   921 static SECStatus 
   922 AddBasicConstraint(void *extHandle)
   923 {
   924     CERTBasicConstraints basicConstraint;    
   925     SECStatus rv;
   926     char buffer[10];
   927     PRBool yesNoAns;
   929     do {
   930         basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
   931         basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?");
   933         buffer[0] = '\0';
   934         if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
   935                                      "enter to skip [<0 for unlimited path]:",
   936                                      buffer, sizeof(buffer)) == SECFailure) {
   937             GEN_BREAK(SECFailure);
   938         }
   939         if (PORT_Strlen (buffer) > 0)
   940             basicConstraint.pathLenConstraint = PORT_Atoi (buffer);
   942         yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
   944         rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle,
   945 		 &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
   946 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
   947     } while (0);
   949     return (rv);
   950 }
   952 static SECStatus 
   953 AddNameConstraints(void *extHandle)
   954 {
   955     PLArenaPool              *arena = NULL;
   956     CERTNameConstraints      *constraints = NULL;
   958     CERTNameConstraint       *current = NULL;
   959     CERTNameConstraint       *last_permited = NULL;
   960     CERTNameConstraint       *last_excluded = NULL;
   961     SECStatus                rv = SECSuccess;
   963     char buffer[512];
   964     int intValue = 0;
   966     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   967     if (arena) {
   968       constraints = PORT_ArenaZNew(arena, CERTNameConstraints);
   969     }
   971     if (!arena || ! constraints) {
   972         SECU_PrintError(progName, "out of memory");
   973         return SECFailure;
   974     }
   976     constraints->permited = constraints->excluded = NULL;
   978     do {
   979         current = PORT_ArenaZNew(arena, CERTNameConstraint);
   980         if (!current) {
   981             GEN_BREAK(SECFailure);
   982         }
   984         (void) SEC_ASN1EncodeInteger(arena, &current->min, 0);
   986         if (!GetGeneralName(arena, &current->name, PR_TRUE)) {
   987             GEN_BREAK(SECFailure);
   988         }
   990         PrintChoicesAndGetAnswer("Type of Name Constraint?\n"
   991             "\t1 - permitted\n\t2 - excluded\n\tAny"
   992             "other number to finish\n\tChoice",
   993             buffer, sizeof(buffer));
   994         intValue = PORT_Atoi(buffer);
   995         switch (intValue) {
   996         case 1:
   997             if (constraints->permited == NULL) {
   998                 constraints->permited = last_permited = current;
   999             }
  1000             last_permited->l.next = &(current->l);
  1001             current->l.prev = &(last_permited->l);
  1002             last_permited = current;
  1003             break;
  1004         case 2:
  1005             if (constraints->excluded == NULL) {
  1006                 constraints->excluded = last_excluded = current;
  1008             last_excluded->l.next = &(current->l);
  1009             current->l.prev = &(last_excluded->l);
  1010             last_excluded = current;
  1011             break;
  1014         PR_snprintf(buffer, sizeof(buffer), "Add another entry to the"
  1015                     " Name Constraint Extension [y/N]");
  1017         if (GetYesNo (buffer) == 0) {
  1018             break;
  1021     } while (1);
  1023     if (rv == SECSuccess) {
  1024         int oidIdent = SEC_OID_X509_NAME_CONSTRAINTS;
  1026         PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1028         if (constraints->permited != NULL) {
  1029             last_permited->l.next = &(constraints->permited->l);
  1030             constraints->permited->l.prev = &(last_permited->l);
  1032         if (constraints->excluded != NULL) {
  1033             last_excluded->l.next = &(constraints->excluded->l);
  1034             constraints->excluded->l.prev = &(last_excluded->l);
  1037         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, constraints,
  1038                  yesNoAns, oidIdent,
  1039                  (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeNameConstraintsExtension);
  1041     if (arena)
  1042         PORT_FreeArena(arena, PR_FALSE);
  1043     return (rv);
  1046 static SECStatus 
  1047 AddAuthKeyID (void *extHandle)
  1049     CERTAuthKeyID *authKeyID = NULL;    
  1050     PLArenaPool *arena = NULL;
  1051     SECStatus rv = SECSuccess;
  1052     PRBool yesNoAns;
  1054     do {
  1055         arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1056         if ( !arena ) {
  1057             SECU_PrintError(progName, "out of memory");
  1058             GEN_BREAK (SECFailure);
  1061         if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0)
  1062             break;
  1064         authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
  1065         if (authKeyID == NULL) {
  1066             GEN_BREAK (SECFailure);
  1069         rv = GetString (arena, "Enter value for the key identifier fields,"
  1070                         "enter to omit:", &authKeyID->keyID);
  1071         if (rv != SECSuccess)
  1072             break;
  1074         SECU_SECItemHexStringToBinary(&authKeyID->keyID);
  1076         authKeyID->authCertIssuer = CreateGeneralName (arena);
  1077         if (authKeyID->authCertIssuer == NULL && 
  1078             SECFailure == PORT_GetError ())
  1079             break;
  1082         rv = GetString (arena, "Enter value for the authCertSerial field, "
  1083                         "enter to omit:", &authKeyID->authCertSerialNumber);
  1085         yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  1087         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  1088 		     authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID, 
  1089 		     (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
  1090         if (rv)
  1091             break;
  1093     } while (0);
  1094     if (arena)
  1095         PORT_FreeArena (arena, PR_FALSE);
  1096     return (rv);
  1099 static SECStatus 
  1100 AddSubjKeyID (void *extHandle)
  1102     SECItem keyID;
  1103     PLArenaPool *arena = NULL;
  1104     SECStatus rv = SECSuccess;
  1105     PRBool yesNoAns;
  1107     do {
  1108         arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1109         if ( !arena ) {
  1110             SECU_PrintError(progName, "out of memory");
  1111             GEN_BREAK (SECFailure);
  1113         printf("Adding Subject Key ID extension.\n");
  1115         rv = GetString (arena, "Enter value for the key identifier fields,"
  1116                         "enter to omit:", &keyID);
  1117         if (rv != SECSuccess)
  1118             break;
  1120         SECU_SECItemHexStringToBinary(&keyID);
  1122         yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  1124         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  1125 		     &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID, 
  1126 		     (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeSubjectKeyID);
  1127         if (rv)
  1128             break;
  1130     } while (0);
  1131     if (arena)
  1132         PORT_FreeArena (arena, PR_FALSE);
  1133     return (rv);
  1136 static SECStatus 
  1137 AddCrlDistPoint(void *extHandle)
  1139     PLArenaPool *arena = NULL;
  1140     CERTCrlDistributionPoints *crlDistPoints = NULL;
  1141     CRLDistributionPoint *current;
  1142     SECStatus rv = SECSuccess;
  1143     int count = 0, intValue;
  1144     char buffer[512];
  1146     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1147     if ( !arena )
  1148         return (SECFailure);
  1150     do {
  1151         current = NULL;
  1153         current = PORT_ArenaZNew(arena, CRLDistributionPoint);
  1154         if (current == NULL) {
  1155             GEN_BREAK (SECFailure);
  1158         /* Get the distributionPointName fields - this field is optional */
  1159         if (PrintChoicesAndGetAnswer(
  1160                 "Enter the type of the distribution point name:\n"
  1161                 "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
  1162                 "number to finish\n\t\tChoice: ",
  1163                 buffer, sizeof(buffer)) == SECFailure) {
  1164 	    GEN_BREAK (SECFailure);
  1166         intValue = PORT_Atoi (buffer);
  1167         switch (intValue) {
  1168         case generalName:
  1169             current->distPointType = intValue;
  1170             current->distPoint.fullName = CreateGeneralName (arena);
  1171             rv = PORT_GetError();
  1172             break;
  1174         case relativeDistinguishedName: {
  1175             CERTName *name;
  1177             current->distPointType = intValue;
  1178             puts ("Enter the relative name: ");
  1179             fflush (stdout);
  1180             if (Gets_s (buffer, sizeof(buffer)) == NULL) {
  1181                 GEN_BREAK (SECFailure);
  1183             /* For simplicity, use CERT_AsciiToName to converse from a string
  1184                to NAME, but we only interest in the first RDN */
  1185             name = CERT_AsciiToName (buffer);
  1186             if (!name) {
  1187                 GEN_BREAK (SECFailure);
  1189             rv = CERT_CopyRDN (arena, &current->distPoint.relativeName,
  1190                                name->rdns[0]);
  1191             CERT_DestroyName (name);
  1192             break;
  1195         if (rv != SECSuccess)
  1196             break;
  1198         /* Get the reason flags */
  1199         if (PrintChoicesAndGetAnswer(
  1200                 "\nSelect one of the following for the reason flags\n"
  1201                 "\t0 - unused\n\t1 - keyCompromise\n"
  1202                 "\t2 - caCompromise\n\t3 - affiliationChanged\n"
  1203                 "\t4 - superseded\n\t5 - cessationOfOperation\n"
  1204                 "\t6 - certificateHold\n"
  1205                 "\tAny other number to finish\t\tChoice: ",
  1206                 buffer, sizeof(buffer)) == SECFailure) {
  1207             GEN_BREAK(SECFailure);
  1209         intValue = PORT_Atoi (buffer);
  1210         if (intValue == 0) {
  1211             /* Checking that zero value of variable 'value'
  1212              * corresponds to '0' input made by user */
  1213             char *chPtr = strchr(buffer, '0');
  1214             if (chPtr == NULL) {
  1215                 intValue = -1;
  1218         if (intValue >= 0 && intValue <8) {
  1219             current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
  1220             if (current->reasons.data == NULL) {
  1221                 GEN_BREAK (SECFailure);
  1223             *current->reasons.data = (char)(0x80 >> intValue);
  1224             current->reasons.len = 1;
  1226         puts ("Enter value for the CRL Issuer name:\n");
  1227         current->crlIssuer = CreateGeneralName (arena);
  1228         if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
  1229             break;
  1231         if (crlDistPoints == NULL) {
  1232             crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
  1233             if (crlDistPoints == NULL) {
  1234                 GEN_BREAK (SECFailure);
  1238         crlDistPoints->distPoints =
  1239             PORT_ArenaGrow (arena, crlDistPoints->distPoints,
  1240                             sizeof (*crlDistPoints->distPoints) * count,
  1241                             sizeof (*crlDistPoints->distPoints) *(count + 1));
  1242         if (crlDistPoints->distPoints == NULL) {
  1243             GEN_BREAK (SECFailure);
  1246         crlDistPoints->distPoints[count] = current;
  1247         ++count;
  1248         if (GetYesNo("Enter another value for the CRLDistributionPoint "
  1249                       "extension [y/N]?") == 0) {
  1250             /* Add null to the end to mark end of data */
  1251             crlDistPoints->distPoints =
  1252                 PORT_ArenaGrow(arena, crlDistPoints->distPoints,
  1253 			   sizeof (*crlDistPoints->distPoints) * count,
  1254 			   sizeof (*crlDistPoints->distPoints) *(count + 1));
  1255             crlDistPoints->distPoints[count] = NULL;    
  1256             break;
  1260     } while (1);
  1262     if (rv == SECSuccess) {
  1263         PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  1265         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  1266 		 crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
  1267 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
  1269     if (arena)
  1270         PORT_FreeArena (arena, PR_FALSE);
  1271     return (rv);
  1276 static SECStatus 
  1277 AddPolicyConstraints(void *extHandle)
  1279     CERTCertificatePolicyConstraints *policyConstr;
  1280     PLArenaPool *arena = NULL;
  1281     SECStatus rv = SECSuccess;
  1282     SECItem *item, *dummy;
  1283     char buffer[512];
  1284     int value;
  1285     PRBool yesNoAns;
  1286     PRBool skipExt = PR_TRUE;
  1288     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1289     if ( !arena ) {
  1290         SECU_PrintError(progName, "out of memory");
  1291         return SECFailure;
  1294     policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
  1295     if (policyConstr == NULL) {
  1296         SECU_PrintError(progName, "out of memory");
  1297         goto loser;
  1300     if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
  1301                "of certs in path\nbefore explicit policy is required\n"
  1302                "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
  1303         goto loser;
  1306     if (PORT_Strlen(buffer)) {
  1307         value = PORT_Atoi(buffer);
  1308 	if (value < 0) {
  1309             goto loser;
  1311         item = &policyConstr->explicitPolicySkipCerts;
  1312         dummy = SEC_ASN1EncodeInteger(arena, item, value);
  1313         if (!dummy) {
  1314             goto loser;
  1316         skipExt = PR_FALSE;
  1319     if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
  1320                "the number of certs in path\n"
  1321 	       "after which policy mapping is not allowed\n"
  1322                "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
  1323         goto loser;
  1326     if (PORT_Strlen(buffer)) {
  1327         value = PORT_Atoi(buffer);
  1328 	if (value < 0) {
  1329             goto loser;
  1331         item = &policyConstr->inhibitMappingSkipCerts;
  1332         dummy = SEC_ASN1EncodeInteger(arena, item, value);
  1333         if (!dummy) {
  1334             goto loser;
  1336         skipExt = PR_FALSE;
  1340     if (!skipExt) {
  1341         yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1343         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
  1344 	     yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
  1345 	     (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension);
  1346     } else {
  1347 	fprintf(stdout, "Policy Constraint extensions must contain "
  1348                         "at least one policy field\n");
  1349 	rv = SECFailure;
  1352 loser:
  1353     if (arena) {
  1354         PORT_FreeArena (arena, PR_FALSE);
  1356     return (rv);
  1360 static SECStatus 
  1361 AddInhibitAnyPolicy(void *extHandle)
  1363     CERTCertificateInhibitAny certInhibitAny;
  1364     PLArenaPool *arena = NULL;
  1365     SECStatus rv = SECSuccess;
  1366     SECItem *item, *dummy;
  1367     char buffer[10];
  1368     int value;
  1369     PRBool yesNoAns;
  1372     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1373     if ( !arena ) {
  1374         SECU_PrintError(progName, "out of memory");
  1375         return SECFailure;
  1378     if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
  1379                                  "permitted to use anyPolicy.\n"
  1380                                  "(press Enter for 0)",
  1381                                  buffer, sizeof(buffer)) == SECFailure) {
  1382         goto loser;
  1385     item = &certInhibitAny.inhibitAnySkipCerts;
  1386     value = PORT_Atoi(buffer);
  1387     if (value < 0) {
  1388         goto loser;
  1390     dummy = SEC_ASN1EncodeInteger(arena, item, value);
  1391     if (!dummy) {
  1392         goto loser;
  1395     yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1397     rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
  1398 		 yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
  1399 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension);
  1400 loser:
  1401     if (arena) {
  1402         PORT_FreeArena (arena, PR_FALSE);
  1404     return (rv);
  1408 static SECStatus 
  1409 AddPolicyMappings(void *extHandle)
  1411     CERTPolicyMap **policyMapArr = NULL;
  1412     CERTPolicyMap *current;
  1413     PLArenaPool *arena = NULL;
  1414     SECStatus rv = SECSuccess;
  1415     int count = 0;
  1416     char buffer[512];
  1418     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1419     if ( !arena ) {
  1420         SECU_PrintError(progName, "out of memory");
  1421         return SECFailure;
  1424     do {
  1425         if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
  1426                                      "decimal format) for Issuer Domain Policy",
  1427                                      buffer, sizeof(buffer)) == SECFailure) {
  1428             GEN_BREAK (SECFailure);
  1431         current = PORT_ArenaZNew(arena, CERTPolicyMap);
  1432         if (current == NULL) {
  1433             GEN_BREAK(SECFailure);
  1436         rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
  1437         if (rv == SECFailure) {
  1438             GEN_BREAK(SECFailure);
  1441         if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
  1442                                      "Subject Domain Policy",
  1443                                      buffer, sizeof(buffer)) == SECFailure) {
  1444             GEN_BREAK (SECFailure);
  1447         rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
  1448         if (rv == SECFailure) {
  1449             GEN_BREAK(SECFailure);
  1452         if (policyMapArr == NULL) {
  1453             policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
  1454             if (policyMapArr == NULL) {
  1455                 GEN_BREAK (SECFailure);
  1459         policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
  1460                                          sizeof (current) * count,
  1461                                          sizeof (current) *(count + 1));
  1462         if (policyMapArr == NULL) {
  1463             GEN_BREAK (SECFailure);
  1466         policyMapArr[count] = current;
  1467         ++count;
  1469         if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
  1470             /* Add null to the end to mark end of data */
  1471             policyMapArr = PORT_ArenaGrow (arena, policyMapArr,
  1472                                            sizeof (current) * count,
  1473                                            sizeof (current) *(count + 1));
  1474             if (policyMapArr == NULL) {
  1475                 GEN_BREAK (SECFailure);
  1477             policyMapArr[count] = NULL;        
  1478             break;
  1481     } while (1);
  1483     if (rv == SECSuccess) {
  1484         CERTCertificatePolicyMappings mappings;
  1485         PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1487         mappings.arena = arena;
  1488         mappings.policyMaps = policyMapArr;
  1489         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
  1490 		 yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
  1491 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension);
  1493     if (arena)
  1494         PORT_FreeArena (arena, PR_FALSE);
  1495     return (rv);
  1498 enum PoliciQualifierEnum {
  1499     cpsPointer = 1,
  1500     userNotice = 2
  1501 };
  1504 static CERTPolicyQualifier **
  1505 RequestPolicyQualifiers(PLArenaPool *arena, SECItem *policyID)
  1507     CERTPolicyQualifier **policyQualifArr = NULL;
  1508     CERTPolicyQualifier *current;
  1509     SECStatus rv = SECSuccess;
  1510     int count = 0;
  1511     char buffer[512];
  1512     void *mark;
  1513     SECOidData *oid = NULL;
  1514     int intValue = 0;
  1515     int inCount = 0;
  1517     PORT_Assert(arena);
  1518     mark = PORT_ArenaMark(arena);
  1519     do {
  1520         current = PORT_ArenaZNew(arena, CERTPolicyQualifier);
  1521         if (current == NULL) {
  1522             GEN_BREAK(SECFailure);
  1525         /* Get the accessMethod fields */
  1526         SECU_PrintObjectID(stdout, policyID,
  1527                            "Choose the type of qualifier for policy" , 0);
  1529         if (PrintChoicesAndGetAnswer(
  1530                 "\t1 - CPS Pointer qualifier\n"
  1531                 "\t2 - User notice qualifier\n"
  1532                 "\tAny other number to finish\n"
  1533                 "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) {
  1534             GEN_BREAK (SECFailure);
  1536         intValue = PORT_Atoi(buffer);
  1537         switch (intValue) {
  1538         case cpsPointer: {
  1539             SECItem input;
  1541             oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
  1542             if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
  1543 				     buffer, sizeof(buffer)) == SECFailure) {
  1544                 GEN_BREAK (SECFailure);
  1546             input.len = PORT_Strlen(buffer);
  1547             input.data = (void*)PORT_ArenaStrdup(arena, buffer);
  1548             if (input.data == NULL ||
  1549 	        SEC_ASN1EncodeItem(arena, &current->qualifierValue, &input,
  1550 			       SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) {
  1551                 GEN_BREAK (SECFailure);
  1553             break;
  1555         case userNotice: {
  1556             SECItem **noticeNumArr;
  1557             CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
  1558             if (!notice) {
  1559                 GEN_BREAK(SECFailure);
  1562             oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
  1564             if (GetYesNo("\t add a User Notice reference? [y/N]")) {
  1566                 if (PrintChoicesAndGetAnswer("Enter user organization string: ",
  1567 				 buffer, sizeof(buffer)) == SECFailure) {
  1568                     GEN_BREAK (SECFailure);
  1571                 notice->noticeReference.organization.type = siAsciiString;
  1572                 notice->noticeReference.organization.len =
  1573                     PORT_Strlen(buffer);
  1574                 notice->noticeReference.organization.data =
  1575                     (void*)PORT_ArenaStrdup(arena, buffer);
  1578                 noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
  1579 		if (!noticeNumArr) {
  1580                     GEN_BREAK (SECFailure);
  1583                 do {
  1584                     SECItem *noticeNum;
  1586                     noticeNum = PORT_ArenaZNew(arena, SECItem);
  1588                     if (PrintChoicesAndGetAnswer(
  1589 				      "Enter User Notice reference number "
  1590 				      "(or -1 to quit): ",
  1591                                       buffer, sizeof(buffer)) == SECFailure) {
  1592                         GEN_BREAK (SECFailure);
  1595                     intValue = PORT_Atoi(buffer);
  1596 		    if (noticeNum == NULL) {
  1597 			if (intValue < 0) {
  1598 			    fprintf(stdout, "a noticeReference must have at "
  1599                                     "least one reference number\n");
  1600                             GEN_BREAK (SECFailure);
  1602 		    } else {
  1603 			if (intValue >= 0) {
  1604                             noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr,
  1605 					      sizeof (current) * inCount,
  1606 					      sizeof (current) *(inCount + 1));
  1607                             if (noticeNumArr == NULL) {
  1608                                 GEN_BREAK (SECFailure);
  1610 			} else {
  1611 			    break;
  1614                     if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
  1615                         GEN_BREAK (SECFailure);
  1617                     noticeNumArr[inCount++] = noticeNum;
  1618                     noticeNumArr[inCount] = NULL;
  1620                 } while (1);
  1621                 if (rv == SECFailure) {
  1622                     GEN_BREAK(SECFailure);
  1624                 notice->noticeReference.noticeNumbers = noticeNumArr;
  1625                 rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
  1626                                                 &notice->derNoticeReference);
  1627                 if (rv == SECFailure) {
  1628                     GEN_BREAK(SECFailure);
  1631             if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
  1632                 /* Getting only 200 bytes - RFC limitation */
  1633                 if (PrintChoicesAndGetAnswer(
  1634                         "\t", buffer, 200) == SECFailure) {
  1635                         GEN_BREAK (SECFailure);
  1637                 notice->displayText.type = siAsciiString;
  1638                 notice->displayText.len = PORT_Strlen(buffer);
  1639                 notice->displayText.data = 
  1640 		                        (void*)PORT_ArenaStrdup(arena, buffer);
  1641 		if (notice->displayText.data == NULL) {
  1642 		    GEN_BREAK(SECFailure);
  1646             rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
  1647             if (rv == SECFailure) {
  1648                 GEN_BREAK(SECFailure);
  1651             break;
  1654         if (rv == SECFailure || oid == NULL ||
  1655             SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid) 
  1656 	    == SECFailure) {
  1657             GEN_BREAK (SECFailure);
  1660         if (!policyQualifArr) {
  1661             policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *);
  1662         } else {
  1663 	    policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr,
  1664                                          sizeof (current) * count,
  1665                                          sizeof (current) *(count + 1));
  1667         if (policyQualifArr == NULL) {
  1668             GEN_BREAK (SECFailure);
  1671         policyQualifArr[count] = current;
  1672         ++count;
  1674         if (!GetYesNo ("Enter another policy qualifier [y/N]")) {
  1675             /* Add null to the end to mark end of data */
  1676             policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
  1677                                               sizeof (current) * count,
  1678                                               sizeof (current) *(count + 1));
  1679             if (policyQualifArr == NULL) {
  1680                 GEN_BREAK (SECFailure);
  1682             policyQualifArr[count] = NULL;        
  1683             break;
  1686     } while (1);
  1688     if (rv != SECSuccess) {
  1689         PORT_ArenaRelease (arena, mark);
  1690         policyQualifArr = NULL;
  1692     return (policyQualifArr);
  1695 static SECStatus 
  1696 AddCertPolicies(void *extHandle)
  1698     CERTPolicyInfo **certPoliciesArr = NULL;
  1699     CERTPolicyInfo *current;
  1700     PLArenaPool *arena = NULL;
  1701     SECStatus rv = SECSuccess;
  1702     int count = 0;
  1703     char buffer[512];
  1705     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1706     if ( !arena ) {
  1707         SECU_PrintError(progName, "out of memory");
  1708         return SECFailure;
  1711     do {
  1712         current = PORT_ArenaZNew(arena, CERTPolicyInfo);
  1713         if (current == NULL) {
  1714             GEN_BREAK(SECFailure);
  1717         if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
  1718                                      "(dotted decimal format)\n"
  1719 				     "or \"any\" for AnyPolicy:",
  1720                                      buffer, sizeof(buffer)) == SECFailure) {
  1721             GEN_BREAK (SECFailure);
  1724 	if (strncmp(buffer, "any", 3) == 0) {
  1725 	    /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
  1726 	    strcpy(buffer, "OID.2.5.29.32.0");
  1728         rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
  1730         if (rv == SECFailure) {
  1731             GEN_BREAK(SECFailure);
  1734         current->policyQualifiers = 
  1735             RequestPolicyQualifiers(arena, &current->policyID); 
  1737         if (!certPoliciesArr) {
  1738             certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *);
  1739         } else {
  1740 	    certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
  1741                                          sizeof (current) * count,
  1742                                          sizeof (current) *(count + 1));
  1744         if (certPoliciesArr == NULL) {
  1745             GEN_BREAK (SECFailure);
  1748         certPoliciesArr[count] = current;
  1749         ++count;
  1751         if (!GetYesNo ("Enter another PolicyInformation field [y/N]?")) {
  1752             /* Add null to the end to mark end of data */
  1753             certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
  1754                                               sizeof (current) * count,
  1755                                               sizeof (current) *(count + 1));
  1756             if (certPoliciesArr == NULL) {
  1757                 GEN_BREAK (SECFailure);
  1759             certPoliciesArr[count] = NULL;        
  1760             break;
  1763     } while (1);
  1765     if (rv == SECSuccess) {
  1766         CERTCertificatePolicies policies;
  1767         PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1769         policies.arena = arena;
  1770         policies.policyInfos = certPoliciesArr;
  1772         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
  1773 		 yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
  1774 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
  1776     if (arena)
  1777 	PORT_FreeArena(arena, PR_FALSE);
  1778     return (rv);
  1781 enum AuthInfoAccessTypesEnum {
  1782     caIssuers = 1,
  1783     ocsp = 2
  1784 };
  1786 enum SubjInfoAccessTypesEnum {
  1787     caRepository = 1,
  1788     timeStamping = 2
  1789 };
  1791 /* Encode and add an AIA or SIA extension */
  1792 static SECStatus 
  1793 AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
  1795     CERTAuthInfoAccess **infoAccArr = NULL;
  1796     CERTAuthInfoAccess *current;
  1797     PLArenaPool *arena = NULL;
  1798     SECStatus rv = SECSuccess;
  1799     int count = 0;
  1800     char buffer[512];
  1801     SECOidData *oid = NULL;
  1802     int intValue = 0;
  1804     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1805     if ( !arena ) {
  1806         SECU_PrintError(progName, "out of memory");
  1807         return SECFailure;
  1810     do {
  1811         current = NULL;
  1812         current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
  1813         if (current == NULL) {
  1814             GEN_BREAK(SECFailure);
  1817         /* Get the accessMethod fields */
  1818         if (addSIAExt) {
  1819             if (isCACert) {
  1820                 puts("Adding \"CA Repository\" access method type for "
  1821                     "Subject Information Access extension:\n");
  1822                 intValue = caRepository;
  1823             } else {
  1824                 puts("Adding \"Time Stamping Services\" access method type for "
  1825                     "Subject Information Access extension:\n");
  1826                 intValue = timeStamping;
  1828         } else {
  1829             PrintChoicesAndGetAnswer("Enter access method type "
  1830                 "for Authority Information Access extension:\n"
  1831                 "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
  1832                 "other number to finish\n\tChoice",
  1833                 buffer, sizeof(buffer));
  1834             intValue = PORT_Atoi(buffer);
  1836         if (addSIAExt) {
  1837             switch (intValue) {
  1838               case caRepository:
  1839                   oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
  1840                   break;
  1842               case timeStamping:
  1843                   oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
  1844                   break;
  1846         } else {
  1847             switch (intValue) {
  1848               case caIssuers:
  1849                   oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
  1850                   break;
  1852               case ocsp:
  1853                   oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
  1854                   break;
  1857         if (oid == NULL ||
  1858             SECITEM_CopyItem(arena, &current->method, &oid->oid) 
  1859 	    == SECFailure) {
  1860             GEN_BREAK (SECFailure);
  1863         current->location = CreateGeneralName(arena);
  1864         if (!current->location) {
  1865             GEN_BREAK(SECFailure);
  1868         if (infoAccArr == NULL) {
  1869             infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *);
  1870         } else {
  1871 	    infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
  1872                                      sizeof (current) * count,
  1873                                      sizeof (current) *(count + 1));
  1875         if (infoAccArr == NULL) {
  1876             GEN_BREAK (SECFailure);
  1879         infoAccArr[count] = current;
  1880         ++count;
  1882         PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
  1883                     " Information Access extension [y/N]",
  1884                     (addSIAExt) ? "Subject" : "Authority");
  1886         if (GetYesNo (buffer) == 0) {
  1887             /* Add null to the end to mark end of data */
  1888             infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
  1889                                          sizeof (current) * count,
  1890                                          sizeof (current) *(count + 1));
  1891             if (infoAccArr == NULL) {
  1892                 GEN_BREAK (SECFailure);
  1894             infoAccArr[count] = NULL;        
  1895             break;
  1898     } while (1);
  1900     if (rv == SECSuccess) {
  1901         int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
  1903         PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1905         if (addSIAExt) {
  1906             oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
  1908         rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
  1909 		 yesNoAns, oidIdent,
  1910 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
  1912     if (arena)
  1913         PORT_FreeArena(arena, PR_FALSE);
  1914     return (rv);
  1917 /* Example of valid input:
  1918  *     1.2.3.4:critical:/tmp/abc,5.6.7.8:not-critical:/tmp/xyz
  1919  */
  1920 static SECStatus
  1921 parseNextGenericExt(const char *nextExtension, const char **oid, int *oidLen,
  1922                     const char **crit, int *critLen,
  1923                     const char **filename, int *filenameLen,
  1924                     const char **next)
  1926     const char *nextColon;
  1927     const char *nextComma;
  1928     const char *iter = nextExtension;
  1930     if (!iter || !*iter)
  1931         return SECFailure;
  1933     /* Require colons at earlier positions than nextComma (or end of string ) */
  1934     nextComma = strchr(iter, ',');
  1936     *oid = iter;
  1937     nextColon = strchr(iter, ':');
  1938     if (!nextColon || (nextComma && nextColon > nextComma))
  1939         return SECFailure;
  1940     *oidLen = (nextColon - *oid);
  1942     if (!*oidLen)
  1943         return SECFailure;
  1945     iter = nextColon;
  1946     ++iter;
  1948     *crit = iter;
  1949     nextColon = strchr(iter, ':');
  1950     if (!nextColon || (nextComma && nextColon > nextComma))
  1951         return SECFailure;
  1952     *critLen = (nextColon - *crit);
  1954     if (!*critLen)
  1955         return SECFailure;
  1957     iter = nextColon;
  1958     ++iter;
  1960     *filename = iter;
  1961     if (nextComma) {
  1962         *filenameLen = (nextComma - *filename);
  1963         iter = nextComma;
  1964         ++iter;
  1965         *next = iter;
  1966     } else {
  1967         *filenameLen = strlen(*filename);
  1968         *next = NULL;
  1971     if (!*filenameLen)
  1972         return SECFailure;
  1974     return SECSuccess;
  1977 SECStatus
  1978 AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
  1979               certutilExtnList extList, const char *extGeneric)
  1981     SECStatus rv = SECSuccess;
  1982     char *errstring = NULL;
  1983     const char *nextExtension = NULL;
  1985     do {
  1986         /* Add key usage extension */
  1987         if (extList[ext_keyUsage].activated) {
  1988             rv = AddKeyUsage(extHandle, extList[ext_keyUsage].arg);
  1989             if (rv) {
  1990 		errstring = "KeyUsage";
  1991                 break;
  1995         /* Add extended key usage extension */
  1996         if (extList[ext_extKeyUsage].activated) {
  1997             rv = AddExtKeyUsage(extHandle, extList[ext_extKeyUsage].arg);
  1998             if (rv) {
  1999 		errstring = "ExtendedKeyUsage";
  2000                 break;
  2004         /* Add basic constraint extension */
  2005         if (extList[ext_basicConstraint].activated) {
  2006             rv = AddBasicConstraint(extHandle);
  2007             if (rv) {
  2008 		errstring = "BasicConstraint";
  2009                 break;
  2013         /* Add name constraints extension */
  2014         if (extList[ext_nameConstraints].activated) {
  2015             rv = AddNameConstraints(extHandle);
  2016             if (rv) {
  2017                 errstring = "NameConstraints";
  2018                 break;
  2022         if (extList[ext_authorityKeyID].activated) {
  2023             rv = AddAuthKeyID(extHandle);
  2024             if (rv) {
  2025 		errstring = "AuthorityKeyID";
  2026                 break;
  2030         if (extList[ext_subjectKeyID].activated) {
  2031             rv = AddSubjKeyID(extHandle);
  2032             if (rv) {
  2033 		errstring = "SubjectKeyID";
  2034                 break;
  2038         if (extList[ext_CRLDistPts].activated) {
  2039             rv = AddCrlDistPoint(extHandle);
  2040             if (rv) {
  2041 		errstring = "CRLDistPoints";
  2042                 break;
  2046         if (extList[ext_NSCertType].activated) {
  2047             rv = AddNscpCertType(extHandle, extList[ext_NSCertType].arg);
  2048             if (rv) {
  2049 		errstring = "NSCertType";
  2050                 break;
  2054         if (extList[ext_authInfoAcc].activated ||
  2055             extList[ext_subjInfoAcc].activated) {
  2056             rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc].activated,
  2057 	                       extList[ext_basicConstraint].activated);
  2058             if (rv) {
  2059 		errstring = "InformationAccess";
  2060                 break;
  2064         if (extList[ext_certPolicies].activated) {
  2065             rv = AddCertPolicies(extHandle);
  2066             if (rv) {
  2067 		errstring = "Policies";
  2068                 break;
  2072         if (extList[ext_policyMappings].activated) {
  2073             rv = AddPolicyMappings(extHandle);
  2074             if (rv) {
  2075 		errstring = "PolicyMappings";
  2076                 break;
  2080         if (extList[ext_policyConstr].activated) {
  2081             rv = AddPolicyConstraints(extHandle);
  2082             if (rv) {
  2083 		errstring = "PolicyConstraints";
  2084                 break;
  2088         if (extList[ext_inhibitAnyPolicy].activated) {
  2089             rv = AddInhibitAnyPolicy(extHandle);
  2090             if (rv) {
  2091 		errstring = "InhibitAnyPolicy";
  2092                 break;
  2096         if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
  2097             PLArenaPool *arena;
  2098             CERTGeneralName *namelist = NULL;
  2099             SECItem item = { 0, NULL, 0 };
  2101             arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2102             if (arena == NULL) {
  2103                 rv = SECFailure;
  2104                 break;
  2107             rv = SECSuccess;
  2109             if (emailAddrs) {
  2110                 rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
  2113             if (dnsNames) {
  2114                 rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
  2117             if (extList[ext_subjectAltName].activated) {
  2118                 rv |= AddGeneralSubjectAlt(arena, &namelist, 
  2119                                            extList[ext_subjectAltName].arg);
  2122             if (rv == SECSuccess) {
  2123 		rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
  2124 	        if (rv == SECSuccess) {
  2125                     rv = CERT_AddExtension(extHandle,
  2126                                           SEC_OID_X509_SUBJECT_ALT_NAME,
  2127                                           &item, PR_FALSE, PR_TRUE);
  2130 	    PORT_FreeArena(arena, PR_FALSE);
  2131 	    if (rv) {
  2132                 errstring = "SubjectAltName";
  2133                 break;
  2136     } while (0);
  2138     if (rv != SECSuccess) {
  2139         SECU_PrintError(progName, "Problem creating %s extension", errstring);
  2142     nextExtension = extGeneric;
  2143     while (nextExtension && *nextExtension) {
  2144         SECItem oid_item, value;
  2145         PRBool isCritical;
  2146         const char *oid, *crit, *filename, *next;
  2147         int oidLen, critLen, filenameLen;
  2148         PRFileDesc *inFile = NULL;
  2149         char *zeroTerminatedFilename = NULL;
  2151         rv = parseNextGenericExt(nextExtension, &oid, &oidLen, &crit, &critLen,
  2152                                  &filename, &filenameLen, &next);
  2153         if (rv!= SECSuccess) {
  2154             SECU_PrintError(progName,
  2155                             "error parsing generic extension parameter %s",
  2156                             nextExtension);
  2157             break;
  2159         oid_item.data = NULL;
  2160         oid_item.len = 0;
  2161         rv = GetOidFromString(NULL, &oid_item, oid, oidLen);
  2162         if (rv != SECSuccess) {
  2163             SECU_PrintError(progName, "malformed extension OID %s", nextExtension);
  2164             break;
  2166         if (!strncmp("critical", crit, critLen)) {
  2167             isCritical = PR_TRUE;
  2168         } else if (!strncmp("not-critical", crit, critLen)) {
  2169             isCritical = PR_FALSE;
  2170         } else {
  2171             rv = SECFailure;
  2172             SECU_PrintError(progName, "expected 'critical' or 'not-critical'");
  2173             break;
  2175         zeroTerminatedFilename = PL_strndup(filename, filenameLen);
  2176         if (!zeroTerminatedFilename) {
  2177             rv = SECFailure;
  2178             SECU_PrintError(progName, "out of memory");
  2179             break;
  2181         rv = SECFailure;
  2182         inFile = PR_Open(zeroTerminatedFilename, PR_RDONLY, 0);
  2183         if (inFile) {
  2184             rv = SECU_ReadDERFromFile(&value, inFile, PR_FALSE, PR_FALSE);
  2185             PR_Close(inFile);
  2186             inFile = NULL;
  2188         if (rv != SECSuccess) {
  2189             SECU_PrintError(progName, "unable to read file %s",
  2190                             zeroTerminatedFilename);
  2192         PL_strfree(zeroTerminatedFilename);
  2193         if (rv != SECSuccess) {
  2194             break;
  2196         rv = CERT_AddExtensionByOID(extHandle, &oid_item, &value, isCritical,
  2197                                     PR_FALSE /*copyData*/);
  2198         if (rv != SECSuccess) {
  2199             SECITEM_FreeItem(&oid_item, PR_FALSE);
  2200             SECITEM_FreeItem(&value, PR_FALSE);
  2201             SECU_PrintError(progName, "failed to add extension %s", nextExtension);
  2202             break;
  2204         nextExtension = next;
  2207     return rv;

mercurial