[PATCH 20/25] Replace 'auth_cred' operation with a signal



Remove the 'auth_cred' operation in VncConnection. Introduce a
new 'vnc-auth-credential' signal
---
 src/vncconnection.c       |  231 ++++++++++++++++++++++++++------------------
 src/vncconnection.h       |   22 ++---
 src/vncdisplay.c          |  127 ++-----------------------
 src/vncimageframebuffer.c |    2 +
 4 files changed, 155 insertions(+), 227 deletions(-)

diff --git a/src/vncconnection.c b/src/vncconnection.c
index 587c170..3def590 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -52,6 +52,10 @@
 #include <sasl/sasl.h>
 #endif
 
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
 #include <zlib.h>
 
 #include <gdk/gdkkeysyms.h>
@@ -198,13 +202,14 @@ enum {
 
 	VNC_AUTH_FAILURE,
 	VNC_AUTH_UNSUPPORTED,
+	VNC_AUTH_CREDENTIAL,
 
 	VNC_LAST_SIGNAL,
 };
 
 static guint signals[VNC_LAST_SIGNAL] = { 0, 0, 0, 0,
 					  0, 0, 0, 0,
-					  0, };
+					  0, 0, };
 
 #define nibhi(a) (((a) >> 4) & 0x0F)
 #define niblo(a) ((a) & 0x0F)
@@ -390,6 +395,7 @@ struct signal_data
 		VncPixelFormat *pixelFormat;
 		const char *authReason;
 		unsigned int authUnsupported;
+		GValueArray *authCred;
 	} params;
 };
 
@@ -464,6 +470,13 @@ static gboolean do_vnc_connection_emit_main_context(gpointer opaque)
 			      data->params.authUnsupported);
 		break;
 
+	case VNC_AUTH_CREDENTIAL:
+		g_signal_emit(G_OBJECT(data->conn),
+			      signals[data->signum],
+			      0,
+			      data->params.authCred);
+		break;
+
 	}
 
 	coroutine_yieldto(data->caller, NULL);
@@ -2576,27 +2589,6 @@ gboolean vnc_connection_server_message(VncConnection *conn)
 	return !vnc_connection_has_error(conn);
 }
 
-gboolean vnc_connection_wants_credential_password(VncConnection *conn)
-{
-	VncConnectionPrivate *priv = conn->priv;
-
-	return priv->want_cred_password;
-}
-
-gboolean vnc_connection_wants_credential_username(VncConnection *conn)
-{
-	VncConnectionPrivate *priv = conn->priv;
-
-	return priv->want_cred_username;
-}
-
-gboolean vnc_connection_wants_credential_x509(VncConnection *conn)
-{
-	VncConnectionPrivate *priv = conn->priv;
-
-	return priv->want_cred_x509;
-}
-
 static gboolean vnc_connection_has_credentials(gpointer data)
 {
 	VncConnection *conn = data;
@@ -2604,9 +2596,9 @@ static gboolean vnc_connection_has_credentials(gpointer data)
 
 	if (priv->has_error)
 		return TRUE;
-	if (vnc_connection_wants_credential_username(conn) && !priv->cred_username)
+	if (priv->want_cred_username && !priv->cred_username)
 		return FALSE;
-	if (vnc_connection_wants_credential_password(conn) && !priv->cred_password)
+	if (priv->want_cred_password && !priv->cred_password)
 		return FALSE;
 	/*
 	 * For x509 we require a minimum of the CA cert.
@@ -2616,7 +2608,7 @@ static gboolean vnc_connection_has_credentials(gpointer data)
 	 * alone though - we'll merely find out when TLS
 	 * negotiation takes place.
 	 */
-	if (vnc_connection_wants_credential_x509(conn) && !priv->cred_x509_cacert)
+	if (priv->want_cred_x509 && !priv->cred_x509_cacert)
 		return FALSE;
 	return TRUE;
 }
