| File: | root/firefox-clang/security/nss/cmd/lib/basicutil.c |
| Warning: | line 570, column 28 Dereference of null pointer |
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 | ** secutil.c - various functions used by security stuff | |||
| 6 | ** | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include "prtypes.h" | |||
| 10 | #include "prtime.h" | |||
| 11 | #include "prlong.h" | |||
| 12 | #include "prerror.h" | |||
| 13 | #include "prprf.h" | |||
| 14 | #include "plgetopt.h" | |||
| 15 | #include "prenv.h" | |||
| 16 | #include "prnetdb.h" | |||
| 17 | ||||
| 18 | #include "basicutil.h" | |||
| 19 | #include <stdarg.h> | |||
| 20 | #include <stddef.h> | |||
| 21 | #include <sys/stat.h> | |||
| 22 | #include <errno(*__errno_location ()).h> | |||
| 23 | ||||
| 24 | #ifdef XP_UNIX1 | |||
| 25 | #include <unistd.h> | |||
| 26 | #endif | |||
| 27 | ||||
| 28 | #include "secoid.h" | |||
| 29 | ||||
| 30 | extern long DER_GetIntegerDER_GetInteger_Util(const SECItem *src); | |||
| 31 | ||||
| 32 | static PRBool wrapEnabled = PR_TRUE1; | |||
| 33 | ||||
| 34 | void | |||
| 35 | SECU_EnableWrap(PRBool enable) | |||
| 36 | { | |||
| 37 | wrapEnabled = enable; | |||
| 38 | } | |||
| 39 | ||||
| 40 | PRBool | |||
| 41 | SECU_GetWrapEnabled(void) | |||
| 42 | { | |||
| 43 | return wrapEnabled; | |||
| 44 | } | |||
| 45 | ||||
| 46 | void | |||
| 47 | SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg, | |||
| 48 | ...) | |||
| 49 | { | |||
| 50 | va_list args; | |||
| 51 | PRErrorCode err = PORT_GetErrorPORT_GetError_Util(); | |||
| 52 | const char *errString = PORT_ErrorToString(err)PR_ErrorToString((err), 0); | |||
| 53 | ||||
| 54 | va_start(args, msg)__builtin_va_start(args, msg); | |||
| 55 | ||||
| 56 | SECU_Indent(out, level); | |||
| 57 | fprintf(out, "%s: ", progName); | |||
| 58 | vfprintf(out, msg, args); | |||
| 59 | if (errString != NULL((void*)0) && PORT_Strlen(errString)strlen(errString) > 0) | |||
| 60 | fprintf(out, ": %s\n", errString); | |||
| 61 | else | |||
| 62 | fprintf(out, ": error %d\n", (int)err); | |||
| 63 | ||||
| 64 | va_end(args)__builtin_va_end(args); | |||
| 65 | } | |||
| 66 | ||||
| 67 | void | |||
| 68 | SECU_PrintError(const char *progName, const char *msg, ...) | |||
| 69 | { | |||
| 70 | va_list args; | |||
| 71 | PRErrorCode err = PORT_GetErrorPORT_GetError_Util(); | |||
| 72 | const char *errName = PR_ErrorToName(err); | |||
| 73 | const char *errString = PR_ErrorToString(err, 0); | |||
| 74 | ||||
| 75 | va_start(args, msg)__builtin_va_start(args, msg); | |||
| 76 | ||||
| 77 | fprintf(stderrstderr, "%s: ", progName); | |||
| 78 | vfprintf(stderrstderr, msg, args); | |||
| 79 | ||||
| 80 | if (errName != NULL((void*)0)) { | |||
| 81 | fprintf(stderrstderr, ": %s", errName); | |||
| 82 | } else { | |||
| 83 | fprintf(stderrstderr, ": error %d", (int)err); | |||
| 84 | } | |||
| 85 | ||||
| 86 | if (errString != NULL((void*)0) && PORT_Strlen(errString)strlen(errString) > 0) | |||
| 87 | fprintf(stderrstderr, ": %s\n", errString); | |||
| 88 | ||||
| 89 | va_end(args)__builtin_va_end(args); | |||
| 90 | } | |||
| 91 | ||||
| 92 | void | |||
| 93 | SECU_PrintSystemError(const char *progName, const char *msg, ...) | |||
| 94 | { | |||
| 95 | va_list args; | |||
| 96 | ||||
| 97 | va_start(args, msg)__builtin_va_start(args, msg); | |||
| 98 | fprintf(stderrstderr, "%s: ", progName); | |||
| 99 | vfprintf(stderrstderr, msg, args); | |||
| 100 | fprintf(stderrstderr, ": %s\n", strerror(errno(*__errno_location ()))); | |||
| 101 | va_end(args)__builtin_va_end(args); | |||
| 102 | } | |||
| 103 | ||||
| 104 | SECStatus | |||
| 105 | secu_StdinToItem(SECItem *dst) | |||
| 106 | { | |||
| 107 | unsigned char buf[1000]; | |||
| 108 | PRInt32 numBytes; | |||
| 109 | PRBool notDone = PR_TRUE1; | |||
| 110 | ||||
| 111 | dst->len = 0; | |||
| 112 | dst->data = NULL((void*)0); | |||
| 113 | ||||
| 114 | while (notDone) { | |||
| 115 | numBytes = PR_Read(PR_STDINPR_GetSpecialFD(PR_StandardInput), buf, sizeof(buf)); | |||
| 116 | ||||
| 117 | if (numBytes < 0) { | |||
| 118 | return SECFailure; | |||
| 119 | } | |||
| 120 | ||||
| 121 | if (numBytes == 0) | |||
| 122 | break; | |||
| 123 | ||||
| 124 | if (dst->data) { | |||
| 125 | unsigned char *p = dst->data; | |||
| 126 | dst->data = (unsigned char *)PORT_ReallocPORT_Realloc_Util(p, dst->len + numBytes); | |||
| 127 | if (!dst->data) { | |||
| 128 | PORT_FreePORT_Free_Util(p); | |||
| 129 | } | |||
| 130 | } else { | |||
| 131 | dst->data = (unsigned char *)PORT_AllocPORT_Alloc_Util(numBytes); | |||
| 132 | } | |||
| 133 | if (!dst->data) { | |||
| 134 | return SECFailure; | |||
| 135 | } | |||
| 136 | PORT_Memcpymemcpy(dst->data + dst->len, buf, numBytes); | |||
| 137 | dst->len += numBytes; | |||
| 138 | } | |||
| 139 | ||||
| 140 | return SECSuccess; | |||
| 141 | } | |||
| 142 | ||||
| 143 | SECStatus | |||
| 144 | SECU_FileToItem(SECItem *dst, PRFileDesc *src) | |||
| 145 | { | |||
| 146 | PRFileInfo info; | |||
| 147 | PRInt32 numBytes; | |||
| 148 | PRStatus prStatus; | |||
| 149 | ||||
| 150 | if (src == PR_STDINPR_GetSpecialFD(PR_StandardInput)) | |||
| 151 | return secu_StdinToItem(dst); | |||
| 152 | ||||
| 153 | prStatus = PR_GetOpenFileInfo(src, &info); | |||
| 154 | ||||
| 155 | if (prStatus != PR_SUCCESS) { | |||
| 156 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO); | |||
| 157 | return SECFailure; | |||
| 158 | } | |||
| 159 | ||||
| 160 | /* XXX workaround for 3.1, not all utils zero dst before sending */ | |||
| 161 | dst->data = 0; | |||
| 162 | if (!SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), dst, info.size)) | |||
| 163 | goto loser; | |||
| 164 | ||||
| 165 | numBytes = PR_Read(src, dst->data, info.size); | |||
| 166 | if (numBytes != info.size) { | |||
| 167 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO); | |||
| 168 | goto loser; | |||
| 169 | } | |||
| 170 | ||||
| 171 | return SECSuccess; | |||
| 172 | loser: | |||
| 173 | SECITEM_FreeItemSECITEM_FreeItem_Util(dst, PR_FALSE0); | |||
| 174 | dst->data = NULL((void*)0); | |||
| 175 | return SECFailure; | |||
| 176 | } | |||
| 177 | ||||
| 178 | SECStatus | |||
| 179 | SECU_TextFileToItem(SECItem *dst, PRFileDesc *src) | |||
| 180 | { | |||
| 181 | PRFileInfo info; | |||
| 182 | PRInt32 numBytes; | |||
| 183 | PRStatus prStatus; | |||
| 184 | unsigned char *buf; | |||
| 185 | ||||
| 186 | if (src == PR_STDINPR_GetSpecialFD(PR_StandardInput)) | |||
| 187 | return secu_StdinToItem(dst); | |||
| 188 | ||||
| 189 | prStatus = PR_GetOpenFileInfo(src, &info); | |||
| 190 | ||||
| 191 | if (prStatus != PR_SUCCESS) { | |||
| 192 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO); | |||
| 193 | return SECFailure; | |||
| 194 | } | |||
| 195 | ||||
| 196 | buf = (unsigned char *)PORT_AllocPORT_Alloc_Util(info.size); | |||
| 197 | if (!buf) | |||
| 198 | return SECFailure; | |||
| 199 | ||||
| 200 | numBytes = PR_Read(src, buf, info.size); | |||
| 201 | if (numBytes != info.size) { | |||
| 202 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO); | |||
| 203 | goto loser; | |||
| 204 | } | |||
| 205 | ||||
| 206 | if (buf[numBytes - 1] == '\n') | |||
| 207 | numBytes--; | |||
| 208 | #ifdef _WINDOWS | |||
| 209 | if (buf[numBytes - 1] == '\r') | |||
| 210 | numBytes--; | |||
| 211 | #endif | |||
| 212 | ||||
| 213 | /* XXX workaround for 3.1, not all utils zero dst before sending */ | |||
| 214 | dst->data = 0; | |||
| 215 | if (!SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), dst, numBytes)) | |||
| 216 | goto loser; | |||
| 217 | ||||
| 218 | memcpy(dst->data, buf, numBytes); | |||
| 219 | ||||
| 220 | PORT_FreePORT_Free_Util(buf); | |||
| 221 | return SECSuccess; | |||
| 222 | loser: | |||
| 223 | PORT_FreePORT_Free_Util(buf); | |||
| 224 | return SECFailure; | |||
| 225 | } | |||
| 226 | ||||
| 227 | #define INDENT_MULT4 4 | |||
| 228 | void | |||
| 229 | SECU_Indent(FILE *out, int level) | |||
| 230 | { | |||
| 231 | int i; | |||
| 232 | ||||
| 233 | for (i = 0; i < level; i++) { | |||
| 234 | fprintf(out, " "); | |||
| 235 | } | |||
| 236 | } | |||
| 237 | ||||
| 238 | void | |||
| 239 | SECU_Newline(FILE *out) | |||
| 240 | { | |||
| 241 | fprintf(out, "\n"); | |||
| 242 | } | |||
| 243 | ||||
| 244 | void | |||
| 245 | SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level) | |||
| 246 | { | |||
| 247 | unsigned i; | |||
| 248 | int column = 0; | |||
| 249 | PRBool isString = PR_TRUE1; | |||
| 250 | PRBool isWhiteSpace = PR_TRUE1; | |||
| 251 | PRBool printedHex = PR_FALSE0; | |||
| 252 | unsigned int limit = 15; | |||
| 253 | ||||
| 254 | if (m) { | |||
| 255 | SECU_Indent(out, level); | |||
| 256 | fprintf(out, "%s:", m); | |||
| 257 | level++; | |||
| 258 | if (wrapEnabled) | |||
| 259 | fprintf(out, "\n"); | |||
| 260 | } | |||
| 261 | ||||
| 262 | if (wrapEnabled) { | |||
| 263 | SECU_Indent(out, level); | |||
| 264 | column = level * INDENT_MULT4; | |||
| 265 | } | |||
| 266 | if (!data->len) { | |||
| 267 | fprintf(out, "(empty)\n"); | |||
| 268 | return; | |||
| 269 | } | |||
| 270 | /* take a pass to see if it's all printable. */ | |||
| 271 | for (i = 0; i < data->len; i++) { | |||
| 272 | unsigned char val = data->data[i]; | |||
| 273 | if (!val || !isprint(val)((*__ctype_b_loc ())[(int) ((val))] & (unsigned short int ) _ISprint)) { | |||
| 274 | isString = PR_FALSE0; | |||
| 275 | break; | |||
| 276 | } | |||
| 277 | if (isWhiteSpace && !isspace(val)((*__ctype_b_loc ())[(int) ((val))] & (unsigned short int ) _ISspace)) { | |||
| 278 | isWhiteSpace = PR_FALSE0; | |||
| 279 | } | |||
| 280 | } | |||
| 281 | ||||
| 282 | /* Short values, such as bit strings (which are printed with this | |||
| 283 | ** function) often look like strings, but we want to see the bits. | |||
| 284 | ** so this test assures that short values will be printed in hex, | |||
| 285 | ** perhaps in addition to being printed as strings. | |||
| 286 | ** The threshold size (4 bytes) is arbitrary. | |||
| 287 | */ | |||
| 288 | if (!isString || data->len <= 4) { | |||
| 289 | for (i = 0; i < data->len; i++) { | |||
| 290 | if (i != data->len - 1) { | |||
| 291 | fprintf(out, "%02x:", data->data[i]); | |||
| 292 | column += 3; | |||
| 293 | } else { | |||
| 294 | fprintf(out, "%02x", data->data[i]); | |||
| 295 | column += 2; | |||
| 296 | break; | |||
| 297 | } | |||
| 298 | if (wrapEnabled && | |||
| 299 | (column > 76 || (i % 16 == limit))) { | |||
| 300 | SECU_Newline(out); | |||
| 301 | SECU_Indent(out, level); | |||
| 302 | column = level * INDENT_MULT4; | |||
| 303 | limit = i % 16; | |||
| 304 | } | |||
| 305 | } | |||
| 306 | printedHex = PR_TRUE1; | |||
| 307 | } | |||
| 308 | if (isString && !isWhiteSpace) { | |||
| 309 | if (printedHex != PR_FALSE0) { | |||
| 310 | SECU_Newline(out); | |||
| 311 | SECU_Indent(out, level); | |||
| 312 | column = level * INDENT_MULT4; | |||
| 313 | } | |||
| 314 | for (i = 0; i < data->len; i++) { | |||
| 315 | unsigned char val = data->data[i]; | |||
| 316 | ||||
| 317 | if (val) { | |||
| 318 | fprintf(out, "%c", val); | |||
| 319 | column++; | |||
| 320 | } else { | |||
| 321 | column = 77; | |||
| 322 | } | |||
| 323 | if (wrapEnabled && column > 76) { | |||
| 324 | SECU_Newline(out); | |||
| 325 | SECU_Indent(out, level); | |||
| 326 | column = level * INDENT_MULT4; | |||
| 327 | } | |||
| 328 | } | |||
| 329 | } | |||
| 330 | ||||
| 331 | if (column != level * INDENT_MULT4) { | |||
| 332 | SECU_Newline(out); | |||
| 333 | } | |||
| 334 | } | |||
| 335 | ||||
| 336 | const char *hex = "0123456789abcdef"; | |||
| 337 | ||||
| 338 | const char printable[257] = { | |||
| 339 | "................" /* 0x */ | |||
| 340 | "................" /* 1x */ | |||
| 341 | " !\"#$%&'()*+,-./" /* 2x */ | |||
| 342 | "0123456789:;<=>?" /* 3x */ | |||
| 343 | "@ABCDEFGHIJKLMNO" /* 4x */ | |||
| 344 | "PQRSTUVWXYZ[\\]^_" /* 5x */ | |||
| 345 | "`abcdefghijklmno" /* 6x */ | |||
| 346 | "pqrstuvwxyz{|}~." /* 7x */ | |||
| 347 | "................" /* 8x */ | |||
| 348 | "................" /* 9x */ | |||
| 349 | "................" /* ax */ | |||
| 350 | "................" /* bx */ | |||
| 351 | "................" /* cx */ | |||
| 352 | "................" /* dx */ | |||
| 353 | "................" /* ex */ | |||
| 354 | "................" /* fx */ | |||
| 355 | }; | |||
| 356 | ||||
| 357 | void | |||
| 358 | SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len) | |||
| 359 | { | |||
| 360 | const unsigned char *cp = (const unsigned char *)vp; | |||
| 361 | char buf[80]; | |||
| 362 | char *bp; | |||
| 363 | char *ap; | |||
| 364 | ||||
| 365 | fprintf(out, "%s [Len: %d]\n", msg, len); | |||
| 366 | memset(buf, ' ', sizeof buf); | |||
| 367 | bp = buf; | |||
| 368 | ap = buf + 50; | |||
| 369 | while (--len >= 0) { | |||
| 370 | unsigned char ch = *cp++; | |||
| 371 | *bp++ = hex[(ch >> 4) & 0xf]; | |||
| 372 | *bp++ = hex[ch & 0xf]; | |||
| 373 | *bp++ = ' '; | |||
| 374 | *ap++ = printable[ch]; | |||
| 375 | if (ap - buf >= 66) { | |||
| 376 | *ap = 0; | |||
| 377 | fprintf(out, " %s\n", buf); | |||
| 378 | memset(buf, ' ', sizeof buf); | |||
| 379 | bp = buf; | |||
| 380 | ap = buf + 50; | |||
| 381 | } | |||
| 382 | } | |||
| 383 | if (bp > buf) { | |||
| 384 | *ap = 0; | |||
| 385 | fprintf(out, " %s\n", buf); | |||
| 386 | } | |||
| 387 | } | |||
| 388 | ||||
| 389 | /* This expents i->data[0] to be the MSB of the integer. | |||
| 390 | ** if you want to print a DER-encoded integer (with the tag and length) | |||
| 391 | ** call SECU_PrintEncodedInteger(); | |||
| 392 | */ | |||
| 393 | void | |||
| 394 | SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level) | |||
| 395 | { | |||
| 396 | int iv; | |||
| 397 | ||||
| 398 | if (!i || !i->len || !i->data) { | |||
| 399 | SECU_Indent(out, level); | |||
| 400 | if (m) { | |||
| 401 | fprintf(out, "%s: (null)\n", m); | |||
| 402 | } else { | |||
| 403 | fprintf(out, "(null)\n"); | |||
| 404 | } | |||
| 405 | } else if (i->len > 4) { | |||
| 406 | SECU_PrintAsHex(out, i, m, level); | |||
| 407 | } else { | |||
| 408 | if (i->type == siUnsignedInteger && *i->data & 0x80) { | |||
| 409 | /* Make sure i->data has zero in the highest bite | |||
| 410 | * if i->data is an unsigned integer */ | |||
| 411 | SECItem tmpI; | |||
| 412 | char data[] = { 0, 0, 0, 0, 0 }; | |||
| 413 | ||||
| 414 | PORT_Memcpymemcpy(data + 1, i->data, i->len); | |||
| 415 | tmpI.len = i->len + 1; | |||
| 416 | tmpI.data = (void *)data; | |||
| 417 | ||||
| 418 | iv = DER_GetIntegerDER_GetInteger_Util(&tmpI); | |||
| 419 | } else { | |||
| 420 | iv = DER_GetIntegerDER_GetInteger_Util(i); | |||
| 421 | } | |||
| 422 | SECU_Indent(out, level); | |||
| 423 | if (m) { | |||
| 424 | fprintf(out, "%s: %d (0x%x)\n", m, iv, iv); | |||
| 425 | } else { | |||
| 426 | fprintf(out, "%d (0x%x)\n", iv, iv); | |||
| 427 | } | |||
| 428 | } | |||
| 429 | } | |||
| 430 | ||||
| 431 | #if defined(DEBUG1) || defined(FORCE_PR_ASSERT) | |||
| 432 | /* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */ | |||
| 433 | static PRBool | |||
| 434 | HasShortDuplicate(int i, secuCommandFlag *a, int count) | |||
| 435 | { | |||
| 436 | char target = a[i].flag; | |||
| 437 | int j; | |||
| 438 | ||||
| 439 | /* duplicate '\0' flags are okay, they are used with long forms */ | |||
| 440 | for (j = i + 1; j < count; j++) { | |||
| 441 | if (a[j].flag && a[j].flag == target) { | |||
| 442 | return PR_TRUE1; | |||
| 443 | } | |||
| 444 | } | |||
| 445 | return PR_FALSE0; | |||
| 446 | } | |||
| 447 | ||||
| 448 | /* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */ | |||
| 449 | static PRBool | |||
| 450 | HasLongDuplicate(int i, secuCommandFlag *a, int count) | |||
| 451 | { | |||
| 452 | int j; | |||
| 453 | char *target = a[i].longform; | |||
| 454 | ||||
| 455 | if (!target) | |||
| 456 | return PR_FALSE0; | |||
| 457 | ||||
| 458 | for (j = i + 1; j < count; j++) { | |||
| 459 | if (a[j].longform && strcmp(a[j].longform, target) == 0) { | |||
| 460 | return PR_TRUE1; | |||
| 461 | } | |||
| 462 | } | |||
| 463 | return PR_FALSE0; | |||
| 464 | } | |||
| 465 | ||||
| 466 | /* Returns true iff a has no short or long form duplicates | |||
| 467 | */ | |||
| 468 | PRBool | |||
| 469 | HasNoDuplicates(secuCommandFlag *a, int count) | |||
| 470 | { | |||
| 471 | int i; | |||
| 472 | ||||
| 473 | for (i = 0; i < count; i++) { | |||
| 474 | if (a[i].flag && HasShortDuplicate(i, a, count)) { | |||
| 475 | return PR_FALSE0; | |||
| 476 | } | |||
| 477 | if (a[i].longform && HasLongDuplicate(i, a, count)) { | |||
| 478 | return PR_FALSE0; | |||
| 479 | } | |||
| 480 | } | |||
| 481 | return PR_TRUE1; | |||
| 482 | } | |||
| 483 | #endif | |||
| 484 | ||||
| 485 | SECStatus | |||
| 486 | SECU_ParseCommandLine(int argc, char **argv, char *progName, | |||
| 487 | const secuCommand *cmd) | |||
| 488 | { | |||
| 489 | PRBool found; | |||
| 490 | PLOptState *optstate; | |||
| 491 | PLOptStatus status; | |||
| 492 | char *optstring; | |||
| 493 | PLLongOpt *longopts = NULL((void*)0); | |||
| ||||
| 494 | int i, j; | |||
| 495 | int lcmd = 0, lopt = 0; | |||
| 496 | ||||
| 497 | PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands))((HasNoDuplicates(cmd->commands, cmd->numCommands)) ? ( (void)0) : PR_Assert("HasNoDuplicates(cmd->commands, cmd->numCommands)" , "/root/firefox-clang/security/nss/cmd/lib/basicutil.c", 497 )); | |||
| 498 | PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions))((HasNoDuplicates(cmd->options, cmd->numOptions)) ? ((void )0) : PR_Assert("HasNoDuplicates(cmd->options, cmd->numOptions)" , "/root/firefox-clang/security/nss/cmd/lib/basicutil.c", 498 )); | |||
| 499 | ||||
| 500 | optstring = (char *)PORT_AllocPORT_Alloc_Util(cmd->numCommands + 2 * cmd->numOptions + 1); | |||
| 501 | if (optstring == NULL((void*)0)) | |||
| 502 | return SECFailure; | |||
| 503 | ||||
| 504 | j = 0; | |||
| 505 | for (i = 0; i
| |||
| 506 | if (cmd->commands[i].flag) /* single character option ? */ | |||
| 507 | optstring[j++] = cmd->commands[i].flag; | |||
| 508 | if (cmd->commands[i].longform) | |||
| 509 | lcmd++; | |||
| 510 | } | |||
| 511 | for (i = 0; i
| |||
| 512 | if (cmd->options[i].flag) { | |||
| 513 | optstring[j++] = cmd->options[i].flag; | |||
| 514 | if (cmd->options[i].needsArg) | |||
| 515 | optstring[j++] = ':'; | |||
| 516 | } | |||
| 517 | if (cmd->options[i].longform) | |||
| 518 | lopt++; | |||
| 519 | } | |||
| 520 | ||||
| 521 | optstring[j] = '\0'; | |||
| 522 | ||||
| 523 | if (lcmd + lopt > 0) { | |||
| 524 | longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1)(PLLongOpt *)PORT_Alloc_Util(sizeof(PLLongOpt) * (lcmd + lopt + 1)); | |||
| 525 | if (!longopts) { | |||
| 526 | PORT_FreePORT_Free_Util(optstring); | |||
| 527 | return SECFailure; | |||
| 528 | } | |||
| 529 | ||||
| 530 | j = 0; | |||
| 531 | for (i = 0; j < lcmd && i < cmd->numCommands; i++) { | |||
| 532 | if (cmd->commands[i].longform) { | |||
| 533 | longopts[j].longOptName = cmd->commands[i].longform; | |||
| 534 | longopts[j].longOption = 0; | |||
| 535 | longopts[j++].valueRequired = cmd->commands[i].needsArg; | |||
| 536 | } | |||
| 537 | } | |||
| 538 | lopt += lcmd; | |||
| 539 | for (i = 0; j < lopt && i < cmd->numOptions; i++) { | |||
| 540 | if (cmd->options[i].longform) { | |||
| 541 | longopts[j].longOptName = cmd->options[i].longform; | |||
| 542 | longopts[j].longOption = 0; | |||
| 543 | longopts[j++].valueRequired = cmd->options[i].needsArg; | |||
| 544 | } | |||
| 545 | } | |||
| 546 | longopts[j].longOptName = NULL((void*)0); | |||
| 547 | } | |||
| 548 | ||||
| 549 | optstate = PL_CreateLongOptState(argc, argv, optstring, longopts); | |||
| 550 | if (!optstate) { | |||
| 551 | PORT_FreePORT_Free_Util(optstring); | |||
| 552 | PORT_FreePORT_Free_Util(longopts); | |||
| 553 | return SECFailure; | |||
| 554 | } | |||
| 555 | /* Parse command line arguments */ | |||
| 556 | while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { | |||
| 557 | const char *optstatelong; | |||
| 558 | char option = optstate->option; | |||
| 559 | ||||
| 560 | /* positional parameter, single-char option or long opt? */ | |||
| 561 | if (optstate->longOptIndex == -1) { | |||
| 562 | /* not a long opt */ | |||
| 563 | if (option == '\0') | |||
| 564 | continue; /* it's a positional parameter */ | |||
| 565 | optstatelong = ""; | |||
| 566 | } else { | |||
| 567 | /* long opt */ | |||
| 568 | if (option == '\0') | |||
| 569 | option = '\377'; /* force unequal with all flags */ | |||
| 570 | optstatelong = longopts[optstate->longOptIndex].longOptName; | |||
| ||||
| 571 | } | |||
| 572 | ||||
| 573 | found = PR_FALSE0; | |||
| 574 | ||||
| 575 | for (i = 0; i < cmd->numCommands; i++) { | |||
| 576 | if (cmd->commands[i].flag == option || | |||
| 577 | cmd->commands[i].longform == optstatelong) { | |||
| 578 | cmd->commands[i].activated = PR_TRUE1; | |||
| 579 | if (optstate->value) { | |||
| 580 | cmd->commands[i].arg = (char *)optstate->value; | |||
| 581 | } | |||
| 582 | found = PR_TRUE1; | |||
| 583 | break; | |||
| 584 | } | |||
| 585 | } | |||
| 586 | ||||
| 587 | if (found) | |||
| 588 | continue; | |||
| 589 | ||||
| 590 | for (i = 0; i < cmd->numOptions; i++) { | |||
| 591 | if (cmd->options[i].flag == option || | |||
| 592 | cmd->options[i].longform == optstatelong) { | |||
| 593 | cmd->options[i].activated = PR_TRUE1; | |||
| 594 | if (optstate->value) { | |||
| 595 | cmd->options[i].arg = (char *)optstate->value; | |||
| 596 | } else if (cmd->options[i].needsArg) { | |||
| 597 | status = PL_OPT_BAD; | |||
| 598 | goto loser; | |||
| 599 | } | |||
| 600 | found = PR_TRUE1; | |||
| 601 | break; | |||
| 602 | } | |||
| 603 | } | |||
| 604 | ||||
| 605 | if (!found) { | |||
| 606 | status = PL_OPT_BAD; | |||
| 607 | break; | |||
| 608 | } | |||
| 609 | } | |||
| 610 | ||||
| 611 | loser: | |||
| 612 | PL_DestroyOptState(optstate); | |||
| 613 | PORT_FreePORT_Free_Util(optstring); | |||
| 614 | if (longopts) | |||
| 615 | PORT_FreePORT_Free_Util(longopts); | |||
| 616 | if (status == PL_OPT_BAD) | |||
| 617 | return SECFailure; | |||
| 618 | return SECSuccess; | |||
| 619 | } | |||
| 620 | ||||
| 621 | char * | |||
| 622 | SECU_GetOptionArg(const secuCommand *cmd, int optionNum) | |||
| 623 | { | |||
| 624 | if (optionNum < 0 || optionNum >= cmd->numOptions) | |||
| 625 | return NULL((void*)0); | |||
| 626 | if (cmd->options[optionNum].activated) | |||
| 627 | return PL_strdup(cmd->options[optionNum].arg); | |||
| 628 | else | |||
| 629 | return NULL((void*)0); | |||
| 630 | } | |||
| 631 | ||||
| 632 | void | |||
| 633 | SECU_PrintPRandOSError(const char *progName) | |||
| 634 | { | |||
| 635 | char buffer[513]; | |||
| 636 | PRInt32 errLenInt = PR_GetErrorTextLength(); | |||
| 637 | size_t errLen = errLenInt < 0 ? 0 : (size_t)errLenInt; | |||
| 638 | if (errLen > 0 && errLen < sizeof buffer) { | |||
| 639 | PR_GetErrorText(buffer); | |||
| 640 | } | |||
| 641 | SECU_PrintError(progName, "function failed"); | |||
| 642 | if (errLen > 0 && errLen < sizeof buffer) { | |||
| 643 | PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\t%s\n", buffer); | |||
| 644 | } | |||
| 645 | } | |||
| 646 | ||||
| 647 | SECOidTag | |||
| 648 | SECU_StringToSignatureAlgTag(const char *alg) | |||
| 649 | { | |||
| 650 | SECOidTag hashAlgTag = SEC_OID_UNKNOWN; | |||
| 651 | ||||
| 652 | if (alg) { | |||
| 653 | if (!PL_strcmp(alg, "MD2")) { | |||
| 654 | hashAlgTag = SEC_OID_MD2; | |||
| 655 | } else if (!PL_strcmp(alg, "MD4")) { | |||
| 656 | hashAlgTag = SEC_OID_MD4; | |||
| 657 | } else if (!PL_strcmp(alg, "MD5")) { | |||
| 658 | hashAlgTag = SEC_OID_MD5; | |||
| 659 | } else if (!PL_strcmp(alg, "SHA1")) { | |||
| 660 | hashAlgTag = SEC_OID_SHA1; | |||
| 661 | } else if (!PL_strcmp(alg, "SHA224")) { | |||
| 662 | hashAlgTag = SEC_OID_SHA224; | |||
| 663 | } else if (!PL_strcmp(alg, "SHA256")) { | |||
| 664 | hashAlgTag = SEC_OID_SHA256; | |||
| 665 | } else if (!PL_strcmp(alg, "SHA384")) { | |||
| 666 | hashAlgTag = SEC_OID_SHA384; | |||
| 667 | } else if (!PL_strcmp(alg, "SHA512")) { | |||
| 668 | hashAlgTag = SEC_OID_SHA512; | |||
| 669 | } | |||
| 670 | } | |||
| 671 | return hashAlgTag; | |||
| 672 | } | |||
| 673 | ||||
| 674 | /* Caller ensures that dst is at least item->len*2+1 bytes long */ | |||
| 675 | void | |||
| 676 | SECU_SECItemToHex(const SECItem *item, char *dst) | |||
| 677 | { | |||
| 678 | if (dst && item && item->data) { | |||
| 679 | unsigned char *src = item->data; | |||
| 680 | unsigned int len = item->len; | |||
| 681 | for (; len > 0; --len, dst += 2) { | |||
| 682 | snprintf(dst, 3, "%02x", *src++); | |||
| 683 | } | |||
| 684 | } | |||
| 685 | } | |||
| 686 | ||||
| 687 | static unsigned char | |||
| 688 | nibble(char c) | |||
| 689 | { | |||
| 690 | c = PORT_Tolower((unsigned char)c)(__extension__ ({ int __res; if (sizeof ((unsigned char)c) > 1) { if (__builtin_constant_p ((unsigned char)c)) { int __c = ((unsigned char)c); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower ((unsigned char)c); } else __res = (*__ctype_tolower_loc ())[(int) ((unsigned char)c)]; __res; })); | |||
| 691 | return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 | |||
| 692 | : -1; | |||
| 693 | } | |||
| 694 | ||||
| 695 | SECStatus | |||
| 696 | SECU_SECItemHexStringToBinary(SECItem *srcdest) | |||
| 697 | { | |||
| 698 | unsigned int i; | |||
| 699 | ||||
| 700 | if (!srcdest) { | |||
| 701 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); | |||
| 702 | return SECFailure; | |||
| 703 | } | |||
| 704 | if (srcdest->len < 4 || (srcdest->len % 2)) { | |||
| 705 | /* too short to convert, or even number of characters */ | |||
| 706 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
| 707 | return SECFailure; | |||
| 708 | } | |||
| 709 | if (PORT_StrncasecmpPL_strncasecmp((const char *)srcdest->data, "0x", 2)) { | |||
| 710 | /* wrong prefix */ | |||
| 711 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
| 712 | return SECFailure; | |||
| 713 | } | |||
| 714 | ||||
| 715 | /* 1st pass to check for hex characters */ | |||
| 716 | for (i = 2; i < srcdest->len; i++) { | |||
| 717 | char c = PORT_Tolower(srcdest->data[i])(__extension__ ({ int __res; if (sizeof (srcdest->data[i]) > 1) { if (__builtin_constant_p (srcdest->data[i])) { int __c = (srcdest->data[i]); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (srcdest->data[i]); } else __res = (*__ctype_tolower_loc ( ))[(int) (srcdest->data[i])]; __res; })); | |||
| 718 | if (!((c >= '0' && c <= '9') || | |||
| 719 | (c >= 'a' && c <= 'f'))) { | |||
| 720 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
| 721 | return SECFailure; | |||
| 722 | } | |||
| 723 | } | |||
| 724 | ||||
| 725 | /* 2nd pass to convert */ | |||
| 726 | for (i = 2; i < srcdest->len; i += 2) { | |||
| 727 | srcdest->data[(i - 2) / 2] = (nibble(srcdest->data[i]) << 4) + | |||
| 728 | nibble(srcdest->data[i + 1]); | |||
| 729 | } | |||
| 730 | ||||
| 731 | /* adjust length */ | |||
| 732 | srcdest->len -= 2; | |||
| 733 | srcdest->len /= 2; | |||
| 734 | return SECSuccess; | |||
| 735 | } | |||
| 736 | ||||
| 737 | SECItem * | |||
| 738 | SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str) | |||
| 739 | { | |||
| 740 | int i = 0; | |||
| 741 | int byteval = 0; | |||
| 742 | int tmp = PORT_Strlen(str)strlen(str); | |||
| 743 | ||||
| 744 | PORT_Assert(item)((item) ? ((void)0) : PR_Assert("item", "/root/firefox-clang/security/nss/cmd/lib/basicutil.c" , 744)); | |||
| 745 | ||||
| 746 | if ((tmp % 2) != 0) { | |||
| 747 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); | |||
| 748 | return NULL((void*)0); | |||
| 749 | } | |||
| 750 | ||||
| 751 | item = SECITEM_AllocItemSECITEM_AllocItem_Util(arena, item, tmp / 2); | |||
| 752 | if (item == NULL((void*)0)) { | |||
| 753 | return NULL((void*)0); | |||
| 754 | } | |||
| 755 | ||||
| 756 | while (str[i]) { | |||
| 757 | if ((str[i] >= '0') && (str[i] <= '9')) { | |||
| 758 | tmp = str[i] - '0'; | |||
| 759 | } else if ((str[i] >= 'a') && (str[i] <= 'f')) { | |||
| 760 | tmp = str[i] - 'a' + 10; | |||
| 761 | } else if ((str[i] >= 'A') && (str[i] <= 'F')) { | |||
| 762 | tmp = str[i] - 'A' + 10; | |||
| 763 | } else { | |||
| 764 | if (!arena) { | |||
| 765 | SECITEM_FreeItemSECITEM_FreeItem_Util(item, PR_FALSE0); | |||
| 766 | } | |||
| 767 | return NULL((void*)0); | |||
| 768 | } | |||
| 769 | ||||
| 770 | byteval = byteval * 16 + tmp; | |||
| 771 | if ((i % 2) != 0) { | |||
| 772 | item->data[i / 2] = byteval; | |||
| 773 | byteval = 0; | |||
| 774 | } | |||
| 775 | i++; | |||
| 776 | } | |||
| 777 | ||||
| 778 | return item; | |||
| 779 | } | |||
| 780 | ||||
| 781 | SECStatus | |||
| 782 | SECU_ecName2params(ECCurveName curve, SECItem *params) | |||
| 783 | { | |||
| 784 | SECOidTag oidTag; | |||
| 785 | SECOidData *oidData = NULL((void*)0); | |||
| 786 | ||||
| 787 | switch (curve) { | |||
| 788 | case ECCurve_NIST_P256: | |||
| 789 | oidTag = SEC_OID_ANSIX962_EC_PRIME256V1; | |||
| 790 | break; | |||
| 791 | case ECCurve_NIST_P384: | |||
| 792 | oidTag = SEC_OID_SECG_EC_SECP384R1; | |||
| 793 | break; | |||
| 794 | case ECCurve_NIST_P521: | |||
| 795 | oidTag = SEC_OID_SECG_EC_SECP521R1; | |||
| 796 | break; | |||
| 797 | case ECCurve25519: | |||
| 798 | oidTag = SEC_OID_CURVE25519; | |||
| 799 | break; | |||
| 800 | case ECCurve_Ed25519: | |||
| 801 | oidTag = SEC_OID_ED25519_PUBLIC_KEY; | |||
| 802 | break; | |||
| 803 | default: | |||
| 804 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |||
| 805 | return SECFailure; | |||
| 806 | } | |||
| 807 | ||||
| 808 | oidData = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(oidTag); | |||
| 809 | if (oidData == NULL((void*)0)) { | |||
| 810 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |||
| 811 | return SECFailure; | |||
| 812 | } | |||
| 813 | ||||
| 814 | if (SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), params, (2 + oidData->oid.len)) == NULL((void*)0)) { | |||
| 815 | return SECFailure; | |||
| 816 | } | |||
| 817 | /* | |||
| 818 | * params->data needs to contain the ASN encoding of an object ID (OID) | |||
| 819 | * representing the named curve. The actual OID is in | |||
| 820 | * oidData->oid.data so we simply prepend 0x06 and OID length | |||
| 821 | */ | |||
| 822 | params->data[0] = SEC_ASN1_OBJECT_ID0x06; | |||
| 823 | params->data[1] = oidData->oid.len; | |||
| 824 | memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); | |||
| 825 | ||||
| 826 | return SECSuccess; | |||
| 827 | } |