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)
{
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'");
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;
#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)
{
/* 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
#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.
#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
*/
}
/* 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,
*/
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_ */
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;
+}