@@ -2625,14 +2617,41 @@ static gboolean vnc_connection_gather_credentials(VncConnection *conn)
 {
 	VncConnectionPrivate *priv = conn->priv;
 
+	if (priv->has_error)
+		return FALSE;
+
 	if (!vnc_connection_has_credentials(conn)) {
-		GVNC_DEBUG("Requesting missing credentials");
-		if (priv->has_error || !priv->ops.auth_cred) {
-			priv->has_error = TRUE;
-			return FALSE;
+		GValueArray *authCred;
+		GValue username, password, clientname;
+		struct signal_data sigdata;
+
+		memset(&username, 0, sizeof(username));
+		memset(&password, 0, sizeof(password));
+		memset(&clientname, 0, sizeof(clientname));
+
+		authCred = g_value_array_new(0);
+		if (priv->want_cred_username) {
+			g_value_init(&username, VNC_TYPE_CONNECTION_CREDENTIAL);
+			g_value_set_enum(&username, VNC_CONNECTION_CREDENTIAL_USERNAME);
+			authCred = g_value_array_append(authCred, &username);
 		}
-		if (!priv->ops.auth_cred(priv->ops_data))
-			priv->has_error = TRUE;
+		if (priv->want_cred_password) {
+			g_value_init(&password, VNC_TYPE_CONNECTION_CREDENTIAL);
+			g_value_set_enum(&password, VNC_CONNECTION_CREDENTIAL_PASSWORD);
+			authCred = g_value_array_append(authCred, &password);
+		}
+		if (priv->want_cred_x509) {
+			g_value_init(&clientname, VNC_TYPE_CONNECTION_CREDENTIAL);
+			g_value_set_enum(&clientname, VNC_CONNECTION_CREDENTIAL_CLIENTNAME);
+			authCred = g_value_array_append(authCred, &clientname);
+		}
+
+		sigdata.params.authCred = authCred;
+		GVNC_DEBUG("Requesting missing credentials");
+		vnc_connection_emit_main_context(conn, VNC_AUTH_CREDENTIAL, &sigdata);
+
+		g_value_array_free(authCred);
+
 		if (priv->has_error)
 			return FALSE;
 		GVNC_DEBUG("Waiting for missing credentials");
@@ -3817,6 +3836,17 @@ static void vnc_connection_class_init(VncConnectionClass *klass)
 			      1,
 			      G_TYPE_UINT);
 
+	signals[VNC_AUTH_CREDENTIAL] =
+		g_signal_new ("vnc-auth-credential",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_credential),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_VALUE_ARRAY);
+
 
 	g_type_class_add_private(klass, sizeof(VncConnectionPrivate));
 }
@@ -4242,88 +4272,99 @@ gboolean vnc_connection_set_auth_subtype(VncConnection *conn, unsigned int type)
 	return !vnc_connection_has_error(conn);
 }
 
