Fix more "warning: ignoring return value of ‘asprintf’, declared with
[Samba/gbeck.git] / source3 / passdb / passdb.c
blobbb0daaa3f47e29de02ed0f4280ee5aa72fce4689
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_t 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_t pdb_decode_acct_ctrl(const char *p)
303 uint32_t 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(talloc_autofree_context(), 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 if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
690 user_name, nt_errstr(result)) < 0) {
691 *pp_err_str = NULL;
693 return result;
695 } else {
696 if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) {
697 *pp_err_str = NULL;
699 return NT_STATUS_NO_SUCH_USER;
701 } else {
702 unbecome_root();
703 /* the entry already existed */
704 local_flags &= ~LOCAL_ADD_USER;
707 /* the 'other' acb bits not being changed here */
708 other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
709 if (local_flags & LOCAL_TRUST_ACCOUNT) {
710 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
711 if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) {
712 *pp_err_str = NULL;
714 TALLOC_FREE(sam_pass);
715 return NT_STATUS_UNSUCCESSFUL;
717 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
718 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
719 if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) {
720 *pp_err_str = NULL;
722 TALLOC_FREE(sam_pass);
723 return NT_STATUS_UNSUCCESSFUL;
725 } else {
726 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
727 if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) {
728 *pp_err_str = NULL;
730 TALLOC_FREE(sam_pass);
731 return NT_STATUS_UNSUCCESSFUL;
736 * We are root - just write the new password
737 * and the valid last change time.
740 if (local_flags & LOCAL_DISABLE_USER) {
741 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
742 if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) {
743 *pp_err_str = NULL;
745 TALLOC_FREE(sam_pass);
746 return NT_STATUS_UNSUCCESSFUL;
748 } else if (local_flags & LOCAL_ENABLE_USER) {
749 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
750 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
751 *pp_err_str = NULL;
753 TALLOC_FREE(sam_pass);
754 return NT_STATUS_UNSUCCESSFUL;
758 if (local_flags & LOCAL_SET_NO_PASSWORD) {
759 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
760 if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) {
761 *pp_err_str = NULL;
763 TALLOC_FREE(sam_pass);
764 return NT_STATUS_UNSUCCESSFUL;
766 } else if (local_flags & LOCAL_SET_PASSWORD) {
768 * If we're dealing with setting a completely empty user account
769 * ie. One with a password of 'XXXX', but not set disabled (like
770 * an account created from scratch) then if the old password was
771 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
772 * We remove that as we're giving this user their first password
773 * and the decision hasn't really been made to disable them (ie.
774 * don't create them disabled). JRA.
776 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
777 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
778 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
779 *pp_err_str = NULL;
781 TALLOC_FREE(sam_pass);
782 return NT_STATUS_UNSUCCESSFUL;
785 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
786 if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) {
787 *pp_err_str = NULL;
789 TALLOC_FREE(sam_pass);
790 return NT_STATUS_UNSUCCESSFUL;
793 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
794 if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) {
795 *pp_err_str = NULL;
797 TALLOC_FREE(sam_pass);
798 return NT_STATUS_UNSUCCESSFUL;
802 if (local_flags & LOCAL_ADD_USER) {
803 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
804 if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) {
805 *pp_msg_str = NULL;
807 TALLOC_FREE(sam_pass);
808 return NT_STATUS_OK;
809 } else {
810 if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) {
811 *pp_err_str = NULL;
813 TALLOC_FREE(sam_pass);
814 return NT_STATUS_UNSUCCESSFUL;
816 } else if (local_flags & LOCAL_DELETE_USER) {
817 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
818 if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) {
819 *pp_err_str = NULL;
821 TALLOC_FREE(sam_pass);
822 return NT_STATUS_UNSUCCESSFUL;
824 if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) {
825 *pp_msg_str = NULL;
827 } else {
828 result = pdb_update_sam_account(sam_pass);
829 if(!NT_STATUS_IS_OK(result)) {
830 if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) {
831 *pp_err_str = NULL;
833 TALLOC_FREE(sam_pass);
834 return result;
836 if(local_flags & LOCAL_DISABLE_USER) {
837 if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) {
838 *pp_msg_str = NULL;
840 } else if (local_flags & LOCAL_ENABLE_USER) {
841 if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) {
842 *pp_msg_str = NULL;
844 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
845 if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) {
846 *pp_msg_str = NULL;
851 TALLOC_FREE(sam_pass);
852 return NT_STATUS_OK;
855 /**********************************************************************
856 Marshall/unmarshall struct samu structs.
857 *********************************************************************/
859 #define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
861 /*********************************************************************
862 *********************************************************************/
864 bool init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
867 /* times are stored as 32bit integer
868 take care on system with 64bit wide time_t
869 --SSS */
870 uint32 logon_time,
871 logoff_time,
872 kickoff_time,
873 bad_password_time,
874 pass_last_set_time,
875 pass_can_change_time,
876 pass_must_change_time;
877 char *username = NULL;
878 char *domain = NULL;
879 char *nt_username = NULL;
880 char *dir_drive = NULL;
881 char *unknown_str = NULL;
882 char *munged_dial = NULL;
883 char *fullname = NULL;
884 char *homedir = NULL;
885 char *logon_script = NULL;
886 char *profile_path = NULL;
887 char *acct_desc = NULL;
888 char *workstations = NULL;
889 uint32 username_len, domain_len, nt_username_len,
890 dir_drive_len, unknown_str_len, munged_dial_len,
891 fullname_len, homedir_len, logon_script_len,
892 profile_path_len, acct_desc_len, workstations_len;
894 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
895 uint16 logon_divs;
896 uint16 bad_password_count, logon_count;
897 uint8 *hours = NULL;
898 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
899 uint32 len = 0;
900 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
901 uint32 pwHistLen = 0;
902 bool ret = True;
903 fstring tmp_string;
904 bool expand_explicit = lp_passdb_expand_explicit();
906 if(sampass == NULL || buf == NULL) {
907 DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
908 return False;
911 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
913 /* unpack the buffer into variables */
914 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V3,
915 &logon_time, /* d */
916 &logoff_time, /* d */
917 &kickoff_time, /* d */
918 &bad_password_time, /* d */
919 &pass_last_set_time, /* d */
920 &pass_can_change_time, /* d */
921 &pass_must_change_time, /* d */
922 &username_len, &username, /* B */
923 &domain_len, &domain, /* B */
924 &nt_username_len, &nt_username, /* B */
925 &fullname_len, &fullname, /* B */
926 &homedir_len, &homedir, /* B */
927 &dir_drive_len, &dir_drive, /* B */
928 &logon_script_len, &logon_script, /* B */
929 &profile_path_len, &profile_path, /* B */
930 &acct_desc_len, &acct_desc, /* B */
931 &workstations_len, &workstations, /* B */
932 &unknown_str_len, &unknown_str, /* B */
933 &munged_dial_len, &munged_dial, /* B */
934 &user_rid, /* d */
935 &group_rid, /* d */
936 &lm_pw_len, &lm_pw_ptr, /* B */
937 &nt_pw_len, &nt_pw_ptr, /* B */
938 /* Change from V1 is addition of password history field. */
939 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
940 /* Change from V2 is the uint32 acb_mask */
941 &acct_ctrl, /* d */
942 /* Also "remove_me" field was removed. */
943 &logon_divs, /* w */
944 &hours_len, /* d */
945 &hourslen, &hours, /* B */
946 &bad_password_count, /* w */
947 &logon_count, /* w */
948 &unknown_6); /* d */
950 if (len == (uint32) -1) {
951 ret = False;
952 goto done;
955 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
956 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
957 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
958 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
959 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
960 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
961 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
963 pdb_set_username(sampass, username, PDB_SET);
964 pdb_set_domain(sampass, domain, PDB_SET);
965 pdb_set_nt_username(sampass, nt_username, PDB_SET);
966 pdb_set_fullname(sampass, fullname, PDB_SET);
968 if (homedir) {
969 fstrcpy( tmp_string, homedir );
970 if (expand_explicit) {
971 standard_sub_basic( username, domain, tmp_string,
972 sizeof(tmp_string) );
974 pdb_set_homedir(sampass, tmp_string, PDB_SET);
976 else {
977 pdb_set_homedir(sampass,
978 talloc_sub_basic(sampass, username, domain,
979 lp_logon_home()),
980 PDB_DEFAULT);
983 if (dir_drive)
984 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
985 else
986 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
988 if (logon_script) {
989 fstrcpy( tmp_string, logon_script );
990 if (expand_explicit) {
991 standard_sub_basic( username, domain, tmp_string,
992 sizeof(tmp_string) );
994 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
996 else {
997 pdb_set_logon_script(sampass,
998 talloc_sub_basic(sampass, username, domain,
999 lp_logon_script()),
1000 PDB_DEFAULT);
1003 if (profile_path) {
1004 fstrcpy( tmp_string, profile_path );
1005 if (expand_explicit) {
1006 standard_sub_basic( username, domain, tmp_string,
1007 sizeof(tmp_string) );
1009 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1011 else {
1012 pdb_set_profile_path(sampass,
1013 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1014 PDB_DEFAULT);
1017 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1018 pdb_set_workstations(sampass, workstations, PDB_SET);
1019 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1021 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1022 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1023 ret = False;
1024 goto done;
1028 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1029 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1030 ret = False;
1031 goto done;
1035 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1036 if (pwHistLen) {
1037 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1038 if (!pw_hist) {
1039 ret = False;
1040 goto done;
1042 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1043 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1044 int i;
1045 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1046 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1047 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1048 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1049 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1050 PW_HISTORY_ENTRY_LEN);
1053 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1054 SAFE_FREE(pw_hist);
1055 ret = False;
1056 goto done;
1058 SAFE_FREE(pw_hist);
1059 } else {
1060 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1063 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1064 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1065 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1066 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1067 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1068 /* Change from V2 is the uint32 acct_ctrl */
1069 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1070 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1071 pdb_set_hours(sampass, hours, PDB_SET);
1073 done:
1075 SAFE_FREE(username);
1076 SAFE_FREE(domain);
1077 SAFE_FREE(nt_username);
1078 SAFE_FREE(fullname);
1079 SAFE_FREE(homedir);
1080 SAFE_FREE(dir_drive);
1081 SAFE_FREE(logon_script);
1082 SAFE_FREE(profile_path);
1083 SAFE_FREE(acct_desc);
1084 SAFE_FREE(workstations);
1085 SAFE_FREE(munged_dial);
1086 SAFE_FREE(unknown_str);
1087 SAFE_FREE(lm_pw_ptr);
1088 SAFE_FREE(nt_pw_ptr);
1089 SAFE_FREE(nt_pw_hist_ptr);
1090 SAFE_FREE(hours);
1092 return ret;
1095 /*********************************************************************
1096 *********************************************************************/
1098 uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1100 size_t len, buflen;
1102 /* times are stored as 32bit integer
1103 take care on system with 64bit wide time_t
1104 --SSS */
1105 uint32 logon_time,
1106 logoff_time,
1107 kickoff_time,
1108 bad_password_time,
1109 pass_last_set_time,
1110 pass_can_change_time,
1111 pass_must_change_time;
1113 uint32 user_rid, group_rid;
1115 const char *username;
1116 const char *domain;
1117 const char *nt_username;
1118 const char *dir_drive;
1119 const char *unknown_str;
1120 const char *munged_dial;
1121 const char *fullname;
1122 const char *homedir;
1123 const char *logon_script;
1124 const char *profile_path;
1125 const char *acct_desc;
1126 const char *workstations;
1127 uint32 username_len, domain_len, nt_username_len,
1128 dir_drive_len, unknown_str_len, munged_dial_len,
1129 fullname_len, homedir_len, logon_script_len,
1130 profile_path_len, acct_desc_len, workstations_len;
1132 const uint8 *lm_pw;
1133 const uint8 *nt_pw;
1134 const uint8 *nt_pw_hist;
1135 uint32 lm_pw_len = 16;
1136 uint32 nt_pw_len = 16;
1137 uint32 nt_pw_hist_len;
1138 uint32 pwHistLen = 0;
1140 *buf = NULL;
1141 buflen = 0;
1143 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1144 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1145 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1146 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1147 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1148 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1149 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1151 user_rid = pdb_get_user_rid(sampass);
1152 group_rid = pdb_get_group_rid(sampass);
1154 username = pdb_get_username(sampass);
1155 if (username) {
1156 username_len = strlen(username) +1;
1157 } else {
1158 username_len = 0;
1161 domain = pdb_get_domain(sampass);
1162 if (domain) {
1163 domain_len = strlen(domain) +1;
1164 } else {
1165 domain_len = 0;
1168 nt_username = pdb_get_nt_username(sampass);
1169 if (nt_username) {
1170 nt_username_len = strlen(nt_username) +1;
1171 } else {
1172 nt_username_len = 0;
1175 fullname = pdb_get_fullname(sampass);
1176 if (fullname) {
1177 fullname_len = strlen(fullname) +1;
1178 } else {
1179 fullname_len = 0;
1183 * Only updates fields which have been set (not defaults from smb.conf)
1186 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1187 dir_drive = pdb_get_dir_drive(sampass);
1188 } else {
1189 dir_drive = NULL;
1191 if (dir_drive) {
1192 dir_drive_len = strlen(dir_drive) +1;
1193 } else {
1194 dir_drive_len = 0;
1197 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1198 homedir = pdb_get_homedir(sampass);
1199 } else {
1200 homedir = NULL;
1202 if (homedir) {
1203 homedir_len = strlen(homedir) +1;
1204 } else {
1205 homedir_len = 0;
1208 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1209 logon_script = pdb_get_logon_script(sampass);
1210 } else {
1211 logon_script = NULL;
1213 if (logon_script) {
1214 logon_script_len = strlen(logon_script) +1;
1215 } else {
1216 logon_script_len = 0;
1219 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1220 profile_path = pdb_get_profile_path(sampass);
1221 } else {
1222 profile_path = NULL;
1224 if (profile_path) {
1225 profile_path_len = strlen(profile_path) +1;
1226 } else {
1227 profile_path_len = 0;
1230 lm_pw = pdb_get_lanman_passwd(sampass);
1231 if (!lm_pw) {
1232 lm_pw_len = 0;
1235 nt_pw = pdb_get_nt_passwd(sampass);
1236 if (!nt_pw) {
1237 nt_pw_len = 0;
1240 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1241 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1242 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1243 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1244 } else {
1245 nt_pw_hist_len = 0;
1248 acct_desc = pdb_get_acct_desc(sampass);
1249 if (acct_desc) {
1250 acct_desc_len = strlen(acct_desc) +1;
1251 } else {
1252 acct_desc_len = 0;
1255 workstations = pdb_get_workstations(sampass);
1256 if (workstations) {
1257 workstations_len = strlen(workstations) +1;
1258 } else {
1259 workstations_len = 0;
1262 unknown_str = NULL;
1263 unknown_str_len = 0;
1265 munged_dial = pdb_get_munged_dial(sampass);
1266 if (munged_dial) {
1267 munged_dial_len = strlen(munged_dial) +1;
1268 } else {
1269 munged_dial_len = 0;
1272 /* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1274 /* one time to get the size needed */
1275 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
1276 logon_time, /* d */
1277 logoff_time, /* d */
1278 kickoff_time, /* d */
1279 bad_password_time, /* d */
1280 pass_last_set_time, /* d */
1281 pass_can_change_time, /* d */
1282 pass_must_change_time, /* d */
1283 username_len, username, /* B */
1284 domain_len, domain, /* B */
1285 nt_username_len, nt_username, /* B */
1286 fullname_len, fullname, /* B */
1287 homedir_len, homedir, /* B */
1288 dir_drive_len, dir_drive, /* B */
1289 logon_script_len, logon_script, /* B */
1290 profile_path_len, profile_path, /* B */
1291 acct_desc_len, acct_desc, /* B */
1292 workstations_len, workstations, /* B */
1293 unknown_str_len, unknown_str, /* B */
1294 munged_dial_len, munged_dial, /* B */
1295 user_rid, /* d */
1296 group_rid, /* d */
1297 lm_pw_len, lm_pw, /* B */
1298 nt_pw_len, nt_pw, /* B */
1299 nt_pw_hist_len, nt_pw_hist, /* B */
1300 pdb_get_acct_ctrl(sampass), /* d */
1301 pdb_get_logon_divs(sampass), /* w */
1302 pdb_get_hours_len(sampass), /* d */
1303 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1304 pdb_get_bad_password_count(sampass), /* w */
1305 pdb_get_logon_count(sampass), /* w */
1306 pdb_get_unknown_6(sampass)); /* d */
1308 if (size_only) {
1309 return buflen;
1312 /* malloc the space needed */
1313 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1314 DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
1315 return (-1);
1318 /* now for the real call to tdb_pack() */
1319 buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING_V3,
1320 logon_time, /* d */
1321 logoff_time, /* d */
1322 kickoff_time, /* d */
1323 bad_password_time, /* d */
1324 pass_last_set_time, /* d */
1325 pass_can_change_time, /* d */
1326 pass_must_change_time, /* d */
1327 username_len, username, /* B */
1328 domain_len, domain, /* B */
1329 nt_username_len, nt_username, /* B */
1330 fullname_len, fullname, /* B */
1331 homedir_len, homedir, /* B */
1332 dir_drive_len, dir_drive, /* B */
1333 logon_script_len, logon_script, /* B */
1334 profile_path_len, profile_path, /* B */
1335 acct_desc_len, acct_desc, /* B */
1336 workstations_len, workstations, /* B */
1337 unknown_str_len, unknown_str, /* B */
1338 munged_dial_len, munged_dial, /* B */
1339 user_rid, /* d */
1340 group_rid, /* d */
1341 lm_pw_len, lm_pw, /* B */
1342 nt_pw_len, nt_pw, /* B */
1343 nt_pw_hist_len, nt_pw_hist, /* B */
1344 pdb_get_acct_ctrl(sampass), /* d */
1345 pdb_get_logon_divs(sampass), /* w */
1346 pdb_get_hours_len(sampass), /* d */
1347 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1348 pdb_get_bad_password_count(sampass), /* w */
1349 pdb_get_logon_count(sampass), /* w */
1350 pdb_get_unknown_6(sampass)); /* d */
1352 /* check to make sure we got it correct */
1353 if (buflen != len) {
1354 DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1355 (unsigned long)buflen, (unsigned long)len));
1356 /* error */
1357 SAFE_FREE (*buf);
1358 return (-1);
1361 return (buflen);
1365 /*********************************************************************
1366 *********************************************************************/
1368 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
1370 uint8 *buf = NULL;
1371 int len;
1373 len = init_buffer_from_sam_v3(&buf, src, False);
1374 if (len == -1 || !buf) {
1375 SAFE_FREE(buf);
1376 return False;
1379 if (!init_sam_from_buffer_v3( dst, buf, len )) {
1380 free(buf);
1381 return False;
1384 dst->methods = src->methods;
1386 if ( src->unix_pw ) {
1387 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
1388 if (!dst->unix_pw) {
1389 free(buf);
1390 return False;
1394 free(buf);
1395 return True;
1398 /*********************************************************************
1399 Update the bad password count checking the AP_RESET_COUNT_TIME
1400 *********************************************************************/
1402 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
1404 time_t LastBadPassword;
1405 uint16 BadPasswordCount;
1406 uint32 resettime;
1407 bool res;
1409 BadPasswordCount = pdb_get_bad_password_count(sampass);
1410 if (!BadPasswordCount) {
1411 DEBUG(9, ("No bad password attempts.\n"));
1412 return True;
1415 become_root();
1416 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
1417 unbecome_root();
1419 if (!res) {
1420 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
1421 return False;
1424 /* First, check if there is a reset time to compare */
1425 if ((resettime == (uint32) -1) || (resettime == 0)) {
1426 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
1427 return True;
1430 LastBadPassword = pdb_get_bad_password_time(sampass);
1431 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
1432 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
1433 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
1434 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1435 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1436 if (updated) {
1437 *updated = True;
1441 return True;
1444 /*********************************************************************
1445 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
1446 *********************************************************************/
1448 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
1450 uint32 duration;
1451 time_t LastBadPassword;
1452 bool res;
1454 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
1455 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
1456 pdb_get_username(sampass)));
1457 return True;
1460 become_root();
1461 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
1462 unbecome_root();
1464 if (!res) {
1465 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
1466 return False;
1469 /* First, check if there is a duration to compare */
1470 if ((duration == (uint32) -1) || (duration == 0)) {
1471 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
1472 return True;
1475 LastBadPassword = pdb_get_bad_password_time(sampass);
1476 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
1477 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
1479 if (LastBadPassword == (time_t)0) {
1480 DEBUG(1,("pdb_update_autolock_flag: Account %s "
1481 "administratively locked out with no bad password "
1482 "time. Leaving locked out.\n",
1483 pdb_get_username(sampass) ));
1484 return True;
1487 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
1488 pdb_set_acct_ctrl(sampass,
1489 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
1490 PDB_CHANGED);
1491 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
1492 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
1493 if (updated) {
1494 *updated = True;
1498 return True;
1501 /*********************************************************************
1502 Increment the bad_password_count
1503 *********************************************************************/
1505 bool pdb_increment_bad_password_count(struct samu *sampass)
1507 uint32 account_policy_lockout;
1508 bool autolock_updated = False, badpw_updated = False;
1509 bool ret;
1511 /* Retrieve the account lockout policy */
1512 become_root();
1513 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
1514 unbecome_root();
1515 if ( !ret ) {
1516 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
1517 return False;
1520 /* If there is no policy, we don't need to continue checking */
1521 if (!account_policy_lockout) {
1522 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
1523 return True;
1526 /* Check if the autolock needs to be cleared */
1527 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
1528 return False;
1530 /* Check if the badpw count needs to be reset */
1531 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
1532 return False;
1535 Ok, now we can assume that any resetting that needs to be
1536 done has been done, and just get on with incrementing
1537 and autolocking if necessary
1540 pdb_set_bad_password_count(sampass,
1541 pdb_get_bad_password_count(sampass)+1,
1542 PDB_CHANGED);
1543 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
1546 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
1547 return True;
1549 if (!pdb_set_acct_ctrl(sampass,
1550 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
1551 PDB_CHANGED)) {
1552 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
1553 return False;
1556 return True;
1559 bool is_dc_trusted_domain_situation(const char *domain_name)
1561 return IS_DC && !strequal(domain_name, lp_workgroup());
1564 /*******************************************************************
1565 Wrapper around retrieving the clear text trust account password.
1566 appropriate account name is stored in account_name.
1567 Caller must free password, but not account_name.
1568 *******************************************************************/
1570 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
1571 const char **account_name, uint32 *channel)
1573 char *pwd;
1574 time_t last_set_time;
1576 /* if we are a DC and this is not our domain, then lookup an account
1577 * for the domain trust */
1579 if (is_dc_trusted_domain_situation(domain)) {
1580 if (!lp_allow_trusted_domains()) {
1581 return false;
1584 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
1585 &last_set_time))
1587 DEBUG(0, ("get_trust_pw: could not fetch trust "
1588 "account password for trusted domain %s\n",
1589 domain));
1590 return false;
1593 if (channel != NULL) {
1594 *channel = SEC_CHAN_DOMAIN;
1597 if (account_name != NULL) {
1598 *account_name = lp_workgroup();
1601 return true;
1605 * Since we can only be member of one single domain, we are now
1606 * in a member situation:
1608 * - Either we are a DC (selfjoined) and the domain is our
1609 * own domain.
1610 * - Or we are on a member and the domain is our own or some
1611 * other (potentially trusted) domain.
1613 * In both cases, we can only get the machine account password
1614 * for our own domain to connect to our own dc. (For a member,
1615 * request to trusted domains are performed through our dc.)
1617 * So we simply use our own domain name to retrieve the
1618 * machine account passowrd and ignore the request domain here.
1621 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
1623 if (pwd != NULL) {
1624 *ret_pwd = pwd;
1625 if (account_name != NULL) {
1626 *account_name = global_myname();
1629 return true;
1632 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
1633 "account password for domain %s\n", domain));
1634 return false;
1637 /*******************************************************************
1638 Wrapper around retrieving the trust account password.
1639 appropriate account name is stored in account_name.
1640 *******************************************************************/
1642 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
1643 const char **account_name, uint32 *channel)
1645 char *pwd = NULL;
1646 time_t last_set_time;
1648 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
1649 E_md4hash(pwd, ret_pwd);
1650 SAFE_FREE(pwd);
1651 return true;
1652 } else if (is_dc_trusted_domain_situation(domain)) {
1653 return false;
1656 /* as a fallback, try to get the hashed pwd directly from the tdb... */
1658 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
1659 &last_set_time,
1660 channel))
1662 if (account_name != NULL) {
1663 *account_name = global_myname();
1666 return true;
1669 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
1670 "password for domain %s\n", domain));
1671 return False;
1674 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
1675 struct samu *pw)
1677 struct samr_LogonHours hours;
1678 const int units_per_week = 168;
1680 ZERO_STRUCT(hours);
1681 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
1682 if (!hours.bits) {
1683 return hours;
1686 hours.units_per_week = units_per_week;
1687 memset(hours.bits, 0xFF, units_per_week);
1689 if (pdb_get_hours(pw)) {
1690 memcpy(hours.bits, pdb_get_hours(pw),
1691 MIN(pdb_get_hours_len(pw), units_per_week));
1694 return hours;