summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2008-11-27 17:49:25 +0100
committerGünther Deschner <gd@samba.org>2009-03-20 10:39:18 +0100
commit842edcd2b08763a35dbdea3518fcc039aa70aad4 (patch)
tree7320544aa8e6f624de6c5c41c8fd9868be5fe668 /source3/rpc_server
parentda46c371006d7cb5bceba790070d805b303ade98 (diff)
downloadsamba-842edcd2b08763a35dbdea3518fcc039aa70aad4.tar.gz
samba-842edcd2b08763a35dbdea3518fcc039aa70aad4.tar.bz2
samba-842edcd2b08763a35dbdea3518fcc039aa70aad4.zip
s3-samr: try to to fix password_expired flag handling.
Guenther
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_samr_nt.c120
-rw-r--r--source3/rpc_server/srv_samr_util.c87
2 files changed, 155 insertions, 52 deletions
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index dcbd0963c4..c60d904b18 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -3636,12 +3636,7 @@ static NTSTATUS set_user_info_18(struct samr_UserInfo18 *id18,
pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
}
- if (id18->password_expired) {
- pdb_set_pass_last_set_time(pwd, 0, PDB_CHANGED);
- } else {
- /* FIXME */
- pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
- }
+ copy_id18_to_sam_passwd(pwd, id18);
return pdb_update_sam_account(pwd);
}
@@ -3848,23 +3843,16 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx,
set_user_info_pw
********************************************************************/
-static bool set_user_info_pw(uint8 *pass, struct samu *pwd,
- int level)
+static bool set_user_info_pw(uint8 *pass, struct samu *pwd)
{
uint32 len = 0;
char *plaintext_buf = NULL;
uint32 acct_ctrl;
- time_t last_set_time;
- enum pdb_value_state last_set_state;
DEBUG(5, ("Attempting administrator password change for user %s\n",
pdb_get_username(pwd)));
acct_ctrl = pdb_get_acct_ctrl(pwd);
- /* we need to know if it's expired, because this is an admin change, not a
- user change, so it's still expired when we're done */
- last_set_state = pdb_get_init_flags(pwd, PDB_PASSLASTSET);
- last_set_time = pdb_get_pass_last_set_time(pwd);
if (!decode_pw_buffer(talloc_tos(),
pass,
@@ -3907,29 +3895,38 @@ static bool set_user_info_pw(uint8 *pass, struct samu *pwd,
memset(plaintext_buf, '\0', strlen(plaintext_buf));
- /*
- * A level 25 change does reset the pwdlastset field, a level 24
- * change does not. I know this is probably not the full story, but
- * it is needed to make XP join LDAP correctly, without it the later
- * auth2 check can fail with PWD_MUST_CHANGE.
- */
- if (level != 25) {
- /*
- * restore last set time as this is an admin change, not a
- * user pw change
- */
- pdb_set_pass_last_set_time (pwd, last_set_time,
- last_set_state);
+ DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
+
+ return True;
+}
+
+/*******************************************************************
+ set_user_info_24
+ ********************************************************************/
+
+static NTSTATUS set_user_info_24(TALLOC_CTX *mem_ctx,
+ struct samr_UserInfo24 *id24,
+ struct samu *pwd)
+{
+ NTSTATUS status;
+
+ if (id24 == NULL) {
+ DEBUG(5, ("set_user_info_24: NULL id24\n"));
+ return NT_STATUS_INVALID_PARAMETER;
}
- DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
+ if (!set_user_info_pw(id24->password.data, pwd)) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
- /* update the SAMBA password */
- if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
- return False;
+ copy_id24_to_sam_passwd(pwd, id24);
+
+ status = pdb_update_sam_account(pwd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- return True;
+ return NT_STATUS_OK;
}
/*******************************************************************
@@ -3955,6 +3952,14 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx,
return NT_STATUS_ACCESS_DENIED;
}
+ if ((id25->info.fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (id25->info.fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)) {
+
+ if (!set_user_info_pw(id25->password.data, pwd)) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+ }
+
copy_id25_to_sam_passwd(pwd, id25);
/* write the change out */
@@ -3981,6 +3986,36 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx,
}
/*******************************************************************
+ set_user_info_26
+ ********************************************************************/
+
+static NTSTATUS set_user_info_26(TALLOC_CTX *mem_ctx,
+ struct samr_UserInfo26 *id26,
+ struct samu *pwd)
+{
+ NTSTATUS status;
+
+ if (id26 == NULL) {
+ DEBUG(5, ("set_user_info_26: NULL id26\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!set_user_info_pw(id26->password.data, pwd)) {
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ copy_id26_to_sam_passwd(pwd, id26);
+
+ status = pdb_update_sam_account(pwd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*******************************************************************
samr_SetUserInfo
********************************************************************/
@@ -4139,10 +4174,8 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p,
dump_data(100, info->info24.password.data, 516);
- if (!set_user_info_pw(info->info24.password.data, pwd,
- switch_value)) {
- status = NT_STATUS_WRONG_PASSWORD;
- }
+ status = set_user_info_24(p->mem_ctx,
+ &info->info24, pwd);
break;
case 25:
@@ -4157,13 +4190,6 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p,
status = set_user_info_25(p->mem_ctx,
&info->info25, pwd);
- if (!NT_STATUS_IS_OK(status)) {
- goto done;
- }
- if (!set_user_info_pw(info->info25.password.data, pwd,
- switch_value)) {
- status = NT_STATUS_WRONG_PASSWORD;
- }
break;
case 26:
@@ -4176,18 +4202,14 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p,
dump_data(100, info->info26.password.data, 516);
- if (!set_user_info_pw(info->info26.password.data, pwd,
- switch_value)) {
- status = NT_STATUS_WRONG_PASSWORD;
- }
+ status = set_user_info_26(p->mem_ctx,
+ &info->info26, pwd);
break;
default:
status = NT_STATUS_INVALID_INFO_CLASS;
}
- done:
-
TALLOC_FREE(pwd);
if (has_enough_rights) {
diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c
index ef588aed1a..068156054f 100644
--- a/source3/rpc_server/srv_samr_util.c
+++ b/source3/rpc_server/srv_samr_util.c
@@ -36,6 +36,27 @@
((s1) && (s2) && (strcmp((s1), (s2)) != 0))
/*************************************************************
+ Copies a struct samr_UserInfo18 to a struct samu
+**************************************************************/
+
+void copy_id18_to_sam_passwd(struct samu *to,
+ struct samr_UserInfo18 *from)
+{
+ struct samr_UserInfo21 i;
+
+ if (from == NULL || to == NULL) {
+ return;
+ }
+
+ ZERO_STRUCT(i);
+
+ i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
+ i.password_expired = from->password_expired;
+
+ copy_id21_to_sam_passwd("INFO_18", to, &i);
+}
+
+/*************************************************************
Copies a struct samr_UserInfo20 to a struct samu
**************************************************************/
@@ -336,7 +357,7 @@ void copy_id21_to_sam_passwd(const char *log_prefix,
if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) {
DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l,
from->password_expired));
- if (from->password_expired == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
+ if (from->password_expired != 0) {
pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
} else {
/* A subtlety here: some windows commands will
@@ -345,9 +366,27 @@ void copy_id21_to_sam_passwd(const char *log_prefix,
in these caess. "net user /dom <user> /active:y"
for example, to clear an autolocked acct.
We must check to see if it's expired first. jmcd */
+
+ uint32_t pwd_max_age = 0;
+ time_t now = time(NULL);
+
+ pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &pwd_max_age);
+
+ if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) {
+ pwd_max_age = get_time_t_max();
+ }
+
stored_time = pdb_get_pass_last_set_time(to);
- if (stored_time == 0)
- pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
+
+ /* we will only *set* a pwdlastset date when
+ a) the last pwdlastset time was 0 (user was forced to
+ change password).
+ b) the users password has not expired. gd. */
+
+ if ((stored_time == 0) ||
+ ((now - stored_time) > pwd_max_age)) {
+ pdb_set_pass_last_set_time(to, now, PDB_CHANGED);
+ }
}
}
}
@@ -368,6 +407,27 @@ void copy_id23_to_sam_passwd(struct samu *to,
}
/*************************************************************
+ Copies a struct samr_UserInfo24 to a struct samu
+**************************************************************/
+
+void copy_id24_to_sam_passwd(struct samu *to,
+ struct samr_UserInfo24 *from)
+{
+ struct samr_UserInfo21 i;
+
+ if (from == NULL || to == NULL) {
+ return;
+ }
+
+ ZERO_STRUCT(i);
+
+ i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
+ i.password_expired = from->password_expired;
+
+ copy_id21_to_sam_passwd("INFO_24", to, &i);
+}
+
+/*************************************************************
Copies a struct samr_UserInfo25 to a struct samu
**************************************************************/
@@ -380,3 +440,24 @@ void copy_id25_to_sam_passwd(struct samu *to,
copy_id21_to_sam_passwd("INFO_25", to, &from->info);
}
+
+/*************************************************************
+ Copies a struct samr_UserInfo26 to a struct samu
+**************************************************************/
+
+void copy_id26_to_sam_passwd(struct samu *to,
+ struct samr_UserInfo26 *from)
+{
+ struct samr_UserInfo21 i;
+
+ if (from == NULL || to == NULL) {
+ return;
+ }
+
+ ZERO_STRUCT(i);
+
+ i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
+ i.password_expired = from->password_expired;
+
+ copy_id21_to_sam_passwd("INFO_26", to, &i);
+}