LCOV - code coverage report
Current view: top level - common - miscellaneous.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 86 230 37.4 %
Date: 2016-09-12 12:29:17 Functions: 10 22 45.5 %

          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        1875 : setup_libgcrypt_logging (void)
     102             : {
     103        1875 :   gcry_set_log_handler (my_gcry_logger, NULL);
     104        1875 :   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
     105        1875 :   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
     106        1875 : }
     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          48 : obsolete_option (const char *configname, unsigned int configlineno,
     140             :                  const char *name)
     141             : {
     142          48 :   if (configname)
     143           0 :     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
     144             :               configname, configlineno, name);
     145             :   else
     146          48 :     log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"),
     147             :               "--", name);
     148          48 : }
     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          17 : try_make_printable_string (const void *p_arg, size_t n, int delim)
     256             : {
     257          17 :   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         290 :   for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
     264             :     {
     265         273 :       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         273 :         buflen++;
     275             :     }
     276          17 :   p = save_p;
     277          17 :   n = save_n;
     278             :   /* And now make the string */
     279          17 :   d = buffer = xtrymalloc (buflen);
     280         290 :   for ( ; n; n--, p++ )
     281             :     {
     282         273 :       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         273 :         *d++ = *p;
     303             :     }
     304          17 :   *d = 0;
     305          17 :   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         383 : is_file_compressed (const char *s, int *ret_rc)
     326             : {
     327             :     iobuf_t a;
     328             :     byte buf[4];
     329         383 :     int i, rc = 0;
     330             :     int overflow;
     331             : 
     332             :     struct magic_compress_s {
     333             :         size_t len;
     334             :         byte magic[4];
     335         383 :     } 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         383 :     if ( iobuf_is_pipe_filename (s) || !ret_rc )
     342          16 :         return 0; /* We can't check stdin or no file was given */
     343             : 
     344         367 :     a = iobuf_open( s );
     345         367 :     if ( a == NULL ) {
     346           0 :         *ret_rc = gpg_error_from_syserror ();
     347           0 :         return 0;
     348             :     }
     349             : 
     350         367 :     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
     351          44 :         *ret_rc = 0;
     352          44 :         goto leave;
     353             :     }
     354             : 
     355         323 :     if ( iobuf_read( a, buf, 4 ) == -1 ) {
     356           0 :         *ret_rc = a->error;
     357           0 :         goto leave;
     358             :     }
     359             : 
     360        1292 :     for ( i = 0; i < DIM( magic ); i++ ) {
     361         969 :         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         367 :     iobuf_close( a );
     370         367 :     return rc;
     371             : }
     372             : 
     373             : 
     374             : /* Try match against each substring of multistr, delimited by | */
     375             : int
     376          12 : match_multistr (const char *multistr,const char *match)
     377             : {
     378             :   do
     379             :     {
     380          12 :       size_t seglen = strcspn (multistr,"|");
     381          12 :       if (!seglen)
     382           0 :         break;
     383             :       /* Using the localized strncasecmp! */
     384          12 :       if (strncasecmp(multistr,match,seglen)==0)
     385           0 :         return 1;
     386          12 :       multistr += seglen;
     387          12 :       if (*multistr == '|')
     388           6 :         multistr++;
     389             :     }
     390          12 :   while (*multistr);
     391             : 
     392           6 :   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        2616 : parse_version_number (const char *s, int *number)
     403             : {
     404        2616 :   int val = 0;
     405             : 
     406        2616 :   if (*s == '0' && digitp (s+1))
     407           0 :     return NULL; /* Leading zeros are not allowed.  */
     408        5235 :   for (; digitp (s); s++ )
     409             :     {
     410        2619 :       val *= 10;
     411        2619 :       val += *s - '0';
     412             :     }
     413        2616 :   *number = val;
     414        2616 :   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         872 : parse_version_string (const char *s, int *major, int *minor, int *micro)
     428             : {
     429         872 :   s = parse_version_number (s, major);
     430         872 :   if (!s || *s != '.')
     431           0 :     return NULL;
     432         872 :   s++;
     433         872 :   s = parse_version_number (s, minor);
     434         872 :   if (!s || *s != '.')
     435           0 :     return NULL;
     436         872 :   s++;
     437         872 :   s = parse_version_number (s, micro);
     438         872 :   if (!s)
     439           0 :     return NULL;
     440         872 :   return s; /* Patchlevel.  */
     441             : }
     442             : 
     443             : /* Return true if version string is at least version B. */
     444             : int
     445         436 : 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         436 :   if (!a || !b)
     452           0 :     return 0;
     453             : 
     454             :   /* Parse version A.  */
     455         436 :   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
     456         436 :   if (!a_plvl )
     457           0 :     return 0; /* Invalid version number.  */
     458             : 
     459             :   /* Parse version B.  */
     460         436 :   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
     461         436 :   if (!b_plvl )
     462           0 :     return 0; /* Invalid version number.  */
     463             : 
     464             :   /* Compare version numbers.  */
     465         872 :   return (a_major > b_major
     466         436 :           || (a_major == b_major && a_minor > b_minor)
     467         436 :           || (a_major == b_major && a_minor == b_minor
     468         436 :               && a_micro > b_micro)
     469        1305 :           || (a_major == b_major && a_minor == b_minor
     470         433 :               && a_micro == b_micro
     471         433 :               && 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             : }

Generated by: LCOV version 1.11