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