Re-add support for the samr parameters string.
[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    Copyright (C) Guenther Deschner              2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 struct samr_UserInfo20 to a struct samu
40 **************************************************************/
41
42 void copy_id20_to_sam_passwd(struct samu *to,
43                              struct samr_UserInfo20 *from)
44 {
45         const char *old_string;
46         char *new_string;
47         DATA_BLOB mung;
48
49         if (from == NULL || to == NULL) {
50                 return;
51         }
52
53         if (from->parameters.array) {
54                 old_string = pdb_get_munged_dial(to);
55                 mung = data_blob_const(from->parameters.array,
56                                        from->parameters.length);
57                 new_string = (mung.length == 0) ?
58                         NULL : base64_encode_data_blob(talloc_tos(), mung);
59                 DEBUG(10,("INFO_20 PARAMETERS: %s -> %s\n",
60                         old_string, new_string));
61                 if (STRING_CHANGED_NC(old_string,new_string)) {
62                         pdb_set_munged_dial(to, new_string, PDB_CHANGED);
63                 }
64
65                 TALLOC_FREE(new_string);
66         }
67 }
68
69 /*************************************************************
70  Copies a struct samr_UserInfo21 to a struct samu
71 **************************************************************/
72
73 void copy_id21_to_sam_passwd(const char *log_prefix,
74                              struct samu *to,
75                              struct samr_UserInfo21 *from)
76 {
77         time_t unix_time, stored_time;
78         const char *old_string, *new_string;
79         const char *l;
80
81         if (from == NULL || to == NULL) {
82                 return;
83         }
84
85         if (log_prefix) {
86                 l = log_prefix;
87         } else {
88                 l = "INFO_21";
89         }
90
91         if (from->fields_present & SAMR_FIELD_LAST_LOGON) {
92                 unix_time = nt_time_to_unix(from->last_logon);
93                 stored_time = pdb_get_logon_time(to);
94                 DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l,
95                         (long unsigned int)stored_time,
96                         (long unsigned int)unix_time));
97                 if (stored_time != unix_time) {
98                         pdb_set_logon_time(to, unix_time, PDB_CHANGED);
99                 }
100         }
101
102         if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) {
103                 unix_time = nt_time_to_unix(from->last_logoff);
104                 stored_time = pdb_get_logoff_time(to);
105                 DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l,
106                         (long unsigned int)stored_time,
107                         (long unsigned int)unix_time));
108                 if (stored_time != unix_time) {
109                         pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
110                 }
111         }
112
113         if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) {
114                 unix_time = nt_time_to_unix(from->acct_expiry);
115                 stored_time = pdb_get_kickoff_time(to);
116                 DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l,
117                         (long unsigned int)stored_time,
118                         (long unsigned int)unix_time));
119                 if (stored_time != unix_time) {
120                         pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
121                 }
122         }
123
124         if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
125                 unix_time = nt_time_to_unix(from->last_password_change);
126                 stored_time = pdb_get_pass_last_set_time(to);
127                 DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l,
128                         (long unsigned int)stored_time,
129                         (long unsigned int)unix_time));
130                 if (stored_time != unix_time) {
131                         pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
132                 }
133         }
134
135         if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) &&
136             (from->account_name.string)) {
137                 old_string = pdb_get_username(to);
138                 new_string = from->account_name.string;
139                 DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l,
140                         old_string, new_string));
141                 if (STRING_CHANGED) {
142                         pdb_set_username(to, new_string, PDB_CHANGED);
143                 }
144         }
145
146         if ((from->fields_present & SAMR_FIELD_FULL_NAME) &&
147             (from->full_name.string)) {
148                 old_string = pdb_get_fullname(to);
149                 new_string = from->full_name.string;
150                 DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l,
151                         old_string, new_string));
152                 if (STRING_CHANGED) {
153                         pdb_set_fullname(to, new_string, PDB_CHANGED);
154                 }
155         }
156
157         if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) &&
158             (from->home_directory.string)) {
159                 old_string = pdb_get_homedir(to);
160                 new_string = from->home_directory.string;
161                 DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l,
162                         old_string, new_string));
163                 if (STRING_CHANGED) {
164                         pdb_set_homedir(to, new_string, PDB_CHANGED);
165                 }
166         }
167
168         if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) &&
169             (from->home_drive.string)) {
170                 old_string = pdb_get_dir_drive(to);
171                 new_string = from->home_drive.string;
172                 DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l,
173                         old_string, new_string));
174                 if (STRING_CHANGED) {
175                         pdb_set_dir_drive(to, new_string, PDB_CHANGED);
176                 }
177         }
178
179         if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) &&
180             (from->logon_script.string)) {
181                 old_string = pdb_get_logon_script(to);
182                 new_string = from->logon_script.string;
183                 DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l,
184                         old_string, new_string));
185                 if (STRING_CHANGED) {
186                         pdb_set_logon_script(to  , new_string, PDB_CHANGED);
187                 }
188         }
189
190         if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) &&
191             (from->profile_path.string)) {
192                 old_string = pdb_get_profile_path(to);
193                 new_string = from->profile_path.string;
194                 DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l,
195                         old_string, new_string));
196                 if (STRING_CHANGED) {
197                         pdb_set_profile_path(to  , new_string, PDB_CHANGED);
198                 }
199         }
200
201         if ((from->fields_present & SAMR_FIELD_DESCRIPTION) &&
202             (from->description.string)) {
203                 old_string = pdb_get_acct_desc(to);
204                 new_string = from->description.string;
205                 DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l,
206                         old_string, new_string));
207                 if (STRING_CHANGED) {
208                         pdb_set_acct_desc(to, new_string, PDB_CHANGED);
209                 }
210         }
211
212         if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) &&
213             (from->workstations.string)) {
214                 old_string = pdb_get_workstations(to);
215                 new_string = from->workstations.string;
216                 DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l,
217                         old_string, new_string));
218                 if (STRING_CHANGED) {
219                         pdb_set_workstations(to  , new_string, PDB_CHANGED);
220                 }
221         }
222
223         if ((from->fields_present & SAMR_FIELD_COMMENT) &&
224             (from->comment.string)) {
225                 old_string = pdb_get_comment(to);
226                 new_string = from->comment.string;
227                 DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l,
228                         old_string, new_string));
229                 if (STRING_CHANGED) {
230                         pdb_set_comment(to, new_string, PDB_CHANGED);
231                 }
232         }
233
234         if ((from->fields_present & SAMR_FIELD_PARAMETERS) &&
235             (from->parameters.array)) {
236                 char *newstr;
237                 DATA_BLOB mung;
238                 old_string = pdb_get_munged_dial(to);
239
240                 mung = data_blob_const(from->parameters.array,
241                                        from->parameters.length);
242                 newstr = (mung.length == 0) ?
243                         NULL : base64_encode_data_blob(talloc_tos(), mung);
244                 DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l,
245                         old_string, newstr));
246                 if (STRING_CHANGED_NC(old_string,newstr)) {
247                         pdb_set_munged_dial(to, newstr, PDB_CHANGED);
248                 }
249
250                 TALLOC_FREE(newstr);
251         }
252
253         if (from->fields_present & SAMR_FIELD_RID) {
254                 if (from->rid == 0) {
255                         DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l));
256                 } else if (from->rid != pdb_get_user_rid(to)) {
257                         DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l,
258                                 pdb_get_user_rid(to), from->rid));
259                 }
260         }
261
262         if (from->fields_present & SAMR_FIELD_PRIMARY_GID) {
263                 if (from->primary_gid == 0) {
264                         DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l));
265                 } else if (from->primary_gid != pdb_get_group_rid(to)) {
266                         DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l,
267                                 pdb_get_group_rid(to), from->primary_gid));
268                         pdb_set_group_sid_from_rid(to,
269                                 from->primary_gid, PDB_CHANGED);
270                 }
271         }
272
273         if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) {
274                 DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l,
275                         pdb_get_acct_ctrl(to), from->acct_flags));
276                 if (from->acct_flags != pdb_get_acct_ctrl(to)) {
277                         if (!(from->acct_flags & ACB_AUTOLOCK) &&
278                              (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
279                                 /* We're unlocking a previously locked user. Reset bad password counts.
280                                    Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
281                                 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
282                                 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
283                         }
284                         pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED);
285                 }
286         }
287
288         if (from->fields_present & SAMR_FIELD_LOGON_HOURS) {
289                 char oldstr[44]; /* hours strings are 42 bytes. */
290                 char newstr[44];
291                 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l,
292                         pdb_get_logon_divs(to), from->logon_hours.units_per_week));
293                 if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) {
294                         pdb_set_logon_divs(to,
295                                 from->logon_hours.units_per_week, PDB_CHANGED);
296                 }
297
298                 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l,
299                         pdb_get_hours_len(to),
300                         from->logon_hours.units_per_week/8));
301                 if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) {
302                         pdb_set_hours_len(to,
303                                 from->logon_hours.units_per_week/8, PDB_CHANGED);
304                 }
305
306                 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l,
307                         pdb_get_hours(to), from->logon_hours.bits));
308                 pdb_sethexhours(oldstr, pdb_get_hours(to));
309                 pdb_sethexhours(newstr, from->logon_hours.bits);
310                 if (!strequal(oldstr, newstr)) {
311                         pdb_set_hours(to, from->logon_hours.bits, PDB_CHANGED);
312                 }
313         }
314
315         if (from->fields_present & SAMR_FIELD_BAD_PWD_COUNT) {
316                 DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l,
317                         pdb_get_bad_password_count(to), from->bad_password_count));
318                 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
319                         pdb_set_bad_password_count(to,
320                                 from->bad_password_count, PDB_CHANGED);
321                 }
322         }
323
324         if (from->fields_present & SAMR_FIELD_NUM_LOGONS) {
325                 DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l,
326                         pdb_get_logon_count(to), from->logon_count));
327                 if (from->logon_count != pdb_get_logon_count(to)) {
328                         pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
329                 }
330         }
331
332         /* If the must change flag is set, the last set time goes to zero.
333            the must change and can change fields also do, but they are
334            calculated from policy, not set from the wire */
335
336         if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) {
337                 DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l,
338                         from->password_expired));
339                 if (from->password_expired == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
340                         pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
341                 } else {
342                         pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
343                 }
344         }
345 }
346
347
348 /*************************************************************
349  Copies a struct samr_UserInfo23 to a struct samu
350 **************************************************************/
351
352 void copy_id23_to_sam_passwd(struct samu *to,
353                              struct samr_UserInfo23 *from)
354 {
355         if (from == NULL || to == NULL) {
356                 return;
357         }
358
359         copy_id21_to_sam_passwd("INFO 23", to, &from->info);
360 }
361
362 /*************************************************************
363  Copies a struct samr_UserInfo25 to a struct samu
364 **************************************************************/
365
366 void copy_id25_to_sam_passwd(struct samu *to,
367                              struct samr_UserInfo25 *from)
368 {
369         if (from == NULL || to == NULL) {
370                 return;
371         }
372
373         copy_id21_to_sam_passwd("INFO_25", to, &from->info);
374 }