Line data Source code
1 : /* miscellaneous.c - Stuff not fitting elsewhere
2 : * Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
6 : * This file is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * This file is distributed in the hope that it will be useful,
22 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 : * GNU General Public License for more details.
25 : *
26 : * You should have received a copy of the GNU General Public License
27 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include <config.h>
31 : #include <stdlib.h>
32 : #include <limits.h>
33 : #include <errno.h>
34 :
35 : #include "util.h"
36 : #include "iobuf.h"
37 : #include "i18n.h"
38 :
39 : /* Used by libgcrypt for logging. */
40 : static void
41 0 : my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
42 : {
43 : (void)dummy;
44 :
45 : /* Map the log levels. */
46 0 : switch (level)
47 : {
48 0 : case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
49 0 : case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
50 0 : case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
51 0 : case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
52 0 : case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
53 0 : case GCRY_LOG_BUG: level = GPGRT_LOG_BUG; break;
54 0 : case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
55 0 : default: level = GPGRT_LOG_ERROR; break;
56 : }
57 0 : log_logv (level, fmt, arg_ptr);
58 0 : }
59 :
60 :
61 : /* This function is called by libgcrypt on a fatal error. */
62 : static void
63 0 : my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
64 : {
65 : (void)opaque;
66 :
67 0 : log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
68 : abort ();
69 : }
70 :
71 :
72 : /* This function is called by libgcrypt if it ran out of core and
73 : there is no way to return that error to the caller. We do our own
74 : function here to make use of our logging functions. */
75 : static int
76 0 : my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
77 : {
78 : static int been_here; /* Used to protect against recursive calls. */
79 :
80 : (void)opaque;
81 :
82 0 : if (!been_here)
83 : {
84 0 : been_here = 1;
85 0 : if ( (flags & 1) )
86 0 : log_fatal (_("out of core in secure memory "
87 : "while allocating %lu bytes"), (unsigned long)req_n);
88 : else
89 0 : log_fatal (_("out of core while allocating %lu bytes"),
90 : (unsigned long)req_n);
91 : }
92 0 : return 0; /* Let libgcrypt call its own fatal error handler.
93 : Actually this will turn out to be
94 : my_gcry_fatalerror_handler. */
95 : }
96 :
97 :
98 : /* Setup libgcrypt to use our own logging functions. Should be used
99 : early at startup. */
100 : void
101 1277 : setup_libgcrypt_logging (void)
102 : {
103 1277 : gcry_set_log_handler (my_gcry_logger, NULL);
104 1277 : gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
105 1277 : gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
106 1277 : }
107 :
108 :
109 : /* Print an out of core message and let the process die. The printed
110 : * error is taken from ERRNO. */
111 : void
112 0 : xoutofcore (void)
113 : {
114 0 : gpg_error_t err = gpg_error_from_syserror ();
115 0 : log_fatal (_("error allocating enough memory: %s\n"), gpg_strerror (err));
116 : abort (); /* Never called; just to make the compiler happy. */
117 : }
118 :
119 :
120 : /* A wrapper around gcry_cipher_algo_name to return the string
121 : "AES-128" instead of "AES". Given that we have an alias in
122 : libgcrypt for it, it does not harm to too much to return this other
123 : string. Some users complained that we print "AES" but "AES192"
124 : and "AES256". We can't fix that in libgcrypt but it is pretty
125 : safe to do it in an application. */
126 : const char *
127 0 : gnupg_cipher_algo_name (int algo)
128 : {
129 : const char *s;
130 :
131 0 : s = gcry_cipher_algo_name (algo);
132 0 : if (!strcmp (s, "AES"))
133 0 : s = "AES128";
134 0 : return s;
135 : }
136 :
137 :
138 : void
139 50 : obsolete_option (const char *configname, unsigned int configlineno,
140 : const char *name)
141 : {
142 50 : if (configname)
143 0 : log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
144 : configname, configlineno, name);
145 : else
146 50 : log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"),
147 : "--", name);
148 50 : }
149 :
150 :
151 : /* Decide whether the filename is stdout or a real filename and return
152 : * an appropriate string. */
153 : const char *
154 0 : print_fname_stdout (const char *s)
155 : {
156 0 : if( !s || (*s == '-' && !s[1]) )
157 0 : return "[stdout]";
158 0 : return s;
159 : }
160 :
161 :
162 : /* Decide whether the filename is stdin or a real filename and return
163 : * an appropriate string. */
164 : const char *
165 0 : print_fname_stdin (const char *s)
166 : {
167 0 : if( !s || (*s == '-' && !s[1]) )
168 0 : return "[stdin]";
169 0 : return s;
170 : }
171 :
172 :
173 : static int
174 26 : do_print_utf8_buffer (estream_t stream,
175 : const void *buffer, size_t length,
176 : const char *delimiters, size_t *bytes_written)
177 : {
178 26 : const char *p = buffer;
179 : size_t i;
180 :
181 : /* We can handle plain ascii simpler, so check for it first. */
182 893 : for (i=0; i < length; i++ )
183 : {
184 867 : if ( (p[i] & 0x80) )
185 0 : break;
186 : }
187 26 : if (i < length)
188 : {
189 0 : int delim = delimiters? *delimiters : 0;
190 : char *buf;
191 : int ret;
192 :
193 : /*(utf8 conversion already does the control character quoting). */
194 0 : buf = utf8_to_native (p, length, delim);
195 0 : if (bytes_written)
196 0 : *bytes_written = strlen (buf);
197 0 : ret = es_fputs (buf, stream);
198 0 : xfree (buf);
199 0 : return ret == EOF? ret : (int)i;
200 : }
201 : else
202 26 : return es_write_sanitized (stream, p, length, delimiters, bytes_written);
203 : }
204 :
205 :
206 : void
207 0 : print_utf8_buffer3 (estream_t stream, const void *p, size_t n,
208 : const char *delim)
209 : {
210 0 : do_print_utf8_buffer (stream, p, n, delim, NULL);
211 0 : }
212 :
213 :
214 : void
215 0 : print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
216 : {
217 : char tmp[2];
218 :
219 0 : tmp[0] = delim;
220 0 : tmp[1] = 0;
221 0 : do_print_utf8_buffer (stream, p, n, tmp, NULL);
222 0 : }
223 :
224 :
225 : void
226 26 : print_utf8_buffer (estream_t stream, const void *p, size_t n)
227 : {
228 26 : do_print_utf8_buffer (stream, p, n, NULL, NULL);
229 26 : }
230 :
231 : /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
232 : RESERVED must be 0. */
233 : void
234 0 : print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
235 : {
236 : #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
237 : const unsigned char *s;
238 :
239 : (void)reserved;
240 :
241 0 : for (s = buffer; length; s++, length--)
242 : {
243 0 : putc ( tohex ((*s>>4)&15), fp);
244 0 : putc ( tohex (*s&15), fp);
245 : }
246 : #undef tohex
247 0 : }
248 :
249 :
250 : /* Create a string from the buffer P_ARG of length N which is suitable
251 : * for printing. Caller must release the created string using xfree.
252 : * On error ERRNO is set and NULL returned. Errors are only possible
253 : * due to malloc failure. */
254 : char *
255 29 : try_make_printable_string (const void *p_arg, size_t n, int delim)
256 : {
257 29 : const unsigned char *p = p_arg;
258 : size_t save_n, buflen;
259 : const unsigned char *save_p;
260 : char *buffer, *d;
261 :
262 : /* First count length. */
263 428 : for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
264 : {
265 399 : if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\'))
266 : {
267 0 : if ( *p=='\n' || *p=='\r' || *p=='\f'
268 0 : || *p=='\v' || *p=='\b' || !*p )
269 0 : buflen += 2;
270 : else
271 0 : buflen += 5;
272 : }
273 : else
274 399 : buflen++;
275 : }
276 29 : p = save_p;
277 29 : n = save_n;
278 : /* And now make the string */
279 29 : d = buffer = xtrymalloc (buflen);
280 428 : for ( ; n; n--, p++ )
281 : {
282 399 : if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
283 0 : *d++ = '\\';
284 0 : if( *p == '\n' )
285 0 : *d++ = 'n';
286 0 : else if( *p == '\r' )
287 0 : *d++ = 'r';
288 0 : else if( *p == '\f' )
289 0 : *d++ = 'f';
290 0 : else if( *p == '\v' )
291 0 : *d++ = 'v';
292 0 : else if( *p == '\b' )
293 0 : *d++ = 'b';
294 0 : else if( !*p )
295 0 : *d++ = '0';
296 : else {
297 0 : sprintf(d, "x%02x", *p );
298 0 : d += 3;
299 : }
300 : }
301 : else
302 399 : *d++ = *p;
303 : }
304 29 : *d = 0;
305 29 : return buffer;
306 : }
307 :
308 :
309 : /* Same as try_make_printable_string but terminates the process on
310 : * memory shortage. */
311 : char *
312 0 : make_printable_string (const void *p, size_t n, int delim )
313 : {
314 0 : char *string = try_make_printable_string (p, n, delim);
315 0 : if (!string)
316 0 : xoutofcore ();
317 0 : return string;
318 : }
319 :
320 :
321 : /*
322 : * Check if the file is compressed.
323 : */
324 : int
325 218 : is_file_compressed (const char *s, int *ret_rc)
326 : {
327 : iobuf_t a;
328 : byte buf[4];
329 218 : int i, rc = 0;
330 : int overflow;
331 :
332 : struct magic_compress_s {
333 : size_t len;
334 : byte magic[4];
335 218 : } magic[] = {
336 : { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
337 : { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
338 : { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
339 : };
340 :
341 218 : if ( iobuf_is_pipe_filename (s) || !ret_rc )
342 16 : return 0; /* We can't check stdin or no file was given */
343 :
344 202 : a = iobuf_open( s );
345 202 : if ( a == NULL ) {
346 0 : *ret_rc = gpg_error_from_syserror ();
347 0 : return 0;
348 : }
349 :
350 202 : if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
351 0 : *ret_rc = 0;
352 0 : goto leave;
353 : }
354 :
355 202 : if ( iobuf_read( a, buf, 4 ) == -1 ) {
356 0 : *ret_rc = a->error;
357 0 : goto leave;
358 : }
359 :
360 808 : for ( i = 0; i < DIM( magic ); i++ ) {
361 606 : if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
362 0 : *ret_rc = 0;
363 0 : rc = 1;
364 0 : break;
365 : }
366 : }
367 :
368 : leave:
369 202 : iobuf_close( a );
370 202 : return rc;
371 : }
372 :
373 :
374 : /* Try match against each substring of multistr, delimited by | */
375 : int
376 24 : match_multistr (const char *multistr,const char *match)
377 : {
378 : do
379 : {
380 24 : size_t seglen = strcspn (multistr,"|");
381 24 : if (!seglen)
382 0 : break;
383 : /* Using the localized strncasecmp! */
384 24 : if (strncasecmp(multistr,match,seglen)==0)
385 0 : return 1;
386 24 : multistr += seglen;
387 24 : if (*multistr == '|')
388 12 : multistr++;
389 : }
390 24 : while (*multistr);
391 :
392 12 : return 0;
393 : }
394 :
395 :
396 :
397 : /* Parse the first portion of the version number S and store it at
398 : NUMBER. On success, the function returns a pointer into S starting
399 : with the first character, which is not part of the initial number
400 : portion; on failure, NULL is returned. */
401 : static const char*
402 3210 : parse_version_number (const char *s, int *number)
403 : {
404 3210 : int val = 0;
405 :
406 3210 : if (*s == '0' && digitp (s+1))
407 0 : return NULL; /* Leading zeros are not allowed. */
408 6423 : for (; digitp (s); s++ )
409 : {
410 3213 : val *= 10;
411 3213 : val += *s - '0';
412 : }
413 3210 : *number = val;
414 3210 : return val < 0? NULL : s;
415 : }
416 :
417 : /* Break up the complete string representation of the version number S,
418 : which is expected to have this format:
419 :
420 : <major number>.<minor number>.<micro number><patch level>.
421 :
422 : The major, minor and micro number components will be stored at
423 : MAJOR, MINOR and MICRO. On success, a pointer to the last
424 : component, the patch level, will be returned; on failure, NULL will
425 : be returned. */
426 : static const char *
427 1070 : parse_version_string (const char *s, int *major, int *minor, int *micro)
428 : {
429 1070 : s = parse_version_number (s, major);
430 1070 : if (!s || *s != '.')
431 0 : return NULL;
432 1070 : s++;
433 1070 : s = parse_version_number (s, minor);
434 1070 : if (!s || *s != '.')
435 0 : return NULL;
436 1070 : s++;
437 1070 : s = parse_version_number (s, micro);
438 1070 : if (!s)
439 0 : return NULL;
440 1070 : return s; /* Patchlevel. */
441 : }
442 :
443 : /* Return true if version string is at least version B. */
444 : int
445 535 : gnupg_compare_version (const char *a, const char *b)
446 : {
447 : int a_major, a_minor, a_micro;
448 : int b_major, b_minor, b_micro;
449 : const char *a_plvl, *b_plvl;
450 :
451 535 : if (!a || !b)
452 0 : return 0;
453 :
454 : /* Parse version A. */
455 535 : a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
456 535 : if (!a_plvl )
457 0 : return 0; /* Invalid version number. */
458 :
459 : /* Parse version B. */
460 535 : b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
461 535 : if (!b_plvl )
462 0 : return 0; /* Invalid version number. */
463 :
464 : /* Compare version numbers. */
465 1070 : return (a_major > b_major
466 535 : || (a_major == b_major && a_minor > b_minor)
467 535 : || (a_major == b_major && a_minor == b_minor
468 535 : && a_micro > b_micro)
469 1602 : || (a_major == b_major && a_minor == b_minor
470 532 : && a_micro == b_micro
471 532 : && strcmp (a_plvl, b_plvl) >= 0));
472 : }
473 :
474 :
475 :
476 : /* Parse an --debug style argument. We allow the use of number values
477 : * in the usual C notation or a string with comma separated keywords.
478 : *
479 : * Returns: 0 on success or -1 and ERRNO set on error. On success the
480 : * supplied variable is updated by the parsed flags.
481 : *
482 : * If STRING is NULL the enabled debug flags are printed.
483 : */
484 : int
485 0 : parse_debug_flag (const char *string, unsigned int *debugvar,
486 : const struct debug_flags_s *flags)
487 :
488 : {
489 0 : unsigned long result = 0;
490 : int i, j;
491 :
492 0 : if (!string)
493 : {
494 0 : if (debugvar)
495 : {
496 0 : log_info ("enabled debug flags:");
497 0 : for (i=0; flags[i].name; i++)
498 0 : if ((*debugvar & flags[i].flag))
499 0 : log_printf (" %s", flags[i].name);
500 0 : log_printf ("\n");
501 : }
502 0 : return 0;
503 : }
504 :
505 0 : while (spacep (string))
506 0 : string++;
507 0 : if (*string == '-')
508 : {
509 0 : errno = EINVAL;
510 0 : return -1;
511 : }
512 :
513 0 : if (!strcmp (string, "?") || !strcmp (string, "help"))
514 : {
515 0 : log_info ("available debug flags:\n");
516 0 : for (i=0; flags[i].name; i++)
517 0 : log_info (" %5u %s\n", flags[i].flag, flags[i].name);
518 0 : if (flags[i].flag != 77)
519 0 : exit (0);
520 : }
521 0 : else if (digitp (string))
522 : {
523 0 : errno = 0;
524 0 : result = strtoul (string, NULL, 0);
525 0 : if (result == ULONG_MAX && errno == ERANGE)
526 0 : return -1;
527 : }
528 : else
529 : {
530 : char **words;
531 0 : words = strtokenize (string, ",");
532 0 : if (!words)
533 0 : return -1;
534 0 : for (i=0; words[i]; i++)
535 : {
536 0 : if (*words[i])
537 : {
538 0 : for (j=0; flags[j].name; j++)
539 0 : if (!strcmp (words[i], flags[j].name))
540 : {
541 0 : result |= flags[j].flag;
542 0 : break;
543 : }
544 0 : if (!flags[j].name)
545 : {
546 0 : if (!strcmp (words[i], "none"))
547 : {
548 0 : *debugvar = 0;
549 0 : result = 0;
550 : }
551 0 : else if (!strcmp (words[i], "all"))
552 0 : result = ~0;
553 : else
554 0 : log_info (_("unknown debug flag '%s' ignored\n"), words[i]);
555 : }
556 : }
557 : }
558 0 : xfree (words);
559 : }
560 :
561 0 : *debugvar |= result;
562 0 : return 0;
563 : }
|