]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add peer certificate alt subject name information to EAP events
authorJouni Malinen <j@w1.fi>
Wed, 14 Jan 2015 11:29:40 +0000 (13:29 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 14 Jan 2015 13:45:18 +0000 (15:45 +0200)
A new "CTRL-EVENT-EAP-PEER-ALT depth=<i> <alt name>" event is now used
to provide information about server certificate chain alternative
subject names for upper layers, e.g., to make it easier to configure
constraints on the server certificate. For example:
CTRL-EVENT-EAP-PEER-ALT depth=0 DNS:server.example.com

Currently, this includes DNS, EMAIL, and URI components from the
certificates. Similar information is priovided to D-Bus Certification
signal in the new altsubject argument which is a string array of these
items.

Signed-off-by: Jouni Malinen <j@w1.fi>
13 files changed:
doc/dbus.doxygen
src/common/wpa_ctrl.h
src/crypto/tls.h
src/crypto/tls_openssl.c
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new.h
wpa_supplicant/notify.c
wpa_supplicant/notify.h
wpa_supplicant/wpas_glue.c

index 2e5d9c7325496cb3ba8d64109947dc91b05e04d6..329e5d03bb66863bbec8b72158c7d236e638f362 100644 (file)
@@ -792,7 +792,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
        <h4>Arguments</h4>
        <dl>
          <dt>a{sv} : parameters</dt>
-         <dd>A dictionary with pairs of field names and their values. Possible dictionary keys are: "depth", "subject", "cert_hash", "cert".</dd>
+         <dd>A dictionary with pairs of field names and their values. Possible dictionary keys are: "depth", "subject", "altsubject", "cert_hash", "cert".</dd>
        </dl>
       </li>
 
index 82fad4b4426415ab82c3f907823275d26f4a8b3a..bc5dd7c35def7d2f36efded132ce3c8b29b6ee09 100644 (file)
@@ -42,6 +42,8 @@ extern "C" {
 #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
 /** EAP peer certificate from TLS */
 #define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
+/** EAP peer certificate alternative subject name component from TLS */
+#define WPA_EVENT_EAP_PEER_ALT "CTRL-EVENT-EAP-PEER-ALT "
 /** EAP TLS certificate chain validation error */
 #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
 /** EAP status */
index a4f954c7a88569f4d8d4d2401c49f6434258b74a..202ada8b2a2fa4d13795c6b78b92af6276ea4113 100644 (file)
@@ -44,6 +44,9 @@ enum tls_fail_reason {
        TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9
 };
 
+
+#define TLS_MAX_ALT_SUBJECT 10
+
 union tls_event_data {
        struct {
                int depth;
@@ -59,6 +62,8 @@ union tls_event_data {
                const struct wpabuf *cert;
                const u8 *hash;
                size_t hash_len;
+               const char *altsubject[TLS_MAX_ALT_SUBJECT];
+               int num_altsubject;
        } peer_cert;
 
        struct {
index 5433ebb2d97c4de4957c8ca06ce9f62a8b2f52ee..e52fd3976904f5be28a2bd974c9c9779a6978277 100644 (file)
@@ -1377,6 +1377,11 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
        struct wpabuf *cert = NULL;
        union tls_event_data ev;
        struct tls_context *context = conn->context;
+       char *altsubject[TLS_MAX_ALT_SUBJECT];
+       int alt, num_altsubject = 0;
+       GENERAL_NAME *gen;
+       void *ext;
+       stack_index_t i;
 #ifdef CONFIG_SHA256
        u8 hash[32];
 #endif /* CONFIG_SHA256 */
@@ -1403,8 +1408,52 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
 #endif /* CONFIG_SHA256 */
        ev.peer_cert.depth = depth;
        ev.peer_cert.subject = subject;
+
+       ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
+       for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
+               char *pos;
+
+               if (num_altsubject == TLS_MAX_ALT_SUBJECT)
+                       break;
+               gen = sk_GENERAL_NAME_value(ext, i);
+               if (gen->type != GEN_EMAIL &&
+                   gen->type != GEN_DNS &&
+                   gen->type != GEN_URI)
+                       continue;
+
+               pos = os_malloc(10 + gen->d.ia5->length + 1);
+               if (pos == NULL)
+                       break;
+               altsubject[num_altsubject++] = pos;
+
+               switch (gen->type) {
+               case GEN_EMAIL:
+                       os_memcpy(pos, "EMAIL:", 6);
+                       pos += 6;
+                       break;
+               case GEN_DNS:
+                       os_memcpy(pos, "DNS:", 4);
+                       pos += 4;
+                       break;
+               case GEN_URI:
+                       os_memcpy(pos, "URI:", 4);
+                       pos += 4;
+                       break;
+               }
+
+               os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
+               pos += gen->d.ia5->length;
+               *pos = '\0';
+       }
+
+       for (alt = 0; alt < num_altsubject; alt++)
+               ev.peer_cert.altsubject[alt] = altsubject[alt];
+       ev.peer_cert.num_altsubject = num_altsubject;
+
        context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
        wpabuf_free(cert);
+       for (alt = 0; alt < num_altsubject; alt++)
+               os_free(altsubject[alt]);
 }
 
 
index 31c1a29c679a95023383f766ae04bd63ccda4c87..62cd4a18c22efce8e05a58dd971478f5771bc487 100644 (file)
@@ -1858,6 +1858,8 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
                sm->eapol_cb->notify_cert(sm->eapol_ctx,
                                          data->peer_cert.depth,
                                          data->peer_cert.subject,
+                                         data->peer_cert.altsubject,
+                                         data->peer_cert.num_altsubject,
                                          hash_hex, data->peer_cert.cert);
                break;
        case TLS_ALERT:
index bc207e74fef76185ed5853a3f62ff4bd7979fff7..8c4a42f63766f1b8dffa9e9f2e082d5d2af204f1 100644 (file)
@@ -228,10 +228,13 @@ struct eapol_callbacks {
         * @ctx: eapol_ctx from eap_peer_sm_init() call
         * @depth: Depth in certificate chain (0 = server)
         * @subject: Subject of the peer certificate
+        * @altsubject: Select fields from AltSubject of the peer certificate
+        * @num_altsubject: Number of altsubject values
         * @cert_hash: SHA-256 hash of the certificate
         * @cert: Peer certificate
         */
        void (*notify_cert)(void *ctx, int depth, const char *subject,
+                           const char *altsubject[], int num_altsubject,
                            const char *cert_hash, const struct wpabuf *cert);
 
        /**
index 941a26945a6bec42935cc958e4567223d75f5e08..621318ee1b12487a3669e39afff9dc629faf789d 100644 (file)
@@ -1962,13 +1962,14 @@ static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
-                                const char *cert_hash,
+                                const char *altsubject[],
+                                int num_altsubject, const char *cert_hash,
                                 const struct wpabuf *cert)
 {
        struct eapol_sm *sm = ctx;
        if (sm->ctx->cert_cb)
-               sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
-                                cert_hash, cert);
+               sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, altsubject,
+                                num_altsubject, cert_hash, cert);
 }
 
 
index e089e88b573df0dfac9bc8066c12fa35f0fab67f..d8ae9d4ec409794f883c6fbc673df32372ad80f3 100644 (file)
@@ -248,10 +248,13 @@ struct eapol_ctx {
         * @ctx: Callback context (ctx)
         * @depth: Depth in certificate chain (0 = server)
         * @subject: Subject of the peer certificate
+        * @altsubject: Select fields from AltSubject of the peer certificate
+        * @num_altsubject: Number of altsubject values
         * @cert_hash: SHA-256 hash of the certificate
         * @cert: Peer certificate
         */
        void (*cert_cb)(void *ctx, int depth, const char *subject,
+                       const char *altsubject[], int num_altsubject,
                        const char *cert_hash, const struct wpabuf *cert);
 
        /**
index b30cc389fda1afd5add36bd9b6d7ba1ede503642..30ef03a7453b7a35a8e493af487f81002a1276f1 100644 (file)
@@ -748,6 +748,8 @@ nomem:
 
 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
                                    int depth, const char *subject,
+                                   const char *altsubject[],
+                                   int num_altsubject,
                                    const char *cert_hash,
                                    const struct wpabuf *cert)
 {
@@ -771,6 +773,9 @@ void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
        if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
            !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
            !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
+           (altsubject && num_altsubject &&
+            !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
+                                               altsubject, num_altsubject)) ||
            (cert_hash &&
             !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
                                          cert_hash)) ||
index 5f32bbf6b7ff3004da505a2ddece829bc1dd2ccf..d162d2b663df61b4cdfd8ee1aa13df3280f74088 100644 (file)
@@ -215,6 +215,8 @@ void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
                                     struct wps_event_fail *fail);
 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
                                    int depth, const char *subject,
+                                   const char *altsubject[],
+                                   int num_altsubject,
                                    const char *cert_hash,
                                    const struct wpabuf *cert);
 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
@@ -484,6 +486,8 @@ wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
 static inline void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
                                                  int depth,
                                                  const char *subject,
+                                                 const char *altsubject[],
+                                                 int num_altsubject,
                                                  const char *cert_hash,
                                                  const struct wpabuf *cert)
 {
index df1ce9e0ccb9a8a5e71738f24a1c4d6572ade467..bf1836a5c320c2ca57dcbc7f73e9b7af2a613a10 100644 (file)
@@ -690,13 +690,13 @@ void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s,
 
 
 void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
-                              const char *subject, const char *cert_hash,
+                              const char *subject, const char *altsubject[],
+                              int num_altsubject, const char *cert_hash,
                               const struct wpabuf *cert)
 {
        wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
                "depth=%d subject='%s'%s%s",
-               depth, subject,
-               cert_hash ? " hash=" : "",
+               depth, subject, cert_hash ? " hash=" : "",
                cert_hash ? cert_hash : "");
 
        if (cert) {
@@ -714,11 +714,20 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
                }
        }
 
+       if (altsubject) {
+               int i;
+
+               for (i = 0; i < num_altsubject; i++)
+                       wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_ALT
+                               "depth=%d %s", depth, altsubject[i]);
+       }
+
        /* notify the old DBus API */
        wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject,
                                                 cert_hash, cert);
        /* notify the new DBus API */
-       wpas_dbus_signal_certification(wpa_s, depth, subject, cert_hash, cert);
+       wpas_dbus_signal_certification(wpa_s, depth, subject, altsubject,
+                                      num_altsubject, cert_hash, cert);
 }
 
 
index 7feb53044624c0e23c66f85682bd63f854213d48..7fb1f58effec5911daeec41751d674bf1ca08926 100644 (file)
@@ -121,7 +121,8 @@ void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s,
                                struct wps_event_fail *fail);
 
 void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
-                              const char *subject, const char *cert_hash,
+                              const char *subject, const char *altsubject[],
+                              int num_altsubject, const char *cert_hash,
                               const struct wpabuf *cert);
 void wpas_notify_preq(struct wpa_supplicant *wpa_s,
                      const u8 *addr, const u8 *dst, const u8 *bssid,
index 8029ae53e64aab45f63f67596145a46386766ad6..83870433550eee388b032c159dfc84aa5f2e17c2 100644 (file)
@@ -860,12 +860,14 @@ static void wpa_supplicant_port_cb(void *ctx, int authorized)
 
 
 static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
+                                  const char *altsubject[], int num_altsubject,
                                   const char *cert_hash,
                                   const struct wpabuf *cert)
 {
        struct wpa_supplicant *wpa_s = ctx;
 
-       wpas_notify_certification(wpa_s, depth, subject, cert_hash, cert);
+       wpas_notify_certification(wpa_s, depth, subject, altsubject,
+                                 num_altsubject, cert_hash, cert);
 }