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)
301 log_debug ("BEGIN Certificate '%s':\n", text? text:"");
304 sexp = ksba_cert_get_serial (cert);
305 p = serial_hex (sexp);
306 log_debug (" serial: %s\n", p?p:"?");
310 ksba_cert_get_validity (cert, 0, t);
311 log_debug (" notBefore: ");
314 ksba_cert_get_validity (cert, 1, t);
315 log_debug (" notAfter: ");
319 p = ksba_cert_get_issuer (cert, 0);
320 log_debug (" issuer: ");
325 p = ksba_cert_get_subject (cert, 0);
326 log_debug (" subject: ");
330 for (idx=1; (p = ksba_cert_get_subject (cert, idx)); idx++)
332 log_debug (" aka: ");
338 log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert));
340 p = get_fingerprint_hexstring (cert);
341 log_debug (" SHA1 fingerprint: %s\n", p);
344 log_debug ("END Certificate\n");
349 /* Log the certificate's name in "#SN/ISSUERDN" format along with
352 cert_log_name (const char *text, ksba_cert_t cert)
354 log_info ("%s", text? text:"certificate" );
360 p = ksba_cert_get_issuer (cert, 0);
361 sn = ksba_cert_get_serial (cert);
370 log_printf (" [invalid]");
378 /* Log the certificate's subject DN along with TEXT. */
380 cert_log_subject (const char *text, ksba_cert_t cert)
382 log_info ("%s", text? text:"subject" );
387 p = ksba_cert_get_subject (cert, 0);
395 log_printf (" [invalid]");
401 /* Callback to print infos about the TLS certificates. */
403 cert_log_cb (http_session_t sess, gpg_error_t err,
404 const char *hostname, const void **certs, size_t *certlens)
412 return; /* No error - no need to log anything */
414 log_debug ("expected hostname: %s\n", hostname);
415 for (n=0; certs[n]; n++)
417 err = ksba_cert_new (&cert);
419 err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]);
421 log_error ("error parsing cert for logging: %s\n", gpg_strerror (err));
425 snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n);
426 dump_cert (textbuf, cert);
429 ksba_cert_release (cert);
435 * Remove all %xx escapes; this is done inplace.
436 * Returns: New length of the string.
439 remove_percent_escapes (unsigned char *string)
442 unsigned char *p, *s;
444 for (p = s = string; *s; s++)
448 if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
465 return -1; /* Bad URI. */
474 *p = 0; /* Always keep a string terminator. */
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
483 host_and_port_from_url (const char *url, int *port)
493 /* Find the scheme */
494 if ( !(s2 = strchr (s, ':')) || s2 == s )
495 return NULL; /* No scheme given. */
498 /* Find the hostname */
500 return NULL; /* Does not start with a slash. */
504 return NULL; /* No host name. */
507 buf = xtrystrdup (s);
510 log_error (_("malloc failed: %s\n"), strerror (errno));
513 if ((p = strchr (buf, '/')))
516 if ((p = strchr (p, ':')))
522 /* Remove quotes and make sure that no Nul has been encoded. */
523 if ((n = remove_percent_escapes (buf)) < 0
524 || n != strlen (buf) )
526 log_error (_("bad URL encoding detected\n"));
535 /* A KSBA reader callback to read from an estream. */
537 my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
540 estream_t fp = cb_value;
543 return gpg_error (GPG_ERR_INV_VALUE);
545 if (!buffer && !count && !r_nread)
551 *r_nread = es_fread (buffer, 1, count, fp);
553 return -1; /* EOF or error. */
554 return 0; /* Success. */
558 /* Create a KSBA reader object and connect it to the estream FP. */
560 create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
563 ksba_reader_t reader;
566 err = ksba_reader_new (&reader);
568 err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
571 log_error (_("error initializing reader object: %s\n"),
573 ksba_reader_release (reader);
581 armor_data (char **r_string, const void *data, size_t datalen)
584 struct b64state b64state;
592 fp = es_fopenmem (0, "rw,samethread");
594 return gpg_error_from_syserror ();
596 if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
597 || (err=b64enc_write (&b64state, data, datalen))
598 || (err = b64enc_finish (&b64state)))
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);
610 err = gpg_error_from_syserror ();
615 buffer = xtrymalloc (length+1);
618 err = gpg_error_from_syserror ();
624 if (es_read (fp, buffer, length, &nread))
626 err = gpg_error_from_syserror ();
637 /* Copy all data from IN to OUT. */
639 copy_stream (estream_t in, estream_t out)
644 while (!es_read (in, buffer, sizeof buffer, &nread))
648 if (es_write (out, buffer, nread, NULL))
652 return gpg_error_from_syserror ();