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.
This commit is contained in:
@@ -41,6 +41,8 @@
|
|||||||
#include "gss_preauth_authorizer_plugin.h"
|
#include "gss_preauth_authorizer_plugin.h"
|
||||||
|
|
||||||
struct gss_client_params {
|
struct gss_client_params {
|
||||||
|
OM_uint32 major_status;
|
||||||
|
OM_uint32 minor_status;
|
||||||
gss_ctx_id_t context_handle;
|
gss_ctx_id_t context_handle;
|
||||||
gss_name_t initiator_name;
|
gss_name_t initiator_name;
|
||||||
gss_OID mech_type;
|
gss_OID mech_type;
|
||||||
@@ -215,6 +217,8 @@ _kdc_gss_rd_padata(astgs_request_t r,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcp->major_status = GSS_S_NO_CONTEXT;
|
||||||
|
|
||||||
ret = pa_gss_get_context_state(r, gcp);
|
ret = pa_gss_get_context_state(r, gcp);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -242,6 +246,10 @@ _kdc_gss_rd_padata(astgs_request_t r,
|
|||||||
&gcp->flags,
|
&gcp->flags,
|
||||||
&gcp->lifetime,
|
&gcp->lifetime,
|
||||||
NULL); /* delegated_cred_handle */
|
NULL); /* delegated_cred_handle */
|
||||||
|
|
||||||
|
gcp->major_status = major;
|
||||||
|
gcp->minor_status = minor;
|
||||||
|
|
||||||
if (GSS_ERROR(major)) {
|
if (GSS_ERROR(major)) {
|
||||||
pa_gss_display_status(r, major, minor, gcp,
|
pa_gss_display_status(r, major, minor, gcp,
|
||||||
"Failed to accept GSS security context");
|
"Failed to accept GSS security context");
|
||||||
@@ -256,7 +264,7 @@ _kdc_gss_rd_padata(astgs_request_t r,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*open = (major == GSS_S_COMPLETE);
|
*open = (gcp->major_status == GSS_S_COMPLETE);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
gss_release_cred(&minor, &cred);
|
gss_release_cred(&minor, &cred);
|
||||||
@@ -567,26 +575,7 @@ _kdc_gss_mk_pa_reply(astgs_request_t r,
|
|||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
const KDC_REQ *req = &r->req;
|
const KDC_REQ *req = &r->req;
|
||||||
|
|
||||||
OM_uint32 major, minor;
|
if (gcp->major_status == GSS_S_COMPLETE) {
|
||||||
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) {
|
|
||||||
krb5_enctype enctype;
|
krb5_enctype enctype;
|
||||||
uint32_t kfe = 0;
|
uint32_t kfe = 0;
|
||||||
krb5_keyblock *reply_key = NULL;
|
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);
|
krb5_free_keyblock_contents(r->context, &r->reply_key);
|
||||||
r->reply_key = *reply_key;
|
r->reply_key = *reply_key;
|
||||||
free(reply_key);
|
free(reply_key);
|
||||||
} else {
|
} else if (gcp->major_status == GSS_S_CONTINUE_NEEDED) {
|
||||||
ret = pa_gss_set_context_state(r, gcp);
|
ret = pa_gss_set_context_state(r, gcp);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = krb5_padata_add(r->context, &r->outpadata, KRB5_PADATA_GSS,
|
/* only return padata in error case if we have an error token */
|
||||||
gcp->output_token.value, gcp->output_token.length);
|
if (!GSS_ERROR(gcp->major_status) || gcp->output_token.length) {
|
||||||
if (ret)
|
ret = krb5_padata_add(r->context, &r->outpadata, KRB5_PADATA_GSS,
|
||||||
goto out;
|
gcp->output_token.value, gcp->output_token.length);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* token is now owned by outpadata */
|
/* token is now owned by outpadata */
|
||||||
gcp->output_token.length = 0;
|
gcp->output_token.length = 0;
|
||||||
gcp->output_token.value = NULL;
|
gcp->output_token.value = NULL;
|
||||||
|
|
||||||
if (!open)
|
if (gcp->major_status == GSS_S_CONTINUE_NEEDED)
|
||||||
ret = KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED;
|
ret = KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED;
|
||||||
|
else
|
||||||
|
ret = _krb5_gss_map_error(gcp->major_status, gcp->minor_status);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -514,14 +514,11 @@ pa_gss_validate(astgs_request_t r, const PA_DATA *pa)
|
|||||||
gss_client_params *gcp = NULL;
|
gss_client_params *gcp = NULL;
|
||||||
char *client_name = NULL;
|
char *client_name = NULL;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
int open;
|
int open = 0;
|
||||||
|
|
||||||
ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
|
ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
|
||||||
if (ret) {
|
if (ret && gcp == NULL)
|
||||||
_kdc_r_log(r, 4, "Failed to decode GSS PA-DATA -- %s",
|
return ret;
|
||||||
r->cname);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open) {
|
if (open) {
|
||||||
ret = _kdc_gss_check_client(r, gcp, &client_name);
|
ret = _kdc_gss_check_client(r, gcp, &client_name);
|
||||||
|
Reference in New Issue
Block a user