From ade74830b45466abb41b8e8dbc2f595d8bacb793 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@novell.com>
Date: Tue, 5 Jul 2011 12:22:32 +0300
Subject: [PATCH] Add dbus signal for information about server certification

In general, this patch attemps to extend commit
00468b4650998144f794762206c695c962c54734 with dbus support.

This can be used by dbus client to implement subject match text
entry with preset value probed from server. This preset value, if
user accepts it, is remembered and passed to subject_match config
for any future authentication.

Signed-off-by: Michael Chang <mchang@novell.com>
---
 src/eap_peer/eap.c             |    7 +++++
 src/eap_peer/eap.h             |   11 ++++++++
 src/eapol_supp/eapol_supp_sm.c |   12 ++++++++-
 src/eapol_supp/eapol_supp_sm.h |   11 ++++++++
 wpa_supplicant/dbus/dbus_new.c |   54 ++++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new.h |   12 +++++++++
 wpa_supplicant/dbus/dbus_old.c |   53 +++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_old.h |   12 +++++++++
 wpa_supplicant/notify.c        |   12 +++++++++
 wpa_supplicant/notify.h        |    4 +++
 wpa_supplicant/wpas_glue.c     |   12 +++++++++
 11 files changed, 199 insertions(+), 1 deletions(-)

Index: wpa_supplicant-0.6.9/src/eap_peer/eap.c
===================================================================
--- wpa_supplicant-0.6.9.orig/src/eap_peer/eap.c
+++ wpa_supplicant-0.6.9/src/eap_peer/eap.c
@@ -1194,6 +1194,13 @@ static void eap_peer_sm_tls_event(void *
 					 wpabuf_head(data->peer_cert.cert),
 					 wpabuf_len(data->peer_cert.cert));
 		}
+		if (sm->eapol_cb->notify_cert) {
+			sm->eapol_cb->notify_cert(sm->eapol_ctx,
+						  data->peer_cert.depth,
+						  data->peer_cert.subject,
+						  hash_hex,
+						  data->peer_cert.cert);
+		}
 		break;
 	}
 
Index: wpa_supplicant-0.6.9/src/eap_peer/eap.h
===================================================================
--- wpa_supplicant-0.6.9.orig/src/eap_peer/eap.h
+++ wpa_supplicant-0.6.9/src/eap_peer/eap.h
@@ -221,6 +221,17 @@ struct eapol_callbacks {
 	 */
 	void (*eap_param_needed)(void *ctx, const char *field,
 				 const char *txt);
+
+	/**
+	 * notify_cert - Notification of a peer certificate
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @depth: Depth in certificate chain (0 = server)
+	 * @subject: Subject of the peer certificate
+	 * @cert_hash: SHA-256 hash of the certificate
+	 * @cert: Peer certificate
+	 */
+	void (*notify_cert)(void *ctx, int depth, const char *subject,
+			    const char *cert_hash, const struct wpabuf *cert);
 };
 
 /**
Index: wpa_supplicant-0.6.9/src/eapol_supp/eapol_supp_sm.c
===================================================================
--- wpa_supplicant-0.6.9.orig/src/eapol_supp/eapol_supp_sm.c
+++ wpa_supplicant-0.6.9/src/eapol_supp/eapol_supp_sm.c
@@ -1786,6 +1786,15 @@ static void eapol_sm_eap_param_needed(vo
 #define eapol_sm_eap_param_needed NULL
 #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 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);
+}
 
 static struct eapol_callbacks eapol_cb =
 {
@@ -1798,7 +1807,8 @@ static struct eapol_callbacks eapol_cb =
 	eapol_sm_set_config_blob,
 	eapol_sm_get_config_blob,
 	eapol_sm_notify_pending,
-	eapol_sm_eap_param_needed
+	eapol_sm_eap_param_needed,
+	eapol_sm_notify_cert
 };
 
 
Index: wpa_supplicant-0.6.9/src/eapol_supp/eapol_supp_sm.h
===================================================================
--- wpa_supplicant-0.6.9.orig/src/eapol_supp/eapol_supp_sm.h
+++ wpa_supplicant-0.6.9/src/eapol_supp/eapol_supp_sm.h
@@ -224,6 +224,17 @@ struct eapol_ctx {
 	 */
 	void (*eap_param_needed)(void *ctx, const char *field,
 				 const char *txt);
