s3-samr: try to to fix password_expired flag handling.
authorGünther Deschner <gd@samba.org>
Thu, 27 Nov 2008 16:49:25 +0000 (17:49 +0100)
committerGünther Deschner <gd@samba.org>
Fri, 20 Mar 2009 09:39:18 +0000 (10:39 +0100)
Guenther

source3/include/proto.h
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_samr_util.c

index 3d87f75c7b2a4bef70f82bdee36ebc9eadaadacf..d8154482be562a7d055bf01107c2e9a590e46d5d 100644 (file)
@@ -5898,6 +5898,8 @@ NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
 
 /* The following definitions come from rpc_server/srv_samr_util.c  */
 
+void copy_id18_to_sam_passwd(struct samu *to,
+                            struct samr_UserInfo18 *from);
 void copy_id20_to_sam_passwd(struct samu *to,
                             struct samr_UserInfo20 *from);
 void copy_id21_to_sam_passwd(const char *log_prefix,
@@ -5905,8 +5907,12 @@ void copy_id21_to_sam_passwd(const char *log_prefix,
                             struct samr_UserInfo21 *from);
 void copy_id23_to_sam_passwd(struct samu *to,
                             struct samr_UserInfo23 *from);
+void copy_id24_to_sam_passwd(struct samu *to,
+                            struct samr_UserInfo24 *from);
 void copy_id25_to_sam_passwd(struct samu *to,
                             struct samr_UserInfo25 *from);
+void copy_id26_to_sam_passwd(struct samu *to,
+                            struct samr_UserInfo26 *from);
 
 /* The following definitions come from rpc_server/srv_spoolss_nt.c  */
 
index dcbd0963c493f409781fca58f25379f22a2f7e59..c60d904b18293684f851665e9cfe7f0878c418ff 100644 (file)
@@ -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 */
@@ -3980,6 +3985,36 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+/*******************************************************************
+ 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) {
index ef588aed1a38c8220a3a834995f22bc579bec919..068156054f00ccaffe289fc30a49656399dbfb48 100644 (file)
                    (!(s1) && (s2)) ||\
                ((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);
+                       }
                }
        }
 }
@@ -367,6 +406,27 @@ void copy_id23_to_sam_passwd(struct samu *to,
        copy_id21_to_sam_passwd("INFO 23", to, &from->info);
 }
 
+/*************************************************************
+ 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);
+}