include updates
[tomato.git] / release / src-rt-6.x.4708 / router / samba-3.0.25b / source / passdb / passdb.c
blobc073cc9a40da95f3783b1dace6840de895c81a8d
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", 32);
350 else
351 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
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 *user, 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( user, "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, user);
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 user, 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, user);
612 unbecome_root();
614 if (!ret) {
615 return False;
618 /* BUILTIN groups are looked up elsewhere */
619 if (!sid_check_is_in_our_domain(&map.sid)) {
620 DEBUG(10, ("Found group %s (%s) not in our domain -- "
621 "ignoring.", user,
622 sid_string_static(&map.sid)));
623 return False;
626 /* yes it's a mapped group */
627 sid_peek_rid(&map.sid, rid);
628 *type = map.sid_name_use;
629 return True;
632 /*************************************************************
633 Change a password entry in the local smbpasswd file.
634 *************************************************************/
636 NTSTATUS local_password_change(const char *user_name, int local_flags,
637 const char *new_passwd,
638 char *err_str, size_t err_str_len,
639 char *msg_str, size_t msg_str_len)
641 struct samu *sam_pass=NULL;
642 uint32 other_acb;
643 NTSTATUS result;
645 *err_str = '\0';
646 *msg_str = '\0';
648 /* Get the smb passwd entry for this user */
650 if ( !(sam_pass = samu_new( NULL )) ) {
651 return NT_STATUS_NO_MEMORY;
654 become_root();
655 if(!pdb_getsampwnam(sam_pass, user_name)) {
656 unbecome_root();
657 TALLOC_FREE(sam_pass);
659 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
660 int tmp_debug = DEBUGLEVEL;
661 struct passwd *pwd;
663 /* Might not exist in /etc/passwd. */
665 if (tmp_debug < 1) {
666 DEBUGLEVEL = 1;
669 if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
670 return NT_STATUS_NO_SUCH_USER;
673 /* create the struct samu and initialize the basic Unix properties */
675 if ( !(sam_pass = samu_new( NULL )) ) {
676 return NT_STATUS_NO_MEMORY;
679 result = samu_set_unix( sam_pass, pwd );
681 DEBUGLEVEL = tmp_debug;
683 TALLOC_FREE( pwd );
685 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
686 return result;
689 if (!NT_STATUS_IS_OK(result)) {
690 slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n",
691 user_name, nt_errstr(result));
692 return result;
694 } else {
695 slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
696 return NT_STATUS_NO_SUCH_USER;
698 } else {
699 unbecome_root();
700 /* the entry already existed */
701 local_flags &= ~LOCAL_ADD_USER;
704 /* the 'other' acb bits not being changed here */
705 other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
706 if (local_flags & LOCAL_TRUST_ACCOUNT) {
707 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
708 slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
709 TALLOC_FREE(sam_pass);
710 return NT_STATUS_UNSUCCESSFUL;
712 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
713 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
714 slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
715 TALLOC_FREE(sam_pass);
716 return NT_STATUS_UNSUCCESSFUL;
718 } else {
719 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
720 slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
721 TALLOC_FREE(sam_pass);
722 return NT_STATUS_UNSUCCESSFUL;
727 * We are root - just write the new password
728 * and the valid last change time.
731 if (local_flags & LOCAL_DISABLE_USER) {
732 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
733 slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
734 TALLOC_FREE(sam_pass);
735 return NT_STATUS_UNSUCCESSFUL;
737 } else if (local_flags & LOCAL_ENABLE_USER) {
738 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
739 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
740 TALLOC_FREE(sam_pass);
741 return NT_STATUS_UNSUCCESSFUL;
745 if (local_flags & LOCAL_SET_NO_PASSWORD) {
746 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
747 slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
748 TALLOC_FREE(sam_pass);
749 return NT_STATUS_UNSUCCESSFUL;
751 } else if (local_flags & LOCAL_SET_PASSWORD) {
753 * If we're dealing with setting a completely empty user account
754 * ie. One with a password of 'XXXX', but not set disabled (like
755 * an account created from scratch) then if the old password was
756 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
757 * We remove that as we're giving this user their first password
758 * and the decision hasn't really been made to disable them (ie.
759 * don't create them disabled). JRA.
761 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
762 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
763 slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
764 TALLOC_FREE(sam_pass);
765 return NT_STATUS_UNSUCCESSFUL;
768 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
769 slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
770 TALLOC_FREE(sam_pass);
771 return NT_STATUS_UNSUCCESSFUL;
774 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
775 slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
776 TALLOC_FREE(sam_pass);
777 return NT_STATUS_UNSUCCESSFUL;
781 if (local_flags & LOCAL_ADD_USER) {
782 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
783 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
784 TALLOC_FREE(sam_pass);
785 return NT_STATUS_OK;
786 } else {
787 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
788 TALLOC_FREE(sam_pass);
789 return NT_STATUS_UNSUCCESSFUL;
791 } else if (local_flags & LOCAL_DELETE_USER) {
792 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
793 slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
794 TALLOC_FREE(sam_pass);
795 return NT_STATUS_UNSUCCESSFUL;
797 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
798 } else {
799 result = pdb_update_sam_account(sam_pass);
800 if(!NT_STATUS_IS_OK(result)) {
801 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
802 TALLOC_FREE(sam_pass);
803 return result;
805 if(local_flags & LOCAL_DISABLE_USER)
806 slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
807 else if (local_flags & LOCAL_ENABLE_USER)
808 slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
809 else if (local_flags & LOCAL_SET_NO_PASSWORD)
810 slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
813 TALLOC_FREE(sam_pass);
814 return NT_STATUS_OK;
817 /**********************************************************************
818 Marshall/unmarshall struct samu structs.
819 *********************************************************************/
821 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
823 /*********************************************************************
824 *********************************************************************/
826 BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
829 /* times are stored as 32bit integer
830 take care on system with 64bit wide time_t
831 --SSS */
832 uint32 logon_time,
833 logoff_time,
834 kickoff_time,
835 bad_password_time,
836 pass_last_set_time,
837 pass_can_change_time,
838 pass_must_change_time;
839 char *username = NULL;
840 char *domain = NULL;
841 char *nt_username = NULL;
842 char *dir_drive = NULL;
843 char *unknown_str = NULL;
844 char *munged_dial = NULL;
845 char *fullname = NULL;
846 char *homedir = NULL;
847 char *logon_script = NULL;
848 char *profile_path = NULL;
849 char *acct_desc = NULL;
850 char *workstations = NULL;
851 uint32 username_len, domain_len, nt_username_len,
852 dir_drive_len, unknown_str_len, munged_dial_len,
853 fullname_len, homedir_len, logon_script_len,
854 profile_path_len, acct_desc_len, workstations_len;
856 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
857 uint16 logon_divs;
858 uint16 bad_password_count, logon_count;
859 uint8 *hours = NULL;
860 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
861 uint32 len = 0;
862 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
863 uint32 pwHistLen = 0;
864 BOOL ret = True;
865 fstring tmpstring;
866 BOOL expand_explicit = lp_passdb_expand_explicit();
868 if(sampass == NULL || buf == NULL) {
869 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
870 return False;
873 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
875 /* unpack the buffer into variables */
876 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V3,
877 &logon_time, /* d */
878 &logoff_time, /* d */
879 &kickoff_time, /* d */
880 &bad_password_time, /* d */
881 &pass_last_set_time, /* d */
882 &pass_can_change_time, /* d */
883 &pass_must_change_time, /* d */
884 &username_len, &username, /* B */
885 &domain_len, &domain, /* B */
886 &nt_username_len, &nt_username, /* B */
887 &fullname_len, &fullname, /* B */
888 &homedir_len, &homedir, /* B */
889 &dir_drive_len, &dir_drive, /* B */
890 &logon_script_len, &logon_script, /* B */
891 &profile_path_len, &profile_path, /* B */
892 &acct_desc_len, &acct_desc, /* B */
893 &workstations_len, &workstations, /* B */
894 &unknown_str_len, &unknown_str, /* B */
895 &munged_dial_len, &munged_dial, /* B */
896 &user_rid, /* d */
897 &group_rid, /* d */
898 &lm_pw_len, &lm_pw_ptr, /* B */
899 &nt_pw_len, &nt_pw_ptr, /* B */
900 /* Change from V1 is addition of password history field. */
901 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
902 /* Change from V2 is the uint32 acb_mask */
903 &acct_ctrl, /* d */
904 /* Also "remove_me" field was removed. */
905 &logon_divs, /* w */
906 &hours_len, /* d */
907 &hourslen, &hours, /* B */
908 &bad_password_count, /* w */
909 &logon_count, /* w */
910 &unknown_6); /* d */
912 if (len == (uint32) -1) {
913 ret = False;
914 goto done;
917 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
918 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
919 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
920 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
921 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
922 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
923 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
925 pdb_set_username(sampass, username, PDB_SET);
926 pdb_set_domain(sampass, domain, PDB_SET);
927 pdb_set_nt_username(sampass, nt_username, PDB_SET);
928 pdb_set_fullname(sampass, fullname, PDB_SET);
930 if (homedir) {
931 fstrcpy( tmpstring, homedir );
932 if (expand_explicit) {
933 standard_sub_basic( username, domain, tmpstring,
934 sizeof(tmpstring) );
936 pdb_set_homedir(sampass, tmpstring, PDB_SET);
938 else {
939 pdb_set_homedir(sampass,
940 talloc_sub_basic(sampass, username, domain,
941 lp_logon_home()),
942 PDB_DEFAULT);
945 if (dir_drive)
946 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
947 else
948 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
950 if (logon_script) {
951 fstrcpy( tmpstring, logon_script );
952 if (expand_explicit) {
953 standard_sub_basic( username, domain, tmpstring,
954 sizeof(tmpstring) );
956 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
958 else {
959 pdb_set_logon_script(sampass,
960 talloc_sub_basic(sampass, username, domain,
961 lp_logon_script()),
962 PDB_DEFAULT);
965 if (profile_path) {
966 fstrcpy( tmpstring, profile_path );
967 if (expand_explicit) {
968 standard_sub_basic( username, domain, tmpstring,
969 sizeof(tmpstring) );
971 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
973 else {
974 pdb_set_profile_path(sampass,
975 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
976 PDB_DEFAULT);
979 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
980 pdb_set_workstations(sampass, workstations, PDB_SET);
981 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
983 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
984 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
985 ret = False;
986 goto done;
990 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
991 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
992 ret = False;
993 goto done;
997 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
998 if (pwHistLen) {
999 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1000 if (!pw_hist) {
1001 ret = False;
1002 goto done;
1004 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1005 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1006 int i;
1007 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1008 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1009 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1010 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1011 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1012 PW_HISTORY_ENTRY_LEN);
1015 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1016 SAFE_FREE(pw_hist);
1017 ret = False;
1018 goto done;
1020 SAFE_FREE(pw_hist);
1021 } else {
1022 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1025 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1026 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1027 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1028 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1029 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1030 /* Change from V2 is the uint32 acct_ctrl */
1031 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1032 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1033 pdb_set_hours(sampass, hours, PDB_SET);
1035 done:
1037 SAFE_FREE(username);
1038 SAFE_FREE(domain);
1039 SAFE_FREE(nt_username);
1040 SAFE_FREE(fullname);
1041 SAFE_FREE(homedir);
1042 SAFE_FREE(dir_drive);
1043 SAFE_FREE(logon_script);
1044 SAFE_FREE(profile_path);
1045 SAFE_FREE(acct_desc);
1046 SAFE_FREE(workstations);
1047 SAFE_FREE(munged_dial);
1048 SAFE_FREE(unknown_str);
1049 SAFE_FREE(lm_pw_ptr);
1050 SAFE_FREE(nt_pw_ptr);
1051 SAFE_FREE(nt_pw_hist_ptr);
1052 SAFE_FREE(hours);
1054 return ret;
1057 /*********************************************************************
1058 *********************************************************************/
1060 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_only)
1062 size_t len, buflen;
1064 /* times are stored as 32bit integer
1065 take care on system with 64bit wide time_t
1066 --SSS */
1067 uint32 logon_time,
1068 logoff_time,
1069 kickoff_time,
1070 bad_password_time,
1071 pass_last_set_time,
1072 pass_can_change_time,
1073 pass_must_change_time;
1075 uint32 user_rid, group_rid;
1077 const char *username;
1078 const char *domain;
1079 const char *nt_username;
1080 const char *dir_drive;
1081 const char *unknown_str;
1082 const char *munged_dial;
1083 const char *fullname;
1084 const char *homedir;
1085 const char *logon_script;
1086 const char *profile_path;
1087 const char *acct_desc;
1088 const char *workstations;
1089 uint32 username_len, domain_len, nt_username_len,
1090 dir_drive_len, unknown_str_len, munged_dial_len,
1091 fullname_len, homedir_len, logon_script_len,
1092 profile_path_len, acct_desc_len, workstations_len;
1094 const uint8 *lm_pw;
1095 const uint8 *nt_pw;
1096 const uint8 *nt_pw_hist;
1097 uint32 lm_pw_len = 16;
1098 uint32 nt_pw_len = 16;
1099 uint32 nt_pw_hist_len;
1100 uint32 pwHistLen = 0;
1102 *buf = NULL;
1103 buflen = 0;
1105 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1106 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1107 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1108 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1109 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1110 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1111 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1113 user_rid = pdb_get_user_rid(sampass);
1114 group_rid = pdb_get_group_rid(sampass);
1116 username = pdb_get_username(sampass);
1117 if (username) {
1118 username_len = strlen(username) +1;
1119 } else {
1120 username_len = 0;
1123 domain = pdb_get_domain(sampass);
1124 if (domain) {
1125 domain_len = strlen(domain) +1;
1126 } else {
1127 domain_len = 0;
1130 nt_username = pdb_get_nt_username(sampass);
1131 if (nt_username) {
1132 nt_username_len = strlen(nt_username) +1;
1133 } else {
1134 nt_username_len = 0;
1137 fullname = pdb_get_fullname(sampass);
1138 if (fullname) {
1139 fullname_len = strlen(fullname) +1;
1140 } else {
1141 fullname_len = 0;
1145 * Only updates fields which have been set (not defaults from smb.conf)
1148 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1149 dir_drive = pdb_get_dir_drive(sampass);
1150 } else {
1151 dir_drive = NULL;
1153 if (dir_drive) {
1154 dir_drive_len = strlen(dir_drive) +1;
1155 } else {
1156 dir_drive_len = 0;
1159 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1160 homedir = pdb_get_homedir(sampass);
1161 } else {
1162 homedir = NULL;
1164 if (homedir) {
1165 homedir_len = strlen(homedir) +1;
1166 } else {
1167 homedir_len = 0;
1170 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1171 logon_script = pdb_get_logon_script(sampass);
1172 } else {
1173 logon_script = NULL;
1175 if (logon_script) {
1176 logon_script_len = strlen(logon_script) +1;
1177 } else {
1178 logon_script_len = 0;
1181 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1182 profile_path = pdb_get_profile_path(sampass);
1183 } else {
1184 profile_path = NULL;
1186 if (profile_path) {
1187 profile_path_len = strlen(profile_path) +1;
1188 } else {
1189 profile_path_len = 0;
1192 lm_pw = pdb_get_lanman_passwd(sampass);
1193 if (!lm_pw) {
1194 lm_pw_len = 0;
1197 nt_pw = pdb_get_nt_passwd(sampass);
1198 if (!nt_pw) {
1199 nt_pw_len = 0;
1202 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1203 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1204 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1205 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1206 } else {
1207 nt_pw_hist_len = 0;
1210 acct_desc = pdb_get_acct_desc(sampass);
1211 if (acct_desc) {
1212 acct_desc_len = strlen(acct_desc) +1;
1213 } else {
1214 acct_desc_len = 0;
1217 workstations = pdb_get_workstations(sampass);
1218 if (workstations) {
1219 workstations_len = strlen(workstations) +1;
1220 } else {
1221 workstations_len = 0;
1224 unknown_str = NULL;
1225 unknown_str_len = 0;
1227 munged_dial = pdb_get_munged_dial(sampass);
1228 if (munged_dial) {
1229 munged_dial_len = strlen(munged_dial) +1;
1230 } else {
1231 munged_dial_len = 0;
1234 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1236 /* one time to get the size needed */
1237 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1238 logon_time, /* d */
1239 logoff_time, /* d */
1240 kickoff_time, /* d */
1241 bad_password_time, /* d */
1242 pass_last_set_time, /* d */
1243 pass_can_change_time, /* d */
1244 pass_must_change_time, /* d */
1245 username_len, username, /* B */
1246 domain_len, domain, /* B */
1247 nt_username_len, nt_username, /* B */
1248 fullname_len, fullname, /* B */
1249 homedir_len, homedir, /* B */
1250 dir_drive_len, dir_drive, /* B */
1251 logon_script_len, logon_script, /* B */
1252 profile_path_len, profile_path, /* B */
1253 acct_desc_len, acct_desc, /* B */
1254 workstations_len, workstations, /* B */
1255 unknown_str_len, unknown_str, /* B */
1256 munged_dial_len, munged_dial, /* B */
1257 user_rid, /* d */
1258 group_rid, /* d */
1259 lm_pw_len, lm_pw, /* B */
1260 nt_pw_len, nt_pw, /* B */
1261 nt_pw_hist_len, nt_pw_hist, /* B */
1262 pdb_get_acct_ctrl(sampass), /* d */
1263 pdb_get_logon_divs(sampass), /* w */
1264 pdb_get_hours_len(sampass), /* d */
1265 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1266 pdb_get_bad_password_count(sampass), /* w */
1267 pdb_get_logon_count(sampass), /* w */
1268 pdb_get_unknown_6(sampass)); /* d */
1270 if (size_only) {
1271 return buflen;
1274 /* malloc the space needed */
1275 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1276 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1277 return (-1);
1280 /* now for the real call to tdb_pack() */
1281 buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V3,
1282 logon_time, /* d */
1283 logoff_time, /* d */
1284 kickoff_time, /* d */
1285 bad_password_time, /* d */
1286 pass_last_set_time, /* d */
1287 pass_can_change_time, /* d */
1288 pass_must_change_time, /* d */
1289 username_len, username, /* B */
1290 domain_len, domain, /* B */
1291 nt_username_len, nt_username, /* B */
1292 fullname_len, fullname, /* B */
1293 homedir_len, homedir, /* B */
1294 dir_drive_len, dir_drive, /* B */
1295 logon_script_len, logon_script, /* B */
1296 profile_path_len, profile_path, /* B */
1297 acct_desc_len, acct_desc, /* B */
1298 workstations_len, workstations, /* B */
1299 unknown_str_len, unknown_str, /* B */
1300 munged_dial_len, munged_dial, /* B */
1301 user_rid, /* d */
1302 group_rid, /* d */
1303 lm_pw_len, lm_pw, /* B */
1304 nt_pw_len, nt_pw, /* B */
1305 nt_pw_hist_len, nt_pw_hist, /* B */
1306 pdb_get_acct_ctrl(sampass), /* d */
1307 pdb_get_logon_divs(sampass), /* w */
1308 pdb_get_hours_len(sampass), /* d */
1309 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1310 pdb_get_bad_password_count(sampass), /* w */
1311 pdb_get_logon_count(sampass), /* w */
1312 pdb_get_unknown_6(sampass)); /* d */
1314 /* check to make sure we got it correct */
1315 if (buflen != len) {
1316 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1317 (unsigned long)buflen, (unsigned long)len));
1318 /* error */
1319 SAFE_FREE (*buf);
1320 return (-1);
1323 return (buflen);
1327 /*********************************************************************
1328 *********************************************************************/
1330 BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src )
1332 uint8 *buf = NULL;
1333 int len;
1335 len = init_buffer_from_sam_v3(&buf, src, False);
1336 if (len == -1 || !buf) {
1337 SAFE_FREE(buf);
1338 return False;
1341 if (!init_sam_from_buffer_v3( dst, buf, len )) {
1342 free(buf);
1343 return False;
1346 dst->methods = src->methods;
1348 if ( src->unix_pw ) {
1349 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1350 if (!dst->unix_pw) {
1351 free(buf);
1352 return False;
1356 free(buf);
1357 return True;
1360 /*********************************************************************
1361 Update the bad password count checking the AP_RESET_COUNT_TIME
1362 *********************************************************************/
1364 BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
1366 time_t LastBadPassword;
1367 uint16 BadPasswordCount;
1368 uint32 resettime;
1369 BOOL res;
1371 BadPasswordCount = pdb_get_bad_password_count(sampass);
1372 if (!BadPasswordCount) {
1373 DEBUG(9, ("No bad password attempts.\n"));
1374 return True;
1377 become_root();
1378 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
1379 unbecome_root();
1381 if (!res) {
1382 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1383 return False;
1386 /* First, check if there is a reset time to compare */
1387 if ((resettime == (uint32) -1) || (resettime == 0)) {
1388 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1389 return True;
1392 LastBadPassword = pdb_get_bad_password_time(sampass);
1393 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1394 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1395 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
1396 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1397 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1398 if (updated) {
1399 *updated = True;
1403 return True;
1406 /*********************************************************************
1407 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1408 *********************************************************************/
1410 BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
1412 uint32 duration;
1413 time_t LastBadPassword;
1414 BOOL res;
1416 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1417 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1418 pdb_get_username(sampass)));
1419 return True;
1422 become_root();
1423 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
1424 unbecome_root();
1426 if (!res) {
1427 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1428 return False;
1431 /* First, check if there is a duration to compare */
1432 if ((duration == (uint32) -1) || (duration == 0)) {
1433 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1434 return True;
1437 LastBadPassword = pdb_get_bad_password_time(sampass);
1438 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1439 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1441 if (LastBadPassword == (time_t)0) {
1442 DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \
1443 bad password time. Leaving locked out.\n",
1444 pdb_get_username(sampass) ));
1445 return True;
1448 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
1449 pdb_set_acct_ctrl(sampass,
1450 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
1451 PDB_CHANGED);
1452 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1453 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1454 if (updated) {
1455 *updated = True;
1459 return True;
1462 /*********************************************************************
1463 Increment the bad_password_count
1464 *********************************************************************/
1466 BOOL pdb_increment_bad_password_count(struct samu *sampass)
1468 uint32 account_policy_lockout;
1469 BOOL autolock_updated = False, badpw_updated = False;
1470 BOOL ret;
1472 /* Retrieve the account lockout policy */
1473 become_root();
1474 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
1475 unbecome_root();
1476 if ( !ret ) {
1477 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
1478 return False;
1481 /* If there is no policy, we don't need to continue checking */
1482 if (!account_policy_lockout) {
1483 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
1484 return True;
1487 /* Check if the autolock needs to be cleared */
1488 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
1489 return False;
1491 /* Check if the badpw count needs to be reset */
1492 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
1493 return False;
1496 Ok, now we can assume that any resetting that needs to be
1497 done has been done, and just get on with incrementing
1498 and autolocking if necessary
1501 pdb_set_bad_password_count(sampass,
1502 pdb_get_bad_password_count(sampass)+1,
1503 PDB_CHANGED);
1504 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
1507 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
1508 return True;
1510 if (!pdb_set_acct_ctrl(sampass,
1511 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
1512 PDB_CHANGED)) {
1513 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
1514 return False;
1517 return True;