From 57286d57732d49fdb8b8e21f584787cdbc917c32 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 8 Mar 2017 12:38:49 +0200 Subject: [PATCH] s3-gse: move krb5 fallback to smb_gss_krb5_import_cred wrapper MIT krb5 1.9 version of gss_krb5_import_cred() may fail when importing credentials from a keytab without specifying actual principal. This was fixed in MIT krb5 1.9.2 (see commit 71c3be093db577aa52f6b9a9a3a9f442ca0d8f20 in MIT krb5-1.9 branch, git master's version is bd18687a705a8a6cdcb7c140764d1a7c6a3381b5). Move fallback code to the smb_gss_krb5_import_cred wrapper. We only expect this fallback to happen with krb5 GSSAPI mechanism, thus hard code use of krb5 mech when calling to gss_acquire_cred. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12611 Signed-off-by: Alexander Bokovoy Reviewed-by: Stefan Metzmacher Autobuild-User(master): Alexander Bokovoy Autobuild-Date(master): Wed Mar 8 22:00:24 CET 2017 on sn-devel-144 --- lib/krb5_wrap/gss_samba.c | 46 +++++++++++++++++++++++++++++++--- source3/librpc/crypto/gse.c | 49 +------------------------------------ 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/lib/krb5_wrap/gss_samba.c b/lib/krb5_wrap/gss_samba.c index 757ffc5a33e..9e5ad4a3c8e 100644 --- a/lib/krb5_wrap/gss_samba.c +++ b/lib/krb5_wrap/gss_samba.c @@ -161,9 +161,49 @@ uint32_t smb_gss_krb5_import_cred(uint32_t *minor_status, krb5_context ctx, krb5_free_string(ctx, discard_const(ccache_element.value)); #else major_status = gss_krb5_import_cred(minor_status, - id, - keytab_principal, - keytab, cred); + id, + keytab_principal, + keytab, cred); + + if (major_status == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) { + if ((keytab_principal == NULL) && (keytab != NULL)) { + /* No principal was specified and MIT krb5 1.9 version failed. + * We have to fall back to set global acceptor identity */ + gss_OID_set_desc mech_set; + char *kt_name = NULL; + + kt_name = malloc(4096); + if (!kt_name) { + return ENOMEM; + } + + major_status = krb5_kt_get_name(ctx, + keytab, + kt_name, 4096); + if (major_status != 0) { + free(kt_name); + return major_status; + } + + major_status = gsskrb5_register_acceptor_identity(kt_name); + if (major_status) { + free(kt_name); + return major_status; + } + + /* We are dealing with krb5 GSSAPI mech in this fallback */ + mech_set.count = 1; + mech_set.elements = gss_mech_krb5; + major_status = gss_acquire_cred(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + &mech_set, + GSS_C_ACCEPT, + cred, + NULL, NULL); + free(kt_name); + } + } #endif return major_status; } diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index f4238f32441..a111320e829 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -435,58 +435,11 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, NULL, NULL, gse_ctx->keytab, &gse_ctx->creds); - if (gss_maj != 0 - && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) { + if (gss_maj != 0) { DEBUG(0, ("smb_gss_krb5_import_cred failed with [%s]\n", gse_errstr(gse_ctx, gss_maj, gss_min))); status = NT_STATUS_INTERNAL_ERROR; goto done; - - /* This is the error the MIT krb5 1.9 gives when it - * implements the function, but we do not specify the - * principal. However, when we specify the principal - * as host$@REALM the GSS acceptor fails with 'wrong - * principal in request'. Work around the issue by - * falling back to the alternate approach below. */ - } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) - /* FIXME!!! - * This call sets the default keytab for the whole server, not - * just for this context. Need to find a way that does not alter - * the state of the whole server ... */ - { - const char *ktname; - gss_OID_set_desc mech_set; - - ret = smb_krb5_kt_get_name(gse_ctx, gse_ctx->k5ctx, - gse_ctx->keytab, &ktname); - if (ret) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - ret = gsskrb5_register_acceptor_identity(ktname); - if (ret) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - mech_set.count = 1; - mech_set.elements = &gse_ctx->gss_mech; - - gss_maj = gss_acquire_cred(&gss_min, - GSS_C_NO_NAME, - GSS_C_INDEFINITE, - &mech_set, - GSS_C_ACCEPT, - &gse_ctx->creds, - NULL, NULL); - - if (gss_maj) { - DEBUG(0, ("gss_acquire_creds failed with [%s]\n", - gse_errstr(gse_ctx, gss_maj, gss_min))); - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } } status = NT_STATUS_OK; -- 2.34.1