Bump to 2.4.3
[platform/upstream/gpg2.git] / dirmngr / misc.c
1 /* misc.c - miscellaneous
2  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
3  *      Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
4  *
5  * This file is part of DirMngr.
6  *
7  * DirMngr is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * DirMngr 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  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <errno.h>
28
29 #include "dirmngr.h"
30 #include "../common/util.h"
31 #include "misc.h"
32
33
34 /* Convert the hex encoded STRING back into binary and store the
35    result into the provided buffer RESULT.  The actual size of that
36    buffer will be returned.  The caller should provide RESULT of at
37    least strlen(STRING)/2 bytes.  There is no error detection, the
38    parsing stops at the first non hex character.  With RESULT given as
39    NULL, the function does only return the size of the buffer which
40    would be needed.  */
41 size_t
42 unhexify (unsigned char *result, const char *string)
43 {
44   const char *s;
45   size_t n;
46
47   for (s=string,n=0; hexdigitp (s) && hexdigitp(s+1); s += 2)
48     {
49       if (result)
50         result[n] = xtoi_2 (s);
51       n++;
52     }
53   return n;
54 }
55
56
57 char*
58 hashify_data( const char* data, size_t len )
59 {
60   unsigned char buf[20];
61   gcry_md_hash_buffer (GCRY_MD_SHA1, buf, data, len);
62   return hexify_data (buf, 20, 0);
63 }
64
65
66 /* FIXME: Replace this by hextobin.  */
67 char*
68 hexify_data (const unsigned char* data, size_t len, int with_prefix)
69 {
70   int i;
71   char *result = xmalloc (2*len + (with_prefix?2:0) + 1);
72   char *p;
73
74   if (with_prefix)
75     p = stpcpy (result, "0x");
76   else
77     p = result;
78
79   for (i = 0; i < 2*len; i+=2 )
80     snprintf (p+i, 3, "%02X", *data++);
81   return result;
82 }
83
84 char *
85 serial_hex (ksba_sexp_t serial )
86 {
87   unsigned char* p = serial;
88   char *endp;
89   unsigned long n;
90   char *certid;
91
92   if (!p)
93     return NULL;
94   else {
95     p++; /* ignore initial '(' */
96     n = strtoul (p, (char**)&endp, 10);
97     p = endp;
98     if (*p!=':')
99       return NULL;
100     else {
101       int i = 0;
102       certid = xmalloc( sizeof( char )*(2*n + 1 ) );
103       for (p++; n; n--, p++) {
104         sprintf ( certid+i , "%02X", *p);
105         i += 2;
106       }
107     }
108   }
109   return certid;
110 }
111
112
113 /* Take an S-Expression encoded blob and return a pointer to the
114    actual data as well as its length.  Return NULL for an invalid
115    S-Expression.*/
116 const unsigned char *
117 serial_to_buffer (const ksba_sexp_t serial, size_t *length)
118 {
119   unsigned char *p = serial;
120   char *endp;
121   unsigned long n;
122
123   if (!p || *p != '(')
124     return NULL;
125   p++;
126   n = strtoul (p, &endp, 10);
127   p = endp;
128   if (*p != ':')
129     return NULL;
130   p++;
131   *length = n;
132   return p;
133 }
134
135
136 /* Do an in-place percent unescaping of STRING. Returns STRING. Note
137    that this function does not do a '+'-to-space unescaping.*/
138 char *
139 unpercent_string (char *string)
140 {
141   char *s = string;
142   char *d = string;
143
144   while (*s)
145     {
146       if (*s == '%' && s[1] && s[2])
147         {
148           s++;
149           *d++ = xtoi_2 ( s);
150           s += 2;
151         }
152       else
153         *d++ = *s++;
154     }
155   *d = 0;
156   return string;
157 }
158
159 /* Convert a canonical encoded S-expression in CANON into the GCRY
160    type. */
161 gpg_error_t
162 canon_sexp_to_gcry (const unsigned char *canon, gcry_sexp_t *r_sexp)
163 {
164   gpg_error_t err;
165   size_t n;
166   gcry_sexp_t sexp;
167
168   *r_sexp = NULL;
169   n = gcry_sexp_canon_len (canon, 0, NULL, NULL);
170   if (!n)
171     {
172       log_error (_("invalid canonical S-expression found\n"));
173       err = gpg_error (GPG_ERR_INV_SEXP);
174     }
175   else if ((err = gcry_sexp_sscan (&sexp, NULL, canon, n)))
176     log_error (_("converting S-expression failed: %s\n"), gcry_strerror (err));
177   else
178     *r_sexp = sexp;
179   return err;
180 }
181
182
183 /* Return an allocated buffer with the formatted fingerprint as one
184    large hexnumber */
185 char *
186 get_fingerprint_hexstring (ksba_cert_t cert)
187 {
188   unsigned char digest[20];
189   gcry_md_hd_t md;
190   int rc;
191   char *buf;
192   int i;
193
194   rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
195   if (rc)
196     log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
197
198   rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
199   if (rc)
200     {
201       log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
202       memset (digest, 0xff, 20); /* Use a dummy value. */
203     }
204   else
205     {
206       gcry_md_final (md);
207       memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
208     }
209   gcry_md_close (md);
210   buf = xmalloc (41);
211   *buf = 0;
212   for (i=0; i < 20; i++ )
213     sprintf (buf+strlen(buf), "%02X", digest[i]);
214   return buf;
215 }
216
217 /* Return an allocated buffer with the formatted fingerprint as one
218    large hexnumber.  This version inserts the usual colons. */
219 char *
220 get_fingerprint_hexstring_colon (ksba_cert_t cert)
221 {
222   unsigned char digest[20];
223   gcry_md_hd_t md;
224   int rc;
225   char *buf;
226   int i;
227
228   rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
229   if (rc)
230     log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
231
232   rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
233   if (rc)
234     {
235       log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
236       memset (digest, 0xff, 20); /* Use a dummy value. */
237     }
238   else
239     {
240       gcry_md_final (md);
241       memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
242     }
243   gcry_md_close (md);
244   buf = xmalloc (61);
245   *buf = 0;
246   for (i=0; i < 20; i++ )
247     sprintf (buf+strlen(buf), "%02X:", digest[i]);
248   buf[strlen(buf)-1] = 0; /* Remove railing colon. */
249   return buf;
250 }
251
252
253 /* Dump the serial number SERIALNO to the log stream.  */
254 void
255 dump_serial (ksba_sexp_t serialno)
256 {
257   char *p;
258
259   p = serial_hex (serialno);
260   log_printf ("%s", p?p:"?");
261   xfree (p);
262 }
263
264
265 /* Dump STRING to the log file but choose the best readable
266    format.  */
267 void
268 dump_string (const char *string)
269 {
270
271   if (!string)
272     log_printf ("[error]");
273   else
274     {
275       const unsigned char *s;
276
277       for (s=string; *s; s++)
278         {
279           if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
280             break;
281         }
282       if (!*s && *string != '[')
283         log_printf ("%s", string);
284       else
285         {
286           log_printf ( "[ ");
287           log_printhex (string, strlen (string), NULL);
288           log_printf ( " ]");
289         }
290     }
291 }
292
293 /* Dump an KSBA cert object to the log stream. Prefix the output with
294    TEXT.  This is used for debugging. */
295 void
296 dump_cert (const char *text, ksba_cert_t cert)
297 {
298   ksba_sexp_t sexp;
299   char *p;
300   ksba_isotime_t t;
301   int idx;
302
303   log_debug ("BEGIN Certificate '%s':\n", text? text:"");
304   if (cert)
305     {
306       sexp = ksba_cert_get_serial (cert);
307       p = serial_hex (sexp);
308       log_debug ("     serial: %s\n", p?p:"?");
309       xfree (p);
310       ksba_free (sexp);
311
312       ksba_cert_get_validity (cert, 0, t);
313       log_debug ("  notBefore: ");
314       dump_isotime (t);
315       log_printf ("\n");
316       ksba_cert_get_validity (cert, 1, t);
317       log_debug ("   notAfter: ");
318       dump_isotime (t);
319       log_printf ("\n");
320
321       p = ksba_cert_get_issuer (cert, 0);
322       log_debug ("     issuer: ");
323       dump_string (p);
324       ksba_free (p);
325       log_printf ("\n");
326
327       p = ksba_cert_get_subject (cert, 0);
328       log_debug ("    subject: ");
329       dump_string (p);
330       ksba_free (p);
331       log_printf ("\n");
332       for (idx=1; (p = ksba_cert_get_subject (cert, idx)); idx++)
333         {
334           log_debug ("        aka: ");
335           dump_string (p);
336           ksba_free (p);
337           log_printf ("\n");
338         }
339
340       log_debug ("  hash algo: %s\n", ksba_cert_get_digest_algo (cert));
341
342       p = get_fingerprint_hexstring (cert);
343       log_debug ("  SHA1 fingerprint: %s\n", p);
344       xfree (p);
345     }
346   log_debug ("END Certificate\n");
347 }
348
349
350
351 /* Log the certificate's name in "#SN/ISSUERDN" format along with
352    TEXT. */
353 void
354 cert_log_name (const char *text, ksba_cert_t cert)
355 {
356   log_info ("%s", text? text:"certificate" );
357   if (cert)
358     {
359       ksba_sexp_t sn;
360       char *p;
361
362       p = ksba_cert_get_issuer (cert, 0);
363       sn = ksba_cert_get_serial (cert);
364       if (p && sn)
365         {
366           log_printf (" #");
367           dump_serial (sn);
368           log_printf ("/");
369           dump_string (p);
370         }
371       else
372         log_printf (" [invalid]");
373       ksba_free (sn);
374       xfree (p);
375     }
376   log_printf ("\n");
377 }
378
379
380 /* Log the certificate's subject DN along with TEXT. */
381 void
382 cert_log_subject (const char *text, ksba_cert_t cert)
383 {
384   log_info ("%s", text? text:"subject" );
385   if (cert)
386     {
387       char *p;
388
389       p = ksba_cert_get_subject (cert, 0);
390       if (p)
391         {
392           log_printf (" /");
393           dump_string (p);
394           xfree (p);
395         }
396       else
397         log_printf (" [invalid]");
398     }
399   log_printf ("\n");
400 }
401
402
403 /* Callback to print infos about the TLS certificates.  */
404 void
405 cert_log_cb (http_session_t sess, gpg_error_t err,
406              const char *hostname, const void **certs, size_t *certlens)
407 {
408   ksba_cert_t cert;
409   size_t n;
410
411   (void)sess;
412
413   if (!err)
414     return; /* No error - no need to log anything  */
415
416   log_debug ("expected hostname: %s\n", hostname);
417   for (n=0; certs[n]; n++)
418     {
419       err = ksba_cert_new (&cert);
420       if (!err)
421         err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]);
422       if (err)
423         log_error ("error parsing cert for logging: %s\n", gpg_strerror (err));
424       else
425         {
426           char textbuf[20];
427           snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n);
428           dump_cert (textbuf, cert);
429         }
430
431       ksba_cert_release (cert);
432     }
433 }
434
435
436 /****************
437  * Remove all %xx escapes; this is done inplace.
438  * Returns: New length of the string.
439  */
440 static int
441 remove_percent_escapes (unsigned char *string)
442 {
443   int n = 0;
444   unsigned char *p, *s;
445
446   for (p = s = string; *s; s++)
447     {
448       if (*s == '%')
449         {
450           if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
451             {
452               s++;
453               *p = xtoi_2 (s);
454               s++;
455               p++;
456               n++;
457             }
458           else
459             {
460               *p++ = *s++;
461               if (*s)
462                 *p++ = *s++;
463               if (*s)
464                 *p++ = *s++;
465               if (*s)
466                 *p = 0;
467               return -1;   /* Bad URI. */
468             }
469         }
470       else
471         {
472           *p++ = *s;
473           n++;
474         }
475     }
476   *p = 0;  /* Always keep a string terminator. */
477   return n;
478 }
479
480
481 /* Return the host name and the port (0 if none was given) from the
482    URL.  Return NULL on error or if host is not included in the
483    URL.  */
484 char *
485 host_and_port_from_url (const char *url, int *port)
486 {
487   const char *s, *s2;
488   char *buf, *p;
489   int n;
490
491   s = url;
492
493   *port = 0;
494
495   /* Find the scheme */
496   if ( !(s2 = strchr (s, ':')) || s2 == s )
497     return NULL;  /* No scheme given. */
498   s = s2+1;
499
500   /* Find the hostname */
501   if (*s != '/')
502     return NULL; /* Does not start with a slash. */
503
504   s++;
505   if (*s != '/')
506     return NULL; /* No host name.  */
507   s++;
508
509   buf = xtrystrdup (s);
510   if (!buf)
511     {
512       log_error (_("malloc failed: %s\n"), strerror (errno));
513       return NULL;
514     }
515   if ((p = strchr (buf, '/')))
516     *p++ = 0;
517   strlwr (buf);
518   if ((p = strchr (buf, ':')))
519     {
520       *p++ = 0;
521       *port = atoi (p);
522     }
523
524   /* Remove quotes and make sure that no Nul has been encoded. */
525   if ((n = remove_percent_escapes (buf)) < 0
526       || n != strlen (buf) )
527     {
528       log_error (_("bad URL encoding detected\n"));
529       xfree (buf);
530       return NULL;
531     }
532
533   return buf;
534 }
535
536
537 /* A KSBA reader callback to read from an estream.  */
538 static int
539 my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
540                            size_t *r_nread)
541 {
542   estream_t fp = cb_value;
543
544   if (!fp)
545     return gpg_error (GPG_ERR_INV_VALUE);
546
547   if (!buffer && !count && !r_nread)
548     {
549       es_rewind (fp);
550       return 0;
551     }
552
553   *r_nread = es_fread (buffer, 1, count, fp);
554   if (!*r_nread)
555     return -1; /* EOF or error.  */
556   return 0; /* Success.  */
557 }
558
559
560 /* Create a KSBA reader object and connect it to the estream FP.  */
561 gpg_error_t
562 create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
563 {
564   gpg_error_t err;
565   ksba_reader_t reader;
566
567   *r_reader = NULL;
568   err = ksba_reader_new (&reader);
569   if (!err)
570     err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
571   if (err)
572     {
573       log_error (_("error initializing reader object: %s\n"),
574                  gpg_strerror (err));
575       ksba_reader_release (reader);
576       return err;
577     }
578   *r_reader = reader;
579   return 0;
580 }
581
582 gpg_error_t
583 armor_data (char **r_string, const void *data, size_t datalen)
584 {
585   gpg_error_t err;
586   struct b64state b64state;
587   estream_t fp;
588   long length;
589   char *buffer;
590   size_t nread;
591
592   *r_string = NULL;
593
594   fp = es_fopenmem (0, "rw,samethread");
595   if (!fp)
596     return gpg_error_from_syserror ();
597
598   if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
599       || (err=b64enc_write (&b64state, data, datalen))
600       || (err = b64enc_finish (&b64state)))
601     {
602       es_fclose (fp);
603       return err;
604     }
605
606   /* FIXME: To avoid the extra buffer allocation estream should
607      provide a function to snatch the internal allocated memory from
608      such a memory stream.  */
609   length = es_ftell (fp);
610   if (length < 0)
611     {
612       err = gpg_error_from_syserror ();
613       es_fclose (fp);
614       return err;
615     }
616
617   buffer = xtrymalloc (length+1);
618   if (!buffer)
619     {
620       err = gpg_error_from_syserror ();
621       es_fclose (fp);
622       return err;
623     }
624
625   es_rewind (fp);
626   if (es_read (fp, buffer, length, &nread))
627     {
628       err = gpg_error_from_syserror ();
629       es_fclose (fp);
630       return err;
631     }
632   buffer[nread] = 0;
633   es_fclose (fp);
634
635   *r_string = buffer;
636   return 0;
637 }
638
639
640 /* Copy all data from IN to OUT.  OUT may be NULL to use this function
641  * as a dummy reader.  */
642 gpg_error_t
643 copy_stream (estream_t in, estream_t out)
644 {
645   char buffer[512];
646   size_t nread;
647
648   while (!es_read (in, buffer, sizeof buffer, &nread))
649     {
650       if (!nread)
651         return 0; /* EOF */
652       if (out && es_write (out, buffer, nread, NULL))
653         break;
654     }
655   return gpg_error_from_syserror ();
656 }