[git] NTBTLS - branch, master, updated. 379c449b6fa539f188fc1d7666ceae17c40a645a

by Werner Koch cvs at cvs.gnupg.org
Mon Feb 20 17:24:03 CET 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Not Too Bad TLS".

The branch, master has been updated
       via  379c449b6fa539f188fc1d7666ceae17c40a645a (commit)
       via  204627b9fd5d67a87a8bee9e2ac3345c06f4c0d8 (commit)
      from  f9552b3c9f2c9705b2715f8a90479bfc600c61d6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 379c449b6fa539f188fc1d7666ceae17c40a645a
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Feb 20 17:21:10 2017 +0100

    Implement hostname checking.
    
    * src/x509.c (struct dn_array_s): New.
    (release_dn_array): New.
    (parse_dn_part): New.
    (parse_dn): New.
    (check_hostname): New.
    (_ntbtls_x509_check_hostname): New.
    * src/protocol.c (_ntbtls_read_certificate): Add hostname check.
    --
    
    The functions parse_dn and parse_dn_part are taken from current
    gnupg/sm/certdump.c.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/ntbtls-int.h b/src/ntbtls-int.h
index 882c90d..7a17323 100644
--- a/src/ntbtls-int.h
+++ b/src/ntbtls-int.h
@@ -383,6 +383,9 @@ gpg_error_t _ntbtls_x509_get_pk (x509_cert_t cert, int idx, gcry_sexp_t *r_pk);
 
 int _ntbtls_x509_can_do (x509_privkey_t privkey, pk_algo_t pkalgo);
 
+gpg_error_t _ntbtls_x509_check_hostname (x509_cert_t cert,
+                                         const char *hostname);
+
 
 /*-- dhm.c --*/
 gpg_error_t _ntbtls_dhm_new (dhm_context_t *r_dhm);
diff --git a/src/protocol.c b/src/protocol.c
index dbbc259..4f3ee4a 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -1995,46 +1995,43 @@ _ntbtls_read_certificate (ntbtls_t tls)
   if (tls->authmode != TLS_VERIFY_NONE)
     {
       /*
-       * Main check: verify certificate
+       * Verify hostname
        */
-      if (!tls->verify_cb)
+      if (tls->hostname)
         {
-          debug_msg (1, "verify callback not set");
-          return gpg_error (GPG_ERR_NOT_INITIALIZED);
-        }
-      err = tls->verify_cb (tls->verify_cb_value, tls, 0);
-      if (err)
-        {
-          debug_ret (1, "error from the verify callback", err);
+          if (!tls->session_negotiate)
+            err = gpg_error (GPG_ERR_MISSING_CERT);
+          else
+            err = _ntbtls_x509_check_hostname
+              (tls->session_negotiate->peer_chain, tls->hostname);
+          if (err)
+            {
+              debug_ret (1, "x509_check_hostname", err);
+            }
         }
+      else
+        err = 0;
 
       /*
-       * Secondary checks: always done, but change 'ret' only if it was 0
+       * Verify certificate.  We don't do this if the hostname check
+       * already failed.
        */
-      //FIXME:
-      /* { */
-      /*   pk_context *pk = &tls->session_negotiate->peer_chain->pk; */
-
-      /*   /\* If certificate uses an EC key, make sure the curve is OK *\/ */
-      /*   if (pk_can_do (pk, POLARSSL_PK_ECKEY) && */
-      /*       !ssl_curve_is_acceptable (tls, pk_ec (*pk)->grp.id)) */
-      /*     { */
-      /*       debug_msg (1, "bad certificate (EC key curve)"); */
-      /*       if (ret == 0) */
-      /*         ret = gpg_error (GPG_ERR_BAD_HS_CERT); */
-      /*     } */
-      /* } */
-      /* */
-      /* if (ssl_check_cert_usage (tls->session_negotiate->peer_chain, */
-      /*                           suite, tls->is_client)) */
-      /*   { */
-      /*     debug_msg (1, "bad certificate (usage extensions)"); */
-      /*     if (!err) */
-      /*       err = gpg_error (GPG_ERR_BAD_HS_CERT); */
-      /*   } */
+      if (!err)
+        {
+          if (!tls->verify_cb)
+            {
+              debug_msg (1, "verify callback not set");
+              return gpg_error (GPG_ERR_NOT_INITIALIZED);
+            }
+          err = tls->verify_cb (tls->verify_cb_value, tls, 0);
+          if (err)
+            {
+              debug_ret (1, "error from the verify callback", err);
+            }
 
-      if (tls->authmode != TLS_VERIFY_REQUIRED)
-        err = 0;
+          if (tls->authmode != TLS_VERIFY_REQUIRED)
+            err = 0;
+        }
     }
 
   return err;
