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