1 /* misc.c - miscellaneous
2 * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3 * Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
5 * This file is part of DirMngr.
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.
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.
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
30 #include "../common/util.h"
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
42 unhexify (unsigned char *result, const char *string)
47 for (s=string,n=0; hexdigitp (s) && hexdigitp(s+1); s += 2)
50 result[n] = xtoi_2 (s);
58 hashify_data( const char* data, size_t len )
60 unsigned char buf[20];
61 gcry_md_hash_buffer (GCRY_MD_SHA1, buf, data, len);
62 return hexify_data (buf, 20, 0);
66 /* FIXME: Replace this by hextobin. */
68 hexify_data (const unsigned char* data, size_t len, int with_prefix)
71 char *result = xmalloc (2*len + (with_prefix?2:0) + 1);
75 p = stpcpy (result, "0x");
79 for (i = 0; i < 2*len; i+=2 )
80 snprintf (p+i, 3, "%02X", *data++);
85 serial_hex (ksba_sexp_t serial )
87 unsigned char* p = serial;
95 p++; /* ignore initial '(' */
96 n = strtoul (p, (char**)&endp, 10);
102 certid = xmalloc( sizeof( char )*(2*n + 1 ) );
103 for (p++; n; n--, p++) {
104 sprintf ( certid+i , "%02X", *p);
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
116 const unsigned char *
117 serial_to_buffer (const ksba_sexp_t serial, size_t *length)
119 unsigned char *p = serial;
126 n = strtoul (p, &endp, 10);
136 /* Do an in-place percent unescaping of STRING. Returns STRING. Note
137 that this function does not do a '+'-to-space unescaping.*/
139 unpercent_string (char *string)
146 if (*s == '%' && s[1] && s[2])
159 /* Convert a canonical encoded S-expression in CANON into the GCRY
162 canon_sexp_to_gcry (const unsigned char *canon, gcry_sexp_t *r_sexp)
169 n = gcry_sexp_canon_len (canon, 0, NULL, NULL);
172 log_error (_("invalid canonical S-expression found\n"));
173 err = gpg_error (GPG_ERR_INV_SEXP);
175 else if ((err = gcry_sexp_sscan (&sexp, NULL, canon, n)))
176 log_error (_("converting S-expression failed: %s\n"), gcry_strerror (err));
183 /* Return an allocated buffer with the formatted fingerprint as one
186 get_fingerprint_hexstring (ksba_cert_t cert)
188 unsigned char digest[20];
194 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
196 log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
198 rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
201 log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
202 memset (digest, 0xff, 20); /* Use a dummy value. */
207 memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
212 for (i=0; i < 20; i++ )
213 sprintf (buf+strlen(buf), "%02X", digest[i]);
217 /* Return an allocated buffer with the formatted fingerprint as one
218 large hexnumber. This version inserts the usual colons. */
220 get_fingerprint_hexstring_colon (ksba_cert_t cert)
222 unsigned char digest[20];
228 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
230 log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
232 rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
235 log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
236 memset (digest, 0xff, 20); /* Use a dummy value. */
241 memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
246 for (i=0; i < 20; i++ )
247 sprintf (buf+strlen(buf), "%02X:", digest[i]);
248 buf[strlen(buf)-1] = 0; /* Remove railing colon. */
253 /* Dump the serial number SERIALNO to the log stream. */
255 dump_serial (ksba_sexp_t serialno)
259 p = serial_hex (serialno);
260 log_printf ("%s", p?p:"?");
265 /* Dump STRING to the log file but choose the best readable
268 dump_string (const char *string)
272 log_printf ("[error]");
275 const unsigned char *s;
277 for (s=string; *s; s++)
279 if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
282 if (!*s && *string != '[')
283 log_printf ("%s", string);
287 log_printhex (NULL, string, strlen (string));
293 /* Dump an KSBA cert object to the log stream. Prefix the output with
294 TEXT. This is used for debugging. */
296 dump_cert (const char *text, ksba_cert_t cert)
303 log_debug ("BEGIN Certificate '%s':\n", text? text:"");
306 sexp = ksba_cert_get_serial (cert);
307 p = serial_hex (sexp);
308 log_debug (" serial: %s\n", p?p:"?");
312 ksba_cert_get_validity (cert, 0, t);
313 log_debug (" notBefore: ");
316 ksba_cert_get_validity (cert, 1, t);
317 log_debug (" notAfter: ");
321 p = ksba_cert_get_issuer (cert, 0);
322 log_debug (" issuer: ");
327 p = ksba_cert_get_subject (cert, 0);
328 log_debug (" subject: ");
332 for (idx=1; (p = ksba_cert_get_subject (cert, idx)); idx++)
334 log_debug (" aka: ");
340 log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert));
342 p = get_fingerprint_hexstring (cert);
343 log_debug (" SHA1 fingerprint: %s\n", p);
346 log_debug ("END Certificate\n");
351 /* Log the certificate's name in "#SN/ISSUERDN" format along with
354 cert_log_name (const char *text, ksba_cert_t cert)
356 log_info ("%s", text? text:"certificate" );
362 p = ksba_cert_get_issuer (cert, 0);
363 sn = ksba_cert_get_serial (cert);
372 log_printf (" [invalid]");
380 /* Log the certificate's subject DN along with TEXT. */
382 cert_log_subject (const char *text, ksba_cert_t cert)
384 log_info ("%s", text? text:"subject" );
389 p = ksba_cert_get_subject (cert, 0);
397 log_printf (" [invalid]");
403 /* Callback to print infos about the TLS certificates. */
405 cert_log_cb (http_session_t sess, gpg_error_t err,
406 const char *hostname, const void **certs, size_t *certlens)
414 return; /* No error - no need to log anything */
416 log_debug ("expected hostname: %s\n", hostname);
417 for (n=0; certs[n]; n++)
419 err = ksba_cert_new (&cert);
421 err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]);
423 log_error ("error parsing cert for logging: %s\n", gpg_strerror (err));
427 snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n);
428 dump_cert (textbuf, cert);
431 ksba_cert_release (cert);
437 * Remove all %xx escapes; this is done inplace.
438 * Returns: New length of the string.
441 remove_percent_escapes (unsigned char *string)
444 unsigned char *p, *s;
446 for (p = s = string; *s; s++)
450 if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
467 return -1; /* Bad URI. */
476 *p = 0; /* Always keep a string terminator. */
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
485 host_and_port_from_url (const char *url, int *port)
495 /* Find the scheme */
496 if ( !(s2 = strchr (s, ':')) || s2 == s )
497 return NULL; /* No scheme given. */
500 /* Find the hostname */
502 return NULL; /* Does not start with a slash. */
506 return NULL; /* No host name. */
509 buf = xtrystrdup (s);
512 log_error (_("malloc failed: %s\n"), strerror (errno));
515 if ((p = strchr (buf, '/')))
518 if ((p = strchr (p, ':')))
524 /* Remove quotes and make sure that no Nul has been encoded. */
525 if ((n = remove_percent_escapes (buf)) < 0
526 || n != strlen (buf) )
528 log_error (_("bad URL encoding detected\n"));
537 /* A KSBA reader callback to read from an estream. */
539 my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
542 estream_t fp = cb_value;
545 return gpg_error (GPG_ERR_INV_VALUE);
547 if (!buffer && !count && !r_nread)
553 *r_nread = es_fread (buffer, 1, count, fp);
555 return -1; /* EOF or error. */
556 return 0; /* Success. */
560 /* Create a KSBA reader object and connect it to the estream FP. */
562 create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
565 ksba_reader_t reader;
568 err = ksba_reader_new (&reader);
570 err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
573 log_error (_("error initializing reader object: %s\n"),
575 ksba_reader_release (reader);
583 armor_data (char **r_string, const void *data, size_t datalen)
586 struct b64state b64state;
594 fp = es_fopenmem (0, "rw,samethread");
596 return gpg_error_from_syserror ();
598 if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
599 || (err=b64enc_write (&b64state, data, datalen))
600 || (err = b64enc_finish (&b64state)))
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);
612 err = gpg_error_from_syserror ();
617 buffer = xtrymalloc (length+1);
620 err = gpg_error_from_syserror ();
626 if (es_read (fp, buffer, length, &nread))
628 err = gpg_error_from_syserror ();
639 /* Copy all data from IN to OUT. */
641 copy_stream (estream_t in, estream_t out)
646 while (!es_read (in, buffer, sizeof buffer, &nread))
650 if (es_write (out, buffer, nread, NULL))
654 return gpg_error_from_syserror ();