dirmngr: Pass Tor credentials to libdns.
[gnupg.git] / dirmngr / misc.c
index 3d33bee..ac3856e 100644 (file)
@@ -36,7 +36,7 @@
    buffer will be returned.  The caller should provide RESULT of at
    least strlen(STRING)/2 bytes.  There is no error detection, the
    parsing stops at the first non hex character.  With RESULT given as
-   NULL, the fucntion does only return the size of the buffer which
+   NULL, the function does only return the size of the buffer which
    would be needed.  */
 size_t
 unhexify (unsigned char *result, const char *string)
@@ -54,22 +54,28 @@ unhexify (unsigned char *result, const char *string)
 }
 
 
-char* 
+char*
 hashify_data( const char* data, size_t len )
 {
   unsigned char buf[20];
   gcry_md_hash_buffer (GCRY_MD_SHA1, buf, data, len);
-  return hexify_data( buf, 20 );
+  return hexify_data (buf, 20, 0);
 }
 
-char* 
-hexify_data( const unsigned char* data, size_t len )
+char*
+hexify_data (const unsigned char* data, size_t len, int with_prefix)
 {
   int i;
-  char* result = xmalloc( sizeof( char ) * (2*len+1));
+  char *result = xmalloc (2*len + (with_prefix?2:0) + 1);
+  char *p;
+
+  if (with_prefix)
+    p = stpcpy (result, "0x");
+  else
+    p = result;
 
-  fori = 0; i < 2*len; i+=2 )
-    sprintf( result+i, "%02X", *data++);
+  for (i = 0; i < 2*len; i+=2 )
+    snprintf (p+i, 3, "%02X", *data++);
   return result;
 }
 
@@ -125,7 +131,7 @@ serial_to_buffer (const ksba_sexp_t serial, size_t *length)
 }
 
 
-/* Do an in-place percent unescaping of STRING. Returns STRING. Noet
+/* Do an in-place percent unescaping of STRING. Returns STRING. Note
    that this function does not do a '+'-to-space unescaping.*/
 char *
 unpercent_string (char *string)