diff --git a/src/x509.c b/src/x509.c
index 6ad7655..651624a 100644
--- a/src/x509.c
+++ b/src/x509.c
@@ -1,5 +1,5 @@
 /* x509.c - X.509 functions
- * Copyright (C) 2014 g10 Code GmbH
+ * Copyright (C) 2001-2010, 2014-2015  g10 Code GmbH
  *
  * This file is part of NTBTLS
  *
@@ -43,6 +43,224 @@ struct x509_privkey_s
 };
 
 
+/* Object to hold a parsed DN. */
+struct dn_array_s
+{
+  char *key;
+  char *value;
+  int   multivalued;
+  int   done;
+};
+
+
+static void
+release_dn_array (struct dn_array_s *dnparts)
+{
+  int i;
+
+  if (!dnparts)
+    return;
+  for (i=0; dnparts[i].key; i++)
+    {
+      free (dnparts[i].key);
+      free (dnparts[i].value);
+    }
+  free (dnparts);
+}
+
+
+/* Helper for parse_dn.  */
+static const unsigned char *
+parse_dn_part (struct dn_array_s *array, const unsigned char *string)
+{
+  static struct {
+    const char *label;
+    const char *oid;
+  } label_map[] = {
+    /* Warning: When adding new labels, make sure that the buffer
+       below we be allocated large enough. */
+    {"EMail",        "1.2.840.113549.1.9.1" },
+    {"T",            "2.5.4.12" },
+    {"GN",           "2.5.4.42" },
+    {"SN",           "2.5.4.4" },
+    {"NameDistinguisher", "0.2.262.1.10.7.20"},
+    {"ADDR",         "2.5.4.16" },
+    {"BC",           "2.5.4.15" },
+    {"D",            "2.5.4.13" },
+    {"PostalCode",   "2.5.4.17" },
+    {"Pseudo",       "2.5.4.65" },
+    {"SerialNumber", "2.5.4.5" },
+    {NULL, NULL}
+  };
+  const unsigned char *s, *s1;
+  size_t n;
+  char *p;
+  int i;
+
+  /* Parse attributeType */
+  for (s = string+1; *s && *s != '='; s++)
+    ;
+  if (!*s)
+    return NULL; /* error */
+  n = s - string;
+  if (!n)
+    return NULL; /* empty key */
+
+  /* We need to allocate a few bytes more due to the possible mapping
+     from the shorter OID to the longer label. */
+  array->key = p = malloc (n+10);
+  if (!array->key)
+    return NULL;
+  memcpy (p, string, n);
+  p[n] = 0;
+  _ntbtls_trim_trailing_spaces (p);
+
+  if (digitp (p))
+    {
+      for (i=0; label_map[i].label; i++ )
+        if ( !strcmp (p, label_map[i].oid) )
+          {
+            strcpy (p, label_map[i].label);
+            break;
+          }
+    }
+  string = s + 1;
+
+  if (*string == '#')
+    { /* hexstring */
+      string++;
+      for (s=string; hexdigitp (s); s++)
+        s++;
+      n = s - string;
+      if (!n || (n & 1))
+        return NULL; /* Empty or odd number of digits. */
+      n /= 2;
+      array->value = p = malloc (n+1);
+      if (!p)
+        return NULL;
+      for (s1=string; n; s1 += 2, n--, p++)
+        {
+          *(unsigned char *)p = xtoi_2 (s1);
+          if (!*p)
+            *p = 0x01; /* Better print a wrong value than truncating
+                          the string. */
+        }
+      *p = 0;
+   }
+  else
+    { /* regular v3 quoted string */
+      for (n=0, s=string; *s; s++)
+        {
+          if (*s == '\\')
+            { /* pair */
+              s++;
+              if (*s == ',' || *s == '=' || *s == '+'
+                  || *s == '<' || *s == '>' || *s == '#' || *s == ';'
+                  || *s == '\\' || *s == '\"' || *s == ' ')
+                n++;
+              else if (hexdigitp (s) && hexdigitp (s+1))
+                {
+                  s++;
+                  n++;
+                }
+              else
+                return NULL; /* invalid escape sequence */
+            }
+          else if (*s == '\"')
+            return NULL; /* invalid encoding */
+          else if (*s == ',' || *s == '=' || *s == '+'
+                   || *s == '<' || *s == '>' || *s == ';' )
+            break;
+          else
+            n++;
+        }
+
+      array->value = p = malloc (n+1);
+      if (!p)
+        return NULL;
+      for (s=string; n; s++, n--)
+        {
+          if (*s == '\\')
+            {
+              s++;
+              if (hexdigitp (s))
+                {
+                  *(unsigned char *)p++ = xtoi_2 (s);
+                  s++;
+                }
+              else
+                *p++ = *s;
+            }
+          else
+            *p++ = *s;
+        }
+      *p = 0;
+    }
+  return s;
+}
+
+
+/* Parse a DN and return an array-ized one.  This is not a validating
+ * parser and it does not support any old-stylish syntax; KSBA is
+ * expected to return only rfc2253 compatible strings.  Returns NULL
+ * on error.  */
+static struct dn_array_s *
+parse_dn (const unsigned char *string)
+{
+  struct dn_array_s *array;
+  size_t arrayidx, arraysize;
+  int i;
+
+  arraysize = 7; /* C,ST,L,O,OU,CN,email */
+  arrayidx = 0;
+  array = malloc ((arraysize+1) * sizeof *array);
+  if (!array)
+    return NULL;
+  while (*string)
+    {
+      while (*string == ' ')
+        string++;
+      if (!*string)
+        break; /* ready */
+      if (arrayidx >= arraysize)
+        {
+          struct dn_array_s *a2;
+
+          arraysize += 5;
+          a2 = realloc (array, (arraysize+1) * sizeof *array);
+          if (!a2)
+            goto failure;
+          array = a2;
+        }
+      array[arrayidx].key = NULL;
+      array[arrayidx].value = NULL;
+      string = parse_dn_part (array+arrayidx, string);
+      if (!string)
+        goto failure;
+      while (*string == ' ')
+        string++;
+      array[arrayidx].multivalued = (*string == '+');
+      array[arrayidx].done = 0;
+      arrayidx++;
+      if (*string && *string != ',' && *string != ';' && *string != '+')
+        goto failure; /* invalid delimiter */
+      if (*string)
+        string++;
+    }
+  array[arrayidx].key = NULL;
+  array[arrayidx].value = NULL;
+  return array;
+
+ failure:
+  for (i=0; i < arrayidx; i++)
+    {
+      free (array[i].key);
+      free (array[i].value);
+    }
+  free (array);
+  return NULL;
+}
+
 
 /* Create a new X.509 certificate chain object and store it at R_CERT.
    Returns an error code and stores NULL at R_CERT on error. */
