diff options
-rw-r--r-- | source4/auth/auth.h | 3 | ||||
-rw-r--r-- | source4/auth/ntlm/auth_sam.c | 2 | ||||
-rw-r--r-- | source4/auth/sam.c | 11 | ||||
-rw-r--r-- | source4/heimdal/kdc/headers.h | 1 | ||||
-rw-r--r-- | source4/heimdal/kdc/kdc_locl.h | 1 | ||||
-rw-r--r-- | source4/heimdal/kdc/kerberos5.c | 22 | ||||
-rw-r--r-- | source4/heimdal/kdc/krb5tgs.c | 8 | ||||
-rw-r--r-- | source4/heimdal/kdc/windc.c | 22 | ||||
-rw-r--r-- | source4/heimdal/kdc/windc_plugin.h | 8 | ||||
-rw-r--r-- | source4/kdc/hdb-samba4.c | 13 | ||||
-rw-r--r-- | source4/kdc/kdc.h | 2 | ||||
-rw-r--r-- | source4/kdc/pac-glue.c | 75 |
12 files changed, 98 insertions, 70 deletions
diff --git a/source4/auth/auth.h b/source4/auth/auth.h index f6d739325d..6bad017862 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -232,7 +232,8 @@ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *logon_workstation, const char *name_for_logs, - bool allow_domain_trust); + bool allow_domain_trust, + bool password_change); struct auth_session_info *system_session(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, const char *netbios_name, diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index 0bb79e234c..253ddf2286 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -175,7 +175,7 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, msg, user_info->workstation_name, user_info->mapped.account_name, - false); + false, false); return nt_status; } diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 68eaacf255..acbd50c3fa 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -147,7 +147,8 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *logon_workstation, const char *name_for_logs, - bool allow_domain_trust) + bool allow_domain_trust, + bool password_change) { uint16_t acct_flags; const char *workstation_list; @@ -189,15 +190,15 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCOUNT_EXPIRED; } - /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0) { + /* check for immediate expiry "must change at next logon" (but not if this is a password change request) */ + if ((must_change_time == 0) && !password_change) { DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", name_for_logs)); return NT_STATUS_PASSWORD_MUST_CHANGE; } - /* check for expired password */ - if (must_change_time < now) { + /* check for expired password (but not if this is a password change request) */ + if ((must_change_time < now) && !password_change) { DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", name_for_logs)); DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", diff --git a/source4/heimdal/kdc/headers.h b/source4/heimdal/kdc/headers.h index 2240336e31..b9a828852a 100644 --- a/source4/heimdal/kdc/headers.h +++ b/source4/heimdal/kdc/headers.h @@ -104,6 +104,7 @@ #ifndef NO_NTLM #include <heimntlm.h> #endif +#include <kdc.h> #include <windc_plugin.h> #undef ALLOC diff --git a/source4/heimdal/kdc/kdc_locl.h b/source4/heimdal/kdc/kdc_locl.h index 9b291ac896..daf155839c 100644 --- a/source4/heimdal/kdc/kdc_locl.h +++ b/source4/heimdal/kdc/kdc_locl.h @@ -39,7 +39,6 @@ #define __KDC_LOCL_H__ #include "headers.h" -#include "kdc.h" typedef struct pk_client_params pk_client_params; struct DigestREQ; diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 941a2e0572..ac495b1ac7 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -668,11 +668,11 @@ log_as_req(krb5_context context, */ krb5_error_code -_kdc_check_flags(krb5_context context, - krb5_kdc_configuration *config, - hdb_entry_ex *client_ex, const char *client_name, - hdb_entry_ex *server_ex, const char *server_name, - krb5_boolean is_as_req) +kdc_check_flags(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *client_ex, const char *client_name, + hdb_entry_ex *server_ex, const char *server_name, + krb5_boolean is_as_req) { if(client_ex != NULL) { hdb_entry *client = &client_ex->entry; @@ -921,7 +921,6 @@ _kdc_as_rep(krb5_context context, "AS-REQ malformed server name from %s", from); goto out; } - if(b->cname == NULL){ ret = KRB5KRB_ERR_GENERIC; e_text = "No client in request"; @@ -1345,14 +1344,9 @@ _kdc_as_rep(krb5_context context, * with in a preauth mech. */ - ret = _kdc_check_flags(context, config, - client, client_name, - server, server_name, - TRUE); - if(ret) - goto out; - - ret = _kdc_windc_client_access(context, client, req, &e_data); + ret = _kdc_check_access(context, config, client, client_name, + server, server_name, + req, &e_data); if(ret) goto out; diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 3abdb18ae4..59104da3d6 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1860,10 +1860,10 @@ server_lookup: * Check flags */ - ret = _kdc_check_flags(context, config, - client, cpn, - server, spn, - FALSE); + ret = kdc_check_flags(context, config, + client, cpn, + server, spn, + FALSE); if(ret) goto out; diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index fe3cd997e7..9d7fa52cea 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -99,12 +99,22 @@ _kdc_pac_verify(krb5_context context, } krb5_error_code -_kdc_windc_client_access(krb5_context context, - struct hdb_entry_ex *client, - KDC_REQ *req, - krb5_data *e_data) +_kdc_check_access(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *client_ex, const char *client_name, + hdb_entry_ex *server_ex, const char *server_name, + KDC_REQ *req, + krb5_data *e_data) { if (windcft == NULL) - return 0; - return (windcft->client_access)(windcctx, context, client, req, e_data); + return kdc_check_flags(context, config, + client_ex, client_name, + server_ex, server_name, + req->msg_type == krb_as_req); + + return (windcft->client_access)(windcctx, + context, config, + client_ex, client_name, + server_ex, server_name, + req, e_data); } diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index 34016694b2..c7efb7b852 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -64,10 +64,14 @@ typedef krb5_error_code typedef krb5_error_code (*krb5plugin_windc_client_access)( - void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *, krb5_data *); + void *, krb5_context, + krb5_kdc_configuration *config, + hdb_entry_ex *, const char *, + hdb_entry_ex *, const char *, + KDC_REQ *, krb5_data *); -#define KRB5_WINDC_PLUGING_MINOR 3 +#define KRB5_WINDC_PLUGING_MINOR 4 typedef struct krb5plugin_windc_ftable { int minor_version; diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index c0fa5132d1..eda7867bb5 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -627,7 +627,18 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, entry_ex->entry.flags.invalid = 0; entry_ex->entry.flags.server = 1; - entry_ex->entry.flags.change_pw = 1; + + /* Don't mark all requests for the krbtgt/realm as + * 'change password', as otherwise we could get into + * trouble, and not enforce the password expirty. + * Instead, only do it when request is for the kpasswd service */ + if (ent_type == HDB_SAMBA4_ENT_TYPE_SERVER + && principal->name.name_string.len == 2 + && (strcmp(principal->name.name_string.val[0], "kadmin") == 0) + && (strcmp(principal->name.name_string.val[1], "changepw") == 0) + && lp_is_my_domain_or_realm(lp_ctx, principal->realm)) { + entry_ex->entry.flags.change_pw = 1; + } entry_ex->entry.flags.client = 0; entry_ex->entry.flags.forwardable = 1; entry_ex->entry.flags.ok_as_delegate = 1; diff --git a/source4/kdc/kdc.h b/source4/kdc/kdc.h index a281e1d9c9..d37a32ebbf 100644 --- a/source4/kdc/kdc.h +++ b/source4/kdc/kdc.h @@ -22,8 +22,8 @@ #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" -#include <kdc.h> #include <hdb.h> +#include <kdc.h> #include <krb5/windc_plugin.h> #include "kdc/pac_glue.h" diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 411e752c04..5bd4cb10c7 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -231,28 +231,29 @@ static void samba_kdc_build_edata_reply(TALLOC_CTX *tmp_ctx, krb5_data *e_data, krb5_error_code samba_kdc_check_client_access(void *priv, - krb5_context context, hdb_entry_ex *entry_ex, + krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *client_ex, const char *client_name, + hdb_entry_ex *server_ex, const char *server_name, KDC_REQ *req, krb5_data *e_data) { krb5_error_code ret; NTSTATUS nt_status; - TALLOC_CTX *tmp_ctx = talloc_new(entry_ex->ctx); - struct hdb_ldb_private *p = talloc_get_type(entry_ex->ctx, struct hdb_ldb_private); - char *name, *workstation = NULL; + TALLOC_CTX *tmp_ctx; + struct hdb_ldb_private *p; + char *workstation = NULL; HostAddresses *addresses = req->req_body.addresses; int i; + bool password_change; + + tmp_ctx = talloc_new(client_ex->ctx); + p = talloc_get_type(client_ex->ctx, struct hdb_ldb_private); if (!tmp_ctx) { return ENOMEM; } - ret = krb5_unparse_name(context, entry_ex->entry.principal, &name); - if (ret != 0) { - talloc_free(tmp_ctx); - return ret; - } - if (addresses) { for (i=0; i < addresses->len; i++) { if (addresses->val->addr_type == KRB5_ADDRESS_NETBIOS) { @@ -272,6 +273,8 @@ krb5_error_code samba_kdc_check_client_access(void *priv, } } + password_change = (server_ex && server_ex->entry.flags.change_pw); + /* we allow all kinds of trusts here */ nt_status = authsam_account_ok(tmp_ctx, p->samdb, @@ -279,30 +282,34 @@ krb5_error_code samba_kdc_check_client_access(void *priv, p->realm_dn, p->msg, workstation, - name, true); - free(name); - - if (NT_STATUS_IS_OK(nt_status)) - return 0; - - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) - ret = KRB5KDC_ERR_KEY_EXPIRED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) - ret = KRB5KDC_ERR_KEY_EXPIRED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) - ret = KRB5KDC_ERR_CLIENT_REVOKED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) - ret = KRB5KDC_ERR_CLIENT_REVOKED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS)) - ret = KRB5KDC_ERR_CLIENT_REVOKED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) - ret = KRB5KDC_ERR_CLIENT_REVOKED; - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION)) - ret = KRB5KDC_ERR_POLICY; - else - ret = KRB5KDC_ERR_POLICY; - - samba_kdc_build_edata_reply(tmp_ctx, e_data, nt_status); + client_name, true, password_change); + + if (NT_STATUS_IS_OK(nt_status)) { + /* Now do the standard Heimdal check */ + ret = kdc_check_flags(context, config, + client_ex, client_name, + server_ex, server_name, + req->msg_type == krb_as_req); + } else { + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) + ret = KRB5KDC_ERR_KEY_EXPIRED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) + ret = KRB5KDC_ERR_KEY_EXPIRED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) + ret = KRB5KDC_ERR_CLIENT_REVOKED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) + ret = KRB5KDC_ERR_CLIENT_REVOKED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS)) + ret = KRB5KDC_ERR_CLIENT_REVOKED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) + ret = KRB5KDC_ERR_CLIENT_REVOKED; + else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION)) + ret = KRB5KDC_ERR_POLICY; + else + ret = KRB5KDC_ERR_POLICY; + + samba_kdc_build_edata_reply(tmp_ctx, e_data, nt_status); + } return ret; } |