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