| 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 | } |