File: | s/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)" ,"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)" ,"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 < cmd->numCommands; 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 < cmd->numOptions; 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_Tolowertolower(c); | |||
691 | return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1; | |||
692 | } | |||
693 | ||||
694 | SECStatus | |||
695 | SECU_SECItemHexStringToBinary(SECItem *srcdest) | |||
696 | { | |||
697 | unsigned int i; | |||
698 | ||||
699 | if (!srcdest) { | |||
700 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); | |||
701 | return SECFailure; | |||
702 | } | |||
703 | if (srcdest->len < 4 || (srcdest->len % 2)) { | |||
704 | /* too short to convert, or even number of characters */ | |||
705 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
706 | return SECFailure; | |||
707 | } | |||
708 | if (PORT_StrncasecmpPL_strncasecmp((const char *)srcdest->data, "0x", 2)) { | |||
709 | /* wrong prefix */ | |||
710 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
711 | return SECFailure; | |||
712 | } | |||
713 | ||||
714 | /* 1st pass to check for hex characters */ | |||
715 | for (i = 2; i < srcdest->len; i++) { | |||
716 | char c = PORT_Tolowertolower(srcdest->data[i]); | |||
717 | if (!((c >= '0' && c <= '9') || | |||
718 | (c >= 'a' && c <= 'f'))) { | |||
719 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA); | |||
720 | return SECFailure; | |||
721 | } | |||
722 | } | |||
723 | ||||
724 | /* 2nd pass to convert */ | |||
725 | for (i = 2; i < srcdest->len; i += 2) { | |||
726 | srcdest->data[(i - 2) / 2] = (nibble(srcdest->data[i]) << 4) + | |||
727 | nibble(srcdest->data[i + 1]); | |||
728 | } | |||
729 | ||||
730 | /* adjust length */ | |||
731 | srcdest->len -= 2; | |||
732 | srcdest->len /= 2; | |||
733 | return SECSuccess; | |||
734 | } | |||
735 | ||||
736 | SECItem * | |||
737 | SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str) | |||
738 | { | |||
739 | int i = 0; | |||
740 | int byteval = 0; | |||
741 | int tmp = PORT_Strlen(str)strlen(str); | |||
742 | ||||
743 | PORT_Assert(item)((item)?((void)0):PR_Assert("item","basicutil.c",743)); | |||
744 | ||||
745 | if ((tmp % 2) != 0) { | |||
746 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); | |||
747 | return NULL((void*)0); | |||
748 | } | |||
749 | ||||
750 | item = SECITEM_AllocItemSECITEM_AllocItem_Util(arena, item, tmp / 2); | |||
751 | if (item == NULL((void*)0)) { | |||
752 | return NULL((void*)0); | |||
753 | } | |||
754 | ||||
755 | while (str[i]) { | |||
756 | if ((str[i] >= '0') && (str[i] <= '9')) { | |||
757 | tmp = str[i] - '0'; | |||
758 | } else if ((str[i] >= 'a') && (str[i] <= 'f')) { | |||
759 | tmp = str[i] - 'a' + 10; | |||
760 | } else if ((str[i] >= 'A') && (str[i] <= 'F')) { | |||
761 | tmp = str[i] - 'A' + 10; | |||
762 | } else { | |||
763 | if (!arena) { | |||
764 | SECITEM_FreeItemSECITEM_FreeItem_Util(item, PR_FALSE0); | |||
765 | } | |||
766 | return NULL((void*)0); | |||
767 | } | |||
768 | ||||
769 | byteval = byteval * 16 + tmp; | |||
770 | if ((i % 2) != 0) { | |||
771 | item->data[i / 2] = byteval; | |||
772 | byteval = 0; | |||
773 | } | |||
774 | i++; | |||
775 | } | |||
776 | ||||
777 | return item; | |||
778 | } | |||
779 | ||||
780 | SECStatus | |||
781 | SECU_ecName2params(ECCurveName curve, SECItem *params) | |||
782 | { | |||
783 | SECOidTag oidTag; | |||
784 | SECOidData *oidData = NULL((void*)0); | |||
785 | ||||
786 | switch (curve) { | |||
787 | case ECCurve_NIST_P256: | |||
788 | oidTag = SEC_OID_ANSIX962_EC_PRIME256V1; | |||
789 | break; | |||
790 | case ECCurve_NIST_P384: | |||
791 | oidTag = SEC_OID_SECG_EC_SECP384R1; | |||
792 | break; | |||
793 | case ECCurve_NIST_P521: | |||
794 | oidTag = SEC_OID_SECG_EC_SECP521R1; | |||
795 | break; | |||
796 | case ECCurve25519: | |||
797 | oidTag = SEC_OID_CURVE25519; | |||
798 | break; | |||
799 | case ECCurve_Ed25519: | |||
800 | oidTag = SEC_OID_ED25519_PUBLIC_KEY; | |||
801 | break; | |||
802 | default: | |||
803 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |||
804 | return SECFailure; | |||
805 | } | |||
806 | ||||
807 | oidData = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(oidTag); | |||
808 | if (oidData == NULL((void*)0)) { | |||
809 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |||
810 | return SECFailure; | |||
811 | } | |||
812 | ||||
813 | if (SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), params, (2 + oidData->oid.len)) == NULL((void*)0)) { | |||
814 | return SECFailure; | |||
815 | } | |||
816 | /* | |||
817 | * params->data needs to contain the ASN encoding of an object ID (OID) | |||
818 | * representing the named curve. The actual OID is in | |||
819 | * oidData->oid.data so we simply prepend 0x06 and OID length | |||
820 | */ | |||
821 | params->data[0] = SEC_ASN1_OBJECT_ID0x06; | |||
822 | params->data[1] = oidData->oid.len; | |||
823 | memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); | |||
824 | ||||
825 | return SECSuccess; | |||
826 | } |