core: Fix arg counting in enginge-gpg
[gpgme.git] / src / conversion.c
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, see <https://gnu.org/licenses/>.
19  * SPDX-License-Identifier: LGPL-2.1-or-later
20  */
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 \f
46 static char *
47 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   argc = 0;
55   argv[argc++] = s1;
56   needed = strlen (s1);
57   while (((argv[argc] = va_arg (arg_ptr, const char *))))
58     {
59       needed += strlen (argv[argc]);
60       if (argc >= DIM (argv)-1)
61         {
62           gpg_err_set_errno (EINVAL);
63           return NULL;
64         }
65       argc++;
66     }
67   needed++;
68   buffer = malloc (needed);
69   if (buffer)
70     {
71       for (p = buffer, argc=0; argv[argc]; argc++)
72         p = stpcpy (p, argv[argc]);
73     }
74   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 _gpgme_strconcat (const char *s1, ...)
83 {
84   va_list arg_ptr;
85   char *result;
86
87   if (!s1)
88     result = strdup ("");
89   else
90     {
91       va_start (arg_ptr, s1);
92       result = do_strconcat (s1, arg_ptr);
93       va_end (arg_ptr);
94     }
95   return result;
96 }
97
98
99
100 \f
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 _gpgme_hextobyte (const char *str)
106 {
107   int val = 0;
108   int i;
109
110 #define NROFHEXDIGITS 2
111   for (i = 0; i < NROFHEXDIGITS; i++)
112     {
113       if (*str >= '0' && *str <= '9')
114         val += *str - '0';
115       else if (*str >= 'A' && *str <= 'F')
116         val += 10 + *str - 'A';
117       else if (*str >= 'a' && *str <= 'f')
118         val += 10 + *str - 'a';
119       else
120         return -1;
121       if (i < NROFHEXDIGITS - 1)
122         val *= 16;
123       str++;
124     }
125   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 _gpgme_decode_c_string (const char *src, char **destp, size_t len)
137 {
138   char *dest;
139
140   /* Set up the destination buffer.  */
141   if (len)
142     {
143       if (len < strlen (src) + 1)
144         return gpg_error (GPG_ERR_INTERNAL);
145
146       dest = *destp;
147     }
148   else
149     {
150       /* The converted string will never be larger than the original
151          string.  */
152       dest = malloc (strlen (src) + 1);
153       if (!dest)
154         return gpg_error_from_syserror ();
155
156       *destp = dest;
157     }
158
159   /* Convert the string.  */
160   while (*src)
161     {
162       if (*src != '\\')
163         {
164           *(dest++) = *(src++);
165           continue;
166         }
167
168       switch (src[1])
169         {
170 #define DECODE_ONE(match,result)        \
171         case match:                     \
172           src += 2;                     \
173           *(dest++) = result;           \
174           break;
175
176           DECODE_ONE ('\'', '\'');
177           DECODE_ONE ('\"', '\"');
178           DECODE_ONE ('\?', '\?');
179           DECODE_ONE ('\\', '\\');
180           DECODE_ONE ('a', '\a');
181           DECODE_ONE ('b', '\b');
182           DECODE_ONE ('f', '\f');
183           DECODE_ONE ('n', '\n');
184           DECODE_ONE ('r', '\r');
185           DECODE_ONE ('t', '\t');
186           DECODE_ONE ('v', '\v');
187
188         case 'x':
189           {
190             int val = _gpgme_hextobyte (&src[2]);
191
192             if (val == -1)
193               {
194                 /* Should not happen.  */
195                 *(dest++) = *(src++);
196                 *(dest++) = *(src++);
197                 if (*src)
198                   *(dest++) = *(src++);
199                 if (*src)
200                   *(dest++) = *(src++);
201               }
202             else
203               {
204                 if (!val)
205                   {
206                     /* A binary zero is not representable in a C
207                        string.  */
208                     *(dest++) = '\\';
209                     *(dest++) = '0';
210                   }
211                 else
212                   *((unsigned char *) dest++) = val;
213                 src += 4;
214               }
215           }
216           break;
217
218         default:
219           {
220             /* Should not happen.  */
221             *(dest++) = *(src++);
222             *(dest++) = *(src++);
223           }
224         }
225     }
226   *(dest++) = 0;
227
228   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 _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   if (len)
247     {
248       if (len < strlen (src) + 1)
249         return gpg_error (GPG_ERR_INTERNAL);
250
251       dest = *destp;
252     }
253   else
254     {
255       /* The converted string will never be larger than the original
256          string.  */
257       dest = malloc (strlen (src) + 1);
258       if (!dest)
259         return gpg_error_from_syserror ();
260
261       *destp = dest;
262     }
263
264   /* Convert the string.  */
265   while (*src)
266     {
267       if (*src != '%')
268         {
269           *(dest++) = *(src++);
270           continue;
271         }
272       else
273         {
274           int val = _gpgme_hextobyte (&src[1]);
275
276           if (val == -1)
277             {
278               /* Should not happen.  */
279               *(dest++) = *(src++);
280               if (*src)
281                 *(dest++) = *(src++);
282               if (*src)
283                 *(dest++) = *(src++);
284             }
285           else
286             {
287               if (!val && !binary)
288                 {
289                   /* A binary zero is not representable in a C
290                      string.  */
291                   *(dest++) = '\\';
292                   *(dest++) = '0';
293                 }
294               else
295                 *((unsigned char *) dest++) = val;
296               src += 3;
297             }
298         }
299     }
300   *(dest++) = 0;
301
302   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 _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   destlen = 0;
321   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   while (*str)
327     {
328       if (*str == '+' || *str == '\"' || *str == '%'
329           || *(const unsigned char *)str <= 0x20)
330         destlen += 3;
331       else
332         destlen++;
333       str++;
334     }
335   /* Terminating nul byte.  */
336   destlen++;
337
338   /* Set up the destination buffer.  */
339   if (len)
340     {
341       if (len < destlen)
342         return gpg_error (GPG_ERR_INTERNAL);
343
344       dest = *destp;
345     }
346   else
347     {
348       /* The converted string will never be larger than the original
349          string.  */
350       dest = malloc (destlen);
351       if (!dest)
352         return gpg_error_from_syserror ();
353
354       *destp = dest;
355     }
356
357   /* Convert the string.  */
358   while (*src)
359     {
360       if (*src == '+' || *src == '\"' || *src == '%'
361           || *(const unsigned char *)src <= 0x20)
362         {
363           snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
364           dest += 3;
365         }
366       else
367         *(dest++) = *src;
368       src++;
369     }
370   *(dest++) = 0;
371
372   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 _gpgme_split_fields (char *string, char **array, int arraysize)
383 {
384   int n = 0;
385   char *p, *pend;
386
387   for (p = string; *p == ' '; p++)
388     ;
389   do
390     {
391       if (n == arraysize)
392         break;
393       array[n++] = p;
394       pend = strchr (p, ' ');
395       if (!pend)
396         break;
397       *pend++ = 0;
398       for (p = pend; *p == ' '; p++)
399         ;
400     }
401   while (*p);
402
403   return n;
404 }
405
406 /* Convert the field STRING into an unsigned long value.  Check for
407  * trailing garbage.  */
408 gpgme_error_t
409 _gpgme_strtoul_field (const char *string, unsigned long *result)
410 {
411   char *endp;
412
413   gpg_err_set_errno (0);
414   *result = strtoul (string, &endp, 0);
415   if (errno)
416     return gpg_error_from_syserror ();
417   if (endp == string || *endp)
418     return gpg_error (GPG_ERR_INV_VALUE);
419   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 _gpgme_string_to_off (const char *string)
428 {
429   gpgme_off_t value = 0;
430
431   while (*string == ' ' || *string == '\t')
432     string++;
433   for (; *string >= '0' && *string <= '9'; string++)
434     {
435       value *= 10;
436       value += atoi_1 (string);
437     }
438   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 _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   while (*timestamp && *timestamp== ' ')
486     timestamp++;
487   if (!*timestamp)
488     return 0;
489
490   if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
491     {
492       struct tm buf;
493       int year;
494
495       year = atoi_4 (timestamp);
496       if (year < 1900)
497         return (time_t)(-1);
498
499       if (endp)
500         *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       memset (&buf, 0, sizeof buf);
508       buf.tm_year = year - 1900;
509       buf.tm_mon = atoi_2 (timestamp+4) - 1;
510       buf.tm_mday = atoi_2 (timestamp+6);
511       buf.tm_hour = atoi_2 (timestamp+9);
512       buf.tm_min = atoi_2 (timestamp+11);
513       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       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     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 _gpgme_parse_timestamp_ul (const char *timestamp)
543 {
544   time_t tim;
545   char *tail;
546
547   if (!*timestamp)
548     return 0; /* Shortcut empty strings.  */
549
550   tim = _gpgme_parse_timestamp (timestamp, &tail);
551   if (tim == -1 || timestamp == tail || (*tail && *tail != ' '))
552     tim = 0; /* No time given or invalid engine.  */
553
554   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 _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
562 {
563   if (protocol == GPGME_PROTOCOL_OPENPGP)
564     {
565       switch (algo)
566         {
567         case 1: case 2: case 3: case 16: case 17: break;
568         case 18: algo = GPGME_PK_ECDH; break;
569         case 19: algo = GPGME_PK_ECDSA; break;
570         case 20: break;
571         case 22: algo = GPGME_PK_EDDSA; break;
572         default: algo = 0; break; /* Unknown.  */
573         }
574     }
575
576   return algo;
577 }
578
579
580 /* Return a string with a cipher algorithm.  */
581 const char *
582 _gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol)
583 {
584   if (protocol == GPGME_PROTOCOL_OPENPGP)
585     {
586       /* The algo is given according to OpenPGP specs.  */
587       switch (algo)
588         {
589         case 1:  return "IDEA";
590         case 2:  return "3DES";
591         case 3:  return "CAST5";
592         case 4:  return "BLOWFISH";
593         case 7:  return "AES";
594         case 8:  return "AES192";
595         case 9:  return "AES256";
596         case 10: return "TWOFISH";
597         case 11: return "CAMELLIA128";
598         case 12: return "CAMELLIA192";
599         case 13: return "CAMELLIA256";
600         }
601     }
602
603   return "Unknown";
604 }
605
606
607 /* Return a string with the cipher mode.  */
608 const char *
609 _gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol)
610 {
611   if (protocol == GPGME_PROTOCOL_OPENPGP)
612     {
613       /* The algo is given according to OpenPGP specs.  */
614       switch (algo)
615         {
616         case 0:  return "CFB";
617         case 1:  return "EAX";
618         case 2:  return "OCB";
619         }
620     }
621
622   return "Unknown";
623 }