[Patches] avoid krb5_ccache ccselect magic (bug #12480)

Stefan Metzmacher metze at samba.org
Thu Dec 29 21:14:54 UTC 2016


Hi,

here're my patches for https://bugzilla.samba.org/show_bug.cgi?id=12480.

Using gss_acquire_cred() (of MIT krb5) followed by
gss_init_sec_context() will
randomly choose any credential cache (from a global list) that
matches the realm of target principal.

Have a look at the commit messages or the bug for more details...

Please review and push:-)

Thanks!
metze
-------------- next part --------------
From 12ce46a02237a7168515176bb10d5c49d9492618 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 22 Dec 2016 08:46:21 +0100
Subject: [PATCH 1/3] s3:librpc/gse: include ccache_name in DEBUG message if
 krb5_cc_resolve() fails

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12480

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source3/librpc/crypto/gse.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index e4ceed1..459cf12 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -172,8 +172,8 @@ static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
 	k5ret = krb5_cc_resolve(gse_ctx->k5ctx, ccache_name,
 				&gse_ctx->ccache);
 	if (k5ret) {
-		DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
-			  error_message(k5ret)));
+		DEBUG(1, ("Failed to resolve credential cache '%s'! (%s)\n",
+			  ccache_name, error_message(k5ret)));
 		status = NT_STATUS_INTERNAL_ERROR;
 		goto err_out;
 	}
-- 
1.9.1


From 978434e11a861a7b990bf585b818af9cb5ed5359 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 22 Dec 2016 08:47:32 +0100
Subject: [PATCH 2/3] s3:librpc/gse: remove unused #ifdef
 HAVE_GSS_KRB5_IMPORT_CRED

We always have gss_krb5_import_cred(), it available in heimdal
and also the oldest version (1.9) of MIT krb5 that we support.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12480

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source3/librpc/crypto/gse.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index 459cf12..1c812f8 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -390,8 +390,6 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-#ifdef HAVE_GSS_KRB5_IMPORT_CRED
-
 	/* This creates a GSSAPI cred_id_t with the keytab set */
 	gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab, 
 				       &gse_ctx->creds);
@@ -410,7 +408,6 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
 		 * 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))
-#endif
 	/* 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
-- 
1.9.1


From 69723ac36d31effd5c1949de0ce693d2face7b2c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 22 Dec 2016 08:49:38 +0100
Subject: [PATCH 3/3] s3:librpc/gse: make use of gss_krb5_import_cred() instead
 of gss_acquire_cred()

This avoids the usage of the ccselect_realm logic in MIT krb5,
which leads to unpredictable results.

The problem is the usage of gss_acquire_cred(), that just creates
a credential handle without ccache.

As result gss_init_sec_context() will trigger a code path
where it use "ccselect" plugins. And the ccselect_realm
module just chooses a random ccache from a global list
where the realm of the provides target principal matches
the realm of the ccache user principal.

In the winbindd case we're using MEMORY:cliconnect to setup
the smb connection to the DC. For ldap connections we use
MEMORY:winbind_ccache.

The typical case is that we do the smb connection first.
If we try to create a new ldap connection, while the
credentials in MEMORY:cliconnect are expired,
we'll do the required kinit into MEMORY:winbind_ccache,
but the ccselect_realm module will select MEMORY:cliconnect
and tries to get a service ticket for the ldap server
using the already expired TGT from MEMORY:cliconnect.

The solution will be to use gss_krb5_import_cred() and explicitly
pass the desired ccache, which avoids the ccselect logic.

We could also use gss_acquire_cred_from(), but that's only available
in modern MIT krb5 versions, while gss_krb5_import_cred() is available
in heimdal and all supported MIT versions (>=1.9).
As far as I can see both call the same internal function in MIT
(at least for the ccache case).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12480

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source3/librpc/crypto/gse.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index 1c812f8..792700e 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -204,7 +204,6 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 	struct gse_context *gse_ctx;
 	OM_uint32 gss_maj, gss_min;
 	gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER;
-	gss_OID_set_desc mech_set;
 #ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
 	gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
 	gss_OID oid = discard_const(GSS_KRB5_CRED_NO_CI_FLAGS_X);
@@ -253,20 +252,26 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 	/* TODO: get krb5 ticket using username/password, if no valid
 	 * one already available in ccache */
 
-	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_INITIATE,
-				   &gse_ctx->creds,
-				   NULL, NULL);
+	gss_maj = gss_krb5_import_cred(&gss_min,
+				       gse_ctx->ccache,
+				       NULL, /* keytab_principal */
+				       NULL, /* keytab */
+				       &gse_ctx->creds);
 	if (gss_maj) {
-		DEBUG(5, ("gss_acquire_creds failed for GSS_C_NO_NAME with [%s] -"
+		char *ccache = NULL;
+		int kret;
+
+		kret = krb5_cc_get_full_name(gse_ctx->k5ctx,
+					     gse_ctx->ccache,
+					     &ccache);
+		if (kret != 0) {
+			ccache = NULL;
+		}
+
+		DEBUG(5, ("gss_krb5_import_cred ccache[%s] failed with [%s] -"
 			  "the caller may retry after a kinit.\n",
-			  gse_errstr(gse_ctx, gss_maj, gss_min)));
+			  ccache, gse_errstr(gse_ctx, gss_maj, gss_min)));
+		SAFE_FREE(ccache);
 		status = NT_STATUS_INTERNAL_ERROR;
 		goto err_out;
 	}
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20161229/fb18e830/signature.sig>


More information about the samba-technical mailing list