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/>.
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)) ||\
36 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
38 /*************************************************************
39 Copies a struct samr_UserInfo2 to a struct samu
40 **************************************************************/
42 void copy_id2_to_sam_passwd(struct samu *to,
43 struct samr_UserInfo2 *from)
45 struct samr_UserInfo21 i;
47 if (from == NULL || to == NULL) {
53 i.fields_present = SAMR_FIELD_COMMENT |
54 SAMR_FIELD_COUNTRY_CODE |
56 i.comment = from->comment;
57 i.country_code = from->country_code;
58 i.code_page = from->code_page;
60 copy_id21_to_sam_passwd("INFO_2", to, &i);
63 /*************************************************************
64 Copies a struct samr_UserInfo4 to a struct samu
65 **************************************************************/
67 void copy_id4_to_sam_passwd(struct samu *to,
68 struct samr_UserInfo4 *from)
70 struct samr_UserInfo21 i;
72 if (from == NULL || to == NULL) {
78 i.fields_present = SAMR_FIELD_LOGON_HOURS;
79 i.logon_hours = from->logon_hours;
81 copy_id21_to_sam_passwd("INFO_4", to, &i);
84 /*************************************************************
85 Copies a struct samr_UserInfo6 to a struct samu
86 **************************************************************/
88 void copy_id6_to_sam_passwd(struct samu *to,
89 struct samr_UserInfo6 *from)
91 struct samr_UserInfo21 i;
93 if (from == NULL || to == NULL) {
99 i.fields_present = SAMR_FIELD_ACCOUNT_NAME |
100 SAMR_FIELD_FULL_NAME;
101 i.account_name = from->account_name;
102 i.full_name = from->full_name;
104 copy_id21_to_sam_passwd("INFO_6", to, &i);
107 /*************************************************************
108 Copies a struct samr_UserInfo8 to a struct samu
109 **************************************************************/
111 void copy_id8_to_sam_passwd(struct samu *to,
112 struct samr_UserInfo8 *from)
114 struct samr_UserInfo21 i;
116 if (from == NULL || to == NULL) {
122 i.fields_present = SAMR_FIELD_FULL_NAME;
123 i.full_name = from->full_name;
125 copy_id21_to_sam_passwd("INFO_8", to, &i);
128 /*************************************************************
129 Copies a struct samr_UserInfo10 to a struct samu
130 **************************************************************/
132 void copy_id10_to_sam_passwd(struct samu *to,
133 struct samr_UserInfo10 *from)
135 struct samr_UserInfo21 i;
137 if (from == NULL || to == NULL) {
143 i.fields_present = SAMR_FIELD_HOME_DIRECTORY |
144 SAMR_FIELD_HOME_DRIVE;
145 i.home_directory = from->home_directory;
146 i.home_drive = from->home_drive;
148 copy_id21_to_sam_passwd("INFO_10", to, &i);
151 /*************************************************************
152 Copies a struct samr_UserInfo11 to a struct samu
153 **************************************************************/
155 void copy_id11_to_sam_passwd(struct samu *to,
156 struct samr_UserInfo11 *from)
158 struct samr_UserInfo21 i;
160 if (from == NULL || to == NULL) {
166 i.fields_present = SAMR_FIELD_LOGON_SCRIPT;
167 i.logon_script = from->logon_script;
169 copy_id21_to_sam_passwd("INFO_11", to, &i);
172 /*************************************************************
173 Copies a struct samr_UserInfo12 to a struct samu
174 **************************************************************/
176 void copy_id12_to_sam_passwd(struct samu *to,
177 struct samr_UserInfo12 *from)
179 struct samr_UserInfo21 i;
181 if (from == NULL || to == NULL) {
187 i.fields_present = SAMR_FIELD_PROFILE_PATH;
188 i.profile_path = from->profile_path;
190 copy_id21_to_sam_passwd("INFO_12", to, &i);
193 /*************************************************************
194 Copies a struct samr_UserInfo13 to a struct samu
195 **************************************************************/
197 void copy_id13_to_sam_passwd(struct samu *to,
198 struct samr_UserInfo13 *from)
200 struct samr_UserInfo21 i;
202 if (from == NULL || to == NULL) {
208 i.fields_present = SAMR_FIELD_DESCRIPTION;
209 i.description = from->description;
211 copy_id21_to_sam_passwd("INFO_13", to, &i);
214 /*************************************************************
215 Copies a struct samr_UserInfo14 to a struct samu
216 **************************************************************/
218 void copy_id14_to_sam_passwd(struct samu *to,
219 struct samr_UserInfo14 *from)
221 struct samr_UserInfo21 i;
223 if (from == NULL || to == NULL) {
229 i.fields_present = SAMR_FIELD_WORKSTATIONS;
230 i.workstations = from->workstations;
232 copy_id21_to_sam_passwd("INFO_14", to, &i);
235 /*************************************************************
236 Copies a struct samr_UserInfo16 to a struct samu
237 **************************************************************/
239 void copy_id16_to_sam_passwd(struct samu *to,
240 struct samr_UserInfo16 *from)
242 struct samr_UserInfo21 i;
244 if (from == NULL || to == NULL) {
250 i.fields_present = SAMR_FIELD_ACCT_FLAGS;
251 i.acct_flags = from->acct_flags;
253 copy_id21_to_sam_passwd("INFO_16", to, &i);
256 /*************************************************************
257 Copies a struct samr_UserInfo17 to a struct samu
258 **************************************************************/
260 void copy_id17_to_sam_passwd(struct samu *to,
261 struct samr_UserInfo17 *from)
263 struct samr_UserInfo21 i;
265 if (from == NULL || to == NULL) {
271 i.fields_present = SAMR_FIELD_ACCT_EXPIRY;
272 i.acct_expiry = from->acct_expiry;
274 copy_id21_to_sam_passwd("INFO_17", to, &i);
277 /*************************************************************
278 Copies a struct samr_UserInfo18 to a struct samu
279 **************************************************************/
281 void copy_id18_to_sam_passwd(struct samu *to,
282 struct samr_UserInfo18 *from)
284 struct samr_UserInfo21 i;
286 if (from == NULL || to == NULL) {
292 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
293 i.password_expired = from->password_expired;
295 copy_id21_to_sam_passwd("INFO_18", to, &i);
298 /*************************************************************
299 Copies a struct samr_UserInfo20 to a struct samu
300 **************************************************************/
302 void copy_id20_to_sam_passwd(struct samu *to,
303 struct samr_UserInfo20 *from)
305 const char *old_string;
309 if (from == NULL || to == NULL) {
313 if (from->parameters.array) {
314 old_string = pdb_get_munged_dial(to);
315 mung = data_blob_const(from->parameters.array,
316 from->parameters.length);
317 new_string = (mung.length == 0) ?
318 NULL : base64_encode_data_blob(talloc_tos(), mung);
319 DEBUG(10,("INFO_20 PARAMETERS: %s -> %s\n",
320 old_string, new_string));
321 if (STRING_CHANGED_NC(old_string,new_string)) {
322 pdb_set_munged_dial(to, new_string, PDB_CHANGED);
325 TALLOC_FREE(new_string);
329 /*************************************************************
330 Copies a struct samr_UserInfo21 to a struct samu
331 **************************************************************/
333 void copy_id21_to_sam_passwd(const char *log_prefix,
335 struct samr_UserInfo21 *from)
337 time_t unix_time, stored_time;
338 const char *old_string, *new_string;
341 if (from == NULL || to == NULL) {
351 if (from->fields_present & SAMR_FIELD_LAST_LOGON) {
352 unix_time = nt_time_to_unix(from->last_logon);
353 stored_time = pdb_get_logon_time(to);
354 DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l,
355 (long unsigned int)stored_time,
356 (long unsigned int)unix_time));
357 if (stored_time != unix_time) {
358 pdb_set_logon_time(to, unix_time, PDB_CHANGED);
362 if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) {
363 unix_time = nt_time_to_unix(from->last_logoff);
364 stored_time = pdb_get_logoff_time(to);
365 DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l,
366 (long unsigned int)stored_time,
367 (long unsigned int)unix_time));
368 if (stored_time != unix_time) {
369 pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
373 if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) {
374 unix_time = nt_time_to_unix(from->acct_expiry);
375 stored_time = pdb_get_kickoff_time(to);
376 DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l,
377 (long unsigned int)stored_time,
378 (long unsigned int)unix_time));
379 if (stored_time != unix_time) {
380 pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
384 if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
385 unix_time = nt_time_to_unix(from->last_password_change);
386 stored_time = pdb_get_pass_last_set_time(to);
387 DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l,
388 (long unsigned int)stored_time,
389 (long unsigned int)unix_time));
390 if (stored_time != unix_time) {
391 pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
395 if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) &&
396 (from->account_name.string)) {
397 old_string = pdb_get_username(to);
398 new_string = from->account_name.string;
399 DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l,
400 old_string, new_string));
401 if (STRING_CHANGED) {
402 pdb_set_username(to, new_string, PDB_CHANGED);
406 if ((from->fields_present & SAMR_FIELD_FULL_NAME) &&
407 (from->full_name.string)) {
408 old_string = pdb_get_fullname(to);
409 new_string = from->full_name.string;
410 DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l,
411 old_string, new_string));
412 if (STRING_CHANGED) {
413 pdb_set_fullname(to, new_string, PDB_CHANGED);
417 if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) &&
418 (from->home_directory.string)) {
419 old_string = pdb_get_homedir(to);
420 new_string = from->home_directory.string;
421 DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l,
422 old_string, new_string));
423 if (STRING_CHANGED) {
424 pdb_set_homedir(to, new_string, PDB_CHANGED);
428 if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) &&
429 (from->home_drive.string)) {
430 old_string = pdb_get_dir_drive(to);
431 new_string = from->home_drive.string;
432 DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l,
433 old_string, new_string));
434 if (STRING_CHANGED) {
435 pdb_set_dir_drive(to, new_string, PDB_CHANGED);
439 if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) &&
440 (from->logon_script.string)) {
441 old_string = pdb_get_logon_script(to);
442 new_string = from->logon_script.string;
443 DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l,
444 old_string, new_string));
445 if (STRING_CHANGED) {
446 pdb_set_logon_script(to , new_string, PDB_CHANGED);
450 if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) &&
451 (from->profile_path.string)) {
452 old_string = pdb_get_profile_path(to);
453 new_string = from->profile_path.string;
454 DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l,
455 old_string, new_string));
456 if (STRING_CHANGED) {
457 pdb_set_profile_path(to , new_string, PDB_CHANGED);
461 if ((from->fields_present & SAMR_FIELD_DESCRIPTION) &&
462 (from->description.string)) {
463 old_string = pdb_get_acct_desc(to);
464 new_string = from->description.string;
465 DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l,
466 old_string, new_string));
467 if (STRING_CHANGED) {
468 pdb_set_acct_desc(to, new_string, PDB_CHANGED);
472 if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) &&
473 (from->workstations.string)) {
474 old_string = pdb_get_workstations(to);
475 new_string = from->workstations.string;
476 DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l,
477 old_string, new_string));
478 if (STRING_CHANGED) {
479 pdb_set_workstations(to , new_string, PDB_CHANGED);
483 if ((from->fields_present & SAMR_FIELD_COMMENT) &&
484 (from->comment.string)) {
485 old_string = pdb_get_comment(to);
486 new_string = from->comment.string;
487 DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l,
488 old_string, new_string));
489 if (STRING_CHANGED) {
490 pdb_set_comment(to, new_string, PDB_CHANGED);
494 if ((from->fields_present & SAMR_FIELD_PARAMETERS) &&
495 (from->parameters.array)) {
498 old_string = pdb_get_munged_dial(to);
500 mung = data_blob_const(from->parameters.array,
501 from->parameters.length);
502 newstr = (mung.length == 0) ?
503 NULL : base64_encode_data_blob(talloc_tos(), mung);
504 DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l,
505 old_string, newstr));
506 if (STRING_CHANGED_NC(old_string,newstr)) {
507 pdb_set_munged_dial(to, newstr, PDB_CHANGED);
513 if (from->fields_present & SAMR_FIELD_RID) {
514 if (from->rid == 0) {
515 DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l));
516 } else if (from->rid != pdb_get_user_rid(to)) {
517 DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l,
518 pdb_get_user_rid(to), from->rid));
522 if (from->fields_present & SAMR_FIELD_PRIMARY_GID) {
523 if (from->primary_gid == 0) {
524 DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l));
525 } else if (from->primary_gid != pdb_get_group_rid(to)) {
526 DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l,
527 pdb_get_group_rid(to), from->primary_gid));
528 pdb_set_group_sid_from_rid(to,
529 from->primary_gid, PDB_CHANGED);
533 if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) {
534 DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l,
535 pdb_get_acct_ctrl(to), from->acct_flags));
536 if (from->acct_flags != pdb_get_acct_ctrl(to)) {
537 if (!(from->acct_flags & ACB_AUTOLOCK) &&
538 (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
539 /* We're unlocking a previously locked user. Reset bad password counts.
540 Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
541 pdb_set_bad_password_count(to, 0, PDB_CHANGED);
542 pdb_set_bad_password_time(to, 0, PDB_CHANGED);
544 pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED);
548 if (from->fields_present & SAMR_FIELD_LOGON_HOURS) {
549 char oldstr[44]; /* hours strings are 42 bytes. */
551 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l,
552 pdb_get_logon_divs(to), from->logon_hours.units_per_week));
553 if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) {
554 pdb_set_logon_divs(to,
555 from->logon_hours.units_per_week, PDB_CHANGED);
558 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l,
559 pdb_get_hours_len(to),
560 from->logon_hours.units_per_week/8));
561 if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) {
562 pdb_set_hours_len(to,
563 from->logon_hours.units_per_week/8, PDB_CHANGED);
566 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l,
567 pdb_get_hours(to), from->logon_hours.bits));
568 pdb_sethexhours(oldstr, pdb_get_hours(to));
569 pdb_sethexhours(newstr, from->logon_hours.bits);
570 if (!strequal(oldstr, newstr)) {
571 pdb_set_hours(to, from->logon_hours.bits, PDB_CHANGED);
575 if (from->fields_present & SAMR_FIELD_BAD_PWD_COUNT) {
576 DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l,
577 pdb_get_bad_password_count(to), from->bad_password_count));
578 if (from->bad_password_count != pdb_get_bad_password_count(to)) {
579 pdb_set_bad_password_count(to,
580 from->bad_password_count, PDB_CHANGED);
584 if (from->fields_present & SAMR_FIELD_NUM_LOGONS) {
585 DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l,
586 pdb_get_logon_count(to), from->logon_count));
587 if (from->logon_count != pdb_get_logon_count(to)) {
588 pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
592 /* If the must change flag is set, the last set time goes to zero.
593 the must change and can change fields also do, but they are
594 calculated from policy, not set from the wire */
596 if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) {
597 DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l,
598 from->password_expired));
599 if (from->password_expired != 0) {
600 pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
602 /* A subtlety here: some windows commands will
603 clear the expired flag even though it's not
604 set, and we don't want to reset the time
605 in these caess. "net user /dom <user> /active:y"
606 for example, to clear an autolocked acct.
607 We must check to see if it's expired first. jmcd */
609 uint32_t pwd_max_age = 0;
610 time_t now = time(NULL);
612 pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &pwd_max_age);
614 if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) {
615 pwd_max_age = get_time_t_max();
618 stored_time = pdb_get_pass_last_set_time(to);
620 /* we will only *set* a pwdlastset date when
621 a) the last pwdlastset time was 0 (user was forced to
623 b) the users password has not expired. gd. */
625 if ((stored_time == 0) ||
626 ((now - stored_time) > pwd_max_age)) {
627 pdb_set_pass_last_set_time(to, now, PDB_CHANGED);
634 /*************************************************************
635 Copies a struct samr_UserInfo23 to a struct samu
636 **************************************************************/
638 void copy_id23_to_sam_passwd(struct samu *to,
639 struct samr_UserInfo23 *from)
641 if (from == NULL || to == NULL) {
645 copy_id21_to_sam_passwd("INFO 23", to, &from->info);
648 /*************************************************************
649 Copies a struct samr_UserInfo24 to a struct samu
650 **************************************************************/
652 void copy_id24_to_sam_passwd(struct samu *to,
653 struct samr_UserInfo24 *from)
655 struct samr_UserInfo21 i;
657 if (from == NULL || to == NULL) {
663 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
664 i.password_expired = from->password_expired;
666 copy_id21_to_sam_passwd("INFO_24", to, &i);
669 /*************************************************************
670 Copies a struct samr_UserInfo25 to a struct samu
671 **************************************************************/
673 void copy_id25_to_sam_passwd(struct samu *to,
674 struct samr_UserInfo25 *from)
676 if (from == NULL || to == NULL) {
680 copy_id21_to_sam_passwd("INFO_25", to, &from->info);
683 /*************************************************************
684 Copies a struct samr_UserInfo26 to a struct samu
685 **************************************************************/
687 void copy_id26_to_sam_passwd(struct samu *to,
688 struct samr_UserInfo26 *from)
690 struct samr_UserInfo21 i;
692 if (from == NULL || to == NULL) {
698 i.fields_present = SAMR_FIELD_EXPIRED_FLAG;
699 i.password_expired = from->password_expired;
701 copy_id21_to_sam_passwd("INFO_26", to, &i);