diff --git a/src/auth.c b/src/auth.c index 88afd7f..a7f8c96 100644 --- a/src/auth.c +++ b/src/auth.c @@ -25,19 +25,72 @@ #include #include #include +#include #include "auth.h" -void viewer_auth_vnc_credentials(GtkWidget *vnc, GValueArray *credList) + +static int +viewer_auth_collect_credentials(const char *type, + const char *address, + char **username, + char **password) { GtkWidget *dialog = NULL; - const char **data; + GladeXML *creds = viewer_load_glade("auth.glade", "auth"); + GtkWidget *credUsername; + GtkWidget *credPassword; + GtkWidget *promptUsername; + GtkWidget *promptPassword; + GtkWidget *labelMessage; + int response; + char *message; + + dialog = glade_xml_get_widget(creds, "auth"); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); + + labelMessage = glade_xml_get_widget(creds, "message"); + credUsername = glade_xml_get_widget(creds, "cred-username"); + promptUsername = glade_xml_get_widget(creds, "prompt-username"); + credPassword = glade_xml_get_widget(creds, "cred-password"); + promptPassword = glade_xml_get_widget(creds, "prompt-password"); + + gtk_widget_set_sensitive(credUsername, username != NULL); + gtk_widget_set_sensitive(promptUsername, username != NULL); + gtk_widget_set_sensitive(credPassword, password != NULL); + gtk_widget_set_sensitive(promptPassword, password != NULL); + + message = g_strdup_printf("Authentication is required for the %s connection to:\n\n" + "%s\n\n", + type, + address ? address : ""); + + gtk_label_set_markup(GTK_LABEL(labelMessage), message); + g_free(message); + + gtk_widget_show_all(dialog); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + + if (response == GTK_RESPONSE_OK) { + if (username) + *username = g_strdup(gtk_entry_get_text(GTK_ENTRY(credUsername))); + if (password) + *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(credPassword))); + } + + gtk_widget_destroy(GTK_WIDGET(dialog)); + + return response == GTK_RESPONSE_OK ? 0 : -1; +} + +void viewer_auth_vnc_credentials(GtkWidget *vnc, GValueArray *credList, char **vncAddress) +{ + char *username = NULL, *password = NULL; gboolean wantPassword = FALSE, wantUsername = FALSE; int i; - DEBUG_LOG("Got credential request for %d credential(s)", credList->n_values); - - data = g_new0(const char *, credList->n_values); + DEBUG_LOG("Got VNC credential request for %d credential(s)", credList->n_values); for (i = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); @@ -49,70 +102,129 @@ void viewer_auth_vnc_credentials(GtkWidget *vnc, GValueArray *credList) wantPassword = TRUE; break; case VNC_DISPLAY_CREDENTIAL_CLIENTNAME: - data[i] = "libvirt"; + break; default: - break; + DEBUG_LOG("Unsupported credential type %d", g_value_get_enum(cred)); + vnc_display_close(VNC_DISPLAY(vnc)); + goto cleanup; } } if (wantUsername || wantPassword) { - GladeXML *creds = viewer_load_glade("auth.glade", "auth"); - GtkWidget *credUsername; - GtkWidget *credPassword; - GtkWidget *promptUsername; - GtkWidget *promptPassword; - int response; + int ret = viewer_auth_collect_credentials("VNC", vncAddress ? *vncAddress : NULL, + wantUsername ? &username : NULL, + wantPassword ? &password : NULL); - dialog = glade_xml_get_widget(creds, "auth"); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - - credUsername = glade_xml_get_widget(creds, "cred-username"); - promptUsername = glade_xml_get_widget(creds, "prompt-username"); - credPassword = glade_xml_get_widget(creds, "cred-password"); - promptPassword = glade_xml_get_widget(creds, "prompt-password"); - - gtk_widget_set_sensitive(credUsername, wantUsername); - gtk_widget_set_sensitive(promptUsername, wantUsername); - gtk_widget_set_sensitive(credPassword, wantPassword); - gtk_widget_set_sensitive(promptPassword, wantPassword); - - gtk_widget_show_all(dialog); - response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_hide(dialog); - - if (response == GTK_RESPONSE_OK) { - for (i = 0 ; i < credList->n_values ; i++) { - GValue *cred = g_value_array_get_nth(credList, i); - switch (g_value_get_enum(cred)) { - case VNC_DISPLAY_CREDENTIAL_USERNAME: - data[i] = gtk_entry_get_text(GTK_ENTRY(credUsername)); - break; - case VNC_DISPLAY_CREDENTIAL_PASSWORD: - data[i] = gtk_entry_get_text(GTK_ENTRY(credPassword)); - break; - } - } - } + if (ret < 0) { + vnc_display_close(VNC_DISPLAY(vnc)); + goto cleanup; + } } for (i = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); - if (data[i]) { - if (vnc_display_set_credential(VNC_DISPLAY(vnc), + switch (g_value_get_enum(cred)) { + case VNC_DISPLAY_CREDENTIAL_USERNAME: + if (!username || + vnc_display_set_credential(VNC_DISPLAY(vnc), g_value_get_enum(cred), - data[i])) { + username)) { DEBUG_LOG("Failed to set credential type %d", g_value_get_enum(cred)); vnc_display_close(VNC_DISPLAY(vnc)); } - } else { + break; + case VNC_DISPLAY_CREDENTIAL_PASSWORD: + if (!password || + vnc_display_set_credential(VNC_DISPLAY(vnc), + g_value_get_enum(cred), + password)) { + DEBUG_LOG("Failed to set credential type %d", g_value_get_enum(cred)); + vnc_display_close(VNC_DISPLAY(vnc)); + } + break; + case VNC_DISPLAY_CREDENTIAL_CLIENTNAME: + if (vnc_display_set_credential(VNC_DISPLAY(vnc), + g_value_get_enum(cred), + "libvirt")) { + DEBUG_LOG("Failed to set credential type %d", g_value_get_enum(cred)); + vnc_display_close(VNC_DISPLAY(vnc)); + } + break; + default: DEBUG_LOG("Unsupported credential type %d", g_value_get_enum(cred)); vnc_display_close(VNC_DISPLAY(vnc)); } } - g_free(data); - if (dialog) - gtk_widget_destroy(GTK_WIDGET(dialog)); + cleanup: + g_free(username); + g_free(password); } + +int +viewer_auth_libvirt_credentials(virConnectCredentialPtr cred, + unsigned int ncred, + void *cbdata) +{ + char **username = NULL, **password = NULL; + const char *uri = cbdata; + int i; + int ret = -1; + + DEBUG_LOG("Got libvirt credential request for %d credential(s)", ncred); + + for (i = 0 ; i < ncred ; i++) { + switch (cred[i].type) { + case VIR_CRED_USERNAME: + case VIR_CRED_AUTHNAME: + username = &cred[i].result; + break; + case VIR_CRED_PASSPHRASE: + password = &cred[i].result; + break; + default: + DEBUG_LOG("Unsupported libvirt credential %d", cred[i].type); + return -1; + } + } + + if (username || password) { + ret = viewer_auth_collect_credentials("libvirt", uri, + username, password); + if (ret < 0) + goto cleanup; + } else { + ret = 0; + } + + for (i = 0 ; i < ncred ; i++) { + switch (cred[i].type) { + case VIR_CRED_AUTHNAME: + case VIR_CRED_USERNAME: + case VIR_CRED_PASSPHRASE: + if (cred[i].result) + cred[i].resultlen = strlen(cred[i].result); + else + cred[i].resultlen = 0; + DEBUG_LOG("Got '%s' %d %d", cred[i].result, cred[i].resultlen, cred[i].type); + break; + } + } + + cleanup: + DEBUG_LOG("Return %d", ret); + return ret; +} + + + + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/auth.glade b/src/auth.glade index 2e443fc..bf58452 100644 --- a/src/auth.glade +++ b/src/auth.glade @@ -12,6 +12,18 @@ True 2 + + + True + 0 + 0 + label + True + + + 1 + + True @@ -61,7 +73,7 @@ - 1 + 2 @@ -88,7 +100,7 @@ -5 - 1 + 3 diff --git a/src/auth.h b/src/auth.h index d7b5334..be3fd20 100644 --- a/src/auth.h +++ b/src/auth.h @@ -23,8 +23,14 @@ #ifndef VIRT_VIEWER_AUTH_H #define VIRT_VIEWER_AUTH_H +#include + #include "util.h" -void viewer_auth_vnc_credentials(GtkWidget *vnc, GValueArray *credList); +void viewer_auth_vnc_credentials(GtkWidget *vnc, GValueArray *credList, char **message); + +int viewer_auth_libvirt_credentials(virConnectCredentialPtr cred, + unsigned int ncred, + void *cbdata); #endif diff --git a/src/util.h b/src/util.h index c4c5b3f..421ea6c 100644 --- a/src/util.h +++ b/src/util.h @@ -31,6 +31,7 @@ extern gboolean doDebug; #define DEBUG_LOG(s, ...) do { if (doDebug) g_debug((s), ## __VA_ARGS__); } while (0) +#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) GladeXML *viewer_load_glade(const char *name, const char *widget); diff --git a/src/viewer.c b/src/viewer.c index a13a128..606be3f 100644 --- a/src/viewer.c +++ b/src/viewer.c @@ -115,6 +115,7 @@ typedef struct VirtViewer { gboolean withEvents; int active; + char *vncAddress; gboolean accelEnabled; GValue accelSetting; @@ -843,6 +844,8 @@ static int viewer_activate(VirtViewer *viewer, DEBUG_LOG("Remote host is %s and transport %s user %s", host, transport ? transport : "", user ? user : ""); + viewer->vncAddress = g_strdup_printf("%s:%s", host, vncport); + #if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) if (transport && g_strcasecmp(transport, "ssh") == 0 && !viewer->direct) @@ -850,10 +853,11 @@ static int viewer_activate(VirtViewer *viewer, return -1; #endif - if (fd >= 0) + if (fd >= 0) { vnc_display_open_fd(VNC_DISPLAY(viewer->vnc), fd); - else + } else { vnc_display_open_host(VNC_DISPLAY(viewer->vnc), host, vncport); + } viewer_set_status(viewer, "Connecting to VNC server"); @@ -896,6 +900,8 @@ static void viewer_deactivate(VirtViewer *viewer) gtk_main_quit(); } viewer->active = 0; + g_free(viewer->vncAddress); + viewer->vncAddress = NULL; viewer_set_title(viewer, FALSE); } @@ -1024,6 +1030,14 @@ viewer_start (const char *uri, GtkWidget *notebook; GtkWidget *align; GtkWidget *menu; + int cred_types[] = + { VIR_CRED_AUTHNAME, VIR_CRED_PASSPHRASE }; + virConnectAuth auth_libvirt = { + .credtype = cred_types, + .ncredtype = ARRAY_CARDINALITY(cred_types), + .cb = viewer_auth_libvirt_credentials, + .cbdata = (void *)uri, + }; doDebug = debug; @@ -1043,9 +1057,10 @@ viewer_start (const char *uri, viewer_event_register(); virSetErrorFunc(NULL, viewer_error_func); - /* XXX write a graphical auth function */ + viewer->conn = virConnectOpenAuth(uri, - virConnectAuthPtrDefault, + //virConnectAuthPtrDefault, + &auth_libvirt, VIR_CONNECT_RO); if (!viewer->conn) { fprintf(stderr, "unable to connect to libvirt %s\n", @@ -1111,7 +1126,7 @@ viewer_start (const char *uri, GTK_SIGNAL_FUNC(viewer_key_ungrab), viewer); g_signal_connect(GTK_OBJECT(viewer->vnc), "vnc-auth-credential", - GTK_SIGNAL_FUNC(viewer_auth_vnc_credentials), NULL); + GTK_SIGNAL_FUNC(viewer_auth_vnc_credentials), &viewer->vncAddress); notebook = glade_xml_get_widget(viewer->glade, "notebook");