<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>
#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 */
TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9
};
+
+#define TLS_MAX_ALT_SUBJECT 10
+
union tls_event_data {
struct {
int depth;
const struct wpabuf *cert;
const u8 *hash;
size_t hash_len;
+ const char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int num_altsubject;
} peer_cert;
struct {
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 */
#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]);
}
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:
* @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);
/**
#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);
}
* @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);
/**
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)
{
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)) ||
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,
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)
{
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) {
}
}
+ 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);
}
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,
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);
}