r13776: Merge in the editposix ldapsam optimization
[Samba/bb.git] / source3 / passdb / passdb.c
blobd795888180fba83a96ad8c9c97b6df2072dd6969
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 uint32 urid;
141 if ( !pwd ) {
142 return NT_STATUS_NO_SUCH_USER;
145 /* Basic properties based upon the Unix account information */
147 pdb_set_username(user, pwd->pw_name, PDB_SET);
148 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
149 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
151 /* save the password structure for later use */
153 user->unix_pw = tcopy_passwd( user, pwd );
155 /* Special case for the guest account which must have a RID of 501 */
157 if ( strequal( pwd->pw_name, guest_account ) ) {
158 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
159 return NT_STATUS_NO_SUCH_USER;
161 return NT_STATUS_OK;
164 /* Non-guest accounts...Check for a workstation or user account */
166 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
167 /* workstation */
169 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
170 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
171 pwd->pw_name));
172 return NT_STATUS_INVALID_COMPUTER_NAME;
175 else {
176 /* user */
178 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
179 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
180 pwd->pw_name));
181 return NT_STATUS_INVALID_ACCOUNT_NAME;
184 /* set some basic attributes */
186 pdb_set_profile_path(user, talloc_sub_specified(user,
187 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
188 PDB_DEFAULT);
189 pdb_set_homedir(user, talloc_sub_specified(user,
190 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
191 PDB_DEFAULT);
192 pdb_set_dir_drive(user, talloc_sub_specified(user,
193 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
194 PDB_DEFAULT);
195 pdb_set_logon_script(user, talloc_sub_specified(user,
196 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
197 PDB_DEFAULT);
200 /* Now deal with the user SID. If we have a backend that can generate
201 RIDs, then do so. But sometimes the caller just wanted a structure
202 initialized and will fill in these fields later (such as from a
203 NET_USER_INFO_3 structure) */
205 if ( create && !pdb_rid_algorithm() ) {
206 uint32 user_rid;
207 DOM_SID user_sid;
209 if ( !pdb_new_rid( &user_rid ) ) {
210 DEBUG(3, ("Could not allocate a new RID\n"));
211 return NT_STATUS_ACCESS_DENIED;
214 sid_copy( &user_sid, get_global_sam_sid() );
215 sid_append_rid( &user_sid, user_rid );
217 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
218 DEBUG(3, ("pdb_set_user_sid failed\n"));
219 return NT_STATUS_INTERNAL_ERROR;
222 return NT_STATUS_OK;
225 /* generate a SID for the user with the RID algorithm */
227 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
229 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
230 return NT_STATUS_INTERNAL_ERROR;
233 return NT_STATUS_OK;
236 /********************************************************************
237 Set the Unix user attributes
238 ********************************************************************/
240 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
242 return samu_set_unix_internal( user, pwd, False );
245 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
247 return samu_set_unix_internal( user, pwd, True );
250 /**********************************************************
251 Encode the account control bits into a string.
252 length = length of string to encode into (including terminating
253 null). length *MUST BE MORE THAN 2* !
254 **********************************************************/
256 char *pdb_encode_acct_ctrl(uint32 acct_ctrl, size_t length)
258 static fstring acct_str;
260 size_t i = 0;
262 SMB_ASSERT(length <= sizeof(acct_str));
264 acct_str[i++] = '[';
266 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
267 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
268 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
269 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
270 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
271 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
272 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
273 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
274 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
275 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
276 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
278 for ( ; i < length - 2 ; i++ )
279 acct_str[i] = ' ';
281 i = length - 2;
282 acct_str[i++] = ']';
283 acct_str[i++] = '\0';
285 return acct_str;
288 /**********************************************************
289 Decode the account control bits from a string.
290 **********************************************************/
292 uint32 pdb_decode_acct_ctrl(const char *p)
294 uint32 acct_ctrl = 0;
295 BOOL finished = False;
298 * Check if the account type bits have been encoded after the
299 * NT password (in the form [NDHTUWSLXI]).
302 if (*p != '[')
303 return 0;
305 for (p++; *p && !finished; p++) {
306 switch (*p) {
307 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
308 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
309 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
310 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
311 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
312 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
313 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
314 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
315 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
316 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
317 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
318 case ' ': { break; }
319 case ':':
320 case '\n':
321 case '\0':
322 case ']':
323 default: { finished = True; }
327 return acct_ctrl;
330 /*************************************************************
331 Routine to set 32 hex password characters from a 16 byte array.
332 **************************************************************/
334 void pdb_sethexpwd(char *p, const unsigned char *pwd, uint32 acct_ctrl)
336 if (pwd != NULL) {
337 int i;
338 for (i = 0; i < 16; i++)
339 slprintf(&p[i*2], 3, "%02X", pwd[i]);
340 } else {
341 if (acct_ctrl & ACB_PWNOTREQ)
342 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
343 else
344 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
348 /*************************************************************
349 Routine to get the 32 hex characters and turn them
350 into a 16 byte array.
351 **************************************************************/
353 BOOL pdb_gethexpwd(const char *p, unsigned char *pwd)
355 int i;
356 unsigned char lonybble, hinybble;
357 const char *hexchars = "0123456789ABCDEF";
358 char *p1, *p2;
360 if (!p)
361 return (False);
363 for (i = 0; i < 32; i += 2) {
364 hinybble = toupper_ascii(p[i]);
365 lonybble = toupper_ascii(p[i + 1]);
367 p1 = strchr(hexchars, hinybble);
368 p2 = strchr(hexchars, lonybble);
370 if (!p1 || !p2)
371 return (False);
373 hinybble = PTR_DIFF(p1, hexchars);
374 lonybble = PTR_DIFF(p2, hexchars);
376 pwd[i / 2] = (hinybble << 4) | lonybble;
378 return (True);
381 /*************************************************************
382 Routine to set 42 hex hours characters from a 21 byte array.
383 **************************************************************/
385 void pdb_sethexhours(char *p, const unsigned char *hours)
387 if (hours != NULL) {
388 int i;
389 for (i = 0; i < 21; i++) {
390 slprintf(&p[i*2], 3, "%02X", hours[i]);
392 } else {
393 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
397 /*************************************************************
398 Routine to get the 42 hex characters and turn them
399 into a 21 byte array.
400 **************************************************************/
402 BOOL pdb_gethexhours(const char *p, unsigned char *hours)
404 int i;
405 unsigned char lonybble, hinybble;
406 const char *hexchars = "0123456789ABCDEF";
407 char *p1, *p2;
409 if (!p) {
410 return (False);
413 for (i = 0; i < 42; i += 2) {
414 hinybble = toupper_ascii(p[i]);
415 lonybble = toupper_ascii(p[i + 1]);
417 p1 = strchr(hexchars, hinybble);
418 p2 = strchr(hexchars, lonybble);
420 if (!p1 || !p2) {
421 return (False);
424 hinybble = PTR_DIFF(p1, hexchars);
425 lonybble = PTR_DIFF(p2, hexchars);
427 hours[i / 2] = (hinybble << 4) | lonybble;
429 return (True);
432 /********************************************************************
433 ********************************************************************/
435 int algorithmic_rid_base(void)
437 static int rid_offset = 0;
439 if (rid_offset != 0)
440 return rid_offset;
442 rid_offset = lp_algorithmic_rid_base();
444 if (rid_offset < BASE_RID) {
445 /* Try to prevent admin foot-shooting, we can't put algorithmic
446 rids below 1000, that's the 'well known RIDs' on NT */
447 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
448 rid_offset = BASE_RID;
450 if (rid_offset & 1) {
451 DEBUG(0, ("algorithmic rid base must be even\n"));
452 rid_offset += 1;
454 return rid_offset;
457 /*******************************************************************
458 Converts NT user RID to a UNIX uid.
459 ********************************************************************/
461 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
463 int rid_offset = algorithmic_rid_base();
464 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
467 uid_t max_algorithmic_uid(void)
469 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
472 /*******************************************************************
473 converts UNIX uid to an NT User RID.
474 ********************************************************************/
476 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
478 int rid_offset = algorithmic_rid_base();
479 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
482 /*******************************************************************
483 Converts NT group RID to a UNIX gid.
484 ********************************************************************/
486 gid_t pdb_group_rid_to_gid(uint32 group_rid)
488 int rid_offset = algorithmic_rid_base();
489 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
492 gid_t max_algorithmic_gid(void)
494 return pdb_group_rid_to_gid(0xffffffff);
497 /*******************************************************************
498 converts NT Group RID to a UNIX uid.
500 warning: you must not call that function only
501 you must do a call to the group mapping first.
502 there is not anymore a direct link between the gid and the rid.
503 ********************************************************************/
505 uint32 pdb_gid_to_group_rid(gid_t gid)
507 int rid_offset = algorithmic_rid_base();
508 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
511 /*******************************************************************
512 Decides if a RID is a well known RID.
513 ********************************************************************/
515 static BOOL rid_is_well_known(uint32 rid)
517 /* Not using rid_offset here, because this is the actual
518 NT fixed value (1000) */
520 return (rid < BASE_RID);
523 /*******************************************************************
524 Decides if a RID is a user or group RID.
525 ********************************************************************/
527 BOOL algorithmic_pdb_rid_is_user(uint32 rid)
529 if ( rid_is_well_known(rid) ) {
531 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
532 * and DOMAIN_USER_RID_GUEST.
534 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
535 return True;
536 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
537 return True;
539 return False;
542 /*******************************************************************
543 Convert a name into a SID. Used in the lookup name rpc.
544 ********************************************************************/
546 BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid,
547 enum SID_NAME_USE *type)
549 GROUP_MAP map;
550 BOOL ret;
552 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
553 * correctly in the case where foo also exists as a user. If the flag
554 * is set, don't look for users at all. */
556 if ((flags & LOOKUP_NAME_GROUP) == 0) {
557 struct samu *sam_account = NULL;
558 DOM_SID user_sid;
560 if ( !(sam_account = samu_new( NULL )) ) {
561 return False;
564 become_root();
565 ret = pdb_getsampwnam(sam_account, user);
566 unbecome_root();
568 if (ret) {
569 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
572 TALLOC_FREE(sam_account);
574 if (ret) {
575 if (!sid_check_is_in_our_domain(&user_sid)) {
576 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
577 user, sid_string_static(&user_sid)));
578 return False;
581 sid_peek_rid(&user_sid, rid);
582 *type = SID_NAME_USER;
583 return True;
588 * Maybe it is a group ?
591 become_root();
592 ret = pdb_getgrnam(&map, user);
593 unbecome_root();
595 if (!ret) {
596 return False;
599 /* BUILTIN groups are looked up elsewhere */
600 if (!sid_check_is_in_our_domain(&map.sid)) {
601 DEBUG(10, ("Found group %s (%s) not in our domain -- "
602 "ignoring.", user,
603 sid_string_static(&map.sid)));
604 return False;
607 /* yes it's a mapped group */
608 sid_peek_rid(&map.sid, rid);
609 *type = map.sid_name_use;
610 return True;
613 /*************************************************************
614 Change a password entry in the local smbpasswd file.
615 *************************************************************/
617 NTSTATUS local_password_change(const char *user_name, int local_flags,
618 const char *new_passwd,
619 char *err_str, size_t err_str_len,
620 char *msg_str, size_t msg_str_len)
622 struct samu *sam_pass=NULL;
623 uint32 other_acb;
624 NTSTATUS result;
626 *err_str = '\0';
627 *msg_str = '\0';
629 /* Get the smb passwd entry for this user */
631 if ( !(sam_pass = samu_new( NULL )) ) {
632 return NT_STATUS_NO_MEMORY;
635 become_root();
636 if(!pdb_getsampwnam(sam_pass, user_name)) {
637 unbecome_root();
638 TALLOC_FREE(sam_pass);
640 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
641 int tmp_debug = DEBUGLEVEL;
642 struct passwd *pwd;
644 /* Might not exist in /etc/passwd. */
646 if (tmp_debug < 1) {
647 DEBUGLEVEL = 1;
650 if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
651 return NT_STATUS_NO_SUCH_USER;
654 /* create the struct samu and initialize the basic Unix properties */
656 if ( !(sam_pass = samu_new( NULL )) ) {
657 return NT_STATUS_NO_MEMORY;
660 result = samu_set_unix( sam_pass, pwd );
662 DEBUGLEVEL = tmp_debug;
664 TALLOC_FREE( pwd );
666 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
667 return result;
670 if (!NT_STATUS_IS_OK(result)) {
671 slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n",
672 user_name, nt_errstr(result));
673 return result;
675 } else {
676 slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
677 return NT_STATUS_NO_SUCH_USER;
679 } else {
680 unbecome_root();
681 /* the entry already existed */
682 local_flags &= ~LOCAL_ADD_USER;
685 /* the 'other' acb bits not being changed here */
686 other_acb = (pdb_get_acct_ctrl(sam_pass) & (!(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
687 if (local_flags & LOCAL_TRUST_ACCOUNT) {
688 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
689 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
690 TALLOC_FREE(sam_pass);
691 return NT_STATUS_UNSUCCESSFUL;
693 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
694 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
695 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
696 TALLOC_FREE(sam_pass);
697 return NT_STATUS_UNSUCCESSFUL;
699 } else {
700 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
701 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
702 TALLOC_FREE(sam_pass);
703 return NT_STATUS_UNSUCCESSFUL;
708 * We are root - just write the new password
709 * and the valid last change time.
712 if (local_flags & LOCAL_DISABLE_USER) {
713 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
714 slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
715 TALLOC_FREE(sam_pass);
716 return NT_STATUS_UNSUCCESSFUL;
718 } else if (local_flags & LOCAL_ENABLE_USER) {
719 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
720 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
721 TALLOC_FREE(sam_pass);
722 return NT_STATUS_UNSUCCESSFUL;
726 if (local_flags & LOCAL_SET_NO_PASSWORD) {
727 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
728 slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
729 TALLOC_FREE(sam_pass);
730 return NT_STATUS_UNSUCCESSFUL;
732 } else if (local_flags & LOCAL_SET_PASSWORD) {
734 * If we're dealing with setting a completely empty user account
735 * ie. One with a password of 'XXXX', but not set disabled (like
736 * an account created from scratch) then if the old password was
737 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
738 * We remove that as we're giving this user their first password
739 * and the decision hasn't really been made to disable them (ie.
740 * don't create them disabled). JRA.
742 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
743 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
744 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
745 TALLOC_FREE(sam_pass);
746 return NT_STATUS_UNSUCCESSFUL;
749 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
750 slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
751 TALLOC_FREE(sam_pass);
752 return NT_STATUS_UNSUCCESSFUL;
755 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
756 slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
757 TALLOC_FREE(sam_pass);
758 return NT_STATUS_UNSUCCESSFUL;
762 if (local_flags & LOCAL_ADD_USER) {
763 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
764 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
765 TALLOC_FREE(sam_pass);
766 return NT_STATUS_OK;
767 } else {
768 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
769 TALLOC_FREE(sam_pass);
770 return NT_STATUS_UNSUCCESSFUL;
772 } else if (local_flags & LOCAL_DELETE_USER) {
773 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
774 slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
775 TALLOC_FREE(sam_pass);
776 return NT_STATUS_UNSUCCESSFUL;
778 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
779 } else {
780 result = pdb_update_sam_account(sam_pass);
781 if(!NT_STATUS_IS_OK(result)) {
782 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
783 TALLOC_FREE(sam_pass);
784 return result;
786 if(local_flags & LOCAL_DISABLE_USER)
787 slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
788 else if (local_flags & LOCAL_ENABLE_USER)
789 slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
790 else if (local_flags & LOCAL_SET_NO_PASSWORD)
791 slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
794 TALLOC_FREE(sam_pass);
795 return NT_STATUS_OK;
798 /**********************************************************************
799 Marshall/unmarshall struct samu structs.
800 *********************************************************************/
802 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
804 /*********************************************************************
805 *********************************************************************/
807 BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
810 /* times are stored as 32bit integer
811 take care on system with 64bit wide time_t
812 --SSS */
813 uint32 logon_time,
814 logoff_time,
815 kickoff_time,
816 bad_password_time,
817 pass_last_set_time,
818 pass_can_change_time,
819 pass_must_change_time;
820 char *username = NULL;
821 char *domain = NULL;
822 char *nt_username = NULL;
823 char *dir_drive = NULL;
824 char *unknown_str = NULL;
825 char *munged_dial = NULL;
826 char *fullname = NULL;
827 char *homedir = NULL;
828 char *logon_script = NULL;
829 char *profile_path = NULL;
830 char *acct_desc = NULL;
831 char *workstations = NULL;
832 uint32 username_len, domain_len, nt_username_len,
833 dir_drive_len, unknown_str_len, munged_dial_len,
834 fullname_len, homedir_len, logon_script_len,
835 profile_path_len, acct_desc_len, workstations_len;
837 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
838 uint16 logon_divs;
839 uint16 bad_password_count, logon_count;
840 uint8 *hours = NULL;
841 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
842 uint32 len = 0;
843 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
844 uint32 pwHistLen = 0;
845 BOOL ret = True;
846 fstring tmpstring;
847 BOOL expand_explicit = lp_passdb_expand_explicit();
849 if(sampass == NULL || buf == NULL) {
850 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
851 return False;
854 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
856 /* unpack the buffer into variables */
857 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V3,
858 &logon_time, /* d */
859 &logoff_time, /* d */
860 &kickoff_time, /* d */
861 &bad_password_time, /* d */
862 &pass_last_set_time, /* d */
863 &pass_can_change_time, /* d */
864 &pass_must_change_time, /* d */
865 &username_len, &username, /* B */
866 &domain_len, &domain, /* B */
867 &nt_username_len, &nt_username, /* B */
868 &fullname_len, &fullname, /* B */
869 &homedir_len, &homedir, /* B */
870 &dir_drive_len, &dir_drive, /* B */
871 &logon_script_len, &logon_script, /* B */
872 &profile_path_len, &profile_path, /* B */
873 &acct_desc_len, &acct_desc, /* B */
874 &workstations_len, &workstations, /* B */
875 &unknown_str_len, &unknown_str, /* B */
876 &munged_dial_len, &munged_dial, /* B */
877 &user_rid, /* d */
878 &group_rid, /* d */
879 &lm_pw_len, &lm_pw_ptr, /* B */
880 &nt_pw_len, &nt_pw_ptr, /* B */
881 /* Change from V1 is addition of password history field. */
882 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
883 /* Change from V2 is the uint32 acb_mask */
884 &acct_ctrl, /* d */
885 /* Also "remove_me" field was removed. */
886 &logon_divs, /* w */
887 &hours_len, /* d */
888 &hourslen, &hours, /* B */
889 &bad_password_count, /* w */
890 &logon_count, /* w */
891 &unknown_6); /* d */
893 if (len == (uint32) -1) {
894 ret = False;
895 goto done;
898 pdb_set_logon_time(sampass, logon_time, PDB_SET);
899 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
900 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
901 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
902 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
903 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
904 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
906 pdb_set_username(sampass, username, PDB_SET);
907 pdb_set_domain(sampass, domain, PDB_SET);
908 pdb_set_nt_username(sampass, nt_username, PDB_SET);
909 pdb_set_fullname(sampass, fullname, PDB_SET);
911 if (homedir) {
912 fstrcpy( tmpstring, homedir );
913 if (expand_explicit) {
914 standard_sub_basic( username, tmpstring,
915 sizeof(tmpstring) );
917 pdb_set_homedir(sampass, tmpstring, PDB_SET);
919 else {
920 pdb_set_homedir(sampass,
921 talloc_sub_basic(sampass, username, lp_logon_home()),
922 PDB_DEFAULT);
925 if (dir_drive)
926 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
927 else
928 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
930 if (logon_script) {
931 fstrcpy( tmpstring, logon_script );
932 if (expand_explicit) {
933 standard_sub_basic( username, tmpstring,
934 sizeof(tmpstring) );
936 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
938 else {
939 pdb_set_logon_script(sampass,
940 talloc_sub_basic(sampass, username, lp_logon_script()),
941 PDB_DEFAULT);
944 if (profile_path) {
945 fstrcpy( tmpstring, profile_path );
946 if (expand_explicit) {
947 standard_sub_basic( username, tmpstring,
948 sizeof(tmpstring) );
950 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
952 else {
953 pdb_set_profile_path(sampass,
954 talloc_sub_basic(sampass, username, lp_logon_path()),
955 PDB_DEFAULT);
958 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
959 pdb_set_workstations(sampass, workstations, PDB_SET);
960 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
962 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
963 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
964 ret = False;
965 goto done;
969 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
970 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
971 ret = False;
972 goto done;
976 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
977 if (pwHistLen) {
978 uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
979 if (!pw_hist) {
980 ret = False;
981 goto done;
983 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
984 if (nt_pw_hist_ptr && nt_pw_hist_len) {
985 int i;
986 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
987 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
988 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
989 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
990 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
991 PW_HISTORY_ENTRY_LEN);
994 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
995 SAFE_FREE(pw_hist);
996 ret = False;
997 goto done;
999 SAFE_FREE(pw_hist);
1000 } else {
1001 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1004 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1005 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1006 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1007 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1008 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1009 /* Change from V2 is the uint32 acct_ctrl */
1010 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1011 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1012 pdb_set_hours(sampass, hours, PDB_SET);
1014 done:
1016 SAFE_FREE(username);
1017 SAFE_FREE(domain);
1018 SAFE_FREE(nt_username);
1019 SAFE_FREE(fullname);
1020 SAFE_FREE(homedir);
1021 SAFE_FREE(dir_drive);
1022 SAFE_FREE(logon_script);
1023 SAFE_FREE(profile_path);
1024 SAFE_FREE(acct_desc);
1025 SAFE_FREE(workstations);
1026 SAFE_FREE(munged_dial);
1027 SAFE_FREE(unknown_str);
1028 SAFE_FREE(lm_pw_ptr);
1029 SAFE_FREE(nt_pw_ptr);
1030 SAFE_FREE(nt_pw_hist_ptr);
1031 SAFE_FREE(hours);
1033 return ret;
1036 /*********************************************************************
1037 *********************************************************************/
1039 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_only)
1041 size_t len, buflen;
1043 /* times are stored as 32bit integer
1044 take care on system with 64bit wide time_t
1045 --SSS */
1046 uint32 logon_time,
1047 logoff_time,
1048 kickoff_time,
1049 bad_password_time,
1050 pass_last_set_time,
1051 pass_can_change_time,
1052 pass_must_change_time;
1054 uint32 user_rid, group_rid;
1056 const char *username;
1057 const char *domain;
1058 const char *nt_username;
1059 const char *dir_drive;
1060 const char *unknown_str;
1061 const char *munged_dial;
1062 const char *fullname;
1063 const char *homedir;
1064 const char *logon_script;
1065 const char *profile_path;
1066 const char *acct_desc;
1067 const char *workstations;
1068 uint32 username_len, domain_len, nt_username_len,
1069 dir_drive_len, unknown_str_len, munged_dial_len,
1070 fullname_len, homedir_len, logon_script_len,
1071 profile_path_len, acct_desc_len, workstations_len;
1073 const uint8 *lm_pw;
1074 const uint8 *nt_pw;
1075 const uint8 *nt_pw_hist;
1076 uint32 lm_pw_len = 16;
1077 uint32 nt_pw_len = 16;
1078 uint32 nt_pw_hist_len;
1079 uint32 pwHistLen = 0;
1081 /* do we have a valid struct samu pointer? */
1082 if (sampass == NULL) {
1083 DEBUG(0, ("init_buffer_from_sam: struct samu is NULL!\n"));
1084 return -1;
1087 *buf = NULL;
1088 buflen = 0;
1090 logon_time = (uint32)pdb_get_logon_time(sampass);
1091 logoff_time = (uint32)pdb_get_logoff_time(sampass);
1092 kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
1093 bad_password_time = (uint32)pdb_get_bad_password_time(sampass);
1094 pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
1095 pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
1096 pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
1098 user_rid = pdb_get_user_rid(sampass);
1099 group_rid = pdb_get_group_rid(sampass);
1101 username = pdb_get_username(sampass);
1102 if (username) {
1103 username_len = strlen(username) +1;
1104 } else {
1105 username_len = 0;
1108 domain = pdb_get_domain(sampass);
1109 if (domain) {
1110 domain_len = strlen(domain) +1;
1111 } else {
1112 domain_len = 0;
1115 nt_username = pdb_get_nt_username(sampass);
1116 if (nt_username) {
1117 nt_username_len = strlen(nt_username) +1;
1118 } else {
1119 nt_username_len = 0;
1122 fullname = pdb_get_fullname(sampass);
1123 if (fullname) {
1124 fullname_len = strlen(fullname) +1;
1125 } else {
1126 fullname_len = 0;
1130 * Only updates fields which have been set (not defaults from smb.conf)
1133 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1134 dir_drive = pdb_get_dir_drive(sampass);
1135 } else {
1136 dir_drive = NULL;
1138 if (dir_drive) {
1139 dir_drive_len = strlen(dir_drive) +1;
1140 } else {
1141 dir_drive_len = 0;
1144 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1145 homedir = pdb_get_homedir(sampass);
1146 } else {
1147 homedir = NULL;
1149 if (homedir) {
1150 homedir_len = strlen(homedir) +1;
1151 } else {
1152 homedir_len = 0;
1155 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1156 logon_script = pdb_get_logon_script(sampass);
1157 } else {
1158 logon_script = NULL;
1160 if (logon_script) {
1161 logon_script_len = strlen(logon_script) +1;
1162 } else {
1163 logon_script_len = 0;
1166 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1167 profile_path = pdb_get_profile_path(sampass);
1168 } else {
1169 profile_path = NULL;
1171 if (profile_path) {
1172 profile_path_len = strlen(profile_path) +1;
1173 } else {
1174 profile_path_len = 0;
1177 lm_pw = pdb_get_lanman_passwd(sampass);
1178 if (!lm_pw) {
1179 lm_pw_len = 0;
1182 nt_pw = pdb_get_nt_passwd(sampass);
1183 if (!nt_pw) {
1184 nt_pw_len = 0;
1187 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1188 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1189 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1190 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1191 } else {
1192 nt_pw_hist_len = 0;
1195 acct_desc = pdb_get_acct_desc(sampass);
1196 if (acct_desc) {
1197 acct_desc_len = strlen(acct_desc) +1;
1198 } else {
1199 acct_desc_len = 0;
1202 workstations = pdb_get_workstations(sampass);
1203 if (workstations) {
1204 workstations_len = strlen(workstations) +1;
1205 } else {
1206 workstations_len = 0;
1209 unknown_str = NULL;
1210 unknown_str_len = 0;
1212 munged_dial = pdb_get_munged_dial(sampass);
1213 if (munged_dial) {
1214 munged_dial_len = strlen(munged_dial) +1;
1215 } else {
1216 munged_dial_len = 0;
1219 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1221 /* one time to get the size needed */
1222 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1223 logon_time, /* d */
1224 logoff_time, /* d */
1225 kickoff_time, /* d */
1226 bad_password_time, /* d */
1227 pass_last_set_time, /* d */
1228 pass_can_change_time, /* d */
1229 pass_must_change_time, /* d */
1230 username_len, username, /* B */
1231 domain_len, domain, /* B */
1232 nt_username_len, nt_username, /* B */
1233 fullname_len, fullname, /* B */
1234 homedir_len, homedir, /* B */
1235 dir_drive_len, dir_drive, /* B */
1236 logon_script_len, logon_script, /* B */
1237 profile_path_len, profile_path, /* B */
1238 acct_desc_len, acct_desc, /* B */
1239 workstations_len, workstations, /* B */
1240 unknown_str_len, unknown_str, /* B */
1241 munged_dial_len, munged_dial, /* B */
1242 user_rid, /* d */
1243 group_rid, /* d */
1244 lm_pw_len, lm_pw, /* B */
1245 nt_pw_len, nt_pw, /* B */
1246 nt_pw_hist_len, nt_pw_hist, /* B */
1247 pdb_get_acct_ctrl(sampass), /* d */
1248 pdb_get_logon_divs(sampass), /* w */
1249 pdb_get_hours_len(sampass), /* d */
1250 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1251 pdb_get_bad_password_count(sampass), /* w */
1252 pdb_get_logon_count(sampass), /* w */
1253 pdb_get_unknown_6(sampass)); /* d */
1255 if (size_only) {
1256 return buflen;
1259 /* malloc the space needed */
1260 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1261 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1262 return (-1);
1265 /* now for the real call to tdb_pack() */
1266 buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V3,
1267 logon_time, /* d */
1268 logoff_time, /* d */
1269 kickoff_time, /* d */
1270 bad_password_time, /* d */
1271 pass_last_set_time, /* d */
1272 pass_can_change_time, /* d */
1273 pass_must_change_time, /* d */
1274 username_len, username, /* B */
1275 domain_len, domain, /* B */
1276 nt_username_len, nt_username, /* B */
1277 fullname_len, fullname, /* B */
1278 homedir_len, homedir, /* B */
1279 dir_drive_len, dir_drive, /* B */
1280 logon_script_len, logon_script, /* B */
1281 profile_path_len, profile_path, /* B */
1282 acct_desc_len, acct_desc, /* B */
1283 workstations_len, workstations, /* B */
1284 unknown_str_len, unknown_str, /* B */
1285 munged_dial_len, munged_dial, /* B */
1286 user_rid, /* d */
1287 group_rid, /* d */
1288 lm_pw_len, lm_pw, /* B */
1289 nt_pw_len, nt_pw, /* B */
1290 nt_pw_hist_len, nt_pw_hist, /* B */
1291 pdb_get_acct_ctrl(sampass), /* d */
1292 pdb_get_logon_divs(sampass), /* w */
1293 pdb_get_hours_len(sampass), /* d */
1294 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1295 pdb_get_bad_password_count(sampass), /* w */
1296 pdb_get_logon_count(sampass), /* w */
1297 pdb_get_unknown_6(sampass)); /* d */
1299 /* check to make sure we got it correct */
1300 if (buflen != len) {
1301 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1302 (unsigned long)buflen, (unsigned long)len));
1303 /* error */
1304 SAFE_FREE (*buf);
1305 return (-1);
1308 return (buflen);
1312 /*********************************************************************
1313 *********************************************************************/
1315 BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src )
1317 BOOL result;
1318 uint8 *buf;
1319 int len;
1321 if ( !dst )
1322 return False;
1324 len = init_buffer_from_sam_v3(&buf, src, False);
1326 if (len == -1)
1327 return False;
1329 result = init_sam_from_buffer_v3( dst, buf, len );
1330 dst->methods = src->methods;
1332 if ( src->unix_pw )
1333 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1335 free(buf);
1337 return result;
1340 /*********************************************************************
1341 Update the bad password count checking the AP_RESET_COUNT_TIME
1342 *********************************************************************/
1344 BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
1346 time_t LastBadPassword;
1347 uint16 BadPasswordCount;
1348 uint32 resettime;
1350 if (!sampass) return False;
1352 BadPasswordCount = pdb_get_bad_password_count(sampass);
1353 if (!BadPasswordCount) {
1354 DEBUG(9, ("No bad password attempts.\n"));
1355 return True;
1358 if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) {
1359 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1360 return False;
1363 /* First, check if there is a reset time to compare */
1364 if ((resettime == (uint32) -1) || (resettime == 0)) {
1365 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1366 return True;
1369 LastBadPassword = pdb_get_bad_password_time(sampass);
1370 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1371 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1372 if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){
1373 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1374 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1375 if (updated) {
1376 *updated = True;
1380 return True;
1383 /*********************************************************************
1384 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1385 *********************************************************************/
1387 BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
1389 uint32 duration;
1390 time_t LastBadPassword;
1392 if (!sampass) return False;
1394 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1395 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1396 pdb_get_username(sampass)));
1397 return True;
1400 if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) {
1401 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1402 return False;
1405 /* First, check if there is a duration to compare */
1406 if ((duration == (uint32) -1) || (duration == 0)) {
1407 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1408 return True;
1411 LastBadPassword = pdb_get_bad_password_time(sampass);
1412 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1413 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1415 if (LastBadPassword == (time_t)0) {
1416 DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \
1417 bad password time. Leaving locked out.\n",
1418 pdb_get_username(sampass) ));
1419 return True;
1422 if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) {
1423 pdb_set_acct_ctrl(sampass,
1424 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
1425 PDB_CHANGED);
1426 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1427 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1428 if (updated) {
1429 *updated = True;
1433 return True;
1436 /*********************************************************************
1437 Increment the bad_password_count
1438 *********************************************************************/
1440 BOOL pdb_increment_bad_password_count(struct samu *sampass)
1442 uint32 account_policy_lockout;
1443 BOOL autolock_updated = False, badpw_updated = False;
1444 BOOL ret;
1446 if (!sampass)
1447 return False;
1449 /* Retrieve the account lockout policy */
1450 become_root();
1451 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
1452 unbecome_root();
1453 if ( !ret ) {
1454 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
1455 return False;
1458 /* If there is no policy, we don't need to continue checking */
1459 if (!account_policy_lockout) {
1460 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
1461 return True;
1464 /* Check if the autolock needs to be cleared */
1465 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
1466 return False;
1468 /* Check if the badpw count needs to be reset */
1469 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
1470 return False;
1473 Ok, now we can assume that any resetting that needs to be
1474 done has been done, and just get on with incrementing
1475 and autolocking if necessary
1478 pdb_set_bad_password_count(sampass,
1479 pdb_get_bad_password_count(sampass)+1,
1480 PDB_CHANGED);
1481 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
1484 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
1485 return True;
1487 if (!pdb_set_acct_ctrl(sampass,
1488 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
1489 PDB_CHANGED)) {
1490 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
1491 return False;
1494 return True;