Re: [gtk-vnc-devel] PATCH 2/2: API for gathering credentials
- From: "Daniel P. Berrange" <berrange redhat com>
- To: gtk-vnc-devel lists sourceforge net
- Subject: Re: [gtk-vnc-devel] PATCH 2/2: API for gathering credentials
- Date: Thu, 5 Jul 2007 19:28:21 +0100
This is the patch whichs adds the APIs for gathering credentials
- Adds the vnc_display_set_credential method for providing data
- Adds the vnc-auth-credential signal for requesting credential
data from the app
- Adds a generic GSource for efficiently waiting in the main loop for
a boolean condition to be satisified
- Extends the C & python example programs to demonstrate ahead of time
and synchronous authentication processes.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
changeset: 23:7f9c4f423f86
tag: tip
user: "Daniel P. Berrange <berrange redhat com>"
date: Thu Jul 05 13:48:15 2007 -0400
summary: Added API for getting authentication credentials from application
diff -r b77ea47300ab -r 7f9c4f423f86 examples/gvncviewer.c
--- a/examples/gvncviewer.c Wed Jul 04 15:32:55 2007 -0400
+++ b/examples/gvncviewer.c Thu Jul 05 13:48:15 2007 -0400
@@ -7,16 +7,83 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
+GtkWidget *window;
+
+void vnc_disconnect(GtkWidget *vnc)
+{
+ printf("VNC widget disconnected\n");
+ gtk_main_quit();
+}
+
+void vnc_initialized(GtkWidget *vnc)
+{
+ printf("VNC widget initialized\n");
+ gtk_widget_show_all(GTK_WIDGET(window));
+}
+
+void vnc_credential(GtkWidget *vnc, int cred)
+{
+ GtkWidget *dialog, *label, *entry, *box, *vbox;
+ const char *data, *title;
+ int response;
+
+ printf("Got credential request for %d\n", cred);
+ if (cred != VNC_DISPLAY_CREDENTIAL_PASSWORD &&
+ cred != VNC_DISPLAY_CREDENTIAL_USERNAME) {
+ printf("Unsupported credential type\n");
+ vnc_display_close(VNC_DISPLAY(vnc));
+ return;
+ }
+
+ dialog = gtk_dialog_new_with_buttons("Authentication required",
+ NULL,
+ 0,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK,
+ NULL);
+
+ box = gtk_hbox_new(6, TRUE);
+
+ if (cred == VNC_DISPLAY_CREDENTIAL_PASSWORD)
+ label = gtk_label_new("Password:");
+ else
+ label = gtk_label_new("Username:");
+
+ entry = gtk_entry_new();
+
+ vbox = gtk_bin_get_child(GTK_BIN(dialog));
+
+ gtk_container_add(GTK_CONTAINER(vbox), box);
+ gtk_container_add(GTK_CONTAINER(box), label);
+ gtk_container_add(GTK_CONTAINER(box), entry);
+
+ gtk_widget_show_all(dialog);
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(GTK_WIDGET(dialog));
+
+ data = gtk_entry_get_text(GTK_ENTRY(entry));
+
+ if (response == GTK_RESPONSE_OK && data) {
+ printf("Setting credentials\n");
+ vnc_display_set_credential(VNC_DISPLAY(vnc), cred, data);
+ } else {
+ printf("Aborting connection\n");
+ vnc_display_close(VNC_DISPLAY(vnc));
+ }
+
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+}
int main(int argc, char **argv)
{
- GtkWidget *window;
GtkWidget *vnc;
char *ret = NULL;
if (argc != 3 && argc != 4) {
- fprintf(stderr, "syntax: vnc-test ipaddress port [password]\n");
- return 1;
+ fprintf(stderr, "syntax: vnc-test ipaddress port [password]\n");
+ return 1;
}
gtk_init(&argc, &argv);
@@ -25,19 +92,35 @@ int main(int argc, char **argv)
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), vnc);
- gtk_widget_show_all(window);
+ gtk_widget_realize(GTK_WIDGET(vnc));
if (argc == 4)
- vnc_display_set_password(VNC_DISPLAY(vnc), argv[3]);
+ vnc_display_set_credential(VNC_DISPLAY(vnc), VNC_DISPLAY_CREDENTIAL_PASSWORD, argv[3]);
+
vnc_display_open_name(VNC_DISPLAY(vnc), argv[1], argv[2]);
gtk_signal_connect(GTK_OBJECT(window), "delete-event",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+ gtk_signal_connect(GTK_OBJECT(vnc), "vnc-initialized",
+ GTK_SIGNAL_FUNC(vnc_initialized), NULL);
+
gtk_signal_connect(GTK_OBJECT(vnc), "vnc-disconnected",
- GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+ GTK_SIGNAL_FUNC(vnc_disconnect), NULL);
+
+ gtk_signal_connect(GTK_OBJECT(vnc), "vnc-auth-credential",
+ GTK_SIGNAL_FUNC(vnc_credential), NULL);
gtk_main();
return 0;
}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r b77ea47300ab -r 7f9c4f423f86 examples/gvncviewer.py
--- a/examples/gvncviewer.py Wed Jul 04 15:32:55 2007 -0400
+++ b/examples/gvncviewer.py Thu Jul 05 13:48:15 2007 -0400
@@ -2,17 +2,63 @@
import gtk
import gtkvnc
+import sys
+if len(sys.argv) != 3 and len(sys.argv) != 4:
+ print "syntax: gvncviewer.py host port [password]"
+ sys.exit(1)
w = gtk.Window()
+def vnc_disconnect(src):
+ print "VNC disconnected"
+ gtk.main_quit()
+
+def vnc_initialize(src):
+ print "VNC initialized"
+ w.show_all()
+
+def vnc_credential(src, type):
+ print "VNC auth credential %d" % type
+
+ if type != gtkvnc.CREDENTIAL_PASSWORD and type != gtkvnc.CREDENTIAL_USERNAME:
+ src.close()
+ return
+
+ dialog = gtk.Dialog("Authentication required", None, 0, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
+ vbox = dialog.get_child()
+ box = gtk.HBox()
+ if type == gtkvnc.CREDENTIAL_PASSWORD:
+ label = gtk.Label("Password:")
+ else:
+ label = gtk.Label("Username:")
+ entry = gtk.Entry()
+
+ box.add(label)
+ box.add(entry)
+ vbox.add(box)
+
+ dialog.show_all()
+ res = dialog.run()
+ dialog.hide()
+ data = entry.get_text()
+ if res == gtk.RESPONSE_CANCEL or data is None or data == "":
+ src.close()
+ else:
+ src.set_credential(type, data)
+ dialog.destroy()
+
v = gtkvnc.Display()
+w.add(v)
+v.realize()
-w.add(v)
-w.show_all()
+if len(sys.argv) == 4:
+ v.set_credential(gtkvnc.CREDENTIAL_PASSWORD, sys.argv[3])
-v.set_password("123456")
-v.open_name("localhost", "5901")
-v.connect("vnc-disconnected", gtk.main_quit)
+v.open_name(sys.argv[1], sys.argv[2])
+v.connect("vnc-disconnected", vnc_disconnect)
+v.connect("vnc-initialized", vnc_initialize)
+v.connect("vnc-auth-credential", vnc_credential)
+w.connect("delete-event", gtk.main_quit)
gtk.main()
diff -r b77ea47300ab -r 7f9c4f423f86 src/gvnc.c
--- a/src/gvnc.c Wed Jul 04 15:32:55 2007 -0400
+++ b/src/gvnc.c Thu Jul 05 13:48:15 2007 -0400
@@ -38,24 +38,6 @@
#define KEY_FILE "key.pem"
#define CERT_FILE "cert.pem"
-static gboolean g_io_wait_helper(GIOChannel *channel G_GNUC_UNUSED,
- GIOCondition cond,
- gpointer data)
-{
- struct coroutine *to = data;
- yieldto(to, &cond);
- return FALSE;
-}
-
-static GIOCondition g_io_wait(GIOChannel *channel, GIOCondition cond)
-{
- GIOCondition *ret;
-
- g_io_add_watch(channel, cond, g_io_wait_helper, coroutine_self());
- ret = yield(NULL);
-
- return *ret;
-}
typedef void gvnc_blt_func(struct gvnc *, uint8_t *, int, int, int, int, int);
@@ -80,6 +62,12 @@ struct gvnc
int minor;
gnutls_session_t tls_session;
+ /* Auth related params */
+ unsigned int auth_type;
+ unsigned int auth_subtype;
+ char *cred_username;
+ char *cred_password;
+
char read_buffer[4096];
size_t read_offset;
size_t read_size;
@@ -98,33 +86,118 @@ struct gvnc
int shared_memory_enabled;
- struct gvnc_ops ops;
+ const struct gvnc_ops *ops;
gpointer ops_data;
int absolute;
};
-enum {
- GVNC_AUTH_INVALID = 0,
- GVNC_AUTH_NONE = 1,
- GVNC_AUTH_VNC = 2,
- GVNC_AUTH_RA2 = 5,
- GVNC_AUTH_RA2NE = 6,
- GVNC_AUTH_TIGHT = 16,
- GVNC_AUTH_ULTRA = 17,
- GVNC_AUTH_TLS = 18,
- GVNC_AUTH_VENCRYPT = 19
+
+/* Main loop helper functions */
+static gboolean g_io_wait_helper(GIOChannel *channel G_GNUC_UNUSED,
+ GIOCondition cond,
+ gpointer data)
+{
+ struct coroutine *to = data;
+ yieldto(to, &cond);
+ return FALSE;
+}
+
+static GIOCondition g_io_wait(GIOChannel *channel, GIOCondition cond)
+{
+ GIOCondition *ret;
+
+ g_io_add_watch(channel, cond, g_io_wait_helper, coroutine_self());
+ ret = yield(NULL);
+
+ return *ret;
+}
+
+
+/*
+ * A special GSource impl which allows us to wait on a certain
+ * condition to be satisified. This is effectively a boolean test
+ * run on each iteration of the main loop. So whenever a file has
+ * new I/O, or a timer occurrs, etc we'll do the check. This is
+ * pretty efficient compared to a normal GLib Idle func which has
+ * to busy wait on a timeout, since our condition is only checked
+ * when some other source's state changes
+ */
+typedef gboolean (*g_condition_wait_func)(gpointer);
+
+struct g_condition_wait_source {
+ GSource src;
+ struct coroutine *co;
+ g_condition_wait_func func;
+ gpointer data;
};
-enum {
- GVNC_AUTH_VENCRYPT_PLAIN = 256,
- GVNC_AUTH_VENCRYPT_TLSNONE = 257,
- GVNC_AUTH_VENCRYPT_TLSVNC = 258,
- GVNC_AUTH_VENCRYPT_TLSPLAIN = 259,
- GVNC_AUTH_VENCRYPT_X509NONE = 260,
- GVNC_AUTH_VENCRYPT_X509VNC = 261,
- GVNC_AUTH_VENCRYPT_X509PLAIN = 262,
+/*
+ * Call immediately before the main loop does an iteration. Returns
+ * true if the condition we're checking is ready for dispatch
+ */
+static gboolean g_condition_wait_prepare(GSource *src,
+ int *timeout) {
+ struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
+ *timeout = -1;
+ return vsrc->func(vsrc->data);
+}
+
+/*
+ * Call immediately after the main loop does an iteration. Returns
+ * true if the condition we're checking is ready for dispatch
+ */
+static gboolean g_condition_wait_check(GSource *src) {
+ struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
+ return vsrc->func(vsrc->data);
+}
+
+static gboolean g_condition_wait_dispatch(GSource *src G_GNUC_UNUSED,
+ GSourceFunc cb,
+ gpointer data) {
+ return cb(data);
+}
+
+GSourceFuncs waitFuncs = {
+ .prepare = g_condition_wait_prepare,
+ .check = g_condition_wait_check,
+ .dispatch = g_condition_wait_dispatch,
};
+
+static gboolean g_condition_wait_helper(gpointer data)
+{
+ struct coroutine *co = (struct coroutine *)data;
+ yieldto(co, NULL);
+ return FALSE;
+}
+
+static gboolean g_condition_wait(g_condition_wait_func func, gpointer data)
+{
+ GSource *src;
+ struct g_condition_wait_source *vsrc;
+
+ /* Short-circuit check in case we've got it ahead of time */
+ if (func(data)) {
+ return TRUE;
+ }
+
+ /*
+ * Don't have it, so yield to the main loop, checking the condition
+ * on each iteration of the main loop
+ */
+ src = g_source_new(&waitFuncs, sizeof(struct g_condition_wait_source));
+ vsrc = (struct g_condition_wait_source *)src;
+
+ vsrc->func = func;
+ vsrc->data = data;
+ vsrc->co = coroutine_self();
+
+ g_source_attach(src, NULL);
+ g_source_set_callback(src, g_condition_wait_helper, coroutine_self(), NULL);
+ yield(NULL);
+ return TRUE;
+}
+
#define DEBUG 0
@@ -812,55 +885,62 @@ static void gvnc_hextile_update(struct g
static void gvnc_update(struct gvnc *gvnc, int x, int y, int width, int height)
{
- if (gvnc->has_error || !gvnc->ops.update)
+ if (gvnc->has_error || !gvnc->ops->update)
return;
- gvnc->has_error = !gvnc->ops.update(gvnc->ops_data, x, y, width, height);
+ if (!gvnc->ops->update(gvnc->ops_data, x, y, width, height))
+ gvnc->has_error = TRUE;
}
static void gvnc_set_color_map_entry(struct gvnc *gvnc, uint16_t color,
uint16_t red, uint16_t green,
uint16_t blue)
{
- if (gvnc->has_error || !gvnc->ops.set_color_map_entry)
+ if (gvnc->has_error || !gvnc->ops->set_color_map_entry)
return;
- gvnc->has_error = !gvnc->ops.set_color_map_entry(gvnc->ops_data, color,
- red, green, blue);
+ if (!gvnc->ops->set_color_map_entry(gvnc->ops_data, color,
+ red, green, blue))
+ gvnc->has_error = TRUE;
}
static void gvnc_bell(struct gvnc *gvnc)
{
- if (gvnc->has_error || !gvnc->ops.bell)
+ if (gvnc->has_error || !gvnc->ops->bell)
return;
- gvnc->has_error = !gvnc->ops.bell(gvnc->ops_data);
+ if (!gvnc->ops->bell(gvnc->ops_data))
+ gvnc->has_error = TRUE;
}
static void gvnc_server_cut_text(struct gvnc *gvnc, const void *data,
size_t len)
{
- if (gvnc->has_error || !gvnc->ops.server_cut_text)
+ if (gvnc->has_error || !gvnc->ops->server_cut_text)
return;
- gvnc->has_error = !gvnc->ops.server_cut_text(gvnc->ops_data, data, len);
+ if (!gvnc->ops->server_cut_text(gvnc->ops_data, data, len))
+ gvnc->has_error = TRUE;
}
static void gvnc_resize(struct gvnc *gvnc, int width, int height)
{
- if (gvnc->has_error || !gvnc->ops.resize)
+ if (gvnc->has_error || !gvnc->ops->resize)
return;
- gvnc->has_error = !gvnc->ops.resize(gvnc->ops_data, width, height);
+ if (!gvnc->ops->resize(gvnc->ops_data, width, height))
+ gvnc->has_error = TRUE;
}
static void gvnc_pointer_type_change(struct gvnc *gvnc, int absolute)
{
- if (gvnc->has_error || !gvnc->ops.pointer_type_change)
+ if (gvnc->has_error || !gvnc->ops->pointer_type_change)
return;
- gvnc->has_error = !gvnc->ops.pointer_type_change(gvnc->ops_data, absolute);
+ if (!gvnc->ops->pointer_type_change(gvnc->ops_data, absolute))
+ gvnc->has_error = TRUE;
}
static void gvnc_shared_memory_rmid(struct gvnc *gvnc, int shmid)
{
- if (gvnc->has_error || !gvnc->ops.shared_memory_rmid)
+ if (gvnc->has_error || !gvnc->ops->shared_memory_rmid)
return;
- gvnc->has_error = !gvnc->ops.shared_memory_rmid(gvnc->ops_data, shmid);
+ if (!gvnc->ops->shared_memory_rmid(gvnc->ops_data, shmid))
+ gvnc->has_error = TRUE;
}
static void gvnc_framebuffer_update(struct gvnc *gvnc, int32_t etype,
@@ -1020,19 +1100,19 @@ static gboolean gvnc_check_auth_result(s
return FALSE;
}
-static gboolean gvnc_perform_auth_vnc(struct gvnc *gvnc, const char *password)
+static gboolean gvnc_perform_auth_vnc(struct gvnc *gvnc)
{
uint8_t challenge[16];
uint8_t key[8];
GVNC_DEBUG("Do Challenge\n");
- if (!password)
+ if (!gvnc->cred_password)
return FALSE;
gvnc_read(gvnc, challenge, 16);
memset(key, 0, 8);
- strncpy((char*)key, (char*)password, 8);
+ strncpy((char*)key, (char*)gvnc->cred_password, 8);
deskey(key, EN0);
des(challenge, challenge);
@@ -1140,9 +1220,109 @@ static gboolean gvnc_start_tls(struct gv
}
}
-static gboolean gvnc_perform_auth_vencrypt(struct gvnc *gvnc, const char *password)
-{
- int major, minor, status, wantAuth = GVNC_AUTH_INVALID, anonTLS;
+static gboolean gvnc_wants_credential_password(struct gvnc *gvnc)
+{
+ if (gvnc->auth_type == GVNC_AUTH_VNC)
+ return TRUE;
+
+ if (gvnc->auth_type == GVNC_AUTH_VENCRYPT) {
+ if (gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_PLAIN ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_TLSVNC ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_TLSPLAIN ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_X509VNC ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_X509PLAIN)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean gvnc_wants_credential_username(struct gvnc *gvnc)
+{
+ if (gvnc->auth_type == GVNC_AUTH_VENCRYPT) {
+ if (gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_PLAIN ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_TLSPLAIN ||
+ gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_X509PLAIN)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean gvnc_has_credential_username(gpointer data)
+{
+ struct gvnc *gvnc = (struct gvnc *)data;
+
+ if (gvnc->has_error)
+ return TRUE;
+ if (gvnc->cred_username == NULL)
+ return FALSE;
+ return TRUE;
+}
+static gboolean gvnc_has_credential_password(gpointer data)
+{
+ struct gvnc *gvnc = (struct gvnc *)data;
+
+ if (gvnc->has_error)
+ return TRUE;
+ if (gvnc->cred_password == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+
+static gboolean gvnc_gather_credentials(struct gvnc *gvnc)
+{
+ if (gvnc_wants_credential_username(gvnc) && !gvnc->cred_username) {
+ GVNC_DEBUG("Requesting username\n");
+ if (gvnc->has_error | !gvnc->ops->cred_username) {
+ gvnc->has_error = TRUE;
+ return TRUE;
+ }
+ if (!gvnc->ops->cred_username(gvnc->ops_data))
+ gvnc->has_error = TRUE;
+ if (gvnc->has_error)
+ return TRUE;
+ GVNC_DEBUG("Waiting for username credential\n");
+ g_condition_wait(gvnc_has_credential_username, gvnc);
+ GVNC_DEBUG("Got username credential: %s\n", gvnc->cred_username);
+ if (gvnc->has_error)
+ return TRUE;
+ }
+ if (gvnc_wants_credential_password(gvnc) && !gvnc->cred_password) {
+ GVNC_DEBUG("Requesting password\n");
+ if (gvnc->has_error | !gvnc->ops->cred_password) {
+ gvnc->has_error = TRUE;
+ return TRUE;
+ }
+ if (!gvnc->ops->cred_password(gvnc->ops_data))
+ gvnc->has_error = TRUE;
+ if (gvnc->has_error)
+ return TRUE;
+ GVNC_DEBUG("Waiting for password credential\n");
+ g_condition_wait(gvnc_has_credential_password, gvnc);
+ GVNC_DEBUG("Got password credential: %s\n", gvnc->cred_password);
+ if (gvnc->has_error)
+ return TRUE;
+ }
+ return gvnc_has_error(gvnc);
+}
+
+static gboolean gvnc_has_auth_subtype(gpointer data)
+{
+ struct gvnc *gvnc = (struct gvnc *)data;
+
+ if (gvnc->has_error)
+ return TRUE;
+ if (gvnc->auth_subtype == GVNC_AUTH_INVALID)
+ return FALSE;
+ return TRUE;
+}
+
+
+static gboolean gvnc_perform_auth_vencrypt(struct gvnc *gvnc)
+{
+ int major, minor, status, anonTLS;
unsigned int nauth, i;
unsigned int auth[20];
@@ -1178,41 +1358,48 @@ static gboolean gvnc_perform_auth_vencry
GVNC_DEBUG("Possible auth %d\n", auth[i]);
}
+ if (gvnc->has_error || !gvnc->ops->auth_subtype)
+ return FALSE;
+
+ if (!gvnc->ops->auth_subtype(gvnc->ops_data, nauth, auth))
+ gvnc->has_error = TRUE;
if (gvnc->has_error)
return FALSE;
- for (i = 0 ; i < nauth ; i++) {
- if (auth[i] == GVNC_AUTH_VENCRYPT_TLSNONE ||
- auth[i] == GVNC_AUTH_VENCRYPT_TLSPLAIN ||
- auth[i] == GVNC_AUTH_VENCRYPT_TLSVNC ||
- auth[i] == GVNC_AUTH_VENCRYPT_X509NONE ||
- auth[i] == GVNC_AUTH_VENCRYPT_X509PLAIN ||
- auth[i] == GVNC_AUTH_VENCRYPT_X509VNC) {
- wantAuth = auth[i];
- break;
- }
- }
-
- if (wantAuth == GVNC_AUTH_VENCRYPT_PLAIN) {
+ GVNC_DEBUG("Waiting for auth subtype\n");
+ g_condition_wait(gvnc_has_auth_subtype, gvnc);
+ if (gvnc->has_error)
+ return FALSE;
+
+ GVNC_DEBUG("Choose auth %d\n", gvnc->auth_subtype);
+
+ if (gvnc_gather_credentials(gvnc))
+ return FALSE;
+
+#if !DEBUG
+ if (gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_PLAIN) {
GVNC_DEBUG("Cowardly refusing to transmit plain text password\n");
return FALSE;
}
-
- GVNC_DEBUG("Choose auth %d\n", wantAuth);
- gvnc_write_u32(gvnc, wantAuth);
+#endif
+
+ gvnc_write_u32(gvnc, gvnc->auth_subtype);
gvnc_flush(gvnc);
status = gvnc_read_u8(gvnc);
if (status != 1) {
- GVNC_DEBUG("Server refused VeNCrypt auth %d %d\n", wantAuth, status);
- return FALSE;
- }
-
- if (wantAuth == GVNC_AUTH_VENCRYPT_TLSNONE ||
- wantAuth == GVNC_AUTH_VENCRYPT_TLSPLAIN ||
- wantAuth == GVNC_AUTH_VENCRYPT_TLSVNC)
+ GVNC_DEBUG("Server refused VeNCrypt auth %d %d\n", gvnc->auth_subtype, status);
+ return FALSE;
+ }
+
+ switch (gvnc->auth_subtype) {
+ case GVNC_AUTH_VENCRYPT_TLSNONE:
+ case GVNC_AUTH_VENCRYPT_TLSPLAIN:
+ case GVNC_AUTH_VENCRYPT_TLSVNC:
anonTLS = 1;
- else
+ break;
+ default:
anonTLS = 0;
+ }
if (!gvnc_start_tls(gvnc, anonTLS)) {
GVNC_DEBUG("Could not start TLS\n");
@@ -1220,7 +1407,7 @@ static gboolean gvnc_perform_auth_vencry
}
GVNC_DEBUG("Completed TLS setup\n");
- switch (wantAuth) {
+ switch (gvnc->auth_subtype) {
/* Plain certificate based auth */
case GVNC_AUTH_VENCRYPT_TLSNONE:
case GVNC_AUTH_VENCRYPT_X509NONE:
@@ -1231,16 +1418,26 @@ static gboolean gvnc_perform_auth_vencry
case GVNC_AUTH_VENCRYPT_TLSVNC:
case GVNC_AUTH_VENCRYPT_X509VNC:
GVNC_DEBUG("Handing off to VNC auth\n");
- return gvnc_perform_auth_vnc(gvnc, password);
+ return gvnc_perform_auth_vnc(gvnc);
default:
return FALSE;
}
}
-static gboolean gvnc_perform_auth(struct gvnc *gvnc, const char *password)
-{
- int wantAuth = GVNC_AUTH_INVALID;
+static gboolean gvnc_has_auth_type(gpointer data)
+{
+ struct gvnc *gvnc = (struct gvnc *)data;
+
+ if (gvnc->has_error)
+ return TRUE;
+ if (gvnc->auth_type == GVNC_AUTH_INVALID)
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean gvnc_perform_auth(struct gvnc *gvnc)
+{
unsigned int nauth, i;
unsigned int auth[10];
@@ -1267,40 +1464,56 @@ static gboolean gvnc_perform_auth(struct
GVNC_DEBUG("Possible auth %d\n", auth[i]);
}
+ if (gvnc->has_error || !gvnc->ops->auth_type)
+ return FALSE;
+
+ if (!gvnc->ops->auth_type(gvnc->ops_data, nauth, auth))
+ gvnc->has_error = TRUE;
if (gvnc->has_error)
return FALSE;
- for (i = 0 ; i < nauth ; i++) {
- if (auth[i] == GVNC_AUTH_NONE ||
- auth[i] == GVNC_AUTH_VNC ||
- auth[i] == GVNC_AUTH_VENCRYPT) {
- wantAuth = auth[i];
- break;
- }
- }
+ GVNC_DEBUG("Waiting for auth type\n");
+ g_condition_wait(gvnc_has_auth_type, gvnc);
+ if (gvnc->has_error)
+ return FALSE;
+
+ GVNC_DEBUG("Choose auth %d\n", gvnc->auth_type);
+ if (gvnc_gather_credentials(gvnc))
+ return FALSE;
if (gvnc->minor > 6) {
- GVNC_DEBUG("Chose auth %d\n", wantAuth);
- gvnc_write_u8(gvnc, wantAuth);
+ gvnc_write_u8(gvnc, gvnc->auth_type);
gvnc_flush(gvnc);
}
- switch (wantAuth) {
+ switch (gvnc->auth_type) {
case GVNC_AUTH_NONE:
if (gvnc->minor == 8)
return gvnc_check_auth_result(gvnc);
return TRUE;
case GVNC_AUTH_VNC:
- return gvnc_perform_auth_vnc(gvnc, password);
+ return gvnc_perform_auth_vnc(gvnc);
case GVNC_AUTH_VENCRYPT:
- return gvnc_perform_auth_vencrypt(gvnc, password);
+ return gvnc_perform_auth_vencrypt(gvnc);
default:
return FALSE;
}
return TRUE;
+}
+
+static void gvnc_init(struct gvnc *gvnc, const struct gvnc_ops *ops, gpointer ops_data)
+{
+ memset(gvnc, 0, sizeof(*gvnc));
+ gvnc->fd = -1;
+
+ gvnc->ops = ops;
+ gvnc->ops_data = ops_data;
+
+ gvnc->auth_type = GVNC_AUTH_INVALID;
+ gvnc->auth_subtype = GVNC_AUTH_INVALID;
}
struct gvnc *gvnc_new(const struct gvnc_ops *ops, gpointer ops_data)
@@ -1309,11 +1522,7 @@ struct gvnc *gvnc_new(const struct gvnc_
if (gvnc == NULL)
return NULL;
- memset(gvnc, 0, sizeof(*gvnc));
- gvnc->fd = -1;
-
- memcpy(&gvnc->ops, ops, sizeof(*ops));
- gvnc->ops_data = ops_data;
+ gvnc_init(gvnc, ops, ops_data);
return gvnc;
}
@@ -1328,29 +1537,29 @@ void gvnc_free(struct gvnc *gvnc)
void gvnc_close(struct gvnc *gvnc)
{
- if (gvnc->tls_session) {
+ const struct gvnc_ops *ops = gvnc->ops;
+ gpointer ops_data = gvnc->ops_data;
+
+ if (gvnc->tls_session)
gnutls_bye(gvnc->tls_session, GNUTLS_SHUT_RDWR);
- gvnc->tls_session = NULL;
- }
- if (gvnc->channel) {
+ if (gvnc->channel)
g_io_channel_unref(gvnc->channel);
- gvnc->channel = NULL;
- }
- if (gvnc->fd != -1) {
+ if (gvnc->fd != -1)
close(gvnc->fd);
- gvnc->fd = -1;
- }
free(gvnc->host);
- gvnc->host = NULL;
-
free(gvnc->port);
- gvnc->port = NULL;
-
free(gvnc->name);
- gvnc->name = NULL;
-
- gvnc->has_error = 0;
+ free(gvnc->cred_username);
+ free(gvnc->cred_password);
+
+ gvnc_init(gvnc, ops, ops_data);
+}
+
+void gvnc_shutdown(struct gvnc *gvnc)
+{
+ GVNC_DEBUG("Marking connection with error\n");
+ gvnc->has_error = TRUE;
}
gboolean gvnc_is_connected(struct gvnc *gvnc)
@@ -1363,7 +1572,7 @@ gboolean gvnc_is_connected(struct gvnc *
}
-static gboolean gvnc_connect(struct gvnc *gvnc, gboolean shared_flag, const char *password)
+static gboolean gvnc_connect(struct gvnc *gvnc, gboolean shared_flag)
{
int ret;
char version[13];
@@ -1392,7 +1601,7 @@ static gboolean gvnc_connect(struct gvnc
gvnc_flush(gvnc);
GVNC_DEBUG("Negotiated protocol %d %d\n", gvnc->major, gvnc->minor);
- if (!gvnc_perform_auth(gvnc, password)) {
+ if (!gvnc_perform_auth(gvnc)) {
GVNC_DEBUG("Auth failed\n");
goto fail;
}
@@ -1420,11 +1629,11 @@ static gboolean gvnc_connect(struct gvnc
return gvnc_has_error(gvnc);
fail:
- gvnc->has_error = 1;
+ gvnc->has_error = TRUE;
return gvnc_has_error(gvnc);
}
-gboolean gvnc_connect_fd(struct gvnc *gvnc, int fd, gboolean shared_flag, const char *password)
+gboolean gvnc_connect_fd(struct gvnc *gvnc, int fd, gboolean shared_flag)
{
int flags;
if (gvnc_is_connected(gvnc))
@@ -1441,10 +1650,10 @@ gboolean gvnc_connect_fd(struct gvnc *gv
return TRUE;
gvnc->fd = fd;
- return gvnc_connect(gvnc, shared_flag, password);
-}
-
-gboolean gvnc_connect_name(struct gvnc *gvnc, const char *host, const char *port, gboolean shared_flag, const char *password)
+ return gvnc_connect(gvnc, shared_flag);
+}
+
+gboolean gvnc_connect_name(struct gvnc *gvnc, const char *host, const char *port, gboolean shared_flag)
{
struct addrinfo *ai, *runp, hints;
int ret;
@@ -1486,14 +1695,16 @@ gboolean gvnc_connect_name(struct gvnc *
}
reconnect:
+ GVNC_DEBUG("Trying to connect\n");
if (connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) {
gvnc->channel = chan;
gvnc->fd = fd;
freeaddrinfo(ai);
- return gvnc_connect(gvnc, shared_flag, password);
+ return gvnc_connect(gvnc, shared_flag);
}
if (errno == EINPROGRESS) {
+ GVNC_DEBUG("Waiting for connect to continue\n");
g_io_wait(chan, G_IO_OUT|G_IO_ERR|G_IO_HUP);
goto reconnect;
} else if (errno != ECONNREFUSED) {
@@ -1510,6 +1721,65 @@ gboolean gvnc_connect_name(struct gvnc *
}
+gboolean gvnc_set_auth_type(struct gvnc *gvnc, unsigned int type)
+{
+ GVNC_DEBUG("Requested auth type %d\n", type);
+ if (gvnc->auth_type != GVNC_AUTH_INVALID) {
+ gvnc->has_error = TRUE;
+ return gvnc_has_error(gvnc);
+ }
+ if (type != GVNC_AUTH_NONE &&
+ type != GVNC_AUTH_VNC &&
+ type != GVNC_AUTH_VENCRYPT) {
+ gvnc->has_error = TRUE;
+ return gvnc_has_error(gvnc);
+ }
+ gvnc->auth_type = type;
+ gvnc->auth_subtype = GVNC_AUTH_INVALID;
+
+ return gvnc_has_error(gvnc);
+}
+
+gboolean gvnc_set_auth_subtype(struct gvnc *gvnc, unsigned int type)
+{
+ GVNC_DEBUG("Requested auth subtype %d\n", type);
+ if (gvnc->auth_type != GVNC_AUTH_VENCRYPT) {
+ gvnc->has_error = TRUE;
+ return gvnc_has_error(gvnc);
+ }
+ if (gvnc->auth_subtype != GVNC_AUTH_INVALID) {
+ gvnc->has_error = TRUE;
+ return gvnc_has_error(gvnc);
+ }
+ gvnc->auth_subtype = type;
+
+ return gvnc_has_error(gvnc);
+}
+
+gboolean gvnc_set_credential_password(struct gvnc *gvnc, const char *password)
+{
+ GVNC_DEBUG("Set password credential\n");
+ if (gvnc->cred_password)
+ free(gvnc->cred_password);
+ if (!(gvnc->cred_password = strdup(password))) {
+ gvnc->has_error = TRUE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean gvnc_set_credential_username(struct gvnc *gvnc, const char *username)
+{
+ GVNC_DEBUG("Set username credential %s\n", username);
+ if (gvnc->cred_username)
+ free(gvnc->cred_username);
+ if (!(gvnc->cred_username = strdup(username))) {
+ gvnc->has_error = TRUE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
gboolean gvnc_set_local(struct gvnc *gvnc, struct gvnc_framebuffer *fb)
{
diff -r b77ea47300ab -r 7f9c4f423f86 src/gvnc.h
--- a/src/gvnc.h Wed Jul 04 15:32:55 2007 -0400
+++ b/src/gvnc.h Thu Jul 05 13:48:15 2007 -0400
@@ -8,6 +8,10 @@ struct gvnc;
struct gvnc_ops
{
+ gboolean (*cred_username)(void *);
+ gboolean (*cred_password)(void *);
+ gboolean (*auth_type)(void *, unsigned int, unsigned int *);
+ gboolean (*auth_subtype)(void *, unsigned int, unsigned int *);
gboolean (*update)(void *, int, int, int, int);
gboolean (*set_color_map_entry)(void *, int, int, int, int);
gboolean (*bell)(void *);
@@ -71,13 +75,42 @@ enum {
GVNC_ENCODING_SHARED_MEMORY = -258,
};
+enum {
+ GVNC_AUTH_INVALID = 0,
+ GVNC_AUTH_NONE = 1,
+ GVNC_AUTH_VNC = 2,
+ GVNC_AUTH_RA2 = 5,
+ GVNC_AUTH_RA2NE = 6,
+ GVNC_AUTH_TIGHT = 16,
+ GVNC_AUTH_ULTRA = 17,
+ GVNC_AUTH_TLS = 18,
+ GVNC_AUTH_VENCRYPT = 19
+};
+
+enum {
+ GVNC_AUTH_VENCRYPT_PLAIN = 256,
+ GVNC_AUTH_VENCRYPT_TLSNONE = 257,
+ GVNC_AUTH_VENCRYPT_TLSVNC = 258,
+ GVNC_AUTH_VENCRYPT_TLSPLAIN = 259,
+ GVNC_AUTH_VENCRYPT_X509NONE = 260,
+ GVNC_AUTH_VENCRYPT_X509VNC = 261,
+ GVNC_AUTH_VENCRYPT_X509PLAIN = 262,
+};
+
struct gvnc *gvnc_new(const struct gvnc_ops *ops, gpointer ops_data);
void gvnc_free(struct gvnc *gvnc);
void gvnc_close(struct gvnc *gvnc);
+void gvnc_shutdown(struct gvnc *gvnc);
gboolean gvnc_is_connected(struct gvnc *gvnc);
-gboolean gvnc_connect_fd(struct gvnc *gvnc, int fd, gboolean shared_flag, const char *password);
-gboolean gvnc_connect_name(struct gvnc *gvnc, const char *host, const char *port, gboolean shared_flag, const char *password);
+gboolean gvnc_connect_fd(struct gvnc *gvnc, int fd, gboolean shared_flag);
+gboolean gvnc_connect_name(struct gvnc *gvnc, const char *host, const char *port, gboolean shared_flag);
+
+gboolean gvnc_set_auth_type(struct gvnc *gvnc, unsigned int type);
+gboolean gvnc_set_auth_subtype(struct gvnc *gvnc, unsigned int type);
+
+gboolean gvnc_set_credential_password(struct gvnc *gvnc, const char *password);
+gboolean gvnc_set_credential_username(struct gvnc *gvnc, const char *username);
gboolean gvnc_server_message(struct gvnc *gvnc);
diff -r b77ea47300ab -r 7f9c4f423f86 src/libgtk-vnc_sym.version
--- a/src/libgtk-vnc_sym.version Wed Jul 04 15:32:55 2007 -0400
+++ b/src/libgtk-vnc_sym.version Thu Jul 05 13:48:15 2007 -0400
@@ -1,10 +1,17 @@
{
global:
vnc_display_get_type;
+ vnc_display_credential_get_type;
+
vnc_display_new;
+
vnc_display_open_fd;
vnc_display_open_name;
- vnc_display_set_password;
+ vnc_display_is_open;
+ vnc_display_close;
+
+ vnc_display_set_credential;
+
vnc_display_set_use_shm;
vnc_display_get_width;
vnc_display_get_height;
diff -r b77ea47300ab -r 7f9c4f423f86 src/vncdisplay.c
--- a/src/vncdisplay.c Wed Jul 04 15:32:55 2007 -0400
+++ b/src/vncdisplay.c Thu Jul 05 13:48:15 2007 -0400
@@ -41,7 +41,6 @@ struct _VncDisplayPrivate
int button_mask;
int last_x;
int last_y;
- const char *password;
int absolute;
@@ -51,12 +50,14 @@ struct _VncDisplayPrivate
/* Signals */
enum
{
+ VNC_CONNECTED,
VNC_INITIALIZED,
VNC_DISCONNECTED,
+ VNC_AUTH_CREDENTIAL,
LAST_SIGNAL
};
-static guint signals[LAST_SIGNAL] = { 0, 0 };
+static guint signals[LAST_SIGNAL] = { 0, 0, 0, 0 };
GtkWidget *vnc_display_new(void)
{
@@ -370,7 +371,66 @@ static gboolean on_shared_memory_rmid(vo
return TRUE;
}
+static gboolean on_cred_username(void *opaque)
+{
+ VncDisplay *obj = VNC_DISPLAY(opaque);
+
+ g_signal_emit (G_OBJECT (obj),
+ signals[VNC_AUTH_CREDENTIAL],
+ 0,
+ VNC_DISPLAY_CREDENTIAL_USERNAME);
+
+ return TRUE;
+}
+
+static gboolean on_cred_password(void *opaque)
+{
+ VncDisplay *obj = VNC_DISPLAY(opaque);
+
+ g_signal_emit (G_OBJECT (obj),
+ signals[VNC_AUTH_CREDENTIAL],
+ 0,
+ VNC_DISPLAY_CREDENTIAL_PASSWORD);
+
+ return TRUE;
+}
+
+static gboolean on_auth_type(void *opaque, unsigned int ntype, unsigned int *types)
+{
+ VncDisplay *obj = VNC_DISPLAY(opaque);
+ VncDisplayPrivate *priv = obj->priv;
+
+ /*
+ * XXX lame - we should have some prioritization. That
+ * said most servers only support 1 auth type at any time
+ */
+ if (ntype)
+ gvnc_set_auth_type(priv->gvnc, types[0]);
+
+ return TRUE;
+}
+
+static gboolean on_auth_subtype(void *opaque, unsigned int ntype, unsigned int *types)
+{
+ VncDisplay *obj = VNC_DISPLAY(opaque);
+ VncDisplayPrivate *priv = obj->priv;
+
+ /*
+ * XXX lame - we should have some prioritization. That
+ * said most servers only support 1 auth type at any time
+ */
+ if (ntype)
+ gvnc_set_auth_subtype(priv->gvnc, types[0]);
+
+ return TRUE;
+}
+
+
static const struct gvnc_ops vnc_display_ops = {
+ .cred_username = on_cred_username,
+ .cred_password = on_cred_password,
+ .auth_type = on_auth_type,
+ .auth_subtype = on_auth_subtype,
.update = on_update,
.resize = on_resize,
.pointer_type_change = on_pointer_type_change,
@@ -390,17 +450,19 @@ static void *vnc_coroutine(void *opaque)
int ret;
- priv->gvnc = gvnc_new(&vnc_display_ops, obj);
- if (priv->gvnc == NULL)
- return NULL;
-
if (priv->fd != -1) {
- if (gvnc_connect_fd(priv->gvnc, priv->fd, FALSE, priv->password))
+ if (gvnc_connect_fd(priv->gvnc, priv->fd, FALSE))
goto cleanup;
} else {
- if (gvnc_connect_name(priv->gvnc, priv->host, priv->port, FALSE, priv->password))
+ if (gvnc_connect_name(priv->gvnc, priv->host, priv->port, FALSE))
goto cleanup;
}
+
+ /* XXX this should be emitted after socket connects, but before
+ protocol negoitiation starts */
+ g_signal_emit (G_OBJECT (obj),
+ signals[VNC_CONNECTED],
+ 0);
g_signal_emit (G_OBJECT (obj),
signals[VNC_INITIALIZED],
@@ -419,8 +481,7 @@ static void *vnc_coroutine(void *opaque)
}
cleanup:
- gvnc_free(priv->gvnc);
- priv->gvnc = NULL;
+ gvnc_close(priv->gvnc);
g_signal_emit (G_OBJECT (obj),
signals[VNC_DISCONNECTED],
0);
@@ -446,7 +507,10 @@ static gboolean do_vnc_display_open(gpoi
gboolean vnc_display_open_fd(VncDisplay *obj, int fd)
{
- if (obj->priv->gvnc)
+ if (!obj->priv->gvnc)
+ return FALSE;
+
+ if (gvnc_is_connected(obj->priv->gvnc))
return FALSE;
obj->priv->fd = fd;
@@ -459,7 +523,10 @@ gboolean vnc_display_open_fd(VncDisplay
gboolean vnc_display_open_name(VncDisplay *obj, const char *host, const char *port)
{
- if (obj->priv->gvnc)
+ if (!obj->priv->gvnc)
+ return FALSE;
+
+ if (gvnc_is_connected(obj->priv->gvnc))
return FALSE;
obj->priv->host = strdup(host);
@@ -477,9 +544,41 @@ gboolean vnc_display_open_name(VncDispla
return TRUE;
}
+
+gboolean vnc_display_is_open(VncDisplay *obj)
+{
+ if (!obj->priv->gvnc)
+ return FALSE;
+
+ if (gvnc_is_connected(obj->priv->gvnc))
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean vnc_display_close(VncDisplay *obj)
+{
+ if (!vnc_display_is_open(obj))
+ return FALSE;
+
+ gvnc_shutdown(obj->priv->gvnc);
+
+ return TRUE;
+}
+
static void vnc_display_class_init(VncDisplayClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ signals[VNC_CONNECTED] =
+ g_signal_new ("vnc-connected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (VncDisplayClass, vnc_connected),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
signals[VNC_INITIALIZED] =
g_signal_new ("vnc-initialized",
@@ -500,6 +599,17 @@ static void vnc_display_class_init(VncDi
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
+
+ signals[VNC_AUTH_CREDENTIAL] =
+ g_signal_new ("vnc-auth-credential",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (VncDisplayClass, vnc_auth_credential),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
klass->enter_grab_event_id =
g_signal_new("enter-grab-event",
@@ -566,11 +676,25 @@ static void vnc_display_init(GTypeInstan
display->priv->absolute = 1;
display->priv->fb.shm_id = -1;
display->priv->fd = -1;
-}
-
-void vnc_display_set_password(VncDisplay *obj, const gchar *password)
-{
- obj->priv->password = password;
+
+ display->priv->gvnc = gvnc_new(&vnc_display_ops, obj);
+}
+
+gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
+{
+ switch (type) {
+ case VNC_DISPLAY_CREDENTIAL_PASSWORD:
+ if (gvnc_set_credential_password(obj->priv->gvnc, data))
+ return FALSE;
+ return TRUE;
+
+ case VNC_DISPLAY_CREDENTIAL_USERNAME:
+ if (gvnc_set_credential_username(obj->priv->gvnc, data))
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
}
void vnc_display_set_use_shm(VncDisplay *obj, gboolean enable)
@@ -604,6 +728,26 @@ GType vnc_display_get_type(void)
return type;
}
+
+
+GType vnc_display_credential_get_type(void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { VNC_DISPLAY_CREDENTIAL_PASSWORD, "VNC_DISPLAY_CREDENTIAL_PASSWORD", "password" },
+ { VNC_DISPLAY_CREDENTIAL_USERNAME, "VNC_DISPLAY_CREDENTIAL_USERNAME", "username" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static ("VncDisplayCredentialType", values );
+ }
+
+ return etype;
+}
+
+
+
int vnc_display_get_width(VncDisplay *obj)
{
diff -r b77ea47300ab -r 7f9c4f423f86 src/vncdisplay.h
--- a/src/vncdisplay.h Wed Jul 04 15:32:55 2007 -0400
+++ b/src/vncdisplay.h Thu Jul 05 13:48:15 2007 -0400
@@ -19,6 +19,7 @@ typedef struct _VncDisplayPrivate VncDis
#include <glib.h>
#define VNC_TYPE_DISPLAY (vnc_display_get_type())
+#define VNC_TYPE_DISPLAY_CREDENTIAL (vnc_display_credential_get_type())
#define VNC_DISPLAY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), VNC_TYPE_DISPLAY, VncDisplay))
@@ -47,22 +48,34 @@ struct _VncDisplayClass
GtkDrawingAreaClass parent_class;
/* Signals */
+ void (* vnc_connected) (VncDisplay *display);
void (* vnc_initialized) (VncDisplay *display);
void (* vnc_disconnected) (VncDisplay *display);
+ void (* vnc_auth_credential) (VncDisplay *display, int credential);
int enter_grab_event_id;
int leave_grab_event_id;
};
+typedef enum
+{
+ VNC_DISPLAY_CREDENTIAL_PASSWORD,
+ VNC_DISPLAY_CREDENTIAL_USERNAME,
+} VncDisplayCredential;
+
G_BEGIN_DECLS
GType vnc_display_get_type(void);
+GType vnc_display_credential_get_type(void);
+
GtkWidget * vnc_display_new(void);
gboolean vnc_display_open_fd(VncDisplay *obj, int fd);
gboolean vnc_display_open_name(VncDisplay *obj, const char *host, const char *port);
+gboolean vnc_display_is_open(VncDisplay *obj);
+gboolean vnc_display_close(VncDisplay *obj);
-void vnc_display_set_password(VncDisplay *obj, const gchar *password);
+gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data);
void vnc_display_set_use_shm(VncDisplay *obj, gboolean enable);
diff -r b77ea47300ab -r 7f9c4f423f86 src/vncmodule.c
--- a/src/vncmodule.c Wed Jul 04 15:32:55 2007 -0400
+++ b/src/vncmodule.c Thu Jul 05 13:48:15 2007 -0400
@@ -21,6 +21,7 @@
#include <pygobject.h>
void gtkvnc_register_classes (PyObject *d);
+void gtkvnc_add_constants(PyObject *module, const gchar *strip_prefix);
extern PyMethodDef gtkvnc_functions[];
DL_EXPORT(void) initgtkvnc(void);
@@ -39,6 +40,7 @@ DL_EXPORT(void) initgtkvnc(void)
if (PyErr_Occurred())
Py_FatalError("can't get dict");
+ gtkvnc_add_constants(m, "VNC_DISPLAY_");
gtkvnc_register_classes (d);
if (PyErr_Occurred ()) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]