dirmngr: Improve DNS code to retrieve arbitrary records.
[gnupg.git] / common / miscellaneous.c
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 <http://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 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   switch (level)
47     {
48     case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
49     case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
50     case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
51     case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
52     case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
53     case GCRY_LOG_BUG:  level = GPGRT_LOG_BUG; break;
54     case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
55     default:            level = GPGRT_LOG_ERROR; break;
56     }
57   log_logv (level, fmt, arg_ptr);
58 }
59
60
61 /* This function is called by libgcrypt on a fatal error.  */
62 static void
63 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
64 {
65   (void)opaque;
66
67   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 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   if (!been_here)
83     {
84       been_here = 1;
85       if ( (flags & 1) )
86         log_fatal (_("out of core in secure memory "
87                      "while allocating %lu bytes"), (unsigned long)req_n);
88       else
89         log_fatal (_("out of core while allocating %lu bytes"),
90                    (unsigned long)req_n);
91     }
92   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 setup_libgcrypt_logging (void)
102 {
103   gcry_set_log_handler (my_gcry_logger, NULL);
104   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
105   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
106 }
107
108
109 /* A wrapper around gcry_cipher_algo_name to return the string
110    "AES-128" instead of "AES".  Given that we have an alias in
111    libgcrypt for it, it does not harm to too much to return this other
112    string.  Some users complained that we print "AES" but "AES192"
113    and "AES256".  We can't fix that in libgcrypt but it is pretty
114    safe to do it in an application. */
115 const char *
116 gnupg_cipher_algo_name (int algo)
117 {
118   const char *s;
119
120   s = gcry_cipher_algo_name (algo);
121   if (!strcmp (s, "AES"))
122     s = "AES128";
123   return s;
124 }
125
126
127 void
128 obsolete_option (const char *configname, unsigned int configlineno,
129                  const char *name)
130 {
131   if (configname)
132     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
133               configname, configlineno, name);
134   else
135     log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"),
136               "--", name);
137 }
138
139
140 /* Decide whether the filename is stdout or a real filename and return
141  * an appropriate string.  */
142 const char *
143 print_fname_stdout (const char *s)
144 {
145     if( !s || (*s == '-' && !s[1]) )
146         return "[stdout]";
147     return s;
148 }
149
150
151 /* Decide whether the filename is stdin or a real filename and return
152  * an appropriate string.  */
153 const char *
154 print_fname_stdin (const char *s)
155 {
156     if( !s || (*s == '-' && !s[1]) )
157         return "[stdin]";
158     return s;
159 }
160
161
162 static int
163 do_print_utf8_buffer (estream_t stream,
164                       const void *buffer, size_t length,
165                       const char *delimiters, size_t *bytes_written)
166 {
167   const char *p = buffer;
168   size_t i;
169
170   /* We can handle plain ascii simpler, so check for it first. */
171   for (i=0; i < length; i++ )
172     {
173       if ( (p[i] & 0x80) )
174         break;
175     }
176   if (i < length)
177     {
178       int delim = delimiters? *delimiters : 0;
179       char *buf;
180       int ret;
181
182       /*(utf8 conversion already does the control character quoting). */
183       buf = utf8_to_native (p, length, delim);
184       if (bytes_written)
185         *bytes_written = strlen (buf);
186       ret = es_fputs (buf, stream);
187       xfree (buf);
188       return ret == EOF? ret : (int)i;
189     }
190   else
191     return es_write_sanitized (stream, p, length, delimiters, bytes_written);
192 }
193
194
195 void
196 print_utf8_buffer3 (estream_t stream, const void *p, size_t n,
197                     const char *delim)
198 {
199   do_print_utf8_buffer (stream, p, n, delim, NULL);
200 }
201
202
203 void
204 print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
205 {
206   char tmp[2];
207
208   tmp[0] = delim;
209   tmp[1] = 0;
210   do_print_utf8_buffer (stream, p, n, tmp, NULL);
211 }
212
213
214 void
215 print_utf8_buffer (estream_t stream, const void *p, size_t n)
216 {
217   do_print_utf8_buffer (stream, p, n, NULL, NULL);
218 }
219
220 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
221    RESERVED must be 0. */
222 void
223 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
224 {
225 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
226   const unsigned char *s;
227
228   (void)reserved;
229
230   for (s = buffer; length; s++, length--)
231     {
232       putc ( tohex ((*s>>4)&15), fp);
233       putc ( tohex (*s&15), fp);
234     }
235 #undef tohex
236 }
237
238 char *
239 make_printable_string (const void *p, size_t n, int delim )
240 {
241   return sanitize_buffer (p, n, delim);
242 }
243
244
245
246 /*
247  * Check if the file is compressed.
248  */
249 int
250 is_file_compressed (const char *s, int *ret_rc)
251 {
252     iobuf_t a;
253     byte buf[4];
254     int i, rc = 0;
255     int overflow;
256
257     struct magic_compress_s {
258         size_t len;
259         byte magic[4];
260     } magic[] = {
261         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
262         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
263         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
264     };
265
266     if ( iobuf_is_pipe_filename (s) || !ret_rc )
267         return 0; /* We can't check stdin or no file was given */
268
269     a = iobuf_open( s );
270     if ( a == NULL ) {
271         *ret_rc = gpg_error_from_syserror ();
272         return 0;
273     }
274
275     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
276         *ret_rc = 0;
277         goto leave;
278     }
279
280     if ( iobuf_read( a, buf, 4 ) == -1 ) {
281         *ret_rc = a->error;
282         goto leave;
283     }
284
285     for ( i = 0; i < DIM( magic ); i++ ) {
286         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
287             *ret_rc = 0;
288             rc = 1;
289             break;
290         }
291     }
292
293 leave:
294     iobuf_close( a );
295     return rc;
296 }
297
298
299 /* Try match against each substring of multistr, delimited by | */
300 int
301 match_multistr (const char *multistr,const char *match)
302 {
303   do
304     {
305       size_t seglen = strcspn (multistr,"|");
306       if (!seglen)
307         break;
308       /* Using the localized strncasecmp! */
309       if (strncasecmp(multistr,match,seglen)==0)
310         return 1;
311       multistr += seglen;
312       if (*multistr == '|')
313         multistr++;
314     }
315   while (*multistr);
316
317   return 0;
318 }
319
320
321 \f
322 /* Parse the first portion of the version number S and store it at
323    NUMBER.  On success, the function returns a pointer into S starting
324    with the first character, which is not part of the initial number
325    portion; on failure, NULL is returned.  */
326 static const char*
327 parse_version_number (const char *s, int *number)
328 {
329   int val = 0;
330
331   if (*s == '0' && digitp (s+1))
332     return NULL; /* Leading zeros are not allowed.  */
333   for (; digitp (s); s++ )
334     {
335       val *= 10;
336       val += *s - '0';
337     }
338   *number = val;
339   return val < 0? NULL : s;
340 }
341
342 /* Break up the complete string representation of the version number S,
343    which is expected to have this format:
344
345       <major number>.<minor number>.<micro number><patch level>.
346
347    The major, minor and micro number components will be stored at
348    MAJOR, MINOR and MICRO. On success, a pointer to the last
349    component, the patch level, will be returned; on failure, NULL will
350    be returned.  */
351 static const char *
352 parse_version_string (const char *s, int *major, int *minor, int *micro)
353 {
354   s = parse_version_number (s, major);
355   if (!s || *s != '.')
356     return NULL;
357   s++;
358   s = parse_version_number (s, minor);
359   if (!s || *s != '.')
360     return NULL;
361   s++;
362   s = parse_version_number (s, micro);
363   if (!s)
364     return NULL;
365   return s; /* Patchlevel.  */
366 }
367
368 /* Return true if version string is at least version B. */
369 int
370 gnupg_compare_version (const char *a, const char *b)
371 {
372   int a_major, a_minor, a_micro;
373   int b_major, b_minor, b_micro;
374   const char *a_plvl, *b_plvl;
375
376   if (!a || !b)
377     return 0;
378
379   /* Parse version A.  */
380   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
381   if (!a_plvl )
382     return 0; /* Invalid version number.  */
383
384   /* Parse version B.  */
385   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
386   if (!b_plvl )
387     return 0; /* Invalid version number.  */
388
389   /* Compare version numbers.  */
390   return (a_major > b_major
391           || (a_major == b_major && a_minor > b_minor)
392           || (a_major == b_major && a_minor == b_minor
393               && a_micro > b_micro)
394           || (a_major == b_major && a_minor == b_minor
395               && a_micro == b_micro
396               && strcmp (a_plvl, b_plvl) >= 0));
397 }
398
399
400 \f
401 /* Parse an --debug style argument.  We allow the use of number values
402  * in the usual C notation or a string with comma separated keywords.
403  *
404  * Returns: 0 on success or -1 and ERRNO set on error.  On success the
405  *          supplied variable is updated by the parsed flags.
406  *
407  * If STRING is NULL the enabled debug flags are printed.
408  */
409 int
410 parse_debug_flag (const char *string, unsigned int *debugvar,
411                   const struct debug_flags_s *flags)
412
413 {
414   unsigned long result = 0;
415   int i, j;
416
417   if (!string)
418     {
419       if (debugvar)
420         {
421           log_info ("enabled debug flags:");
422           for (i=0; flags[i].name; i++)
423             if ((*debugvar & flags[i].flag))
424               log_printf (" %s", flags[i].name);
425           log_printf ("\n");
426         }
427       return 0;
428     }
429
430   while (spacep (string))
431     string++;
432   if (*string == '-')
433     {
434       errno = EINVAL;
435       return -1;
436     }
437
438   if (!strcmp (string, "?") || !strcmp (string, "help"))
439     {
440       log_info ("available debug flags:\n");
441       for (i=0; flags[i].name; i++)
442         log_info (" %5u %s\n", flags[i].flag, flags[i].name);
443       if (flags[i].flag != 77)
444         exit (0);
445     }
446   else if (digitp (string))
447     {
448       errno = 0;
449       result = strtoul (string, NULL, 0);
450       if (result == ULONG_MAX && errno == ERANGE)
451         return -1;
452     }
453   else
454     {
455       char **words;
456       words = strtokenize (string, ",");
457       if (!words)
458         return -1;
459       for (i=0; words[i]; i++)
460         {
461           if (*words[i])
462             {
463               for (j=0; flags[j].name; j++)
464                 if (!strcmp (words[i], flags[j].name))
465                   {
466                     result |= flags[j].flag;
467                     break;
468                   }
469               if (!flags[j].name)
470                 {
471                   if (!strcmp (words[i], "none"))
472                     {
473                       *debugvar = 0;
474                       result = 0;
475                     }
476                   else if (!strcmp (words[i], "all"))
477                     result = ~0;
478                   else
479                     log_info (_("unknown debug flag '%s' ignored\n"), words[i]);
480                 }
481             }
482         }
483       xfree (words);
484     }
485
486   *debugvar |= result;
487   return 0;
488 }