File: | s/cmd/multinit/multinit.c |
Warning: | line 238, column 37 Array access (via field 'data') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
13 | typedef struct commandDescriptStr { | |||
14 | int required; | |||
15 | char *arg; | |||
16 | char *des; | |||
17 | } commandDescript; | |||
18 | ||||
19 | enum 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 | ||||
40 | static 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 | ||||
60 | static 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 | */ | |||
114 | static void | |||
115 | short_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 | */ | |||
164 | static void | |||
165 | long_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 | */ | |||
201 | struct 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 */ | |||
209 | static 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 | */ | |||
217 | static void | |||
218 | initBuffer(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 | */ | |||
233 | static void | |||
234 | growBuffer(void) | |||
235 | { | |||
236 | char *new = PORT_ReallocPORT_Realloc_Util(buffer.data, buffer.len + CHUNK_SIZE1000); | |||
237 | if (!new) { | |||
238 | buffer.data[buffer.len - 2] = 'D'; /* signal malloc failure in summary */ | |||
| ||||
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 | */ | |||
251 | static void | |||
252 | appendLabel(char label) | |||
253 | { | |||
254 | if (!buffer.data
| |||
255 | return; | |||
256 | } | |||
257 | ||||
258 | *buffer.next++ = label; | |||
259 | if (buffer.data + buffer.len >= buffer.next) { | |||
260 | growBuffer(); | |||
261 | } | |||
262 | } | |||
263 | ||||
264 | /* | |||
265 | * append a string onto the buffer. The result will be <string> | |||
266 | */ | |||
267 | static void | |||
268 | appendString(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 | */ | |||
284 | static void | |||
285 | appendBool(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 | */ | |||
301 | static void | |||
302 | appendHex(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 | */ | |||
315 | static void | |||
316 | appendInt(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 */ | |||
334 | static void | |||
335 | appendFlags(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 | */ | |||
351 | static void | |||
352 | dumpBuffer(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 | */ | |||
368 | static void | |||
369 | usage(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 | */ | |||
379 | static void | |||
380 | usage_long(const char *prog) | |||
381 | { | |||
382 | long_help(prog); | |||
383 | dumpBuffer(); | |||
384 | exit(1); | |||
385 | } | |||
386 | ||||
387 | static const char * | |||
388 | bool2String(PRBool bool) | |||
389 | { | |||
390 | return bool ? "true" : "false"; | |||
391 | } | |||
392 | ||||
393 | /* | |||
394 | * print out interesting info about the given slot | |||
395 | */ | |||
396 | void | |||
397 | print_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 | */ | |||
414 | void | |||
415 | do_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 | ||||
436 | static PRBool | |||
437 | sort_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 | */ | |||
462 | void | |||
463 | do_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 | */ | |||
531 | void | |||
532 | do_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 | */ | |||
540 | void | |||
541 | do_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 | */ | |||
558 | void | |||
559 | do_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 | */ | |||
599 | static int main_initialized; | |||
600 | static int lib1_initialized; | |||
601 | static int lib2_initialized; | |||
602 | ||||
603 | void | |||
604 | main_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 | ||||
638 | void | |||
639 | main_Do(secuCommandFlag *command, const char *progName, int log) | |||
640 | { | |||
641 | do_command("main", main_initialized, command, progName, log); | |||
642 | } | |||
643 | ||||
644 | void | |||
645 | main_Shutdown(int old_style, const char *progName, int log) | |||
646 | { | |||
647 | SECStatus rv; | |||
648 | appendLabel('N'); | |||
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 */ | |||
670 | NSSInitContext * | |||
671 | lib_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 */ | |||
711 | void | |||
712 | lib_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 | ||||
733 | static NSSInitContext *lib1_context; | |||
734 | static NSSInitContext *lib2_context; | |||
735 | void | |||
736 | lib1_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 | ||||
744 | void | |||
745 | lib2_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 | ||||
753 | void | |||
754 | lib1_Do(secuCommandFlag *command, const char *progName, int log) | |||
755 | { | |||
756 | do_command("lib1", lib1_initialized, command, progName, log); | |||
757 | } | |||
758 | ||||
759 | void | |||
760 | lib2_Do(secuCommandFlag *command, const char *progName, int log) | |||
761 | { | |||
762 | do_command("lib2", lib2_initialized, command, progName, log); | |||
763 | } | |||
764 | ||||
765 | void | |||
766 | lib1_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 | ||||
774 | void | |||
775 | lib2_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 | ||||
783 | int | |||
784 | main(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]; | |||
| ||||
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)) { | |||
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) { | |||
810 | usage(progName); | |||
811 | } | |||
812 | ||||
813 | if (libinit.options[opt_help].activated) { | |||
814 | long_help(progName); | |||
815 | exit(0); | |||
816 | } | |||
817 | ||||
818 | log = libinit.options[opt_verbose].activated; | |||
819 | if (libinit.options[opt_summary].activated) { | |||
820 | initBuffer(); | |||
821 | } | |||
822 | ||||
823 | order = libinit.options[opt_liborder].arg; | |||
824 | if (!order) { | |||
825 | usage(progName); | |||
826 | } | |||
827 | ||||
828 | if (log) { | |||
829 | fprintf(stderrstderr, "* initializing with order \"%s\"*\n", order); | |||
830 | } | |||
831 | ||||
832 | for (; *order; order++) { | |||
833 | switch (*order) { | |||
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, | |||
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 | } |