Bug Summary

File:s/cmd/multinit/multinit.c
Warning:line 238, column 37
Array access (via field 'data') results in a null pointer dereference

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 multinit.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/multinit -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/multinit -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -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 -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 multinit.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#include <stdio.h>
6#include <string.h>
7#include <stdlib.h>
8#include "nss.h"
9#include "secutil.h"
10#include "pk11pub.h"
11#include "cert.h"
12
13typedef struct commandDescriptStr {
14 int required;
15 char *arg;
16 char *des;
17} commandDescript;
18
19enum optionNames {
20 opt_liborder = 0,
21 opt_mainDB,
22 opt_lib1DB,
23 opt_lib2DB,
24 opt_mainRO,
25 opt_lib1RO,
26 opt_lib2RO,
27 opt_mainCMD,
28 opt_lib1CMD,
29 opt_lib2CMD,
30 opt_mainTokNam,
31 opt_lib1TokNam,
32 opt_lib2TokNam,
33 opt_oldStyle,
34 opt_verbose,
35 opt_summary,
36 opt_help,
37 opt_last
38};
39
40static const secuCommandFlag options_init[] = {
41 { /* opt_liborder */ 'o', PR_TRUE1, "1M2zmi", PR_TRUE1, "order" },
42 { /* opt_mainDB */ 'd', PR_TRUE1, 0, PR_FALSE0, "main_db" },
43 { /* opt_lib1DB */ '1', PR_TRUE1, 0, PR_FALSE0, "lib1_db" },
44 { /* opt_lib2DB */ '2', PR_TRUE1, 0, PR_FALSE0, "lib2_db" },
45 { /* opt_mainRO */ 'r', PR_FALSE0, 0, PR_FALSE0, "main_readonly" },
46 { /* opt_lib1RO */ 0, PR_FALSE0, 0, PR_FALSE0, "lib1_readonly" },
47 { /* opt_lib2RO */ 0, PR_FALSE0, 0, PR_FALSE0, "lib2_readonly" },
48 { /* opt_mainCMD */ 'c', PR_TRUE1, 0, PR_FALSE0, "main_command" },
49 { /* opt_lib1CMD */ 0, PR_TRUE1, 0, PR_FALSE0, "lib1_command" },
50 { /* opt_lib2CMD */ 0, PR_TRUE1, 0, PR_FALSE0, "lib2_command" },
51 { /* opt_mainTokNam */ 't', PR_TRUE1, 0, PR_FALSE0, "main_token_name" },
52 { /* opt_lib1TokNam */ 0, PR_TRUE1, 0, PR_FALSE0, "lib1_token_name" },
53 { /* opt_lib2TokNam */ 0, PR_TRUE1, 0, PR_FALSE0, "lib2_token_name" },
54 { /* opt_oldStype */ 's', PR_FALSE0, 0, PR_FALSE0, "oldStype" },
55 { /* opt_verbose */ 'v', PR_FALSE0, 0, PR_FALSE0, "verbose" },
56 { /* opt_summary */ 'z', PR_FALSE0, 0, PR_FALSE0, "summary" },
57 { /* opt_help */ 'h', PR_FALSE0, 0, PR_FALSE0, "help" }
58};
59
60static const commandDescript options_des[] = {
61 { /* opt_liborder */ PR_FALSE0, "initOrder",
62 " Specifies the order of NSS initialization and shutdown. Order is\n"
63 " given as a string where each character represents either an init or\n"
64 " a shutdown of the main program or one of the 2 test libraries\n"
65 " (library 1 and library 2). The valid characters are as follows:\n"
66 " M Init the main program\n 1 Init library 1\n"
67 " 2 Init library 2\n"
68 " m Shutdown the main program\n i Shutdown library 1\n"
69 " z Shutdown library 2\n" },
70 { /* opt_mainDB */ PR_TRUE1, "nss_db",
71 " Specified the directory to open the nss database for the main\n"
72 " program. Must be specified if \"M\" is given in the order string\n" },
73 { /* opt_lib1DB */ PR_FALSE0, "nss_db",
74 " Specified the directory to open the nss database for library 1.\n"
75 " Must be specified if \"1\" is given in the order string\n" },
76 { /* opt_lib2DB */ PR_FALSE0, "nss_db",
77 " Specified the directory to open the nss database for library 2.\n"
78 " Must be specified if \"2\" is given in the order string\n" },
79 { /* opt_mainRO */ PR_FALSE0, NULL((void*)0),
80 " Open the main program's database read only.\n" },
81 { /* opt_lib1RO */ PR_FALSE0, NULL((void*)0),
82 " Open library 1's database read only.\n" },
83 { /* opt_lib2RO */ PR_FALSE0, NULL((void*)0),
84 " Open library 2's database read only.\n" },
85 { /* opt_mainCMD */ PR_FALSE0, "nss_command",
86 " Specifies the NSS command to execute in the main program.\n"
87 " Valid commands are: \n"
88 " key_slot, list_slots, list_certs, add_cert, none.\n"
89 " Default is \"none\".\n" },
90 { /* opt_lib1CMD */ PR_FALSE0, "nss_command",
91 " Specifies the NSS command to execute in library 1.\n" },
92 { /* opt_lib2CMD */ PR_FALSE0, "nss_command",
93 " Specifies the NSS command to execute in library 2.\n" },
94 { /* opt_mainTokNam */ PR_FALSE0, "token_name",
95 " Specifies the name of PKCS11 token for the main program's "
96 "database.\n" },
97 { /* opt_lib1TokNam */ PR_FALSE0, "token_name",
98 " Specifies the name of PKCS11 token for library 1's database.\n" },
99 { /* opt_lib2TokNam */ PR_FALSE0, "token_name",
100 " Specifies the name of PKCS11 token for library 2's database.\n" },
101 { /* opt_oldStype */ PR_FALSE0, NULL((void*)0),
102 " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
103 " program.\n" },
104 { /* opt_verbose */ PR_FALSE0, NULL((void*)0),
105 " Noisily output status to standard error\n" },
106 { /* opt_summarize */ PR_FALSE0, NULL((void*)0),
107 "report a summary of the test results\n" },
108 { /* opt_help */ PR_FALSE0, NULL((void*)0), " give this message\n" }
109};
110
111/*
112 * output our short help (table driven). (does not exit).
113 */
114static void
115short_help(const char *prog)
116{
117 int count = opt_last;
118 int i, words_found;
119
120 /* make sure all the tables are up to date before we allow compiles to
121 * succeed */
122 PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) == opt_last)extern void pr_static_assert(int arg[(sizeof(options_init) / sizeof
(secuCommandFlag) == opt_last) ? 1 : -1])
;
123 PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) ==extern void pr_static_assert(int arg[(sizeof(options_init) / sizeof
(secuCommandFlag) == sizeof(options_des) / sizeof(commandDescript
)) ? 1 : -1])
124 sizeof(options_des) / sizeof(commandDescript))extern void pr_static_assert(int arg[(sizeof(options_init) / sizeof
(secuCommandFlag) == sizeof(options_des) / sizeof(commandDescript
)) ? 1 : -1])
;
125
126 /* print the base usage */
127 fprintf(stderrstderr, "usage: %s ", prog);
128 for (i = 0, words_found = 0; i < count; i++) {
129 if (!options_des[i].required) {
130 fprintf(stderrstderr, "[");
131 }
132 if (options_init[i].longform) {
133 fprintf(stderrstderr, "--%s", options_init[i].longform);
134 words_found++;
135 } else {
136 fprintf(stderrstderr, "-%c", options_init[i].flag);
137 }
138 if (options_init[i].needsArg) {
139 if (options_des[i].arg) {
140 fprintf(stderrstderr, " %s", options_des[i].arg);
141 } else {
142 fprintf(stderrstderr, " arg");
143 }
144 words_found++;
145 }
146 if (!options_des[i].required) {
147 fprintf(stderrstderr, "]");
148 }
149 if (i < count - 1) {
150 if (words_found >= 5) {
151 fprintf(stderrstderr, "\n ");
152 words_found = 0;
153 } else {
154 fprintf(stderrstderr, " ");
155 }
156 }
157 }
158 fprintf(stderrstderr, "\n");
159}
160
161/*
162 * print out long help. like short_help, this does not exit
163 */
164static void
165long_help(const char *prog)
166{
167 int i;
168 int count = opt_last;
169
170 short_help(prog);
171 /* print the option descriptions */
172 fprintf(stderrstderr, "\n");
173 for (i = 0; i < count; i++) {
174 fprintf(stderrstderr, " ");
175 if (options_init[i].flag) {
176 fprintf(stderrstderr, "-%c", options_init[i].flag);
177 if (options_init[i].longform) {
178 fprintf(stderrstderr, ",");
179 }
180 }
181 if (options_init[i].longform) {
182 fprintf(stderrstderr, "--%s", options_init[i].longform);
183 }
184 if (options_init[i].needsArg) {
185 if (options_des[i].arg) {
186 fprintf(stderrstderr, " %s", options_des[i].arg);
187 } else {
188 fprintf(stderrstderr, " arg");
189 }
190 if (options_init[i].arg) {
191 fprintf(stderrstderr, " (default = \"%s\")", options_init[i].arg);
192 }
193 }
194 fprintf(stderrstderr, "\n%s", options_des[i].des);
195 }
196}
197
198/*
199 * record summary data
200 */
201struct bufferData {
202 char *data; /* lowest address of the buffer */
203 char *next; /* pointer to the next element on the buffer */
204 int len; /* length of the buffer */
205};
206
207/* our actual buffer. If data is NULL, then all append ops
208 * except are noops */
209static struct bufferData buffer = { NULL((void*)0), NULL((void*)0), 0 };
210
211#define CHUNK_SIZE1000 1000
212
213/*
214 * get our initial data. and set the buffer variables up. on failure,
215 * just don't initialize the buffer.
216 */
217static void
218initBuffer(void)
219{
220 buffer.data = PORT_AllocPORT_Alloc_Util(CHUNK_SIZE1000);
221 if (!buffer.data) {
222 return;
223 }
224 buffer.next = buffer.data;
225 buffer.len = CHUNK_SIZE1000;
226}
227
228/*
229 * grow the buffer. If we can't get more data, record a 'D' in the second
230 * to last record and allow the rest of the data to overwrite the last
231 * element.
232 */
233static void
234growBuffer(void)
235{
236 char *new = PORT_ReallocPORT_Realloc_Util(buffer.data, buffer.len + CHUNK_SIZE1000);
22
Null pointer value stored to 'buffer.data'
237 if (!new) {
23
Assuming 'new' is null
24
Taking true branch
238 buffer.data[buffer.len - 2] = 'D'; /* signal malloc failure in summary */
25
Array access (via field 'data') results in a null pointer dereference
239 /* buffer must always point to good memory if it exists */
240 buffer.next = buffer.data + (buffer.len - 1);
241 return;
242 }
243 buffer.next = new + (buffer.next - buffer.data);
244 buffer.data = new;
245 buffer.len += CHUNK_SIZE1000;
246}
247
248/*
249 * append a label, doubles as appending a single character.
250 */
251static void
252appendLabel(char label)
253{
254 if (!buffer.data
18.1
Field 'data' is non-null
) {
19
Taking false branch
255 return;
256 }
257
258 *buffer.next++ = label;
259 if (buffer.data + buffer.len >= buffer.next) {
20
Taking true branch
260 growBuffer();
21
Calling 'growBuffer'
261 }
262}
263
264/*
265 * append a string onto the buffer. The result will be <string>
266 */
267static void
268appendString(char *string)
269{
270 if (!buffer.data) {
271 return;
272 }
273
274 appendLabel('<');
275 while (*string) {
276 appendLabel(*string++);
277 }
278 appendLabel('>');
279}
280
281/*
282 * append a bool, T= true, F=false
283 */
284static void
285appendBool(PRBool bool)
286{
287 if (!buffer.data) {
288 return;
289 }
290
291 if (bool) {
292 appendLabel('t');
293 } else {
294 appendLabel('f');
295 }
296}
297
298/*
299 * append a single hex nibble.
300 */
301static void
302appendHex(unsigned char nibble)
303{
304 if (nibble <= 9) {
305 appendLabel('0' + nibble);
306 } else {
307 appendLabel('a' + nibble - 10);
308 }
309}
310
311/*
312 * append a 32 bit integer (even on a 64 bit platform).
313 * for simplicity append it as a hex value, full extension with 0x prefix.
314 */
315static void
316appendInt(unsigned int value)
317{
318 int i;
319
320 if (!buffer.data) {
321 return;
322 }
323
324 appendLabel('0');
325 appendLabel('x');
326 value = value & 0xffffffff; /* only look at the buttom 8 bytes */
327 for (i = 0; i < 8; i++) {
328 appendHex(value >> 28);
329 value = value << 4;
330 }
331}
332
333/* append a trust flag */
334static void
335appendFlags(unsigned int flag)
336{
337 char trust[10];
338 char *cp = trust;
339
340 trust[0] = 0;
341 printflags(trust, flag);
342 while (*cp) {
343 appendLabel(*cp++);
344 }
345}
346
347/*
348 * dump our buffer out with a result= flag so we can find it easily.
349 * free the buffer as a side effect.
350 */
351static void
352dumpBuffer(void)
353{
354 if (!buffer.data) {
355 return;
356 }
357
358 appendLabel(0); /* terminate */
359 printf("\nresult=%s\n", buffer.data);
360 PORT_FreePORT_Free_Util(buffer.data);
361 buffer.data = buffer.next = NULL((void*)0);
362 buffer.len = 0;
363}
364
365/*
366 * usage, like traditional usage, automatically exit
367 */
368static void
369usage(const char *prog)
370{
371 short_help(prog);
372 dumpBuffer();
373 exit(1);
374}
375
376/*
377 * like usage, except prints the long version of help
378 */
379static void
380usage_long(const char *prog)
381{
382 long_help(prog);
383 dumpBuffer();
384 exit(1);
385}
386
387static const char *
388bool2String(PRBool bool)
389{
390 return bool ? "true" : "false";
391}
392
393/*
394 * print out interesting info about the given slot
395 */
396void
397print_slot(PK11SlotInfo *slot, int log)
398{
399 if (log) {
400 fprintf(stderrstderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
401 PK11_GetSlotName(slot), PK11_GetTokenName(slot),
402 bool2String(PK11_IsPresent(slot)),
403 bool2String(PK11_IsReadOnly(slot)));
404 }
405 appendLabel('S');
406 appendString(PK11_GetTokenName(slot));
407 appendBool(PK11_IsPresent(slot));
408 appendBool(PK11_IsReadOnly(slot));
409}
410
411/*
412 * list all our slots
413 */
414void
415do_list_slots(const char *progName, int log)
416{
417 PK11SlotList *list;
418 PK11SlotListElement *le;
419
420 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, NULL((void*)0));
421 if (list == NULL((void*)0)) {
422 fprintf(stderrstderr, "ERROR: no tokens found %s\n",
423 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
424 appendLabel('S');
425 appendString("none");
426 return;
427 }
428
429 for (le = PK11_GetFirstSafe(list); le;
430 le = PK11_GetNextSafe(list, le, PR_TRUE1)) {
431 print_slot(le->slot, log);
432 }
433 PK11_FreeSlotList(list);
434}
435
436static PRBool
437sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
438{
439 char *commonNameA, *commonNameB;
440 int ret;
441
442 commonNameA = CERT_GetCommonName(&certa->subject);
443 commonNameB = CERT_GetCommonName(&certb->subject);
444
445 if (commonNameA == NULL((void*)0)) {
446 PORT_FreePORT_Free_Util(commonNameB);
447 return PR_TRUE1;
448 }
449 if (commonNameB == NULL((void*)0)) {
450 PORT_FreePORT_Free_Util(commonNameA);
451 return PR_FALSE0;
452 }
453 ret = PORT_Strcmpstrcmp(commonNameA, commonNameB);
454 PORT_FreePORT_Free_Util(commonNameA);
455 PORT_FreePORT_Free_Util(commonNameB);
456 return (ret < 0) ? PR_TRUE1 : PR_FALSE0;
457}
458
459/*
460 * list all the certs
461 */
462void
463do_list_certs(const char *progName, int log)
464{
465 CERTCertList *list;
466 CERTCertList *sorted;
467 CERTCertListNode *node;
468 CERTCertTrust trust;
469 unsigned int i;
470
471 list = PK11_ListCerts(PK11CertListUnique, NULL((void*)0));
472 if (list == NULL((void*)0)) {
473 fprintf(stderrstderr, "ERROR: no certs found %s\n",
474 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
475 appendLabel('C');
476 appendString("none");
477 return;
478 }
479
480 sorted = CERT_NewCertList();
481 if (sorted == NULL((void*)0)) {
482 fprintf(stderrstderr, "ERROR: no certs found %s\n",
483 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
484 appendLabel('C');
485 appendLabel('E');
486 appendInt(PORT_GetErrorPORT_GetError_Util());
487 return;
488 }
489
490 /* sort the list */
491 for (node = CERT_LIST_HEAD(list)((CERTCertListNode *)(&list->list)->next); !CERT_LIST_END(node, list)(((void *)node) == ((void *)&list->list));
492 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
493 CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL((void*)0));
494 }
495
496 for (node = CERT_LIST_HEAD(sorted)((CERTCertListNode *)(&sorted->list)->next); !CERT_LIST_END(node, sorted)(((void *)node) == ((void *)&sorted->list));
497 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
498 CERTCertificate *cert = node->cert;
499 char *commonName;
500
501 SECU_PrintCertNickname(node, stderrstderr);
502 if (log) {
503 fprintf(stderrstderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot) : "none");
504 fprintf(stderrstderr, "* Nickname=%s*\n", cert->nickname);
505 fprintf(stderrstderr, "* Subject=<%s>*\n", cert->subjectName);
506 fprintf(stderrstderr, "* Issuer=<%s>*\n", cert->issuerName);
507 fprintf(stderrstderr, "* SN=");
508 for (i = 0; i < cert->serialNumber.len; i++) {
509 if (i != 0)
510 fprintf(stderrstderr, ":");
511 fprintf(stderrstderr, "%02x", cert->serialNumber.data[0]);
512 }
513 fprintf(stderrstderr, " *\n");
514 }
515 appendLabel('C');
516 commonName = CERT_GetCommonName(&cert->subject);
517 appendString(commonName ? commonName : "*NoName*");
518 PORT_FreePORT_Free_Util(commonName);
519 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
520 appendFlags(trust.sslFlags);
521 appendFlags(trust.emailFlags);
522 appendFlags(trust.objectSigningFlags);
523 }
524 }
525 CERT_DestroyCertList(list);
526}
527
528/*
529 * need to implement yet... try to add a new certificate
530 */
531void
532do_add_cert(const char *progName, int log)
533{
534 PORT_Assert(/* do_add_cert not implemented */ 0)((0)?((void)0):PR_Assert("0","multinit.c",534));
535}
536
537/*
538 * display the current key slot
539 */
540void
541do_key_slot(const char *progName, int log)
542{
543 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
544 if (!slot) {
545 fprintf(stderrstderr, "ERROR: no internal key slot found %s\n",
546 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
547 appendLabel('K');
548 appendLabel('S');
549 appendString("none");
550 }
551 print_slot(slot, log);
552 PK11_FreeSlot(slot);
553}
554
555/*
556 * execute some NSS command.
557 */
558void
559do_command(const char *label, int initialized, secuCommandFlag *command,
560 const char *progName, int log)
561{
562 char *command_string;
563 if (!initialized) {
564 return;
565 }
566
567 if (command->activated) {
568 command_string = command->arg;
569 } else {
570 command_string = "none";
571 }
572
573 if (log) {
574 fprintf(stderrstderr, "*Executing nss command \"%s\" for %s*\n",
575 command_string, label);
576 }
577
578 /* do something */
579 if (PORT_StrcasecmpPL_strcasecmp(command_string, "list_slots") == 0) {
580 do_list_slots(progName, log);
581 } else if (PORT_StrcasecmpPL_strcasecmp(command_string, "list_certs") == 0) {
582 do_list_certs(progName, log);
583 } else if (PORT_StrcasecmpPL_strcasecmp(command_string, "add_cert") == 0) {
584 do_add_cert(progName, log);
585 } else if (PORT_StrcasecmpPL_strcasecmp(command_string, "key_slot") == 0) {
586 do_key_slot(progName, log);
587 } else if (PORT_StrcasecmpPL_strcasecmp(command_string, "none") != 0) {
588 fprintf(stderrstderr, ">> Unknown command (%s)\n", command_string);
589 appendLabel('E');
590 appendString("bc");
591 usage_long(progName);
592 }
593}
594
595/*
596 * functions do handle
597 * different library initializations.
598 */
599static int main_initialized;
600static int lib1_initialized;
601static int lib2_initialized;
602
603void
604main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
605 int readOnly, const char *progName, int log)
606{
607 SECStatus rv;
608 if (log) {
609 fprintf(stderrstderr, "*NSS_Init for the main program*\n");
610 }
611 appendLabel('M');
612 if (!db->activated) {
613 fprintf(stderrstderr, ">> No main_db has been specified\n");
614 usage(progName);
615 }
616 if (main_initialized) {
617 fprintf(stderrstderr, "Warning: Second initialization of Main\n");
618 appendLabel('E');
619 appendString("2M");
620 }
621 if (tokNam->activated) {
622 PK11_ConfigurePKCS11(NULL((void*)0), NULL((void*)0), NULL((void*)0), tokNam->arg,
623 NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, 0);
624 }
625 rv = NSS_Initialize(db->arg, "", "", "",
626 NSS_INIT_NOROOTINIT0x10 |
627 (readOnly ? NSS_INIT_READONLY0x1 : 0));
628 if (rv != SECSuccess) {
629 appendLabel('E');
630 appendInt(PORT_GetErrorPORT_GetError_Util());
631 fprintf(stderrstderr, ">> %s\n", SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
632 dumpBuffer();
633 exit(1);
634 }
635 main_initialized = 1;
636}
637
638void
639main_Do(secuCommandFlag *command, const char *progName, int log)
640{
641 do_command("main", main_initialized, command, progName, log);
642}
643
644void
645main_Shutdown(int old_style, const char *progName, int log)
646{
647 SECStatus rv;
648 appendLabel('N');
18
Calling 'appendLabel'
649 if (log) {
650 fprintf(stderrstderr, "*NSS_Shutdown for the main program*\n");
651 }
652 if (!main_initialized) {
653 fprintf(stderrstderr, "Warning: Main shutdown without corresponding init\n");
654 }
655 if (old_style) {
656 rv = NSS_Shutdown();
657 } else {
658 rv = NSS_ShutdownContext(NULL((void*)0));
659 }
660 fprintf(stderrstderr, "Shutdown main state = %d\n", rv);
661 if (rv != SECSuccess) {
662 appendLabel('E');
663 appendInt(PORT_GetErrorPORT_GetError_Util());
664 fprintf(stderrstderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
665 }
666 main_initialized = 0;
667}
668
669/* common library init */
670NSSInitContext *
671lib_Init(const char *lableString, char label, int initialized,
672 secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
673 const char *progName, int log)
674{
675 NSSInitContext *ctxt;
676 NSSInitParameters initStrings;
677 NSSInitParameters *initStringPtr = NULL((void*)0);
678
679 appendLabel(label);
680 if (log) {
681 fprintf(stderrstderr, "*NSS_Init for %s*\n", lableString);
682 }
683
684 if (!db->activated) {
685 fprintf(stderrstderr, ">> No %s_db has been specified\n", lableString);
686 usage(progName);
687 }
688 if (initialized) {
689 fprintf(stderrstderr, "Warning: Second initialization of %s\n", lableString);
690 }
691 if (tokNam->activated) {
692 PORT_Memsetmemset(&initStrings, 0, sizeof(initStrings));
693 initStrings.length = sizeof(initStrings);
694 initStrings.dbTokenDescription = tokNam->arg;
695 initStringPtr = &initStrings;
696 }
697 ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr,
698 NSS_INIT_NOROOTINIT0x10 |
699 (readonly ? NSS_INIT_READONLY0x1 : 0));
700 if (ctxt == NULL((void*)0)) {
701 appendLabel('E');
702 appendInt(PORT_GetErrorPORT_GetError_Util());
703 fprintf(stderrstderr, ">> %s\n", SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
704 dumpBuffer();
705 exit(1);
706 }
707 return ctxt;
708}
709
710/* common library shutdown */
711void
712lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
713 int initialize, const char *progName, int log)
714{
715 SECStatus rv;
716 appendLabel(label);
717 if (log) {
718 fprintf(stderrstderr, "*NSS_Shutdown for %s\n*", labelString);
719 }
720 if (!initialize) {
721 fprintf(stderrstderr, "Warning: %s shutdown without corresponding init\n",
722 labelString);
723 }
724 rv = NSS_ShutdownContext(ctx);
725 fprintf(stderrstderr, "Shutdown %s state = %d\n", labelString, rv);
726 if (rv != SECSuccess) {
727 appendLabel('E');
728 appendInt(PORT_GetErrorPORT_GetError_Util());
729 fprintf(stderrstderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
730 }
731}
732
733static NSSInitContext *lib1_context;
734static NSSInitContext *lib2_context;
735void
736lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
737 int readOnly, const char *progName, int log)
738{
739 lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam,
740 readOnly, progName, log);
741 lib1_initialized = 1;
742}
743
744void
745lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
746 int readOnly, const char *progName, int log)
747{
748 lib2_context = lib_Init("lib2", '2', lib2_initialized,
749 db, tokNam, readOnly, progName, log);
750 lib2_initialized = 1;
751}
752
753void
754lib1_Do(secuCommandFlag *command, const char *progName, int log)
755{
756 do_command("lib1", lib1_initialized, command, progName, log);
757}
758
759void
760lib2_Do(secuCommandFlag *command, const char *progName, int log)
761{
762 do_command("lib2", lib2_initialized, command, progName, log);
763}
764
765void
766lib1_Shutdown(const char *progName, int log)
767{
768 lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log);
769 lib1_initialized = 0;
770 /* don't clear lib1_Context, so we can test multiple attempts to close
771 * the same context produces correct errors*/
772}
773
774void
775lib2_Shutdown(const char *progName, int log)
776{
777 lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log);
778 lib2_initialized = 0;
779 /* don't clear lib2_Context, so we can test multiple attempts to close
780 * the same context produces correct errors*/
781}
782
783int
784main(int argc, char **argv)
785{
786 SECStatus rv;
787 secuCommand libinit;
788 char *progName;
789 char *order;
790 secuCommandFlag *options;
791 int log = 0;
792
793 progName = strrchr(argv[0], '/');
794 progName = progName ? progName + 1 : argv[0];
1
Assuming 'progName' is non-null
2
'?' condition is true
795
796 libinit.numCommands = 0;
797 libinit.commands = 0;
798 libinit.numOptions = opt_last;
799 options = (secuCommandFlag *)PORT_AllocPORT_Alloc_Util(sizeof(options_init));
800 if (options == NULL((void*)0)) {
3
Assuming 'options' is not equal to NULL
4
Taking false branch
801 fprintf(stderrstderr, ">> %s:Not enough free memory to run command\n",
802 progName);
803 exit(1);
804 }
805 PORT_Memcpymemcpy(options, options_init, sizeof(options_init));
806 libinit.options = options;
807
808 rv = SECU_ParseCommandLine(argc, argv, progName, &libinit);
809 if (rv != SECSuccess) {
5
Assuming 'rv' is equal to SECSuccess
6
Taking false branch
810 usage(progName);
811 }
812
813 if (libinit.options[opt_help].activated) {
7
Assuming field 'activated' is 0
8
Taking false branch
814 long_help(progName);
815 exit(0);
816 }
817
818 log = libinit.options[opt_verbose].activated;
819 if (libinit.options[opt_summary].activated) {
9
Assuming field 'activated' is not equal to 0
10
Taking true branch
820 initBuffer();
821 }
822
823 order = libinit.options[opt_liborder].arg;
824 if (!order) {
11
Assuming 'order' is non-null
12
Taking false branch
825 usage(progName);
826 }
827
828 if (log) {
13
Assuming 'log' is 0
14
Taking false branch
829 fprintf(stderrstderr, "* initializing with order \"%s\"*\n", order);
830 }
831
832 for (; *order; order++) {
15
Loop condition is true. Entering loop body
833 switch (*order) {
16
Control jumps to 'case 109:' at line 852
834 case 'M':
835 main_Init(&libinit.options[opt_mainDB],
836 &libinit.options[opt_mainTokNam],
837 libinit.options[opt_mainRO].activated,
838 progName, log);
839 break;
840 case '1':
841 lib1_Init(&libinit.options[opt_lib1DB],
842 &libinit.options[opt_lib1TokNam],
843 libinit.options[opt_lib1RO].activated,
844 progName, log);
845 break;
846 case '2':
847 lib2_Init(&libinit.options[opt_lib2DB],
848 &libinit.options[opt_lib2TokNam],
849 libinit.options[opt_lib2RO].activated,
850 progName, log);
851 break;
852 case 'm':
853 main_Shutdown(libinit.options[opt_oldStyle].activated,
17
Calling 'main_Shutdown'
854 progName, log);
855 break;
856 case 'i':
857 lib1_Shutdown(progName, log);
858 break;
859 case 'z':
860 lib2_Shutdown(progName, log);
861 break;
862 default:
863 fprintf(stderrstderr, ">> Unknown init/shutdown command \"%c\"", *order);
864 usage_long(progName);
865 }
866 main_Do(&libinit.options[opt_mainCMD], progName, log);
867 lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
868 lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
869 }
870
871 if (NSS_IsInitialized()) {
872 appendLabel('X');
873 fprintf(stderrstderr, "Warning: NSS is initialized\n");
874 }
875 dumpBuffer();
876
877 exit(0);
878}