Add support for libvirt graphical auth

This commit is contained in:
Daniel P. Berrange 2009-07-29 12:35:27 +01:00
parent 852825ae5e
commit bc55a8d757
5 changed files with 204 additions and 58 deletions

View File

@ -25,19 +25,72 @@
#include <vncdisplay.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <string.h>
#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"
"<b>%s</b>\n\n",
type,
address ? address : "<unknown>");
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:
*/

View File

@ -12,6 +12,18 @@
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkLabel" id="message">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
@ -61,7 +73,7 @@
</child>
</widget>
<packing>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
@ -88,7 +100,7 @@
<property name="response_id">-5</property>
</widget>
<packing>
<property name="position">1</property>
<property name="position">3</property>
</packing>
</child>
</widget>

View File

@ -23,8 +23,14 @@
#ifndef VIRT_VIEWER_AUTH_H
#define VIRT_VIEWER_AUTH_H
#include <libvirt/libvirt.h>
#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

View File

@ -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);

View File

@ -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");