From 4d0bc8edc5dcea345e2dbe3fee75be02f73966ef Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Aug 2017 15:33:17 +0200 Subject: [PATCH 01/13] UPSTREAM-FIRST!!! HEIMDAL:lib/krb5: add krb5_rd_req_in_set_verify_ap_req_flags() In the next commits we want to be able to pass down things like KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- source4/heimdal/lib/krb5/rd_req.c | 18 ++++++++++++++++-- source4/heimdal/lib/krb5/version-script.map | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 21daeb596b55..76d5caadb318 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -519,6 +519,7 @@ struct krb5_rd_req_in_ctx_data { krb5_keytab keytab; krb5_keyblock *keyblock; krb5_boolean check_pac; + krb5_flags verify_ap_req_flags; }; struct krb5_rd_req_out_ctx_data { @@ -577,6 +578,15 @@ krb5_rd_req_in_set_keytab(krb5_context context, return 0; } +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_rd_req_in_set_verify_ap_req_flags(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_flags flags) +{ + in->verify_ap_req_flags = flags; + return 0; +} + /** * Set if krb5_rq_red() is going to check the Windows PAC or not * @@ -850,6 +860,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_req_flags = 0; *outctx = NULL; @@ -890,6 +901,9 @@ krb5_rd_req_ctx(krb5_context context, if (inctx && inctx->keytab) id = inctx->keytab; + if (inctx) + verify_ap_req_flags = inctx->verify_ap_req_flags; + if((*auth_context)->keyblock){ ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, @@ -947,7 +961,7 @@ krb5_rd_req_ctx(krb5_context context, &ap_req, server, o->keyblock, - 0, + verify_ap_req_flags, &o->ap_req_options, &o->ticket, KRB5_KU_AP_REQ_AUTH); @@ -995,7 +1009,7 @@ krb5_rd_req_ctx(krb5_context context, &ap_req, server, &entry.keyblock, - 0, + verify_ap_req_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 ddae2a067645..7b49c15dfc0e 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_verify_ap_req_flags; krb5_rd_req_out_ctx_free; krb5_rd_req_out_get_ap_req_options; krb5_rd_req_out_get_keyblock; -- 2.17.1 From cc710fc3750a3d9c4f3b0888b8dee24253da871a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Aug 2017 15:33:17 +0200 Subject: [PATCH 02/13] UPSTREAM-FIRST!!! HEIMDAL:lib/krb5: add KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK In active directory a domain member replies on (trusts) the [K]DCs of the domain. It's the job of the [K]DCs to only generate useful tickets as they know about the trust topology. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- source4/heimdal/lib/krb5/krb5.h | 1 + source4/heimdal/lib/krb5/rd_req.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 9c0f5669466c..03119fa78321 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -422,6 +422,7 @@ typedef union { /* flags for krb5_verify_ap_req */ #define KRB5_VERIFY_AP_REQ_IGNORE_INVALID (1 << 0) +#define KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK (1 << 1) #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 76d5caadb318..1a1c31d8d8ba 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_TRANSITED_CHECK)) { ret = check_transited(context, ticket, &t); if(ret) { free_EncTicketPart(&t); -- 2.17.1 From d8676a759ec1388f4e4b5494e92b8d3148a7bd57 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Aug 2017 15:33:17 +0200 Subject: [PATCH 03/13] UPSTREAM-FIRST!!! HEIMDAL:lib/gssapi/krb5: add GSS_KRB5_CRED_NO_TRANSIT_CHECK_X This allows KRB5_GC_NO_TRANSIT_CHECK (on the initiator) and KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK (on the acceptor) to be controlled via the gssapi layer. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- .../heimdal/lib/gssapi/gssapi/gssapi_oid.h | 3 +++ .../lib/gssapi/krb5/accept_sec_context.c | 11 ++++++++- .../heimdal/lib/gssapi/krb5/gsskrb5_locl.h | 1 + .../lib/gssapi/krb5/init_sec_context.c | 16 ++++++++----- .../heimdal/lib/gssapi/krb5/set_cred_option.c | 24 +++++++++++++++++++ source4/heimdal/lib/gssapi/mech/gss_oid.c | 3 +++ source4/heimdal/lib/gssapi/version-script.map | 1 + 7 files changed, 52 insertions(+), 7 deletions(-) diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h index 3d00c060d10d..0eed639d53e1 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h @@ -96,6 +96,9 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_force_v1_oid_desc; extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_no_ci_flags_x_oid_desc; #define GSS_KRB5_CRED_NO_CI_FLAGS_X (&__gss_krb5_cred_no_ci_flags_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) + 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) diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index cfe27ace875e..2e4ed53ba08e 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -398,13 +398,22 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, krb5_rd_req_in_ctx in = NULL; krb5_rd_req_out_ctx out = NULL; krb5_principal server = NULL; + krb5_flags verify_ap_req_flags = 0; - if (acceptor_cred) + if (acceptor_cred) { server = acceptor_cred->principal; + if (acceptor_cred->cred_flags & GSS_CF_NO_TRANSIT_CHECK) { + verify_ap_req_flags |= KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK; + } + } + kret = krb5_rd_req_in_ctx_alloc(context, &in); if (kret == 0) kret = krb5_rd_req_in_set_keytab(context, in, keytab); + if (kret == 0) + kret = krb5_rd_req_in_set_verify_ap_req_flags(context, in, + verify_ap_req_flags); if (kret) { if (in) krb5_rd_req_in_ctx_free(context, in); diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h index 6b9b03f34908..6a1e977452cf 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/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 0a89ae1f36cf..2f55f27000c2 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -205,6 +205,7 @@ gsskrb5_get_creds( OM_uint32 * minor_status, krb5_context context, krb5_ccache ccache, + krb5_flags options, gsskrb5_ctx ctx, const gss_name_t target_name, int use_dns, @@ -246,7 +247,7 @@ gsskrb5_get_creds( this_cred.session.keytype = KEYTYPE_NULL; kret = krb5_get_credentials(context, - 0, + options, ccache, &this_cred, &ctx->kcred); @@ -397,6 +398,7 @@ init_auth krb5_data fwd_data; OM_uint32 lifetime_rec; int allow_dns = 1; + krb5_flags options = 0; krb5_data_zero(&outbuf); krb5_data_zero(&fwd_data); @@ -414,8 +416,12 @@ init_auth goto failure; } ctx->more_flags |= CLOSE_CCACHE; - } else + } else { ctx->ccache = cred->ccache; + if (cred->cred_flags & GSS_CF_NO_TRANSIT_CHECK) { + options |= KRB5_GC_NO_TRANSIT_CHECK; + } + } kret = krb5_cc_get_principal (context, ctx->ccache, &ctx->source); if (kret) { @@ -455,12 +461,10 @@ init_auth * DNS canonicalizion. */ ret = gsskrb5_get_creds(minor_status, context, ctx->ccache, - ctx, name, 0, time_req, - time_rec); + options, ctx, name, 0, time_req, time_rec); if (ret && allow_dns) ret = gsskrb5_get_creds(minor_status, context, ctx->ccache, - ctx, name, 1, time_req, - time_rec); + options, ctx, name, 1, time_req, time_rec); if (ret) goto failure; diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c index bd3871675109..8d9f49884884 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -216,6 +216,26 @@ no_ci_flags(OM_uint32 *minor_status, } +static OM_uint32 +no_transit_check(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + 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; +} + OM_uint32 GSSAPI_CALLCONV _gsskrb5_set_cred_option (OM_uint32 *minor_status, @@ -243,6 +263,10 @@ _gsskrb5_set_cred_option } + if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_TRANSIT_CHECK_X)) { + return no_transit_check(minor_status, context, cred_handle, value); + } + *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 916d1e4dda5e..6f86eec65c39 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 bcb79bf8f76e..776fe19dbf3c 100644 --- a/source4/heimdal/lib/gssapi/version-script.map +++ b/source4/heimdal/lib/gssapi/version-script.map @@ -154,6 +154,7 @@ HEIMDAL_GSS_2.0 { __gss_c_ntlm_session_key_oid_desc; __gss_c_ntlm_force_v1_oid_desc; __gss_krb5_cred_no_ci_flags_x_oid_desc; + __gss_krb5_cred_no_transit_check_x_oid_desc; __gss_krb5_import_cred_x_oid_desc; __gss_c_ma_sasl_mech_name_oid_desc; __gss_c_ma_mech_name_oid_desc; -- 2.17.1 From ab72e28da7e778ec14aa615a1c1bf22e12146e5a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 20 Jul 2019 10:15:04 +0000 Subject: [PATCH 04/13] UPSTREAM-FIRST!!! HEIMDAL:lib/krb5: let krb5_rd_req_ctx() fallback only on KRB5KRB_AP_ERR_BAD_INTEGRITY This avoids hidding a real error like KRB5KRB_AP_ERR_ILL_CR_TKT. We only want to retry with the next key if the decryption failed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- source4/heimdal/lib/krb5/rd_req.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 1a1c31d8d8ba..aef42d8b4ffc 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1014,10 +1014,15 @@ krb5_rd_req_ctx(krb5_context context, &o->ap_req_options, &o->ticket, KRB5_KU_AP_REQ_AUTH); - if (ret) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + /* failed to decrypt, try the next key */ krb5_kt_free_entry (context, &entry); continue; } + if (ret) { + krb5_kt_free_entry (context, &entry); + goto out; + } /* * Found a match, save the keyblock for PAC processing, -- 2.17.1 From f9e3c669b6cb606c8b8650a9e8f134c10fb3b07c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 20 Jul 2019 10:15:04 +0000 Subject: [PATCH 05/13] UPSTREAM-FIRST!!! HEIMDAL:lib/krb5: add krb5_rd_req_in_set_iterate_keytab() A caller might not know the kvno maintained by the KDC. And most often there's need to know it. So this function makes it possible to force the keytab iteration in order to get a consistent behavior. Otherwise it's possible to get a different behavior if the guessed kvno in the keytab accidentally matches the kvno of the ticket and we'll give up if the key is not able to decrypt the ticket. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- source4/heimdal/lib/krb5/rd_req.c | 27 +++++++++++++++++++++ source4/heimdal/lib/krb5/version-script.map | 1 + 2 files changed, 28 insertions(+) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index aef42d8b4ffc..4ea3cee959dc 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -518,6 +518,7 @@ krb5_verify_ap_req2(krb5_context context, struct krb5_rd_req_in_ctx_data { krb5_keytab keytab; + krb5_boolean iterate_keytab; krb5_keyblock *keyblock; krb5_boolean check_pac; krb5_flags verify_ap_req_flags; @@ -588,6 +589,27 @@ krb5_rd_req_in_set_verify_ap_req_flags(krb5_context context, return 0; } +/** + * Set if krb5_rq_red() is going to iterate the keytab to find a key + * + * @param context Keberos 5 context. + * @param in krb5_rd_req_in_ctx to check the option on. + * @param flag flag to select if the keytab should be iterated (TRUE) or not (FALSE). + * + * @return Kerberos 5 error code, see krb5_get_error_message(). + * + * @ingroup krb5_auth + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_rd_req_in_set_iterate_keytab(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_boolean flag) +{ + in->iterate_keytab = flag; + return 0; +} + /** * Set if krb5_rq_red() is going to check the Windows PAC or not * @@ -917,6 +939,11 @@ krb5_rd_req_ctx(krb5_context context, &o->keyblock); if (ret) goto out; + } else if (id && inctx && inctx->iterate_keytab) { + /* + * Force iterating over the keytab. + */ + o->keyblock = NULL; } else { if(id == NULL) { diff --git a/source4/heimdal/lib/krb5/version-script.map b/source4/heimdal/lib/krb5/version-script.map index 7b49c15dfc0e..b18a1c5d7375 100644 --- a/source4/heimdal/lib/krb5/version-script.map +++ b/source4/heimdal/lib/krb5/version-script.map @@ -526,6 +526,7 @@ HEIMDAL_KRB5_2.0 { krb5_rd_req_ctx; krb5_rd_req_in_ctx_alloc; krb5_rd_req_in_ctx_free; + krb5_rd_req_in_set_iterate_keytab; krb5_rd_req_in_set_keyblock; krb5_rd_req_in_set_keytab; krb5_rd_req_in_set_pac_check; -- 2.17.1 From 1c6a70a94b46f363ddaf2371fe31ff08d4fe9fd9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 10:30:01 +0200 Subject: [PATCH 06/13] UPSTREAM-FIRST!!! HEIMDAL:lib/gssapi/krb5: add GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X This allows krb5_rd_req_in_set_iterate_keytab() to be used via the gssapi layer. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- .../heimdal/lib/gssapi/gssapi/gssapi_oid.h | 3 +++ .../lib/gssapi/krb5/accept_sec_context.c | 7 ++++++ .../heimdal/lib/gssapi/krb5/gsskrb5_locl.h | 1 + .../heimdal/lib/gssapi/krb5/set_cred_option.c | 22 +++++++++++++++++++ source4/heimdal/lib/gssapi/mech/gss_oid.c | 3 +++ source4/heimdal/lib/gssapi/version-script.map | 1 + 6 files changed, 37 insertions(+) diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_oid.h index 0eed639d53e1..48ff4035d854 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_cred_no_transit_check_x_oid_desc; #define GSS_KRB5_CRED_NO_TRANSIT_CHECK_X (&__gss_krb5_cred_no_transit_check_x_oid_desc) +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_iterate_acceptor_keytab_x_oid_desc; +#define GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X (&__gss_krb5_cred_iterate_acceptor_keytab_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) diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index 2e4ed53ba08e..d5865e5bdd71 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -398,11 +398,16 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, krb5_rd_req_in_ctx in = NULL; krb5_rd_req_out_ctx out = NULL; krb5_principal server = NULL; + krb5_boolean iterate_keytab = FALSE; krb5_flags verify_ap_req_flags = 0; if (acceptor_cred) { server = acceptor_cred->principal; + if (acceptor_cred->cred_flags & GSS_CF_ITERATE_ACCEPTOR_KEYTAB) { + iterate_keytab = TRUE; + } + if (acceptor_cred->cred_flags & GSS_CF_NO_TRANSIT_CHECK) { verify_ap_req_flags |= KRB5_VERIFY_AP_REQ_NO_TRANSITED_CHECK; } @@ -411,6 +416,8 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, kret = krb5_rd_req_in_ctx_alloc(context, &in); if (kret == 0) kret = krb5_rd_req_in_set_keytab(context, in, keytab); + if (kret == 0 && iterate_keytab) + kret = krb5_rd_req_in_set_iterate_keytab(context, in, TRUE); if (kret == 0) kret = krb5_rd_req_in_set_verify_ap_req_flags(context, in, verify_ap_req_flags); diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h index 6a1e977452cf..00b6f3405e29 100644 --- a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -95,6 +95,7 @@ typedef struct { #define GSS_CF_DESTROY_CRED_ON_RELEASE 1 #define GSS_CF_NO_CI_FLAGS 2 #define GSS_CF_NO_TRANSIT_CHECK 4 +#define GSS_CF_ITERATE_ACCEPTOR_KEYTAB 8 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 8d9f49884884..9ad17bfc322c 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -215,6 +215,25 @@ no_ci_flags(OM_uint32 *minor_status, } +static OM_uint32 +iterate_acceptor_keytab(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + 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_ITERATE_ACCEPTOR_KEYTAB; + + *minor_status = 0; + return GSS_S_COMPLETE; +} static OM_uint32 no_transit_check(OM_uint32 *minor_status, @@ -262,6 +281,9 @@ _gsskrb5_set_cred_option return no_ci_flags(minor_status, context, cred_handle, value); } + if (gss_oid_equal(desired_object, GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X)) { + return iterate_acceptor_keytab(minor_status, context, cred_handle, value); + } if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_TRANSIT_CHECK_X)) { return no_transit_check(minor_status, context, cred_handle, value); diff --git a/source4/heimdal/lib/gssapi/mech/gss_oid.c b/source4/heimdal/lib/gssapi/mech/gss_oid.c index 6f86eec65c39..de4ed2e571f3 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_oid.c +++ b/source4/heimdal/lib/gssapi/mech/gss_oid.c @@ -97,6 +97,9 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_import_cred_x_oid_desc = { 6, rk_UNC /* 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_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X - 1.2.752.43.13.31 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_cred_iterate_acceptor_keytab_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x20") }; + /* 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 776fe19dbf3c..6fcfce3ec5ea 100644 --- a/source4/heimdal/lib/gssapi/version-script.map +++ b/source4/heimdal/lib/gssapi/version-script.map @@ -153,6 +153,7 @@ HEIMDAL_GSS_2.0 { __gss_c_ntlm_v2_oid_desc; __gss_c_ntlm_session_key_oid_desc; __gss_c_ntlm_force_v1_oid_desc; + __gss_krb5_cred_iterate_acceptor_keytab_x_oid_desc; __gss_krb5_cred_no_ci_flags_x_oid_desc; __gss_krb5_cred_no_transit_check_x_oid_desc; __gss_krb5_import_cred_x_oid_desc; -- 2.17.1 From 5bca0ad99f20763f15cab60cce807f8e0778a673 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 16:09:47 +0000 Subject: [PATCH 07/13] s4:heimdal_build: define HAVE_GSS_KRB5_CRED_{NO_TRANSIT_CHECK,ITERATE_ACCEPTOR_KEYTAB}_X BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- source4/heimdal_build/wscript_configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/heimdal_build/wscript_configure b/source4/heimdal_build/wscript_configure index 903fb5139db8..57658b577a1a 100644 --- a/source4/heimdal_build/wscript_configure +++ b/source4/heimdal_build/wscript_configure @@ -87,6 +87,8 @@ conf.define('HAVE_GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT', 1) conf.define('HAVE_GSS_IMPORT_CRED', 1) conf.define('HAVE_GSS_EXPORT_CRED', 1) conf.define('HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X', 1) +conf.define('HAVE_GSS_KRB5_CRED_NO_TRANSIT_CHECK_X', 1) +conf.define('HAVE_GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X', 1) conf.define('HAVE_GSSAPI', 1) conf.define('HAVE_ADDR_TYPE_IN_KRB5_ADDRESS', 1) conf.define('HAVE_CHECKSUM_IN_KRB5_CHECKSUM', 1) -- 2.17.1 From ed3cf363e5e499ff14be7fe740ab71c2c4e6918c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 16:09:47 +0000 Subject: [PATCH 08/13] configure_mitkrb5: check for GSS_KRB5_CRED_NO_TRANSIT_CHECK_X BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- wscript_configure_system_mitkrb5 | 1 + 1 file changed, 1 insertion(+) diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5 index b05ac3f3e50c..bad6ce9a95d6 100644 --- a/wscript_configure_system_mitkrb5 +++ b/wscript_configure_system_mitkrb5 @@ -115,6 +115,7 @@ conf.CHECK_FUNCS_IN(''' gss_acquire_cred_from ''', 'gssapi gssapi_krb5') conf.CHECK_VARIABLE('GSS_KRB5_CRED_NO_CI_FLAGS_X', headers=possible_gssapi_headers) +conf.CHECK_VARIABLE('GSS_KRB5_CRED_NO_TRANSIT_CHECK_X', headers=possible_gssapi_headers) conf.CHECK_FUNCS_IN('krb5_mk_req_extended krb5_kt_compare', 'krb5') conf.CHECK_FUNCS(''' krb5_auth_con_getrecvsubkey -- 2.17.1 From acc0d6233edd830a2ab1c82fb0240eeb6dd131c4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Sep 2019 16:13:01 +0200 Subject: [PATCH 09/13] TODO: docs-xml: add "kerberos acceptor disable transited check" option TODO: I guess this should be the default without any option. We always get the service ticket (encrypted with the machine password) from our own [K]DC. Client realm and principal as well as the transited field are part of the encrypted ticket. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- .../kerberosacceptordisabletransitedcheck.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs-xml/smbdotconf/security/kerberosacceptordisabletransitedcheck.xml diff --git a/docs-xml/smbdotconf/security/kerberosacceptordisabletransitedcheck.xml b/docs-xml/smbdotconf/security/kerberosacceptordisabletransitedcheck.xml new file mode 100644 index 000000000000..2e459013d3a8 --- /dev/null +++ b/docs-xml/smbdotconf/security/kerberosacceptordisabletransitedcheck.xml @@ -0,0 +1,12 @@ + + + TODO: See https://bugzilla.samba.org/show_bug.cgi?id=12907 + + +no +yes + -- 2.17.1 From 31ec1cb9033b2ee5580ebf2a4de5ee5abbd22266 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 16:52:15 +0000 Subject: [PATCH 10/13] krb5_wrap: add smb_gss_krb5_prepare_acceptor_cred() BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- lib/krb5_wrap/gss_samba.c | 45 +++++++++++++++++++++++++++++++++++++++ lib/krb5_wrap/gss_samba.h | 4 ++++ 2 files changed, 49 insertions(+) diff --git a/lib/krb5_wrap/gss_samba.c b/lib/krb5_wrap/gss_samba.c index 2a99661ddee2..d3478a42dc4b 100644 --- a/lib/krb5_wrap/gss_samba.c +++ b/lib/krb5_wrap/gss_samba.c @@ -210,5 +210,50 @@ uint32_t smb_gss_krb5_import_cred(uint32_t *minor_status, krb5_context ctx, return major_status; } +uint32_t smb_gss_krb5_prepare_acceptor_cred(uint32_t *minor_status, + bool disable_transited_check, + gss_cred_id_t *cred) +{ +#ifdef HAVE_GSS_KRB5_CRED_NO_TRANSIT_CHECK_X + OM_uint32 gss_maj, gss_min; + gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; + gss_OID no_transit_oid = discard_const(GSS_KRB5_CRED_NO_TRANSIT_CHECK_X); +#ifdef HAVE_GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X /* only heimdal */ + gss_OID iterate_keytab_oid = + discard_const(GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X); + + gss_maj = gss_set_cred_option(&gss_min, cred, + iterate_keytab_oid, + &empty_buffer); + if (gss_maj) { + DBG_ERR("gss_set_cred_option(ITERATE_ACCEPTOR_KEYTAB_X)\n"); + *minor_status = gss_min; + return gss_maj; + } +#endif /* HAVE_GSS_KRB5_CRED_ITERATE_ACCEPTOR_KEYTAB_X */ + + if (!disable_transited_check) { + goto done; + } + + /* + * If we require a valid PAC we can + * skip the transit checks in the krb5 + * code. + */ + gss_maj = gss_set_cred_option(&gss_min, cred, + no_transit_oid, + &empty_buffer); + if (gss_maj) { + DBG_ERR("gss_set_cred_option(NO_TRANSIT_CHECK_X)\n"); + *minor_status = gss_min; + return gss_maj; + } + +done: +#endif /* HAVE_GSS_KRB5_CRED_NO_TRANSIT_CHECK_X */ + *minor_status = 0; + return 0; +} #endif /* HAVE_GSSAPI */ diff --git a/lib/krb5_wrap/gss_samba.h b/lib/krb5_wrap/gss_samba.h index 89aee3479c55..26fc268a0f60 100644 --- a/lib/krb5_wrap/gss_samba.h +++ b/lib/krb5_wrap/gss_samba.h @@ -45,5 +45,9 @@ uint32_t smb_gss_krb5_import_cred(OM_uint32 *minor_status, krb5_context ctx, krb5_ccache id, krb5_principal keytab_principal, krb5_keytab keytab, gss_cred_id_t *cred); +uint32_t smb_gss_krb5_prepare_acceptor_cred(uint32_t *minor_status, + bool disable_transited_check, + gss_cred_id_t *cred); + #endif /* HAVE_GSSAPI */ #endif /* _GSS_SAMBA_H */ -- 2.17.1 From f5e19f531f65621fe229af997f5b5b9aebc10d96 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 17:13:41 +0000 Subject: [PATCH 11/13] s3:gse: let gse_init_server() use smb_gss_krb5_prepare_acceptor_cred() We should check all keys in our in memory keytab and skip the transited checks if configured by "kerberos acceptor disable transited check = yes". BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- source3/librpc/crypto/gse.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index 9a9f4261222f..7d7cf3bdd180 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -576,6 +576,8 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, OM_uint32 gss_maj, gss_min; krb5_error_code ret; NTSTATUS status; + bool disable_transited_check = + lp_kerberos_acceptor_disable_transited_check(); status = gse_context_init(mem_ctx, do_sign, do_seal, NULL, add_gss_c_flags, &gse_ctx); @@ -602,6 +604,17 @@ static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, goto done; } + gss_maj = smb_gss_krb5_prepare_acceptor_cred(&gss_min, + disable_transited_check, + &gse_ctx->creds); + + if (gss_maj != 0) { + DEBUG(0, ("smb_gss_krb5_prepare_acceptor_cred failed with [%s]\n", + gse_errstr(gse_ctx, gss_maj, gss_min))); + status = NT_STATUS_INTERNAL_ERROR; + goto done; + } + status = NT_STATUS_OK; done: -- 2.17.1 From f50b727524fe47dee8ad0a6085353f57f0c52380 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 17:25:09 +0000 Subject: [PATCH 12/13] auth/credentials_krb5: let cli_credentials_get_server_gss_creds() use an early return This will simplify the next commits. Check with: git show -w BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 Signed-off-by: Stefan Metzmacher --- auth/credentials/credentials_krb5.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index 20e677e521a8..ae2a86c97ad9 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -1359,14 +1359,16 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, ret = EINVAL; } } - if (ret == 0) { - cred->server_gss_creds_obtained = cred->keytab_obtained; - talloc_set_destructor(gcc, free_gssapi_creds); - cred->server_gss_creds = gcc; - *_gcc = gcc; + if (ret != 0) { + talloc_free(mem_ctx); + return ret; } + cred->server_gss_creds_obtained = cred->keytab_obtained; + talloc_set_destructor(gcc, free_gssapi_creds); + cred->server_gss_creds = gcc; + *_gcc = gcc; talloc_free(mem_ctx); - return ret; + return 0; } /** -- 2.17.1 From ae8358cc15885fb4186fbfcb7735dc2dd05e807f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Aug 2019 17:25:30 +0000 Subject: [PATCH 13/13] auth/credentials_krb5: make use of smb_gss_krb5_prepare_acceptor_cred() We should check all keys in our in memory keytab and skip the transited checks if configured by "kerberos acceptor disable transited check = yes". BUG: https://bugzilla.samba.org/show_bug.cgi?id=12907 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14125 Signed-off-by: Stefan Metzmacher --- auth/credentials/credentials_krb5.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index ae2a86c97ad9..98982aacac9f 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -1303,6 +1303,8 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, krb5_principal princ; const char *error_string; enum credentials_obtained obtained; + bool disable_transited_check = + lpcfg_kerberos_acceptor_disable_transited_check(lp_ctx); mem_ctx = talloc_new(cred); if (!mem_ctx) { @@ -1363,6 +1365,20 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, talloc_free(mem_ctx); return ret; } + maj_stat = smb_gss_krb5_prepare_acceptor_cred(&min_stat, + disable_transited_check, + &gcc->creds); + if (maj_stat) { + if (min_stat) { + ret = min_stat; + } else { + ret = EINVAL; + } + } + if (ret != 0) { + talloc_free(mem_ctx); + return ret; + } cred->server_gss_creds_obtained = cred->keytab_obtained; talloc_set_destructor(gcc, free_gssapi_creds); cred->server_gss_creds = gcc; -- 2.17.1