security/nss/cmd/lib/basicutil.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial