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
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 hexify_data (const unsigned char* data, size_t len, int with_prefix)
69 char *result = xmalloc (2*len + (with_prefix?2:0) + 1);
73 p = stpcpy (result, "0x");
77 for (i = 0; i < 2*len; i+=2 )
78 snprintf (p+i, 3, "%02X", *data++);
83 serial_hex (ksba_sexp_t serial )
85 unsigned char* p = serial;
93 p++; /* ignore initial '(' */
94 n = strtoul (p, (char**)&endp, 10);
100 certid = xmalloc( sizeof( char )*(2*n + 1 ) );
101 for (p++; n; n--, p++) {
102 sprintf ( certid+i , "%02X", *p);
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
114 const unsigned char *
115 serial_to_buffer (const ksba_sexp_t serial, size_t *length)
117 unsigned char *p = serial;
124 n = strtoul (p, &endp, 10);
134 /* Do an in-place percent unescaping of STRING. Returns STRING. Note
135 that this function does not do a '+'-to-space unescaping.*/
137 unpercent_string (char *string)
144 if (*s == '%' && s[1] && s[2])
157 /* Convert a canonical encoded S-expression in CANON into the GCRY
160 canon_sexp_to_gcry (const unsigned char *canon, gcry_sexp_t *r_sexp)
167 n = gcry_sexp_canon_len (canon, 0, NULL, NULL);
170 log_error (_("invalid canonical S-expression found\n"));
171 err = gpg_error (GPG_ERR_INV_SEXP);
173 else if ((err = gcry_sexp_sscan (&sexp, NULL, canon, n)))
174 log_error (_("converting S-expression failed: %s\n"), gcry_strerror (err));
181 /* Return an allocated buffer with the formatted fingerprint as one
184 get_fingerprint_hexstring (ksba_cert_t cert)
186 unsigned char digest[20];
192 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
194 log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
196 rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
199 log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
200 memset (digest, 0xff, 20); /* Use a dummy value. */
205 memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
210 for (i=0; i < 20; i++ )
211 sprintf (buf+strlen(buf), "%02X", digest[i]);
215 /* Return an allocated buffer with the formatted fingerprint as one
216 large hexnumber. This version inserts the usual colons. */
218 get_fingerprint_hexstring_colon (ksba_cert_t cert)
220 unsigned char digest[20];
226 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
228 log_fatal (_("gcry_md_open failed: %s\n"), gpg_strerror (rc));
230 rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
233 log_error (_("oops: ksba_cert_hash failed: %s\n"), gpg_strerror (rc));
234 memset (digest, 0xff, 20); /* Use a dummy value. */
239 memcpy (digest, gcry_md_read (md, GCRY_MD_SHA1), 20);
244 for (i=0; i < 20; i++ )
245 sprintf (buf+strlen(buf), "%02X:", digest[i]);
246 buf[strlen(buf)-1] = 0; /* Remove railing colon. */
251 /* Dump the serial number SERIALNO to the log stream. */
253 dump_serial (ksba_sexp_t serialno)
257 p = serial_hex (serialno);
258 log_printf ("%s", p?p:"?");
263 /* Dump STRING to the log file but choose the best readable
266 dump_string (const char *string)
270 log_printf ("[error]");
273 const unsigned char *s;
275 for (s=string; *s; s++)
277 if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
280 if (!*s && *string != '[')
281 log_printf ("%s", string);
285 log_printhex (NULL, string, strlen (string));
291 /* Dump an KSBA cert object to the log stream. Prefix the output with
292 TEXT. This is used for debugging. */
294 dump_cert (const char *text, ksba_cert_t cert)
300 log_debug ("BEGIN Certificate '%s':\n", text? text:"");
303 sexp = ksba_cert_get_serial (cert);
304 p = serial_hex (sexp);
305 log_debug (" serial: %s\n", p?p:"?");
309 ksba_cert_get_validity (cert, 0, t);
310 log_debug (" notBefore: ");
313 ksba_cert_get_validity (cert, 1, t);
314 log_debug (" notAfter: ");
318 p = ksba_cert_get_issuer (cert, 0);
319 log_debug (" issuer: ");
324 p = ksba_cert_get_subject (cert, 0);
325 log_debug (" subject: ");
330 log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert));
332 p = get_fingerprint_hexstring (cert);
333 log_debug (" SHA1 fingerprint: %s\n", p);
336 log_debug ("END Certificate\n");
341 /* Log the certificate's name in "#SN/ISSUERDN" format along with
344 cert_log_name (const char *text, ksba_cert_t cert)
346 log_info ("%s", text? text:"certificate" );
352 p = ksba_cert_get_issuer (cert, 0);
353 sn = ksba_cert_get_serial (cert);
362 log_printf (" [invalid]");
370 /* Log the certificate's subject DN along with TEXT. */
372 cert_log_subject (const char *text, ksba_cert_t cert)
374 log_info ("%s", text? text:"subject" );
379 p = ksba_cert_get_subject (cert, 0);
387 log_printf (" [invalid]");
393 /* Callback to print infos about the TLS certificates. */
395 cert_log_cb (http_session_t sess, gpg_error_t err,
396 const char *hostname, const void **certs, size_t *certlens)
404 return; /* No error - no need to log anything */
406 log_debug ("expected hostname: %s\n", hostname);
407 for (n=0; certs[n]; n++)
409 err = ksba_cert_new (&cert);
411 err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]);
413 log_error ("error parsing cert for logging: %s\n", gpg_strerror (err));
417 snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n);
418 dump_cert (textbuf, cert);
421 ksba_cert_release (cert);
427 * Remove all %xx escapes; this is done inplace.
428 * Returns: New length of the string.
431 remove_percent_escapes (unsigned char *string)
434 unsigned char *p, *s;
436 for (p = s = string; *s; s++)
440 if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
457 return -1; /* Bad URI. */
466 *p = 0; /* Always keep a string terminator. */
471 /* Return the host name and the port (0 if none was given) from the
472 URL. Return NULL on error or if host is not included in the
475 host_and_port_from_url (const char *url, int *port)
485 /* Find the scheme */
486 if ( !(s2 = strchr (s, ':')) || s2 == s )
487 return NULL; /* No scheme given. */
490 /* Find the hostname */
492 return NULL; /* Does not start with a slash. */
496 return NULL; /* No host name. */
499 buf = xtrystrdup (s);
502 log_error (_("malloc failed: %s\n"), strerror (errno));
505 if ((p = strchr (buf, '/')))
508 if ((p = strchr (p, ':')))
514 /* Remove quotes and make sure that no Nul has been encoded. */
515 if ((n = remove_percent_escapes (buf)) < 0
516 || n != strlen (buf) )
518 log_error (_("bad URL encoding detected\n"));
527 /* A KSBA reader callback to read from an estream. */
529 my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
532 estream_t fp = cb_value;
535 return gpg_error (GPG_ERR_INV_VALUE);
537 if (!buffer && !count && !r_nread)
543 *r_nread = es_fread (buffer, 1, count, fp);
545 return -1; /* EOF or error. */
546 return 0; /* Success. */
550 /* Create a KSBA reader object and connect it to the estream FP. */
552 create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
555 ksba_reader_t reader;
558 err = ksba_reader_new (&reader);
560 err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
563 log_error (_("error initializing reader object: %s\n"),
565 ksba_reader_release (reader);
573 armor_data (char **r_string, const void *data, size_t datalen)
576 struct b64state b64state;
584 fp = es_fopenmem (0, "rw,samethread");
586 return gpg_error_from_syserror ();
588 if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
589 || (err=b64enc_write (&b64state, data, datalen))
590 || (err = b64enc_finish (&b64state)))
596 /* FIXME: To avoid the extra buffer allocation estream should
597 provide a function to snatch the internal allocated memory from
598 such a memory stream. */
599 length = es_ftell (fp);
602 err = gpg_error_from_syserror ();
607 buffer = xtrymalloc (length+1);
610 err = gpg_error_from_syserror ();
616 if (es_read (fp, buffer, length, &nread))
618 err = gpg_error_from_syserror ();
629 /* Copy all data from IN to OUT. */
631 copy_stream (estream_t in, estream_t out)
636 while (!es_read (in, buffer, sizeof buffer, &nread))
640 if (es_write (out, buffer, nread, NULL))
644 return gpg_error_from_syserror ();