Update Japanese Translation.
[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 /****************
388  * Remove all %xx escapes; this is done inplace.
389  * Returns: New length of the string.
390  */
391 static int
392 remove_percent_escapes (unsigned char *string)
393 {
394   int n = 0;
395   unsigned char *p, *s;
396
397   for (p = s = string; *s; s++)
398     {
399       if (*s == '%')
400         {
401           if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
402             {
403               s++;
404               *p = xtoi_2 (s);
405               s++;
406               p++;
407               n++;
408             }
409           else
410             {
411               *p++ = *s++;
412               if (*s)
413                 *p++ = *s++;
414               if (*s)
415                 *p++ = *s++;
416               if (*s)
417                 *p = 0;
418               return -1;   /* Bad URI. */
419             }
420         }
421       else
422         {
423           *p++ = *s;
424           n++;
425         }
426     }
427   *p = 0;  /* Always keep a string terminator. */
428   return n;
429 }
430
431
432 /* Return the host name and the port (0 if none was given) from the
433    URL.  Return NULL on error or if host is not included in the
434    URL.  */
435 char *
436 host_and_port_from_url (const char *url, int *port)
437 {
438   const char *s, *s2;
439   char *buf, *p;
440   int n;
441
442   s = url;
443
444   *port = 0;
445
446   /* Find the scheme */
447   if ( !(s2 = strchr (s, ':')) || s2 == s )
448     return NULL;  /* No scheme given. */
449   s = s2+1;
450
451   /* Find the hostname */
452   if (*s != '/')
453     return NULL; /* Does not start with a slash. */
454
455   s++;
456   if (*s != '/')
457     return NULL; /* No host name.  */
458   s++;
459
460   buf = xtrystrdup (s);
461   if (!buf)
462     {
463       log_error (_("malloc failed: %s\n"), strerror (errno));
464       return NULL;
465     }
466   if ((p = strchr (buf, '/')))
467     *p++ = 0;
468   strlwr (buf);
469   if ((p = strchr (p, ':')))
470     {
471       *p++ = 0;
472       *port = atoi (p);
473     }
474
475   /* Remove quotes and make sure that no Nul has been encoded. */
476   if ((n = remove_percent_escapes (buf)) < 0
477       || n != strlen (buf) )
478     {
479       log_error (_("bad URL encoding detected\n"));
480       xfree (buf);
481       return NULL;
482     }
483
484   return buf;
485 }
486
487
488 /* A KSBA reader callback to read from an estream.  */
489 static int
490 my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
491                            size_t *r_nread)
492 {
493   estream_t fp = cb_value;
494
495   if (!fp)
496     return gpg_error (GPG_ERR_INV_VALUE);
497
498   if (!buffer && !count && !r_nread)
499     {
500       es_rewind (fp);
501       return 0;
502     }
503
504   *r_nread = es_fread (buffer, 1, count, fp);
505   if (!*r_nread)
506     return -1; /* EOF or error.  */
507   return 0; /* Success.  */
508 }
509
510
511 /* Create a KSBA reader object and connect it to the estream FP.  */
512 gpg_error_t
513 create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
514 {
515   gpg_error_t err;
516   ksba_reader_t reader;
517
518   *r_reader = NULL;
519   err = ksba_reader_new (&reader);
520   if (!err)
521     err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
522   if (err)
523     {
524       log_error (_("error initializing reader object: %s\n"),
525                  gpg_strerror (err));
526       ksba_reader_release (reader);
527       return err;
528     }
529   *r_reader = reader;
530   return 0;
531 }