Bug Summary

File:root/firefox-clang/security/nss/cmd/certutil/certext.c
Warning:line 1143, column 9
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name certext.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/certutil/certutil_certutil -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/certutil/certutil_certutil -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D NSPR20 -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/cmd/certutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/certutil/certutil_certutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/security/nss/cmd/certutil/certext.c
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_UNIX1)
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 rv = e; \
35 break;
36
37static char *
38Gets_s(char *buff, size_t size)
39{
40 char *str;
41
42 if (buff == NULL((void*)0) || size < 1) {
43 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/cmd/certutil/certext.c"
, 43))
;
44 return NULL((void*)0);
45 }
46 if ((str = fgets(buff, size, stdinstdin)) != NULL((void*)0)) {
47 int len = PORT_Strlen(str)strlen(str);
48 /*
49 * fgets() automatically converts native text file
50 * line endings to '\n'. As defensive programming
51 * (just in case fgets has a bug or we put stdin in
52 * binary mode by mistake), we handle three native
53 * text file line endings here:
54 * '\n' Unix (including Linux and Mac OS X)
55 * '\r''\n' DOS/Windows & OS/2
56 * '\r' Mac OS Classic
57 * len can not be less then 1, since in case with
58 * empty string it has at least '\n' in the buffer
59 */
60 if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
61 buff[len - 1] = '\0';
62 if (len > 1 && buff[len - 2] == '\r')
63 buff[len - 2] = '\0';
64 }
65 } else {
66 buff[0] = '\0';
67 }
68 return str;
69}
70
71static SECStatus
72PrintChoicesAndGetAnswer(char *str, char *rBuff, int rSize)
73{
74 fputs(str, stdoutstdout);
75 fputs(" > ", stdoutstdout);
76 fflush(stdoutstdout);
77 if (Gets_s(rBuff, rSize) == NULL((void*)0)) {
78 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INPUT_LEN);
79 return SECFailure;
80 }
81 return SECSuccess;
82}
83
84static CERTGeneralName *
85GetGeneralName(PLArenaPool *arena, CERTGeneralName *useExistingName, PRBool onlyOne)
86{
87 CERTGeneralName *namesList = NULL((void*)0);
88 CERTGeneralName *current;
89 CERTGeneralName *tail = NULL((void*)0);
90 SECStatus rv = SECSuccess;
91 int intValue;
92 char buffer[512];
93 void *mark;
94
95 PORT_Assert(arena)((arena) ? ((void)0) : PR_Assert("arena", "/root/firefox-clang/security/nss/cmd/certutil/certext.c"
, 95))
;
96 mark = PORT_ArenaMarkPORT_ArenaMark_Util(arena);
97 do {
98 if (PrintChoicesAndGetAnswer(
99 "\nSelect one of the following general name type: \n"
100 "\t2 - rfc822Name\n"
101 "\t3 - dnsName\n"
102 "\t5 - directoryName\n"
103 "\t7 - uniformResourceidentifier\n"
104 "\t8 - ipAddress\n"
105 "\t9 - registerID\n"
106 "\tAny other number to finish\n"
107 "\t\tChoice:",
108 buffer, sizeof(buffer)) == SECFailure) {
109 GEN_BREAK(SECFailure)rv = SECFailure; break;;
110 }
111 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
112 /*
113 * Should use ZAlloc instead of Alloc to avoid problem with garbage
114 * initialized pointers in CERT_CopyName
115 */
116 switch (intValue) {
117 case certRFC822Name:
118 case certDNSName:
119 case certDirectoryName:
120 case certURI:
121 case certIPAddress:
122 case certRegisterID:
123 break;
124 default:
125 intValue = 0; /* force a break for anything else */
126 }
127
128 if (intValue == 0)
129 break;
130
131 if (namesList == NULL((void*)0)) {
132 if (useExistingName) {
133 namesList = current = tail = useExistingName;
134 } else {
135 namesList = current = tail =
136 PORT_ArenaZNew(arena, CERTGeneralName)(CERTGeneralName *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTGeneralName
))
;
137 }
138 } else {
139 current = PORT_ArenaZNew(arena, CERTGeneralName)(CERTGeneralName *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTGeneralName
))
;
140 }
141 if (current == NULL((void*)0)) {
142 GEN_BREAK(SECFailure)rv = SECFailure; break;;
143 }
144
145 current->type = intValue;
146 puts("\nEnter data:");
147 fflush(stdoutstdout);
148 if (Gets_s(buffer, sizeof(buffer)) == NULL((void*)0)) {
149 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INPUT_LEN);
150 GEN_BREAK(SECFailure)rv = SECFailure; break;;
151 }
152 switch (current->type) {
153 case certURI:
154 case certDNSName:
155 case certRFC822Name:
156 current->name.other.data =
157 PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, strlen(buffer));
158 if (current->name.other.data == NULL((void*)0)) {
159 GEN_BREAK(SECFailure)rv = SECFailure; break;;
160 }
161 PORT_Memcpymemcpy(current->name.other.data, buffer,
162 current->name.other.len = strlen(buffer));
163 break;
164
165 case certEDIPartyName:
166 case certIPAddress:
167 case certOtherName:
168 case certRegisterID:
169 case certX400Address: {
170
171 current->name.other.data =
172 PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, strlen(buffer) + 2);
173 if (current->name.other.data == NULL((void*)0)) {
174 GEN_BREAK(SECFailure)rv = SECFailure; break;;
175 }
176
177 PORT_Memcpymemcpy(current->name.other.data + 2, buffer,
178 strlen(buffer));
179 /* This may not be accurate for all cases. For now,
180 * use this tag type */
181 current->name.other.data[0] =
182 (char)(((current->type - 1) & 0x1f) | 0x80);
183 current->name.other.data[1] = (char)strlen(buffer);
184 current->name.other.len = strlen(buffer) + 2;
185 break;
186 }
187
188 case certDirectoryName: {
189 CERTName *directoryName = NULL((void*)0);
190
191 directoryName = CERT_AsciiToName(buffer);
192 if (!directoryName) {
193 fprintf(stderrstderr, "certutil: improperly formatted name: "
194 "\"%s\"\n",
195 buffer);
196 break;
197 }
198
199 rv = CERT_CopyName(arena, &current->name.directoryName,
200 directoryName);
201 CERT_DestroyName(directoryName);
202
203 break;
204 }
205 }
206 if (rv != SECSuccess)
207 break;
208 current->l.next = &(namesList->l);
209 current->l.prev = &(tail->l);
210 tail->l.next = &(current->l);
211 tail = current;
212
213 } while (!onlyOne);
214
215 if (rv != SECSuccess) {
216 PORT_ArenaReleasePORT_ArenaRelease_Util(arena, mark);
217 namesList = NULL((void*)0);
218 }
219 return (namesList);
220}
221
222static CERTGeneralName *
223CreateGeneralName(PLArenaPool *arena)
224{
225 return GetGeneralName(arena, NULL((void*)0), PR_FALSE0);
226}
227
228static SECStatus
229GetString(PLArenaPool *arena, char *prompt, SECItem *value)
230{
231 char buffer[251];
232 char *buffPrt;
233
234 buffer[0] = '\0';
235 value->data = NULL((void*)0);
236 value->len = 0;
237
238 puts(prompt);
239 buffPrt = Gets_s(buffer, sizeof(buffer));
240 /* returned NULL here treated the same way as empty string */
241 if (buffPrt && strlen(buffer) > 0) {
242 value->data = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, strlen(buffer));
243 if (value->data == NULL((void*)0)) {
244 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
245 return (SECFailure);
246 }
247 PORT_Memcpymemcpy(value->data, buffer, value->len = strlen(buffer));
248 }
249 return (SECSuccess);
250}
251
252static PRBool
253GetYesNo(char *prompt)
254{
255 char buf[3];
256 char *buffPrt;
257
258 buf[0] = 'n';
259 puts(prompt);
260 buffPrt = Gets_s(buf, sizeof(buf));
261 return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE1 : PR_FALSE0;
262}
263
264/* Parses comma separated values out of the string pointed by nextPos.
265 * Parsed value is compared to an array of possible values(valueArray).
266 * If match is found, a value index is returned, otherwise returns SECFailue.
267 * nextPos is set to the token after found comma separator or to NULL.
268 * NULL in nextPos should be used as indication of the last parsed token.
269 * A special value "critical" can be parsed out from the supplied sting.*/
270
271static SECStatus
272parseNextCmdInput(const char *const *valueArray, int *value, char **nextPos,
273 PRBool *critical)
274{
275 char *thisPos;
276 int keyLen = 0;
277 int arrIndex = 0;
278
279 if (!valueArray || !value || !nextPos || !critical) {
280 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
281 return SECFailure;
282 }
283 *critical = PR_FALSE0;
284 thisPos = *nextPos;
285 while (1) {
286 if ((*nextPos = strchr(thisPos, ',')) == NULL((void*)0)) {
287 keyLen = strlen(thisPos);
288 } else {
289 keyLen = *nextPos - thisPos;
290 *nextPos += 1;
291 }
292 /* if critical keyword is found, return without setting value */
293 if (!strncmp("critical", thisPos, keyLen)) {
294 *critical = PR_TRUE1;
295 return SECSuccess;
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_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
306 return SECFailure;
307}
308
309static const char *const
310 keyUsageKeyWordArray[] = { "digitalSignature",
311 "nonRepudiation",
312 "keyEncipherment",
313 "dataEncipherment",
314 "keyAgreement",
315 "certSigning",
316 "crlSigning",
317 NULL((void*)0) };
318
319static SECStatus
320parseKeyUsage(const char *const *wordArray, const char *userSuppliedValue,
321 unsigned char *keyUsage, PRBool *isCriticalExt)
322{
323 int value = 0;
324 char *nextPos = (char *)userSuppliedValue;
325 PRBool readCriticalToken;
326 while (1) {
327 if (parseNextCmdInput(wordArray, &value, &nextPos,
328 &readCriticalToken) == SECFailure) {
329 return SECFailure;
330 }
331 if (readCriticalToken == PR_TRUE1) {
332 *isCriticalExt = PR_TRUE1;
333 } else {
334 *keyUsage |= (0x80 >> value);
335 }
336 if (!nextPos)
337 break;
338 }
339 return SECSuccess;
340}
341
342static SECStatus
343AddKeyUsage(void *extHandle, const char *userSuppliedValue)
344{
345 SECItem bitStringValue;
346 unsigned char keyUsage = 0x0;
347 char buffer[5];
348 int value;
349 PRBool isCriticalExt = PR_FALSE0;
350
351 if (!userSuppliedValue) {
352 while (1) {
353 if (PrintChoicesAndGetAnswer(
354 "\t\t0 - Digital Signature\n"
355 "\t\t1 - Non-repudiation\n"
356 "\t\t2 - Key encipherment\n"
357 "\t\t3 - Data encipherment\n"
358 "\t\t4 - Key agreement\n"
359 "\t\t5 - Cert signing key\n"
360 "\t\t6 - CRL signing key\n"
361 "\t\tOther to finish\n",
362 buffer, sizeof(buffer)) == SECFailure) {
363 return SECFailure;
364 }
365 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
366 if (value < 0 || value > 6)
367 break;
368 if (value == 0) {
369 /* Checking that zero value of variable 'value'
370 * corresponds to '0' input made by user */
371 char *chPtr = strchr(buffer, '0');
372 if (chPtr == NULL((void*)0)) {
373 continue;
374 }
375 }
376 keyUsage |= (0x80 >> value);
377 }
378 isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
379 } else {
380 SECStatus rv = parseKeyUsage(keyUsageKeyWordArray, userSuppliedValue,
381 &keyUsage, &isCriticalExt);
382 if (rv != SECSuccess) {
383 return rv;
384 }
385 }
386
387 bitStringValue.data = &keyUsage;
388 bitStringValue.len = 1;
389
390 return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
391 isCriticalExt));
392}
393
394static CERTOidSequence *
395CreateOidSequence(void)
396{
397 CERTOidSequence *rv = (CERTOidSequence *)NULL((void*)0);
398 PLArenaPool *arena = (PLArenaPool *)NULL((void*)0);
399
400 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
401 if ((PLArenaPool *)NULL((void*)0) == arena) {
402 goto loser;
403 }
404
405 rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence)(CERTOidSequence *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTOidSequence
))
;
406 if ((CERTOidSequence *)NULL((void*)0) == rv) {
407 goto loser;
408 }
409
410 rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *)(SECItem * *)PORT_ArenaZAlloc_Util(arena, sizeof(SECItem *));
411 if ((SECItem **)NULL((void*)0) == rv->oids) {
412 goto loser;
413 }
414
415 rv->arena = arena;
416 return rv;
417
418loser:
419 if ((PLArenaPool *)NULL((void*)0) != arena) {
420 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
421 }
422
423 return (CERTOidSequence *)NULL((void*)0);
424}
425
426static void
427DestroyOidSequence(CERTOidSequence *os)
428{
429 if (os->arena) {
430 PORT_FreeArenaPORT_FreeArena_Util(os->arena, PR_FALSE0);
431 }
432}
433
434static SECStatus
435AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
436{
437 SECItem **oids;
438 PRUint32 count = 0;
439 SECOidData *od;
440
441 od = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(oidTag);
442 if ((SECOidData *)NULL((void*)0) == od) {
443 return SECFailure;
444 }
445
446 for (oids = os->oids; (SECItem *)NULL((void*)0) != *oids; oids++) {
447 if (*oids == &od->oid) {
448 /* We already have this oid */
449 return SECSuccess;
450 }
451 count++;
452 }
453
454 /* ArenaZRealloc */
455
456 {
457 PRUint32 i;
458
459 oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2)(SECItem * *)PORT_ArenaZAlloc_Util(os->arena, sizeof(SECItem
*) * (count + 2))
;
460 if ((SECItem **)NULL((void*)0) == oids) {
461 return SECFailure;
462 }
463
464 for (i = 0; i < count; i++) {
465 oids[i] = os->oids[i];
466 }
467
468 /* ArenaZFree(os->oids); */
469 }
470
471 os->oids = oids;
472 os->oids[count] = &od->oid;
473
474 return SECSuccess;
475}
476
477SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
478
479const SEC_ASN1Template CERT_OidSeqTemplate[] = {
480 { SEC_ASN1_SEQUENCE_OF(0x02000 | 0x10) | SEC_ASN1_XTRN0, offsetof(CERTOidSequence, oids)__builtin_offsetof(CERTOidSequence, oids),
481 SEC_ASN1_SUB(SEC_ObjectIDTemplate)SEC_ObjectIDTemplate_Util }
482};
483
484static SECItem *
485EncodeOidSequence(CERTOidSequence *os)
486{
487 SECItem *rv;
488
489 rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(os->arena, sizeof(SECItem
))
;
490 if ((SECItem *)NULL((void*)0) == rv) {
491 goto loser;
492 }
493
494 if (!SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(os->arena, rv, os, CERT_OidSeqTemplate)) {
495 goto loser;
496 }
497
498 return rv;
499
500loser:
501 return (SECItem *)NULL((void*)0);
502}
503
504static const char *const
505 extKeyUsageKeyWordArray[] = { "serverAuth",
506 "clientAuth",
507 "codeSigning",
508 "emailProtection",
509 "timeStamp",
510 "ocspResponder",
511 "stepUp",
512 "msTrustListSigning",
513 "x509Any",
514 "ipsecIKE",
515 "ipsecIKEEnd",
516 "ipsecIKEIntermediate",
517 "ipsecEnd",
518 "ipsecTunnel",
519 "ipsecUser",
520 NULL((void*)0) };
521
522static SECStatus
523AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
524{
525 char buffer[5];
526 int value;
527 CERTOidSequence *os;
528 SECStatus rv;
529 SECItem *item;
530 PRBool isCriticalExt = PR_FALSE0;
531 char *nextPos = (char *)userSuppliedValue;
532
533 os = CreateOidSequence();
534 if ((CERTOidSequence *)NULL((void*)0) == os) {
535 return SECFailure;
536 }
537
538 while (1) {
539 if (!userSuppliedValue) {
540 /*
541 * none of the 'new' extended key usage options work with the prompted menu. This is so
542 * old scripts can continue to work.
543 */
544 if (PrintChoicesAndGetAnswer(
545 "\t\t0 - Server Auth\n"
546 "\t\t1 - Client Auth\n"
547 "\t\t2 - Code Signing\n"
548 "\t\t3 - Email Protection\n"
549 "\t\t4 - Timestamp\n"
550 "\t\t5 - OCSP Responder\n"
551 "\t\t6 - Step-up\n"
552 "\t\t7 - Microsoft Trust List Signing\n"
553 "\t\tOther to finish\n",
554 buffer, sizeof(buffer)) == SECFailure) {
555 GEN_BREAK(SECFailure)rv = SECFailure; break;;
556 }
557 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
558
559 if (value == 0) {
560 /* Checking that zero value of variable 'value'
561 * corresponds to '0' input made by user */
562 char *chPtr = strchr(buffer, '0');
563 if (chPtr == NULL((void*)0)) {
564 continue;
565 }
566 }
567 } else {
568 PRBool readCriticalToken = PR_FALSE0;
569 if (parseNextCmdInput(extKeyUsageKeyWordArray, &value, &nextPos,
570 &readCriticalToken) == SECFailure) {
571 return SECFailure;
572 }
573 if (readCriticalToken == PR_TRUE1) {
574 isCriticalExt = PR_TRUE1;
575 if (!nextPos) {
576 goto endloop;
577 }
578 continue;
579 }
580 }
581
582 switch (value) {
583 case 0:
584 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
585 break;
586 case 1:
587 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
588 break;
589 case 2:
590 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
591 break;
592 case 3:
593 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
594 break;
595 case 4:
596 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
597 break;
598 case 5:
599 rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
600 break;
601 case 6:
602 rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
603 break;
604 case 7:
605 rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
606 break;
607 /*
608 * These new usages can only be added explicitly by the userSuppliedValues. This allows old
609 * scripts which used '>7' as an exit value to continue to work.
610 */
611 case 8:
612 if (!userSuppliedValue)
613 goto endloop;
614 rv = AddOidToSequence(os, SEC_OID_X509_ANY_EXT_KEY_USAGE);
615 break;
616 case 9:
617 if (!userSuppliedValue)
618 goto endloop;
619 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_IKE);
620 break;
621 case 10:
622 if (!userSuppliedValue)
623 goto endloop;
624 rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_END);
625 break;
626 case 11:
627 if (!userSuppliedValue)
628 goto endloop;
629 rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_INTERMEDIATE);
630 break;
631 case 12:
632 if (!userSuppliedValue)
633 goto endloop;
634 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_END);
635 break;
636 case 13:
637 if (!userSuppliedValue)
638 goto endloop;
639 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL);
640 break;
641 case 14:
642 if (!userSuppliedValue)
643 goto endloop;
644 rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_USER);
645 break;
646 default:
647 goto endloop;
648 }
649
650 if (userSuppliedValue && !nextPos)
651 break;
652 if (SECSuccess != rv)
653 goto loser;
654 }
655
656endloop:
657 item = EncodeOidSequence(os);
658
659 if (!userSuppliedValue) {
660 isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
661 }
662
663 rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
664 isCriticalExt, PR_TRUE1);
665/*FALLTHROUGH*/
666loser:
667 DestroyOidSequence(os);
668 return rv;
669}
670
671static const char *const
672 nsCertTypeKeyWordArray[] = { "sslClient",
673 "sslServer",
674 "smime",
675 "objectSigning",
676 "Not!Used",
677 "sslCA",
678 "smimeCA",
679 "objectSigningCA",
680 NULL((void*)0) };
681
682static SECStatus
683AddNscpCertType(void *extHandle, const char *userSuppliedValue)
684{
685 SECItem bitStringValue;
686 unsigned char keyUsage = 0x0;
687 char buffer[5];
688 int value;
689 PRBool isCriticalExt = PR_FALSE0;
690
691 if (!userSuppliedValue) {
692 while (1) {
693 if (PrintChoicesAndGetAnswer(
694 "\t\t0 - SSL Client\n"
695 "\t\t1 - SSL Server\n"
696 "\t\t2 - S/MIME\n"
697 "\t\t3 - Object Signing\n"
698 "\t\t4 - Reserved for future use\n"
699 "\t\t5 - SSL CA\n"
700 "\t\t6 - S/MIME CA\n"
701 "\t\t7 - Object Signing CA\n"
702 "\t\tOther to finish\n",
703 buffer, sizeof(buffer)) == SECFailure) {
704 return SECFailure;
705 }
706 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
707 if (value < 0 || value > 7)
708 break;
709 if (value == 0) {
710 /* Checking that zero value of variable 'value'
711 * corresponds to '0' input made by user */
712 char *chPtr = strchr(buffer, '0');
713 if (chPtr == NULL((void*)0)) {
714 continue;
715 }
716 }
717 keyUsage |= (0x80 >> value);
718 }
719 isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
720 } else {
721 SECStatus rv = parseKeyUsage(nsCertTypeKeyWordArray, userSuppliedValue,
722 &keyUsage, &isCriticalExt);
723 if (rv != SECSuccess) {
724 return rv;
725 }
726 }
727
728 bitStringValue.data = &keyUsage;
729 bitStringValue.len = 1;
730
731 return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
732 isCriticalExt));
733}
734
735SECStatus
736GetOidFromString(PLArenaPool *arena, SECItem *to,
737 const char *from, size_t fromLen)
738{
739 SECStatus rv;
740 SECOidTag tag;
741 SECOidData *coid;
742
743 /* try dotted form first */
744 rv = SEC_StringToOID(arena, to, from, fromLen);
745 if (rv == SECSuccess) {
746 return rv;
747 }
748
749 /* Check to see if it matches a name in our oid table. */
750 tag = SECOID_FindOIDTagFromDescripton(from, fromLen, PR_FALSE0);
751 if (tag == SEC_OID_UNKNOWN) {
752 /* none found */
753 return SECFailure;
754 }
755
756 coid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(tag);
757 return SECITEM_CopyItemSECITEM_CopyItem_Util(arena, to, &coid->oid);
758}
759
760static SECStatus
761AddSubjectAltNames(PLArenaPool *arena, CERTGeneralName **existingListp,
762 const char *constNames, CERTGeneralNameType type)
763{
764 CERTGeneralName *nameList = NULL((void*)0);
765 CERTGeneralName *current = NULL((void*)0);
766 PRCList *prev = NULL((void*)0);
767 char *cp, *nextName = NULL((void*)0);
768 SECStatus rv = SECSuccess;
769 PRBool readTypeFromName = (PRBool)(type == 0);
770 char *names = NULL((void*)0);
771
772 if (constNames)
773 names = PORT_StrdupPORT_Strdup_Util(constNames);
774
775 if (names == NULL((void*)0)) {
776 return SECFailure;
777 }
778
779 /*
780 * walk down the comma separated list of names. NOTE: there is
781 * no sanity checks to see if the email address look like
782 * email addresses.
783 *
784 * Each name may optionally be prefixed with a type: string.
785 * If it isn't, the type from the previous name will be used.
786 * If there wasn't a previous name yet, the type given
787 * as a parameter to this function will be used.
788 * If the type value is zero (undefined), we'll fail.
789 */
790 for (cp = names; cp; cp = nextName) {
791 int len;
792 char *oidString;
793 char *nextComma;
794 CERTName *name;
795 PRStatus status;
796 unsigned char *data;
797 PRNetAddr addr;
798
799 nextName = NULL((void*)0);
800 if (*cp == ',') {
801 cp++;
802 }
803 nextComma = PORT_Strchrstrchr(cp, ',');
804 if (nextComma) {
805 *nextComma = 0;
806 nextName = nextComma + 1;
807 }
808 if ((*cp) == 0) {
809 continue;
810 }
811 if (readTypeFromName) {
812 char *save = cp;
813 /* Because we already replaced nextComma with end-of-string,
814 * a found colon belongs to the current name */
815 cp = PORT_Strchrstrchr(cp, ':');
816 if (cp) {
817 *cp = 0;
818 cp++;
819 type = CERT_GetGeneralNameTypeFromString(save);
820 if (*cp == 0) {
821 continue;
822 }
823 } else {
824 if (type == 0) {
825 /* no type known yet */
826 rv = SECFailure;
827 break;
828 }
829 cp = save;
830 }
831 }
832
833 current = PORT_ArenaZNew(arena, CERTGeneralName)(CERTGeneralName *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTGeneralName
))
;
834 if (!current) {
835 rv = SECFailure;
836 break;
837 }
838
839 current->type = type;
840 switch (type) {
841 /* string types */
842 case certRFC822Name:
843 case certDNSName:
844 case certURI:
845 current->name.other.data =
846 (unsigned char *)PORT_ArenaStrdupPORT_ArenaStrdup_Util(arena, cp);
847 current->name.other.len = PORT_Strlen(cp)strlen(cp);
848 break;
849 /* unformated data types */
850 case certX400Address:
851 case certEDIPartyName:
852 /* turn a string into a data and len */
853 rv = SECFailure; /* punt on these for now */
854 fprintf(stderrstderr, "EDI Party Name and X.400 Address not supported\n");
855 break;
856 case certDirectoryName:
857 /* certDirectoryName */
858 name = CERT_AsciiToName(cp);
859 if (name == NULL((void*)0)) {
860 rv = SECFailure;
861 fprintf(stderrstderr, "Invalid Directory Name (\"%s\")\n", cp);
862 break;
863 }
864 rv = CERT_CopyName(arena, &current->name.directoryName, name);
865 CERT_DestroyName(name);
866 break;
867 /* types that require more processing */
868 case certIPAddress:
869 /* convert the string to an ip address */
870 status = PR_StringToNetAddr(cp, &addr);
871 if (status != PR_SUCCESS) {
872 rv = SECFailure;
873 fprintf(stderrstderr, "Invalid IP Address (\"%s\")\n", cp);
874 break;
875 }
876
877 if (PR_NetAddrFamily(&addr)((&addr)->raw.family) == PR_AF_INET2) {
878 len = sizeof(addr.inet.ip);
879 data = (unsigned char *)&addr.inet.ip;
880 } else if (PR_NetAddrFamily(&addr)((&addr)->raw.family) == PR_AF_INET610) {
881 len = sizeof(addr.ipv6.ip);
882 data = (unsigned char *)&addr.ipv6.ip;
883 } else {
884 fprintf(stderrstderr, "Invalid IP Family\n");
885 rv = SECFailure;
886 break;
887 }
888 current->name.other.data = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, len);
889 if (current->name.other.data == NULL((void*)0)) {
890 rv = SECFailure;
891 break;
892 }
893 current->name.other.len = len;
894 PORT_Memcpymemcpy(current->name.other.data, data, len);
895 break;
896 case certRegisterID:
897 rv = GetOidFromString(arena, &current->name.other, cp, strlen(cp));
898 break;
899 case certOtherName:
900 oidString = cp;
901 cp = PORT_Strchrstrchr(cp, ';');
902 if (cp == NULL((void*)0)) {
903 rv = SECFailure;
904 fprintf(stderrstderr, "missing name in other name\n");
905 break;
906 }
907 *cp++ = 0;
908 current->name.OthName.name.data =
909 (unsigned char *)PORT_ArenaStrdupPORT_ArenaStrdup_Util(arena, cp);
910 if (current->name.OthName.name.data == NULL((void*)0)) {
911 rv = SECFailure;
912 break;
913 }
914 current->name.OthName.name.len = PORT_Strlen(cp)strlen(cp);
915 rv = GetOidFromString(arena, &current->name.OthName.oid,
916 oidString, strlen(oidString));
917 break;
918 default:
919 rv = SECFailure;
920 fprintf(stderrstderr, "Missing or invalid Subject Alternate Name type\n");
921 break;
922 }
923 if (rv == SECFailure) {
924 break;
925 }
926
927 if (prev) {
928 current->l.prev = prev;
929 prev->next = &(current->l);
930 } else {
931 nameList = current;
932 }
933 prev = &(current->l);
934 }
935 PORT_FreePORT_Free_Util(names);
936 /* at this point nameList points to the head of a doubly linked,
937 * but not yet circular, list and current points to its tail. */
938 if (rv == SECSuccess && nameList) {
939 if (*existingListp != NULL((void*)0)) {
940 PRCList *existingprev;
941 /* add nameList to the end of the existing list */
942 existingprev = (*existingListp)->l.prev;
943 (*existingListp)->l.prev = &(current->l);
944 nameList->l.prev = existingprev;
945 existingprev->next = &(nameList->l);
946 current->l.next = &((*existingListp)->l);
947 } else {
948 /* make nameList circular and set it as the new existingList */
949 nameList->l.prev = prev;
950 current->l.next = &(nameList->l);
951 *existingListp = nameList;
952 }
953 }
954 return rv;
955}
956
957static SECStatus
958AddEmailSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
959 const char *emailAddrs)
960{
961 return AddSubjectAltNames(arena, existingListp, emailAddrs,
962 certRFC822Name);
963}
964
965static SECStatus
966AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
967 const char *dnsNames)
968{
969 return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
970}
971
972static SECStatus
973AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
974 const char *altNames)
975{
976 return AddSubjectAltNames(arena, existingListp, altNames, 0);
977}
978
979static SECStatus
980AddBasicConstraint(PLArenaPool *arena, void *extHandle)
981{
982 CERTBasicConstraints basicConstraint;
983 SECStatus rv;
984 char buffer[10];
985 PRBool yesNoAns;
986
987 do {
988 basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT-2;
989 basicConstraint.isCA = GetYesNo("Is this a CA certificate [y/N]?");
990
991 buffer[0] = '\0';
992 if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
993 "enter to skip [<0 for unlimited path]:",
994 buffer, sizeof(buffer)) == SECFailure) {
995 GEN_BREAK(SECFailure)rv = SECFailure; break;;
996 }
997 if (PORT_Strlen(buffer)strlen(buffer) > 0)
998 basicConstraint.pathLenConstraint = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
999
1000 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1001
1002 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1003 &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
1004 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeBasicConstraintValue);
1005 } while (0);
1006
1007 return (rv);
1008}
1009
1010static SECStatus
1011AddNameConstraints(void *extHandle)
1012{
1013 PLArenaPool *arena = NULL((void*)0);
1014 CERTNameConstraints *constraints = NULL((void*)0);
1015
1016 CERTNameConstraint *current = NULL((void*)0);
1017 CERTNameConstraint *last_permited = NULL((void*)0);
1018 CERTNameConstraint *last_excluded = NULL((void*)0);
1019 SECStatus rv = SECSuccess;
1020
1021 char buffer[512];
1022 int intValue = 0;
1023
1024 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1025 if (arena) {
1026 constraints = PORT_ArenaZNew(arena, CERTNameConstraints)(CERTNameConstraints *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTNameConstraints
))
;
1027 }
1028
1029 if (!arena || !constraints) {
1030 SECU_PrintError(progName, "out of memory");
1031 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1032 return SECFailure;
1033 }
1034
1035 constraints->permited = constraints->excluded = NULL((void*)0);
1036
1037 do {
1038 current = PORT_ArenaZNew(arena, CERTNameConstraint)(CERTNameConstraint *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTNameConstraint
))
;
1039 if (!current) {
1040 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1041 }
1042
1043 if (!GetGeneralName(arena, &current->name, PR_TRUE1)) {
1044 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1045 }
1046
1047 if (PrintChoicesAndGetAnswer("Type of Name Constraint?\n"
1048 "\t1 - permitted\n\t2 - excluded\n\tAny"
1049 "other number to finish\n\tChoice",
1050 buffer, sizeof(buffer)) !=
1051 SECSuccess) {
1052 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1053 }
1054
1055 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1056 switch (intValue) {
1057 case 1:
1058 if (constraints->permited == NULL((void*)0)) {
1059 constraints->permited = last_permited = current;
1060 }
1061 last_permited->l.next = &(current->l);
1062 current->l.prev = &(last_permited->l);
1063 last_permited = current;
1064 break;
1065 case 2:
1066 if (constraints->excluded == NULL((void*)0)) {
1067 constraints->excluded = last_excluded = current;
1068 }
1069 last_excluded->l.next = &(current->l);
1070 current->l.prev = &(last_excluded->l);
1071 last_excluded = current;
1072 break;
1073 }
1074
1075 PR_snprintf(buffer, sizeof(buffer), "Add another entry to the"
1076 " Name Constraint Extension [y/N]");
1077
1078 if (GetYesNo(buffer) == 0) {
1079 break;
1080 }
1081
1082 } while (1);
1083
1084 if (rv == SECSuccess) {
1085 int oidIdent = SEC_OID_X509_NAME_CONSTRAINTS;
1086
1087 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1088
1089 if (constraints->permited != NULL((void*)0)) {
1090 last_permited->l.next = &(constraints->permited->l);
1091 constraints->permited->l.prev = &(last_permited->l);
1092 }
1093 if (constraints->excluded != NULL((void*)0)) {
1094 last_excluded->l.next = &(constraints->excluded->l);
1095 constraints->excluded->l.prev = &(last_excluded->l);
1096 }
1097
1098 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, constraints,
1099 yesNoAns, oidIdent,
1100 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeNameConstraintsExtension);
1101 }
1102 if (arena)
1103 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1104 return (rv);
1105}
1106
1107static SECStatus
1108AddAuthKeyID(void *extHandle)
1109{
1110 CERTAuthKeyID *authKeyID = NULL((void*)0);
1111 PLArenaPool *arena = NULL((void*)0);
1112 SECStatus rv = SECSuccess;
1113 PRBool yesNoAns;
1114
1115 do {
1116 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1117 if (!arena) {
1118 SECU_PrintError(progName, "out of memory");
1119 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1120 }
1121
1122 if (GetYesNo("Enter value for the authKeyID extension [y/N]?") == 0)
1123 break;
1124
1125 authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID)(CERTAuthKeyID *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTAuthKeyID
))
;
1126 if (authKeyID == NULL((void*)0)) {
1127 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1128 }
1129
1130 rv = GetString(arena, "Enter value for the key identifier fields,"
1131 "enter to omit:",
1132 &authKeyID->keyID);
1133 if (rv != SECSuccess)
1134 break;
1135
1136 SECU_SECItemHexStringToBinary(&authKeyID->keyID);
1137
1138 authKeyID->authCertIssuer = CreateGeneralName(arena);
1139 if (authKeyID->authCertIssuer == NULL((void*)0) &&
1140 SECFailure == PORT_GetErrorPORT_GetError_Util())
1141 break;
1142
1143 rv = GetString(arena, "Enter value for the authCertSerial field, "
Value stored to 'rv' is never read
1144 "enter to omit:",
1145 &authKeyID->authCertSerialNumber);
1146
1147 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1148
1149 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1150 authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID,
1151 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAuthKeyID);
1152 if (rv)
1153 break;
1154
1155 } while (0);
1156 if (arena)
1157 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1158 return (rv);
1159}
1160
1161static SECStatus
1162AddSubjKeyID(void *extHandle)
1163{
1164 SECItem keyID;
1165 PLArenaPool *arena = NULL((void*)0);
1166 SECStatus rv = SECSuccess;
1167 PRBool yesNoAns;
1168
1169 do {
1170 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1171 if (!arena) {
1172 SECU_PrintError(progName, "out of memory");
1173 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1174 }
1175 printf("Adding Subject Key ID extension.\n");
1176
1177 rv = GetString(arena, "Enter value for the key identifier fields,"
1178 "enter to omit:",
1179 &keyID);
1180 if (rv != SECSuccess)
1181 break;
1182
1183 SECU_SECItemHexStringToBinary(&keyID);
1184
1185 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1186
1187 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1188 &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID,
1189 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeSubjectKeyID);
1190 if (rv)
1191 break;
1192
1193 } while (0);
1194 if (arena)
1195 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1196 return (rv);
1197}
1198
1199static SECStatus
1200AddCrlDistPoint(void *extHandle)
1201{
1202 PLArenaPool *arena = NULL((void*)0);
1203 CERTCrlDistributionPoints *crlDistPoints = NULL((void*)0);
1204 CRLDistributionPoint *current;
1205 SECStatus rv = SECSuccess;
1206 int count = 0, intValue;
1207 char buffer[512];
1208
1209 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1210 if (!arena)
1211 return (SECFailure);
1212
1213 do {
1214 current = NULL((void*)0);
1215
1216 current = PORT_ArenaZNew(arena, CRLDistributionPoint)(CRLDistributionPoint *)PORT_ArenaZAlloc_Util(arena, sizeof(CRLDistributionPoint
))
;
1217 if (current == NULL((void*)0)) {
1218 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1219 }
1220
1221 /* Get the distributionPointName fields - this field is optional */
1222 if (PrintChoicesAndGetAnswer(
1223 "Enter the type of the distribution point name:\n"
1224 "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
1225 "number to finish\n\t\tChoice: ",
1226 buffer, sizeof(buffer)) == SECFailure) {
1227 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1228 }
1229 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1230 switch (intValue) {
1231 case generalName:
1232 PORT_SetErrorPORT_SetError_Util(0);
1233 current->distPointType = intValue;
1234 current->distPoint.fullName = CreateGeneralName(arena);
1235 rv = PORT_GetErrorPORT_GetError_Util();
1236 break;
1237
1238 case relativeDistinguishedName: {
1239 CERTName *name;
1240
1241 current->distPointType = intValue;
1242 puts("Enter the relative name: ");
1243 fflush(stdoutstdout);
1244 if (Gets_s(buffer, sizeof(buffer)) == NULL((void*)0)) {
1245 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1246 }
1247 /* For simplicity, use CERT_AsciiToName to converse from a string
1248 to NAME, but we only interest in the first RDN */
1249 name = CERT_AsciiToName(buffer);
1250 if (!name) {
1251 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1252 }
1253 rv = CERT_CopyRDN(arena, &current->distPoint.relativeName,
1254 name->rdns[0]);
1255 CERT_DestroyName(name);
1256 break;
1257 }
1258 }
1259 if (rv != SECSuccess)
1260 break;
1261
1262 /* Get the reason flags */
1263 if (PrintChoicesAndGetAnswer(
1264 "\nSelect one of the following for the reason flags\n"
1265 "\t0 - unused\n\t1 - keyCompromise\n"
1266 "\t2 - caCompromise\n\t3 - affiliationChanged\n"
1267 "\t4 - superseded\n\t5 - cessationOfOperation\n"
1268 "\t6 - certificateHold\n"
1269 "\tAny other number to finish\t\tChoice: ",
1270 buffer, sizeof(buffer)) == SECFailure) {
1271 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1272 }
1273 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1274 if (intValue == 0) {
1275 /* Checking that zero value of variable 'value'
1276 * corresponds to '0' input made by user */
1277 char *chPtr = strchr(buffer, '0');
1278 if (chPtr == NULL((void*)0)) {
1279 intValue = -1;
1280 }
1281 }
1282 if (intValue >= 0 && intValue < 8) {
1283 current->reasons.data = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, sizeof(char));
1284 if (current->reasons.data == NULL((void*)0)) {
1285 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1286 }
1287 *current->reasons.data = (char)(0x80 >> intValue);
1288 current->reasons.len = 1;
1289 }
1290 puts("Enter value for the CRL Issuer name:\n");
1291 current->crlIssuer = CreateGeneralName(arena);
1292 if (current->crlIssuer == NULL((void*)0) && (rv = PORT_GetErrorPORT_GetError_Util()) == SECFailure)
1293 break;
1294
1295 if (crlDistPoints == NULL((void*)0)) {
1296 crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints)(CERTCrlDistributionPoints *)PORT_ArenaZAlloc_Util(arena, sizeof
(CERTCrlDistributionPoints))
;
1297 if (crlDistPoints == NULL((void*)0)) {
1298 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1299 }
1300 }
1301
1302 if (crlDistPoints->distPoints) {
1303 crlDistPoints->distPoints =
1304 PORT_ArenaGrowPORT_ArenaGrow_Util(arena, crlDistPoints->distPoints,
1305 sizeof(*crlDistPoints->distPoints) * count,
1306 sizeof(*crlDistPoints->distPoints) * (count + 1));
1307 } else {
1308 crlDistPoints->distPoints =
1309 PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(*crlDistPoints->distPoints) * (count + 1));
1310 }
1311 if (crlDistPoints->distPoints == NULL((void*)0)) {
1312 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1313 }
1314
1315 crlDistPoints->distPoints[count] = current;
1316 ++count;
1317 if (GetYesNo("Enter another value for the CRLDistributionPoint "
1318 "extension [y/N]?") == 0) {
1319 /* Add null to the end to mark end of data */
1320 crlDistPoints->distPoints =
1321 PORT_ArenaGrowPORT_ArenaGrow_Util(arena, crlDistPoints->distPoints,
1322 sizeof(*crlDistPoints->distPoints) * count,
1323 sizeof(*crlDistPoints->distPoints) * (count + 1));
1324 crlDistPoints->distPoints[count] = NULL((void*)0);
1325 break;
1326 }
1327
1328 } while (1);
1329
1330 if (rv == SECSuccess) {
1331 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1332
1333 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1334 crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
1335 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeCRLDistributionPoints);
1336 }
1337 if (arena)
1338 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1339 return (rv);
1340}
1341
1342static SECStatus
1343AddPolicyConstraints(void *extHandle)
1344{
1345 CERTCertificatePolicyConstraints *policyConstr;
1346 PLArenaPool *arena = NULL((void*)0);
1347 SECStatus rv = SECSuccess;
1348 SECItem *item, *dummy;
1349 char buffer[512];
1350 int value;
1351 PRBool yesNoAns;
1352 PRBool skipExt = PR_TRUE1;
1353
1354 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1355 if (!arena) {
1356 SECU_PrintError(progName, "out of memory");
1357 return SECFailure;
1358 }
1359
1360 policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints)(CERTCertificatePolicyConstraints *)PORT_ArenaZAlloc_Util(arena
, sizeof(CERTCertificatePolicyConstraints))
;
1361 if (policyConstr == NULL((void*)0)) {
1362 SECU_PrintError(progName, "out of memory");
1363 goto loser;
1364 }
1365
1366 if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
1367 "of certs in path\nbefore explicit policy is required\n"
1368 "(press Enter to omit)",
1369 buffer, sizeof(buffer)) == SECFailure) {
1370 goto loser;
1371 }
1372
1373 if (PORT_Strlen(buffer)strlen(buffer)) {
1374 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1375 if (value < 0) {
1376 goto loser;
1377 }
1378 item = &policyConstr->explicitPolicySkipCerts;
1379 dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(arena, item, value);
1380 if (!dummy) {
1381 goto loser;
1382 }
1383 skipExt = PR_FALSE0;
1384 }
1385
1386 if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
1387 "the number of certs in path\n"
1388 "after which policy mapping is not allowed\n"
1389 "(press Enter to omit)",
1390 buffer, sizeof(buffer)) == SECFailure) {
1391 goto loser;
1392 }
1393
1394 if (PORT_Strlen(buffer)strlen(buffer)) {
1395 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1396 if (value < 0) {
1397 goto loser;
1398 }
1399 item = &policyConstr->inhibitMappingSkipCerts;
1400 dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(arena, item, value);
1401 if (!dummy) {
1402 goto loser;
1403 }
1404 skipExt = PR_FALSE0;
1405 }
1406
1407 if (!skipExt) {
1408 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1409
1410 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
1411 yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
1412 EXTEN_EXT_VALUE_ENCODER_CERT_EncodePolicyConstraintsExtension);
1413 } else {
1414 fprintf(stdoutstdout, "Policy Constraint extensions must contain "
1415 "at least one policy field\n");
1416 rv = SECFailure;
1417 }
1418
1419loser:
1420 if (arena) {
1421 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1422 }
1423 return (rv);
1424}
1425
1426static SECStatus
1427AddInhibitAnyPolicy(void *extHandle)
1428{
1429 CERTCertificateInhibitAny certInhibitAny;
1430 PLArenaPool *arena = NULL((void*)0);
1431 SECStatus rv = SECSuccess;
1432 SECItem *item, *dummy;
1433 char buffer[10];
1434 int value;
1435 PRBool yesNoAns;
1436
1437 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1438 if (!arena) {
1439 SECU_PrintError(progName, "out of memory");
1440 return SECFailure;
1441 }
1442
1443 if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
1444 "permitted to use anyPolicy.\n"
1445 "(press Enter for 0)",
1446 buffer, sizeof(buffer)) == SECFailure) {
1447 goto loser;
1448 }
1449
1450 item = &certInhibitAny.inhibitAnySkipCerts;
1451 value = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1452 if (value < 0) {
1453 goto loser;
1454 }
1455 dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(arena, item, value);
1456 if (!dummy) {
1457 goto loser;
1458 }
1459
1460 yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1461
1462 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
1463 yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
1464 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeInhibitAnyExtension);
1465loser:
1466 if (arena) {
1467 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1468 }
1469 return (rv);
1470}
1471
1472static SECStatus
1473AddPolicyMappings(void *extHandle)
1474{
1475 CERTPolicyMap **policyMapArr = NULL((void*)0);
1476 CERTPolicyMap *current;
1477 PLArenaPool *arena = NULL((void*)0);
1478 SECStatus rv = SECSuccess;
1479 int count = 0;
1480 char buffer[512];
1481
1482 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1483 if (!arena) {
1484 SECU_PrintError(progName, "out of memory");
1485 return SECFailure;
1486 }
1487
1488 do {
1489 if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
1490 "decimal format) for Issuer Domain Policy",
1491 buffer, sizeof(buffer)) == SECFailure) {
1492 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1493 }
1494
1495 current = PORT_ArenaZNew(arena, CERTPolicyMap)(CERTPolicyMap *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTPolicyMap
))
;
1496 if (current == NULL((void*)0)) {
1497 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1498 }
1499
1500 rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
1501 if (rv == SECFailure) {
1502 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1503 }
1504
1505 if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
1506 "Subject Domain Policy",
1507 buffer, sizeof(buffer)) == SECFailure) {
1508 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1509 }
1510
1511 rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
1512 if (rv == SECFailure) {
1513 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1514 }
1515
1516 if (policyMapArr == NULL((void*)0)) {
1517 policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *)(CERTPolicyMap * *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTPolicyMap
*))
;
1518 if (policyMapArr == NULL((void*)0)) {
1519 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1520 }
1521 }
1522
1523 policyMapArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, policyMapArr,
1524 sizeof(current) * count,
1525 sizeof(current) * (count + 1));
1526 if (policyMapArr == NULL((void*)0)) {
1527 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1528 }
1529
1530 policyMapArr[count] = current;
1531 ++count;
1532
1533 if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
1534 /* Add null to the end to mark end of data */
1535 policyMapArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, policyMapArr,
1536 sizeof(current) * count,
1537 sizeof(current) * (count + 1));
1538 if (policyMapArr == NULL((void*)0)) {
1539 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1540 }
1541 policyMapArr[count] = NULL((void*)0);
1542 break;
1543 }
1544
1545 } while (1);
1546
1547 if (rv == SECSuccess) {
1548 CERTCertificatePolicyMappings mappings;
1549 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1550
1551 mappings.arena = arena;
1552 mappings.policyMaps = policyMapArr;
1553 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
1554 yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
1555 EXTEN_EXT_VALUE_ENCODER_CERT_EncodePolicyMappingExtension);
1556 }
1557 if (arena)
1558 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1559 return (rv);
1560}
1561
1562enum PoliciQualifierEnum {
1563 cpsPointer = 1,
1564 userNotice = 2
1565};
1566
1567static CERTPolicyQualifier **
1568RequestPolicyQualifiers(PLArenaPool *arena, SECItem *policyID)
1569{
1570 CERTPolicyQualifier **policyQualifArr = NULL((void*)0);
1571 CERTPolicyQualifier *current;
1572 SECStatus rv = SECSuccess;
1573 int count = 0;
1574 char buffer[512];
1575 void *mark;
1576 SECOidData *oid = NULL((void*)0);
1577 int intValue = 0;
1578 int inCount = 0;
1579
1580 PORT_Assert(arena)((arena) ? ((void)0) : PR_Assert("arena", "/root/firefox-clang/security/nss/cmd/certutil/certext.c"
, 1580))
;
1581 mark = PORT_ArenaMarkPORT_ArenaMark_Util(arena);
1582 do {
1583 current = PORT_ArenaZNew(arena, CERTPolicyQualifier)(CERTPolicyQualifier *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTPolicyQualifier
))
;
1584 if (current == NULL((void*)0)) {
1585 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1586 }
1587
1588 /* Get the accessMethod fields */
1589 SECU_PrintObjectID(stdoutstdout, policyID,
1590 "Choose the type of qualifier for policy", 0);
1591
1592 if (PrintChoicesAndGetAnswer(
1593 "\t1 - CPS Pointer qualifier\n"
1594 "\t2 - User notice qualifier\n"
1595 "\tAny other number to finish\n"
1596 "\t\tChoice: ",
1597 buffer, sizeof(buffer)) == SECFailure) {
1598 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1599 }
1600 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1601 switch (intValue) {
1602 case cpsPointer: {
1603 SECItem input;
1604
1605 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
1606 if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
1607 buffer, sizeof(buffer)) == SECFailure) {
1608 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1609 }
1610 input.len = PORT_Strlen(buffer)strlen(buffer);
1611 input.data = (void *)PORT_ArenaStrdupPORT_ArenaStrdup_Util(arena, buffer);
1612 if (input.data == NULL((void*)0) ||
1613 SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &current->qualifierValue, &input,
1614 SEC_ASN1_GET(SEC_IA5StringTemplate)SEC_IA5StringTemplate_Util) == NULL((void*)0)) {
1615 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1616 }
1617 break;
1618 }
1619 case userNotice: {
1620 SECItem **noticeNumArr;
1621 CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice)(CERTUserNotice *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTUserNotice
))
;
1622 if (!notice) {
1623 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1624 }
1625
1626 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
1627
1628 if (GetYesNo("\t add a User Notice reference? [y/N]")) {
1629
1630 if (PrintChoicesAndGetAnswer("Enter user organization string: ",
1631 buffer, sizeof(buffer)) ==
1632 SECFailure) {
1633 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1634 }
1635
1636 notice->noticeReference.organization.type = siAsciiString;
1637 notice->noticeReference.organization.len =
1638 PORT_Strlen(buffer)strlen(buffer);
1639 notice->noticeReference.organization.data =
1640 (void *)PORT_ArenaStrdupPORT_ArenaStrdup_Util(arena, buffer);
1641
1642 noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2)(SECItem * *)PORT_ArenaZAlloc_Util(arena, sizeof(SECItem *) *
(2))
;
1643 if (!noticeNumArr) {
1644 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1645 }
1646
1647 do {
1648 SECItem *noticeNum;
1649
1650 noticeNum = PORT_ArenaZNew(arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(arena, sizeof(SECItem));
1651
1652 if (PrintChoicesAndGetAnswer(
1653 "Enter User Notice reference number "
1654 "(or -1 to quit): ",
1655 buffer, sizeof(buffer)) == SECFailure) {
1656 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1657 }
1658
1659 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1660 if (noticeNum == NULL((void*)0)) {
1661 if (intValue < 0) {
1662 fprintf(stdoutstdout, "a noticeReference must have at "
1663 "least one reference number\n");
1664 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1665 }
1666 } else {
1667 if (intValue >= 0) {
1668 noticeNumArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, noticeNumArr,
1669 sizeof(current) *
1670 inCount,
1671 sizeof(current) *
1672 (inCount + 1));
1673 if (noticeNumArr == NULL((void*)0)) {
1674 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1675 }
1676 } else {
1677 break;
1678 }
1679 }
1680 if (!SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(arena, noticeNum, intValue)) {
1681 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1682 }
1683 noticeNumArr[inCount++] = noticeNum;
1684 noticeNumArr[inCount] = NULL((void*)0);
1685
1686 } while (1);
1687 if (rv == SECFailure) {
1688 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1689 }
1690 notice->noticeReference.noticeNumbers = noticeNumArr;
1691 rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
1692 &notice->derNoticeReference);
1693 if (rv == SECFailure) {
1694 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1695 }
1696 }
1697 if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
1698 /* Getting only 200 bytes - RFC limitation */
1699 if (PrintChoicesAndGetAnswer(
1700 "\t", buffer, 200) == SECFailure) {
1701 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1702 }
1703 notice->displayText.type = siAsciiString;
1704 notice->displayText.len = PORT_Strlen(buffer)strlen(buffer);
1705 notice->displayText.data =
1706 (void *)PORT_ArenaStrdupPORT_ArenaStrdup_Util(arena, buffer);
1707 if (notice->displayText.data == NULL((void*)0)) {
1708 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1709 }
1710 }
1711
1712 rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
1713 if (rv == SECFailure) {
1714 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1715 }
1716
1717 break;
1718 }
1719 }
1720 if (rv == SECFailure || oid == NULL((void*)0) ||
1721 SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &current->qualifierID, &oid->oid) ==
1722 SECFailure) {
1723 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1724 }
1725
1726 if (!policyQualifArr) {
1727 policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *)(CERTPolicyQualifier * *)PORT_ArenaZAlloc_Util(arena, sizeof(
CERTPolicyQualifier *))
;
1728 } else {
1729 policyQualifArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, policyQualifArr,
1730 sizeof(current) * count,
1731 sizeof(current) * (count + 1));
1732 }
1733 if (policyQualifArr == NULL((void*)0)) {
1734 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1735 }
1736
1737 policyQualifArr[count] = current;
1738 ++count;
1739
1740 if (!GetYesNo("Enter another policy qualifier [y/N]")) {
1741 /* Add null to the end to mark end of data */
1742 policyQualifArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, policyQualifArr,
1743 sizeof(current) * count,
1744 sizeof(current) * (count + 1));
1745 if (policyQualifArr == NULL((void*)0)) {
1746 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1747 }
1748 policyQualifArr[count] = NULL((void*)0);
1749 break;
1750 }
1751
1752 } while (1);
1753
1754 if (rv != SECSuccess) {
1755 PORT_ArenaReleasePORT_ArenaRelease_Util(arena, mark);
1756 policyQualifArr = NULL((void*)0);
1757 }
1758 return (policyQualifArr);
1759}
1760
1761static SECStatus
1762AddCertPolicies(void *extHandle)
1763{
1764 CERTPolicyInfo **certPoliciesArr = NULL((void*)0);
1765 CERTPolicyInfo *current;
1766 PLArenaPool *arena = NULL((void*)0);
1767 SECStatus rv = SECSuccess;
1768 int count = 0;
1769 char buffer[512];
1770
1771 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1772 if (!arena) {
1773 SECU_PrintError(progName, "out of memory");
1774 return SECFailure;
1775 }
1776
1777 do {
1778 current = PORT_ArenaZNew(arena, CERTPolicyInfo)(CERTPolicyInfo *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTPolicyInfo
))
;
1779 if (current == NULL((void*)0)) {
1780 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1781 }
1782
1783 if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
1784 "(dotted decimal format)\n"
1785 "or \"any\" for AnyPolicy:",
1786 buffer, sizeof(buffer)) == SECFailure) {
1787 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1788 }
1789
1790 if (strncmp(buffer, "any", 3) == 0) {
1791 /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
1792 strcpy(buffer, "OID.2.5.29.32.0");
1793 }
1794 rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
1795
1796 if (rv == SECFailure) {
1797 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1798 }
1799
1800 current->policyQualifiers =
1801 RequestPolicyQualifiers(arena, &current->policyID);
1802
1803 if (!certPoliciesArr) {
1804 certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *)(CERTPolicyInfo * *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTPolicyInfo
*))
;
1805 } else {
1806 certPoliciesArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, certPoliciesArr,
1807 sizeof(current) * count,
1808 sizeof(current) * (count + 1));
1809 }
1810 if (certPoliciesArr == NULL((void*)0)) {
1811 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1812 }
1813
1814 certPoliciesArr[count] = current;
1815 ++count;
1816
1817 if (!GetYesNo("Enter another PolicyInformation field [y/N]?")) {
1818 /* Add null to the end to mark end of data */
1819 certPoliciesArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, certPoliciesArr,
1820 sizeof(current) * count,
1821 sizeof(current) * (count + 1));
1822 if (certPoliciesArr == NULL((void*)0)) {
1823 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1824 }
1825 certPoliciesArr[count] = NULL((void*)0);
1826 break;
1827 }
1828
1829 } while (1);
1830
1831 if (rv == SECSuccess) {
1832 CERTCertificatePolicies policies;
1833 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1834
1835 policies.arena = arena;
1836 policies.policyInfos = certPoliciesArr;
1837
1838 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
1839 yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
1840 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeCertPoliciesExtension);
1841 }
1842 if (arena)
1843 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1844 return (rv);
1845}
1846
1847enum AuthInfoAccessTypesEnum {
1848 caIssuers = 1,
1849 ocsp = 2
1850};
1851
1852enum SubjInfoAccessTypesEnum {
1853 caRepository = 1,
1854 timeStamping = 2
1855};
1856
1857/* Encode and add an AIA or SIA extension */
1858static SECStatus
1859AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
1860{
1861 CERTAuthInfoAccess **infoAccArr = NULL((void*)0);
1862 CERTAuthInfoAccess *current;
1863 PLArenaPool *arena = NULL((void*)0);
1864 SECStatus rv = SECSuccess;
1865 int count = 0;
1866 char buffer[512];
1867 SECOidData *oid = NULL((void*)0);
1868 int intValue = 0;
1869
1870 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1871 if (!arena) {
1872 SECU_PrintError(progName, "out of memory");
1873 return SECFailure;
1874 }
1875
1876 do {
1877 current = NULL((void*)0);
1878 current = PORT_ArenaZNew(arena, CERTAuthInfoAccess)(CERTAuthInfoAccess *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTAuthInfoAccess
))
;
1879 if (current == NULL((void*)0)) {
1880 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1881 }
1882
1883 /* Get the accessMethod fields */
1884 if (addSIAExt) {
1885 if (isCACert) {
1886 puts("Adding \"CA Repository\" access method type for "
1887 "Subject Information Access extension:\n");
1888 intValue = caRepository;
1889 } else {
1890 puts("Adding \"Time Stamping Services\" access method type for "
1891 "Subject Information Access extension:\n");
1892 intValue = timeStamping;
1893 }
1894 } else {
1895 if (PrintChoicesAndGetAnswer("Enter access method type "
1896 "for Authority Information Access extension:\n"
1897 "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
1898 "other number to finish\n\tChoice",
1899 buffer, sizeof(buffer)) !=
1900 SECSuccess) {
1901 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1902 }
1903 intValue = PORT_Atoi(buffer)(int)strtol(buffer, ((void*)0), 10);
1904 }
1905 if (addSIAExt) {
1906 switch (intValue) {
1907 case caRepository:
1908 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_CA_REPOSITORY);
1909 break;
1910
1911 case timeStamping:
1912 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_TIMESTAMPING);
1913 break;
1914 }
1915 } else {
1916 switch (intValue) {
1917 case caIssuers:
1918 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_CA_ISSUERS);
1919 break;
1920
1921 case ocsp:
1922 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKIX_OCSP);
1923 break;
1924 }
1925 }
1926 if (oid == NULL((void*)0) ||
1927 SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &current->method, &oid->oid) ==
1928 SECFailure) {
1929 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1930 }
1931
1932 current->location = CreateGeneralName(arena);
1933 if (!current->location) {
1934 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1935 }
1936
1937 if (infoAccArr == NULL((void*)0)) {
1938 infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *)(CERTAuthInfoAccess * *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTAuthInfoAccess
*))
;
1939 } else {
1940 infoAccArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, infoAccArr,
1941 sizeof(current) * count,
1942 sizeof(current) * (count + 1));
1943 }
1944 if (infoAccArr == NULL((void*)0)) {
1945 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1946 }
1947
1948 infoAccArr[count] = current;
1949 ++count;
1950
1951 PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
1952 " Information Access extension [y/N]",
1953 (addSIAExt) ? "Subject" : "Authority");
1954
1955 if (GetYesNo(buffer) == 0) {
1956 /* Add null to the end to mark end of data */
1957 infoAccArr = PORT_ArenaGrowPORT_ArenaGrow_Util(arena, infoAccArr,
1958 sizeof(current) * count,
1959 sizeof(current) * (count + 1));
1960 if (infoAccArr == NULL((void*)0)) {
1961 GEN_BREAK(SECFailure)rv = SECFailure; break;;
1962 }
1963 infoAccArr[count] = NULL((void*)0);
1964 break;
1965 }
1966
1967 } while (1);
1968
1969 if (rv == SECSuccess) {
1970 int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
1971
1972 PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1973
1974 if (addSIAExt) {
1975 oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
1976 }
1977 rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
1978 yesNoAns, oidIdent,
1979 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeInfoAccessExtension);
1980 }
1981 if (arena)
1982 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1983 return (rv);
1984}
1985
1986/* Example of valid input:
1987 * 1.2.3.4:critical:/tmp/abc,5.6.7.8:not-critical:/tmp/xyz
1988 */
1989static SECStatus
1990parseNextGenericExt(const char *nextExtension, const char **oid, int *oidLen,
1991 const char **crit, int *critLen,
1992 const char **filename, int *filenameLen,
1993 const char **next)
1994{
1995 const char *nextColon;
1996 const char *nextComma;
1997 const char *iter = nextExtension;
1998
1999 if (!iter || !*iter)
2000 return SECFailure;
2001
2002 /* Require colons at earlier positions than nextComma (or end of string ) */
2003 nextComma = strchr(iter, ',');
2004
2005 *oid = iter;
2006 nextColon = strchr(iter, ':');
2007 if (!nextColon || (nextComma && nextColon > nextComma))
2008 return SECFailure;
2009 *oidLen = (nextColon - *oid);
2010
2011 if (!*oidLen)
2012 return SECFailure;
2013
2014 iter = nextColon;
2015 ++iter;
2016
2017 *crit = iter;
2018 nextColon = strchr(iter, ':');
2019 if (!nextColon || (nextComma && nextColon > nextComma))
2020 return SECFailure;
2021 *critLen = (nextColon - *crit);
2022
2023 if (!*critLen)
2024 return SECFailure;
2025
2026 iter = nextColon;
2027 ++iter;
2028
2029 *filename = iter;
2030 if (nextComma) {
2031 *filenameLen = (nextComma - *filename);
2032 iter = nextComma;
2033 ++iter;
2034 *next = iter;
2035 } else {
2036 *filenameLen = strlen(*filename);
2037 *next = NULL((void*)0);
2038 }
2039
2040 if (!*filenameLen)
2041 return SECFailure;
2042
2043 return SECSuccess;
2044}
2045
2046SECStatus
2047AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
2048 certutilExtnList extList, const char *extGeneric)
2049{
2050 PLArenaPool *arena;
2051 SECStatus rv = SECSuccess;
2052 char *errstring = NULL((void*)0);
2053 const char *nextExtension = NULL((void*)0);
2054
2055 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2056 if (arena == NULL((void*)0)) {
2057 return SECFailure;
2058 }
2059
2060 do {
2061 /* Add key usage extension */
2062 if (extList[ext_keyUsage].activated) {
2063 rv = AddKeyUsage(extHandle, extList[ext_keyUsage].arg);
2064 if (rv) {
2065 errstring = "KeyUsage";
2066 break;
2067 }
2068 }
2069
2070 /* Add extended key usage extension */
2071 if (extList[ext_extKeyUsage].activated) {
2072 rv = AddExtKeyUsage(extHandle, extList[ext_extKeyUsage].arg);
2073 if (rv) {
2074 errstring = "ExtendedKeyUsage";
2075 break;
2076 }
2077 }
2078
2079 /* Add basic constraint extension */
2080 if (extList[ext_basicConstraint].activated) {
2081 rv = AddBasicConstraint(arena, extHandle);
2082 if (rv) {
2083 errstring = "BasicConstraint";
2084 break;
2085 }
2086 }
2087
2088 /* Add name constraints extension */
2089 if (extList[ext_nameConstraints].activated) {
2090 rv = AddNameConstraints(extHandle);
2091 if (rv) {
2092 errstring = "NameConstraints";
2093 break;
2094 }
2095 }
2096
2097 if (extList[ext_authorityKeyID].activated) {
2098 rv = AddAuthKeyID(extHandle);
2099 if (rv) {
2100 errstring = "AuthorityKeyID";
2101 break;
2102 }
2103 }
2104
2105 if (extList[ext_subjectKeyID].activated) {
2106 rv = AddSubjKeyID(extHandle);
2107 if (rv) {
2108 errstring = "SubjectKeyID";
2109 break;
2110 }
2111 }
2112
2113 if (extList[ext_CRLDistPts].activated) {
2114 rv = AddCrlDistPoint(extHandle);
2115 if (rv) {
2116 errstring = "CRLDistPoints";
2117 break;
2118 }
2119 }
2120
2121 if (extList[ext_NSCertType].activated) {
2122 rv = AddNscpCertType(extHandle, extList[ext_NSCertType].arg);
2123 if (rv) {
2124 errstring = "NSCertType";
2125 break;
2126 }
2127 }
2128
2129 if (extList[ext_authInfoAcc].activated ||
2130 extList[ext_subjInfoAcc].activated) {
2131 rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc].activated,
2132 extList[ext_basicConstraint].activated);
2133 if (rv) {
2134 errstring = "InformationAccess";
2135 break;
2136 }
2137 }
2138
2139 if (extList[ext_certPolicies].activated) {
2140 rv = AddCertPolicies(extHandle);
2141 if (rv) {
2142 errstring = "Policies";
2143 break;
2144 }
2145 }
2146
2147 if (extList[ext_policyMappings].activated) {
2148 rv = AddPolicyMappings(extHandle);
2149 if (rv) {
2150 errstring = "PolicyMappings";
2151 break;
2152 }
2153 }
2154
2155 if (extList[ext_policyConstr].activated) {
2156 rv = AddPolicyConstraints(extHandle);
2157 if (rv) {
2158 errstring = "PolicyConstraints";
2159 break;
2160 }
2161 }
2162
2163 if (extList[ext_inhibitAnyPolicy].activated) {
2164 rv = AddInhibitAnyPolicy(extHandle);
2165 if (rv) {
2166 errstring = "InhibitAnyPolicy";
2167 break;
2168 }
2169 }
2170
2171 if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
2172 CERTGeneralName *namelist = NULL((void*)0);
2173 SECItem item = { 0, NULL((void*)0), 0 };
2174
2175 rv = SECSuccess;
2176
2177 if (emailAddrs) {
2178 rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
2179 }
2180
2181 if (dnsNames) {
2182 rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
2183 }
2184
2185 if (extList[ext_subjectAltName].activated) {
2186 rv |= AddGeneralSubjectAlt(arena, &namelist,
2187 extList[ext_subjectAltName].arg);
2188 }
2189
2190 if (rv == SECSuccess) {
2191 rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
2192 if (rv == SECSuccess) {
2193 rv = CERT_AddExtension(extHandle,
2194 SEC_OID_X509_SUBJECT_ALT_NAME,
2195 &item, PR_FALSE0, PR_TRUE1);
2196 }
2197 }
2198 if (rv) {
2199 errstring = "SubjectAltName";
2200 break;
2201 }
2202 }
2203 } while (0);
2204
2205 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2206
2207 if (rv != SECSuccess) {
2208 SECU_PrintError(progName, "Problem creating %s extension", errstring);
2209 }
2210
2211 nextExtension = extGeneric;
2212 while (nextExtension && *nextExtension) {
2213 SECItem oid_item, value;
2214 PRBool isCritical;
2215 const char *oid, *crit, *filename, *next;
2216 int oidLen, critLen, filenameLen;
2217 PRFileDesc *inFile = NULL((void*)0);
2218 char *zeroTerminatedFilename = NULL((void*)0);
2219
2220 rv = parseNextGenericExt(nextExtension, &oid, &oidLen, &crit, &critLen,
2221 &filename, &filenameLen, &next);
2222 if (rv != SECSuccess) {
2223 SECU_PrintError(progName,
2224 "error parsing generic extension parameter %s",
2225 nextExtension);
2226 break;
2227 }
2228 oid_item.data = NULL((void*)0);
2229 oid_item.len = 0;
2230 rv = GetOidFromString(NULL((void*)0), &oid_item, oid, oidLen);
2231 if (rv != SECSuccess) {
2232 SECU_PrintError(progName, "malformed extension OID %s", nextExtension);
2233 break;
2234 }
2235 if (!strncmp("critical", crit, critLen)) {
2236 isCritical = PR_TRUE1;
2237 } else if (!strncmp("not-critical", crit, critLen)) {
2238 isCritical = PR_FALSE0;
2239 } else {
2240 rv = SECFailure;
2241 SECU_PrintError(progName, "expected 'critical' or 'not-critical'");
2242 break;
2243 }
2244 zeroTerminatedFilename = PL_strndup(filename, filenameLen);
2245 if (!zeroTerminatedFilename) {
2246 rv = SECFailure;
2247 SECU_PrintError(progName, "out of memory");
2248 break;
2249 }
2250 rv = SECFailure;
2251 inFile = PR_Open(zeroTerminatedFilename, PR_RDONLY0x01, 0);
2252 if (inFile) {
2253 rv = SECU_ReadDERFromFile(&value, inFile, PR_FALSE0, PR_FALSE0);
2254 PR_Close(inFile);
2255 inFile = NULL((void*)0);
2256 }
2257 if (rv != SECSuccess) {
2258 SECU_PrintError(progName, "unable to read file %s",
2259 zeroTerminatedFilename);
2260 }
2261 PL_strfree(zeroTerminatedFilename);
2262 if (rv != SECSuccess) {
2263 break;
2264 }
2265 rv = CERT_AddExtensionByOID(extHandle, &oid_item, &value, isCritical,
2266 PR_TRUE1 /*copyData*/);
2267 SECITEM_FreeItemSECITEM_FreeItem_Util(&value, PR_FALSE0);
2268 SECITEM_FreeItemSECITEM_FreeItem_Util(&oid_item, PR_FALSE0);
2269 if (rv != SECSuccess) {
2270 SECU_PrintError(progName, "failed to add extension %s", nextExtension);
2271 break;
2272 }
2273 nextExtension = next;
2274 }
2275
2276 return rv;
2277}