Cross realm S4U2Self cont.

Isaac Boukris iboukris at gmail.com
Mon Aug 6 12:36:47 UTC 2018


Hi Stefan,

On Fri, Aug 3, 2018 at 5:33 PM, Stefan Metzmacher <metze at samba.org> wrote:
> I hope I got the chance in the next weeks...

Thanks!

>> Note that unlike what I said initially, transitive trust still does
>> not work (only direct trust). I thought it worked when I was testing
>> with kgetcred against windows but when I try to actually accept the
>> ticket by the service, it fails at krb5_check_transited(). Also, there
>> seem to be the same issue on the KDC side when Samba KDC is in a the
>> trust path.
>
> Have a look at this thread:
> http://mailman.mit.edu/pipermail/krbdev/2017-August/thread.html#12791
>
> We need to get something like this:
> gss_set_cred_option(GSS_KRB5_CRED_NO_TRANSIT_CHECK_X)
> in order to disable the check.
>
> Which can be used if the application requires a validated PAC.


Ok, I've implemented the no_transit_check flag, and finally got
net-ads-pac-dump impersonate to work with transitive trust (against
windows KDCs only, so far).
See attached patch (wip), if it looks in the right direction I'll try
to port to upstream heimdal/mit projects (after I finish cleaning up
this series though).

What I still wander is, why does it seem to be a problem only with
s4u2self, or is it really?
Technically it sounds like it should happen with regular tickets too,
so I'm trying to trigger it that way (and also, to see how can it be
tested in samba).


As regarding my last comment about the same issue in samba KDC side,
I'm not so sure actually, I'm trying to test this again now.
However, I think I found another bug in samba KDC with transitive
trust, which would cause s4u2self to fail.
This bug is not directly related to s4u2self, and can easily be
reproduces with MIT's kvno tool against samba KDC (in transitive trust
env).

In short, the first step in cross-realm s4u2self, is to obtain a
krbtgt to client realm, and while samba kdc gives proper referral to
intermediate realm when asked for HOST/transitively-trusted-realm, it
won't give a referral when asked for
krbtgt/transitively-trusted-realm, so the service cannot get started
(windows kdc does give referral in that case).
I have a POC patch for this bug (which I'm not happy with), but since
it's not directly related, I send it with more details in a separate
thread.

Regards.
-------------- next part --------------
From 0bbb019b03454d799feda01d5c4c4ed178671c56 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris at gmail.com>
Date: Mon, 6 Aug 2018 14:39:46 +0300
Subject: [PATCH] WIP: Implement and use GSS_KRB5_CRED_NO_TRANSIT_CHECK_X

See:
http://mailman.mit.edu/pipermail/krbdev/2017-August/thread.html#12791

Signed-off-by: Isaac Boukris <iboukris at gmail.com>
---
 source3/librpc/crypto/gse.c                        | 17 ++++++++++++++
 source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h     |  3 +++
 .../heimdal/lib/gssapi/krb5/accept_sec_context.c   | 11 +++++++++
 source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h     |  1 +
 source4/heimdal/lib/gssapi/krb5/set_cred_option.c  | 26 ++++++++++++++++++----
 source4/heimdal/lib/gssapi/mech/gss_oid.c          |  3 +++
 source4/heimdal/lib/gssapi/version-script.map      |  1 +
 source4/heimdal/lib/krb5/krb5.h                    |  3 +++
 source4/heimdal/lib/krb5/rd_req.c                  | 21 ++++++++++++++---
 source4/heimdal/lib/krb5/version-script.map        |  1 +
 10 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index 70e29c27923..68ec4d199f2 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -600,6 +600,23 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
+#ifdef GSS_KRB5_CRED_NO_TRANSIT_CHECK_X
+	{
+		gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
+		gss_OID oid = discard_const(GSS_KRB5_CRED_NO_TRANSIT_CHECK_X);
+
+		gss_maj = gss_set_cred_option(&gss_min, &gse_ctx->creds, oid,
+					      &empty_buffer);
+		if (gss_maj != 0) {
+			DEBUG(0, ("gss_set_cred_option failed with [%s]\n",
+				  gse_errstr(gse_ctx, gss_maj, gss_min)));
+			status = NT_STATUS_INTERNAL_ERROR;
+			/* do we need to release the cred handle? */
+			goto done;
+		}
+	}
+#endif /* GSS_KRB5_CRED_NO_TRANSIT_CHECK_X */
+
 	status = NT_STATUS_OK;
 
 done:
diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h
index 3d00c060d10..d134c0668e3 100644
--- a/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h
+++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h
@@ -99,6 +99,9 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_no_ci_flags_x_oid_desc;
 extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_import_cred_x_oid_desc;
 #define GSS_KRB5_IMPORT_CRED_X (&__gss_krb5_import_cred_x_oid_desc)
 
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_no_transit_check_x_oid_desc;
+#define GSS_KRB5_CRED_NO_TRANSIT_CHECK_X (&__gss_krb5_cred_no_transit_check_x_oid_desc)
+
  /* glue for gss_inquire_saslname_for_mech */
 extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_sasl_mech_name_oid_desc;
 #define GSS_C_MA_SASL_MECH_NAME (&__gss_c_ma_sasl_mech_name_oid_desc)
diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
index cfe27ace875..744edb1cdf7 100644
--- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
@@ -412,6 +412,17 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
 	    return GSS_S_FAILURE;
 	}
 