@@ -165,7 +383,6 @@ x509_log_time (const char *text, ksba_isotime_t t)
 void
 _ntbtls_x509_log_cert (const char *text, x509_cert_t chain_arg, int full)
 {
-  gpg_error_t err;
   x509_cert_t chain;
   ksba_cert_t cert;
   ksba_sexp_t sexp;
@@ -244,8 +461,6 @@ _ntbtls_x509_get_peer_cert (ntbtls_t tls, int idx)
 {
   x509_cert_t cert;
 
-  debug_crt (1, "peer certs A", tls->session_negotiate->peer_chain);
-
   if (!tls || !tls->session_negotiate || idx < 0)
     return NULL;
   for (cert = tls->session_negotiate->peer_chain;
@@ -256,7 +471,6 @@ _ntbtls_x509_get_peer_cert (ntbtls_t tls, int idx)
     return NULL;
 
   ksba_cert_ref (cert->crt);
-  debug_crt (1, "peer certs B", tls->session_negotiate->peer_chain);
   return cert->crt;
 }
 
@@ -315,3 +529,124 @@ _ntbtls_x509_can_do (x509_privkey_t privkey, pk_algo_t pk_alg)
   /* FIXME: Check that PRIVKEY matches PKALGO.  */
   return 1;
 }
+
+
+/* Check that CERT_NAME matches the hostname WANT_NAME.  Returns 0 if
+ * they match, GPG_ERR_WRONG_NAME if they don't match, or an other
+ * error code for a bad CERT_NAME.  */
+static gpg_err_code_t
+check_hostname (const char *cert_name, const char *want_name)
+{
+  const char *s;
+
+  _ntbtls_debug_msg (2, "comparing hostname '%s' to '%s'\n",
+                     cert_name, want_name);
+
+  /* Check that CERT_NAME looks like a valid hostname.  We check the
+   * LDH rule, no empty label, and no leading or trailing hyphen.  We
+   * do not check digit-only names.  */
+  if (!*cert_name || *cert_name == '-')
+    return GPG_ERR_INV_NAME;
+
+  for (s = cert_name; *s; s++)
+    {
+      if (!(alnump (s) || strchr ("-.", *s)))
+        return GPG_ERR_INV_NAME;
+      else if (*s == '.' && s[1] == '.')
+        return GPG_ERR_INV_NAME;
+    }
+
+  if (s[-1] == '-')
+    return GPG_ERR_INV_NAME;
+
+  if (strstr (cert_name, ".."))
+    return GPG_ERR_INV_NAME;
+
+  /* Now do the actual strcmp.  */
+  if (_ntbtls_ascii_strcasecmp (cert_name, want_name))
+    return GPG_ERR_WRONG_NAME;
+
+  return 0; /* Match.  */
+}
+
+
+/* Check that  HOSTNAME is in CERT.  */
+gpg_error_t
+_ntbtls_x509_check_hostname (x509_cert_t cert, const char *hostname)
+{
+  gpg_err_code_t ec;
+  gpg_error_t err;
+  int idx;
+  struct dn_array_s *dnparts = NULL;
+  char *dn = NULL;
+  char *endp, *name;
+  char *p;
+  int n, cn_count;
+
+  if (!cert || !cert->crt)
+    return gpg_error (GPG_ERR_MISSING_CERT);
+
+  /* First we look at the subjectAltNames.  */
+  for (idx=1; (dn = ksba_cert_get_subject (cert->crt, idx)); idx++)
+    {
+      if (!strncmp (dn, "(8:dns-name", 11))
+        {
+          n = strtol (dn + 11, &endp, 10);
+          if (n < 1 || *endp != ':' || endp[1+n] != ')')
+            {
+              err = gpg_error (GPG_ERR_INV_SEXP);
+              goto leave;
+            }
+          name = endp+1;
+          /* Make sure that thare is no embedded nul and trun it into
+           * a string.  */
+          for (p = name; n; p++, n--)
+            if (!*p)
+              *p = '\x01'; /* Replace by invalid DNS character.  */
+          *p = 0;  /* Replace the final ')'.  */
+          ec = check_hostname (name, hostname);
+          if (ec != GPG_ERR_WRONG_NAME)
+            {
+              err = gpg_error (ec);
+              goto leave;
+            }
+        }
+      ksba_free (dn);
+    }
+
+  /* Then we look at the CN of the subject.  */
+  dn = ksba_cert_get_subject (cert->crt, 0);
+  if (!dn)
+    {
+      err = gpg_error (GPG_ERR_BAD_CERT);
+      goto leave;
+    }
+
+  dnparts = parse_dn (dn);
+  if (!dnparts)
+    {
+      err = gpg_error (GPG_ERR_BAD_CERT);  /* Or out of mem.  */
+      goto leave;
+    }
+
+  for (idx=cn_count=0; dnparts[idx].key; idx++)
+    if (!strcmp (dnparts[idx].key, "CN")
+        && ++cn_count > 1)
+      {
+        err = gpg_error (GPG_ERR_BAD_CERT);
+        goto leave;
+      }
+
+  for (idx=0; dnparts[idx].key; idx++)
+    if (!strcmp (dnparts[idx].key, "CN"))
+      break;
+  if (dnparts[idx].key)
+    err = gpg_error (check_hostname (dnparts[idx].value, hostname));
+  else
+    err = gpg_error (GPG_ERR_WRONG_NAME);
+
+ leave:
+  release_dn_array (dnparts);
+  ksba_free (dn);
+  return err;
+}

commit 204627b9fd5d67a87a8bee9e2ac3345c06f4c0d8
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Feb 20 17:16:43 2017 +0100

    New function ntbtls_set_log_handler
    
    * src/ntbtls.h.in (ntbtls_log_handler_t): New type.
    (ntbtls_set_log_handler): New.
    * src/visibility.c (ntbtls_set_log_handler): New.
    * src/visibility.h (ntbtls_set_log_handler): Mark visible.
    * src/libntbtls.def: Add ntbtls_set_log_handler.
    * src/libntbtls.vers: Add ntbtls_set_log_handler.
    * src/debug.c (log_handler, log_handler_value): New vars.
    (_ntbtls_set_log_handler): New.
    (_ntbtls_set_debug): Do not re-set the prefix.
    (_ntbtls_debug_msg): Divert to a log handler.
    
    * src/util.c (_ntbtls_trim_trailing_spaces): New.
    (ascii_toupper): New.
    (_ntbtls_ascii_strcasecmp): New.
    * src/util.h (spacep, digitp, alphap, alnump, hexdigitp): New macros.
    (ascii_isspace): New macro.
    (atoi_1, atoi_2, atoi_4, xtoi_1, xtoi_2, xtoi_4): New macros.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/debug.c b/src/debug.c
index 7772eda..d2b7c59 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -27,14 +27,24 @@
 static int debug_level;
 static const char *debug_prefix;
 static estream_t debug_stream;
+static ntbtls_log_handler_t log_handler;
+static void *log_handler_value;
 
 
+/* Set the Debug level up to which debug messages are shown. 0
+ * disables debug messages except for those which will always be
+ * shown.  PREFIX is prefix to prefix all output; the default is
+ * "ntbtls".  STREAM is the output stream; the default is es_stderr.
+ * Changing STREAM and PREFIX is not thread-safe and their values are
+ * ignored if a log handler has been set.  */
 void
 _ntbtls_set_debug (int level, const char *prefix, gpgrt_stream_t stream)
 {
   static char *debug_prefix_buffer;
 
-  debug_prefix = "ntbtls";
+  if (!debug_prefix)
+    debug_prefix = "ntbtls";
+
   if (prefix)
     {
       free (debug_prefix_buffer);
@@ -49,9 +59,18 @@ _ntbtls_set_debug (int level, const char *prefix, gpgrt_stream_t stream)
 }
 
 
+/* Set a dedicated log handler.  See the description of
+ * ntbtls_log_handler_t for details.  This is not thread-safe.  */
+void
+_ntbtls_set_log_handler (ntbtls_log_handler_t cb, void *cb_value)
+{
+  log_handler = cb;
+  log_handler_value = cb_value;
+}
+
 
-/* FIXME: For now we print to stderr.  Note that a LEVEL of -1 will
- * always print even when debugging has not been enabled.  */
+/* Note that a LEVEL of -1 will always print even when debugging has
+ * not been enabled.  */
 void
 _ntbtls_debug_msg (int level, const char *format, ...)
 {
@@ -62,20 +81,27 @@ _ntbtls_debug_msg (int level, const char *format, ...)
   if (level != -1 && (!debug_level || level > debug_level))
     return;
 
-  if ((no_lf = (*format == '\b')))
-    format++;
-
-  saved_errno = errno;
   va_start (arg_ptr, format);
-  gpgrt_fputs ("ntbtls: ", es_stderr);
-  gpgrt_vfprintf (es_stderr, format, arg_ptr);
-  if (no_lf)
-    gpgrt_fflush (es_stderr); /* To sync with stderr.  */
-  else if (*format && format[strlen(format)-1] != '\n')
-    gpgrt_fputc ('\n', es_stderr);
+  saved_errno = errno;
+  if (log_handler)
+    {
+      log_handler (log_handler_value, level, format, arg_ptr);
+    }
+  else
+    {
+      if ((no_lf = (*format == '\b')))
+        format++;
+
+      gpgrt_fputs ("ntbtls: ", es_stderr);
+      gpgrt_vfprintf (es_stderr, format, arg_ptr);
+      if (no_lf)
+        gpgrt_fflush (es_stderr); /* To sync with stderr.  */
+      else if (*format && format[strlen(format)-1] != '\n')
+        gpgrt_fputc ('\n', es_stderr);
+    }
+
   va_end (arg_ptr);
   gpg_err_set_errno (saved_errno);
-
 }
 
 
diff --git a/src/libntbtls.def b/src/libntbtls.def
index c0b9eb8..637de78 100644
--- a/src/libntbtls.def
+++ b/src/libntbtls.def
@@ -39,4 +39,5 @@ EXPORTS
     ntbtls_x509_append_cert               @12
 
     ntbtls_x509_get_peer_cert             @13
+    ntbtls_set_log_handler                @14
 ; END
diff --git a/src/libntbtls.vers b/src/libntbtls.vers
index 8909c19..47f3c69 100644
--- a/src/libntbtls.vers
+++ b/src/libntbtls.vers
@@ -23,6 +23,7 @@ NTBTLS_1.0 {
   global:
     ntbtls_check_version;
     ntbtls_set_debug;
+    ntbtls_set_log_handler;
 
     ntbtls_new;
     ntbtls_release;
diff --git a/src/ntbtls-int.h b/src/ntbtls-int.h
index a059115..882c90d 100644
--- a/src/ntbtls-int.h
+++ b/src/ntbtls-int.h
@@ -280,6 +280,8 @@ tls_own_cert (ntbtls_t tls)
 
 /*-- util.c --*/
 const char *_ntbtls_check_version (const char *req_version);
+char *_ntbtls_trim_trailing_spaces (char *string);
+int _ntbtls_ascii_strcasecmp (const char *a, const char *b);
 
 /*-- protocol.c --*/
 const char *_ntbtls_state2str (tls_state_t state);
diff --git a/src/ntbtls.h.in b/src/ntbtls.h.in
index ce713e4..b887b0a 100644
--- a/src/ntbtls.h.in
+++ b/src/ntbtls.h.in
@@ -78,6 +78,20 @@ typedef gpg_error_t (*ntbtls_verify_cb_t) (void *opaque,
                                            unsigned int verify_flags);
 
 
+/*
+ * The type of an optional log handler.
+ *
+ * OPAQUE is the value supplied to the set function.  LEVEL is the
+ * debug level for that message; it might be -1 for always log or any
+ * value less than the limit set with ntbtls_set_debug.  FMT is the
+ * format string.  Unless FMT starts with a '\b' the log function is
+ * expected to append a missing final linefeed.
+ */
+typedef void (*ntbtls_log_handler_t)(void *opaque,
+                                     int level,
+                                     const char *fmt,
+                                     va_list argv);
+
 /* Check that the library fulfills the version requirement.  */
 const char *ntbtls_check_version (const char *req_version);
 
@@ -128,11 +142,15 @@ ksba_cert_t ntbtls_x509_get_peer_cert (ntbtls_t tls, int idx);
  */
 
 /* Enable debugging at LEVEL (> 0) using an optional PREFIX (default:
-   "ntbtls") and an optional debug stream STREAM (default: es_stderr).
-   This function is not thread-safe and shall thus be called only once
-   before any extra threads have been started.  */
+ * "ntbtls") and an optional debug stream STREAM (default: es_stderr).
+ * This function is not thread-safe and shall thus be called only once
+ * before any extra threads have been started.  */
 void ntbtls_set_debug (int level, const char *prefix, gpgrt_stream_t stream);
 
+/* Set a dedicated log handler.  See the description of
+ * ntbtls_log_handler_t for details.  This is not thread-safe.  */
+void ntbtls_set_log_handler (ntbtls_log_handler_t cb, void *cb_value);
+
 
 #if 0 /* (Keep Emacsens' auto-indent happy.) */
 {
diff --git a/src/util.c b/src/util.c
index d36ae79..80d5903 100644
--- a/src/util.c
+++ b/src/util.c
@@ -34,7 +34,7 @@ compat_identification (void)
   static const char blurb[] =
     "\n\n"
     "This is NTBTLS " PACKAGE_VERSION " - Not Too Bad TLS\n"
-    "Copyright (C) 2014 g10 Code GmbH\n"
+    "Copyright (C) 2014-2017 g10 Code GmbH\n"
     "Copyright (C) 2006-2014 Brainspark B.V.\n"
     "\n"
     "(" BUILD_REVISION " " BUILD_TIMESTAMP ")\n"
@@ -138,3 +138,51 @@ _ntbtls_check_version (const char *req_version)
 
   return NULL; /* Not sufficent.  */
 }
+
+
+/*
+ * Remove trailing white spaces from STRING.  Returns STRING.
+ */
+char *
+_ntbtls_trim_trailing_spaces (char *string)
+{
+  char *p, *mark;
+
+  for (mark = NULL, p = string; *p; p++ )
+    {
+      if (isspace (*(unsigned char*)p))
+        {
+          if (!mark)
+            mark = p;
+	}
+      else
+        mark = NULL;
+    }
+  if (mark)
+    *mark = 0;
+
+  return string;
+}
+
+
+static inline int
+ascii_toupper (int c)
+{
+  if (c >= 'a' && c <= 'z')
+    c &= ~0x20;
+  return c;
+}
+
+int
+_ntbtls_ascii_strcasecmp (const char *a, const char *b)
+{
+  if (a == b)
+    return 0;
+
+  for (; *a && *b; a++, b++)
+    {
+      if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b))
+        break;
+    }
+  return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
+}
diff --git a/src/util.h b/src/util.h
index 9e49111..98a8392 100644
--- a/src/util.h
+++ b/src/util.h
@@ -30,9 +30,31 @@
 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
 #define DIMof(type,member)   DIM(((type *)0)->member)
 
