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/>.
26 #include "../librpc/gen_ndr/samr.h"
27 #include "rpc_server/srv_samr_util.h"
30 #define DBGC_CLASS DBGC_RPC_SRV
32 #define STRING_CHANGED (old_string && !new_string) ||\
33 (!old_string && new_string) ||\
34 (old_string && new_string && (strcmp(old_string, new_string) != 0))
36 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
38 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
40 /*************************************************************
41 Copies a struct samr_UserInfo2 to a struct samu
42 **************************************************************/
44 void copy_id2_to_sam_passwd(struct samu
*to
,
45 struct samr_UserInfo2
*from
)
47 struct samr_UserInfo21 i
;
49 if (from
== NULL
|| to
== NULL
) {
55 i
.fields_present
= SAMR_FIELD_COMMENT
|
56 SAMR_FIELD_COUNTRY_CODE
|
58 i
.comment
= from
->comment
;
59 i
.country_code
= from
->country_code
;
60 i
.code_page
= from
->code_page
;
62 copy_id21_to_sam_passwd("INFO_2", to
, &i
);
65 /*************************************************************
66 Copies a struct samr_UserInfo4 to a struct samu
67 **************************************************************/
69 void copy_id4_to_sam_passwd(struct samu
*to
,
70 struct samr_UserInfo4
*from
)
72 struct samr_UserInfo21 i
;
74 if (from
== NULL
|| to
== NULL
) {
80 i
.fields_present
= SAMR_FIELD_LOGON_HOURS
;
81 i
.logon_hours
= from
->logon_hours
;
83 copy_id21_to_sam_passwd("INFO_4", to
, &i
);
86 /*************************************************************
87 Copies a struct samr_UserInfo6 to a struct samu
88 **************************************************************/
90 void copy_id6_to_sam_passwd(struct samu
*to
,
91 struct samr_UserInfo6
*from
)
93 struct samr_UserInfo21 i
;
95 if (from
== NULL
|| to
== NULL
) {
101 i
.fields_present
= SAMR_FIELD_ACCOUNT_NAME
|
102 SAMR_FIELD_FULL_NAME
;
103 i
.account_name
= from
->account_name
;
104 i
.full_name
= from
->full_name
;
106 copy_id21_to_sam_passwd("INFO_6", to
, &i
);
109 /*************************************************************
110 Copies a struct samr_UserInfo8 to a struct samu
111 **************************************************************/
113 void copy_id8_to_sam_passwd(struct samu
*to
,
114 struct samr_UserInfo8
*from
)
116 struct samr_UserInfo21 i
;
118 if (from
== NULL
|| to
== NULL
) {
124 i
.fields_present
= SAMR_FIELD_FULL_NAME
;
125 i
.full_name
= from
->full_name
;
127 copy_id21_to_sam_passwd("INFO_8", to
, &i
);
130 /*************************************************************
131 Copies a struct samr_UserInfo10 to a struct samu
132 **************************************************************/
134 void copy_id10_to_sam_passwd(struct samu
*to
,
135 struct samr_UserInfo10
*from
)
137 struct samr_UserInfo21 i
;
139 if (from
== NULL
|| to
== NULL
) {
145 i
.fields_present
= SAMR_FIELD_HOME_DIRECTORY
|
146 SAMR_FIELD_HOME_DRIVE
;
147 i
.home_directory
= from
->home_directory
;
148 i
.home_drive
= from
->home_drive
;
150 copy_id21_to_sam_passwd("INFO_10", to
, &i
);
153 /*************************************************************
154 Copies a struct samr_UserInfo11 to a struct samu
155 **************************************************************/
157 void copy_id11_to_sam_passwd(struct samu
*to
,
158 struct samr_UserInfo11
*from
)
160 struct samr_UserInfo21 i
;
162 if (from
== NULL
|| to
== NULL
) {
168 i
.fields_present
= SAMR_FIELD_LOGON_SCRIPT
;
169 i
.logon_script
= from
->logon_script
;
171 copy_id21_to_sam_passwd("INFO_11", to
, &i
);
174 /*************************************************************
175 Copies a struct samr_UserInfo12 to a struct samu
176 **************************************************************/
178 void copy_id12_to_sam_passwd(struct samu
*to
,
179 struct samr_UserInfo12
*from
)
181 struct samr_UserInfo21 i
;
183 if (from
== NULL
|| to
== NULL
) {
189 i
.fields_present
= SAMR_FIELD_PROFILE_PATH
;
190 i
.profile_path
= from
->profile_path
;
192 copy_id21_to_sam_passwd("INFO_12", to
, &i
);
195 /*************************************************************
196 Copies a struct samr_UserInfo13 to a struct samu
197 **************************************************************/
199 void copy_id13_to_sam_passwd(struct samu
*to
,
200 struct samr_UserInfo13
*from
)
202 struct samr_UserInfo21 i
;
204 if (from
== NULL
|| to
== NULL
) {
210 i
.fields_present
= SAMR_FIELD_DESCRIPTION
;
211 i
.description
= from
->description
;
213 copy_id21_to_sam_passwd("INFO_13", to
, &i
);
216 /*************************************************************
217 Copies a struct samr_UserInfo14 to a struct samu
218 **************************************************************/
220 void copy_id14_to_sam_passwd(struct samu
*to
,
221 struct samr_UserInfo14
*from
)
223 struct samr_UserInfo21 i
;
225 if (from
== NULL
|| to
== NULL
) {
231 i
.fields_present
= SAMR_FIELD_WORKSTATIONS
;
232 i
.workstations
= from
->workstations
;
234 copy_id21_to_sam_passwd("INFO_14", to
, &i
);
237 /*************************************************************
238 Copies a struct samr_UserInfo16 to a struct samu
239 **************************************************************/
241 void copy_id16_to_sam_passwd(struct samu
*to
,
242 struct samr_UserInfo16
*from
)
244 struct samr_UserInfo21 i
;
246 if (from
== NULL
|| to
== NULL
) {
252 i
.fields_present
= SAMR_FIELD_ACCT_FLAGS
;
253 i
.acct_flags
= from
->acct_flags
;
255 copy_id21_to_sam_passwd("INFO_16", to
, &i
);
258 /*************************************************************
259 Copies a struct samr_UserInfo17 to a struct samu
260 **************************************************************/
262 void copy_id17_to_sam_passwd(struct samu
*to
,
263 struct samr_UserInfo17
*from
)
265 struct samr_UserInfo21 i
;
267 if (from
== NULL
|| to
== NULL
) {
273 i
.fields_present
= SAMR_FIELD_ACCT_EXPIRY
;
274 i
.acct_expiry
= from
->acct_expiry
;
276 copy_id21_to_sam_passwd("INFO_17", to
, &i
);
279 /*************************************************************
280 Copies a struct samr_UserInfo18 to a struct samu
281 **************************************************************/
283 void copy_id18_to_sam_passwd(struct samu
*to
,
284 struct samr_UserInfo18
*from
)
286 struct samr_UserInfo21 i
;
288 if (from
== NULL
|| to
== NULL
) {
294 i
.fields_present
= SAMR_FIELD_EXPIRED_FLAG
;
295 i
.password_expired
= from
->password_expired
;
297 copy_id21_to_sam_passwd("INFO_18", to
, &i
);
300 /*************************************************************
301 Copies a struct samr_UserInfo20 to a struct samu
302 **************************************************************/
304 void copy_id20_to_sam_passwd(struct samu
*to
,
305 struct samr_UserInfo20
*from
)
307 const char *old_string
;
311 if (from
== NULL
|| to
== NULL
) {
315 if (from
->parameters
.array
) {
316 old_string
= pdb_get_munged_dial(to
);
317 mung
= data_blob_const(from
->parameters
.array
,
318 from
->parameters
.length
);
319 new_string
= (mung
.length
== 0) ?
320 NULL
: base64_encode_data_blob(talloc_tos(), mung
);
321 DEBUG(10,("INFO_20 PARAMETERS: %s -> %s\n",
322 old_string
, new_string
));
323 if (STRING_CHANGED_NC(old_string
,new_string
)) {
324 pdb_set_munged_dial(to
, new_string
, PDB_CHANGED
);
327 TALLOC_FREE(new_string
);
331 /*************************************************************
332 Copies a struct samr_UserInfo21 to a struct samu
333 **************************************************************/
335 void copy_id21_to_sam_passwd(const char *log_prefix
,
337 struct samr_UserInfo21
*from
)
339 time_t unix_time
, stored_time
;
340 const char *old_string
, *new_string
;
343 if (from
== NULL
|| to
== NULL
) {
353 if (from
->fields_present
& SAMR_FIELD_LAST_LOGON
) {
354 unix_time
= nt_time_to_unix(from
->last_logon
);
355 stored_time
= pdb_get_logon_time(to
);
356 DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l
,
357 (long unsigned int)stored_time
,
358 (long unsigned int)unix_time
));
359 if (stored_time
!= unix_time
) {
360 pdb_set_logon_time(to
, unix_time
, PDB_CHANGED
);
364 if (from
->fields_present
& SAMR_FIELD_LAST_LOGOFF
) {
365 unix_time
= nt_time_to_unix(from
->last_logoff
);
366 stored_time
= pdb_get_logoff_time(to
);
367 DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l
,
368 (long unsigned int)stored_time
,
369 (long unsigned int)unix_time
));
370 if (stored_time
!= unix_time
) {
371 pdb_set_logoff_time(to
, unix_time
, PDB_CHANGED
);
375 if (from
->fields_present
& SAMR_FIELD_ACCT_EXPIRY
) {
376 unix_time
= nt_time_to_unix(from
->acct_expiry
);
377 stored_time
= pdb_get_kickoff_time(to
);
378 DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l
,
379 (long unsigned int)stored_time
,
380 (long unsigned int)unix_time
));
381 if (stored_time
!= unix_time
) {
382 pdb_set_kickoff_time(to
, unix_time
, PDB_CHANGED
);
386 if (from
->fields_present
& SAMR_FIELD_LAST_PWD_CHANGE
) {
387 unix_time
= nt_time_to_unix(from
->last_password_change
);
388 stored_time
= pdb_get_pass_last_set_time(to
);
389 DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l
,
390 (long unsigned int)stored_time
,
391 (long unsigned int)unix_time
));
392 if (stored_time
!= unix_time
) {
393 pdb_set_pass_last_set_time(to
, unix_time
, PDB_CHANGED
);
397 if ((from
->fields_present
& SAMR_FIELD_ACCOUNT_NAME
) &&
398 (from
->account_name
.string
)) {
399 old_string
= pdb_get_username(to
);
400 new_string
= from
->account_name
.string
;
401 DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l
,
402 old_string
, new_string
));
403 if (STRING_CHANGED
) {
404 pdb_set_username(to
, new_string
, PDB_CHANGED
);
408 if ((from
->fields_present
& SAMR_FIELD_FULL_NAME
) &&
409 (from
->full_name
.string
)) {
410 old_string
= pdb_get_fullname(to
);
411 new_string
= from
->full_name
.string
;
412 DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l
,
413 old_string
, new_string
));
414 if (STRING_CHANGED
) {
415 pdb_set_fullname(to
, new_string
, PDB_CHANGED
);
419 if ((from
->fields_present
& SAMR_FIELD_HOME_DIRECTORY
) &&
420 (from
->home_directory
.string
)) {
421 old_string
= pdb_get_homedir(to
);
422 new_string
= from
->home_directory
.string
;
423 DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l
,
424 old_string
, new_string
));
425 if (STRING_CHANGED
) {
426 pdb_set_homedir(to
, new_string
, PDB_CHANGED
);
430 if ((from
->fields_present
& SAMR_FIELD_HOME_DRIVE
) &&
431 (from
->home_drive
.string
)) {
432 old_string
= pdb_get_dir_drive(to
);
433 new_string
= from
->home_drive
.string
;
434 DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l
,
435 old_string
, new_string
));
436 if (STRING_CHANGED
) {
437 pdb_set_dir_drive(to
, new_string
, PDB_CHANGED
);
441 if ((from
->fields_present
& SAMR_FIELD_LOGON_SCRIPT
) &&
442 (from
->logon_script
.string
)) {
443 old_string
= pdb_get_logon_script(to
);
444 new_string
= from
->logon_script
.string
;
445 DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l
,
446 old_string
, new_string
));
447 if (STRING_CHANGED
) {
448 pdb_set_logon_script(to
, new_string
, PDB_CHANGED
);
452 if ((from
->fields_present
& SAMR_FIELD_PROFILE_PATH
) &&
453 (from
->profile_path
.string
)) {
454 old_string
= pdb_get_profile_path(to
);
455 new_string
= from
->profile_path
.string
;
456 DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l
,
457 old_string
, new_string
));
458 if (STRING_CHANGED
) {
459 pdb_set_profile_path(to
, new_string
, PDB_CHANGED
);
463 if ((from
->fields_present
& SAMR_FIELD_DESCRIPTION
) &&
464 (from
->description
.string
)) {
465 old_string
= pdb_get_acct_desc(to
);
466 new_string
= from
->description
.string
;
467 DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l
,
468 old_string
, new_string
));
469 if (STRING_CHANGED
) {
470 pdb_set_acct_desc(to
, new_string
, PDB_CHANGED
);
474 if ((from
->fields_present
& SAMR_FIELD_WORKSTATIONS
) &&
475 (from
->workstations
.string
)) {
476 old_string
= pdb_get_workstations(to
);
477 new_string
= from
->workstations
.string
;
478 DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l
,
479 old_string
, new_string
));
480 if (STRING_CHANGED
) {
481 pdb_set_workstations(to
, new_string
, PDB_CHANGED
);
485 if ((from
->fields_present
& SAMR_FIELD_COMMENT
) &&
486 (from
->comment
.string
)) {
487 old_string
= pdb_get_comment(to
);
488 new_string
= from
->comment
.string
;
489 DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l
,
490 old_string
, new_string
));
491 if (STRING_CHANGED
) {
492 pdb_set_comment(to
, new_string
, PDB_CHANGED
);
496 if ((from
->fields_present
& SAMR_FIELD_PARAMETERS
) &&
497 (from
->parameters
.array
)) {
500 old_string
= pdb_get_munged_dial(to
);
502 mung
= data_blob_const(from
->parameters
.array
,
503 from
->parameters
.length
);
504 newstr
= (mung
.length
== 0) ?
505 NULL
: base64_encode_data_blob(talloc_tos(), mung
);
506 DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l
,
507 old_string
, newstr
));
508 if (STRING_CHANGED_NC(old_string
,newstr
)) {
509 pdb_set_munged_dial(to
, newstr
, PDB_CHANGED
);
515 if (from
->fields_present
& SAMR_FIELD_RID
) {
516 if (from
->rid
== 0) {
517 DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l
));
518 } else if (from
->rid
!= pdb_get_user_rid(to
)) {
519 DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l
,
520 pdb_get_user_rid(to
), from
->rid
));
524 if (from
->fields_present
& SAMR_FIELD_PRIMARY_GID
) {
525 if (from
->primary_gid
== 0) {
526 DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l
));
527 } else if (from
->primary_gid
!= pdb_get_group_rid(to
)) {
528 DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l
,
529 pdb_get_group_rid(to
), from
->primary_gid
));
530 pdb_set_group_sid_from_rid(to
,
531 from
->primary_gid
, PDB_CHANGED
);
535 if (from
->fields_present
& SAMR_FIELD_ACCT_FLAGS
) {
536 DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l
,
537 pdb_get_acct_ctrl(to
), from
->acct_flags
));
538 if (from
->acct_flags
!= pdb_get_acct_ctrl(to
)) {
540 /* You cannot autolock an unlocked account via
541 * setuserinfo calls, so make sure to remove the
542 * ACB_AUTOLOCK bit here - gd */
544 if ((from
->acct_flags
& ACB_AUTOLOCK
) &&
545 !(pdb_get_acct_ctrl(to
) & ACB_AUTOLOCK
)) {
546 from
->acct_flags
&= ~ACB_AUTOLOCK
;
549 if (!(from
->acct_flags
& ACB_AUTOLOCK
) &&
550 (pdb_get_acct_ctrl(to
) & ACB_AUTOLOCK
)) {
551 /* We're unlocking a previously locked user. Reset bad password counts.
552 Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */
553 pdb_set_bad_password_count(to
, 0, PDB_CHANGED
);
554 pdb_set_bad_password_time(to
, 0, PDB_CHANGED
);
556 pdb_set_acct_ctrl(to
, from
->acct_flags
, PDB_CHANGED
);
560 if (from
->fields_present
& SAMR_FIELD_LOGON_HOURS
) {
561 char oldstr
[44]; /* hours strings are 42 bytes. */
563 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l
,
564 pdb_get_logon_divs(to
), from
->logon_hours
.units_per_week
));
565 if (from
->logon_hours
.units_per_week
!= pdb_get_logon_divs(to
)) {
566 pdb_set_logon_divs(to
,
567 from
->logon_hours
.units_per_week
, PDB_CHANGED
);
570 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l
,
571 pdb_get_hours_len(to
),
572 from
->logon_hours
.units_per_week
/8));
573 if (from
->logon_hours
.units_per_week
/8 != pdb_get_hours_len(to
)) {
574 pdb_set_hours_len(to
,
575 from
->logon_hours
.units_per_week
/8, PDB_CHANGED
);
578 DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l
,
579 pdb_get_hours(to
), from
->logon_hours
.bits
));
580 pdb_sethexhours(oldstr
, pdb_get_hours(to
));
581 pdb_sethexhours(newstr
, from
->logon_hours
.bits
);
582 if (!strequal(oldstr
, newstr
)) {
583 pdb_set_hours(to
, from
->logon_hours
.bits
, PDB_CHANGED
);
587 if (from
->fields_present
& SAMR_FIELD_BAD_PWD_COUNT
) {
588 DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l
,
589 pdb_get_bad_password_count(to
), from
->bad_password_count
));
590 if (from
->bad_password_count
!= pdb_get_bad_password_count(to
)) {
591 pdb_set_bad_password_count(to
,
592 from
->bad_password_count
, PDB_CHANGED
);
596 if (from
->fields_present
& SAMR_FIELD_NUM_LOGONS
) {
597 DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l
,
598 pdb_get_logon_count(to
), from
->logon_count
));
599 if (from
->logon_count
!= pdb_get_logon_count(to
)) {
600 pdb_set_logon_count(to
, from
->logon_count
, PDB_CHANGED
);
604 /* If the must change flag is set, the last set time goes to zero.
605 the must change and can change fields also do, but they are
606 calculated from policy, not set from the wire */
608 if (from
->fields_present
& SAMR_FIELD_EXPIRED_FLAG
) {
609 DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l
,
610 from
->password_expired
));
611 if (from
->password_expired
!= 0) {
612 pdb_set_pass_last_set_time(to
, 0, PDB_CHANGED
);
614 /* A subtlety here: some windows commands will
615 clear the expired flag even though it's not
616 set, and we don't want to reset the time
617 in these caess. "net user /dom <user> /active:y"
618 for example, to clear an autolocked acct.
619 We must check to see if it's expired first. jmcd */
621 uint32_t pwd_max_age
= 0;
622 time_t now
= time(NULL
);
624 pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE
, &pwd_max_age
);
626 if (pwd_max_age
== (uint32_t)-1 || pwd_max_age
== 0) {
627 pwd_max_age
= get_time_t_max();
630 stored_time
= pdb_get_pass_last_set_time(to
);
632 /* we will only *set* a pwdlastset date when
633 a) the last pwdlastset time was 0 (user was forced to
635 b) the users password has not expired. gd. */
637 if ((stored_time
== 0) ||
638 ((now
- stored_time
) > pwd_max_age
)) {
639 pdb_set_pass_last_set_time(to
, now
, PDB_CHANGED
);
646 /*************************************************************
647 Copies a struct samr_UserInfo23 to a struct samu
648 **************************************************************/
650 void copy_id23_to_sam_passwd(struct samu
*to
,
651 struct samr_UserInfo23
*from
)
653 if (from
== NULL
|| to
== NULL
) {
657 copy_id21_to_sam_passwd("INFO 23", to
, &from
->info
);
660 /*************************************************************
661 Copies a struct samr_UserInfo24 to a struct samu
662 **************************************************************/
664 void copy_id24_to_sam_passwd(struct samu
*to
,
665 struct samr_UserInfo24
*from
)
667 struct samr_UserInfo21 i
;
669 if (from
== NULL
|| to
== NULL
) {
675 i
.fields_present
= SAMR_FIELD_EXPIRED_FLAG
;
676 i
.password_expired
= from
->password_expired
;
678 copy_id21_to_sam_passwd("INFO_24", to
, &i
);
681 /*************************************************************
682 Copies a struct samr_UserInfo25 to a struct samu
683 **************************************************************/
685 void copy_id25_to_sam_passwd(struct samu
*to
,
686 struct samr_UserInfo25
*from
)
688 if (from
== NULL
|| to
== NULL
) {
692 copy_id21_to_sam_passwd("INFO_25", to
, &from
->info
);
695 /*************************************************************
696 Copies a struct samr_UserInfo26 to a struct samu
697 **************************************************************/
699 void copy_id26_to_sam_passwd(struct samu
*to
,
700 struct samr_UserInfo26
*from
)
702 struct samr_UserInfo21 i
;
704 if (from
== NULL
|| to
== NULL
) {
710 i
.fields_present
= SAMR_FIELD_EXPIRED_FLAG
;
711 i
.password_expired
= from
->password_expired
;
713 copy_id21_to_sam_passwd("INFO_26", to
, &i
);