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 : }
|