LCOV - code coverage report
Current view: top level - src - conversion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 130 222 58.6 %
Date: 2018-11-15 08:49:49 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /* conversion.c - String conversion helper functions.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : 
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #ifdef HAVE_SYS_TYPES_H
      29             :   /* Solaris 8 needs sys/types.h before time.h.  */
      30             : # include <sys/types.h>
      31             : #endif
      32             : #include <time.h>
      33             : #include <errno.h>
      34             : #include <stdarg.h>
      35             : 
      36             : #include "gpgme.h"
      37             : #include "util.h"
      38             : #include "debug.h"
      39             : 
      40             : #define atoi_1(p)   (*(p) - '0' )
      41             : #define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
      42             : #define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
      43             : 
      44             : 
      45             : 
      46             : static char *
      47          72 : do_strconcat (const char *s1, va_list arg_ptr)
      48             : {
      49             :   const char *argv[16];
      50             :   size_t argc;
      51             :   size_t needed;
      52             :   char *buffer, *p;
      53             : 
      54          72 :   argc = 0;
      55          72 :   argv[argc++] = s1;
      56          72 :   needed = strlen (s1);
      57         271 :   while (((argv[argc] = va_arg (arg_ptr, const char *))))
      58             :     {
      59         127 :       needed += strlen (argv[argc]);
      60         127 :       if (argc >= DIM (argv)-1)
      61             :         {
      62           0 :           gpg_err_set_errno (EINVAL);
      63           0 :           return NULL;
      64             :         }
      65         127 :       argc++;
      66             :     }
      67          72 :   needed++;
      68          72 :   buffer = malloc (needed);
      69          72 :   if (buffer)
      70             :     {
      71         271 :       for (p = buffer, argc=0; argv[argc]; argc++)
      72         199 :         p = stpcpy (p, argv[argc]);
      73             :     }
      74          72 :   return buffer;
      75             : }
      76             : 
      77             : 
      78             : /* Concatenate the string S1 with all the following strings up to a
      79             :  * NULL.  Returns a malloced buffer with the new string or NULL on a
      80             :    malloc error or if too many arguments are given.  */
      81             : char *
      82          72 : _gpgme_strconcat (const char *s1, ...)
      83             : {
      84             :   va_list arg_ptr;
      85             :   char *result;
      86             : 
      87          72 :   if (!s1)
      88           0 :     result = strdup ("");
      89             :   else
      90             :     {
      91          72 :       va_start (arg_ptr, s1);
      92          72 :       result = do_strconcat (s1, arg_ptr);
      93          72 :       va_end (arg_ptr);
      94             :     }
      95          72 :   return result;
      96             : }
      97             : 
      98             : 
      99             : 
     100             : 
     101             : /* Convert two hexadecimal digits from STR to the value they
     102             :    represent.  Returns -1 if one of the characters is not a
     103             :    hexadecimal digit.  */
     104             : int
     105         511 : _gpgme_hextobyte (const char *str)
     106             : {
     107         511 :   int val = 0;
     108             :   int i;
     109             : 
     110             : #define NROFHEXDIGITS 2
     111        1518 :   for (i = 0; i < NROFHEXDIGITS; i++)
     112             :     {
     113        1011 :       if (*str >= '0' && *str <= '9')
     114         907 :         val += *str - '0';
     115         104 :       else if (*str >= 'A' && *str <= 'F')
     116          34 :         val += 10 + *str - 'A';
     117          70 :       else if (*str >= 'a' && *str <= 'f')
     118          66 :         val += 10 + *str - 'a';
     119             :       else
     120           4 :         return -1;
     121        1007 :       if (i < NROFHEXDIGITS - 1)
     122         506 :         val *= 16;
     123        1007 :       str++;
     124             :     }
     125         507 :   return val;
     126             : }
     127             : 
     128             : 
     129             : /* Decode the C formatted string SRC and store the result in the
     130             :    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
     131             :    large enough buffer is allocated with malloc and *DESTP is set to
     132             :    the result.  Currently, LEN is only used to specify if allocation
     133             :    is desired or not, the caller is expected to make sure that *DESTP
     134             :    is large enough if LEN is not zero.  */
     135             : gpgme_error_t
     136        1651 : _gpgme_decode_c_string (const char *src, char **destp, size_t len)
     137             : {
     138             :   char *dest;
     139             : 
     140             :   /* Set up the destination buffer.  */
     141        1651 :   if (len)
     142             :     {
     143        1647 :       if (len < strlen (src) + 1)
     144           0 :         return gpg_error (GPG_ERR_INTERNAL);
     145             : 
     146        1647 :       dest = *destp;
     147             :     }
     148             :   else
     149             :     {
     150             :       /* The converted string will never be larger than the original
     151             :          string.  */
     152           4 :       dest = malloc (strlen (src) + 1);
     153           4 :       if (!dest)
     154           0 :         return gpg_error_from_syserror ();
     155             : 
     156           4 :       *destp = dest;
     157             :     }
     158             : 
     159             :   /* Convert the string.  */
     160       63090 :   while (*src)
     161             :     {
     162       59788 :       if (*src != '\\')
     163             :         {
     164       59788 :           *(dest++) = *(src++);
     165       59788 :           continue;
     166             :         }
     167             : 
     168           0 :       switch (src[1])
     169             :         {
     170             : #define DECODE_ONE(match,result)        \
     171             :         case match:                     \
     172             :           src += 2;                     \
     173             :           *(dest++) = result;           \
     174             :           break;
     175             : 
     176           0 :           DECODE_ONE ('\'', '\'');
     177           0 :           DECODE_ONE ('\"', '\"');
     178           0 :           DECODE_ONE ('\?', '\?');
     179           0 :           DECODE_ONE ('\\', '\\');
     180           0 :           DECODE_ONE ('a', '\a');
     181           0 :           DECODE_ONE ('b', '\b');
     182           0 :           DECODE_ONE ('f', '\f');
     183           0 :           DECODE_ONE ('n', '\n');
     184           0 :           DECODE_ONE ('r', '\r');
     185           0 :           DECODE_ONE ('t', '\t');
     186           0 :           DECODE_ONE ('v', '\v');
     187             : 
     188             :         case 'x':
     189             :           {
     190           0 :             int val = _gpgme_hextobyte (&src[2]);
     191             : 
     192           0 :             if (val == -1)
     193             :               {
     194             :                 /* Should not happen.  */
     195           0 :                 *(dest++) = *(src++);
     196           0 :                 *(dest++) = *(src++);
     197           0 :                 if (*src)
     198           0 :                   *(dest++) = *(src++);
     199           0 :                 if (*src)
     200           0 :                   *(dest++) = *(src++);
     201             :               }
     202             :             else
     203             :               {
     204           0 :                 if (!val)
     205             :                   {
     206             :                     /* A binary zero is not representable in a C
     207             :                        string.  */
     208           0 :                     *(dest++) = '\\';
     209           0 :                     *(dest++) = '0';
     210             :                   }
     211             :                 else
     212           0 :                   *((unsigned char *) dest++) = val;
     213           0 :                 src += 4;
     214             :               }
     215             :           }
     216           0 :           break;
     217             : 
     218             :         default:
     219             :           {
     220             :             /* Should not happen.  */
     221           0 :             *(dest++) = *(src++);
     222           0 :             *(dest++) = *(src++);
     223             :           }
     224             :         }
     225             :     }
     226        1651 :   *(dest++) = 0;
     227             : 
     228        1651 :   return 0;
     229             : }
     230             : 
     231             : 
     232             : /* Decode the percent escaped string SRC and store the result in the
     233             :    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
     234             :    large enough buffer is allocated with malloc and *DESTP is set to
     235             :    the result.  Currently, LEN is only used to specify if allocation
     236             :    is desired or not, the caller is expected to make sure that *DESTP
     237             :    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
     238             :    characters are allowed in the output.  */
     239             : gpgme_error_t
     240        3014 : _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
     241             :                               int binary)
     242             : {
     243             :   char *dest;
     244             : 
     245             :   /* Set up the destination buffer.  */
     246        3014 :   if (len)
     247             :     {
     248        2290 :       if (len < strlen (src) + 1)
     249           0 :         return gpg_error (GPG_ERR_INTERNAL);
     250             : 
     251        2290 :       dest = *destp;
     252             :     }
     253             :   else
     254             :     {
     255             :       /* The converted string will never be larger than the original
     256             :          string.  */
     257         724 :       dest = malloc (strlen (src) + 1);
     258         724 :       if (!dest)
     259           0 :         return gpg_error_from_syserror ();
     260             : 
     261         724 :       *destp = dest;
     262             :     }
     263             : 
     264             :   /* Convert the string.  */
     265       93172 :   while (*src)
     266             :     {
     267       87143 :       if (*src != '%')
     268             :         {
     269       86750 :           *(dest++) = *(src++);
     270       86750 :           continue;
     271             :         }
     272             :       else
     273             :         {
     274         393 :           int val = _gpgme_hextobyte (&src[1]);
     275             : 
     276         394 :           if (val == -1)
     277             :             {
     278             :               /* Should not happen.  */
     279           0 :               *(dest++) = *(src++);
     280           0 :               if (*src)
     281           0 :                 *(dest++) = *(src++);
     282           0 :               if (*src)
     283           0 :                 *(dest++) = *(src++);
     284             :             }
     285             :           else
     286             :             {
     287         394 :               if (!val && !binary)
     288             :                 {
     289             :                   /* A binary zero is not representable in a C
     290             :                      string.  */
     291           0 :                   *(dest++) = '\\';
     292           0 :                   *(dest++) = '0';
     293             :                 }
     294             :               else
     295         394 :                 *((unsigned char *) dest++) = val;
     296         394 :               src += 3;
     297             :             }
     298             :         }
     299             :     }
     300        3015 :   *(dest++) = 0;
     301             : 
     302        3015 :   return 0;
     303             : }
     304             : 
     305             : 
     306             : /* Encode the string SRC with percent escaping and store the result in
     307             :    the buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
     308             :    large enough buffer is allocated with malloc and *DESTP is set to
     309             :    the result.  Currently, LEN is only used to specify if allocation
     310             :    is desired or not, the caller is expected to make sure that *DESTP
     311             :    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
     312             :    characters are allowed in the output.  */
     313             : gpgme_error_t
     314           0 : _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
     315             : {
     316             :   size_t destlen;
     317             :   char *dest;
     318             :   const char *str;
     319             : 
     320           0 :   destlen = 0;
     321           0 :   str = src;
     322             :   /* We percent-escape the + character because the user might need a
     323             :      "percent plus" escaped string (special gpg format).  But we
     324             :      percent-escape the space character, which works with and without
     325             :      the special plus format.  */
     326           0 :   while (*str)
     327             :     {
     328           0 :       if (*str == '+' || *str == '\"' || *str == '%'
     329           0 :           || *(const unsigned char *)str <= 0x20)
     330           0 :         destlen += 3;
     331             :       else
     332           0 :         destlen++;
     333           0 :       str++;
     334             :     }
     335             :   /* Terminating nul byte.  */
     336           0 :   destlen++;
     337             : 
     338             :   /* Set up the destination buffer.  */
     339           0 :   if (len)
     340             :     {
     341           0 :       if (len < destlen)
     342           0 :         return gpg_error (GPG_ERR_INTERNAL);
     343             : 
     344           0 :       dest = *destp;
     345             :     }
     346             :   else
     347             :     {
     348             :       /* The converted string will never be larger than the original
     349             :          string.  */
     350           0 :       dest = malloc (destlen);
     351           0 :       if (!dest)
     352           0 :         return gpg_error_from_syserror ();
     353             : 
     354           0 :       *destp = dest;
     355             :     }
     356             : 
     357             :   /* Convert the string.  */
     358           0 :   while (*src)
     359             :     {
     360           0 :       if (*src == '+' || *src == '\"' || *src == '%'
     361           0 :           || *(const unsigned char *)src <= 0x20)
     362             :         {
     363           0 :           snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
     364           0 :           dest += 3;
     365             :         }
     366             :       else
     367           0 :         *(dest++) = *src;
     368           0 :       src++;
     369             :     }
     370           0 :   *(dest++) = 0;
     371             : 
     372           0 :   return 0;
     373             : }
     374             : 
     375             : 
     376             : /* Split a string into space delimited fields and remove leading and
     377             :  * trailing spaces from each field.  A pointer to each field is
     378             :  * stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
     379             :  * modifies STRING.  The number of parsed fields is returned.
     380             :  */
     381             : int
     382         118 : _gpgme_split_fields (char *string, char **array, int arraysize)
     383             : {
     384         118 :   int n = 0;
     385             :   char *p, *pend;
     386             : 
     387         118 :   for (p = string; *p == ' '; p++)
     388             :     ;
     389             :   do
     390             :     {
     391         355 :       if (n == arraysize)
     392          17 :         break;
     393         338 :       array[n++] = p;
     394         338 :       pend = strchr (p, ' ');
     395         338 :       if (!pend)
     396         101 :         break;
     397         237 :       *pend++ = 0;
     398         237 :       for (p = pend; *p == ' '; p++)
     399             :         ;
     400             :     }
     401         237 :   while (*p);
     402             : 
     403         118 :   return n;
     404             : }
     405             : 
     406             : /* Convert the field STRING into an unsigned long value.  Check for
     407             :  * trailing garbage.  */
     408             : gpgme_error_t
     409         385 : _gpgme_strtoul_field (const char *string, unsigned long *result)
     410             : {
     411             :   char *endp;
     412             : 
     413         385 :   gpg_err_set_errno (0);
     414         385 :   *result = strtoul (string, &endp, 0);
     415         385 :   if (errno)
     416           0 :     return gpg_error_from_syserror ();
     417         385 :   if (endp == string || *endp)
     418           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     419         385 :   return 0;
     420             : }
     421             : 
     422             : 
     423             : /* Convert STRING into an offset value.  Note that this functions only
     424             :  * allows for a base-10 length.  This function is similar to atoi()
     425             :  * and thus there is no error checking.  */
     426             : gpgme_off_t
     427          88 : _gpgme_string_to_off (const char *string)
     428             : {
     429          88 :   gpgme_off_t value = 0;
     430             : 
     431         176 :   while (*string == ' ' || *string == '\t')
     432           0 :     string++;
     433         225 :   for (; *string >= '0' && *string <= '9'; string++)
     434             :     {
     435         137 :       value *= 10;
     436         137 :       value += atoi_1 (string);
     437             :     }
     438          88 :   return value;
     439             : }
     440             : 
     441             : 
     442             : #ifdef HAVE_W32_SYSTEM
     443             : static time_t
     444             : _gpgme_timegm (struct tm *tm)
     445             : {
     446             :   /* This one is thread safe.  */
     447             :   SYSTEMTIME st;
     448             :   FILETIME ft;
     449             :   unsigned long long cnsecs;
     450             : 
     451             :   st.wYear   = tm->tm_year + 1900;
     452             :   st.wMonth  = tm->tm_mon  + 1;
     453             :   st.wDay    = tm->tm_mday;
     454             :   st.wHour   = tm->tm_hour;
     455             :   st.wMinute = tm->tm_min;
     456             :   st.wSecond = tm->tm_sec;
     457             :   st.wMilliseconds = 0; /* Not available.  */
     458             :   st.wDayOfWeek = 0;    /* Ignored.  */
     459             : 
     460             :   /* System time is UTC thus the conversion is pretty easy.  */
     461             :   if (!SystemTimeToFileTime (&st, &ft))
     462             :     {
     463             :       gpg_err_set_errno (EINVAL);
     464             :       return (time_t)(-1);
     465             :     }
     466             : 
     467             :   cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
     468             :             | ft.dwLowDateTime);
     469             :   cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
     470             :   return (time_t)(cnsecs / 10000000ULL);
     471             : }
     472             : #endif
     473             : 
     474             : 
     475             : /* Parse the string TIMESTAMP into a time_t.  The string may either be
     476             :    seconds since Epoch or in the ISO 8601 format like
     477             :    "20390815T143012".  Returns 0 for an empty string or seconds since
     478             :    Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
     479             :    point to the next non-parsed character in TIMESTRING. */
     480             : time_t
     481        4963 : _gpgme_parse_timestamp (const char *timestamp, char **endp)
     482             : {
     483             :   /* Need to skip leading spaces, because that is what strtoul does
     484             :      but not our ISO 8601 checking code. */
     485       10121 :   while (*timestamp && *timestamp== ' ')
     486         195 :     timestamp++;
     487        4963 :   if (!*timestamp)
     488        2174 :     return 0;
     489             : 
     490        2789 :   if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
     491             :     {
     492             :       struct tm buf;
     493             :       int year;
     494             : 
     495          11 :       year = atoi_4 (timestamp);
     496          11 :       if (year < 1900)
     497           0 :         return (time_t)(-1);
     498             : 
     499          11 :       if (endp)
     500           3 :         *endp = (char*)(timestamp + 15);
     501             : 
     502             :       /* Fixme: We would better use a configure test to see whether
     503             :          mktime can handle dates beyond 2038. */
     504             :       if (sizeof (time_t) <= 4 && year >= 2038)
     505             :         return (time_t)2145914603; /* 2037-12-31 23:23:23 */
     506             : 
     507          11 :       memset (&buf, 0, sizeof buf);
     508          11 :       buf.tm_year = year - 1900;
     509          11 :       buf.tm_mon = atoi_2 (timestamp+4) - 1;
     510          11 :       buf.tm_mday = atoi_2 (timestamp+6);
     511          11 :       buf.tm_hour = atoi_2 (timestamp+9);
     512          11 :       buf.tm_min = atoi_2 (timestamp+11);
     513          11 :       buf.tm_sec = atoi_2 (timestamp+13);
     514             : 
     515             : #ifdef HAVE_W32_SYSTEM
     516             :       return _gpgme_timegm (&buf);
     517             : #else
     518             : #ifdef HAVE_TIMEGM
     519          11 :       return timegm (&buf);
     520             : #else
     521             :       {
     522             :         time_t tim;
     523             : 
     524             :         putenv ("TZ=UTC");
     525             :         tim = mktime (&buf);
     526             : #ifdef __GNUC__
     527             : #warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
     528             : #endif
     529             :         return tim;
     530             :       }
     531             : #endif /* !HAVE_TIMEGM */
     532             : #endif /* !HAVE_W32_SYSTEM */
     533             :     }
     534             :   else
     535        2778 :     return (time_t)strtoul (timestamp, endp, 10);
     536             : }
     537             : 
     538             : 
     539             : /* This function is similar to _gpgme_parse_timestamp but returns an
     540             :  * unsigned long and 0 on error.  */
     541             : unsigned long
     542        2657 : _gpgme_parse_timestamp_ul (const char *timestamp)
     543             : {
     544             :   time_t tim;
     545             :   char *tail;
     546             : 
     547        2657 :   if (!*timestamp)
     548        2657 :     return 0; /* Shortcut empty strings.  */
     549             : 
     550           0 :   tim = _gpgme_parse_timestamp (timestamp, &tail);
     551           0 :   if (tim == -1 || timestamp == tail || (*tail && *tail != ' '))
     552           0 :     tim = 0; /* No time given or invalid engine.  */
     553             : 
     554           0 :   return (unsigned long)tim;
     555             : }
     556             : 
     557             : 
     558             : /* The GPG backend uses OpenPGP algorithm numbers which we need to map
     559             :    to our algorithm numbers.  This function MUST not change ERRNO. */
     560             : int
     561        2566 : _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
     562             : {
     563        2566 :   if (protocol == GPGME_PROTOCOL_OPENPGP)
     564             :     {
     565        2557 :       switch (algo)
     566             :         {
     567        2550 :         case 1: case 2: case 3: case 16: case 17: break;
     568           2 :         case 18: algo = GPGME_PK_ECDH; break;
     569           0 :         case 19: algo = GPGME_PK_ECDSA; break;
     570           0 :         case 20: break;
     571           5 :         case 22: algo = GPGME_PK_EDDSA; break;
     572           0 :         default: algo = 0; break; /* Unknown.  */
     573             :         }
     574             :     }
     575             : 
     576        2566 :   return algo;
     577             : }
     578             : 
     579             : 
     580             : /* Return a string with a cipher algorithm.  */
     581             : const char *
     582          54 : _gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol)
     583             : {
     584          54 :   if (protocol == GPGME_PROTOCOL_OPENPGP)
     585             :     {
     586             :       /* The algo is given according to OpenPGP specs.  */
     587          54 :       switch (algo)
     588             :         {
     589           0 :         case 1:  return "IDEA";
     590           0 :         case 2:  return "3DES";
     591           0 :         case 3:  return "CAST5";
     592           0 :         case 4:  return "BLOWFISH";
     593          10 :         case 7:  return "AES";
     594           0 :         case 8:  return "AES192";
     595           4 :         case 9:  return "AES256";
     596          40 :         case 10: return "TWOFISH";
     597           0 :         case 11: return "CAMELLIA128";
     598           0 :         case 12: return "CAMELLIA192";
     599           0 :         case 13: return "CAMELLIA256";
     600             :         }
     601             :     }
     602             : 
     603           0 :   return "Unknown";
     604             : }
     605             : 
     606             : 
     607             : /* Return a string with the cipher mode.  */
     608             : const char *
     609          54 : _gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol)
     610             : {
     611          54 :   if (protocol == GPGME_PROTOCOL_OPENPGP)
     612             :     {
     613             :       /* The algo is given according to OpenPGP specs.  */
     614          54 :       switch (algo)
     615             :         {
     616          54 :         case 0:  return "CFB";
     617           0 :         case 1:  return "EAX";
     618           0 :         case 2:  return "OCB";
     619             :         }
     620             :     }
     621             : 
     622           0 :   return "Unknown";
     623             : }

Generated by: LCOV version 1.13