From df9e74b292853060b19cd8a2cdd668c5c6aa3909 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 15 Aug 2021 15:39:58 +1000 Subject: [PATCH] kdc: allow GSS error tokens in PA reply If GSS_Accept_sec_context() returns an error status and error token, ensure we include the error token in the PA-GSS padata in the KRB-ERROR reply, rather than bailing out early. --- kdc/gss_preauth.c | 48 +++++++++++++++++++++-------------------------- kdc/kerberos5.c | 9 +++------ 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/kdc/gss_preauth.c b/kdc/gss_preauth.c index d4d673f50..d7b2690c4 100644 --- a/kdc/gss_preauth.c +++ b/kdc/gss_preauth.c @@ -41,6 +41,8 @@ #include "gss_preauth_authorizer_plugin.h" struct gss_client_params { + OM_uint32 major_status; + OM_uint32 minor_status; gss_ctx_id_t context_handle; gss_name_t initiator_name; gss_OID mech_type; @@ -215,6 +217,8 @@ _kdc_gss_rd_padata(astgs_request_t r, goto out; } + gcp->major_status = GSS_S_NO_CONTEXT; + ret = pa_gss_get_context_state(r, gcp); if (ret) goto out; @@ -242,6 +246,10 @@ _kdc_gss_rd_padata(astgs_request_t r, &gcp->flags, &gcp->lifetime, NULL); /* delegated_cred_handle */ + + gcp->major_status = major; + gcp->minor_status = minor; + if (GSS_ERROR(major)) { pa_gss_display_status(r, major, minor, gcp, "Failed to accept GSS security context"); @@ -256,7 +264,7 @@ _kdc_gss_rd_padata(astgs_request_t r, goto out; } - *open = (major == GSS_S_COMPLETE); + *open = (gcp->major_status == GSS_S_COMPLETE); out: gss_release_cred(&minor, &cred); @@ -567,26 +575,7 @@ _kdc_gss_mk_pa_reply(astgs_request_t r, krb5_error_code ret; const KDC_REQ *req = &r->req; - OM_uint32 major, minor; - int open; - - major = gss_inquire_context(&minor, - gcp->context_handle, - NULL, /* initiator_name */ - NULL, /* target_name */ - NULL, /* lifetime_req */ - NULL, /* mech_type */ - NULL, /* ctx_flags */ - NULL, /* locally_initiated */ - &open); - if (GSS_ERROR(major)) { - pa_gss_display_status(r, major, minor, gcp, - "Failed to inquire GSS context"); - ret = _krb5_gss_map_error(major, minor); - goto out; - } - - if (open) { + if (gcp->major_status == GSS_S_COMPLETE) { krb5_enctype enctype; uint32_t kfe = 0; krb5_keyblock *reply_key = NULL; @@ -611,23 +600,28 @@ _kdc_gss_mk_pa_reply(astgs_request_t r, krb5_free_keyblock_contents(r->context, &r->reply_key); r->reply_key = *reply_key; free(reply_key); - } else { + } else if (gcp->major_status == GSS_S_CONTINUE_NEEDED) { ret = pa_gss_set_context_state(r, gcp); if (ret) goto out; } - ret = krb5_padata_add(r->context, &r->outpadata, KRB5_PADATA_GSS, - gcp->output_token.value, gcp->output_token.length); - if (ret) - goto out; + /* only return padata in error case if we have an error token */ + if (!GSS_ERROR(gcp->major_status) || gcp->output_token.length) { + ret = krb5_padata_add(r->context, &r->outpadata, KRB5_PADATA_GSS, + gcp->output_token.value, gcp->output_token.length); + if (ret) + goto out; + } /* token is now owned by outpadata */ gcp->output_token.length = 0; gcp->output_token.value = NULL; - if (!open) + if (gcp->major_status == GSS_S_CONTINUE_NEEDED) ret = KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED; + else + ret = _krb5_gss_map_error(gcp->major_status, gcp->minor_status); out: return ret; diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index f0cc2bdba..12e19b599 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -514,14 +514,11 @@ pa_gss_validate(astgs_request_t r, const PA_DATA *pa) gss_client_params *gcp = NULL; char *client_name = NULL; krb5_error_code ret; - int open; + int open = 0; ret = _kdc_gss_rd_padata(r, pa, &gcp, &open); - if (ret) { - _kdc_r_log(r, 4, "Failed to decode GSS PA-DATA -- %s", - r->cname); - goto out; - } + if (ret && gcp == NULL) + return ret; if (open) { ret = _kdc_gss_check_client(r, gcp, &client_name);