-gboolean vnc_connection_set_credential_password(VncConnection *conn, const char *password)
-{
-	VncConnectionPrivate *priv = conn->priv;
 
-        GVNC_DEBUG("Set password credential %s", password);
-        if (priv->cred_password)
-                g_free(priv->cred_password);
-        if (!(priv->cred_password = g_strdup(password))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
+static int vnc_connection_best_path(char **buf,
+				    const char *basedir,
+				    const char *basefile,
+				    char **dirs,
+				    unsigned int ndirs)
+{
+	unsigned int i;
+	gchar *tmp;
+	for (i = 0 ; i < ndirs ; i++) {
+		struct stat sb;
+		tmp = g_strdup_printf("%s/%s/%s", dirs[i], basedir, basefile);
+		if (stat(tmp, &sb) == 0) {
+			*buf = tmp;
+			return 0;
+		}
+		g_free(tmp);
+	}
+	return -1;
 }
 
-gboolean vnc_connection_set_credential_username(VncConnection *conn, const char *username)
-{
-	VncConnectionPrivate *priv = conn->priv;
 
-        GVNC_DEBUG("Set username credential %s", username);
-        if (priv->cred_username)
-                g_free(priv->cred_username);
-        if (!(priv->cred_username = g_strdup(username))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
-}
 
-gboolean vnc_connection_set_credential_x509_cacert(VncConnection *conn, const char *file)
+static gboolean vnc_connection_set_credential_x509(VncConnection *conn,
+						   const gchar *name)
 {
 	VncConnectionPrivate *priv = conn->priv;
+	char sysdir[PATH_MAX];
+#ifndef WIN32
+	char userdir[PATH_MAX];
+	struct passwd *pw;
+	char *dirs[] = { sysdir, userdir };
+#else
+	char *dirs[] = { sysdir };
+#endif
 
-        GVNC_DEBUG("Set x509 cacert %s", file);
-        if (priv->cred_x509_cacert)
-                g_free(priv->cred_x509_cacert);
-        if (!(priv->cred_x509_cacert = g_strdup(file))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
-}
+	strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
+	sysdir[PATH_MAX-1] = '\0';
 
-gboolean vnc_connection_set_credential_x509_cacrl(VncConnection *conn, const char *file)
-{
-	VncConnectionPrivate *priv = conn->priv;
+#ifndef WIN32
+	if (!(pw = getpwuid(getuid())))
+		return FALSE;
 
-        GVNC_DEBUG("Set x509 cacrl %s", file);
-        if (priv->cred_x509_cacrl)
-                g_free(priv->cred_x509_cacrl);
-        if (!(priv->cred_x509_cacrl = g_strdup(file))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
-}
+	snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
+	userdir[PATH_MAX-1] = '\0';
+#endif
 
-gboolean vnc_connection_set_credential_x509_key(VncConnection *conn, const char *file)
-{
-	VncConnectionPrivate *priv = conn->priv;
+	if (vnc_connection_best_path(&priv->cred_x509_cacert, "CA", "cacert.pem",
+				     dirs, sizeof(dirs)/sizeof(dirs[0])) < 0)
+		return FALSE;
 
-        GVNC_DEBUG("Set x509 key %s", file);
-        if (priv->cred_x509_key)
-                g_free(priv->cred_x509_key);
-        if (!(priv->cred_x509_key = g_strdup(file))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
+	/* Don't mind failures of CRL */
+	vnc_connection_best_path(&priv->cred_x509_cacrl, "CA", "cacrl.pem",
+				 dirs, sizeof(dirs)/sizeof(dirs[0]));
+
+	/* Set client key & cert if we have them. Server will reject auth
+	 * if it decides it requires them*/
+	vnc_connection_best_path(&priv->cred_x509_key, name, "private/clientkey.pem",
+				 dirs, sizeof(dirs)/sizeof(dirs[0]));
+	vnc_connection_best_path(&priv->cred_x509_cert, name, "clientcert.pem",
+				 dirs, sizeof(dirs)/sizeof(dirs[0]));
+
+	return TRUE;
 }
 
-gboolean vnc_connection_set_credential_x509_cert(VncConnection *conn, const char *file)
+gboolean vnc_connection_set_credential(VncConnection *conn, int type, const gchar *data)
 {
 	VncConnectionPrivate *priv = conn->priv;
 
-        GVNC_DEBUG("Set x509 cert %s", file);
-        if (priv->cred_x509_cert)
+        GVNC_DEBUG("Set credential %d %s", type, data);
+	switch (type) {
+	case VNC_CONNECTION_CREDENTIAL_PASSWORD:
+		g_free(priv->cred_password);
+		priv->cred_password = g_strdup(data);
+		break;
+
+	case VNC_CONNECTION_CREDENTIAL_USERNAME:
+		g_free(priv->cred_username);
+		priv->cred_username = g_strdup(data);
+		break;
+
+	case VNC_CONNECTION_CREDENTIAL_CLIENTNAME:
+                g_free(priv->cred_x509_cacert);
+		g_free(priv->cred_x509_cacrl);
+		g_free(priv->cred_x509_key);
                 g_free(priv->cred_x509_cert);
-        if (!(priv->cred_x509_cert = g_strdup(file))) {
-                priv->has_error = TRUE;
-                return FALSE;
-        }
-        return TRUE;
+		return vnc_connection_set_credential_x509(conn, data);
+
+	default:
+		priv->has_error = TRUE;
+	}
+
+	return !vnc_connection_has_error(conn);
 }
 
 
diff --git a/src/vncconnection.h b/src/vncconnection.h
index bd8532f..866d461 100644
--- a/src/vncconnection.h
+++ b/src/vncconnection.h
@@ -61,13 +61,13 @@ struct _VncConnectionClass
 	void (*vnc_pixel_format_changed)(VncConnection *conn, VncPixelFormat *format);
 	void (*vnc_auth_failure)(VncConnection *conn, const char *reason);
 	void (*vnc_auth_unsupported)(VncConnection *conn, unsigned int authType);
+	void (*vnc_auth_credential)(VncConnection *conn, GValueArray *creds);
 };
 
 typedef void (rgb24_render_func)(void *, int, int, int, int, guint8 *, int);
 
 struct vnc_connection_ops
 {
-	gboolean (*auth_cred)(void *);
 	gboolean (*auth_type)(void *, unsigned int, unsigned int *);
 	gboolean (*auth_subtype)(void *, unsigned int, unsigned int *);
 	gboolean (*set_color_map_entry)(void *, int, int, int, int);
@@ -135,6 +135,14 @@ typedef enum {
 	GVNC_AUTH_VENCRYPT_TLSSASL = 264,
 } VncConnectionAuthVencrypt;
 
+typedef enum
+{
+	VNC_CONNECTION_CREDENTIAL_PASSWORD,
+	VNC_CONNECTION_CREDENTIAL_USERNAME,
+	VNC_CONNECTION_CREDENTIAL_CLIENTNAME,
+} VncConnectionCredential;
+
+
 GType vnc_connection_get_type(void) G_GNUC_CONST;
 
 VncConnection *vnc_connection_new(const struct vnc_connection_ops *ops, gpointer ops_data);
@@ -148,17 +156,7 @@ gboolean vnc_connection_is_open(VncConnection *conn);
 
 gboolean vnc_connection_set_auth_type(VncConnection *conn, unsigned int type);
 gboolean vnc_connection_set_auth_subtype(VncConnection *conn, unsigned int type);
-
-gboolean vnc_connection_set_credential_password(VncConnection *conn, const char *password);
-gboolean vnc_connection_set_credential_username(VncConnection *conn, const char *username);
-gboolean vnc_connection_set_credential_x509_cacert(VncConnection *conn, const char *file);
-gboolean vnc_connection_set_credential_x509_cacrl(VncConnection *conn, const char *file);
-gboolean vnc_connection_set_credential_x509_key(VncConnection *conn, const char *file);
-gboolean vnc_connection_set_credential_x509_cert(VncConnection *conn, const char *file);
-
-gboolean vnc_connection_wants_credential_password(VncConnection *conn);
-gboolean vnc_connection_wants_credential_username(VncConnection *conn);
-gboolean vnc_connection_wants_credential_x509(VncConnection *conn);
+gboolean vnc_connection_set_credential(VncConnection *conn, int type, const gchar *data);
 
 gboolean vnc_connection_initialize(VncConnection *conn, gboolean shared_flag);
 gboolean vnc_connection_is_initialized(VncConnection *conn);
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 0d46119..eeaf524 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -40,9 +40,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
 
 #ifdef HAVE_WINSOCK2_H
 #include <winsock2.h>
@@ -882,12 +879,6 @@ static gboolean emit_signal_auth_cred(gpointer opaque)
 	struct signal_data *s = opaque;
 
 	switch (s->signum) {
-	case VNC_AUTH_CREDENTIAL:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_AUTH_CREDENTIAL],
-			      0,
-			      s->cred_list);
-		break;
 	case VNC_CONNECTED:
 	case VNC_INITIALIZED:
 	case VNC_DISCONNECTED:
@@ -1092,40 +1083,13 @@ static void on_pointer_mode_changed(VncConnection *conn G_GNUC_UNUSED,
 		do_pointer_show(obj);
 }
 
-static gboolean on_auth_cred(void *opaque)
+static void on_auth_cred(VncConnection *conn G_GNUC_UNUSED,
+			 GValueArray *creds,
+			 gpointer opaque)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-	GValueArray *cred_list;
-	GValue username, password, clientname;
-	struct signal_data s;
-
-	memset(&username, 0, sizeof(username));
-	memset(&password, 0, sizeof(password));
-	memset(&clientname, 0, sizeof(clientname));
-
-	cred_list = g_value_array_new(0);
-	if (vnc_connection_wants_credential_username(obj->priv->conn)) {
-		g_value_init(&username, VNC_TYPE_DISPLAY_CREDENTIAL);
-		g_value_set_enum(&username, VNC_DISPLAY_CREDENTIAL_USERNAME);
-		cred_list = g_value_array_append(cred_list, &username);
-	}
-	if (vnc_connection_wants_credential_password(obj->priv->conn)) {
-		g_value_init(&password, VNC_TYPE_DISPLAY_CREDENTIAL);
-		g_value_set_enum(&password, VNC_DISPLAY_CREDENTIAL_PASSWORD);
-		cred_list = g_value_array_append(cred_list, &password);
-	}
-	if (vnc_connection_wants_credential_x509(obj->priv->conn)) {
-		g_value_init(&clientname, VNC_TYPE_DISPLAY_CREDENTIAL);
-		g_value_set_enum(&clientname, VNC_DISPLAY_CREDENTIAL_CLIENTNAME);
-		cred_list = g_value_array_append(cred_list, &clientname);
-	}
-
-	s.cred_list = cred_list;
-	emit_signal_delayed(obj, VNC_AUTH_CREDENTIAL, &s);
-
-	g_value_array_free(cred_list);
 
-	return TRUE;
+	g_signal_emit(G_OBJECT(obj), signals[VNC_AUTH_CREDENTIAL], 0, creds);
 }
 
 static gboolean on_auth_type(void *opaque, unsigned int ntype, unsigned int *types)
@@ -1310,7 +1274,6 @@ static gboolean on_render_jpeg(void *opaque G_GNUC_UNUSED,
 }
 
 static const struct vnc_connection_ops vnc_display_ops = {
-	.auth_cred = on_auth_cred,
 	.auth_type = on_auth_type,
 	.auth_subtype = on_auth_subtype,
 	.render_jpeg = on_render_jpeg,
@@ -2020,89 +1983,13 @@ static void vnc_display_init(VncDisplay *display)
 			 G_CALLBACK(on_auth_failure), display);
 	g_signal_connect(G_OBJECT(priv->conn), "vnc-auth-unsupported",
 			 G_CALLBACK(on_auth_unsupported), display);
-}
-
-static int vnc_display_best_path(char *buf,
-				 int buflen,
-				 const char *basedir,
-				 const char *basefile,
-				 char **dirs,
-				 unsigned int ndirs)
-{
-	unsigned int i;
-	for (i = 0 ; i < ndirs ; i++) {
-		struct stat sb;
-		snprintf(buf, buflen-1, "%s/%s/%s", dirs[i], basedir, basefile);
-		buf[buflen-1] = '\0';
-		if (stat(buf, &sb) == 0)
-			return 0;
-	}
-	return -1;
-}
-
-static int vnc_display_set_x509_credential(VncDisplay *obj, const char *name)
-{
-	char file[PATH_MAX];
-	char sysdir[PATH_MAX];
-#ifndef WIN32
-	char userdir[PATH_MAX];
-	struct passwd *pw;
-	char *dirs[] = { sysdir, userdir };
-#else
-	char *dirs[] = { sysdir };
-#endif
-
-	strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
-	sysdir[PATH_MAX-1] = '\0';
-
-#ifndef WIN32
-	if (!(pw = getpwuid(getuid())))
-		return TRUE;
-
-	snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
-	userdir[PATH_MAX-1] = '\0';
-#endif
-
-	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem",
-				  dirs, sizeof(dirs)/sizeof(dirs[0])) < 0)
-		return TRUE;
-	vnc_connection_set_credential_x509_cacert(obj->priv->conn, file);
-
-	/* Don't mind failures of CRL */
-	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem",
-				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
-		vnc_connection_set_credential_x509_cacert(obj->priv->conn, file);
-
-	/* Set client key & cert if we have them. Server will reject auth
-	 * if it decides it requires them*/
-	if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem",
-				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
-		vnc_connection_set_credential_x509_key(obj->priv->conn, file);
-	if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem",
-				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
-		vnc_connection_set_credential_x509_cert(obj->priv->conn, file);
-
-	return FALSE;
+	g_signal_connect(G_OBJECT(priv->conn), "vnc-auth-credential",
+			 G_CALLBACK(on_auth_cred), display);
 }
 
 gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
 {
-	switch (type) {
-	case VNC_DISPLAY_CREDENTIAL_PASSWORD:
-		if (vnc_connection_set_credential_password(obj->priv->conn, data))
-			return FALSE;
-		return TRUE;
-
-	case VNC_DISPLAY_CREDENTIAL_USERNAME:
-		if (vnc_connection_set_credential_username(obj->priv->conn, data))
-			return FALSE;
-		return TRUE;
-
-	case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
-		return vnc_display_set_x509_credential(obj, data);
-	}
-
-	return FALSE;
+	return !vnc_connection_set_credential(obj->priv->conn, type, data);
 }
 
 void vnc_display_set_pointer_local(VncDisplay *obj, gboolean enable)
diff --git a/src/vncimageframebuffer.c b/src/vncimageframebuffer.c
index 1a71707..4a38c93 100644
--- a/src/vncimageframebuffer.c
+++ b/src/vncimageframebuffer.c
@@ -150,6 +150,8 @@ VncImageFramebuffer *vnc_image_framebuffer_new(GdkImage *image,
 	localFormat.bits_per_pixel = image->bpp * 8;
 	localFormat.byte_order = image->byte_order == GDK_LSB_FIRST ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
 
+	memset(image->mem, 0, image->bpl * image->height);
+
 	return VNC_IMAGE_FRAMEBUFFER(g_object_new(VNC_TYPE_IMAGE_FRAMEBUFFER,
 						  "image", image,
 						  "buffer", (guint8 *)image->mem,
-- 
1.6.5.2



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]