[Spice-devel] [spice-gtk] spice-channel: support SASL GSSAPI
Fabiano FidĂȘncio
fidencio at redhat.com
Mon Jun 6 12:51:23 UTC 2016
From: Alexander Bokovoy <abokovoy at redhat.com>
Support SASL GSSAPI Kerberos by discovering default credential from
default Kerberos credentials cache.
If default Kerberos credential is missing, fallback to standard method
with password and username.
Signed-of-by: Alexander Bokovoy <abokovoy at redhat.com>
---
src/spice-channel.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/src/spice-channel.c b/src/spice-channel.c
index c6e548d..af49d8a 100644
--- a/src/spice-channel.c
+++ b/src/spice-channel.c
@@ -1358,17 +1358,32 @@ static gchar *addr_to_string(GSocketAddress *addr)
static gboolean
spice_channel_gather_sasl_credentials(SpiceChannel *channel,
- sasl_interact_t *interact)
+ sasl_interact_t *interact,
+ sasl_conn_t *sasl_conn)
{
SpiceChannelPrivate *c;
- int ninteract;
+ int ninteract, rc;
gboolean ret = TRUE;
+ const char *mechname = NULL;
+ gboolean is_gssapi = FALSE;
+ krb5_context krbctx = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_principal defprinc = NULL;
+ krb5_error_code krberr = 0;
+ char *username = NULL;
g_return_val_if_fail(channel != NULL, FALSE);
g_return_val_if_fail(channel->priv != NULL, FALSE);
c = channel->priv;
+ if (sasl_conn != NULL) {
+ rc = sasl_getprop(sasl_conn, SASL_MECHNAME, (const void**) &mechname);
+ if (rc == SASL_OK && g_strcmp0(mechname, "GSSAPI") == 0) {
+ is_gssapi = TRUE;
+ }
+ }
+
/* FIXME: we could keep connection open and ask connection details if missing */
for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
@@ -1387,6 +1402,44 @@ spice_channel_gather_sasl_credentials(SpiceChannel *channel,
switch (interact[ninteract].id) {
case SASL_CB_AUTHNAME:
case SASL_CB_USER:
+ /* For SASL GSSAPI derive user name from the default Kerberos credential */
+ if (is_gssapi && spice_session_get_username(c->session) == NULL) {
+ krberr = krb5_init_context(&krbctx);
+ if (krberr) {
+ g_critical("Cannot initialize Kerberos context while using SASL GSSAPI");
+ return FALSE;
+ }
+ krberr = krb5_cc_default(krbctx, &ccache);
+ if (krberr) {
+ krb5_free_context(krbctx);
+ g_critical("Default Kerberos credential cache not found. Need username and password to initialize");
+ return FALSE;
+ }
+ krberr = krb5_cc_get_principal(krbctx, ccache, &defprinc);
+ if (krberr) {
+ krb5_cc_close(krbctx, ccache);
+ krb5_free_context(krbctx);
+ g_critical("Kerberos user principal not found. Need username and password to initialize");
+ return FALSE;
+ }
+
+ krberr = krb5_unparse_name_flags(krbctx, defprinc, KRB5_PRINCIPAL_UNPARSE_SHORT, &username);
+ if (krberr) {
+ krb5_free_principal(krbctx, defprinc);
+ krb5_cc_close(krbctx, ccache);
+ krb5_free_context(krbctx);
+ g_critical("Kerberos user principal cannot be parsed. Need username and password to initialize");
+ return FALSE;
+ }
+
+ g_object_set(c->session, "username", username, NULL);
+
+ krb5_free_unparsed_name(krbctx, username);
+ krb5_free_principal(krbctx, defprinc);
+ krb5_cc_close(krbctx, ccache);
+ krb5_free_context(krbctx);
+ }
+
if (spice_session_get_username(c->session) == NULL)
return FALSE;
@@ -1595,7 +1648,7 @@ restart:
/* Need to gather some credentials from the client */
if (err == SASL_INTERACT) {
- if (!spice_channel_gather_sasl_credentials(channel, interact)) {
+ if (!spice_channel_gather_sasl_credentials(channel, interact, saslconn)) {
CHANNEL_DEBUG(channel, "Failed to collect auth credentials");
goto error;
}
@@ -1679,7 +1732,7 @@ restart:
/* Need to gather some credentials from the client */
if (err == SASL_INTERACT) {
if (!spice_channel_gather_sasl_credentials(channel,
- interact)) {
+ interact, saslconn)) {
CHANNEL_DEBUG(channel, "%s", "Failed to collect auth credentials");
goto error;
}
--
2.7.4
More information about the Spice-devel
mailing list