+/* Macros to replace ctype macros so o avoid locale problems.  */
+#define spacep(p)   (*(p) == ' ' || *(p) == '\t')
+#define digitp(p)   (*(p) >= '0' && *(p) <= '9')
+#define alphap(p)   ((*(p) >= 'A' && *(p) <= 'Z')       \
+                     || (*(p) >= 'a' && *(p) <= 'z'))
+#define alnump(p)   (alphap (p) || digitp (p))
+#define hexdigitp(a) (digitp (a)                     \
+                      || (*(a) >= 'A' && *(a) <= 'F')  \
+                      || (*(a) >= 'a' && *(a) <= 'f'))
+  /* Note this isn't identical to a C locale isspace() without \f and
+     \v, but works for the purposes used here. */
+#define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
+
+/* The atoi macros assume that the buffer has only valid digits. */
+#define atoi_1(p)   (*(p) - '0' )
+#define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
+#define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
+#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
+                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+#define xtoi_4(p)   ((xtoi_2(p) * 256) + xtoi_2((p)+2))
+
 
 /* Return the size of a OID string without the nul.  */
-//FIXME: Do we use it?
+/* FIXME: Do we use it? */
 #define OID_SIZE(x) (sizeof(x) - 1)
 
 
@@ -94,6 +116,7 @@ buf32_to_u32 (const void *buffer)
 
 /*-- debug.c --*/
 void _ntbtls_set_debug (int level, const char *prefix, gpgrt_stream_t stream);