+	if (acceptor_cred != NULL &&
+		(acceptor_cred->cred_flags & GSS_CF_NO_TRANSIT_CHECK)) {
+	    kret = krb5_rd_req_in_set_no_transit_check(context, in, true);
+	    if (kret) {
+		if (in)
+		    krb5_rd_req_in_ctx_free(context, in);
+		*minor_status = kret;
+		return GSS_S_FAILURE;
+	    }
+	}
+
 	kret = krb5_rd_req_ctx(context,
 			       &ctx->auth_context,
 			       &indata,
diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
index 6b9b03f3490..6a1e977452c 100644
--- a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
+++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
@@ -94,6 +94,7 @@ typedef struct {
   int cred_flags;
 #define GSS_CF_DESTROY_CRED_ON_RELEASE	1
 #define GSS_CF_NO_CI_FLAGS		2
+#define GSS_CF_NO_TRANSIT_CHECK		4
   struct krb5_keytab_data *keytab;
   OM_uint32 lifetime;
   gss_cred_usage_t usage;
diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
index bd387167510..7e42dd493aa 100644
--- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
+++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
@@ -196,9 +196,7 @@ out:
 
 static OM_uint32
 no_ci_flags(OM_uint32 *minor_status,
-	    krb5_context context,
-	    gss_cred_id_t *cred_handle,
-	    const gss_buffer_t value)
+	    gss_cred_id_t *cred_handle)
 {
     gsskrb5_cred cred;
 
@@ -212,7 +210,24 @@ no_ci_flags(OM_uint32 *minor_status,
 
     *minor_status = 0;
     return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+no_transit_check(OM_uint32 *minor_status,
+		 gss_cred_id_t *cred_handle)
+{
+    gsskrb5_cred cred;
+
+    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
+	*minor_status = 0;
+	return GSS_S_FAILURE;
+    }
+
+    cred = (gsskrb5_cred)*cred_handle;
+    cred->cred_flags |= GSS_CF_NO_TRANSIT_CHECK;
 
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
 }
 
 
@@ -239,9 +254,12 @@ _gsskrb5_set_cred_option
 	return allowed_enctypes(minor_status, context, cred_handle, value);
 
     if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) {
-	return no_ci_flags(minor_status, context, cred_handle, value);
+	return no_ci_flags(minor_status, cred_handle);
     }
 
+    if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_TRANSIT_CHECK_X)) {
+	return no_transit_check(minor_status, cred_handle);
+    }
 
     *minor_status = EINVAL;
     return GSS_S_FAILURE;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_oid.c b/source4/heimdal/lib/gssapi/mech/gss_oid.c
