r20243: Make lookup_name resolve both the mapped and the real unix group name
[Samba/gebeck_regimport.git] / source / passdb / passdb.c
blobae7f57fb5a11a187313c058f8a6745cc3ee2e0b7
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(struct samu *user)
55 data_blob_clear_free( &user->lm_pw );
56 data_blob_clear_free( &user->nt_pw );
58 if ( user->plaintext_pw )
59 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
61 return 0;
64 /**********************************************************************
65 generate a new struct samuser
66 ***********************************************************************/
68 struct samu *samu_new( TALLOC_CTX *ctx )
70 struct samu *user;
72 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
73 DEBUG(0,("samuser_new: Talloc failed!\n"));
74 return NULL;
77 talloc_set_destructor( user, samu_destroy );
79 /* no initial methods */
81 user->methods = NULL;
83 /* Don't change these timestamp settings without a good reason.
84 They are important for NT member server compatibility. */
86 user->logon_time = (time_t)0;
87 user->pass_last_set_time = (time_t)0;
88 user->pass_can_change_time = (time_t)0;
89 user->logoff_time = get_time_t_max();
90 user->kickoff_time = get_time_t_max();
91 user->pass_must_change_time = get_time_t_max();
92 user->fields_present = 0x00ffffff;
93 user->logon_divs = 168; /* hours per week */
94 user->hours_len = 21; /* 21 times 8 bits = 168 */
95 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
96 user->bad_password_count = 0;
97 user->logon_count = 0;
98 user->unknown_6 = 0x000004ec; /* don't know */
100 /* Some parts of samba strlen their pdb_get...() returns,
101 so this keeps the interface unchanged for now. */
103 user->username = "";
104 user->domain = "";
105 user->nt_username = "";
106 user->full_name = "";
107 user->home_dir = "";
108 user->logon_script = "";
109 user->profile_path = "";
110 user->acct_desc = "";
111 user->workstations = "";
112 user->comment = "";
113 user->munged_dial = "";
115 user->plaintext_pw = NULL;
117 /* Unless we know otherwise have a Account Control Bit
118 value of 'normal user'. This helps User Manager, which
119 asks for a filtered list of users. */
121 user->acct_ctrl = ACB_NORMAL;
124 return user;
127 /*********************************************************************
128 Initialize a struct samu from a struct passwd including the user
129 and group SIDs. The *user structure is filled out with the Unix
130 attributes and a user SID.
131 *********************************************************************/
133 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, BOOL create)
135 const char *guest_account = lp_guestaccount();
136 const char *domain = global_myname();
137 uint32 urid;
139 if ( !pwd ) {
140 return NT_STATUS_NO_SUCH_USER;
143 /* Basic properties based upon the Unix account information */
145 pdb_set_username(user, pwd->pw_name, PDB_SET);
146 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
147 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
148 #if 0
149 /* This can lead to a primary group of S-1-22-2-XX which
150 will be rejected by other parts of the Samba code.
151 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
152 --jerry */
154 gid_to_sid(&group_sid, pwd->pw_gid);
155 pdb_set_group_sid(user, &group_sid, PDB_SET);
156 #endif
158 /* save the password structure for later use */
160 user->unix_pw = tcopy_passwd( user, pwd );
162 /* Special case for the guest account which must have a RID of 501 */
164 if ( strequal( pwd->pw_name, guest_account ) ) {
165 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
166 return NT_STATUS_NO_SUCH_USER;
168 return NT_STATUS_OK;
171 /* Non-guest accounts...Check for a workstation or user account */
173 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
174 /* workstation */
176 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
177 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
178 pwd->pw_name));
179 return NT_STATUS_INVALID_COMPUTER_NAME;
182 else {
183 /* user */
185 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
186 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
187 pwd->pw_name));
188 return NT_STATUS_INVALID_ACCOUNT_NAME;
191 /* set some basic attributes */
193 pdb_set_profile_path(user, talloc_sub_specified(user,
194 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
195 PDB_DEFAULT);
196 pdb_set_homedir(user, talloc_sub_specified(user,
197 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
198 PDB_DEFAULT);
199 pdb_set_dir_drive(user, talloc_sub_specified(user,
200 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
201 PDB_DEFAULT);
202 pdb_set_logon_script(user, talloc_sub_specified(user,
203 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
204 PDB_DEFAULT);
207 /* Now deal with the user SID. If we have a backend that can generate
208 RIDs, then do so. But sometimes the caller just wanted a structure
209 initialized and will fill in these fields later (such as from a
210 NET_USER_INFO_3 structure) */
212 if ( create && !pdb_rid_algorithm() ) {
213 uint32 user_rid;
214 DOM_SID user_sid;
216 if ( !pdb_new_rid( &user_rid ) ) {
217 DEBUG(3, ("Could not allocate a new RID\n"));
218 return NT_STATUS_ACCESS_DENIED;
221 sid_copy( &user_sid, get_global_sam_sid() );
222 sid_append_rid( &user_sid, user_rid );
224 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
225 DEBUG(3, ("pdb_set_user_sid failed\n"));
226 return NT_STATUS_INTERNAL_ERROR;
229 return NT_STATUS_OK;
232 /* generate a SID for the user with the RID algorithm */
234 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
236 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
237 return NT_STATUS_INTERNAL_ERROR;
240 return NT_STATUS_OK;
243 /********************************************************************
244 Set the Unix user attributes
245 ********************************************************************/
247 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
249 return samu_set_unix_internal( user, pwd, False );
252 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
254 return samu_set_unix_internal( user, pwd, True );
257 /**********************************************************
258 Encode the account control bits into a string.
259 length = length of string to encode into (including terminating
260 null). length *MUST BE MORE THAN 2* !
261 **********************************************************/
263 char *pdb_encode_acct_ctrl(uint32 acct_ctrl, size_t length)
265 static fstring acct_str;
267 size_t i = 0;
269 SMB_ASSERT(length <= sizeof(acct_str));
271 acct_str[i++] = '[';
273 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
274 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
275 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
276 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
277 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
278 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
279 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
280 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
281 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
282 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
283 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
285 for ( ; i < length - 2 ; i++ )
286 acct_str[i] = ' ';
288 i = length - 2;
289 acct_str[i++] = ']';
290 acct_str[i++] = '\0';
292 return acct_str;
295 /**********************************************************
296 Decode the account control bits from a string.
297 **********************************************************/
299 uint32 pdb_decode_acct_ctrl(const char *p)
301 uint32 acct_ctrl = 0;
302 BOOL finished = False;
305 * Check if the account type bits have been encoded after the
306 * NT password (in the form [NDHTUWSLXI]).
309 if (*p != '[')
310 return 0;
312 for (p++; *p && !finished; p++) {
313 switch (*p) {
314 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
315 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
316 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
317 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
318 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
319 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
320 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
321 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
322 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
323 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
324 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
325 case ' ': { break; }
326 case ':':
327 case '\n':
328 case '\0':
329 case ']':
330 default: { finished = True; }
334 return acct_ctrl;
337 /*************************************************************
338 Routine to set 32 hex password characters from a 16 byte array.
339 **************************************************************/
341 void pdb_sethexpwd(char *p, const unsigned char *pwd, uint32 acct_ctrl)
343 if (pwd != NULL) {
344 int i;
345 for (i = 0; i < 16; i++)
346 slprintf(&p[i*2], 3, "%02X", pwd[i]);
347 } else {
348 if (acct_ctrl & ACB_PWNOTREQ)
349 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
350 else
351 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
355 /*************************************************************
356 Routine to get the 32 hex characters and turn them
357 into a 16 byte array.
358 **************************************************************/
360 BOOL pdb_gethexpwd(const char *p, unsigned char *pwd)
362 int i;
363 unsigned char lonybble, hinybble;
364 const char *hexchars = "0123456789ABCDEF";
365 char *p1, *p2;
367 if (!p)
368 return (False);
370 for (i = 0; i < 32; i += 2) {
371 hinybble = toupper_ascii(p[i]);
372 lonybble = toupper_ascii(p[i + 1]);
374 p1 = strchr(hexchars, hinybble);
375 p2 = strchr(hexchars, lonybble);
377 if (!p1 || !p2)
378 return (False);
380 hinybble = PTR_DIFF(p1, hexchars);
381 lonybble = PTR_DIFF(p2, hexchars);
383 pwd[i / 2] = (hinybble << 4) | lonybble;
385 return (True);
388 /*************************************************************
389 Routine to set 42 hex hours characters from a 21 byte array.
390 **************************************************************/
392 void pdb_sethexhours(char *p, const unsigned char *hours)
394 if (hours != NULL) {
395 int i;
396 for (i = 0; i < 21; i++) {
397 slprintf(&p[i*2], 3, "%02X", hours[i]);
399 } else {
400 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
404 /*************************************************************
405 Routine to get the 42 hex characters and turn them
406 into a 21 byte array.
407 **************************************************************/
409 BOOL pdb_gethexhours(const char *p, unsigned char *hours)
411 int i;
412 unsigned char lonybble, hinybble;
413 const char *hexchars = "0123456789ABCDEF";
414 char *p1, *p2;
416 if (!p) {
417 return (False);
420 for (i = 0; i < 42; i += 2) {
421 hinybble = toupper_ascii(p[i]);
422 lonybble = toupper_ascii(p[i + 1]);
424 p1 = strchr(hexchars, hinybble);
425 p2 = strchr(hexchars, lonybble);
427 if (!p1 || !p2) {
428 return (False);
431 hinybble = PTR_DIFF(p1, hexchars);
432 lonybble = PTR_DIFF(p2, hexchars);
434 hours[i / 2] = (hinybble << 4) | lonybble;
436 return (True);
439 /********************************************************************
440 ********************************************************************/
442 int algorithmic_rid_base(void)
444 static int rid_offset = 0;
446 if (rid_offset != 0)
447 return rid_offset;
449 rid_offset = lp_algorithmic_rid_base();
451 if (rid_offset < BASE_RID) {
452 /* Try to prevent admin foot-shooting, we can't put algorithmic
453 rids below 1000, that's the 'well known RIDs' on NT */
454 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
455 rid_offset = BASE_RID;
457 if (rid_offset & 1) {
458 DEBUG(0, ("algorithmic rid base must be even\n"));
459 rid_offset += 1;
461 return rid_offset;
464 /*******************************************************************
465 Converts NT user RID to a UNIX uid.
466 ********************************************************************/
468 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
470 int rid_offset = algorithmic_rid_base();
471 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
474 uid_t max_algorithmic_uid(void)
476 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
479 /*******************************************************************
480 converts UNIX uid to an NT User RID.
481 ********************************************************************/
483 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
485 int rid_offset = algorithmic_rid_base();
486 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
489 /*******************************************************************
490 Converts NT group RID to a UNIX gid.
491 ********************************************************************/
493 gid_t pdb_group_rid_to_gid(uint32 group_rid)
495 int rid_offset = algorithmic_rid_base();
496 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
499 gid_t max_algorithmic_gid(void)
501 return pdb_group_rid_to_gid(0xffffffff);
504 /*******************************************************************
505 converts NT Group RID to a UNIX uid.
507 warning: you must not call that function only
508 you must do a call to the group mapping first.
509 there is not anymore a direct link between the gid and the rid.
510 ********************************************************************/
512 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
514 int rid_offset = algorithmic_rid_base();
515 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
518 /*******************************************************************
519 Decides if a RID is a well known RID.
520 ********************************************************************/
522 static BOOL rid_is_well_known(uint32 rid)
524 /* Not using rid_offset here, because this is the actual
525 NT fixed value (1000) */
527 return (rid < BASE_RID);
530 /*******************************************************************
531 Decides if a RID is a user or group RID.
532 ********************************************************************/
534 BOOL algorithmic_pdb_rid_is_user(uint32 rid)
536 if ( rid_is_well_known(rid) ) {
538 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
539 * and DOMAIN_USER_RID_GUEST.
541 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
542 return True;
543 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
544 return True;
546 return False;
549 /*******************************************************************
550 Convert a name into a SID. Used in the lookup name rpc.
551 ********************************************************************/
553 BOOL lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
554 enum lsa_SidType *type)
556 GROUP_MAP map;
557 BOOL ret;
559 /* Windows treats "MACHINE\None" as a special name for
560 rid 513 on non-DCs. You cannot create a user or group
561 name "None" on Windows. You will get an error that
562 the group already exists. */
564 if ( strequal( name, "None" ) ) {
565 *rid = DOMAIN_GROUP_RID_USERS;
566 *type = SID_NAME_DOM_GRP;
568 return True;
571 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
572 * correctly in the case where foo also exists as a user. If the flag
573 * is set, don't look for users at all. */
575 if ((flags & LOOKUP_NAME_GROUP) == 0) {
576 struct samu *sam_account = NULL;
577 DOM_SID user_sid;
579 if ( !(sam_account = samu_new( NULL )) ) {
580 return False;
583 become_root();
584 ret = pdb_getsampwnam(sam_account, name);
585 unbecome_root();
587 if (ret) {
588 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
591 TALLOC_FREE(sam_account);
593 if (ret) {
594 if (!sid_check_is_in_our_domain(&user_sid)) {
595 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
596 name, sid_string_static(&user_sid)));
597 return False;
600 sid_peek_rid(&user_sid, rid);
601 *type = SID_NAME_USER;
602 return True;
607 * Maybe it is a group ?
610 become_root();
611 ret = pdb_getgrnam(&map, name);
612 unbecome_root();
614 if (!ret) {
615 /* try to see if we can lookup a mapped
616 * group with the unix group name */
618 struct group *grp;
620 grp = getgrnam(name);
621 if (!grp) {
622 return False;
625 become_root();
626 ret = pdb_getgrgid(&map, grp->gr_gid);
627 unbecome_root();
629 if (!ret) {
630 return False;
634 /* BUILTIN groups are looked up elsewhere */
635 if (!sid_check_is_in_our_domain(&map.sid)) {
636 DEBUG(10, ("Found group %s (%s) not in our domain -- "
637 "ignoring.", name,
638 sid_string_static(&map.sid)));
639 return False;
642 /* yes it's a mapped group */
643 sid_peek_rid(&map.sid, rid);
644 *type = map.sid_name_use;
645 return True;
648 /*************************************************************
649 Change a password entry in the local smbpasswd file.
650 *************************************************************/
652 NTSTATUS local_password_change(const char *user_name, int local_flags,
653 const char *new_passwd,
654 char *err_str, size_t err_str_len,
655 char *msg_str, size_t msg_str_len)
657 struct samu *sam_pass=NULL;
658 uint32 other_acb;
659 NTSTATUS result;
661 *err_str = '\0';
662 *msg_str = '\0';
664 /* Get the smb passwd entry for this user */
666 if ( !(sam_pass = samu_new( NULL )) ) {
667 return NT_STATUS_NO_MEMORY;
670 become_root();
671 if(!pdb_getsampwnam(sam_pass, user_name)) {
672 unbecome_root();
673 TALLOC_FREE(sam_pass);
675 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
676 int tmp_debug = DEBUGLEVEL;
677 struct passwd *pwd;
679 /* Might not exist in /etc/passwd. */
681 if (tmp_debug < 1) {
682 DEBUGLEVEL = 1;
685 if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
686 return NT_STATUS_NO_SUCH_USER;
689 /* create the struct samu and initialize the basic Unix properties */
691 if ( !(sam_pass = samu_new( NULL )) ) {
692 return NT_STATUS_NO_MEMORY;
695 result = samu_set_unix( sam_pass, pwd );
697 DEBUGLEVEL = tmp_debug;
699 TALLOC_FREE( pwd );
701 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
702 return result;
705 if (!NT_STATUS_IS_OK(result)) {
706 slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n",
707 user_name, nt_errstr(result));
708 return result;
710 } else {
711 slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
712 return NT_STATUS_NO_SUCH_USER;
714 } else {
715 unbecome_root();
716 /* the entry already existed */
717 local_flags &= ~LOCAL_ADD_USER;
720 /* the 'other' acb bits not being changed here */
721 other_acb = (pdb_get_acct_ctrl(sam_pass) & (!(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
722 if (local_flags & LOCAL_TRUST_ACCOUNT) {
723 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
724 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
725 TALLOC_FREE(sam_pass);
726 return NT_STATUS_UNSUCCESSFUL;
728 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
729 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
730 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
731 TALLOC_FREE(sam_pass);
732 return NT_STATUS_UNSUCCESSFUL;
734 } else {
735 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
736 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
737 TALLOC_FREE(sam_pass);
738 return NT_STATUS_UNSUCCESSFUL;
743 * We are root - just write the new password
744 * and the valid last change time.
747 if (local_flags & LOCAL_DISABLE_USER) {
748 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
749 slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
750 TALLOC_FREE(sam_pass);
751 return NT_STATUS_UNSUCCESSFUL;
753 } else if (local_flags & LOCAL_ENABLE_USER) {
754 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
755 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
756 TALLOC_FREE(sam_pass);
757 return NT_STATUS_UNSUCCESSFUL;
761 if (local_flags & LOCAL_SET_NO_PASSWORD) {
762 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
763 slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
764 TALLOC_FREE(sam_pass);
765 return NT_STATUS_UNSUCCESSFUL;
767 } else if (local_flags & LOCAL_SET_PASSWORD) {
769 * If we're dealing with setting a completely empty user account
770 * ie. One with a password of 'XXXX', but not set disabled (like
771 * an account created from scratch) then if the old password was
772 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
773 * We remove that as we're giving this user their first password
774 * and the decision hasn't really been made to disable them (ie.
775 * don't create them disabled). JRA.
777 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
778 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
779 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
780 TALLOC_FREE(sam_pass);
781 return NT_STATUS_UNSUCCESSFUL;
784 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
785 slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
786 TALLOC_FREE(sam_pass);
787 return NT_STATUS_UNSUCCESSFUL;
790 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
791 slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
792 TALLOC_FREE(sam_pass);
793 return NT_STATUS_UNSUCCESSFUL;
797 if (local_flags & LOCAL_ADD_USER) {
798 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
799 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
800 TALLOC_FREE(sam_pass);
801 return NT_STATUS_OK;
802 } else {
803 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
804 TALLOC_FREE(sam_pass);
805 return NT_STATUS_UNSUCCESSFUL;
807 } else if (local_flags & LOCAL_DELETE_USER) {
808 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
809 slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
810 TALLOC_FREE(sam_pass);
811 return NT_STATUS_UNSUCCESSFUL;
813 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
814 } else {
815 result = pdb_update_sam_account(sam_pass);
816 if(!NT_STATUS_IS_OK(result)) {
817 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
818 TALLOC_FREE(sam_pass);
819 return result;
821 if(local_flags & LOCAL_DISABLE_USER)
822 slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
823 else if (local_flags & LOCAL_ENABLE_USER)
824 slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
825 else if (local_flags & LOCAL_SET_NO_PASSWORD)
826 slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
829 TALLOC_FREE(sam_pass);
830 return NT_STATUS_OK;
833 /**********************************************************************
834 Marshall/unmarshall struct samu structs.
835 *********************************************************************/
837 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
839 /*********************************************************************
840 *********************************************************************/
842 BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
845 /* times are stored as 32bit integer
846 take care on system with 64bit wide time_t
847 --SSS */
848 uint32 logon_time,
849 logoff_time,
850 kickoff_time,
851 bad_password_time,
852 pass_last_set_time,
853 pass_can_change_time,
854 pass_must_change_time;
855 char *username = NULL;
856 char *domain = NULL;
857 char *nt_username = NULL;
858 char *dir_drive = NULL;
859 char *unknown_str = NULL;
860 char *munged_dial = NULL;
861 char *fullname = NULL;
862 char *homedir = NULL;
863 char *logon_script = NULL;
864 char *profile_path = NULL;
865 char *acct_desc = NULL;
866 char *workstations = NULL;
867 uint32 username_len, domain_len, nt_username_len,
868 dir_drive_len, unknown_str_len, munged_dial_len,
869 fullname_len, homedir_len, logon_script_len,
870 profile_path_len, acct_desc_len, workstations_len;
872 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
873 uint16 logon_divs;
874 uint16 bad_password_count, logon_count;
875 uint8 *hours = NULL;
876 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
877 uint32 len = 0;
878 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
879 uint32 pwHistLen = 0;
880 BOOL ret = True;
881 fstring tmpstring;
882 BOOL expand_explicit = lp_passdb_expand_explicit();
884 if(sampass == NULL || buf == NULL) {
885 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
886 return False;
889 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
891 /* unpack the buffer into variables */
892 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V3,
893 &logon_time, /* d */
894 &logoff_time, /* d */
895 &kickoff_time, /* d */
896 &bad_password_time, /* d */
897 &pass_last_set_time, /* d */
898 &pass_can_change_time, /* d */
899 &pass_must_change_time, /* d */
900 &username_len, &username, /* B */
901 &domain_len, &domain, /* B */
902 &nt_username_len, &nt_username, /* B */
903 &fullname_len, &fullname, /* B */
904 &homedir_len, &homedir, /* B */
905 &dir_drive_len, &dir_drive, /* B */
906 &logon_script_len, &logon_script, /* B */
907 &profile_path_len, &profile_path, /* B */
908 &acct_desc_len, &acct_desc, /* B */
909 &workstations_len, &workstations, /* B */
910 &unknown_str_len, &unknown_str, /* B */
911 &munged_dial_len, &munged_dial, /* B */
912 &user_rid, /* d */
913 &group_rid, /* d */
914 &lm_pw_len, &lm_pw_ptr, /* B */
915 &nt_pw_len, &nt_pw_ptr, /* B */
916 /* Change from V1 is addition of password history field. */
917 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
918 /* Change from V2 is the uint32 acb_mask */
919 &acct_ctrl, /* d */
920 /* Also "remove_me" field was removed. */
921 &logon_divs, /* w */
922 &hours_len, /* d */
923 &hourslen, &hours, /* B */
924 &bad_password_count, /* w */
925 &logon_count, /* w */
926 &unknown_6); /* d */
928 if (len == (uint32) -1) {
929 ret = False;
930 goto done;
933 pdb_set_logon_time(sampass, logon_time, PDB_SET);
934 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
935 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
936 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
937 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
938 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
939 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
941 pdb_set_username(sampass, username, PDB_SET);
942 pdb_set_domain(sampass, domain, PDB_SET);
943 pdb_set_nt_username(sampass, nt_username, PDB_SET);
944 pdb_set_fullname(sampass, fullname, PDB_SET);
946 if (homedir) {
947 fstrcpy( tmpstring, homedir );
948 if (expand_explicit) {
949 standard_sub_basic( username, domain, tmpstring,
950 sizeof(tmpstring) );
952 pdb_set_homedir(sampass, tmpstring, PDB_SET);
954 else {
955 pdb_set_homedir(sampass,
956 talloc_sub_basic(sampass, username, domain,
957 lp_logon_home()),
958 PDB_DEFAULT);
961 if (dir_drive)
962 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
963 else
964 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
966 if (logon_script) {
967 fstrcpy( tmpstring, logon_script );
968 if (expand_explicit) {
969 standard_sub_basic( username, domain, tmpstring,
970 sizeof(tmpstring) );
972 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
974 else {
975 pdb_set_logon_script(sampass,
976 talloc_sub_basic(sampass, username, domain,
977 lp_logon_script()),
978 PDB_DEFAULT);
981 if (profile_path) {
982 fstrcpy( tmpstring, profile_path );
983 if (expand_explicit) {
984 standard_sub_basic( username, domain, tmpstring,
985 sizeof(tmpstring) );
987 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
989 else {
990 pdb_set_profile_path(sampass,
991 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
992 PDB_DEFAULT);
995 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
996 pdb_set_workstations(sampass, workstations, PDB_SET);
997 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
999 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1000 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1001 ret = False;
1002 goto done;
1006 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1007 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1008 ret = False;
1009 goto done;
1013 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1014 if (pwHistLen) {
1015 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1016 if (!pw_hist) {
1017 ret = False;
1018 goto done;
1020 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1021 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1022 int i;
1023 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1024 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1025 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1026 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1027 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1028 PW_HISTORY_ENTRY_LEN);
1031 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1032 SAFE_FREE(pw_hist);
1033 ret = False;
1034 goto done;
1036 SAFE_FREE(pw_hist);
1037 } else {
1038 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1041 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1042 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1043 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1044 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1045 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1046 /* Change from V2 is the uint32 acct_ctrl */
1047 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1048 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1049 pdb_set_hours(sampass, hours, PDB_SET);
1051 done:
1053 SAFE_FREE(username);
1054 SAFE_FREE(domain);
1055 SAFE_FREE(nt_username);
1056 SAFE_FREE(fullname);
1057 SAFE_FREE(homedir);
1058 SAFE_FREE(dir_drive);
1059 SAFE_FREE(logon_script);
1060 SAFE_FREE(profile_path);
1061 SAFE_FREE(acct_desc);
1062 SAFE_FREE(workstations);
1063 SAFE_FREE(munged_dial);
1064 SAFE_FREE(unknown_str);
1065 SAFE_FREE(lm_pw_ptr);
1066 SAFE_FREE(nt_pw_ptr);
1067 SAFE_FREE(nt_pw_hist_ptr);
1068 SAFE_FREE(hours);
1070 return ret;
1073 /*********************************************************************
1074 *********************************************************************/
1076 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_only)
1078 size_t len, buflen;
1080 /* times are stored as 32bit integer
1081 take care on system with 64bit wide time_t
1082 --SSS */
1083 uint32 logon_time,
1084 logoff_time,
1085 kickoff_time,
1086 bad_password_time,
1087 pass_last_set_time,
1088 pass_can_change_time,
1089 pass_must_change_time;
1091 uint32 user_rid, group_rid;
1093 const char *username;
1094 const char *domain;
1095 const char *nt_username;
1096 const char *dir_drive;
1097 const char *unknown_str;
1098 const char *munged_dial;
1099 const char *fullname;
1100 const char *homedir;
1101 const char *logon_script;
1102 const char *profile_path;
1103 const char *acct_desc;
1104 const char *workstations;
1105 uint32 username_len, domain_len, nt_username_len,
1106 dir_drive_len, unknown_str_len, munged_dial_len,
1107 fullname_len, homedir_len, logon_script_len,
1108 profile_path_len, acct_desc_len, workstations_len;
1110 const uint8 *lm_pw;
1111 const uint8 *nt_pw;
1112 const uint8 *nt_pw_hist;
1113 uint32 lm_pw_len = 16;
1114 uint32 nt_pw_len = 16;
1115 uint32 nt_pw_hist_len;
1116 uint32 pwHistLen = 0;
1118 *buf = NULL;
1119 buflen = 0;
1121 logon_time = (uint32)pdb_get_logon_time(sampass);
1122 logoff_time = (uint32)pdb_get_logoff_time(sampass);
1123 kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
1124 bad_password_time = (uint32)pdb_get_bad_password_time(sampass);
1125 pass_can_change_time = (uint32)pdb_get_pass_can_change_time_noncalc(sampass);
1126 pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
1127 pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
1129 user_rid = pdb_get_user_rid(sampass);
1130 group_rid = pdb_get_group_rid(sampass);
1132 username = pdb_get_username(sampass);
1133 if (username) {
1134 username_len = strlen(username) +1;
1135 } else {
1136 username_len = 0;
1139 domain = pdb_get_domain(sampass);
1140 if (domain) {
1141 domain_len = strlen(domain) +1;
1142 } else {
1143 domain_len = 0;
1146 nt_username = pdb_get_nt_username(sampass);
1147 if (nt_username) {
1148 nt_username_len = strlen(nt_username) +1;
1149 } else {
1150 nt_username_len = 0;
1153 fullname = pdb_get_fullname(sampass);
1154 if (fullname) {
1155 fullname_len = strlen(fullname) +1;
1156 } else {
1157 fullname_len = 0;
1161 * Only updates fields which have been set (not defaults from smb.conf)
1164 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1165 dir_drive = pdb_get_dir_drive(sampass);
1166 } else {
1167 dir_drive = NULL;
1169 if (dir_drive) {
1170 dir_drive_len = strlen(dir_drive) +1;
1171 } else {
1172 dir_drive_len = 0;
1175 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1176 homedir = pdb_get_homedir(sampass);
1177 } else {
1178 homedir = NULL;
1180 if (homedir) {
1181 homedir_len = strlen(homedir) +1;
1182 } else {
1183 homedir_len = 0;
1186 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1187 logon_script = pdb_get_logon_script(sampass);
1188 } else {
1189 logon_script = NULL;
1191 if (logon_script) {
1192 logon_script_len = strlen(logon_script) +1;
1193 } else {
1194 logon_script_len = 0;
1197 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1198 profile_path = pdb_get_profile_path(sampass);
1199 } else {
1200 profile_path = NULL;
1202 if (profile_path) {
1203 profile_path_len = strlen(profile_path) +1;
1204 } else {
1205 profile_path_len = 0;
1208 lm_pw = pdb_get_lanman_passwd(sampass);
1209 if (!lm_pw) {
1210 lm_pw_len = 0;
1213 nt_pw = pdb_get_nt_passwd(sampass);
1214 if (!nt_pw) {
1215 nt_pw_len = 0;
1218 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1219 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1220 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1221 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1222 } else {
1223 nt_pw_hist_len = 0;
1226 acct_desc = pdb_get_acct_desc(sampass);
1227 if (acct_desc) {
1228 acct_desc_len = strlen(acct_desc) +1;
1229 } else {
1230 acct_desc_len = 0;
1233 workstations = pdb_get_workstations(sampass);
1234 if (workstations) {
1235 workstations_len = strlen(workstations) +1;
1236 } else {
1237 workstations_len = 0;
1240 unknown_str = NULL;
1241 unknown_str_len = 0;
1243 munged_dial = pdb_get_munged_dial(sampass);
1244 if (munged_dial) {
1245 munged_dial_len = strlen(munged_dial) +1;
1246 } else {
1247 munged_dial_len = 0;
1250 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1252 /* one time to get the size needed */
1253 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1254 logon_time, /* d */
1255 logoff_time, /* d */
1256 kickoff_time, /* d */
1257 bad_password_time, /* d */
1258 pass_last_set_time, /* d */
1259 pass_can_change_time, /* d */
1260 pass_must_change_time, /* d */
1261 username_len, username, /* B */
1262 domain_len, domain, /* B */
1263 nt_username_len, nt_username, /* B */
1264 fullname_len, fullname, /* B */
1265 homedir_len, homedir, /* B */
1266 dir_drive_len, dir_drive, /* B */
1267 logon_script_len, logon_script, /* B */
1268 profile_path_len, profile_path, /* B */
1269 acct_desc_len, acct_desc, /* B */
1270 workstations_len, workstations, /* B */
1271 unknown_str_len, unknown_str, /* B */
1272 munged_dial_len, munged_dial, /* B */
1273 user_rid, /* d */
1274 group_rid, /* d */
1275 lm_pw_len, lm_pw, /* B */
1276 nt_pw_len, nt_pw, /* B */
1277 nt_pw_hist_len, nt_pw_hist, /* B */
1278 pdb_get_acct_ctrl(sampass), /* d */
1279 pdb_get_logon_divs(sampass), /* w */
1280 pdb_get_hours_len(sampass), /* d */
1281 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1282 pdb_get_bad_password_count(sampass), /* w */
1283 pdb_get_logon_count(sampass), /* w */
1284 pdb_get_unknown_6(sampass)); /* d */
1286 if (size_only) {
1287 return buflen;
1290 /* malloc the space needed */
1291 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1292 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1293 return (-1);
1296 /* now for the real call to tdb_pack() */
1297 buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V3,
1298 logon_time, /* d */
1299 logoff_time, /* d */
1300 kickoff_time, /* d */
1301 bad_password_time, /* d */
1302 pass_last_set_time, /* d */
1303 pass_can_change_time, /* d */
1304 pass_must_change_time, /* d */
1305 username_len, username, /* B */
1306 domain_len, domain, /* B */
1307 nt_username_len, nt_username, /* B */
1308 fullname_len, fullname, /* B */
1309 homedir_len, homedir, /* B */
1310 dir_drive_len, dir_drive, /* B */
1311 logon_script_len, logon_script, /* B */
1312 profile_path_len, profile_path, /* B */
1313 acct_desc_len, acct_desc, /* B */
1314 workstations_len, workstations, /* B */
1315 unknown_str_len, unknown_str, /* B */
1316 munged_dial_len, munged_dial, /* B */
1317 user_rid, /* d */
1318 group_rid, /* d */
1319 lm_pw_len, lm_pw, /* B */
1320 nt_pw_len, nt_pw, /* B */
1321 nt_pw_hist_len, nt_pw_hist, /* B */
1322 pdb_get_acct_ctrl(sampass), /* d */
1323 pdb_get_logon_divs(sampass), /* w */
1324 pdb_get_hours_len(sampass), /* d */
1325 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1326 pdb_get_bad_password_count(sampass), /* w */
1327 pdb_get_logon_count(sampass), /* w */
1328 pdb_get_unknown_6(sampass)); /* d */
1330 /* check to make sure we got it correct */
1331 if (buflen != len) {
1332 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1333 (unsigned long)buflen, (unsigned long)len));
1334 /* error */
1335 SAFE_FREE (*buf);
1336 return (-1);
1339 return (buflen);
1343 /*********************************************************************
1344 *********************************************************************/
1346 BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src )
1348 uint8 *buf = NULL;
1349 int len;
1351 len = init_buffer_from_sam_v3(&buf, src, False);
1352 if (len == -1 || !buf) {
1353 SAFE_FREE(buf);
1354 return False;
1357 if (!init_sam_from_buffer_v3( dst, buf, len )) {
1358 free(buf);
1359 return False;
1362 dst->methods = src->methods;
1364 if ( src->unix_pw ) {
1365 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1366 if (!dst->unix_pw) {
1367 free(buf);
1368 return False;
1372 free(buf);
1373 return True;
1376 /*********************************************************************
1377 Update the bad password count checking the AP_RESET_COUNT_TIME
1378 *********************************************************************/
1380 BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
1382 time_t LastBadPassword;
1383 uint16 BadPasswordCount;
1384 uint32 resettime;
1386 BadPasswordCount = pdb_get_bad_password_count(sampass);
1387 if (!BadPasswordCount) {
1388 DEBUG(9, ("No bad password attempts.\n"));
1389 return True;
1392 if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) {
1393 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1394 return False;
1397 /* First, check if there is a reset time to compare */
1398 if ((resettime == (uint32) -1) || (resettime == 0)) {
1399 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1400 return True;
1403 LastBadPassword = pdb_get_bad_password_time(sampass);
1404 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1405 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1406 if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){
1407 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1408 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1409 if (updated) {
1410 *updated = True;
1414 return True;
1417 /*********************************************************************
1418 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1419 *********************************************************************/
1421 BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
1423 uint32 duration;
1424 time_t LastBadPassword;
1426 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1427 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1428 pdb_get_username(sampass)));
1429 return True;
1432 if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) {
1433 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1434 return False;
1437 /* First, check if there is a duration to compare */
1438 if ((duration == (uint32) -1) || (duration == 0)) {
1439 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1440 return True;
1443 LastBadPassword = pdb_get_bad_password_time(sampass);
1444 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1445 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1447 if (LastBadPassword == (time_t)0) {
1448 DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \
1449 bad password time. Leaving locked out.\n",
1450 pdb_get_username(sampass) ));
1451 return True;
1454 if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) {
1455 pdb_set_acct_ctrl(sampass,
1456 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
1457 PDB_CHANGED);
1458 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1459 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1460 if (updated) {
1461 *updated = True;
1465 return True;
1468 /*********************************************************************
1469 Increment the bad_password_count
1470 *********************************************************************/
1472 BOOL pdb_increment_bad_password_count(struct samu *sampass)
1474 uint32 account_policy_lockout;
1475 BOOL autolock_updated = False, badpw_updated = False;
1476 BOOL ret;
1478 /* Retrieve the account lockout policy */
1479 become_root();
1480 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
1481 unbecome_root();
1482 if ( !ret ) {
1483 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
1484 return False;
1487 /* If there is no policy, we don't need to continue checking */
1488 if (!account_policy_lockout) {
1489 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
1490 return True;
1493 /* Check if the autolock needs to be cleared */
1494 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
1495 return False;
1497 /* Check if the badpw count needs to be reset */
1498 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
1499 return False;
1502 Ok, now we can assume that any resetting that needs to be
1503 done has been done, and just get on with incrementing
1504 and autolocking if necessary
1507 pdb_set_bad_password_count(sampass,
1508 pdb_get_bad_password_count(sampass)+1,
1509 PDB_CHANGED);
1510 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
1513 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
1514 return True;
1516 if (!pdb_set_acct_ctrl(sampass,
1517 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
1518 PDB_CHANGED)) {
1519 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
1520 return False;
1523 return True;