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