security/nss/cmd/certutil/certext.c

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:bdd35af432c4
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/. */
4
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>
14
15 #if defined(WIN32)
16 #include "fcntl.h"
17 #include "io.h"
18 #endif
19
20 #include "secutil.h"
21
22 #if defined(XP_UNIX)
23 #include <unistd.h>
24 #endif
25
26 #include "cert.h"
27 #include "xconst.h"
28 #include "prprf.h"
29 #include "certutil.h"
30 #include "genname.h"
31 #include "prnetdb.h"
32
33 #define GEN_BREAK(e) rv=e; break;
34
35 static char *
36 Gets_s(char *buff, size_t size) {
37 char *str;
38
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 }
67
68
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 }
81
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;
92
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 }
124
125 if (intValue == 0)
126 break;
127
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 }
141
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;
161
162 case certEDIPartyName:
163 case certIPAddress:
164 case certOtherName:
165 case certRegisterID:
166 case certX400Address: {
167
168 current->name.other.data =
169 PORT_ArenaAlloc (arena, strlen (buffer) + 2);
170 if (current->name.other.data == NULL) {
171 GEN_BREAK (SECFailure);
172 }
173
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 }
184
185 case certDirectoryName: {
186 CERTName *directoryName = NULL;
187
188 directoryName = CERT_AsciiToName (buffer);
189 if (!directoryName) {
190 fprintf(stderr, "certutil: improperly formatted name: "
191 "\"%s\"\n", buffer);
192 break;
193 }
194
195 rv = CERT_CopyName (arena, &current->name.directoryName,
196 directoryName);
197 CERT_DestroyName (directoryName);
198
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;
208
209 }while (!onlyOne);
210
211 if (rv != SECSuccess) {
212 PORT_ArenaRelease (arena, mark);
213 namesList = NULL;
214 }
215 return (namesList);
216 }
217
218 static CERTGeneralName *
219 CreateGeneralName(PLArenaPool *arena)
220 {
221 return GetGeneralName(arena, NULL, PR_FALSE);
222 }
223
224 static SECStatus
225 GetString(PLArenaPool *arena, char *prompt, SECItem *value)
226 {
227 char buffer[251];
228 char *buffPrt;
229
230 buffer[0] = '\0';
231 value->data = NULL;
232 value->len = 0;
233
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 }
247
248 static PRBool
249 GetYesNo(char *prompt)
250 {
251 char buf[3];
252 char *buffPrt;
253
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 }
259
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.*/
266
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;
274
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 }
308
309 static const char * const
310 keyUsageKeyWordArray[] = { "digitalSignature",
311 "nonRepudiation",
312 "keyEncipherment",
313 "dataEncipherment",
314 "keyAgreement",
315 "certSigning",
316 "crlSigning",
317 NULL};
318
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;
328
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 }
368
369 bitStringValue.data = &keyUsage;
370 bitStringValue.len = 1;
371
372 return (CERT_EncodeAndAddBitStrExtension
373 (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
374 isCriticalExt));
375
376 }
377
378
379 static CERTOidSequence *
380 CreateOidSequence(void)
381 {
382 CERTOidSequence *rv = (CERTOidSequence *)NULL;
383 PLArenaPool *arena = (PLArenaPool *)NULL;
384
385 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
386 if( (PLArenaPool *)NULL == arena ) {
387 goto loser;
388 }
389
390 rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
391 if( (CERTOidSequence *)NULL == rv ) {
392 goto loser;
393 }
394
395 rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
396 if( (SECItem **)NULL == rv->oids ) {
397 goto loser;
398 }
399
400 rv->arena = arena;
401 return rv;
402
403 loser:
404 if( (PLArenaPool *)NULL != arena ) {
405 PORT_FreeArena(arena, PR_FALSE);
406 }
407
408 return (CERTOidSequence *)NULL;
409 }
410
411 static void
412 DestroyOidSequence(CERTOidSequence *os)
413 {
414 if (os->arena) {
415 PORT_FreeArena(os->arena, PR_FALSE);
416 }
417 }
418
419 static SECStatus
420 AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
421 {
422 SECItem **oids;
423 PRUint32 count = 0;
424 SECOidData *od;
425
426 od = SECOID_FindOIDByTag(oidTag);
427 if( (SECOidData *)NULL == od ) {
428 return SECFailure;
429 }
430
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 }
438
439 /* ArenaZRealloc */
440
441 {
442 PRUint32 i;
443
444 oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
445 if( (SECItem **)NULL == oids ) {
446 return SECFailure;
447 }
448
449 for( i = 0; i < count; i++ ) {
450 oids[i] = os->oids[i];
451 }
452
453 /* ArenaZFree(os->oids); */
454 }
455
456 os->oids = oids;
457 os->oids[count] = &od->oid;
458
459 return SECSuccess;
460 }
461
462 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
463
464 const SEC_ASN1Template CERT_OidSeqTemplate[] = {
465 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
466 SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
467 };
468
469
470 static SECItem *
471 EncodeOidSequence(CERTOidSequence *os)
472 {
473 SECItem *rv;
474
475 rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
476 if( (SECItem *)NULL == rv ) {
477 goto loser;
478 }
479
480 if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
481 goto loser;
482 }
483
484 return rv;
485
486 loser:
487 return (SECItem *)NULL;
488 }
489
490 static const char * const
491 extKeyUsageKeyWordArray[] = { "serverAuth",
492 "clientAuth",
493 "codeSigning",
494 "emailProtection",
495 "timeStamp",
496 "ocspResponder",
497 "stepUp",
498 "msTrustListSigning",
499 NULL};
500
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;
511
512 os = CreateOidSequence();
513 if( (CERTOidSequence *)NULL == os ) {
514 return SECFailure;
515 }
516
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);
533
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 }
548
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 }
577
578 if (userSuppliedValue && !nextPos)
579 break;
580 if( SECSuccess != rv )
581 goto loser;
582 }
583
584 endloop:
585 item = EncodeOidSequence(os);
586
587 if (!userSuppliedValue) {
588 isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
589 }
590
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 }
598
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 };
609
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;
619
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 }
660
661 bitStringValue.data = &keyUsage;
662 bitStringValue.len = 1;
663
664 return (CERT_EncodeAndAddBitStrExtension
665 (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
666 isCriticalExt));
667
668 }
669
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;
677
678 /* try dotted form first */
679 rv = SEC_StringToOID(arena, to, from, fromLen);
680 if (rv == SECSuccess) {
681 return rv;
682 }
683
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 }
700
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;
712
713 if (constNames)
714 names = PORT_Strdup(constNames);
715
716 if (names == NULL) {
717 return SECFailure;
718 }
719
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;
739
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 }
773
774 current = PORT_ArenaZNew(arena, CERTGeneralName);
775 if (!current) {
776 rv = SECFailure;
777 break;
778 }
779
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 }
817
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 }
867
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 }
898
899 static SECStatus
900 AddEmailSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
901 const char *emailAddrs)
902 {
903 return AddSubjectAltNames(arena, existingListp, emailAddrs,
904 certRFC822Name);
905 }
906
907 static SECStatus
908 AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
909 const char *dnsNames)
910 {
911 return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
912 }
913
914 static SECStatus
915 AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
916 const char *altNames)
917 {
918 return AddSubjectAltNames(arena, existingListp, altNames, 0);
919 }
920
921 static SECStatus
922 AddBasicConstraint(void *extHandle)
923 {
924 CERTBasicConstraints basicConstraint;
925 SECStatus rv;
926 char buffer[10];
927 PRBool yesNoAns;
928
929 do {
930 basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
931 basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?");
932
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);
941
942 yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
943
944 rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle,
945 &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
946 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
947 } while (0);
948
949 return (rv);
950 }
951
952 static SECStatus
953 AddNameConstraints(void *extHandle)
954 {
955 PLArenaPool *arena = NULL;
956 CERTNameConstraints *constraints = NULL;
957
958 CERTNameConstraint *current = NULL;
959 CERTNameConstraint *last_permited = NULL;
960 CERTNameConstraint *last_excluded = NULL;
961 SECStatus rv = SECSuccess;
962
963 char buffer[512];
964 int intValue = 0;
965
966 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
967 if (arena) {
968 constraints = PORT_ArenaZNew(arena, CERTNameConstraints);
969 }
970
971 if (!arena || ! constraints) {
972 SECU_PrintError(progName, "out of memory");
973 return SECFailure;
974 }
975
976 constraints->permited = constraints->excluded = NULL;
977
978 do {
979 current = PORT_ArenaZNew(arena, CERTNameConstraint);
980 if (!current) {
981 GEN_BREAK(SECFailure);
982 }
983
984 (void) SEC_ASN1EncodeInteger(arena, &current->min, 0);
985
986 if (!GetGeneralName(arena, &current->name, PR_TRUE)) {
987 GEN_BREAK(SECFailure);
988 }
989
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;
1007 }
1008 last_excluded->l.next = &(current->l);
1009 current->l.prev = &(last_excluded->l);
1010 last_excluded = current;
1011 break;
1012 }
1013
1014 PR_snprintf(buffer, sizeof(buffer), "Add another entry to the"
1015 " Name Constraint Extension [y/N]");
1016
1017 if (GetYesNo (buffer) == 0) {
1018 break;
1019 }
1020
1021 } while (1);
1022
1023 if (rv == SECSuccess) {
1024 int oidIdent = SEC_OID_X509_NAME_CONSTRAINTS;
1025
1026 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1027
1028 if (constraints->permited != NULL) {
1029 last_permited->l.next = &(constraints->permited->l);
1030 constraints->permited->l.prev = &(last_permited->l);
1031 }
1032 if (constraints->excluded != NULL) {
1033 last_excluded->l.next = &(constraints->excluded->l);
1034 constraints->excluded->l.prev = &(last_excluded->l);
1035 }
1036
1037 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, constraints,
1038 yesNoAns, oidIdent,
1039 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeNameConstraintsExtension);
1040 }
1041 if (arena)
1042 PORT_FreeArena(arena, PR_FALSE);
1043 return (rv);
1044 }
1045
1046 static SECStatus
1047 AddAuthKeyID (void *extHandle)
1048 {
1049 CERTAuthKeyID *authKeyID = NULL;
1050 PLArenaPool *arena = NULL;
1051 SECStatus rv = SECSuccess;
1052 PRBool yesNoAns;
1053
1054 do {
1055 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1056 if ( !arena ) {
1057 SECU_PrintError(progName, "out of memory");
1058 GEN_BREAK (SECFailure);
1059 }
1060
1061 if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0)
1062 break;
1063
1064 authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
1065 if (authKeyID == NULL) {
1066 GEN_BREAK (SECFailure);
1067 }
1068
1069 rv = GetString (arena, "Enter value for the key identifier fields,"
1070 "enter to omit:", &authKeyID->keyID);
1071 if (rv != SECSuccess)
1072 break;
1073
1074 SECU_SECItemHexStringToBinary(&authKeyID->keyID);
1075
1076 authKeyID->authCertIssuer = CreateGeneralName (arena);
1077 if (authKeyID->authCertIssuer == NULL &&
1078 SECFailure == PORT_GetError ())
1079 break;
1080
1081
1082 rv = GetString (arena, "Enter value for the authCertSerial field, "
1083 "enter to omit:", &authKeyID->authCertSerialNumber);
1084
1085 yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
1086
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;
1092
1093 } while (0);
1094 if (arena)
1095 PORT_FreeArena (arena, PR_FALSE);
1096 return (rv);
1097 }
1098
1099 static SECStatus
1100 AddSubjKeyID (void *extHandle)
1101 {
1102 SECItem keyID;
1103 PLArenaPool *arena = NULL;
1104 SECStatus rv = SECSuccess;
1105 PRBool yesNoAns;
1106
1107 do {
1108 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1109 if ( !arena ) {
1110 SECU_PrintError(progName, "out of memory");
1111 GEN_BREAK (SECFailure);
1112 }
1113 printf("Adding Subject Key ID extension.\n");
1114
1115 rv = GetString (arena, "Enter value for the key identifier fields,"
1116 "enter to omit:", &keyID);
1117 if (rv != SECSuccess)
1118 break;
1119
1120 SECU_SECItemHexStringToBinary(&keyID);
1121
1122 yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
1123
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;
1129
1130 } while (0);
1131 if (arena)
1132 PORT_FreeArena (arena, PR_FALSE);
1133 return (rv);
1134 }
1135
1136 static SECStatus
1137 AddCrlDistPoint(void *extHandle)
1138 {
1139 PLArenaPool *arena = NULL;
1140 CERTCrlDistributionPoints *crlDistPoints = NULL;
1141 CRLDistributionPoint *current;
1142 SECStatus rv = SECSuccess;
1143 int count = 0, intValue;
1144 char buffer[512];
1145
1146 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1147 if ( !arena )
1148 return (SECFailure);
1149
1150 do {
1151 current = NULL;
1152
1153 current = PORT_ArenaZNew(arena, CRLDistributionPoint);
1154 if (current == NULL) {
1155 GEN_BREAK (SECFailure);
1156 }
1157
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);
1165 }
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;
1173
1174 case relativeDistinguishedName: {
1175 CERTName *name;
1176
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);
1182 }
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);
1188 }
1189 rv = CERT_CopyRDN (arena, &current->distPoint.relativeName,
1190 name->rdns[0]);
1191 CERT_DestroyName (name);
1192 break;
1193 }
1194 }
1195 if (rv != SECSuccess)
1196 break;
1197
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);
1208 }
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;
1216 }
1217 }
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);
1222 }
1223 *current->reasons.data = (char)(0x80 >> intValue);
1224 current->reasons.len = 1;
1225 }
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;
1230
1231 if (crlDistPoints == NULL) {
1232 crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
1233 if (crlDistPoints == NULL) {
1234 GEN_BREAK (SECFailure);
1235 }
1236 }
1237
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);
1244 }
1245
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;
1257 }
1258
1259
1260 } while (1);
1261
1262 if (rv == SECSuccess) {
1263 PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
1264
1265 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1266 crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
1267 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
1268 }
1269 if (arena)
1270 PORT_FreeArena (arena, PR_FALSE);
1271 return (rv);
1272 }
1273
1274
1275
1276 static SECStatus
1277 AddPolicyConstraints(void *extHandle)
1278 {
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;
1287
1288 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1289 if ( !arena ) {
1290 SECU_PrintError(progName, "out of memory");
1291 return SECFailure;
1292 }
1293
1294 policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
1295 if (policyConstr == NULL) {
1296 SECU_PrintError(progName, "out of memory");
1297 goto loser;
1298 }
1299
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;
1304 }
1305
1306 if (PORT_Strlen(buffer)) {
1307 value = PORT_Atoi(buffer);
1308 if (value < 0) {
1309 goto loser;
1310 }
1311 item = &policyConstr->explicitPolicySkipCerts;
1312 dummy = SEC_ASN1EncodeInteger(arena, item, value);
1313 if (!dummy) {
1314 goto loser;
1315 }
1316 skipExt = PR_FALSE;
1317 }
1318
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;
1324 }
1325
1326 if (PORT_Strlen(buffer)) {
1327 value = PORT_Atoi(buffer);
1328 if (value < 0) {
1329 goto loser;
1330 }
1331 item = &policyConstr->inhibitMappingSkipCerts;
1332 dummy = SEC_ASN1EncodeInteger(arena, item, value);
1333 if (!dummy) {
1334 goto loser;
1335 }
1336 skipExt = PR_FALSE;
1337 }
1338
1339
1340 if (!skipExt) {
1341 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1342
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;
1350 }
1351
1352 loser:
1353 if (arena) {
1354 PORT_FreeArena (arena, PR_FALSE);
1355 }
1356 return (rv);
1357 }
1358
1359
1360 static SECStatus
1361 AddInhibitAnyPolicy(void *extHandle)
1362 {
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;
1370
1371
1372 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1373 if ( !arena ) {
1374 SECU_PrintError(progName, "out of memory");
1375 return SECFailure;
1376 }
1377
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;
1383 }
1384
1385 item = &certInhibitAny.inhibitAnySkipCerts;
1386 value = PORT_Atoi(buffer);
1387 if (value < 0) {
1388 goto loser;
1389 }
1390 dummy = SEC_ASN1EncodeInteger(arena, item, value);
1391 if (!dummy) {
1392 goto loser;
1393 }
1394
1395 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1396
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);
1403 }
1404 return (rv);
1405 }
1406
1407
1408 static SECStatus
1409 AddPolicyMappings(void *extHandle)
1410 {
1411 CERTPolicyMap **policyMapArr = NULL;
1412 CERTPolicyMap *current;
1413 PLArenaPool *arena = NULL;
1414 SECStatus rv = SECSuccess;
1415 int count = 0;
1416 char buffer[512];
1417
1418 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1419 if ( !arena ) {
1420 SECU_PrintError(progName, "out of memory");
1421 return SECFailure;
1422 }
1423
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);
1429 }
1430
1431 current = PORT_ArenaZNew(arena, CERTPolicyMap);
1432 if (current == NULL) {
1433 GEN_BREAK(SECFailure);
1434 }
1435
1436 rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
1437 if (rv == SECFailure) {
1438 GEN_BREAK(SECFailure);
1439 }
1440
1441 if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
1442 "Subject Domain Policy",
1443 buffer, sizeof(buffer)) == SECFailure) {
1444 GEN_BREAK (SECFailure);
1445 }
1446
1447 rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
1448 if (rv == SECFailure) {
1449 GEN_BREAK(SECFailure);
1450 }
1451
1452 if (policyMapArr == NULL) {
1453 policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
1454 if (policyMapArr == NULL) {
1455 GEN_BREAK (SECFailure);
1456 }
1457 }
1458
1459 policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
1460 sizeof (current) * count,
1461 sizeof (current) *(count + 1));
1462 if (policyMapArr == NULL) {
1463 GEN_BREAK (SECFailure);
1464 }
1465
1466 policyMapArr[count] = current;
1467 ++count;
1468
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);
1476 }
1477 policyMapArr[count] = NULL;
1478 break;
1479 }
1480
1481 } while (1);
1482
1483 if (rv == SECSuccess) {
1484 CERTCertificatePolicyMappings mappings;
1485 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1486
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);
1492 }
1493 if (arena)
1494 PORT_FreeArena (arena, PR_FALSE);
1495 return (rv);
1496 }
1497
1498 enum PoliciQualifierEnum {
1499 cpsPointer = 1,
1500 userNotice = 2
1501 };
1502
1503
1504 static CERTPolicyQualifier **
1505 RequestPolicyQualifiers(PLArenaPool *arena, SECItem *policyID)
1506 {
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;
1516
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);
1523 }
1524
1525 /* Get the accessMethod fields */
1526 SECU_PrintObjectID(stdout, policyID,
1527 "Choose the type of qualifier for policy" , 0);
1528
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);
1535 }
1536 intValue = PORT_Atoi(buffer);
1537 switch (intValue) {
1538 case cpsPointer: {
1539 SECItem input;
1540
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);
1545 }
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);
1552 }
1553 break;
1554 }
1555 case userNotice: {
1556 SECItem **noticeNumArr;
1557 CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
1558 if (!notice) {
1559 GEN_BREAK(SECFailure);
1560 }
1561
1562 oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
1563
1564 if (GetYesNo("\t add a User Notice reference? [y/N]")) {
1565
1566 if (PrintChoicesAndGetAnswer("Enter user organization string: ",
1567 buffer, sizeof(buffer)) == SECFailure) {
1568 GEN_BREAK (SECFailure);
1569 }
1570
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);
1576
1577
1578 noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
1579 if (!noticeNumArr) {
1580 GEN_BREAK (SECFailure);
1581 }
1582
1583 do {
1584 SECItem *noticeNum;
1585
1586 noticeNum = PORT_ArenaZNew(arena, SECItem);
1587
1588 if (PrintChoicesAndGetAnswer(
1589 "Enter User Notice reference number "
1590 "(or -1 to quit): ",
1591 buffer, sizeof(buffer)) == SECFailure) {
1592 GEN_BREAK (SECFailure);
1593 }
1594
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);
1601 }
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);
1609 }
1610 } else {
1611 break;
1612 }
1613 }
1614 if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
1615 GEN_BREAK (SECFailure);
1616 }
1617 noticeNumArr[inCount++] = noticeNum;
1618 noticeNumArr[inCount] = NULL;
1619
1620 } while (1);
1621 if (rv == SECFailure) {
1622 GEN_BREAK(SECFailure);
1623 }
1624 notice->noticeReference.noticeNumbers = noticeNumArr;
1625 rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
1626 &notice->derNoticeReference);
1627 if (rv == SECFailure) {
1628 GEN_BREAK(SECFailure);
1629 }
1630 }
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);
1636 }
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);
1643 }
1644 }
1645
1646 rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
1647 if (rv == SECFailure) {
1648 GEN_BREAK(SECFailure);
1649 }
1650
1651 break;
1652 }
1653 }
1654 if (rv == SECFailure || oid == NULL ||
1655 SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid)
1656 == SECFailure) {
1657 GEN_BREAK (SECFailure);
1658 }
1659
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));
1666 }
1667 if (policyQualifArr == NULL) {
1668 GEN_BREAK (SECFailure);
1669 }
1670
1671 policyQualifArr[count] = current;
1672 ++count;
1673
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);
1681 }
1682 policyQualifArr[count] = NULL;
1683 break;
1684 }
1685
1686 } while (1);
1687
1688 if (rv != SECSuccess) {
1689 PORT_ArenaRelease (arena, mark);
1690 policyQualifArr = NULL;
1691 }
1692 return (policyQualifArr);
1693 }
1694
1695 static SECStatus
1696 AddCertPolicies(void *extHandle)
1697 {
1698 CERTPolicyInfo **certPoliciesArr = NULL;
1699 CERTPolicyInfo *current;
1700 PLArenaPool *arena = NULL;
1701 SECStatus rv = SECSuccess;
1702 int count = 0;
1703 char buffer[512];
1704
1705 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1706 if ( !arena ) {
1707 SECU_PrintError(progName, "out of memory");
1708 return SECFailure;
1709 }
1710
1711 do {
1712 current = PORT_ArenaZNew(arena, CERTPolicyInfo);
1713 if (current == NULL) {
1714 GEN_BREAK(SECFailure);
1715 }
1716
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);
1722 }
1723
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");
1727 }
1728 rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
1729
1730 if (rv == SECFailure) {
1731 GEN_BREAK(SECFailure);
1732 }
1733
1734 current->policyQualifiers =
1735 RequestPolicyQualifiers(arena, &current->policyID);
1736
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));
1743 }
1744 if (certPoliciesArr == NULL) {
1745 GEN_BREAK (SECFailure);
1746 }
1747
1748 certPoliciesArr[count] = current;
1749 ++count;
1750
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);
1758 }
1759 certPoliciesArr[count] = NULL;
1760 break;
1761 }
1762
1763 } while (1);
1764
1765 if (rv == SECSuccess) {
1766 CERTCertificatePolicies policies;
1767 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1768
1769 policies.arena = arena;
1770 policies.policyInfos = certPoliciesArr;
1771
1772 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
1773 yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
1774 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
1775 }
1776 if (arena)
1777 PORT_FreeArena(arena, PR_FALSE);
1778 return (rv);
1779 }
1780
1781 enum AuthInfoAccessTypesEnum {
1782 caIssuers = 1,
1783 ocsp = 2
1784 };
1785
1786 enum SubjInfoAccessTypesEnum {
1787 caRepository = 1,
1788 timeStamping = 2
1789 };
1790
1791 /* Encode and add an AIA or SIA extension */
1792 static SECStatus
1793 AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
1794 {
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;
1803
1804 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1805 if ( !arena ) {
1806 SECU_PrintError(progName, "out of memory");
1807 return SECFailure;
1808 }
1809
1810 do {
1811 current = NULL;
1812 current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
1813 if (current == NULL) {
1814 GEN_BREAK(SECFailure);
1815 }
1816
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;
1827 }
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);
1835 }
1836 if (addSIAExt) {
1837 switch (intValue) {
1838 case caRepository:
1839 oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
1840 break;
1841
1842 case timeStamping:
1843 oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
1844 break;
1845 }
1846 } else {
1847 switch (intValue) {
1848 case caIssuers:
1849 oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
1850 break;
1851
1852 case ocsp:
1853 oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
1854 break;
1855 }
1856 }
1857 if (oid == NULL ||
1858 SECITEM_CopyItem(arena, &current->method, &oid->oid)
1859 == SECFailure) {
1860 GEN_BREAK (SECFailure);
1861 }
1862
1863 current->location = CreateGeneralName(arena);
1864 if (!current->location) {
1865 GEN_BREAK(SECFailure);
1866 }
1867
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));
1874 }
1875 if (infoAccArr == NULL) {
1876 GEN_BREAK (SECFailure);
1877 }
1878
1879 infoAccArr[count] = current;
1880 ++count;
1881
1882 PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
1883 " Information Access extension [y/N]",
1884 (addSIAExt) ? "Subject" : "Authority");
1885
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);
1893 }
1894 infoAccArr[count] = NULL;
1895 break;
1896 }
1897
1898 } while (1);
1899
1900 if (rv == SECSuccess) {
1901 int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
1902
1903 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1904
1905 if (addSIAExt) {
1906 oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
1907 }
1908 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
1909 yesNoAns, oidIdent,
1910 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
1911 }
1912 if (arena)
1913 PORT_FreeArena(arena, PR_FALSE);
1914 return (rv);
1915 }
1916
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)
1925 {
1926 const char *nextColon;
1927 const char *nextComma;
1928 const char *iter = nextExtension;
1929
1930 if (!iter || !*iter)
1931 return SECFailure;
1932
1933 /* Require colons at earlier positions than nextComma (or end of string ) */
1934 nextComma = strchr(iter, ',');
1935
1936 *oid = iter;
1937 nextColon = strchr(iter, ':');
1938 if (!nextColon || (nextComma && nextColon > nextComma))
1939 return SECFailure;
1940 *oidLen = (nextColon - *oid);
1941
1942 if (!*oidLen)
1943 return SECFailure;
1944
1945 iter = nextColon;
1946 ++iter;
1947
1948 *crit = iter;
1949 nextColon = strchr(iter, ':');
1950 if (!nextColon || (nextComma && nextColon > nextComma))
1951 return SECFailure;
1952 *critLen = (nextColon - *crit);
1953
1954 if (!*critLen)
1955 return SECFailure;
1956
1957 iter = nextColon;
1958 ++iter;
1959
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;
1969 }
1970
1971 if (!*filenameLen)
1972 return SECFailure;
1973
1974 return SECSuccess;
1975 }
1976
1977 SECStatus
1978 AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
1979 certutilExtnList extList, const char *extGeneric)
1980 {
1981 SECStatus rv = SECSuccess;
1982 char *errstring = NULL;
1983 const char *nextExtension = NULL;
1984
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;
1992 }
1993 }
1994
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;
2001 }
2002 }
2003
2004 /* Add basic constraint extension */
2005 if (extList[ext_basicConstraint].activated) {
2006 rv = AddBasicConstraint(extHandle);
2007 if (rv) {
2008 errstring = "BasicConstraint";
2009 break;
2010 }
2011 }
2012
2013 /* Add name constraints extension */
2014 if (extList[ext_nameConstraints].activated) {
2015 rv = AddNameConstraints(extHandle);
2016 if (rv) {
2017 errstring = "NameConstraints";
2018 break;
2019 }
2020 }
2021
2022 if (extList[ext_authorityKeyID].activated) {
2023 rv = AddAuthKeyID(extHandle);
2024 if (rv) {
2025 errstring = "AuthorityKeyID";
2026 break;
2027 }
2028 }
2029
2030 if (extList[ext_subjectKeyID].activated) {
2031 rv = AddSubjKeyID(extHandle);
2032 if (rv) {
2033 errstring = "SubjectKeyID";
2034 break;
2035 }
2036 }
2037
2038 if (extList[ext_CRLDistPts].activated) {
2039 rv = AddCrlDistPoint(extHandle);
2040 if (rv) {
2041 errstring = "CRLDistPoints";
2042 break;
2043 }
2044 }
2045
2046 if (extList[ext_NSCertType].activated) {
2047 rv = AddNscpCertType(extHandle, extList[ext_NSCertType].arg);
2048 if (rv) {
2049 errstring = "NSCertType";
2050 break;
2051 }
2052 }
2053
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;
2061 }
2062 }
2063
2064 if (extList[ext_certPolicies].activated) {
2065 rv = AddCertPolicies(extHandle);
2066 if (rv) {
2067 errstring = "Policies";
2068 break;
2069 }
2070 }
2071
2072 if (extList[ext_policyMappings].activated) {
2073 rv = AddPolicyMappings(extHandle);
2074 if (rv) {
2075 errstring = "PolicyMappings";
2076 break;
2077 }
2078 }
2079
2080 if (extList[ext_policyConstr].activated) {
2081 rv = AddPolicyConstraints(extHandle);
2082 if (rv) {
2083 errstring = "PolicyConstraints";
2084 break;
2085 }
2086 }
2087
2088 if (extList[ext_inhibitAnyPolicy].activated) {
2089 rv = AddInhibitAnyPolicy(extHandle);
2090 if (rv) {
2091 errstring = "InhibitAnyPolicy";
2092 break;
2093 }
2094 }
2095
2096 if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
2097 PLArenaPool *arena;
2098 CERTGeneralName *namelist = NULL;
2099 SECItem item = { 0, NULL, 0 };
2100
2101 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2102 if (arena == NULL) {
2103 rv = SECFailure;
2104 break;
2105 }
2106
2107 rv = SECSuccess;
2108
2109 if (emailAddrs) {
2110 rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
2111 }
2112
2113 if (dnsNames) {
2114 rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
2115 }
2116
2117 if (extList[ext_subjectAltName].activated) {
2118 rv |= AddGeneralSubjectAlt(arena, &namelist,
2119 extList[ext_subjectAltName].arg);
2120 }
2121
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);
2128 }
2129 }
2130 PORT_FreeArena(arena, PR_FALSE);
2131 if (rv) {
2132 errstring = "SubjectAltName";
2133 break;
2134 }
2135 }
2136 } while (0);
2137
2138 if (rv != SECSuccess) {
2139 SECU_PrintError(progName, "Problem creating %s extension", errstring);
2140 }
2141
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;
2150
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;
2158 }
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;
2165 }
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;
2174 }
2175 zeroTerminatedFilename = PL_strndup(filename, filenameLen);
2176 if (!zeroTerminatedFilename) {
2177 rv = SECFailure;
2178 SECU_PrintError(progName, "out of memory");
2179 break;
2180 }
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;
2187 }
2188 if (rv != SECSuccess) {
2189 SECU_PrintError(progName, "unable to read file %s",
2190 zeroTerminatedFilename);
2191 }
2192 PL_strfree(zeroTerminatedFilename);
2193 if (rv != SECSuccess) {
2194 break;
2195 }
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;
2203 }
2204 nextExtension = next;
2205 }
2206
2207 return rv;
2208 }

mercurial