util_str: Don't return memory from talloc_tos(), use mem_ctx instead.
[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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_SRV
28
29 #define STRING_CHANGED (old_string && !new_string) ||\
30                     (!old_string && new_string) ||\
31                 (old_string && new_string && (strcmp(old_string, new_string) != 0))
32
33 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
34                     (!(s1) && (s2)) ||\
35                 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
36
37 /*************************************************************
38  Copies a SAM_USER_INFO_20 to a struct samu
39 **************************************************************/
40
41 void copy_id20_to_sam_passwd(struct samu *to, SAM_USER_INFO_20 *from)
42 {
43         const char *old_string;
44         char *new_string;
45         DATA_BLOB mung;
46
47         if (from == NULL || to == NULL)
48                 return;
49
50         if (from->hdr_munged_dial.buffer) {
51                 old_string = pdb_get_munged_dial(to);
52                 mung.length = from->hdr_munged_dial.uni_str_len;
53                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
54                 mung.free = NULL;
55                 new_string = (mung.length == 0) ?
56                         NULL : base64_encode_data_blob(talloc_tos(), 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                 TALLOC_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_LAST_PWD_CHANGE) {
103                 unix_time=nt_time_to_unix(from->pass_last_set_time);
104                 stored_time = pdb_get_pass_last_set_time(to);
105                 DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
106                 if (stored_time != unix_time) 
107                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
108         }
109
110         if ((from->fields_present & ACCT_USERNAME) &&
111             (from->hdr_user_name.buffer)) {
112                 old_string = pdb_get_username(to);
113                 new_string = unistr2_static(&from->uni_user_name);
114                 DEBUG(10,("INFO_21 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
115                 if (STRING_CHANGED)
116                     pdb_set_username(to      , new_string, PDB_CHANGED);
117         }
118
119         if ((from->fields_present & ACCT_FULL_NAME) &&
120             (from->hdr_full_name.buffer)) {
121                 old_string = pdb_get_fullname(to);
122                 new_string = unistr2_static(&from->uni_full_name);
123                 DEBUG(10,("INFO_21 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
124                 if (STRING_CHANGED)
125                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
126         }
127         
128         if ((from->fields_present & ACCT_HOME_DIR) &&
129             (from->hdr_home_dir.buffer)) {
130                 old_string = pdb_get_homedir(to);
131                 new_string = unistr2_static(&from->uni_home_dir);
132                 DEBUG(10,("INFO_21 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
133                 if (STRING_CHANGED)
134                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
135         }
136
137         if ((from->fields_present & ACCT_HOME_DRIVE) &&
138             (from->hdr_dir_drive.buffer)) {
139                 old_string = pdb_get_dir_drive(to);
140                 new_string = unistr2_static(&from->uni_dir_drive);
141                 DEBUG(10,("INFO_21 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
142                 if (STRING_CHANGED)
143                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
144         }
145
146         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
147             (from->hdr_logon_script.buffer)) {
148                 old_string = pdb_get_logon_script(to);
149                 new_string = unistr2_static(&from->uni_logon_script);
150                 DEBUG(10,("INFO_21 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
151                 if (STRING_CHANGED)
152                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
153         }
154
155         if ((from->fields_present & ACCT_PROFILE) &&
156             (from->hdr_profile_path.buffer)) {
157                 old_string = pdb_get_profile_path(to);
158                 new_string = unistr2_static(&from->uni_profile_path);
159                 DEBUG(10,("INFO_21 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
160                 if (STRING_CHANGED)
161                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
162         }
163         
164         if ((from->fields_present & ACCT_DESCRIPTION) &&
165             (from->hdr_acct_desc.buffer)) {
166                 old_string = pdb_get_acct_desc(to);
167                 new_string = unistr2_static(&from->uni_acct_desc);
168                 DEBUG(10,("INFO_21 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
169                 if (STRING_CHANGED)
170                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
171         }
172         
173         if ((from->fields_present & ACCT_WORKSTATIONS) &&
174             (from->hdr_workstations.buffer)) {
175                 old_string = pdb_get_workstations(to);
176                 new_string = unistr2_static(&from->uni_workstations);
177                 DEBUG(10,("INFO_21 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
178                 if (STRING_CHANGED)
179                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
180         }
181
182         if ((from->fields_present & ACCT_COMMENT) &&
183             (from->hdr_comment.buffer)) {
184                 old_string = pdb_get_comment(to);
185                 new_string = unistr2_static(&from->uni_comment);
186                 DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string));
187                 if (STRING_CHANGED)
188                         pdb_set_comment(to, new_string, PDB_CHANGED);
189         }
190         
191         if ((from->fields_present & ACCT_CALLBACK) &&
192             (from->hdr_munged_dial.buffer)) {
193                 char *newstr;
194                 old_string = pdb_get_munged_dial(to);
195                 mung.length = from->hdr_munged_dial.uni_str_len;
196                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
197                 mung.free = NULL;
198                 newstr = (mung.length == 0) ?
199                         NULL : base64_encode_data_blob(talloc_tos(), mung);
200                 DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
201                 if (STRING_CHANGED_NC(old_string,newstr))
202                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
203
204                 TALLOC_FREE(newstr);
205         }
206         
207         if (from->fields_present & ACCT_RID) {
208                 if (from->user_rid == 0) {
209                         DEBUG(10, ("INFO_21: Asked to set User RID to 0 !? Skipping change!\n"));
210                 } else if (from->user_rid != pdb_get_user_rid(to)) {
211                         DEBUG(10,("INFO_21 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
212                 }
213         }
214         
215         if (from->fields_present & ACCT_PRIMARY_GID) {
216                 if (from->group_rid == 0) {
217                         DEBUG(10, ("INFO_21: Asked to set Group RID to 0 !? Skipping change!\n"));
218                 } else if (from->group_rid != pdb_get_group_rid(to)) {
219                         DEBUG(10,("INFO_21 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
220                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
221                 }
222         }
223         
224         if (from->fields_present & ACCT_FLAGS) {
225                 DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
226                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
227                         if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
228                                 /* We're unlocking a previously locked user. Reset bad password counts.
229                                    Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
230                                 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
231                                 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
232                         }
233                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
234                 }
235         }
236
237         if (from->fields_present & ACCT_LOGON_HOURS) {
238                 char oldstr[44]; /* hours strings are 42 bytes. */
239                 char newstr[44];
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(talloc_tos(), 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                 TALLOC_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(talloc_tos(), 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                 TALLOC_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 }