index 916d1e4dda5..6f86eec65c3 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_oid.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_oid.c
@@ -94,6 +94,9 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_cred_no_ci_flags_x_oid_desc = { 6, r
 /* GSS_KRB5_IMPORT_CRED_X - 1.2.752.43.13.30 */
 gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_import_cred_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1e") };
 
+/* GSS_KRB5_CRED_NO_TRANSIT_CHECK_X - 1.2.752.43.13.31 */
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_cred_no_transit_check_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1f") };
+
 /* GSS_C_MA_SASL_MECH_NAME - 1.2.752.43.13.100 */
 gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_sasl_mech_name_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x64") };
 
diff --git a/source4/heimdal/lib/gssapi/version-script.map b/source4/heimdal/lib/gssapi/version-script.map
index bcb79bf8f76..484d6f98013 100644
--- a/source4/heimdal/lib/gssapi/version-script.map
+++ b/source4/heimdal/lib/gssapi/version-script.map
@@ -155,6 +155,7 @@ HEIMDAL_GSS_2.0 {
 		__gss_c_ntlm_force_v1_oid_desc;
 		__gss_krb5_cred_no_ci_flags_x_oid_desc;
 		__gss_krb5_import_cred_x_oid_desc;
+		__gss_krb5_cred_no_transit_check_x_oid_desc;
 		__gss_c_ma_sasl_mech_name_oid_desc;
 		__gss_c_ma_mech_name_oid_desc;
 		__gss_c_ma_mech_description_oid_desc;
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index 9c0f5669466..9983adef7ab 100644
--- a/source4/heimdal/lib/krb5/krb5.h
+++ b/source4/heimdal/lib/krb5/krb5.h
@@ -422,6 +422,9 @@ typedef union {
 /* flags for krb5_verify_ap_req */
 
 #define KRB5_VERIFY_AP_REQ_IGNORE_INVALID	(1 << 0)
+#define KRB5_VERIFY_AP_REQ_NO_TRANSIT_CHECK	(1 << 1)
+
+/* for get_creds */
 
 #define KRB5_GC_CACHED			(1U << 0)
 #define KRB5_GC_USER_USER		(1U << 1)
diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c
index 21daeb596b5..c06dedf4d80 100644
--- a/source4/heimdal/lib/krb5/rd_req.c
+++ b/source4/heimdal/lib/krb5/rd_req.c
@@ -253,7 +253,8 @@ krb5_decrypt_ticket(krb5_context context,
 	    return KRB5KRB_AP_ERR_TKT_EXPIRED;
 	}
 
-	if(!t.flags.transited_policy_checked) {
+	if(!t.flags.transited_policy_checked &&
+		!(flags & KRB5_VERIFY_AP_REQ_NO_TRANSIT_CHECK)) {
 	    ret = check_transited(context, ticket, &t);
 	    if(ret) {
 		free_EncTicketPart(&t);
@@ -519,6 +520,7 @@ struct krb5_rd_req_in_ctx_data {
     krb5_keytab keytab;
     krb5_keyblock *keyblock;
     krb5_boolean check_pac;
+    krb5_boolean no_transit_check;
 };
 
 struct krb5_rd_req_out_ctx_data {
@@ -608,6 +610,15 @@ krb5_rd_req_in_set_keyblock(krb5_context context,
     return 0;
 }
 
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_rd_req_in_set_no_transit_check(krb5_context context,
+			     krb5_rd_req_in_ctx in,
+			     krb5_boolean flag)
+{
+    in->no_transit_check = flag;
+    return 0;
+}
+
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_rd_req_out_get_ap_req_options(krb5_context context,
 				   krb5_rd_req_out_ctx out,
@@ -850,6 +861,7 @@ krb5_rd_req_ctx(krb5_context context,
     krb5_rd_req_out_ctx o = NULL;
     krb5_keytab id = NULL, keytab = NULL;
     krb5_principal service = NULL;
+    krb5_flags verify_ap_flags = 0;
 
     *outctx = NULL;
 
@@ -937,6 +949,9 @@ krb5_rd_req_ctx(krb5_context context,
 	}
     }
 
+    if (inctx != NULL && inctx->no_transit_check) {
+	verify_ap_flags |= KRB5_VERIFY_AP_REQ_NO_TRANSIT_CHECK;
+    }
     if (o->keyblock) {
 	/*
 	 * We got an exact keymatch, use that.
@@ -947,7 +962,7 @@ krb5_rd_req_ctx(krb5_context context,
 				  &ap_req,
 				  server,
 				  o->keyblock,
-				  0,
+				  verify_ap_flags,
 				  &o->ap_req_options,
 				  &o->ticket,
 				  KRB5_KU_AP_REQ_AUTH);
@@ -995,7 +1010,7 @@ krb5_rd_req_ctx(krb5_context context,
 				      &ap_req,
 				      server,
 				      &entry.keyblock,
-				      0,
+				      verify_ap_flags,
 				      &o->ap_req_options,
 				      &o->ticket,
 				      KRB5_KU_AP_REQ_AUTH);
diff --git a/source4/heimdal/lib/krb5/version-script.map b/source4/heimdal/lib/krb5/version-script.map
index ddae2a06764..4c51b2f35f3 100644
--- a/source4/heimdal/lib/krb5/version-script.map
+++ b/source4/heimdal/lib/krb5/version-script.map
@@ -529,6 +529,7 @@ HEIMDAL_KRB5_2.0 {
 		krb5_rd_req_in_set_keyblock;
 		krb5_rd_req_in_set_keytab;
 		krb5_rd_req_in_set_pac_check;
+		krb5_rd_req_in_set_no_transit_check;
 		krb5_rd_req_out_ctx_free;
 		krb5_rd_req_out_get_ap_req_options;
 		krb5_rd_req_out_get_keyblock;
-- 
2.14.3



More information about the samba-technical mailing list