ike: Reject certificates that are not compliant with RFC 4945
authorTobias Brunner <tobias@strongswan.org>
Wed, 25 Apr 2018 09:10:48 +0000 (11:10 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 22 May 2018 07:50:47 +0000 (09:50 +0200)
src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c

index 41be15a..9e5833e 100644 (file)
@@ -18,6 +18,7 @@
 #include <daemon.h>
 #include <sa/ikev1/keymat_v1.h>
 #include <encoding/payloads/hash_payload.h>
+#include <credentials/certificates/x509.h>
 
 typedef struct private_pubkey_v1_authenticator_t private_pubkey_v1_authenticator_t;
 
@@ -130,6 +131,29 @@ METHOD(authenticator_t, build, status_t,
        return status;
 }
 
+/**
+ * Check if the end-entity certificate, if any, is compliant with RFC 4945
+ */
+static bool is_compliant_cert(auth_cfg_t *auth)
+{
+       certificate_t *cert;
+       x509_t *x509;
+
+       cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+       if (!cert || cert->get_type(cert) != CERT_X509)
+       {
+               return TRUE;
+       }
+       x509 = (x509_t*)cert;
+       if (x509->get_flags(x509) & X509_IKE_COMPLIANT)
+       {
+               return TRUE;
+       }
+       DBG1(DBG_IKE, "rejecting certificate without digitalSignature or "
+                "nonRepudiation keyUsage flags");
+       return FALSE;
+}
+
 METHOD(authenticator_t, process, status_t,
        private_pubkey_v1_authenticator_t *this, message_t *message)
 {
@@ -176,7 +200,8 @@ METHOD(authenticator_t, process, status_t,
                                                                                                                id, auth, TRUE);
        while (enumerator->enumerate(enumerator, &public, &current_auth))
        {
-               if (public->verify(public, scheme, NULL, hash, sig))
+               if (public->verify(public, scheme, NULL, hash, sig) &&
+                       is_compliant_cert(current_auth))
                {
                        DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
                                 id, signature_scheme_names, scheme);
index c6c4829..652b837 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2017 Tobias Brunner
+ * Copyright (C) 2008-2018 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * HSR Hochschule fuer Technik Rapperswil
@@ -23,6 +23,7 @@
 #include <asn1/asn1.h>
 #include <asn1/oid.h>
 #include <collections/array.h>
+#include <credentials/certificates/x509.h>
 
 typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t;
 
@@ -414,6 +415,29 @@ METHOD(authenticator_t, build, status_t,
        return status;
 }
 
+/**
+ * Check if the end-entity certificate, if any, is compliant with RFC 4945
+ */
+static bool is_compliant_cert(auth_cfg_t *auth)
+{
+       certificate_t *cert;
+       x509_t *x509;
+
+       cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+       if (!cert || cert->get_type(cert) != CERT_X509)
+       {
+               return TRUE;
+       }
+       x509 = (x509_t*)cert;
+       if (x509->get_flags(x509) & X509_IKE_COMPLIANT)
+       {
+               return TRUE;
+       }
+       DBG1(DBG_IKE, "rejecting certificate without digitalSignature or "
+                "nonRepudiation keyUsage flags");
+       return FALSE;
+}
+
 METHOD(authenticator_t, process, status_t,
        private_pubkey_authenticator_t *this, message_t *message)
 {
@@ -479,7 +503,8 @@ METHOD(authenticator_t, process, status_t,
        while (enumerator->enumerate(enumerator, &public, &current_auth))
        {
                if (public->verify(public, params->scheme, params->params, octets,
-                                                  auth_data))
+                                                  auth_data) &&
+                       is_compliant_cert(current_auth))
                {
                        if (auth_method != AUTH_DS)
                        {