From: Alexander Bokovoy <abokovoy@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel