From a550317253966c6feded683a859f8c50f298be74 Mon Sep 17 00:00:00 2001 From: Andrew Kroeger Date: Wed, 12 Mar 2008 23:11:48 -0500 Subject: heimdal: Add parameter to windc_plugin to allow extended return codes. These changes add a krb5_data parameter named e_data to the windc_plugin to allow the samba KDC to return extended error information in addition to the standard KRB5KDC_ERR_* codes. Windows uses the extended information to provide detailed information in user dialogs (e.g. account disabled, logon hours restriction, must change password, etc.). This particular commit modifies only heimdal code. Hopefully this can be submitted and accepted into the upstream heimdal codebase. (This used to be commit f542362be25e7182a0836de7a0163f6b9fce9408) --- source4/heimdal/kdc/kdc-private.h | 3 ++- source4/heimdal/kdc/kerberos5.c | 2 +- source4/heimdal/kdc/windc.c | 5 +++-- source4/heimdal/kdc/windc_plugin.h | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source4') diff --git a/source4/heimdal/kdc/kdc-private.h b/source4/heimdal/kdc/kdc-private.h index 030be9ae58..4052e9b509 100644 --- a/source4/heimdal/kdc/kdc-private.h +++ b/source4/heimdal/kdc/kdc-private.h @@ -281,6 +281,7 @@ krb5_error_code _kdc_windc_client_access ( krb5_context /*context*/, struct hdb_entry_ex */*client*/, - KDC_REQ */*req*/); + KDC_REQ */*req*/, + krb5_data */*e_data*/); #endif /* __kdc_private_h__ */ diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 40a9c9c972..23ca5a035e 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -1043,7 +1043,7 @@ _kdc_as_rep(krb5_context context, goto out; } - ret = _kdc_windc_client_access(context, client, req); + ret = _kdc_windc_client_access(context, client, req, &e_data); if(ret) goto out; diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index 395ab73432..85e4d7f725 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -101,9 +101,10 @@ _kdc_pac_verify(krb5_context context, krb5_error_code _kdc_windc_client_access(krb5_context context, struct hdb_entry_ex *client, - KDC_REQ *req) + KDC_REQ *req, + krb5_data *e_data) { if (windcft == NULL) return 0; - return (windcft->client_access)(windcctx, context, client, req); + return (windcft->client_access)(windcctx, context, client, req, e_data); } diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index ec480cf950..3ae0c94681 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -64,7 +64,7 @@ typedef krb5_error_code typedef krb5_error_code (*krb5plugin_windc_client_access)( - void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *); + void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *, krb5_data *); #define KRB5_WINDC_PLUGING_MINOR 2 -- cgit From 131111f16615177d4e7f999d740a94ca6b07e01e Mon Sep 17 00:00:00 2001 From: Andrew Kroeger Date: Wed, 12 Mar 2008 23:21:14 -0500 Subject: kdc: Provide extended error information in AS-REP error replies. This change utilizes the addition of the e_data parameter to the windc_plugin in the heimdal code to pass extended information back to the client. The extended information is provided in an e-data block as part of the kerberos error message, and allows the client to determine which specific error condition occurred. (This used to be commit 502466ba950bfd104518b9eb9586896c1e076343) --- source4/kdc/pac-glue.c | 67 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 17 deletions(-) (limited to 'source4') diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 66f36af870..f65bd67ab1 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -220,13 +220,48 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context, return ret; } +static void samba_kdc_build_edata_reply(TALLOC_CTX *tmp_ctx, krb5_data *e_data, + NTSTATUS nt_status) +{ + PA_DATA pa; + unsigned char *buf; + size_t len; + krb5_error_code ret = 0; + uint32_t *tmp; + + if (!e_data) + return; + + pa.padata_type = KRB5_PADATA_PW_SALT; + pa.padata_value.length = 12; + pa.padata_value.data = malloc(pa.padata_value.length); + if (!pa.padata_value.data) { + e_data->length = 0; + e_data->data = NULL; + return; + } + + SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status)); + SIVAL(pa.padata_value.data, 4, 0); + SIVAL(pa.padata_value.data, 8, 1); + + ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret); + free(pa.padata_value.data); + + e_data->data = buf; + e_data->length = len; + + return; +} + /* Given an hdb entry (and in particular it's private member), consult * the account_ok routine in auth/auth_sam.c for consistancy */ krb5_error_code samba_kdc_check_client_access(void *priv, krb5_context context, hdb_entry_ex *entry_ex, - KDC_REQ *req) + KDC_REQ *req, + krb5_data *e_data) { krb5_error_code ret; NTSTATUS nt_status; @@ -274,30 +309,28 @@ krb5_error_code samba_kdc_check_client_access(void *priv, name); free(name); - /* TODO: Need a more complete mapping of NTSTATUS to krb5kdc errors */ - - /* TODO: Also need to add the appropriate e-data struct of type - * PA-PW-SALT (3) that includes the NT_STATUS code, which gives Windows - * the information it needs to display the appropriate dialog. */ + if (NT_STATUS_IS_OK(nt_status)) + return 0; if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) - return KRB5KDC_ERR_KEY_EXPIRED; + ret = KRB5KDC_ERR_KEY_EXPIRED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) - return KRB5KDC_ERR_KEY_EXPIRED; + ret = KRB5KDC_ERR_KEY_EXPIRED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) - return KRB5KDC_ERR_CLIENT_REVOKED; + ret = KRB5KDC_ERR_CLIENT_REVOKED; else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION)) - return KRB5KDC_ERR_POLICY; - else if (!NT_STATUS_IS_OK(nt_status)) { - return KRB5KDC_ERR_POLICY; - } + ret = KRB5KDC_ERR_POLICY; + else + ret = KRB5KDC_ERR_POLICY; - return 0; + samba_kdc_build_edata_reply(tmp_ctx, e_data, nt_status); + + return ret; } -- cgit