+
+	/**
+	 * cert_cb - Notification of a peer certificate
+	 * @ctx: Callback context (ctx)
+	 * @depth: Depth in certificate chain (0 = server)
+	 * @subject: Subject of the peer certificate
+	 * @cert_hash: SHA-256 hash of the certificate
+	 * @cert: Peer certificate
+	 */
+	void (*cert_cb)(void *ctx, int depth, const char *subject,
+			const char *cert_hash, const struct wpabuf *cert);
 };
 
 
Index: wpa_supplicant-0.6.9/wpa_supplicant/wpas_glue.c
===================================================================
--- wpa_supplicant-0.6.9.orig/wpa_supplicant/wpas_glue.c
+++ wpa_supplicant-0.6.9/wpa_supplicant/wpas_glue.c
@@ -103,6 +103,15 @@ static int wpa_ether_send(struct wpa_sup
 
 	return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
 }
+
+static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
+				   const char *cert_hash,
+				   const struct wpabuf *cert)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject, cert_hash, cert);
+}
 #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
 
 
@@ -562,6 +571,7 @@ int wpa_supplicant_init_eapol(struct wpa
 	ctx->wps = wpa_s->wps;
 	ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
 	ctx->cb = wpa_supplicant_eapol_cb;
+	ctx->cert_cb = wpa_supplicant_cert_cb;
 	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);
 	if (wpa_s->eapol == NULL) {
Index: wpa_supplicant-0.6.9/wpa_supplicant/ctrl_iface_dbus.c
===================================================================
--- wpa_supplicant-0.6.9.orig/wpa_supplicant/ctrl_iface_dbus.c
+++ wpa_supplicant-0.6.9/wpa_supplicant/ctrl_iface_dbus.c
@@ -797,6 +797,58 @@ out:
 }
 #endif /* CONFIG_WPS */
 
+void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
+					      int depth, const char *subject,
+					      const char *cert_hash,
+					      const struct wpabuf *cert)
+{
+	struct ctrl_iface_dbus_priv *iface;
+	DBusMessage *_signal = NULL;
+	const char *hash;
+	const char *cert_hex;
+	int cert_hex_len;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s->global == NULL)
+		return;
+	iface = wpa_s->global->dbus_ctrl_iface;
+	if (iface == NULL)
+		return;
+
+	_signal = dbus_message_new_signal(wpa_s->dbus_path,
+					  WPAS_DBUS_IFACE_INTERFACE,
+					  "Certification");
+	if (_signal == NULL) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_certification: "
+		           "Could not create dbus signal; likely out of "
+		           "memory");
+		return;
+	}
+
+	hash = cert_hash ? cert_hash : "";
+	cert_hex = cert ? wpabuf_head(cert) : "";
+	cert_hex_len = cert ? wpabuf_len(cert) : 0;
+
+	if (!dbus_message_append_args(_signal,
+				      DBUS_TYPE_INT32,&depth,
+				      DBUS_TYPE_STRING, &subject,
+	                              DBUS_TYPE_STRING, &hash,
+	                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+				      &cert_hex, cert_hex_len,
+	                              DBUS_TYPE_INVALID)) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_certification: "
+		           "Not enough memory to construct signal");
+		goto out;
+	}
+
+	dbus_connection_send(iface->con, _signal, NULL);
+
+out:
+	dbus_message_unref(_signal);
+
+}
 
 /**
  * integrate_with_eloop - Register our mainloop integration with dbus
Index: wpa_supplicant-0.6.9/wpa_supplicant/ctrl_iface_dbus.h
===================================================================
--- wpa_supplicant-0.6.9.orig/wpa_supplicant/ctrl_iface_dbus.h
+++ wpa_supplicant-0.6.9/wpa_supplicant/ctrl_iface_dbus.h
@@ -89,6 +89,11 @@ void wpa_supplicant_dbus_notify_state_ch
 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
 					 const struct wps_credential *cred);
 
+void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
+					      int depth, const char *subject,
+					      const char *cert_hash,
+					      const struct wpabuf *cert);
+
 char * wpas_dbus_decompose_object_path(const char *path, char **network,
                                        char **bssid);
 
@@ -139,6 +144,14 @@ wpa_supplicant_dbus_notify_wps_cred(stru
 {
 }
 
+static inline void
+void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
+					      int depth, const char *subject,
+					      const char *cert_hash,
+					      const struct wpabuf *cert)
+{
+}
+
 static inline int
 wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
 {
