LCOV - code coverage report
Current view: top level - common - miscellaneous.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 74 192 38.5 %
Date: 2015-11-05 17:10:59 Functions: 9 20 45.0 %

          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 <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           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        1334 : setup_libgcrypt_logging (void)
     102             : {
     103        1334 :   gcry_set_log_handler (my_gcry_logger, NULL);
     104        1334 :   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
     105        1334 :   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
     106        1334 : }
     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           0 : gnupg_cipher_algo_name (int algo)
     117             : {
     118             :   const char *s;
     119             : 
     120           0 :   s = gcry_cipher_algo_name (algo);
     121           0 :   if (!strcmp (s, "AES"))
     122           0 :     s = "AES128";
     123           0 :   return s;
     124             : }
     125             : 
     126             : 
     127             : void
     128           4 : obsolete_option (const char *configname, unsigned int configlineno,
     129             :                  const char *name)
     130             : {
     131           4 :   if (configname)
     132           3 :     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
     133             :               configname, configlineno, name);
     134             :   else
     135           1 :     log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"),
     136             :               "--", name);
     137           4 : }
     138             : 
     139             : 
     140             : /* Decide whether the filename is stdout or a real filename and return
     141             :  * an appropriate string.  */
     142             : const char *
     143           0 : print_fname_stdout (const char *s)
     144             : {
     145           0 :     if( !s || (*s == '-' && !s[1]) )
     146           0 :         return "[stdout]";
     147           0 :     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           0 : print_fname_stdin (const char *s)
     155             : {
     156           0 :     if( !s || (*s == '-' && !s[1]) )
     157           0 :         return "[stdin]";
     158           0 :     return s;
     159             : }
     160             : 
     161             : 
     162             : static int
     163           3 : do_print_utf8_buffer (estream_t stream,
     164             :                       const void *buffer, size_t length,
     165             :                       const char *delimiters, size_t *bytes_written)
     166             : {
     167           3 :   const char *p = buffer;
     168             :   size_t i;
     169             : 
     170             :   /* We can handle plain ascii simpler, so check for it first. */
     171          60 :   for (i=0; i < length; i++ )
     172             :     {
     173          57 :       if ( (p[i] & 0x80) )
     174           0 :         break;
     175             :     }
     176           3 :   if (i < length)
     177             :     {
     178           0 :       int delim = delimiters? *delimiters : 0;
     179             :       char *buf;
     180             :       int ret;
     181             : 
     182             :       /*(utf8 conversion already does the control character quoting). */
     183           0 :       buf = utf8_to_native (p, length, delim);
     184           0 :       if (bytes_written)
     185           0 :         *bytes_written = strlen (buf);
     186           0 :       ret = es_fputs (buf, stream);
     187           0 :       xfree (buf);
     188           0 :       return ret == EOF? ret : (int)i;
     189             :     }
     190             :   else
     191           3 :     return es_write_sanitized (stream, p, length, delimiters, bytes_written);
     192             : }
     193             : 
     194             : 
     195             : void
     196           0 : print_utf8_buffer3 (estream_t stream, const void *p, size_t n,
     197             :                     const char *delim)
     198             : {
     199           0 :   do_print_utf8_buffer (stream, p, n, delim, NULL);
     200           0 : }
     201             : 
     202             : 
     203             : void
     204           0 : print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
     205             : {
     206             :   char tmp[2];
     207             : 
     208           0 :   tmp[0] = delim;
     209           0 :   tmp[1] = 0;
     210           0 :   do_print_utf8_buffer (stream, p, n, tmp, NULL);
     211           0 : }
     212             : 
     213             : 
     214             : void
     215           3 : print_utf8_buffer (estream_t stream, const void *p, size_t n)
     216             : {
     217           3 :   do_print_utf8_buffer (stream, p, n, NULL, NULL);
     218           3 : }
     219             : 
     220             : /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
     221             :    RESERVED must be 0. */
     222             : void
     223           0 : 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           0 :   for (s = buffer; length; s++, length--)
     231             :     {
     232           0 :       putc ( tohex ((*s>>4)&15), fp);
     233           0 :       putc ( tohex (*s&15), fp);
     234             :     }
     235             : #undef tohex
     236           0 : }
     237             : 
     238             : char *
     239           0 : make_printable_string (const void *p, size_t n, int delim )
     240             : {
     241           0 :   return sanitize_buffer (p, n, delim);
     242             : }
     243             : 
     244             : 
     245             : 
     246             : /*
     247             :  * Check if the file is compressed.
     248             :  */
     249             : int
     250         378 : is_file_compressed (const char *s, int *ret_rc)
     251             : {
     252             :     iobuf_t a;
     253             :     byte buf[4];
     254         378 :     int i, rc = 0;
     255             :     int overflow;
     256             : 
     257             :     struct magic_compress_s {
     258             :         size_t len;
     259             :         byte magic[4];
     260         378 :     } 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         378 :     if ( iobuf_is_pipe_filename (s) || !ret_rc )
     267          14 :         return 0; /* We can't check stdin or no file was given */
     268             : 
     269         364 :     a = iobuf_open( s );
     270         364 :     if ( a == NULL ) {
     271           0 :         *ret_rc = gpg_error_from_syserror ();
     272           0 :         return 0;
     273             :     }
     274             : 
     275         364 :     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
     276          44 :         *ret_rc = 0;
     277          44 :         goto leave;
     278             :     }
     279             : 
     280         320 :     if ( iobuf_read( a, buf, 4 ) == -1 ) {
     281           0 :         *ret_rc = a->error;
     282           0 :         goto leave;
     283             :     }
     284             : 
     285        1280 :     for ( i = 0; i < DIM( magic ); i++ ) {
     286         960 :         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
     287           0 :             *ret_rc = 0;
     288           0 :             rc = 1;
     289           0 :             break;
     290             :         }
     291             :     }
     292             : 
     293             : leave:
     294         364 :     iobuf_close( a );
     295         364 :     return rc;
     296             : }
     297             : 
     298             : 
     299             : /* Try match against each substring of multistr, delimited by | */
     300             : int
     301          12 : match_multistr (const char *multistr,const char *match)
     302             : {
     303             :   do
     304             :     {
     305          12 :       size_t seglen = strcspn (multistr,"|");
     306          12 :       if (!seglen)
     307           0 :         break;
     308             :       /* Using the localized strncasecmp! */
     309          12 :       if (strncasecmp(multistr,match,seglen)==0)
     310           0 :         return 1;
     311          12 :       multistr += seglen;
     312          12 :       if (*multistr == '|')
     313           6 :         multistr++;
     314             :     }
     315          12 :   while (*multistr);
     316             : 
     317           6 :   return 0;
     318             : }
     319             : 
     320             : 
     321             : 
     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        2346 : parse_version_number (const char *s, int *number)
     328             : {
     329        2346 :   int val = 0;
     330             : 
     331        2346 :   if (*s == '0' && digitp (s+1))
     332           0 :     return NULL; /* Leading zeros are not allowed.  */
     333        4692 :   for (; digitp (s); s++ )
     334             :     {
     335        2346 :       val *= 10;
     336        2346 :       val += *s - '0';
     337             :     }
     338        2346 :   *number = val;
     339        2346 :   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         782 : parse_version_string (const char *s, int *major, int *minor, int *micro)
     353             : {
     354         782 :   s = parse_version_number (s, major);
     355         782 :   if (!s || *s != '.')
     356           0 :     return NULL;
     357         782 :   s++;
     358         782 :   s = parse_version_number (s, minor);
     359         782 :   if (!s || *s != '.')
     360           0 :     return NULL;
     361         782 :   s++;
     362         782 :   s = parse_version_number (s, micro);
     363         782 :   if (!s)
     364           0 :     return NULL;
     365         782 :   return s; /* Patchlevel.  */
     366             : }
     367             : 
     368             : /* Return true if version string is at least version B. */
     369             : int
     370         391 : 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         391 :   if (!a || !b)
     377           0 :     return 0;
     378             : 
     379             :   /* Parse version A.  */
     380         391 :   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
     381         391 :   if (!a_plvl )
     382           0 :     return 0; /* Invalid version number.  */
     383             : 
     384             :   /* Parse version B.  */
     385         391 :   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
     386         391 :   if (!b_plvl )
     387           0 :     return 0; /* Invalid version number.  */
     388             : 
     389             :   /* Compare version numbers.  */
     390         782 :   return (a_major > b_major
     391         391 :           || (a_major == b_major && a_minor > b_minor)
     392         391 :           || (a_major == b_major && a_minor == b_minor
     393         391 :               && a_micro > b_micro)
     394        1173 :           || (a_major == b_major && a_minor == b_minor
     395         391 :               && a_micro == b_micro
     396         391 :               && strcmp (a_plvl, b_plvl) >= 0));
     397             : }
     398             : 
     399             : 
     400             : 
     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           0 : parse_debug_flag (const char *string, unsigned int *debugvar,
     411             :                   const struct debug_flags_s *flags)
     412             : 
     413             : {
     414           0 :   unsigned long result = 0;
     415             :   int i, j;
     416             : 
     417           0 :   if (!string)
     418             :     {
     419           0 :       if (debugvar)
     420             :         {
     421           0 :           log_info ("enabled debug flags:");
     422           0 :           for (i=0; flags[i].name; i++)
     423           0 :             if ((*debugvar & flags[i].flag))
     424           0 :               log_printf (" %s", flags[i].name);
     425           0 :           log_printf ("\n");
     426             :         }
     427           0 :       return 0;
     428             :     }
     429             : 
     430           0 :   while (spacep (string))
     431           0 :     string++;
     432           0 :   if (*string == '-')
     433             :     {
     434           0 :       errno = EINVAL;
     435           0 :       return -1;
     436             :     }
     437             : 
     438           0 :   if (!strcmp (string, "?") || !strcmp (string, "help"))
     439             :     {
     440           0 :       log_info ("available debug flags:\n");
     441           0 :       for (i=0; flags[i].name; i++)
     442           0 :         log_info (" %5u %s\n", flags[i].flag, flags[i].name);
     443           0 :       if (flags[i].flag != 77)
     444           0 :         exit (0);
     445             :     }
     446           0 :   else if (digitp (string))
     447             :     {
     448           0 :       errno = 0;
     449           0 :       result = strtoul (string, NULL, 0);
     450           0 :       if (result == ULONG_MAX && errno == ERANGE)
     451           0 :         return -1;
     452             :     }
     453             :   else
     454             :     {
     455             :       char **words;
     456           0 :       words = strtokenize (string, ",");
     457           0 :       if (!words)
     458           0 :         return -1;
     459           0 :       for (i=0; words[i]; i++)
     460             :         {
     461           0 :           if (*words[i])
     462             :             {
     463           0 :               for (j=0; flags[j].name; j++)
     464           0 :                 if (!strcmp (words[i], flags[j].name))
     465             :                   {
     466           0 :                     result |= flags[j].flag;
     467           0 :                     break;
     468             :                   }
     469           0 :               if (!flags[j].name)
     470             :                 {
     471           0 :                   if (!strcmp (words[i], "none"))
     472             :                     {
     473           0 :                       *debugvar = 0;
     474           0 :                       result = 0;
     475             :                     }
     476           0 :                   else if (!strcmp (words[i], "all"))
     477           0 :                     result = ~0;
     478             :                   else
     479           0 :                     log_info (_("unknown debug flag '%s' ignored\n"), words[i]);
     480             :                 }
     481             :             }
     482             :         }
     483           0 :       xfree (words);
     484             :     }
     485             : 
     486           0 :   *debugvar |= result;
     487           0 :   return 0;
     488             : }

Generated by: LCOV version 1.11