@@ -136,7 +142,7 @@ unpercent_string (char *string)
   while (*s)
     {
       if (*s == '%' && s[1] && s[2])
-        { 
+        {
           s++;
           *d++ = xtoi_2 ( s);
           s += 2;
@@ -144,7 +150,7 @@ unpercent_string (char *string)
       else
         *d++ = *s++;
     }
-  *d = 0; 
+  *d = 0;
   return string;
 }
 
@@ -159,7 +165,7 @@ canon_sexp_to_gcry (const unsigned char *canon, gcry_sexp_t *r_sexp)
 
   *r_sexp = NULL;
   n = gcry_sexp_canon_len (canon, 0, NULL, NULL);
-  if (!n) 
+  if (!n)
     {
       log_error (_("invalid canonical S-expression found\n"));
       err = gpg_error (GPG_ERR_INV_SEXP);
@@ -284,14 +290,14 @@ dump_string (const char *string)
 
 /* Dump an KSBA cert object to the log stream. Prefix the output with
    TEXT.  This is used for debugging. */
-void 
+void
 dump_cert (const char *text, ksba_cert_t cert)
 {
   ksba_sexp_t sexp;
   char *p;
   ksba_isotime_t t;
 
-  log_debug ("BEGIN Certificate `%s':\n", text? text:"");
+  log_debug ("BEGIN Certificate '%s':\n", text? text:"");
   if (cert)
     {
       sexp = ksba_cert_get_serial (cert);
@@ -314,7 +320,7 @@ dump_cert (const char *text, ksba_cert_t cert)
       dump_string (p);
       ksba_free (p);
       log_printf ("\n");
-    
+
       p = ksba_cert_get_subject (cert, 0);
       log_debug ("    subject: ");
       dump_string (p);
@@ -334,7 +340,7 @@ dump_cert (const char *text, ksba_cert_t cert)
 
 /* Log the certificate's name in "#SN/ISSUERDN" format along with
    TEXT. */
-void 
+void
 cert_log_name (const char *text, ksba_cert_t cert)
 {
   log_info ("%s", text? text:"certificate" );
@@ -362,7 +368,7 @@ cert_log_name (const char *text, ksba_cert_t cert)
 
 
 /* Log the certificate's subject DN along with TEXT. */
-void 
+void
 cert_log_subject (const char *text, ksba_cert_t cert)
 {
   log_info ("%s", text? text:"subject" );
@@ -384,6 +390,39 @@ cert_log_subject (const char *text, ksba_cert_t cert)
 }
 
 
+/* Callback to print infos about the TLS certificates.  */
+void
+cert_log_cb (http_session_t sess, gpg_error_t err,
+             const char *hostname, const void **certs, size_t *certlens)
+{
+  ksba_cert_t cert;
+  size_t n;
+
+  (void)sess;
+
+  if (!err)
+    return; /* No error - no need to log anything  */
+
+  log_debug ("expected hostname: %s\n", hostname);
+  for (n=0; certs[n]; n++)
+    {
+      err = ksba_cert_new (&cert);
+      if (!err)
+        err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]);
+      if (err)
+        log_error ("error parsing cert for logging: %s\n", gpg_strerror (err));
+      else
+        {
+          char textbuf[20];
+          snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n);
+          dump_cert (textbuf, cert);
+        }
+
+      ksba_cert_release (cert);
+    }
+}
+
+
 /****************
  * Remove all %xx escapes; this is done inplace.
  * Returns: New length of the string.
@@ -491,7 +530,7 @@ my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
                            size_t *r_nread)
 {
   estream_t fp = cb_value;
-  
+
   if (!fp)
     return gpg_error (GPG_ERR_INV_VALUE);
 
@@ -529,3 +568,78 @@ create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
   *r_reader = reader;
   return 0;
 }
+
+gpg_error_t
+armor_data (char **r_string, const void *data, size_t datalen)
+{
+  gpg_error_t err;
+  struct b64state b64state;
+  estream_t fp;
+  long length;
+  char *buffer;
+  size_t nread;
+
+  *r_string = NULL;
+
+  fp = es_fopenmem (0, "rw,samethread");
+  if (!fp)
+    return gpg_error_from_syserror ();
+
+  if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
+      || (err=b64enc_write (&b64state, data, datalen))
+      || (err = b64enc_finish (&b64state)))
+    {
+      es_fclose (fp);
+      return err;
+    }
+
+  /* FIXME: To avoid the extra buffer allocation estream should
+     provide a function to snatch the internal allocated memory from
+     such a memory stream.  */
+  length = es_ftell (fp);
+  if (length < 0)
+    {
+      err = gpg_error_from_syserror ();
+      es_fclose (fp);
+      return err;
+    }
+
+  buffer = xtrymalloc (length+1);
+  if (!buffer)
+    {
+      err = gpg_error_from_syserror ();
+      es_fclose (fp);
+      return err;
+    }
+
+  es_rewind (fp);
+  if (es_read (fp, buffer, length, &nread))
+    {
+      err = gpg_error_from_syserror ();
+      es_fclose (fp);
+      return err;
+    }
+  buffer[nread] = 0;
+  es_fclose (fp);
+
+  *r_string = buffer;
+  return 0;
+}
+
+/* Copy all data from IN to OUT.  */
+gpg_error_t
+copy_stream (estream_t in, estream_t out)
+{
+  char buffer[512];
+  size_t nread;
+
+  while (!es_read (in, buffer, sizeof buffer, &nread))
+    {
+      if (!nread)
+        return 0; /* EOF */
+      if (es_write (out, buffer, nread, NULL))
+        break;
+
+    }
+  return gpg_error_from_syserror ();
+}