/* virt-click * Copyright (C) 2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Parts are derived from 'gvnccapture': * * Vnc Image Capture * * Copyright (C) 2010 Daniel P. Berrange * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #ifdef HAVE_TERMIOS_H #include #endif #include #include #include #include "click.h" static const guint preferable_auths[] = { /* * Both these two provide TLS based auth, and can layer * all the other auth types on top. So these two must * be the first listed */ VNC_CONNECTION_AUTH_VENCRYPT, VNC_CONNECTION_AUTH_TLS, /* * Then stackable auth types in order of preference */ VNC_CONNECTION_AUTH_SASL, VNC_CONNECTION_AUTH_MSLOGON, VNC_CONNECTION_AUTH_VNC, /* * Or nothing at all */ VNC_CONNECTION_AUTH_NONE }; static gchar * get_credential (const gchar *prompt, gboolean doecho) { #ifdef HAVE_TERMIOS_H struct termios old, new; #endif gchar buf[100]; gchar *res; int n = sizeof(buf); ssize_t len; printf("%s", prompt); fflush(stdout); #ifdef HAVE_TERMIOS_H /* Turn echoing off and fail if we can't. */ if (!doecho && tcgetattr (fileno (stdin), &old) != 0) return NULL; new = old; new.c_lflag &= ~ECHO; if (!doecho && tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0) return NULL; #else doecho = TRUE; /* Avoid unused parameter compile warning */ #endif /* Read the password. */ if ((res = fgets(buf, n, stdin)) != NULL) { len = strlen(res); if (res[len-1] == '\n') res[len-1] = '\0'; } #ifdef HAVE_TERMIOS_H /* Restore terminal. */ if (!doecho) { printf("\n"); (void) tcsetattr(fileno (stdin), TCSAFLUSH, &old); } #endif return res ? g_strdup(res) : NULL; } void vc_vnc_auth_credential (VncConnection *conn, GValueArray *credList, gpointer opaque) { self_t *self = opaque; guint i; char **data; data = g_new0(char *, credList->n_values); 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_CONNECTION_CREDENTIAL_PASSWORD: data[i] = get_credential ("Password: ", FALSE); if (!data[i]) { if (verbose) fprintf (stderr, "vnc: failed to read password\n"); vnc_connection_shutdown(conn); goto cleanup; } break; case VNC_CONNECTION_CREDENTIAL_USERNAME: data[i] = get_credential ("Username: ", TRUE); if (!data[i]) { if (verbose) fprintf (stderr, "vnc: failed to read username\n"); vnc_connection_shutdown(conn); goto cleanup; } break; case VNC_CONNECTION_CREDENTIAL_CLIENTNAME: data[i] = g_strdup ("virt-click"); break; default: break; } } for (i = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); if (data[i]) { if (!vnc_connection_set_credential(conn, g_value_get_enum(cred), data[i])) { fprintf (stderr, "vnc: failed to set credential type %d %s\n", g_value_get_enum(cred), data[i]); vnc_connection_shutdown(conn); } } else { if (verbose) fprintf (stderr, "vnc: unsupported credential type %d\n", g_value_get_enum(cred)); vnc_connection_shutdown(conn); } } cleanup: for (i = 0 ; i < credList->n_values ; i++) g_free(data[i]); g_free(data); } void vc_vnc_auth_choose_type (VncConnection *conn, GValueArray *types, gpointer opaque G_GNUC_UNUSED) { guint i, j; if (!types->n_values) { VNC_DEBUG("No auth types to choose from"); return; } for (i = 0 ; i < G_N_ELEMENTS(preferable_auths) ; i++) { int pref = preferable_auths[i]; for (j = 0 ; j < types->n_values ; j++) { GValue *type = g_value_array_get_nth(types, j); VNC_DEBUG("Compare %d vs %d", pref, g_value_get_enum(type)); if (pref == g_value_get_enum(type)) { VNC_DEBUG("Chosen auth %d", pref); vnc_connection_set_auth_type(conn, pref); return; } } } GValue *type = g_value_array_get_nth(types, 0); VNC_DEBUG("Chosen default auth %d", g_value_get_enum(type)); vnc_connection_set_auth_type(conn, g_value_get_enum(type)); }