r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[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(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_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(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                 SAFE_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                 pstring oldstr, newstr;
239                 DEBUG(15,("INFO_21 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
240                 if (from->logon_divs != pdb_get_logon_divs(to)) {
241                         pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
242                 }
243
244                 DEBUG(15,("INFO_21 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
245                 if (from->logon_hrs.len != pdb_get_hours_len(to)) {
246                         pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
247                 }
248
249                 DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
250                 pdb_sethexhours(oldstr, pdb_get_hours(to));
251                 pdb_sethexhours(newstr, from->logon_hrs.hours);
252                 if (!strequal(oldstr, newstr)) {
253                         pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
254                 }
255         }
256
257         if (from->fields_present & ACCT_BAD_PWD_COUNT) {
258                 DEBUG(10,("INFO_21 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
259                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
260                         pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
261                 }
262         }
263
264         if (from->fields_present & ACCT_NUM_LOGONS) {
265                 DEBUG(10,("INFO_21 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
266                 if (from->logon_count != pdb_get_logon_count(to)) {
267                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
268                 }
269         }
270
271         /* If the must change flag is set, the last set time goes to zero.
272            the must change and can change fields also do, but they are 
273            calculated from policy, not set from the wire */
274
275         if (from->fields_present & ACCT_EXPIRED_FLAG) {
276                 DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
277                 if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
278                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);         
279                 } else {
280                         pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
281                 }
282         }
283
284         DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2));
285 }
286
287
288 /*************************************************************
289  Copies a SAM_USER_INFO_23 to a struct samu
290 **************************************************************/
291
292 void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
293 {
294         time_t unix_time, stored_time;
295         const char *old_string, *new_string;
296         DATA_BLOB mung;
297
298         if (from == NULL || to == NULL) 
299                 return;
300
301         if (from->fields_present & ACCT_LAST_LOGON) {
302                 unix_time=nt_time_to_unix(from->logon_time);
303                 stored_time = pdb_get_logon_time(to);
304                 DEBUG(10,("INFO_23 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
305                 if (stored_time != unix_time) 
306                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
307         }
308
309         if (from->fields_present & ACCT_LAST_LOGOFF) {
310                 unix_time=nt_time_to_unix(from->logoff_time);
311                 stored_time = pdb_get_logoff_time(to);
312                 DEBUG(10,("INFO_23 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
313                 if (stored_time != unix_time) 
314                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
315         }
316         
317         if (from->fields_present & ACCT_EXPIRY) {
318                 unix_time=nt_time_to_unix(from->kickoff_time);
319                 stored_time = pdb_get_kickoff_time(to);
320                 DEBUG(10,("INFO_23 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
321                 if (stored_time != unix_time) 
322                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
323         }       
324
325         if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
326                 unix_time=nt_time_to_unix(from->pass_last_set_time);
327                 stored_time = pdb_get_pass_last_set_time(to);
328                 DEBUG(10,("INFO_23 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
329                 if (stored_time != unix_time) 
330                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
331         }
332
333         /* Backend should check this for sanity */
334         if ((from->fields_present & ACCT_USERNAME) &&
335             (from->hdr_user_name.buffer)) {
336                 old_string = pdb_get_username(to);
337                 new_string = unistr2_static(&from->uni_user_name);
338                 DEBUG(10,("INFO_23 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
339                 if (STRING_CHANGED)
340                     pdb_set_username(to      , new_string, PDB_CHANGED);
341         }
342
343         if ((from->fields_present & ACCT_FULL_NAME) &&
344             (from->hdr_full_name.buffer)) {
345                 old_string = pdb_get_fullname(to);
346                 new_string = unistr2_static(&from->uni_full_name);
347                 DEBUG(10,("INFO_23 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
348                 if (STRING_CHANGED)
349                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
350         }
351         
352         if ((from->fields_present & ACCT_HOME_DIR) &&
353             (from->hdr_home_dir.buffer)) {
354                 old_string = pdb_get_homedir(to);
355                 new_string = unistr2_static(&from->uni_home_dir);
356                 DEBUG(10,("INFO_23 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
357                 if (STRING_CHANGED)
358                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
359         }
360
361         if ((from->fields_present & ACCT_HOME_DRIVE) &&
362             (from->hdr_dir_drive.buffer)) {
363                 old_string = pdb_get_dir_drive(to);
364                 new_string = unistr2_static(&from->uni_dir_drive);
365                 DEBUG(10,("INFO_23 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
366                 if (STRING_CHANGED)
367                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
368         }
369
370         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
371             (from->hdr_logon_script.buffer)) {
372                 old_string = pdb_get_logon_script(to);
373                 new_string = unistr2_static(&from->uni_logon_script);
374                 DEBUG(10,("INFO_23 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
375                 if (STRING_CHANGED)
376                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
377         }
378
379         if ((from->fields_present & ACCT_PROFILE) &&
380             (from->hdr_profile_path.buffer)) {
381                 old_string = pdb_get_profile_path(to);
382                 new_string = unistr2_static(&from->uni_profile_path);
383                 DEBUG(10,("INFO_23 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
384                 if (STRING_CHANGED)
385                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
386         }
387         
388         if ((from->fields_present & ACCT_DESCRIPTION) &&
389             (from->hdr_acct_desc.buffer)) {
390                 old_string = pdb_get_acct_desc(to);
391                 new_string = unistr2_static(&from->uni_acct_desc);
392                 DEBUG(10,("INFO_23 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
393                 if (STRING_CHANGED)
394                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
395         }
396         
397         if ((from->fields_present & ACCT_WORKSTATIONS) &&
398             (from->hdr_workstations.buffer)) {
399                 old_string = pdb_get_workstations(to);
400                 new_string = unistr2_static(&from->uni_workstations);
401                 DEBUG(10,("INFO_23 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
402                 if (STRING_CHANGED)
403                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
404         }
405
406         if ((from->fields_present & ACCT_COMMENT) &&
407             (from->hdr_comment.buffer)) {
408                 old_string = pdb_get_comment(to);
409                 new_string = unistr2_static(&from->uni_comment);
410                 DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
411                 if (STRING_CHANGED)
412                         pdb_set_comment(to   , new_string, PDB_CHANGED);
413         }
414         
415         if ((from->fields_present & ACCT_CALLBACK) &&
416             (from->hdr_munged_dial.buffer)) {
417                 char *newstr;
418                 old_string = pdb_get_munged_dial(to);
419                 mung.length = from->hdr_munged_dial.uni_str_len;
420                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
421                 mung.free = NULL;
422                 newstr = (mung.length == 0) ?
423                         NULL : base64_encode_data_blob(mung);
424                 DEBUG(10,("INFO_23 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
425                 if (STRING_CHANGED_NC(old_string, newstr))
426                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
427
428                 SAFE_FREE(newstr);
429         }
430         
431         if (from->fields_present & ACCT_RID) {
432                 if (from->user_rid == 0) {
433                         DEBUG(10, ("INFO_23: Asked to set User RID to 0 !? Skipping change!\n"));
434                 } else if (from->user_rid != pdb_get_user_rid(to)) {
435                         DEBUG(10,("INFO_23 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
436                 }
437         }
438
439         if (from->fields_present & ACCT_PRIMARY_GID) {
440                 if  (from->group_rid == 0) {
441                         DEBUG(10, ("INFO_23: Asked to set Group RID to 0 !? Skipping change!\n"));
442                 } else if (from->group_rid != pdb_get_group_rid(to)) {
443                         DEBUG(10,("INFO_23 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
444                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
445                 }
446         }
447         
448         if (from->fields_present & ACCT_FLAGS) {
449                 DEBUG(10,("INFO_23 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
450                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
451                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
452                 }
453         }
454
455         if (from->fields_present & ACCT_LOGON_HOURS) {
456                 DEBUG(15,("INFO_23 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
457                 if (from->logon_divs != pdb_get_logon_divs(to)) {
458                         pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
459                 }
460
461                 DEBUG(15,("INFO_23 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
462                 if (from->logon_hrs.len != pdb_get_hours_len(to)) {
463                         pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
464                 }
465
466                 DEBUG(15,("INFO_23 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
467                 /* Fix me: only update if it changes --metze */
468                 pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
469         }
470
471         if (from->fields_present & ACCT_BAD_PWD_COUNT) {
472                 DEBUG(10,("INFO_23 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
473                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
474                         pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
475                 }
476         }
477
478         if (from->fields_present & ACCT_NUM_LOGONS) {
479                 DEBUG(10,("INFO_23 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
480                 if (from->logon_count != pdb_get_logon_count(to)) {
481                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
482                 }
483         }
484
485         /* If the must change flag is set, the last set time goes to zero.
486            the must change and can change fields also do, but they are 
487            calculated from policy, not set from the wire */
488
489         if (from->fields_present & ACCT_EXPIRED_FLAG) {
490                 DEBUG(10,("INFO_23 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
491                 if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
492                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);         
493                 } else {
494                         pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
495                 }
496         }
497
498         DEBUG(10,("INFO_23 PADDING_2: %02X\n",from->padding2));
499 }
500
501 /*************************************************************
502  Copies a SAM_USER_INFO_25 to a struct samu
503 **************************************************************/
504
505 void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
506 {
507         time_t unix_time, stored_time;
508         const char *old_string, *new_string;
509         DATA_BLOB mung;
510
511         if (from == NULL || to == NULL) 
512                 return;
513
514         if (from->fields_present & ACCT_LAST_LOGON) {
515                 unix_time=nt_time_to_unix(from->logon_time);
516                 stored_time = pdb_get_logon_time(to);
517                 DEBUG(10,("INFO_25 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
518                 if (stored_time != unix_time) 
519                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
520         }
521
522         if (from->fields_present & ACCT_LAST_LOGOFF) {
523                 unix_time=nt_time_to_unix(from->logoff_time);
524                 stored_time = pdb_get_logoff_time(to);
525                 DEBUG(10,("INFO_25 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
526                 if (stored_time != unix_time) 
527                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
528         }
529
530         if (from->fields_present & ACCT_EXPIRY) {
531                 unix_time=nt_time_to_unix(from->kickoff_time);
532                 stored_time = pdb_get_kickoff_time(to);
533                 DEBUG(10,("INFO_25 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
534                 if (stored_time != unix_time) 
535                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
536         }       
537
538         if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
539                 unix_time=nt_time_to_unix(from->pass_last_set_time);
540                 stored_time = pdb_get_pass_last_set_time(to);
541                 DEBUG(10,("INFO_25 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
542                 if (stored_time != unix_time) 
543                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
544         }
545
546         if ((from->fields_present & ACCT_USERNAME) &&
547             (from->hdr_user_name.buffer)) {
548                 old_string = pdb_get_username(to);
549                 new_string = unistr2_static(&from->uni_user_name);
550                 DEBUG(10,("INFO_25 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
551                 if (STRING_CHANGED)
552                     pdb_set_username(to      , new_string, PDB_CHANGED);
553         }
554
555         if ((from->fields_present & ACCT_FULL_NAME) &&
556             (from->hdr_full_name.buffer)) {
557                 old_string = pdb_get_fullname(to);
558                 new_string = unistr2_static(&from->uni_full_name);
559                 DEBUG(10,("INFO_25 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
560                 if (STRING_CHANGED)
561                         pdb_set_fullname(to      , new_string, PDB_CHANGED);
562         }
563         
564         if ((from->fields_present & ACCT_HOME_DIR) &&
565             (from->hdr_home_dir.buffer)) {
566                 old_string = pdb_get_homedir(to);
567                 new_string = unistr2_static(&from->uni_home_dir);
568                 DEBUG(10,("INFO_25 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
569                 if (STRING_CHANGED)
570                         pdb_set_homedir(to       , new_string, PDB_CHANGED);
571         }
572
573         if ((from->fields_present & ACCT_HOME_DRIVE) &&
574             (from->hdr_dir_drive.buffer)) {
575                 old_string = pdb_get_dir_drive(to);
576                 new_string = unistr2_static(&from->uni_dir_drive);
577                 DEBUG(10,("INFO_25 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
578                 if (STRING_CHANGED)
579                         pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
580         }
581
582         if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
583             (from->hdr_logon_script.buffer)) {
584                 old_string = pdb_get_logon_script(to);
585                 new_string = unistr2_static(&from->uni_logon_script);
586                 DEBUG(10,("INFO_25 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
587                 if (STRING_CHANGED)
588                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
589         }
590
591         if ((from->fields_present & ACCT_PROFILE) &&
592             (from->hdr_profile_path.buffer)) {
593                 old_string = pdb_get_profile_path(to);
594                 new_string = unistr2_static(&from->uni_profile_path);
595                 DEBUG(10,("INFO_25 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
596                 if (STRING_CHANGED)
597                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
598         }
599         
600         if ((from->fields_present & ACCT_DESCRIPTION) &&
601             (from->hdr_acct_desc.buffer)) {
602                 old_string = pdb_get_acct_desc(to);
603                 new_string = unistr2_static(&from->uni_acct_desc);
604                 DEBUG(10,("INFO_25 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
605                 if (STRING_CHANGED)
606                         pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
607         }
608         
609         if ((from->fields_present & ACCT_WORKSTATIONS) &&
610             (from->hdr_workstations.buffer)) {
611                 old_string = pdb_get_workstations(to);
612                 new_string = unistr2_static(&from->uni_workstations);
613                 DEBUG(10,("INFO_25 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
614                 if (STRING_CHANGED)
615                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
616         }
617
618         if ((from->fields_present & ACCT_COMMENT) &&
619             (from->hdr_comment.buffer)) {
620                 old_string = pdb_get_comment(to);
621                 new_string = unistr2_static(&from->uni_comment);
622                 DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
623                 if (STRING_CHANGED)
624                         pdb_set_comment(to   , new_string, PDB_CHANGED);
625         }
626         
627         if ((from->fields_present & ACCT_CALLBACK) &&
628             (from->hdr_munged_dial.buffer)) {
629                 char *newstr;
630                 old_string = pdb_get_munged_dial(to);
631                 mung.length = from->hdr_munged_dial.uni_str_len;
632                 mung.data = (uint8 *) from->uni_munged_dial.buffer;
633                 mung.free = NULL;
634                 newstr = (mung.length == 0) ?
635                         NULL : base64_encode_data_blob(mung);
636                 DEBUG(10,("INFO_25 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
637                 if (STRING_CHANGED_NC(old_string,newstr))
638                         pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
639
640                 SAFE_FREE(newstr);
641         }
642         
643         if (from->fields_present & ACCT_RID) {
644                 if (from->user_rid == 0) {
645                         DEBUG(10, ("INFO_25: Asked to set User RID to 0 !? Skipping change!\n"));
646                 } else if (from->user_rid != pdb_get_user_rid(to)) {
647                         DEBUG(10,("INFO_25 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
648                 }
649         }
650         
651         if (from->fields_present & ACCT_PRIMARY_GID) {
652                 if (from->group_rid == 0) {
653                         DEBUG(10, ("INFO_25: Asked to set Group RID to 0 !? Skipping change!\n"));
654                 } else if (from->group_rid != pdb_get_group_rid(to)) {
655                         DEBUG(10,("INFO_25 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
656                         pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
657                 }
658         }
659         
660         if (from->fields_present & ACCT_FLAGS) {
661                 DEBUG(10,("INFO_25 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
662                 if (from->acb_info != pdb_get_acct_ctrl(to)) {
663                         if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
664                                 /* We're unlocking a previously locked user. Reset bad password counts.
665                                    Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
666                                 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
667                                 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
668                         }
669                         pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
670                 }
671         }
672
673         if (from->fields_present & ACCT_LOGON_HOURS) {
674                 DEBUG(15,("INFO_25 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
675                 if (from->logon_divs != pdb_get_logon_divs(to)) {
676                         pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
677                 }
678
679                 DEBUG(15,("INFO_25 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
680                 if (from->logon_hrs.len != pdb_get_hours_len(to)) {
681                         pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
682                 }
683
684                 DEBUG(15,("INFO_25 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
685                 /* Fix me: only update if it changes --metze */
686                 pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
687         }
688
689         if (from->fields_present & ACCT_BAD_PWD_COUNT) {
690                 DEBUG(10,("INFO_25 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
691                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
692                         pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
693                 }
694         }
695
696         if (from->fields_present & ACCT_NUM_LOGONS) {
697                 DEBUG(10,("INFO_25 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
698                 if (from->logon_count != pdb_get_logon_count(to)) {
699                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
700                 }
701         }
702
703         /* If the must change flag is set, the last set time goes to zero.
704            the must change and can change fields also do, but they are 
705            calculated from policy, not set from the wire */
706
707         if (from->fields_present & ACCT_EXPIRED_FLAG) {
708                 DEBUG(10,("INFO_25 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
709                 if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
710                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);         
711                 } else {
712                         pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
713                 }
714         }
715 }