summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/auth.h3
-rw-r--r--source4/auth/ntlm/auth_sam.c2
-rw-r--r--source4/auth/sam.c11
-rw-r--r--source4/heimdal/kdc/headers.h1
-rw-r--r--source4/heimdal/kdc/kdc_locl.h1
-rw-r--r--source4/heimdal/kdc/kerberos5.c22
-rw-r--r--source4/heimdal/kdc/krb5tgs.c8
-rw-r--r--source4/heimdal/kdc/windc.c22
-rw-r--r--source4/heimdal/kdc/windc_plugin.h8
-rw-r--r--source4/kdc/hdb-samba4.c13
-rw-r--r--source4/kdc/kdc.h2
-rw-r--r--source4/kdc/pac-glue.c75
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;
}