r17727: Start pulling in changes for 3.0.23c
[Samba.git] / source / passdb / passdb.c
blob27176b751e605a996e64ea692f750fb5770de78d
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Jeremy Allison 1996-2001
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6 Copyright (C) Gerald (Jerry) Carter 2000-2006
7 Copyright (C) Andrew Bartlett 2001-2002
8 Copyright (C) Simo Sorce 2003
9 Copyright (C) Volker Lendecke 2006
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 2 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, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 /******************************************************************
32 get the default domain/netbios name to be used when
33 testing authentication. For example, if you connect
34 to a Windows member server using a bogus domain name, the
35 Windows box will map the BOGUS\user to DOMAIN\user. A
36 standalone box will map to WKS\user.
37 ******************************************************************/
39 const char *my_sam_name(void)
41 /* standalone servers can only use the local netbios name */
42 if ( lp_server_role() == ROLE_STANDALONE )
43 return global_myname();
45 /* Windows domain members default to the DOMAIN
46 name when not specified */
47 return lp_workgroup();
50 /**********************************************************************
51 ***********************************************************************/
53 static int samu_destroy(void *p)
55 struct samu *user = p;
57 data_blob_clear_free( &user->lm_pw );
58 data_blob_clear_free( &user->nt_pw );
60 if ( user->plaintext_pw )
61 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
63 return 0;
66 /**********************************************************************
67 generate a new struct samuser
68 ***********************************************************************/
70 struct samu *samu_new( TALLOC_CTX *ctx )
72 struct samu *user;
74 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
75 DEBUG(0,("samuser_new: Talloc failed!\n"));
76 return NULL;
79 talloc_set_destructor( user, samu_destroy );
81 /* no initial methods */
83 user->methods = NULL;
85 /* Don't change these timestamp settings without a good reason.
86 They are important for NT member server compatibility. */
88 user->logon_time = (time_t)0;
89 user->pass_last_set_time = (time_t)0;
90 user->pass_can_change_time = (time_t)0;
91 user->logoff_time = get_time_t_max();
92 user->kickoff_time = get_time_t_max();
93 user->pass_must_change_time = get_time_t_max();
94 user->fields_present = 0x00ffffff;
95 user->logon_divs = 168; /* hours per week */
96 user->hours_len = 21; /* 21 times 8 bits = 168 */
97 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
98 user->bad_password_count = 0;
99 user->logon_count = 0;
100 user->unknown_6 = 0x000004ec; /* don't know */
102 /* Some parts of samba strlen their pdb_get...() returns,
103 so this keeps the interface unchanged for now. */
105 user->username = "";
106 user->domain = "";
107 user->nt_username = "";
108 user->full_name = "";
109 user->home_dir = "";
110 user->logon_script = "";
111 user->profile_path = "";
112 user->acct_desc = "";
113 user->workstations = "";
114 user->unknown_str = "";
115 user->munged_dial = "";
117 user->plaintext_pw = NULL;
119 /* Unless we know otherwise have a Account Control Bit
120 value of 'normal user'. This helps User Manager, which
121 asks for a filtered list of users. */
123 user->acct_ctrl = ACB_NORMAL;
126 return user;
129 /*********************************************************************
130 Initialize a struct samu from a struct passwd including the user
131 and group SIDs. The *user structure is filled out with the Unix
132 attributes and a user SID.
133 *********************************************************************/
135 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, BOOL create)
137 const char *guest_account = lp_guestaccount();
138 const char *domain = global_myname();
139 DOM_SID group_sid;
140 uint32 urid;
142 if ( !pwd ) {
143 return NT_STATUS_NO_SUCH_USER;
146 /* Basic properties based upon the Unix account information */
148 pdb_set_username(user, pwd->pw_name, PDB_SET);
149 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
150 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
151 gid_to_sid(&group_sid, pwd->pw_gid);
152 pdb_set_group_sid(user, &group_sid, PDB_SET);
154 /* save the password structure for later use */
156 user->unix_pw = tcopy_passwd( user, pwd );
158 /* Special case for the guest account which must have a RID of 501 */
160 if ( strequal( pwd->pw_name, guest_account ) ) {
161 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
162 return NT_STATUS_NO_SUCH_USER;
164 return NT_STATUS_OK;
167 /* Non-guest accounts...Check for a workstation or user account */
169 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
170 /* workstation */
172 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
173 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
174 pwd->pw_name));
175 return NT_STATUS_INVALID_COMPUTER_NAME;
178 else {
179 /* user */
181 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
182 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
183 pwd->pw_name));
184 return NT_STATUS_INVALID_ACCOUNT_NAME;
187 /* set some basic attributes */
189 pdb_set_profile_path(user, talloc_sub_specified(user,
190 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
191 PDB_DEFAULT);
192 pdb_set_homedir(user, talloc_sub_specified(user,
193 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
194 PDB_DEFAULT);
195 pdb_set_dir_drive(user, talloc_sub_specified(user,
196 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
197 PDB_DEFAULT);
198 pdb_set_logon_script(user, talloc_sub_specified(user,
199 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
200 PDB_DEFAULT);
203 /* Now deal with the user SID. If we have a backend that can generate
204 RIDs, then do so. But sometimes the caller just wanted a structure
205 initialized and will fill in these fields later (such as from a
206 NET_USER_INFO_3 structure) */
208 if ( create && !pdb_rid_algorithm() ) {
209 uint32 user_rid;
210 DOM_SID user_sid;
212 if ( !pdb_new_rid( &user_rid ) ) {
213 DEBUG(3, ("Could not allocate a new RID\n"));
214 return NT_STATUS_ACCESS_DENIED;
217 sid_copy( &user_sid, get_global_sam_sid() );
218 sid_append_rid( &user_sid, user_rid );
220 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
221 DEBUG(3, ("pdb_set_user_sid failed\n"));
222 return NT_STATUS_INTERNAL_ERROR;
225 return NT_STATUS_OK;
228 /* generate a SID for the user with the RID algorithm */
230 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
232 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
233 return NT_STATUS_INTERNAL_ERROR;
236 return NT_STATUS_OK;
239 /********************************************************************
240 Set the Unix user attributes
241 ********************************************************************/
243 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
245 return samu_set_unix_internal( user, pwd, False );
248 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
250 return samu_set_unix_internal( user, pwd, True );
253 /**********************************************************
254 Encode the account control bits into a string.
255 length = length of string to encode into (including terminating
256 null). length *MUST BE MORE THAN 2* !
257 **********************************************************/
259 char *pdb_encode_acct_ctrl(uint32 acct_ctrl, size_t length)
261 static fstring acct_str;
263 size_t i = 0;
265 SMB_ASSERT(length <= sizeof(acct_str));
267 acct_str[i++] = '[';
269 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
270 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
271 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
272 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
273 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
274 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
275 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
276 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
277 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
278 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
279 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
281 for ( ; i < length - 2 ; i++ )
282 acct_str[i] = ' ';
284 i = length - 2;
285 acct_str[i++] = ']';
286 acct_str[i++] = '\0';
288 return acct_str;
291 /**********************************************************
292 Decode the account control bits from a string.
293 **********************************************************/
295 uint32 pdb_decode_acct_ctrl(const char *p)
297 uint32 acct_ctrl = 0;
298 BOOL finished = False;
301 * Check if the account type bits have been encoded after the
302 * NT password (in the form [NDHTUWSLXI]).
305 if (*p != '[')
306 return 0;
308 for (p++; *p && !finished; p++) {
309 switch (*p) {
310 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
311 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
312 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
313 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
314 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
315 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
316 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
317 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
318 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
319 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
320 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
321 case ' ': { break; }
322 case ':':
323 case '\n':
324 case '\0':
325 case ']':
326 default: { finished = True; }
330 return acct_ctrl;
333 /*************************************************************
334 Routine to set 32 hex password characters from a 16 byte array.
335 **************************************************************/
337 void pdb_sethexpwd(char *p, const unsigned char *pwd, uint32 acct_ctrl)
339 if (pwd != NULL) {
340 int i;
341 for (i = 0; i < 16; i++)
342 slprintf(&p[i*2], 3, "%02X", pwd[i]);
343 } else {
344 if (acct_ctrl & ACB_PWNOTREQ)
345 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
346 else
347 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
351 /*************************************************************
352 Routine to get the 32 hex characters and turn them
353 into a 16 byte array.
354 **************************************************************/
356 BOOL pdb_gethexpwd(const char *p, unsigned char *pwd)
358 int i;
359 unsigned char lonybble, hinybble;
360 const char *hexchars = "0123456789ABCDEF";
361 char *p1, *p2;
363 if (!p)
364 return (False);
366 for (i = 0; i < 32; i += 2) {
367 hinybble = toupper_ascii(p[i]);
368 lonybble = toupper_ascii(p[i + 1]);
370 p1 = strchr(hexchars, hinybble);
371 p2 = strchr(hexchars, lonybble);
373 if (!p1 || !p2)
374 return (False);
376 hinybble = PTR_DIFF(p1, hexchars);
377 lonybble = PTR_DIFF(p2, hexchars);
379 pwd[i / 2] = (hinybble << 4) | lonybble;
381 return (True);
384 /*************************************************************
385 Routine to set 42 hex hours characters from a 21 byte array.
386 **************************************************************/
388 void pdb_sethexhours(char *p, const unsigned char *hours)
390 if (hours != NULL) {
391 int i;
392 for (i = 0; i < 21; i++) {
393 slprintf(&p[i*2], 3, "%02X", hours[i]);
395 } else {
396 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
400 /*************************************************************
401 Routine to get the 42 hex characters and turn them
402 into a 21 byte array.
403 **************************************************************/
405 BOOL pdb_gethexhours(const char *p, unsigned char *hours)
407 int i;
408 unsigned char lonybble, hinybble;
409 const char *hexchars = "0123456789ABCDEF";
410 char *p1, *p2;
412 if (!p) {
413 return (False);
416 for (i = 0; i < 42; i += 2) {
417 hinybble = toupper_ascii(p[i]);
418 lonybble = toupper_ascii(p[i + 1]);
420 p1 = strchr(hexchars, hinybble);
421 p2 = strchr(hexchars, lonybble);
423 if (!p1 || !p2) {
424 return (False);
427 hinybble = PTR_DIFF(p1, hexchars);
428 lonybble = PTR_DIFF(p2, hexchars);
430 hours[i / 2] = (hinybble << 4) | lonybble;
432 return (True);
435 /********************************************************************
436 ********************************************************************/
438 int algorithmic_rid_base(void)
440 static int rid_offset = 0;
442 if (rid_offset != 0)
443 return rid_offset;
445 rid_offset = lp_algorithmic_rid_base();
447 if (rid_offset < BASE_RID) {
448 /* Try to prevent admin foot-shooting, we can't put algorithmic
449 rids below 1000, that's the 'well known RIDs' on NT */
450 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
451 rid_offset = BASE_RID;
453 if (rid_offset & 1) {
454 DEBUG(0, ("algorithmic rid base must be even\n"));
455 rid_offset += 1;
457 return rid_offset;
460 /*******************************************************************
461 Converts NT user RID to a UNIX uid.
462 ********************************************************************/
464 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
466 int rid_offset = algorithmic_rid_base();
467 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
470 uid_t max_algorithmic_uid(void)
472 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
475 /*******************************************************************
476 converts UNIX uid to an NT User RID.
477 ********************************************************************/
479 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
481 int rid_offset = algorithmic_rid_base();
482 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
485 /*******************************************************************
486 Converts NT group RID to a UNIX gid.
487 ********************************************************************/
489 gid_t pdb_group_rid_to_gid(uint32 group_rid)
491 int rid_offset = algorithmic_rid_base();
492 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
495 gid_t max_algorithmic_gid(void)
497 return pdb_group_rid_to_gid(0xffffffff);
500 /*******************************************************************
501 converts NT Group RID to a UNIX uid.
503 warning: you must not call that function only
504 you must do a call to the group mapping first.
505 there is not anymore a direct link between the gid and the rid.
506 ********************************************************************/
508 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
510 int rid_offset = algorithmic_rid_base();
511 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
514 /*******************************************************************
515 Decides if a RID is a well known RID.
516 ********************************************************************/
518 static BOOL rid_is_well_known(uint32 rid)
520 /* Not using rid_offset here, because this is the actual
521 NT fixed value (1000) */
523 return (rid < BASE_RID);
526 /*******************************************************************
527 Decides if a RID is a user or group RID.
528 ********************************************************************/
530 BOOL algorithmic_pdb_rid_is_user(uint32 rid)
532 if ( rid_is_well_known(rid) ) {
534 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
535 * and DOMAIN_USER_RID_GUEST.
537 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
538 return True;
539 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
540 return True;
542 return False;
545 /*******************************************************************
546 Convert a name into a SID. Used in the lookup name rpc.
547 ********************************************************************/
549 BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid,
550 enum SID_NAME_USE *type)
552 GROUP_MAP map;
553 BOOL ret;
555 /* Windows treats "MACHINE\None" as a special name for
556 rid 513 on non-DCs. You cannot create a user or group
557 name "None" on Windows. You will get an error that
558 the group already exists. */
560 if ( strequal( user, "None" ) ) {
561 *rid = DOMAIN_GROUP_RID_USERS;
562 *type = SID_NAME_DOM_GRP;
564 return True;
567 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
568 * correctly in the case where foo also exists as a user. If the flag
569 * is set, don't look for users at all. */
571 if ((flags & LOOKUP_NAME_GROUP) == 0) {
572 struct samu *sam_account = NULL;
573 DOM_SID user_sid;
575 if ( !(sam_account = samu_new( NULL )) ) {
576 return False;
579 become_root();
580 ret = pdb_getsampwnam(sam_account, user);
581 unbecome_root();
583 if (ret) {
584 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
587 TALLOC_FREE(sam_account);
589 if (ret) {
590 if (!sid_check_is_in_our_domain(&user_sid)) {
591 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
592 user, sid_string_static(&user_sid)));
593 return False;
596 sid_peek_rid(&user_sid, rid);
597 *type = SID_NAME_USER;
598 return True;
603 * Maybe it is a group ?
606 become_root();
607 ret = pdb_getgrnam(&map, user);
608 unbecome_root();
610 if (!ret) {
611 return False;
614 /* BUILTIN groups are looked up elsewhere */
615 if (!sid_check_is_in_our_domain(&map.sid)) {
616 DEBUG(10, ("Found group %s (%s) not in our domain -- "
617 "ignoring.", user,
618 sid_string_static(&map.sid)));
619 return False;
622 /* yes it's a mapped group */
623 sid_peek_rid(&map.sid, rid);
624 *type = map.sid_name_use;
625 return True;
628 /*************************************************************
629 Change a password entry in the local smbpasswd file.
630 *************************************************************/
632 NTSTATUS local_password_change(const char *user_name, int local_flags,
633 const char *new_passwd,
634 char *err_str, size_t err_str_len,
635 char *msg_str, size_t msg_str_len)
637 struct samu *sam_pass=NULL;
638 uint32 other_acb;
639 NTSTATUS result;
641 *err_str = '\0';
642 *msg_str = '\0';
644 /* Get the smb passwd entry for this user */
646 if ( !(sam_pass = samu_new( NULL )) ) {
647 return NT_STATUS_NO_MEMORY;
650 become_root();
651 if(!pdb_getsampwnam(sam_pass, user_name)) {
652 unbecome_root();
653 TALLOC_FREE(sam_pass);
655 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
656 int tmp_debug = DEBUGLEVEL;
657 struct passwd *pwd;
659 /* Might not exist in /etc/passwd. */
661 if (tmp_debug < 1) {
662 DEBUGLEVEL = 1;
665 if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
666 return NT_STATUS_NO_SUCH_USER;
669 /* create the struct samu and initialize the basic Unix properties */
671 if ( !(sam_pass = samu_new( NULL )) ) {
672 return NT_STATUS_NO_MEMORY;
675 result = samu_set_unix( sam_pass, pwd );
677 DEBUGLEVEL = tmp_debug;
679 TALLOC_FREE( pwd );
681 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
682 return result;
685 if (!NT_STATUS_IS_OK(result)) {
686 slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n",
687 user_name, nt_errstr(result));
688 return result;
690 } else {
691 slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
692 return NT_STATUS_NO_SUCH_USER;
694 } else {
695 unbecome_root();
696 /* the entry already existed */
697 local_flags &= ~LOCAL_ADD_USER;
700 /* the 'other' acb bits not being changed here */
701 other_acb = (pdb_get_acct_ctrl(sam_pass) & (!(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
702 if (local_flags & LOCAL_TRUST_ACCOUNT) {
703 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
704 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
705 TALLOC_FREE(sam_pass);
706 return NT_STATUS_UNSUCCESSFUL;
708 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
709 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
710 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
711 TALLOC_FREE(sam_pass);
712 return NT_STATUS_UNSUCCESSFUL;
714 } else {
715 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
716 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
717 TALLOC_FREE(sam_pass);
718 return NT_STATUS_UNSUCCESSFUL;
723 * We are root - just write the new password
724 * and the valid last change time.
727 if (local_flags & LOCAL_DISABLE_USER) {
728 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
729 slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
730 TALLOC_FREE(sam_pass);
731 return NT_STATUS_UNSUCCESSFUL;
733 } else if (local_flags & LOCAL_ENABLE_USER) {
734 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
735 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
736 TALLOC_FREE(sam_pass);
737 return NT_STATUS_UNSUCCESSFUL;
741 if (local_flags & LOCAL_SET_NO_PASSWORD) {
742 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
743 slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
744 TALLOC_FREE(sam_pass);
745 return NT_STATUS_UNSUCCESSFUL;
747 } else if (local_flags & LOCAL_SET_PASSWORD) {
749 * If we're dealing with setting a completely empty user account
750 * ie. One with a password of 'XXXX', but not set disabled (like
751 * an account created from scratch) then if the old password was
752 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
753 * We remove that as we're giving this user their first password
754 * and the decision hasn't really been made to disable them (ie.
755 * don't create them disabled). JRA.
757 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
758 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
759 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
760 TALLOC_FREE(sam_pass);
761 return NT_STATUS_UNSUCCESSFUL;
764 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
765 slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
766 TALLOC_FREE(sam_pass);
767 return NT_STATUS_UNSUCCESSFUL;
770 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
771 slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
772 TALLOC_FREE(sam_pass);
773 return NT_STATUS_UNSUCCESSFUL;
777 if (local_flags & LOCAL_ADD_USER) {
778 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
779 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
780 TALLOC_FREE(sam_pass);
781 return NT_STATUS_OK;
782 } else {
783 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
784 TALLOC_FREE(sam_pass);
785 return NT_STATUS_UNSUCCESSFUL;
787 } else if (local_flags & LOCAL_DELETE_USER) {
788 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
789 slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
790 TALLOC_FREE(sam_pass);
791 return NT_STATUS_UNSUCCESSFUL;
793 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
794 } else {
795 result = pdb_update_sam_account(sam_pass);
796 if(!NT_STATUS_IS_OK(result)) {
797 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
798 TALLOC_FREE(sam_pass);
799 return result;
801 if(local_flags & LOCAL_DISABLE_USER)
802 slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
803 else if (local_flags & LOCAL_ENABLE_USER)
804 slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
805 else if (local_flags & LOCAL_SET_NO_PASSWORD)
806 slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
809 TALLOC_FREE(sam_pass);
810 return NT_STATUS_OK;
813 /**********************************************************************
814 Marshall/unmarshall struct samu structs.
815 *********************************************************************/
817 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
819 /*********************************************************************
820 *********************************************************************/
822 BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
825 /* times are stored as 32bit integer
826 take care on system with 64bit wide time_t
827 --SSS */
828 uint32 logon_time,
829 logoff_time,
830 kickoff_time,
831 bad_password_time,
832 pass_last_set_time,
833 pass_can_change_time,
834 pass_must_change_time;
835 char *username = NULL;
836 char *domain = NULL;
837 char *nt_username = NULL;
838 char *dir_drive = NULL;
839 char *unknown_str = NULL;
840 char *munged_dial = NULL;
841 char *fullname = NULL;
842 char *homedir = NULL;
843 char *logon_script = NULL;
844 char *profile_path = NULL;
845 char *acct_desc = NULL;
846 char *workstations = NULL;
847 uint32 username_len, domain_len, nt_username_len,
848 dir_drive_len, unknown_str_len, munged_dial_len,
849 fullname_len, homedir_len, logon_script_len,
850 profile_path_len, acct_desc_len, workstations_len;
852 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
853 uint16 logon_divs;
854 uint16 bad_password_count, logon_count;
855 uint8 *hours = NULL;
856 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
857 uint32 len = 0;
858 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
859 uint32 pwHistLen = 0;
860 BOOL ret = True;
861 fstring tmpstring;
862 BOOL expand_explicit = lp_passdb_expand_explicit();
864 if(sampass == NULL || buf == NULL) {
865 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
866 return False;
869 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
871 /* unpack the buffer into variables */
872 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V3,
873 &logon_time, /* d */
874 &logoff_time, /* d */
875 &kickoff_time, /* d */
876 &bad_password_time, /* d */
877 &pass_last_set_time, /* d */
878 &pass_can_change_time, /* d */
879 &pass_must_change_time, /* d */
880 &username_len, &username, /* B */
881 &domain_len, &domain, /* B */
882 &nt_username_len, &nt_username, /* B */
883 &fullname_len, &fullname, /* B */
884 &homedir_len, &homedir, /* B */
885 &dir_drive_len, &dir_drive, /* B */
886 &logon_script_len, &logon_script, /* B */
887 &profile_path_len, &profile_path, /* B */
888 &acct_desc_len, &acct_desc, /* B */
889 &workstations_len, &workstations, /* B */
890 &unknown_str_len, &unknown_str, /* B */
891 &munged_dial_len, &munged_dial, /* B */
892 &user_rid, /* d */
893 &group_rid, /* d */
894 &lm_pw_len, &lm_pw_ptr, /* B */
895 &nt_pw_len, &nt_pw_ptr, /* B */
896 /* Change from V1 is addition of password history field. */
897 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
898 /* Change from V2 is the uint32 acb_mask */
899 &acct_ctrl, /* d */
900 /* Also "remove_me" field was removed. */
901 &logon_divs, /* w */
902 &hours_len, /* d */
903 &hourslen, &hours, /* B */
904 &bad_password_count, /* w */
905 &logon_count, /* w */
906 &unknown_6); /* d */
908 if (len == (uint32) -1) {
909 ret = False;
910 goto done;
913 pdb_set_logon_time(sampass, logon_time, PDB_SET);
914 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
915 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
916 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
917 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
918 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
919 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
921 pdb_set_username(sampass, username, PDB_SET);
922 pdb_set_domain(sampass, domain, PDB_SET);
923 pdb_set_nt_username(sampass, nt_username, PDB_SET);
924 pdb_set_fullname(sampass, fullname, PDB_SET);
926 if (homedir) {
927 fstrcpy( tmpstring, homedir );
928 if (expand_explicit) {
929 standard_sub_basic( username, tmpstring,
930 sizeof(tmpstring) );
932 pdb_set_homedir(sampass, tmpstring, PDB_SET);
934 else {
935 pdb_set_homedir(sampass,
936 talloc_sub_basic(sampass, username, lp_logon_home()),
937 PDB_DEFAULT);
940 if (dir_drive)
941 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
942 else
943 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
945 if (logon_script) {
946 fstrcpy( tmpstring, logon_script );
947 if (expand_explicit) {
948 standard_sub_basic( username, tmpstring,
949 sizeof(tmpstring) );
951 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
953 else {
954 pdb_set_logon_script(sampass,
955 talloc_sub_basic(sampass, username, lp_logon_script()),
956 PDB_DEFAULT);
959 if (profile_path) {
960 fstrcpy( tmpstring, profile_path );
961 if (expand_explicit) {
962 standard_sub_basic( username, tmpstring,
963 sizeof(tmpstring) );
965 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
967 else {
968 pdb_set_profile_path(sampass,
969 talloc_sub_basic(sampass, username, lp_logon_path()),
970 PDB_DEFAULT);
973 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
974 pdb_set_workstations(sampass, workstations, PDB_SET);
975 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
977 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
978 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
979 ret = False;
980 goto done;
984 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
985 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
986 ret = False;
987 goto done;
991 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
992 if (pwHistLen) {
993 uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
994 if (!pw_hist) {
995 ret = False;
996 goto done;
998 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
999 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1000 int i;
1001 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1002 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1003 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1004 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1005 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1006 PW_HISTORY_ENTRY_LEN);
1009 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1010 SAFE_FREE(pw_hist);
1011 ret = False;
1012 goto done;
1014 SAFE_FREE(pw_hist);
1015 } else {
1016 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1019 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1020 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1021 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1022 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1023 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1024 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1025 /* Change from V2 is the uint32 acct_ctrl */
1026 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1027 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1028 pdb_set_hours(sampass, hours, PDB_SET);
1030 done:
1032 SAFE_FREE(username);
1033 SAFE_FREE(domain);
1034 SAFE_FREE(nt_username);
1035 SAFE_FREE(fullname);
1036 SAFE_FREE(homedir);
1037 SAFE_FREE(dir_drive);
1038 SAFE_FREE(logon_script);
1039 SAFE_FREE(profile_path);
1040 SAFE_FREE(acct_desc);
1041 SAFE_FREE(workstations);
1042 SAFE_FREE(munged_dial);
1043 SAFE_FREE(unknown_str);
1044 SAFE_FREE(lm_pw_ptr);
1045 SAFE_FREE(nt_pw_ptr);
1046 SAFE_FREE(nt_pw_hist_ptr);
1047 SAFE_FREE(hours);
1049 return ret;
1052 /*********************************************************************
1053 *********************************************************************/
1055 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_only)
1057 size_t len, buflen;
1059 /* times are stored as 32bit integer
1060 take care on system with 64bit wide time_t
1061 --SSS */
1062 uint32 logon_time,
1063 logoff_time,
1064 kickoff_time,
1065 bad_password_time,
1066 pass_last_set_time,
1067 pass_can_change_time,
1068 pass_must_change_time;
1070 uint32 user_rid, group_rid;
1072 const char *username;
1073 const char *domain;
1074 const char *nt_username;
1075 const char *dir_drive;
1076 const char *unknown_str;
1077 const char *munged_dial;
1078 const char *fullname;
1079 const char *homedir;
1080 const char *logon_script;
1081 const char *profile_path;
1082 const char *acct_desc;
1083 const char *workstations;
1084 uint32 username_len, domain_len, nt_username_len,
1085 dir_drive_len, unknown_str_len, munged_dial_len,
1086 fullname_len, homedir_len, logon_script_len,
1087 profile_path_len, acct_desc_len, workstations_len;
1089 const uint8 *lm_pw;
1090 const uint8 *nt_pw;
1091 const uint8 *nt_pw_hist;
1092 uint32 lm_pw_len = 16;
1093 uint32 nt_pw_len = 16;
1094 uint32 nt_pw_hist_len;
1095 uint32 pwHistLen = 0;
1097 *buf = NULL;
1098 buflen = 0;
1100 logon_time = (uint32)pdb_get_logon_time(sampass);
1101 logoff_time = (uint32)pdb_get_logoff_time(sampass);
1102 kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
1103 bad_password_time = (uint32)pdb_get_bad_password_time(sampass);
1104 pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
1105 pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
1106 pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
1108 user_rid = pdb_get_user_rid(sampass);
1109 group_rid = pdb_get_group_rid(sampass);
1111 username = pdb_get_username(sampass);
1112 if (username) {
1113 username_len = strlen(username) +1;
1114 } else {
1115 username_len = 0;
1118 domain = pdb_get_domain(sampass);
1119 if (domain) {
1120 domain_len = strlen(domain) +1;
1121 } else {
1122 domain_len = 0;
1125 nt_username = pdb_get_nt_username(sampass);
1126 if (nt_username) {
1127 nt_username_len = strlen(nt_username) +1;
1128 } else {
1129 nt_username_len = 0;
1132 fullname = pdb_get_fullname(sampass);
1133 if (fullname) {
1134 fullname_len = strlen(fullname) +1;
1135 } else {
1136 fullname_len = 0;
1140 * Only updates fields which have been set (not defaults from smb.conf)
1143 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1144 dir_drive = pdb_get_dir_drive(sampass);
1145 } else {
1146 dir_drive = NULL;
1148 if (dir_drive) {
1149 dir_drive_len = strlen(dir_drive) +1;
1150 } else {
1151 dir_drive_len = 0;
1154 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1155 homedir = pdb_get_homedir(sampass);
1156 } else {
1157 homedir = NULL;
1159 if (homedir) {
1160 homedir_len = strlen(homedir) +1;
1161 } else {
1162 homedir_len = 0;
1165 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1166 logon_script = pdb_get_logon_script(sampass);
1167 } else {
1168 logon_script = NULL;
1170 if (logon_script) {
1171 logon_script_len = strlen(logon_script) +1;
1172 } else {
1173 logon_script_len = 0;
1176 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1177 profile_path = pdb_get_profile_path(sampass);
1178 } else {
1179 profile_path = NULL;
1181 if (profile_path) {
1182 profile_path_len = strlen(profile_path) +1;
1183 } else {
1184 profile_path_len = 0;
1187 lm_pw = pdb_get_lanman_passwd(sampass);
1188 if (!lm_pw) {
1189 lm_pw_len = 0;
1192 nt_pw = pdb_get_nt_passwd(sampass);
1193 if (!nt_pw) {
1194 nt_pw_len = 0;
1197 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1198 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1199 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1200 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1201 } else {
1202 nt_pw_hist_len = 0;
1205 acct_desc = pdb_get_acct_desc(sampass);
1206 if (acct_desc) {
1207 acct_desc_len = strlen(acct_desc) +1;
1208 } else {
1209 acct_desc_len = 0;
1212 workstations = pdb_get_workstations(sampass);
1213 if (workstations) {
1214 workstations_len = strlen(workstations) +1;
1215 } else {
1216 workstations_len = 0;
1219 unknown_str = NULL;
1220 unknown_str_len = 0;
1222 munged_dial = pdb_get_munged_dial(sampass);
1223 if (munged_dial) {
1224 munged_dial_len = strlen(munged_dial) +1;
1225 } else {
1226 munged_dial_len = 0;
1229 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1231 /* one time to get the size needed */
1232 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1233 logon_time, /* d */
1234 logoff_time, /* d */
1235 kickoff_time, /* d */
1236 bad_password_time, /* d */
1237 pass_last_set_time, /* d */
1238 pass_can_change_time, /* d */
1239 pass_must_change_time, /* d */
1240 username_len, username, /* B */
1241 domain_len, domain, /* B */
1242 nt_username_len, nt_username, /* B */
1243 fullname_len, fullname, /* B */
1244 homedir_len, homedir, /* B */
1245 dir_drive_len, dir_drive, /* B */
1246 logon_script_len, logon_script, /* B */
1247 profile_path_len, profile_path, /* B */
1248 acct_desc_len, acct_desc, /* B */
1249 workstations_len, workstations, /* B */
1250 unknown_str_len, unknown_str, /* B */
1251 munged_dial_len, munged_dial, /* B */
1252 user_rid, /* d */
1253 group_rid, /* d */
1254 lm_pw_len, lm_pw, /* B */
1255 nt_pw_len, nt_pw, /* B */
1256 nt_pw_hist_len, nt_pw_hist, /* B */
1257 pdb_get_acct_ctrl(sampass), /* d */
1258 pdb_get_logon_divs(sampass), /* w */
1259 pdb_get_hours_len(sampass), /* d */
1260 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1261 pdb_get_bad_password_count(sampass), /* w */
1262 pdb_get_logon_count(sampass), /* w */
1263 pdb_get_unknown_6(sampass)); /* d */
1265 if (size_only) {
1266 return buflen;
1269 /* malloc the space needed */
1270 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1271 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1272 return (-1);
1275 /* now for the real call to tdb_pack() */
1276 buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V3,
1277 logon_time, /* d */
1278 logoff_time, /* d */
1279 kickoff_time, /* d */
1280 bad_password_time, /* d */
1281 pass_last_set_time, /* d */
1282 pass_can_change_time, /* d */
1283 pass_must_change_time, /* d */
1284 username_len, username, /* B */
1285 domain_len, domain, /* B */
1286 nt_username_len, nt_username, /* B */
1287 fullname_len, fullname, /* B */
1288 homedir_len, homedir, /* B */
1289 dir_drive_len, dir_drive, /* B */
1290 logon_script_len, logon_script, /* B */
1291 profile_path_len, profile_path, /* B */
1292 acct_desc_len, acct_desc, /* B */
1293 workstations_len, workstations, /* B */
1294 unknown_str_len, unknown_str, /* B */
1295 munged_dial_len, munged_dial, /* B */
1296 user_rid, /* d */
1297 group_rid, /* d */
1298 lm_pw_len, lm_pw, /* B */
1299 nt_pw_len, nt_pw, /* B */
1300 nt_pw_hist_len, nt_pw_hist, /* B */
1301 pdb_get_acct_ctrl(sampass), /* d */
1302 pdb_get_logon_divs(sampass), /* w */
1303 pdb_get_hours_len(sampass), /* d */
1304 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1305 pdb_get_bad_password_count(sampass), /* w */
1306 pdb_get_logon_count(sampass), /* w */
1307 pdb_get_unknown_6(sampass)); /* d */
1309 /* check to make sure we got it correct */
1310 if (buflen != len) {
1311 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1312 (unsigned long)buflen, (unsigned long)len));
1313 /* error */
1314 SAFE_FREE (*buf);
1315 return (-1);
1318 return (buflen);
1322 /*********************************************************************
1323 *********************************************************************/
1325 BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src )
1327 uint8 *buf = NULL;
1328 int len;
1330 len = init_buffer_from_sam_v3(&buf, src, False);
1331 if (len == -1 || !buf) {
1332 SAFE_FREE(buf);
1333 return False;
1336 if (!init_sam_from_buffer_v3( dst, buf, len )) {
1337 free(buf);
1338 return False;
1341 dst->methods = src->methods;
1343 if ( src->unix_pw ) {
1344 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1345 if (!dst->unix_pw) {
1346 free(buf);
1347 return False;
1351 free(buf);
1352 return True;
1355 /*********************************************************************
1356 Update the bad password count checking the AP_RESET_COUNT_TIME
1357 *********************************************************************/
1359 BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
1361 time_t LastBadPassword;
1362 uint16 BadPasswordCount;
1363 uint32 resettime;
1365 BadPasswordCount = pdb_get_bad_password_count(sampass);
1366 if (!BadPasswordCount) {
1367 DEBUG(9, ("No bad password attempts.\n"));
1368 return True;
1371 if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) {
1372 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1373 return False;
1376 /* First, check if there is a reset time to compare */
1377 if ((resettime == (uint32) -1) || (resettime == 0)) {
1378 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1379 return True;
1382 LastBadPassword = pdb_get_bad_password_time(sampass);
1383 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1384 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1385 if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){
1386 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1387 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1388 if (updated) {
1389 *updated = True;
1393 return True;
1396 /*********************************************************************
1397 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1398 *********************************************************************/
1400 BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
1402 uint32 duration;
1403 time_t LastBadPassword;
1405 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1406 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1407 pdb_get_username(sampass)));
1408 return True;
1411 if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) {
1412 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1413 return False;
1416 /* First, check if there is a duration to compare */
1417 if ((duration == (uint32) -1) || (duration == 0)) {
1418 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1419 return True;
1422 LastBadPassword = pdb_get_bad_password_time(sampass);
1423 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1424 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1426 if (LastBadPassword == (time_t)0) {
1427 DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \
1428 bad password time. Leaving locked out.\n",
1429 pdb_get_username(sampass) ));
1430 return True;
1433 if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) {
1434 pdb_set_acct_ctrl(sampass,
1435 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
1436 PDB_CHANGED);
1437 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1438 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1439 if (updated) {
1440 *updated = True;
1444 return True;
1447 /*********************************************************************
1448 Increment the bad_password_count
1449 *********************************************************************/
1451 BOOL pdb_increment_bad_password_count(struct samu *sampass)
1453 uint32 account_policy_lockout;
1454 BOOL autolock_updated = False, badpw_updated = False;
1455 BOOL ret;
1457 /* Retrieve the account lockout policy */
1458 become_root();
1459 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
1460 unbecome_root();
1461 if ( !ret ) {
1462 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
1463 return False;
1466 /* If there is no policy, we don't need to continue checking */
1467 if (!account_policy_lockout) {
1468 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
1469 return True;
1472 /* Check if the autolock needs to be cleared */
1473 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
1474 return False;
1476 /* Check if the badpw count needs to be reset */
1477 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
1478 return False;
1481 Ok, now we can assume that any resetting that needs to be
1482 done has been done, and just get on with incrementing
1483 and autolocking if necessary
1486 pdb_set_bad_password_count(sampass,
1487 pdb_get_bad_password_count(sampass)+1,
1488 PDB_CHANGED);
1489 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
1492 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
1493 return True;
1495 if (!pdb_set_acct_ctrl(sampass,
1496 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
1497 PDB_CHANGED)) {
1498 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
1499 return False;
1502 return True;