Bug Summary

File:s/cmd/certutil/certext.c
Warning:line 706, column 31
The right operand of '>>' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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