r18722: Fix up password change times. The can change and must change times are
[metze/samba/wip.git] / source3 / rpc_server / srv_samr_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SAMR Pipe utility functions.
4    
5    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
6    Copyright (C) Gerald (Jerry) Carter          2000-2001
7    Copyright (C) Andrew Bartlett                2001-2002
8    Copyright (C) Stefan (metze) Metzmacher      2002
9       
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
29
30 #define STRING_CHANGED (old_string && !new_string) ||\
31                     (!old_string && new_string) ||\
32                 (old_string && new_string && (strcmp(old_string, new_string) != 0))
33
34 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
35                     (!(s1) && (s2)) ||\
36                 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
37
38 /*************************************************************
39  Copies a SAM_USER_INFO_20 to a struct samu
40 **************************************************************/
41
42 void copy_id20_to_sam_passwd(struct samu *to, SAM_USER_INFO_20 *from)
43 {
44         const char *old_string;
45         char *new_string;
46         DATA_BLOB mung;
47
48         if (from == NULL || to == NULL) 
49                 return;
50         
51         if (from->hdr_munged_dial.buffer) {
52                 old_string = pdb_get_munged_dial(to);
53                 mung.length = from->hdr_munged_dial.uni_str_len;
54                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
55                 new_string = (mung.length == 0) ?
56                         NULL : base64_encode_data_blob(mung);
57                 DEBUG(10,("INFO_20 UNI_MUNGED_DIAL: %s -> %s\n",old_string, new_string));
58                 if (STRING_CHANGED_NC(old_string,new_string))
59                         pdb_set_munged_dial(to   , new_string, PDB_CHANGED);
60
61                 SAFE_FREE(new_string);
62         }
63 }
64
65 /*************************************************************
66  Copies a SAM_USER_INFO_21 to a struct samu
67 **************************************************************/
68
69 void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
70 {
71         time_t unix_time, stored_time;
72         const char *old_string, *new_string;
73         DATA_BLOB mung;
74
75         if (from == NULL || to == NULL) 
76                 return;
77
78         if (from->fields_present & ACCT_LAST_LOGON) {
79                 unix_time=nt_time_to_unix(from->logon_time);
80                 stored_time = pdb_get_logon_time(to);
81                 DEBUG(10,("INFO_21 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
82                 if (stored_time != unix_time) 
83                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
84         }
85
86         if (from->fields_present & ACCT_LAST_LOGOFF) {
87                 unix_time=nt_time_to_unix(from->logoff_time);
88                 stored_time = pdb_get_logoff_time(to);
89                 DEBUG(10,("INFO_21 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
90                 if (stored_time != unix_time) 
91                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
92         }
93
94         if (from->fields_present & ACCT_EXPIRY) {
95                 unix_time=nt_time_to_unix(from->kickoff_time);
96                 stored_time = pdb_get_kickoff_time(to);
97                 DEBUG(10,("INFO_21 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
98                 if (stored_time != unix_time) 
99                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
100         }       
101
102         if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
103                 unix_time=nt_time_to_unix(from->pass_can_change_time);
104                 stored_time = pdb_get_pass_can_change_time(to);
105                 DEBUG(10,("INFO_21 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
106                 if (stored_time != unix_time) 
107                         pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
108         }
109
110         if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
111                 unix_time=nt_time_to_unix(from->pass_last_set_time);
112                 stored_time = pdb_get_pass_last_set_time(to);
113                 DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
114                 if (stored_time != unix_time) 
115                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
116         }
117
118         if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
119                 unix_time=nt_time_to_unix(from->pass_must_change_time);
120                 stored_time=pdb_get_pass_must_change_time(to);
121                 DEBUG(10,("INFO_21 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
122                 if (stored_time != unix_time) 
123                         pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
124         }
125
126         if ((from->fields_present & ACCT_USERNAME) &&
127             (from->hdr_user_name.buffer)) {
128                 old_string = pdb_get_username(to);
129                 new_string = unistr2_static(&from->uni_user_name);
130                 DEBUG(10,("INFO_21 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
131                 if (STRING_CHANGED)
132                     pdb_set_username(to      , new_string, PDB_CHANGED);
133         }
134
135         if ((from->fields_present & ACCT_FULL_NAME) &&
136             (from->hdr_full_name.buffer)) {
137                 old_string = pdb_get_fullname(to);
138                 new_string = unistr2_static(&from->uni_full_name);
139                 DEBUG(10,("INFO_21 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
140                 if (STRING_CHANGED)
141                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
142         }
143         
144         if ((from->fields_present & ACCT_HOME_DIR) &&
145             (from->hdr_home_dir.buffer)) {
146                 old_string = pdb_get_homedir(to);
147                 new_string = unistr2_static(&from->uni_home_dir);
148                 DEBUG(10,("INFO_21 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
149                 if (STRING_CHANGED)
150                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
151         }
152
153         if ((from->fields_present & ACCT_HOME_DRIVE) &&
154             (from->hdr_dir_drive.buffer)) {
155                 old_string = pdb_get_dir_drive(to);
156                 new_string = unistr2_static(&from->uni_dir_drive);
157                 DEBUG(10,("INFO_21 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
158                 if (STRING_CHANGED)
159                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
160         }
161
162         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
163             (from->hdr_logon_script.buffer)) {
164                 old_string = pdb_get_logon_script(to);
165                 new_string = unistr2_static(&from->uni_logon_script);
166                 DEBUG(10,("INFO_21 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
167                 if (STRING_CHANGED)
168                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
169         }
170
171         if ((from->fields_present & ACCT_PROFILE) &&
172             (from->hdr_profile_path.buffer)) {
173                 old_string = pdb_get_profile_path(to);
174                 new_string = unistr2_static(&from->uni_profile_path);
175                 DEBUG(10,("INFO_21 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
176                 if (STRING_CHANGED)
177                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
178         }
179         
180         if ((from->fields_present & ACCT_DESCRIPTION) &&
181             (from->hdr_acct_desc.buffer)) {
182                 old_string = pdb_get_acct_desc(to);
183                 new_string = unistr2_static(&from->uni_acct_desc);
184                 DEBUG(10,("INFO_21 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
185                 if (STRING_CHANGED)
186                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
187         }
188         
189         if ((from->fields_present & ACCT_WORKSTATIONS) &&
190             (from->hdr_workstations.buffer)) {
191                 old_string = pdb_get_workstations(to);
192                 new_string = unistr2_static(&from->uni_workstations);
193                 DEBUG(10,("INFO_21 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
194                 if (STRING_CHANGED)
195                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
196         }
197
198         if ((from->fields_present & ACCT_COMMENT) &&
199             (from->hdr_comment.buffer)) {
200                 old_string = pdb_get_comment(to);
201                 new_string = unistr2_static(&from->uni_comment);
202                 DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string));
203                 if (STRING_CHANGED)
204                         pdb_set_comment(to, new_string, PDB_CHANGED);
205         }
206         
207         if ((from->fields_present & ACCT_CALLBACK) &&
208             (from->hdr_munged_dial.buffer)) {
209                 char *newstr;
210                 old_string = pdb_get_munged_dial(to);
211                 mung.length = from->hdr_munged_dial.uni_str_len;
212                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
213                 newstr = (mung.length == 0) ?
214                         NULL : base64_encode_data_blob(mung);
215                 DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
216                 if (STRING_CHANGED_NC(old_string,newstr))
217                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
218
219                 SAFE_FREE(newstr);
220         }
221         
222         if (from->fields_present & ACCT_RID) {
223                 if (from->user_rid == 0) {
224                         DEBUG(10, ("INFO_21: Asked to set User RID to 0 !? Skipping change!\n"));
225                 } else if (from->user_rid != pdb_get_user_rid(to)) {
226                         DEBUG(10,("INFO_21 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
227                 }
228         }
229         
230         if (from->fields_present & ACCT_PRIMARY_GID) {
231                 if (from->group_rid == 0) {
232                         DEBUG(10, ("INFO_21: Asked to set Group RID to 0 !? Skipping change!\n"));
233                 } else if (from->group_rid != pdb_get_group_rid(to)) {
234                         DEBUG(10,("INFO_21 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
235                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
236                 }
237         }
238         
239         if (from->fields_present & ACCT_FLAGS) {
240                 DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
241                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
242                         if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
243                                 /* We're unlocking a previously locked user. Reset bad password counts.
244                                    Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
245                                 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
246                                 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
247                         }
248                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
249                 }
250         }
251
252         if (from->fields_present & ACCT_LOGON_HOURS) {
253                 pstring oldstr, newstr;
254                 DEBUG(15,("INFO_21 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
255                 if (from->logon_divs != pdb_get_logon_divs(to)) {
256                         pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
257                 }
258
259                 DEBUG(15,("INFO_21 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
260                 if (from->logon_hrs.len != pdb_get_hours_len(to)) {
261                         pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
262                 }
263
264                 DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
265                 pdb_sethexhours(oldstr, pdb_get_hours(to));
266                 pdb_sethexhours(newstr, from->logon_hrs.hours);
267                 if (!strequal(oldstr, newstr)) {
268                         pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
269                 }
270         }
271
272         if (from->fields_present & ACCT_BAD_PWD_COUNT) {
273                 DEBUG(10,("INFO_21 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
274                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
275                         pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
276                 }
277         }
278
279         if (from->fields_present & ACCT_NUM_LOGONS) {
280                 DEBUG(10,("INFO_21 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
281                 if (from->logon_count != pdb_get_logon_count(to)) {
282                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
283                 }
284         }
285
286         /* If the must change flag is set, the last set time goes to zero.
287            the must change and can change fields also do, but they are 
288            calculated from policy, not set from the wire */
289
290         if (from->fields_present & ACCT_EXPIRED_FLAG) {
291                 DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
292                 if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
293                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);         
294                 } else {
295                         pdb_set_pass_last_set_time(to, time(0), PDB_CHANGED);
296                 }
297         }
298
299         DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2));
300 }
301
302
303 /*************************************************************
304  Copies a SAM_USER_INFO_23 to a struct samu
305 **************************************************************/
306
307 void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
308 {
309         time_t unix_time, stored_time;
310         const char *old_string, *new_string;
311         DATA_BLOB mung;
312
313         if (from == NULL || to == NULL) 
314                 return;
315
316         if (from->fields_present & ACCT_LAST_LOGON) {
317                 unix_time=nt_time_to_unix(from->logon_time);
318                 stored_time = pdb_get_logon_time(to);
319                 DEBUG(10,("INFO_23 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
320                 if (stored_time != unix_time) 
321                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
322         }
323
324         if (from->fields_present & ACCT_LAST_LOGOFF) {
325                 unix_time=nt_time_to_unix(from->logoff_time);
326                 stored_time = pdb_get_logoff_time(to);
327                 DEBUG(10,("INFO_23 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
328                 if (stored_time != unix_time) 
329                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
330         }
331         
332         if (from->fields_present & ACCT_EXPIRY) {
333                 unix_time=nt_time_to_unix(from->kickoff_time);
334                 stored_time = pdb_get_kickoff_time(to);
335                 DEBUG(10,("INFO_23 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
336                 if (stored_time != unix_time) 
337                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
338         }       
339
340         if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
341                 unix_time=nt_time_to_unix(from->pass_can_change_time);
342                 stored_time = pdb_get_pass_can_change_time(to);
343                 DEBUG(10,("INFO_23 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
344                 if (stored_time != unix_time) 
345                         pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
346         }
347
348         if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
349                 unix_time=nt_time_to_unix(from->pass_last_set_time);
350                 stored_time = pdb_get_pass_last_set_time(to);
351                 DEBUG(10,("INFO_23 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
352                 if (stored_time != unix_time) 
353                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
354         }
355
356         if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
357                 unix_time=nt_time_to_unix(from->pass_must_change_time);
358                 stored_time=pdb_get_pass_must_change_time(to);
359                 DEBUG(10,("INFO_23 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
360                 if (stored_time != unix_time) 
361                         pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
362         }
363
364         /* Backend should check this for sanity */
365         if ((from->fields_present & ACCT_USERNAME) &&
366             (from->hdr_user_name.buffer)) {
367                 old_string = pdb_get_username(to);
368                 new_string = unistr2_static(&from->uni_user_name);
369                 DEBUG(10,("INFO_23 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
370                 if (STRING_CHANGED)
371                     pdb_set_username(to      , new_string, PDB_CHANGED);
372         }
373
374         if ((from->fields_present & ACCT_FULL_NAME) &&
375             (from->hdr_full_name.buffer)) {
376                 old_string = pdb_get_fullname(to);
377                 new_string = unistr2_static(&from->uni_full_name);
378                 DEBUG(10,("INFO_23 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
379                 if (STRING_CHANGED)
380                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
381         }
382         
383         if ((from->fields_present & ACCT_HOME_DIR) &&
384             (from->hdr_home_dir.buffer)) {
385                 old_string = pdb_get_homedir(to);
386                 new_string = unistr2_static(&from->uni_home_dir);
387                 DEBUG(10,("INFO_23 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
388                 if (STRING_CHANGED)
389                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
390         }
391
392         if ((from->fields_present & ACCT_HOME_DRIVE) &&
393             (from->hdr_dir_drive.buffer)) {
394                 old_string = pdb_get_dir_drive(to);
395                 new_string = unistr2_static(&from->uni_dir_drive);
396                 DEBUG(10,("INFO_23 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
397                 if (STRING_CHANGED)
398                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
399         }
400
401         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
402             (from->hdr_logon_script.buffer)) {
403                 old_string = pdb_get_logon_script(to);
404                 new_string = unistr2_static(&from->uni_logon_script);
405                 DEBUG(10,("INFO_23 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
406                 if (STRING_CHANGED)
407                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
408         }
409
410         if ((from->fields_present & ACCT_PROFILE) &&
411             (from->hdr_profile_path.buffer)) {
412                 old_string = pdb_get_profile_path(to);
413                 new_string = unistr2_static(&from->uni_profile_path);
414                 DEBUG(10,("INFO_23 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
415                 if (STRING_CHANGED)
416                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
417         }
418         
419         if ((from->fields_present & ACCT_DESCRIPTION) &&
420             (from->hdr_acct_desc.buffer)) {
421                 old_string = pdb_get_acct_desc(to);
422                 new_string = unistr2_static(&from->uni_acct_desc);
423                 DEBUG(10,("INFO_23 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
424                 if (STRING_CHANGED)
425                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
426         }
427         
428         if ((from->fields_present & ACCT_WORKSTATIONS) &&
429             (from->hdr_workstations.buffer)) {
430                 old_string = pdb_get_workstations(to);
431                 new_string = unistr2_static(&from->uni_workstations);
432                 DEBUG(10,("INFO_23 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
433                 if (STRING_CHANGED)
434                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
435         }
436
437         if ((from->fields_present & ACCT_COMMENT) &&
438             (from->hdr_comment.buffer)) {
439                 old_string = pdb_get_comment(to);
440                 new_string = unistr2_static(&from->uni_comment);
441                 DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
442                 if (STRING_CHANGED)
443                         pdb_set_comment(to   , new_string, PDB_CHANGED);
444         }
445         
446         if ((from->fields_present & ACCT_CALLBACK) &&
447             (from->hdr_munged_dial.buffer)) {
448                 char *newstr;
449                 old_string = pdb_get_munged_dial(to);
450                 mung.length = from->hdr_munged_dial.uni_str_len;
451                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
452                 newstr = (mung.length == 0) ?
453                         NULL : base64_encode_data_blob(mung);
454                 DEBUG(10,("INFO_23 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
455                 if (STRING_CHANGED_NC(old_string, newstr))
456                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
457
458                 SAFE_FREE(newstr);
459         }
460         
461         if (from->fields_present & ACCT_RID) {
462                 if (from->user_rid == 0) {
463                         DEBUG(10, ("INFO_23: Asked to set User RID to 0 !? Skipping change!\n"));
464                 } else if (from->user_rid != pdb_get_user_rid(to)) {
465                         DEBUG(10,("INFO_23 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
466                 }
467         }
468
469         if (from->fields_present & ACCT_PRIMARY_GID) {
470                 if  (from->group_rid == 0) {
471                         DEBUG(10, ("INFO_23: Asked to set Group RID to 0 !? Skipping change!\n"));
472                 } else if (from->group_rid != pdb_get_group_rid(to)) {
473                         DEBUG(10,("INFO_23 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
474                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
475                 }
476         }
477         
478         if (from->fields_present & ACCT_FLAGS) {
479                 DEBUG(10,("INFO_23 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
480                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
481                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
482                 }
483         }
484
485         if (from->fields_present & ACCT_LOGON_HOURS) {
486                 DEBUG(15,("INFO_23 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
487                 if (from->logon_divs != pdb_get_logon_divs(to)) {
488                         pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
489                 }
490
491                 DEBUG(15,("INFO_23 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
492                 if (from->logon_hrs.len != pdb_get_hours_len(to)) {
493                         pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
494                 }
495
496                 DEBUG(15,("INFO_23 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
497                 /* Fix me: only update if it changes --metze */
498                 pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
499         }
500
501         if (from->fields_present & ACCT_BAD_PWD_COUNT) {
502                 DEBUG(10,("INFO_23 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
503                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
504                         pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
505                 }
506         }
507
508         if (from->fields_present & ACCT_NUM_LOGONS) {
509                 DEBUG(10,("INFO_23 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
510                 if (from->logon_count != pdb_get_logon_count(to)) {
511                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
512                 }
513         }
514
515         /* If the must change flag is set, the last set time goes to zero.
516            the must change and can change fields also do, but they are 
517            calculated from policy, not set from the wire */
518
519         if (from->fields_present & ACCT_EXPIRED_FLAG) {
520                 DEBUG(10,("INFO_23 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
521                 if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
522                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);         
523                 } else {
524                         pdb_set_pass_last_set_time(to, time(0), PDB_CHANGED);
525                 }
526         }
527
528         DEBUG(10,("INFO_23 PADDING_2: %02X\n",from->padding2));
529 }
530
531 /*************************************************************
532  Copies a SAM_USER_INFO_25 to a struct samu
533 **************************************************************/
534
535 void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
536 {
537         time_t unix_time, stored_time;
538         const char *old_string, *new_string;
539         DATA_BLOB mung;
540
541         if (from == NULL || to == NULL) 
542                 return;
543
544         if (from->fields_present & ACCT_LAST_LOGON) {
545                 unix_time=nt_time_to_unix(from->logon_time);
546                 stored_time = pdb_get_logon_time(to);
547                 DEBUG(10,("INFO_25 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
548                 if (stored_time != unix_time) 
549                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
550         }
551
552         if (from->fields_present & ACCT_LAST_LOGOFF) {
553                 unix_time=nt_time_to_unix(from->logoff_time);
554                 stored_time = pdb_get_logoff_time(to);
555                 DEBUG(10,("INFO_25 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
556                 if (stored_time != unix_time) 
557                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
558         }
559
560         if (from->fields_present & ACCT_EXPIRY) {
561                 unix_time=nt_time_to_unix(from->kickoff_time);
562                 stored_time = pdb_get_kickoff_time(to);
563                 DEBUG(10,("INFO_25 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
564                 if (stored_time != unix_time) 
565                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
566         }       
567
568         if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
569                 unix_time=nt_time_to_unix(from->pass_can_change_time);
570                 stored_time = pdb_get_pass_can_change_time(to);
571                 DEBUG(10,("INFO_25 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
572                 if (stored_time != unix_time) 
573                         pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
574         }
575
576         if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
577                 unix_time=nt_time_to_unix(from->pass_last_set_time);
578                 stored_time = pdb_get_pass_last_set_time(to);
579                 DEBUG(10,("INFO_25 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
580                 if (stored_time != unix_time) 
581                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
582         }
583
584         if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
585                 unix_time=nt_time_to_unix(from->pass_must_change_time);
586                 stored_time=pdb_get_pass_must_change_time(to);
587                 DEBUG(10,("INFO_25 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
588                 if (stored_time != unix_time) 
589                         pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
590         }
591
592         if ((from->fields_present & ACCT_USERNAME) &&
593             (from->hdr_user_name.buffer)) {
594                 old_string = pdb_get_username(to);
595                 new_string = unistr2_static(&from->uni_user_name);
596                 DEBUG(10,("INFO_25 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
597                 if (STRING_CHANGED)
598                     pdb_set_username(to      , new_string, PDB_CHANGED);
599         }
600
601         if ((from->fields_present & ACCT_FULL_NAME) &&
602             (from->hdr_full_name.buffer)) {
603                 old_string = pdb_get_fullname(to);
604                 new_string = unistr2_static(&from->uni_full_name);
605                 DEBUG(10,("INFO_25 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
606                 if (STRING_CHANGED)
607                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
608         }
609         
610         if ((from->fields_present & ACCT_HOME_DIR) &&
611             (from->hdr_home_dir.buffer)) {
612                 old_string = pdb_get_homedir(to);
613                 new_string = unistr2_static(&from->uni_home_dir);
614                 DEBUG(10,("INFO_25 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
615                 if (STRING_CHANGED)
616                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
617         }
618
619         if ((from->fields_present & ACCT_HOME_DRIVE) &&
620             (from->hdr_dir_drive.buffer)) {
621                 old_string = pdb_get_dir_drive(to);
622                 new_string = unistr2_static(&from->uni_dir_drive);
623                 DEBUG(10,("INFO_25 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
624                 if (STRING_CHANGED)
625                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
626         }
627
628         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
629             (from->hdr_logon_script.buffer)) {
630                 old_string = pdb_get_logon_script(to);
631                 new_string = unistr2_static(&from->uni_logon_script);
632                 DEBUG(10,("INFO_25 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
633                 if (STRING_CHANGED)
634                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
635         }
636
637         if ((from->fields_present & ACCT_PROFILE) &&
638             (from->hdr_profile_path.buffer)) {
639                 old_string = pdb_get_profile_path(to);
640                 new_string = unistr2_static(&from->uni_profile_path);
641                 DEBUG(10,("INFO_25 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
642                 if (STRING_CHANGED)
643                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
644         }
645         
646         if ((from->fields_present & ACCT_DESCRIPTION) &&
647             (from->hdr_acct_desc.buffer)) {
648                 old_string = pdb_get_acct_desc(to);
649                 new_string = unistr2_static(&from->uni_acct_desc);
650                 DEBUG(10,("INFO_25 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
651                 if (STRING_CHANGED)
652                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
653         }
654         
655         if ((from->fields_present & ACCT_WORKSTATIONS) &&
656             (from->hdr_workstations.buffer)) {
657                 old_string = pdb_get_workstations(to);
658                 new_string = unistr2_static(&from->uni_workstations);
659                 DEBUG(10,("INFO_25 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
660                 if (STRING_CHANGED)
661                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
662         }
663
664         if ((from->fields_present & ACCT_COMMENT) &&
665             (from->hdr_comment.buffer)) {
666                 old_string = pdb_get_comment(to);
667                 new_string = unistr2_static(&from->uni_comment);
668                 DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
669                 if (STRING_CHANGED)
670                         pdb_set_comment(to   , new_string, PDB_CHANGED);
671         }
672         
673         if ((from->fields_present & ACCT_CALLBACK) &&
674             (from->hdr_munged_dial.buffer)) {
675                 char *newstr;
676                 old_string = pdb_get_munged_dial(to);
677                 mung.length = from->hdr_munged_dial.uni_str_len;
678                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
679                 newstr = (mung.length == 0) ?
680                         NULL : base64_encode_data_blob(mung);
681                 DEBUG(10,("INFO_25 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
682                 if (STRING_CHANGED_NC(old_string,newstr))
683                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
684
685                 SAFE_FREE(newstr);
686         }
687         
688         if (from->fields_present & ACCT_RID) {
689                 if (from->user_rid == 0) {
690                         DEBUG(10, ("INFO_25: Asked to set User RID to 0 !? Skipping change!\n"));
691                 } else if (from->user_rid != pdb_get_user_rid(to)) {
692                         DEBUG(10,("INFO_25 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
693                 }
694         }
695         
696         if (from->fields_present & ACCT_PRIMARY_GID) {
697                 if (from->group_rid == 0) {
698                         DEBUG(10, ("INFO_25: Asked to set Group RID to 0 !? Skipping change!\n"));
699                 } else if (from->group_rid != pdb_get_group_rid(to)) {
700                         DEBUG(10,("INFO_25 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
701                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
702                 }
703         }
704         
705         if (from->fields_present & ACCT_FLAGS) {
706                 DEBUG(10,("INFO_25 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
707                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
708                         if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
709                                 /* We're unlocking a previously locked user. Reset bad password counts.
710                                    Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
711                                 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
712                                 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
713                         }
714                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
715                 }
716         }
717 }