]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Refactored: Netscape certificate type verification
authorAdriaan de Jong <dejong@fox-it.com>
Thu, 30 Jun 2011 11:51:16 +0000 (13:51 +0200)
committerDavid Sommerseth <davids@redhat.com>
Fri, 21 Oct 2011 12:51:45 +0000 (14:51 +0200)
Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: James Yonan <james@openvpn.net>
Signed-off-by: David Sommerseth <davids@redhat.com>
init.c
options.c
options.h
ssl.c
ssl_verify.c
ssl_verify.h
ssl_verify_backend.h
ssl_verify_openssl.c

diff --git a/init.c b/init.c
index b809b960de0228a2063a2187c524dfaf011f75fe..6fc1a6bfbb08b313adb37476fa2babfa2933904b 100644 (file)
--- a/init.c
+++ b/init.c
@@ -2471,7 +2471,7 @@ do_option_warnings (struct context *c)
   if (o->tls_client
       && !o->tls_verify
       && !o->tls_remote
-      && !(o->ns_cert_type & NS_SSL_SERVER)
+      && !(o->ns_cert_type & NS_CERT_CHECK_SERVER)
       && !o->remote_cert_eku)
     msg (M_WARN, "WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.");
   if (o->tls_remote)
index a84e34dffd71b1b27709c48c5f232f73d93aacdd..f055185f78abe91c6bbf5e24d946896d0d61ba0f 100644 (file)
--- a/options.c
+++ b/options.c
@@ -6313,9 +6313,9 @@ add_option (struct options *options,
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
       if (streq (p[1], "server"))
-       options->ns_cert_type = NS_SSL_SERVER;
+       options->ns_cert_type = NS_CERT_CHECK_SERVER;
       else if (streq (p[1], "client"))
-       options->ns_cert_type = NS_SSL_CLIENT;
+       options->ns_cert_type = NS_CERT_CHECK_CLIENT;
       else
        {
          msg (msglevel, "--ns-cert-type must be 'client' or 'server'");
index c49cb521eaa34fd207a09b518c1ce3eb20321f62..8532402cd77a4c0ce91a10fba002d94957949d1f 100644 (file)
--- a/options.h
+++ b/options.h
@@ -539,7 +539,7 @@ struct options
   const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
 #endif
 
-  int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
+  int ns_cert_type; /* set to 0, NS_CERT_CHECK_SERVER, or NS_CERT_CHECK_CLIENT */
   unsigned remote_cert_ku[MAX_PARMS];
   const char *remote_cert_eku;
   uint8_t *verify_hash;
diff --git a/ssl.c b/ssl.c
index ac337e0828bd881534fd482bbf15cfcd2acf061c..e16f1a3dad15d27497184b5120dedbb1fa0f0946 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -387,26 +387,6 @@ bool verify_cert_ku (X509 *x509, const unsigned * const expected_ku, int expecte
 
 #endif /* OPENSSL_VERSION_NUMBER */
 
-/*
- * nsCertType checking
- */
-
-#define verify_nsCertType(x, usage) (((x)->ex_flags & EXFLAG_NSCERT) && ((x)->ex_nscert & (usage)))
-
-static const char *
-print_nsCertType (int type)
-{
-  switch (type)
-    {
-    case NS_SSL_SERVER:
-      return "SERVER";
-    case NS_SSL_CLIENT:
-      return "CLIENT";
-    default:
-      return "?";
-    }
-}
-
 static void
 string_mod_sslname (char *str, const unsigned int restrictive_flags, const unsigned int ssl_flags)
 {
@@ -532,21 +512,9 @@ verify_cert(struct tls_session *session, x509_cert_t *cert, int cert_depth)
   /* export current untrusted IP */
   setenv_untrusted (session);
 
-  /* verify certificate nsCertType */
-  if (opt->ns_cert_type && cert_depth == 0)
-    {
-      if (verify_nsCertType (cert, opt->ns_cert_type))
-       {
-         msg (D_HANDSHAKE, "VERIFY OK: nsCertType=%s",
-              print_nsCertType (opt->ns_cert_type));
-       }
-      else
-       {
-         msg (D_HANDSHAKE, "VERIFY nsCertType ERROR: %s, require nsCertType=%s",
-              subject, print_nsCertType (opt->ns_cert_type));
-         goto err;             /* Reject connection */
-       }
-    }
+  /* If this is the peer's own certificate, verify it */
+  if (cert_depth == 0 && verify_peer_cert(opt, cert, subject, common_name))
+    goto err;
 
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
 
index 5f743dadb00d5e49e150f32c8491c05c770a8dc8..4ca414f9303f5ca7212c9b8eded184babc6dcf9f 100644 (file)
@@ -306,6 +306,54 @@ x509_track_add (const struct x509_track **ll_head, const char *name, int msgleve
 
 #endif
 
+/*
+ * Returns the string associated with the given certificate type.
+ */
+static const char *
+print_nsCertType (int type)
+{
+  switch (type)
+    {
+    case NS_CERT_CHECK_SERVER:
+      return "SERVER";
+    case NS_CERT_CHECK_CLIENT:
+      return "CLIENT";
+    default:
+      return "?";
+    }
+}
+
+/*
+ * Verify the peer's certificate fields.
+ *
+ * @param opt the tls options to verify against
+ * @param peer_cert the peer's certificate
+ * @param subject the peer's extracted subject name
+ * @param subject the peer's extracted common name
+ */
+int
+verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert,
+    const char *subject, const char *common_name)
+{
+  /* verify certificate nsCertType */
+  if (opt->ns_cert_type != NS_CERT_CHECK_NONE)
+    {
+      if (verify_nsCertType (peer_cert, opt->ns_cert_type))
+       {
+         msg (D_HANDSHAKE, "VERIFY OK: nsCertType=%s",
+              print_nsCertType (opt->ns_cert_type));
+       }
+      else
+       {
+         msg (D_HANDSHAKE, "VERIFY nsCertType ERROR: %s, require nsCertType=%s",
+              subject, print_nsCertType (opt->ns_cert_type));
+         return 1;             /* Reject connection */
+       }
+    }
+
+  return 0;
+}
+
 /*
  * Export the subject, common_name, and raw certificate fields to the
  * environment for later verification by scripts and plugins.
index 03a794227edcfcad314746a6dab527c1e0f78e90..acb27f5b4284c49b536013231673df6bd36bd004 100644 (file)
@@ -214,6 +214,16 @@ void x509_track_add (const struct x509_track **ll_head, const char *name, int ms
 
 #endif
 
+/*
+ * Certificate checking for verify_nsCertType
+ */
+/** Do not perform Netscape certificate type verification */
+#define NS_CERT_CHECK_NONE (0)
+/** Do not perform Netscape certificate type verification */
+#define NS_CERT_CHECK_SERVER (1<<0)
+/** Do not perform Netscape certificate type verification */
+#define NS_CERT_CHECK_CLIENT (1<<1)
+
 /*
  * TODO: document
  */
@@ -233,6 +243,8 @@ tls_client_reason (struct tls_multi *multi)
 }
 
 /* TEMP */
+int verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert,
+    const char *subject, const char *common_name);
 void
 verify_cert_set_env(struct env_set *es, x509_cert_t *peer_cert, int cert_depth,
     const char *subject, const char *common_name,
index a32f0ea6af4a260ab6433af6c9298891118156dd..6f0e54e9a329e624e7bebe5c2d6d6f4adeeaf2e1 100644 (file)
@@ -141,4 +141,17 @@ void setenv_x509_track (const struct x509_track *xt, struct env_set *es,
  */
 void setenv_x509 (struct env_set *es, int cert_depth, x509_cert_t *cert);
 
+/*
+ * Check X.509 Netscape certificate type field, if available.
+ *
+ * @param cert         Certificate to check.
+ * @param usage                One of \c NS_CERT_CHECK_CLIENT, \c NS_CERT_CHECK_SERVER,
+ *                     or \c NS_CERT_CHECK_NONE.
+ *
+ * @return             \c true if NS_CERT_CHECK_NONE or if the certificate has
+ *                     the expected bit set. \c false if the certificate does
+ *                     not have NS cert type verification or the wrong bit set.
+ */
+bool verify_nsCertType(const x509_cert_t *cert, const int usage);
+
 #endif /* SSL_VERIFY_BACKEND_H_ */
index 417e5d73d49c248a3b6861eac5159c5e8f42ea2b..033af1dbf6e02828dde4a0949d84ad501976f03d 100644 (file)
@@ -377,3 +377,18 @@ setenv_x509 (struct env_set *es, int cert_depth, x509_cert_t *peer_cert)
       OPENSSL_free (buf);
     }
 }
+
+bool
+verify_nsCertType(const x509_cert_t *peer_cert, const int usage)
+{
+  if (usage == NS_CERT_CHECK_NONE)
+    return true;
+  if (usage == NS_CERT_CHECK_CLIENT)
+    return ((peer_cert->ex_flags & EXFLAG_NSCERT)
+       && (peer_cert->ex_nscert & NS_SSL_CLIENT));
+  if (usage == NS_CERT_CHECK_SERVER)
+    return ((peer_cert->ex_flags & EXFLAG_NSCERT)
+       && (peer_cert->ex_nscert & NS_SSL_SERVER));
+
+  return false;
+}