Fix a panic in the [ug]id2sid valgrind bug fix
[Samba.git] / source / passdb / passdb.c
blob46dab156eefc313a9a0cb88a519d2436b18ac5ab
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 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
30 /******************************************************************
31 get the default domain/netbios name to be used when
32 testing authentication. For example, if you connect
33 to a Windows member server using a bogus domain name, the
34 Windows box will map the BOGUS\user to DOMAIN\user. A
35 standalone box will map to WKS\user.
36 ******************************************************************/
38 const char *my_sam_name(void)
40 /* standalone servers can only use the local netbios name */
41 if ( lp_server_role() == ROLE_STANDALONE )
42 return global_myname();
44 /* Windows domain members default to the DOMAIN
45 name when not specified */
46 return lp_workgroup();
49 /**********************************************************************
50 ***********************************************************************/
52 static int samu_destroy(struct samu *user)
54 data_blob_clear_free( &user->lm_pw );
55 data_blob_clear_free( &user->nt_pw );
57 if ( user->plaintext_pw )
58 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
60 return 0;
63 /**********************************************************************
64 generate a new struct samuser
65 ***********************************************************************/
67 struct samu *samu_new( TALLOC_CTX *ctx )
69 struct samu *user;
71 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
72 DEBUG(0,("samuser_new: Talloc failed!\n"));
73 return NULL;
76 talloc_set_destructor( user, samu_destroy );
78 /* no initial methods */
80 user->methods = NULL;
82 /* Don't change these timestamp settings without a good reason.
83 They are important for NT member server compatibility. */
85 user->logon_time = (time_t)0;
86 user->pass_last_set_time = (time_t)0;
87 user->pass_can_change_time = (time_t)0;
88 user->logoff_time = get_time_t_max();
89 user->kickoff_time = get_time_t_max();
90 user->pass_must_change_time = get_time_t_max();
91 user->fields_present = 0x00ffffff;
92 user->logon_divs = 168; /* hours per week */
93 user->hours_len = 21; /* 21 times 8 bits = 168 */
94 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
95 user->bad_password_count = 0;
96 user->logon_count = 0;
97 user->unknown_6 = 0x000004ec; /* don't know */
99 /* Some parts of samba strlen their pdb_get...() returns,
100 so this keeps the interface unchanged for now. */
102 user->username = "";
103 user->domain = "";
104 user->nt_username = "";
105 user->full_name = "";
106 user->home_dir = "";
107 user->logon_script = "";
108 user->profile_path = "";
109 user->acct_desc = "";
110 user->workstations = "";
111 user->comment = "";
112 user->munged_dial = "";
114 user->plaintext_pw = NULL;
116 /* Unless we know otherwise have a Account Control Bit
117 value of 'normal user'. This helps User Manager, which
118 asks for a filtered list of users. */
120 user->acct_ctrl = ACB_NORMAL;
123 return user;
126 /*********************************************************************
127 Initialize a struct samu from a struct passwd including the user
128 and group SIDs. The *user structure is filled out with the Unix
129 attributes and a user SID.
130 *********************************************************************/
132 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
134 const char *guest_account = lp_guestaccount();
135 const char *domain = global_myname();
136 uint32 urid;
138 if ( !pwd ) {
139 return NT_STATUS_NO_SUCH_USER;
142 /* Basic properties based upon the Unix account information */
144 pdb_set_username(user, pwd->pw_name, PDB_SET);
145 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
146 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
147 #if 0
148 /* This can lead to a primary group of S-1-22-2-XX which
149 will be rejected by other parts of the Samba code.
150 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
151 --jerry */
153 gid_to_sid(&group_sid, pwd->pw_gid);
154 pdb_set_group_sid(user, &group_sid, PDB_SET);
155 #endif
157 /* save the password structure for later use */
159 user->unix_pw = tcopy_passwd( user, pwd );
161 /* Special case for the guest account which must have a RID of 501 */
163 if ( strequal( pwd->pw_name, guest_account ) ) {
164 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
165 return NT_STATUS_NO_SUCH_USER;
167 return NT_STATUS_OK;
170 /* Non-guest accounts...Check for a workstation or user account */
172 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
173 /* workstation */
175 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
176 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
177 pwd->pw_name));
178 return NT_STATUS_INVALID_COMPUTER_NAME;
181 else {
182 /* user */
184 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
185 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
186 pwd->pw_name));
187 return NT_STATUS_INVALID_ACCOUNT_NAME;
190 /* set some basic attributes */
192 pdb_set_profile_path(user, talloc_sub_specified(user,
193 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
194 PDB_DEFAULT);
195 pdb_set_homedir(user, talloc_sub_specified(user,
196 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
197 PDB_DEFAULT);
198 pdb_set_dir_drive(user, talloc_sub_specified(user,
199 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
200 PDB_DEFAULT);
201 pdb_set_logon_script(user, talloc_sub_specified(user,
202 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
203 PDB_DEFAULT);
206 /* Now deal with the user SID. If we have a backend that can generate
207 RIDs, then do so. But sometimes the caller just wanted a structure
208 initialized and will fill in these fields later (such as from a
209 netr_SamInfo3 structure) */
211 if ( create && !pdb_rid_algorithm() ) {
212 uint32 user_rid;
213 DOM_SID user_sid;
215 if ( !pdb_new_rid( &user_rid ) ) {
216 DEBUG(3, ("Could not allocate a new RID\n"));
217 return NT_STATUS_ACCESS_DENIED;
220 sid_copy( &user_sid, get_global_sam_sid() );
221 sid_append_rid( &user_sid, user_rid );
223 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
224 DEBUG(3, ("pdb_set_user_sid failed\n"));
225 return NT_STATUS_INTERNAL_ERROR;
228 return NT_STATUS_OK;
231 /* generate a SID for the user with the RID algorithm */
233 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
235 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
236 return NT_STATUS_INTERNAL_ERROR;
239 return NT_STATUS_OK;
242 /********************************************************************
243 Set the Unix user attributes
244 ********************************************************************/
246 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
248 return samu_set_unix_internal( user, pwd, False );
251 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
253 return samu_set_unix_internal( user, pwd, True );
256 /**********************************************************
257 Encode the account control bits into a string.
258 length = length of string to encode into (including terminating
259 null). length *MUST BE MORE THAN 2* !
260 **********************************************************/
262 char *pdb_encode_acct_ctrl(uint32 acct_ctrl, size_t length)
264 fstring acct_str;
265 char *result;
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 result = talloc_strdup(talloc_tos(), acct_str);
293 SMB_ASSERT(result != NULL);
294 return result;
297 /**********************************************************
298 Decode the account control bits from a string.
299 **********************************************************/
301 uint32 pdb_decode_acct_ctrl(const char *p)
303 uint32 acct_ctrl = 0;
304 bool finished = False;
307 * Check if the account type bits have been encoded after the
308 * NT password (in the form [NDHTUWSLXI]).
311 if (*p != '[')
312 return 0;
314 for (p++; *p && !finished; p++) {
315 switch (*p) {
316 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
317 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
318 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
319 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
320 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
321 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
322 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
323 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
324 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
325 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
326 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
327 case ' ': { break; }
328 case ':':
329 case '\n':
330 case '\0':
331 case ']':
332 default: { finished = True; }
336 return acct_ctrl;
339 /*************************************************************
340 Routine to set 32 hex password characters from a 16 byte array.
341 **************************************************************/
343 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
345 if (pwd != NULL) {
346 int i;
347 for (i = 0; i < 16; i++)
348 slprintf(&p[i*2], 3, "%02X", pwd[i]);
349 } else {
350 if (acct_ctrl & ACB_PWNOTREQ)
351 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
352 else
353 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
357 /*************************************************************
358 Routine to get the 32 hex characters and turn them
359 into a 16 byte array.
360 **************************************************************/
362 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
364 int i;
365 unsigned char lonybble, hinybble;
366 const char *hexchars = "0123456789ABCDEF";
367 char *p1, *p2;
369 if (!p)
370 return (False);
372 for (i = 0; i < 32; i += 2) {
373 hinybble = toupper_ascii(p[i]);
374 lonybble = toupper_ascii(p[i + 1]);
376 p1 = strchr(hexchars, hinybble);
377 p2 = strchr(hexchars, lonybble);
379 if (!p1 || !p2)
380 return (False);
382 hinybble = PTR_DIFF(p1, hexchars);
383 lonybble = PTR_DIFF(p2, hexchars);
385 pwd[i / 2] = (hinybble << 4) | lonybble;
387 return (True);
390 /*************************************************************
391 Routine to set 42 hex hours characters from a 21 byte array.
392 **************************************************************/
394 void pdb_sethexhours(char *p, const unsigned char *hours)
396 if (hours != NULL) {
397 int i;
398 for (i = 0; i < 21; i++) {
399 slprintf(&p[i*2], 3, "%02X", hours[i]);
401 } else {
402 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
406 /*************************************************************
407 Routine to get the 42 hex characters and turn them
408 into a 21 byte array.
409 **************************************************************/
411 bool pdb_gethexhours(const char *p, unsigned char *hours)
413 int i;
414 unsigned char lonybble, hinybble;
415 const char *hexchars = "0123456789ABCDEF";
416 char *p1, *p2;
418 if (!p) {
419 return (False);
422 for (i = 0; i < 42; i += 2) {
423 hinybble = toupper_ascii(p[i]);
424 lonybble = toupper_ascii(p[i + 1]);
426 p1 = strchr(hexchars, hinybble);
427 p2 = strchr(hexchars, lonybble);
429 if (!p1 || !p2) {
430 return (False);
433 hinybble = PTR_DIFF(p1, hexchars);
434 lonybble = PTR_DIFF(p2, hexchars);
436 hours[i / 2] = (hinybble << 4) | lonybble;
438 return (True);
441 /********************************************************************
442 ********************************************************************/
444 int algorithmic_rid_base(void)
446 int rid_offset;
448 rid_offset = lp_algorithmic_rid_base();
450 if (rid_offset < BASE_RID) {
451 /* Try to prevent admin foot-shooting, we can't put algorithmic
452 rids below 1000, that's the 'well known RIDs' on NT */
453 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
454 rid_offset = BASE_RID;
456 if (rid_offset & 1) {
457 DEBUG(0, ("algorithmic rid base must be even\n"));
458 rid_offset += 1;
460 return rid_offset;
463 /*******************************************************************
464 Converts NT user RID to a UNIX uid.
465 ********************************************************************/
467 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
469 int rid_offset = algorithmic_rid_base();
470 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
473 uid_t max_algorithmic_uid(void)
475 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
478 /*******************************************************************
479 converts UNIX uid to an NT User RID.
480 ********************************************************************/
482 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
484 int rid_offset = algorithmic_rid_base();
485 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
488 /*******************************************************************
489 Converts NT group RID to a UNIX gid.
490 ********************************************************************/
492 gid_t pdb_group_rid_to_gid(uint32 group_rid)
494 int rid_offset = algorithmic_rid_base();
495 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
498 gid_t max_algorithmic_gid(void)
500 return pdb_group_rid_to_gid(0xffffffff);
503 /*******************************************************************
504 converts NT Group RID to a UNIX uid.
506 warning: you must not call that function only
507 you must do a call to the group mapping first.
508 there is not anymore a direct link between the gid and the rid.
509 ********************************************************************/
511 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
513 int rid_offset = algorithmic_rid_base();
514 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
517 /*******************************************************************
518 Decides if a RID is a well known RID.
519 ********************************************************************/
521 static bool rid_is_well_known(uint32 rid)
523 /* Not using rid_offset here, because this is the actual
524 NT fixed value (1000) */
526 return (rid < BASE_RID);
529 /*******************************************************************
530 Decides if a RID is a user or group RID.
531 ********************************************************************/
533 bool algorithmic_pdb_rid_is_user(uint32 rid)
535 if ( rid_is_well_known(rid) ) {
537 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
538 * and DOMAIN_USER_RID_GUEST.
540 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
541 return True;
542 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
543 return True;
545 return False;
548 /*******************************************************************
549 Convert a name into a SID. Used in the lookup name rpc.
550 ********************************************************************/
552 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
553 enum lsa_SidType *type)
555 GROUP_MAP map;
556 bool ret;
558 /* Windows treats "MACHINE\None" as a special name for
559 rid 513 on non-DCs. You cannot create a user or group
560 name "None" on Windows. You will get an error that
561 the group already exists. */
563 if ( strequal( name, "None" ) ) {
564 *rid = DOMAIN_GROUP_RID_USERS;
565 *type = SID_NAME_DOM_GRP;
567 return True;
570 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
571 * correctly in the case where foo also exists as a user. If the flag
572 * is set, don't look for users at all. */
574 if ((flags & LOOKUP_NAME_GROUP) == 0) {
575 struct samu *sam_account = NULL;
576 DOM_SID user_sid;
578 if ( !(sam_account = samu_new( NULL )) ) {
579 return False;
582 become_root();
583 ret = pdb_getsampwnam(sam_account, name);
584 unbecome_root();
586 if (ret) {
587 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
590 TALLOC_FREE(sam_account);
592 if (ret) {
593 if (!sid_check_is_in_our_domain(&user_sid)) {
594 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
595 name, sid_string_dbg(&user_sid)));
596 return False;
599 sid_peek_rid(&user_sid, rid);
600 *type = SID_NAME_USER;
601 return True;
606 * Maybe it is a group ?
609 become_root();
610 ret = pdb_getgrnam(&map, name);
611 unbecome_root();
613 if (!ret) {
614 return False;
617 /* BUILTIN groups are looked up elsewhere */
618 if (!sid_check_is_in_our_domain(&map.sid)) {
619 DEBUG(10, ("Found group %s (%s) not in our domain -- "
620 "ignoring.", name, sid_string_dbg(&map.sid)));
621 return False;
624 /* yes it's a mapped group */
625 sid_peek_rid(&map.sid, rid);
626 *type = map.sid_name_use;
627 return True;
630 /*************************************************************
631 Change a password entry in the local smbpasswd file.
632 *************************************************************/
634 NTSTATUS local_password_change(const char *user_name,
635 int local_flags,
636 const char *new_passwd,
637 char **pp_err_str,
638 char **pp_msg_str)
640 struct samu *sam_pass=NULL;
641 uint32 other_acb;
642 NTSTATUS result;
644 *pp_err_str = NULL;
645 *pp_msg_str = NULL;
647 /* Get the smb passwd entry for this user */
649 if ( !(sam_pass = samu_new( NULL )) ) {
650 return NT_STATUS_NO_MEMORY;
653 become_root();
654 if(!pdb_getsampwnam(sam_pass, user_name)) {
655 unbecome_root();
656 TALLOC_FREE(sam_pass);
658 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
659 int tmp_debug = DEBUGLEVEL;
660 struct passwd *pwd;
662 /* Might not exist in /etc/passwd. */
664 if (tmp_debug < 1) {
665 DEBUGLEVEL = 1;
668 if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
669 return NT_STATUS_NO_SUCH_USER;
672 /* create the struct samu and initialize the basic Unix properties */
674 if ( !(sam_pass = samu_new( NULL )) ) {
675 return NT_STATUS_NO_MEMORY;
678 result = samu_set_unix( sam_pass, pwd );
680 DEBUGLEVEL = tmp_debug;
682 TALLOC_FREE( pwd );
684 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
685 return result;
688 if (!NT_STATUS_IS_OK(result)) {
689 asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
690 user_name, nt_errstr(result));
691 return result;
693 } else {
694 asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name);
695 return NT_STATUS_NO_SUCH_USER;
697 } else {
698 unbecome_root();
699 /* the entry already existed */
700 local_flags &= ~LOCAL_ADD_USER;
703 /* the 'other' acb bits not being changed here */
704 other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
705 if (local_flags & LOCAL_TRUST_ACCOUNT) {
706 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
707 asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
708 TALLOC_FREE(sam_pass);
709 return NT_STATUS_UNSUCCESSFUL;
711 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
712 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
713 asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
714 TALLOC_FREE(sam_pass);
715 return NT_STATUS_UNSUCCESSFUL;
717 } else {
718 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
719 asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name);
720 TALLOC_FREE(sam_pass);
721 return NT_STATUS_UNSUCCESSFUL;
726 * We are root - just write the new password
727 * and the valid last change time.
730 if (local_flags & LOCAL_DISABLE_USER) {
731 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
732 asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name);
733 TALLOC_FREE(sam_pass);
734 return NT_STATUS_UNSUCCESSFUL;
736 } else if (local_flags & LOCAL_ENABLE_USER) {
737 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
738 asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name);
739 TALLOC_FREE(sam_pass);
740 return NT_STATUS_UNSUCCESSFUL;
744 if (local_flags & LOCAL_SET_NO_PASSWORD) {
745 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
746 asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name);
747 TALLOC_FREE(sam_pass);
748 return NT_STATUS_UNSUCCESSFUL;
750 } else if (local_flags & LOCAL_SET_PASSWORD) {
752 * If we're dealing with setting a completely empty user account
753 * ie. One with a password of 'XXXX', but not set disabled (like
754 * an account created from scratch) then if the old password was
755 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
756 * We remove that as we're giving this user their first password
757 * and the decision hasn't really been made to disable them (ie.
758 * don't create them disabled). JRA.
760 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
761 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
762 asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name);
763 TALLOC_FREE(sam_pass);
764 return NT_STATUS_UNSUCCESSFUL;
767 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
768 asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name);
769 TALLOC_FREE(sam_pass);
770 return NT_STATUS_UNSUCCESSFUL;
773 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
774 asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name);
775 TALLOC_FREE(sam_pass);
776 return NT_STATUS_UNSUCCESSFUL;
780 if (local_flags & LOCAL_ADD_USER) {
781 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
782 asprintf(pp_msg_str, "Added user %s.\n", user_name);
783 TALLOC_FREE(sam_pass);
784 return NT_STATUS_OK;
785 } else {
786 asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name);
787 TALLOC_FREE(sam_pass);
788 return NT_STATUS_UNSUCCESSFUL;
790 } else if (local_flags & LOCAL_DELETE_USER) {
791 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
792 asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name);
793 TALLOC_FREE(sam_pass);
794 return NT_STATUS_UNSUCCESSFUL;
796 asprintf(pp_msg_str, "Deleted user %s.\n", user_name);
797 } else {
798 result = pdb_update_sam_account(sam_pass);
799 if(!NT_STATUS_IS_OK(result)) {
800 asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name);
801 TALLOC_FREE(sam_pass);
802 return result;
804 if(local_flags & LOCAL_DISABLE_USER)
805 asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
806 else if (local_flags & LOCAL_ENABLE_USER)
807 asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
808 else if (local_flags & LOCAL_SET_NO_PASSWORD)
809 asprintf(pp_msg_str, "User %s password set to none.\n", user_name);
812 TALLOC_FREE(sam_pass);
813 return NT_STATUS_OK;
816 /**********************************************************************
817 Marshall/unmarshall struct samu structs.
818 *********************************************************************/
820 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
822 /*********************************************************************
823 *********************************************************************/
825 bool init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
828 /* times are stored as 32bit integer
829 take care on system with 64bit wide time_t
830 --SSS */
831 uint32 logon_time,
832 logoff_time,
833 kickoff_time,
834 bad_password_time,
835 pass_last_set_time,
836 pass_can_change_time,
837 pass_must_change_time;
838 char *username = NULL;
839 char *domain = NULL;
840 char *nt_username = NULL;
841 char *dir_drive = NULL;
842 char *unknown_str = NULL;
843 char *munged_dial = NULL;
844 char *fullname = NULL;
845 char *homedir = NULL;
846 char *logon_script = NULL;
847 char *profile_path = NULL;
848 char *acct_desc = NULL;
849 char *workstations = NULL;
850 uint32 username_len, domain_len, nt_username_len,
851 dir_drive_len, unknown_str_len, munged_dial_len,
852 fullname_len, homedir_len, logon_script_len,
853 profile_path_len, acct_desc_len, workstations_len;
855 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
856 uint16 logon_divs;
857 uint16 bad_password_count, logon_count;
858 uint8 *hours = NULL;
859 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
860 uint32 len = 0;
861 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
862 uint32 pwHistLen = 0;
863 bool ret = True;
864 fstring tmp_string;
865 bool expand_explicit = lp_passdb_expand_explicit();
867 if(sampass == NULL || buf == NULL) {
868 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
869 return False;
872 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
874 /* unpack the buffer into variables */
875 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V3,
876 &logon_time, /* d */
877 &logoff_time, /* d */
878 &kickoff_time, /* d */
879 &bad_password_time, /* d */
880 &pass_last_set_time, /* d */
881 &pass_can_change_time, /* d */
882 &pass_must_change_time, /* d */
883 &username_len, &username, /* B */
884 &domain_len, &domain, /* B */
885 &nt_username_len, &nt_username, /* B */
886 &fullname_len, &fullname, /* B */
887 &homedir_len, &homedir, /* B */
888 &dir_drive_len, &dir_drive, /* B */
889 &logon_script_len, &logon_script, /* B */
890 &profile_path_len, &profile_path, /* B */
891 &acct_desc_len, &acct_desc, /* B */
892 &workstations_len, &workstations, /* B */
893 &unknown_str_len, &unknown_str, /* B */
894 &munged_dial_len, &munged_dial, /* B */
895 &user_rid, /* d */
896 &group_rid, /* d */
897 &lm_pw_len, &lm_pw_ptr, /* B */
898 &nt_pw_len, &nt_pw_ptr, /* B */
899 /* Change from V1 is addition of password history field. */
900 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
901 /* Change from V2 is the uint32 acb_mask */
902 &acct_ctrl, /* d */
903 /* Also "remove_me" field was removed. */
904 &logon_divs, /* w */
905 &hours_len, /* d */
906 &hourslen, &hours, /* B */
907 &bad_password_count, /* w */
908 &logon_count, /* w */
909 &unknown_6); /* d */
911 if (len == (uint32) -1) {
912 ret = False;
913 goto done;
916 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
917 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
918 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
919 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
920 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
921 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
922 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
924 pdb_set_username(sampass, username, PDB_SET);
925 pdb_set_domain(sampass, domain, PDB_SET);
926 pdb_set_nt_username(sampass, nt_username, PDB_SET);
927 pdb_set_fullname(sampass, fullname, PDB_SET);
929 if (homedir) {
930 fstrcpy( tmp_string, homedir );
931 if (expand_explicit) {
932 standard_sub_basic( username, domain, tmp_string,
933 sizeof(tmp_string) );
935 pdb_set_homedir(sampass, tmp_string, PDB_SET);
937 else {
938 pdb_set_homedir(sampass,
939 talloc_sub_basic(sampass, username, domain,
940 lp_logon_home()),
941 PDB_DEFAULT);
944 if (dir_drive)
945 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
946 else
947 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
949 if (logon_script) {
950 fstrcpy( tmp_string, logon_script );
951 if (expand_explicit) {
952 standard_sub_basic( username, domain, tmp_string,
953 sizeof(tmp_string) );
955 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
957 else {
958 pdb_set_logon_script(sampass,
959 talloc_sub_basic(sampass, username, domain,
960 lp_logon_script()),
961 PDB_DEFAULT);
964 if (profile_path) {
965 fstrcpy( tmp_string, profile_path );
966 if (expand_explicit) {
967 standard_sub_basic( username, domain, tmp_string,
968 sizeof(tmp_string) );
970 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
972 else {
973 pdb_set_profile_path(sampass,
974 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
975 PDB_DEFAULT);
978 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
979 pdb_set_workstations(sampass, workstations, PDB_SET);
980 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
982 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
983 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
984 ret = False;
985 goto done;
989 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
990 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
991 ret = False;
992 goto done;
996 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
997 if (pwHistLen) {
998 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
999 if (!pw_hist) {
1000 ret = False;
1001 goto done;
1003 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1004 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1005 int i;
1006 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1007 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1008 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1009 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1010 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1011 PW_HISTORY_ENTRY_LEN);
1014 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1015 SAFE_FREE(pw_hist);
1016 ret = False;
1017 goto done;
1019 SAFE_FREE(pw_hist);
1020 } else {
1021 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1024 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1025 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1026 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1027 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1028 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1029 /* Change from V2 is the uint32 acct_ctrl */
1030 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1031 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1032 pdb_set_hours(sampass, hours, PDB_SET);
1034 done:
1036 SAFE_FREE(username);
1037 SAFE_FREE(domain);
1038 SAFE_FREE(nt_username);
1039 SAFE_FREE(fullname);
1040 SAFE_FREE(homedir);
1041 SAFE_FREE(dir_drive);
1042 SAFE_FREE(logon_script);
1043 SAFE_FREE(profile_path);
1044 SAFE_FREE(acct_desc);
1045 SAFE_FREE(workstations);
1046 SAFE_FREE(munged_dial);
1047 SAFE_FREE(unknown_str);
1048 SAFE_FREE(lm_pw_ptr);
1049 SAFE_FREE(nt_pw_ptr);
1050 SAFE_FREE(nt_pw_hist_ptr);
1051 SAFE_FREE(hours);
1053 return ret;
1056 /*********************************************************************
1057 *********************************************************************/
1059 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1061 size_t len, buflen;
1063 /* times are stored as 32bit integer
1064 take care on system with 64bit wide time_t
1065 --SSS */
1066 uint32 logon_time,
1067 logoff_time,
1068 kickoff_time,
1069 bad_password_time,
1070 pass_last_set_time,
1071 pass_can_change_time,
1072 pass_must_change_time;
1074 uint32 user_rid, group_rid;
1076 const char *username;
1077 const char *domain;
1078 const char *nt_username;
1079 const char *dir_drive;
1080 const char *unknown_str;
1081 const char *munged_dial;
1082 const char *fullname;
1083 const char *homedir;
1084 const char *logon_script;
1085 const char *profile_path;
1086 const char *acct_desc;
1087 const char *workstations;
1088 uint32 username_len, domain_len, nt_username_len,
1089 dir_drive_len, unknown_str_len, munged_dial_len,
1090 fullname_len, homedir_len, logon_script_len,
1091 profile_path_len, acct_desc_len, workstations_len;
1093 const uint8 *lm_pw;
1094 const uint8 *nt_pw;
1095 const uint8 *nt_pw_hist;
1096 uint32 lm_pw_len = 16;
1097 uint32 nt_pw_len = 16;
1098 uint32 nt_pw_hist_len;
1099 uint32 pwHistLen = 0;
1101 *buf = NULL;
1102 buflen = 0;
1104 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1105 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1106 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1107 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1108 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1109 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1110 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1112 user_rid = pdb_get_user_rid(sampass);
1113 group_rid = pdb_get_group_rid(sampass);
1115 username = pdb_get_username(sampass);
1116 if (username) {
1117 username_len = strlen(username) +1;
1118 } else {
1119 username_len = 0;
1122 domain = pdb_get_domain(sampass);
1123 if (domain) {
1124 domain_len = strlen(domain) +1;
1125 } else {
1126 domain_len = 0;
1129 nt_username = pdb_get_nt_username(sampass);
1130 if (nt_username) {
1131 nt_username_len = strlen(nt_username) +1;
1132 } else {
1133 nt_username_len = 0;
1136 fullname = pdb_get_fullname(sampass);
1137 if (fullname) {
1138 fullname_len = strlen(fullname) +1;
1139 } else {
1140 fullname_len = 0;
1144 * Only updates fields which have been set (not defaults from smb.conf)
1147 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1148 dir_drive = pdb_get_dir_drive(sampass);
1149 } else {
1150 dir_drive = NULL;
1152 if (dir_drive) {
1153 dir_drive_len = strlen(dir_drive) +1;
1154 } else {
1155 dir_drive_len = 0;
1158 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1159 homedir = pdb_get_homedir(sampass);
1160 } else {
1161 homedir = NULL;
1163 if (homedir) {
1164 homedir_len = strlen(homedir) +1;
1165 } else {
1166 homedir_len = 0;
1169 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1170 logon_script = pdb_get_logon_script(sampass);
1171 } else {
1172 logon_script = NULL;
1174 if (logon_script) {
1175 logon_script_len = strlen(logon_script) +1;
1176 } else {
1177 logon_script_len = 0;
1180 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1181 profile_path = pdb_get_profile_path(sampass);
1182 } else {
1183 profile_path = NULL;
1185 if (profile_path) {
1186 profile_path_len = strlen(profile_path) +1;
1187 } else {
1188 profile_path_len = 0;
1191 lm_pw = pdb_get_lanman_passwd(sampass);
1192 if (!lm_pw) {
1193 lm_pw_len = 0;
1196 nt_pw = pdb_get_nt_passwd(sampass);
1197 if (!nt_pw) {
1198 nt_pw_len = 0;
1201 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1202 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1203 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1204 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1205 } else {
1206 nt_pw_hist_len = 0;
1209 acct_desc = pdb_get_acct_desc(sampass);
1210 if (acct_desc) {
1211 acct_desc_len = strlen(acct_desc) +1;
1212 } else {
1213 acct_desc_len = 0;
1216 workstations = pdb_get_workstations(sampass);
1217 if (workstations) {
1218 workstations_len = strlen(workstations) +1;
1219 } else {
1220 workstations_len = 0;
1223 unknown_str = NULL;
1224 unknown_str_len = 0;
1226 munged_dial = pdb_get_munged_dial(sampass);
1227 if (munged_dial) {
1228 munged_dial_len = strlen(munged_dial) +1;
1229 } else {
1230 munged_dial_len = 0;
1233 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1235 /* one time to get the size needed */
1236 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1237 logon_time, /* d */
1238 logoff_time, /* d */
1239 kickoff_time, /* d */
1240 bad_password_time, /* d */
1241 pass_last_set_time, /* d */
1242 pass_can_change_time, /* d */
1243 pass_must_change_time, /* d */
1244 username_len, username, /* B */
1245 domain_len, domain, /* B */
1246 nt_username_len, nt_username, /* B */
1247 fullname_len, fullname, /* B */
1248 homedir_len, homedir, /* B */
1249 dir_drive_len, dir_drive, /* B */
1250 logon_script_len, logon_script, /* B */
1251 profile_path_len, profile_path, /* B */
1252 acct_desc_len, acct_desc, /* B */
1253 workstations_len, workstations, /* B */
1254 unknown_str_len, unknown_str, /* B */
1255 munged_dial_len, munged_dial, /* B */
1256 user_rid, /* d */
1257 group_rid, /* d */
1258 lm_pw_len, lm_pw, /* B */
1259 nt_pw_len, nt_pw, /* B */
1260 nt_pw_hist_len, nt_pw_hist, /* B */
1261 pdb_get_acct_ctrl(sampass), /* d */
1262 pdb_get_logon_divs(sampass), /* w */
1263 pdb_get_hours_len(sampass), /* d */
1264 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1265 pdb_get_bad_password_count(sampass), /* w */
1266 pdb_get_logon_count(sampass), /* w */
1267 pdb_get_unknown_6(sampass)); /* d */
1269 if (size_only) {
1270 return buflen;
1273 /* malloc the space needed */
1274 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1275 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1276 return (-1);
1279 /* now for the real call to tdb_pack() */
1280 buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING_V3,
1281 logon_time, /* d */
1282 logoff_time, /* d */
1283 kickoff_time, /* d */
1284 bad_password_time, /* d */
1285 pass_last_set_time, /* d */
1286 pass_can_change_time, /* d */
1287 pass_must_change_time, /* d */
1288 username_len, username, /* B */
1289 domain_len, domain, /* B */
1290 nt_username_len, nt_username, /* B */
1291 fullname_len, fullname, /* B */
1292 homedir_len, homedir, /* B */
1293 dir_drive_len, dir_drive, /* B */
1294 logon_script_len, logon_script, /* B */
1295 profile_path_len, profile_path, /* B */
1296 acct_desc_len, acct_desc, /* B */
1297 workstations_len, workstations, /* B */
1298 unknown_str_len, unknown_str, /* B */
1299 munged_dial_len, munged_dial, /* B */
1300 user_rid, /* d */
1301 group_rid, /* d */
1302 lm_pw_len, lm_pw, /* B */
1303 nt_pw_len, nt_pw, /* B */
1304 nt_pw_hist_len, nt_pw_hist, /* B */
1305 pdb_get_acct_ctrl(sampass), /* d */
1306 pdb_get_logon_divs(sampass), /* w */
1307 pdb_get_hours_len(sampass), /* d */
1308 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1309 pdb_get_bad_password_count(sampass), /* w */
1310 pdb_get_logon_count(sampass), /* w */
1311 pdb_get_unknown_6(sampass)); /* d */
1313 /* check to make sure we got it correct */
1314 if (buflen != len) {
1315 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1316 (unsigned long)buflen, (unsigned long)len));
1317 /* error */
1318 SAFE_FREE (*buf);
1319 return (-1);
1322 return (buflen);
1326 /*********************************************************************
1327 *********************************************************************/
1329 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
1331 uint8 *buf = NULL;
1332 int len;
1334 len = init_buffer_from_sam_v3(&buf, src, False);
1335 if (len == -1 || !buf) {
1336 SAFE_FREE(buf);
1337 return False;
1340 if (!init_sam_from_buffer_v3( dst, buf, len )) {
1341 free(buf);
1342 return False;
1345 dst->methods = src->methods;
1347 if ( src->unix_pw ) {
1348 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1349 if (!dst->unix_pw) {
1350 free(buf);
1351 return False;
1355 free(buf);
1356 return True;
1359 /*********************************************************************
1360 Update the bad password count checking the AP_RESET_COUNT_TIME
1361 *********************************************************************/
1363 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
1365 time_t LastBadPassword;
1366 uint16 BadPasswordCount;
1367 uint32 resettime;
1368 bool res;
1370 BadPasswordCount = pdb_get_bad_password_count(sampass);
1371 if (!BadPasswordCount) {
1372 DEBUG(9, ("No bad password attempts.\n"));
1373 return True;
1376 become_root();
1377 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
1378 unbecome_root();
1380 if (!res) {
1381 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1382 return False;
1385 /* First, check if there is a reset time to compare */
1386 if ((resettime == (uint32) -1) || (resettime == 0)) {
1387 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1388 return True;
1391 LastBadPassword = pdb_get_bad_password_time(sampass);
1392 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1393 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1394 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
1395 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1396 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1397 if (updated) {
1398 *updated = True;
1402 return True;
1405 /*********************************************************************
1406 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1407 *********************************************************************/
1409 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
1411 uint32 duration;
1412 time_t LastBadPassword;
1413 bool res;
1415 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1416 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1417 pdb_get_username(sampass)));
1418 return True;
1421 become_root();
1422 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
1423 unbecome_root();
1425 if (!res) {
1426 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1427 return False;
1430 /* First, check if there is a duration to compare */
1431 if ((duration == (uint32) -1) || (duration == 0)) {
1432 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1433 return True;
1436 LastBadPassword = pdb_get_bad_password_time(sampass);
1437 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1438 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1440 if (LastBadPassword == (time_t)0) {
1441 DEBUG(1,("pdb_update_autolock_flag: Account %s "
1442 "administratively locked out with no bad password "
1443 "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;
1520 bool is_trusted_domain_situation(const char *domain_name)
1522 return IS_DC &&
1523 lp_allow_trusted_domains() &&
1524 !strequal(domain_name, lp_workgroup());
1527 /*******************************************************************
1528 Wrapper around retrieving the clear text trust account password.
1529 appropriate account name is stored in account_name.
1530 Caller must free password, but not account_name.
1531 *******************************************************************/
1533 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
1534 const char **account_name, uint32 *channel)
1536 char *pwd;
1537 time_t last_set_time;
1539 /* if we are a DC and this is not our domain, then lookup an account
1540 * for the domain trust */
1542 if (is_trusted_domain_situation(domain)) {
1543 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
1544 &last_set_time))
1546 DEBUG(0, ("get_trust_pw: could not fetch trust "
1547 "account password for trusted domain %s\n",
1548 domain));
1549 return false;
1552 if (channel != NULL) {
1553 *channel = SEC_CHAN_DOMAIN;
1556 if (account_name != NULL) {
1557 *account_name = lp_workgroup();
1560 return true;
1563 /* Just get the account for the requested domain. In the future this
1564 * might also cover to be member of more than one domain. */
1566 pwd = secrets_fetch_machine_password(domain, &last_set_time, channel);
1568 if (pwd != NULL) {
1569 *ret_pwd = pwd;
1570 if (account_name != NULL) {
1571 *account_name = global_myname();
1574 return true;
1577 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
1578 "account password for domain %s\n", domain));
1579 return false;
1582 /*******************************************************************
1583 Wrapper around retrieving the trust account password.
1584 appropriate account name is stored in account_name.
1585 *******************************************************************/
1587 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
1588 const char **account_name, uint32 *channel)
1590 char *pwd = NULL;
1591 time_t last_set_time;
1593 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
1594 E_md4hash(pwd, ret_pwd);
1595 SAFE_FREE(pwd);
1596 return true;
1597 } else if (is_trusted_domain_situation(domain)) {
1598 return false;
1601 /* as a fallback, try to get the hashed pwd directly from the tdb... */
1603 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
1604 &last_set_time,
1605 channel))
1607 if (account_name != NULL) {
1608 *account_name = global_myname();
1611 return true;
1614 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
1615 "password for domain %s\n", domain));
1616 return False;
1619 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
1620 struct samu *pw)
1622 struct samr_LogonHours hours;
1623 const int units_per_week = 168;
1625 ZERO_STRUCT(hours);
1626 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
1627 if (!hours.bits) {
1628 return hours;
1631 hours.units_per_week = units_per_week;
1632 memset(hours.bits, 0xFF, units_per_week);
1634 if (pdb_get_hours(pw)) {
1635 memcpy(hours.bits, pdb_get_hours(pw),
1636 MIN(pdb_get_hours_len(pw), units_per_week));
1639 return hours;