+void _ntbtls_set_log_handler (ntbtls_log_handler_t cb, void *cb_value);
 
 void _ntbtls_debug_msg (int level, const char *format,
                         ...) GPGRT_ATTR_PRINTF(2,0);
@@ -121,6 +144,9 @@ void _ntbtls_debug_crt (int level, const char *text, x509_cert_t chain);
 # define GPG_ERR_REQUEST_TOO_SHORT 223
 # define GPG_ERR_REQUEST_TOO_LONG  224
 #endif
+#if GPG_ERROR_VERSION_NUMBER < 0x011b00 /* 1.27 */
+# define GPG_ERR_WRONG_NAME  313
+#endif
 
 
 
diff --git a/src/visibility.c b/src/visibility.c
index 37a67ae..73f2452 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -38,6 +38,13 @@ ntbtls_set_debug (int level, const char *prefix, gpgrt_stream_t stream)
 }
 
 
+void
+ntbtls_set_log_handler (ntbtls_log_handler_t cb, void *cb_value)
+{
+  _ntbtls_set_log_handler (cb, cb_value);
+}
+
+
 gpg_error_t
 ntbtls_new (ntbtls_t *r_tls, unsigned int flags)
 {
diff --git a/src/visibility.h b/src/visibility.h
index b3f973d..7f6db83 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -43,6 +43,7 @@
 
 MARK_VISIBLE (ntbtls_check_version)
 MARK_VISIBLE (ntbtls_set_debug)
+MARK_VISIBLE (ntbtls_set_log_handler)
 MARK_VISIBLE (ntbtls_new)
 MARK_VISIBLE (ntbtls_release)
 MARK_VISIBLE (ntbtls_set_transport)
@@ -67,6 +68,7 @@ MARK_VISIBLE (ntbtls_x509_get_peer_cert)
 
 #define ntbtls_check_version         _ntbtls_USE_THE_UNDERSCORED_FUNCTION
 #define ntbtls_set_debug             _ntbtls_USE_THE_UNDERSCORED_FUNCTION
+#define ntbtls_set_log_handler       _ntbtls_USE_THE_UNDERSCORED_FUNCTION
 #define ntbtls_new                   _ntbtls_USE_THE_UNDERSCORED_FUNCTION
 #define ntbtls_released              _ntbtls_USE_THE_UNDERSCORED_FUNCTION
 #define ntbtls_set_transport         _ntbtls_USE_THE_UNDERSCORED_FUNCTION

-----------------------------------------------------------------------

Summary of changes:
 src/debug.c        |  54 ++++++---
 src/libntbtls.def  |   1 +
 src/libntbtls.vers |   1 +
 src/ntbtls-int.h   |   5 +
 src/ntbtls.h.in    |  24 +++-
 src/protocol.c     |  63 +++++-----
 src/util.c         |  50 +++++++-
 src/util.h         |  28 ++++-
 src/visibility.c   |   7 ++
 src/visibility.h   |   2 +
 src/x509.c         | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 11 files changed, 523 insertions(+), 57 deletions(-)


hooks/post-receive
-- 
Not Too Bad TLS
http://git.gnupg.org




More information about the Gnupg-commits mailing list