Fix bug 7104 - "wide links" and "unix extensions" are incompatible.
[Samba.git] / source / rpc_server / srv_samr_util.c
blob068156054f00ccaffe289fc30a49656399dbfb48
1 /*
2 Unix SMB/CIFS implementation.
3 SAMR Pipe utility functions.
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
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.
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.
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/>.
25 #include "includes.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
30 #define STRING_CHANGED (old_string && !new_string) ||\
31 (!old_string && new_string) ||\
32 (old_string && new_string && (strcmp(old_string, new_string) != 0))
34 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
35 (!(s1) && (s2)) ||\
36 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
38 /*************************************************************
39 Copies a struct samr_UserInfo18 to a struct samu
40 **************************************************************/
42 void copy_id18_to_sam_passwd(struct samu *to,
43 struct samr_UserInfo18 *from)
45 struct samr_UserInfo21 i;
47 if (from == NULL || to == NULL) {
48 return;
51 ZERO_STRUCT(i);
53 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
54 i.password_expired = from->password_expired;
56 copy_id21_to_sam_passwd("INFO_18", to, &i);
59 /*************************************************************
60 Copies a struct samr_UserInfo20 to a struct samu
61 **************************************************************/
63 void copy_id20_to_sam_passwd(struct samu *to,
64 struct samr_UserInfo20 *from)
66 const char *old_string;
67 char *new_string;
68 DATA_BLOB mung;
70 if (from == NULL || to == NULL) {
71 return;
74 if (from->parameters.array) {
75 old_string = pdb_get_munged_dial(to);
76 mung = data_blob_const(from->parameters.array,
77 from->parameters.length);
78 new_string = (mung.length == 0) ?
79 NULL : base64_encode_data_blob(talloc_tos(), mung);
80 DEBUG(10,("INFO_20 PARAMETERS: %s -> %s\n",
81 old_string, new_string));
82 if (STRING_CHANGED_NC(old_string,new_string)) {
83 pdb_set_munged_dial(to, new_string, PDB_CHANGED);
86 TALLOC_FREE(new_string);
90 /*************************************************************
91 Copies a struct samr_UserInfo21 to a struct samu
92 **************************************************************/
94 void copy_id21_to_sam_passwd(const char *log_prefix,
95 struct samu *to,
96 struct samr_UserInfo21 *from)
98 time_t unix_time, stored_time;
99 const char *old_string, *new_string;
100 const char *l;
102 if (from == NULL || to == NULL) {
103 return;
106 if (log_prefix) {
107 l = log_prefix;
108 } else {
109 l = "INFO_21";
112 if (from->fields_present & SAMR_FIELD_LAST_LOGON) {
113 unix_time = nt_time_to_unix(from->last_logon);
114 stored_time = pdb_get_logon_time(to);
115 DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l,
116 (long unsigned int)stored_time,
117 (long unsigned int)unix_time));
118 if (stored_time != unix_time) {
119 pdb_set_logon_time(to, unix_time, PDB_CHANGED);
123 if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) {
124 unix_time = nt_time_to_unix(from->last_logoff);
125 stored_time = pdb_get_logoff_time(to);
126 DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l,
127 (long unsigned int)stored_time,
128 (long unsigned int)unix_time));
129 if (stored_time != unix_time) {
130 pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
134 if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) {
135 unix_time = nt_time_to_unix(from->acct_expiry);
136 stored_time = pdb_get_kickoff_time(to);
137 DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l,
138 (long unsigned int)stored_time,
139 (long unsigned int)unix_time));
140 if (stored_time != unix_time) {
141 pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
145 if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
146 unix_time = nt_time_to_unix(from->last_password_change);
147 stored_time = pdb_get_pass_last_set_time(to);
148 DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l,
149 (long unsigned int)stored_time,
150 (long unsigned int)unix_time));
151 if (stored_time != unix_time) {
152 pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
156 if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) &&
157 (from->account_name.string)) {
158 old_string = pdb_get_username(to);
159 new_string = from->account_name.string;
160 DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l,
161 old_string, new_string));
162 if (STRING_CHANGED) {
163 pdb_set_username(to, new_string, PDB_CHANGED);
167 if ((from->fields_present & SAMR_FIELD_FULL_NAME) &&
168 (from->full_name.string)) {
169 old_string = pdb_get_fullname(to);
170 new_string = from->full_name.string;
171 DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l,
172 old_string, new_string));
173 if (STRING_CHANGED) {
174 pdb_set_fullname(to, new_string, PDB_CHANGED);
178 if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) &&
179 (from->home_directory.string)) {
180 old_string = pdb_get_homedir(to);
181 new_string = from->home_directory.string;
182 DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l,
183 old_string, new_string));
184 if (STRING_CHANGED) {
185 pdb_set_homedir(to, new_string, PDB_CHANGED);
189 if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) &&
190 (from->home_drive.string)) {
191 old_string = pdb_get_dir_drive(to);
192 new_string = from->home_drive.string;
193 DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l,
194 old_string, new_string));
195 if (STRING_CHANGED) {
196 pdb_set_dir_drive(to, new_string, PDB_CHANGED);
200 if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) &&
201 (from->logon_script.string)) {
202 old_string = pdb_get_logon_script(to);
203 new_string = from->logon_script.string;
204 DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l,
205 old_string, new_string));
206 if (STRING_CHANGED) {
207 pdb_set_logon_script(to , new_string, PDB_CHANGED);
211 if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) &&
212 (from->profile_path.string)) {
213 old_string = pdb_get_profile_path(to);
214 new_string = from->profile_path.string;
215 DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l,
216 old_string, new_string));
217 if (STRING_CHANGED) {
218 pdb_set_profile_path(to , new_string, PDB_CHANGED);
222 if ((from->fields_present & SAMR_FIELD_DESCRIPTION) &&
223 (from->description.string)) {
224 old_string = pdb_get_acct_desc(to);
225 new_string = from->description.string;
226 DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l,
227 old_string, new_string));
228 if (STRING_CHANGED) {
229 pdb_set_acct_desc(to, new_string, PDB_CHANGED);
233 if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) &&
234 (from->workstations.string)) {
235 old_string = pdb_get_workstations(to);
236 new_string = from->workstations.string;
237 DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l,
238 old_string, new_string));
239 if (STRING_CHANGED) {
240 pdb_set_workstations(to , new_string, PDB_CHANGED);
244 if ((from->fields_present & SAMR_FIELD_COMMENT) &&
245 (from->comment.string)) {
246 old_string = pdb_get_comment(to);
247 new_string = from->comment.string;
248 DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l,
249 old_string, new_string));
250 if (STRING_CHANGED) {
251 pdb_set_comment(to, new_string, PDB_CHANGED);
255 if ((from->fields_present & SAMR_FIELD_PARAMETERS) &&
256 (from->parameters.array)) {
257 char *newstr;
258 DATA_BLOB mung;
259 old_string = pdb_get_munged_dial(to);
261 mung = data_blob_const(from->parameters.array,
262 from->parameters.length);
263 newstr = (mung.length == 0) ?
264 NULL : base64_encode_data_blob(talloc_tos(), mung);
265 DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l,
266 old_string, newstr));
267 if (STRING_CHANGED_NC(old_string,newstr)) {
268 pdb_set_munged_dial(to, newstr, PDB_CHANGED);
271 TALLOC_FREE(newstr);
274 if (from->fields_present & SAMR_FIELD_RID) {
275 if (from->rid == 0) {
276 DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l));
277 } else if (from->rid != pdb_get_user_rid(to)) {
278 DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l,
279 pdb_get_user_rid(to), from->rid));
283 if (from->fields_present & SAMR_FIELD_PRIMARY_GID) {
284 if (from->primary_gid == 0) {
285 DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l));
286 } else if (from->primary_gid != pdb_get_group_rid(to)) {
287 DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l,
288 pdb_get_group_rid(to), from->primary_gid));
289 pdb_set_group_sid_from_rid(to,
290 from->primary_gid, PDB_CHANGED);
294 if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) {
295 DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l,
296 pdb_get_acct_ctrl(to), from->acct_flags));
297 if (from->acct_flags != pdb_get_acct_ctrl(to)) {
298 if (!(from->acct_flags & ACB_AUTOLOCK) &&
299 (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
300 /* We're unlocking a previously locked user. Reset bad password counts.
301 Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
302 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
303 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
305 pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED);
309 if (from->fields_present & SAMR_FIELD_LOGON_HOURS) {
310 char oldstr[44]; /* hours strings are 42 bytes. */
311 char newstr[44];
312 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l,
313 pdb_get_logon_divs(to), from->logon_hours.units_per_week));
314 if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) {
315 pdb_set_logon_divs(to,
316 from->logon_hours.units_per_week, PDB_CHANGED);
319 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l,
320 pdb_get_hours_len(to),
321 from->logon_hours.units_per_week/8));
322 if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) {
323 pdb_set_hours_len(to,
324 from->logon_hours.units_per_week/8, PDB_CHANGED);
327 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l,
328 pdb_get_hours(to), from->logon_hours.bits));
329 pdb_sethexhours(oldstr, pdb_get_hours(to));
330 pdb_sethexhours(newstr, from->logon_hours.bits);
331 if (!strequal(oldstr, newstr)) {
332 pdb_set_hours(to, from->logon_hours.bits, PDB_CHANGED);
336 if (from->fields_present & SAMR_FIELD_BAD_PWD_COUNT) {
337 DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l,
338 pdb_get_bad_password_count(to), from->bad_password_count));
339 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
340 pdb_set_bad_password_count(to,
341 from->bad_password_count, PDB_CHANGED);
345 if (from->fields_present & SAMR_FIELD_NUM_LOGONS) {
346 DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l,
347 pdb_get_logon_count(to), from->logon_count));
348 if (from->logon_count != pdb_get_logon_count(to)) {
349 pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
353 /* If the must change flag is set, the last set time goes to zero.
354 the must change and can change fields also do, but they are
355 calculated from policy, not set from the wire */
357 if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) {
358 DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l,
359 from->password_expired));
360 if (from->password_expired != 0) {
361 pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
362 } else {
363 /* A subtlety here: some windows commands will
364 clear the expired flag even though it's not
365 set, and we don't want to reset the time
366 in these caess. "net user /dom <user> /active:y"
367 for example, to clear an autolocked acct.
368 We must check to see if it's expired first. jmcd */
370 uint32_t pwd_max_age = 0;
371 time_t now = time(NULL);
373 pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &pwd_max_age);
375 if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) {
376 pwd_max_age = get_time_t_max();
379 stored_time = pdb_get_pass_last_set_time(to);
381 /* we will only *set* a pwdlastset date when
382 a) the last pwdlastset time was 0 (user was forced to
383 change password).
384 b) the users password has not expired. gd. */
386 if ((stored_time == 0) ||
387 ((now - stored_time) > pwd_max_age)) {
388 pdb_set_pass_last_set_time(to, now, PDB_CHANGED);
395 /*************************************************************
396 Copies a struct samr_UserInfo23 to a struct samu
397 **************************************************************/
399 void copy_id23_to_sam_passwd(struct samu *to,
400 struct samr_UserInfo23 *from)
402 if (from == NULL || to == NULL) {
403 return;
406 copy_id21_to_sam_passwd("INFO 23", to, &from->info);
409 /*************************************************************
410 Copies a struct samr_UserInfo24 to a struct samu
411 **************************************************************/
413 void copy_id24_to_sam_passwd(struct samu *to,
414 struct samr_UserInfo24 *from)
416 struct samr_UserInfo21 i;
418 if (from == NULL || to == NULL) {
419 return;
422 ZERO_STRUCT(i);
424 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
425 i.password_expired = from->password_expired;
427 copy_id21_to_sam_passwd("INFO_24", to, &i);
430 /*************************************************************
431 Copies a struct samr_UserInfo25 to a struct samu
432 **************************************************************/
434 void copy_id25_to_sam_passwd(struct samu *to,
435 struct samr_UserInfo25 *from)
437 if (from == NULL || to == NULL) {
438 return;
441 copy_id21_to_sam_passwd("INFO_25", to, &from->info);
444 /*************************************************************
445 Copies a struct samr_UserInfo26 to a struct samu
446 **************************************************************/
448 void copy_id26_to_sam_passwd(struct samu *to,
449 struct samr_UserInfo26 *from)
451 struct samr_UserInfo21 i;
453 if (from == NULL || to == NULL) {
454 return;
457 ZERO_STRUCT(i);
459 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
460 i.password_expired = from->password_expired;
462 copy_id21_to_sam_passwd("INFO_26", to, &i);