Consolidate user create/delete paths in smbpasswd
[Samba.git] / source3 / passdb / passdb.c
blob3ab0a1d995adcfe958a73a199c422ddf5c37cb77
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.
34 LEGACY: this function provides the legacy domain mapping used with
35 the lp_map_untrusted_to_domain() parameter
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 /* Default to the DOMAIN name when not specified */
45 return lp_workgroup();
48 /**********************************************************************
49 ***********************************************************************/
51 static int samu_destroy(struct samu *user)
53 data_blob_clear_free( &user->lm_pw );
54 data_blob_clear_free( &user->nt_pw );
56 if ( user->plaintext_pw )
57 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
59 return 0;
62 /**********************************************************************
63 generate a new struct samuser
64 ***********************************************************************/
66 struct samu *samu_new( TALLOC_CTX *ctx )
68 struct samu *user;
70 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
71 DEBUG(0,("samuser_new: Talloc failed!\n"));
72 return NULL;
75 talloc_set_destructor( user, samu_destroy );
77 /* no initial methods */
79 user->methods = NULL;
81 /* Don't change these timestamp settings without a good reason.
82 They are important for NT member server compatibility. */
84 user->logon_time = (time_t)0;
85 user->pass_last_set_time = (time_t)0;
86 user->pass_can_change_time = (time_t)0;
87 user->logoff_time = get_time_t_max();
88 user->kickoff_time = get_time_t_max();
89 user->pass_must_change_time = get_time_t_max();
90 user->fields_present = 0x00ffffff;
91 user->logon_divs = 168; /* hours per week */
92 user->hours_len = 21; /* 21 times 8 bits = 168 */
93 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
94 user->bad_password_count = 0;
95 user->logon_count = 0;
96 user->unknown_6 = 0x000004ec; /* don't know */
98 /* Some parts of samba strlen their pdb_get...() returns,
99 so this keeps the interface unchanged for now. */
101 user->username = "";
102 user->domain = "";
103 user->nt_username = "";
104 user->full_name = "";
105 user->home_dir = "";
106 user->logon_script = "";
107 user->profile_path = "";
108 user->acct_desc = "";
109 user->workstations = "";
110 user->comment = "";
111 user->munged_dial = "";
113 user->plaintext_pw = NULL;
115 /* Unless we know otherwise have a Account Control Bit
116 value of 'normal user'. This helps User Manager, which
117 asks for a filtered list of users. */
119 user->acct_ctrl = ACB_NORMAL;
121 return user;
124 /*********************************************************************
125 Initialize a struct samu from a struct passwd including the user
126 and group SIDs. The *user structure is filled out with the Unix
127 attributes and a user SID.
128 *********************************************************************/
130 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
132 const char *guest_account = lp_guestaccount();
133 const char *domain = global_myname();
134 uint32 urid;
136 if ( !pwd ) {
137 return NT_STATUS_NO_SUCH_USER;
140 /* Basic properties based upon the Unix account information */
142 pdb_set_username(user, pwd->pw_name, PDB_SET);
143 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
144 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
145 #if 0
146 /* This can lead to a primary group of S-1-22-2-XX which
147 will be rejected by other parts of the Samba code.
148 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
149 --jerry */
151 gid_to_sid(&group_sid, pwd->pw_gid);
152 pdb_set_group_sid(user, &group_sid, PDB_SET);
153 #endif
155 /* save the password structure for later use */
157 user->unix_pw = tcopy_passwd( user, pwd );
159 /* Special case for the guest account which must have a RID of 501 */
161 if ( strequal( pwd->pw_name, guest_account ) ) {
162 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
163 return NT_STATUS_NO_SUCH_USER;
165 return NT_STATUS_OK;
168 /* Non-guest accounts...Check for a workstation or user account */
170 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
171 /* workstation */
173 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
174 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
175 pwd->pw_name));
176 return NT_STATUS_INVALID_COMPUTER_NAME;
179 else {
180 /* user */
182 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
183 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
184 pwd->pw_name));
185 return NT_STATUS_INVALID_ACCOUNT_NAME;
188 /* set some basic attributes */
190 pdb_set_profile_path(user, talloc_sub_specified(user,
191 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
192 PDB_DEFAULT);
193 pdb_set_homedir(user, talloc_sub_specified(user,
194 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
195 PDB_DEFAULT);
196 pdb_set_dir_drive(user, talloc_sub_specified(user,
197 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
198 PDB_DEFAULT);
199 pdb_set_logon_script(user, talloc_sub_specified(user,
200 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
201 PDB_DEFAULT);
204 /* Now deal with the user SID. If we have a backend that can generate
205 RIDs, then do so. But sometimes the caller just wanted a structure
206 initialized and will fill in these fields later (such as from a
207 netr_SamInfo3 structure) */
209 if ( create && !pdb_rid_algorithm() ) {
210 uint32 user_rid;
211 DOM_SID user_sid;
213 if ( !pdb_new_rid( &user_rid ) ) {
214 DEBUG(3, ("Could not allocate a new RID\n"));
215 return NT_STATUS_ACCESS_DENIED;
218 sid_copy( &user_sid, get_global_sam_sid() );
219 sid_append_rid( &user_sid, user_rid );
221 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
222 DEBUG(3, ("pdb_set_user_sid failed\n"));
223 return NT_STATUS_INTERNAL_ERROR;
226 return NT_STATUS_OK;
229 /* generate a SID for the user with the RID algorithm */
231 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
233 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
234 return NT_STATUS_INTERNAL_ERROR;
237 return NT_STATUS_OK;
240 /********************************************************************
241 Set the Unix user attributes
242 ********************************************************************/
244 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
246 return samu_set_unix_internal( user, pwd, False );
249 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
251 return samu_set_unix_internal( user, pwd, True );
254 /**********************************************************
255 Encode the account control bits into a string.
256 length = length of string to encode into (including terminating
257 null). length *MUST BE MORE THAN 2* !
258 **********************************************************/
260 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
262 fstring acct_str;
263 char *result;
265 size_t i = 0;
267 SMB_ASSERT(length <= sizeof(acct_str));
269 acct_str[i++] = '[';
271 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
272 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
273 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
274 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
275 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
276 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
277 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
278 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
279 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
280 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
281 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
283 for ( ; i < length - 2 ; i++ )
284 acct_str[i] = ' ';
286 i = length - 2;
287 acct_str[i++] = ']';
288 acct_str[i++] = '\0';
290 result = talloc_strdup(talloc_tos(), acct_str);
291 SMB_ASSERT(result != NULL);
292 return result;
295 /**********************************************************
296 Decode the account control bits from a string.
297 **********************************************************/
299 uint32_t pdb_decode_acct_ctrl(const char *p)
301 uint32_t acct_ctrl = 0;
302 bool finished = false;
305 * Check if the account type bits have been encoded after the
306 * NT password (in the form [NDHTUWSLXI]).
309 if (*p != '[')
310 return 0;
312 for (p++; *p && !finished; p++) {
313 switch (*p) {
314 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
315 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
316 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
317 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
318 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
319 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
320 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
321 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
322 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
323 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
324 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
325 case ' ': { break; }
326 case ':':
327 case '\n':
328 case '\0':
329 case ']':
330 default: { finished = true; }
334 return acct_ctrl;
337 /*************************************************************
338 Routine to set 32 hex password characters from a 16 byte array.
339 **************************************************************/
341 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
343 if (pwd != NULL) {
344 int i;
345 for (i = 0; i < 16; i++)
346 slprintf(&p[i*2], 3, "%02X", pwd[i]);
347 } else {
348 if (acct_ctrl & ACB_PWNOTREQ)
349 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
350 else
351 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
355 /*************************************************************
356 Routine to get the 32 hex characters and turn them
357 into a 16 byte array.
358 **************************************************************/
360 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
362 int i;
363 unsigned char lonybble, hinybble;
364 const char *hexchars = "0123456789ABCDEF";
365 char *p1, *p2;
367 if (!p)
368 return false;
370 for (i = 0; i < 32; i += 2) {
371 hinybble = toupper_ascii(p[i]);
372 lonybble = toupper_ascii(p[i + 1]);
374 p1 = strchr(hexchars, hinybble);
375 p2 = strchr(hexchars, lonybble);
377 if (!p1 || !p2)
378 return false;
380 hinybble = PTR_DIFF(p1, hexchars);
381 lonybble = PTR_DIFF(p2, hexchars);
383 pwd[i / 2] = (hinybble << 4) | lonybble;
385 return true;
388 /*************************************************************
389 Routine to set 42 hex hours characters from a 21 byte array.
390 **************************************************************/
392 void pdb_sethexhours(char *p, const unsigned char *hours)
394 if (hours != NULL) {
395 int i;
396 for (i = 0; i < 21; i++) {
397 slprintf(&p[i*2], 3, "%02X", hours[i]);
399 } else {
400 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
404 /*************************************************************
405 Routine to get the 42 hex characters and turn them
406 into a 21 byte array.
407 **************************************************************/
409 bool pdb_gethexhours(const char *p, unsigned char *hours)
411 int i;
412 unsigned char lonybble, hinybble;
413 const char *hexchars = "0123456789ABCDEF";
414 char *p1, *p2;
416 if (!p) {
417 return (False);
420 for (i = 0; i < 42; i += 2) {
421 hinybble = toupper_ascii(p[i]);
422 lonybble = toupper_ascii(p[i + 1]);
424 p1 = strchr(hexchars, hinybble);
425 p2 = strchr(hexchars, lonybble);
427 if (!p1 || !p2) {
428 return (False);
431 hinybble = PTR_DIFF(p1, hexchars);
432 lonybble = PTR_DIFF(p2, hexchars);
434 hours[i / 2] = (hinybble << 4) | lonybble;
436 return (True);
439 /********************************************************************
440 ********************************************************************/
442 int algorithmic_rid_base(void)
444 int rid_offset;
446 rid_offset = lp_algorithmic_rid_base();
448 if (rid_offset < BASE_RID) {
449 /* Try to prevent admin foot-shooting, we can't put algorithmic
450 rids below 1000, that's the 'well known RIDs' on NT */
451 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
452 rid_offset = BASE_RID;
454 if (rid_offset & 1) {
455 DEBUG(0, ("algorithmic rid base must be even\n"));
456 rid_offset += 1;
458 return rid_offset;
461 /*******************************************************************
462 Converts NT user RID to a UNIX uid.
463 ********************************************************************/
465 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
467 int rid_offset = algorithmic_rid_base();
468 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
471 uid_t max_algorithmic_uid(void)
473 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
476 /*******************************************************************
477 converts UNIX uid to an NT User RID.
478 ********************************************************************/
480 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
482 int rid_offset = algorithmic_rid_base();
483 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
486 /*******************************************************************
487 Converts NT group RID to a UNIX gid.
488 ********************************************************************/
490 gid_t pdb_group_rid_to_gid(uint32 group_rid)
492 int rid_offset = algorithmic_rid_base();
493 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
496 gid_t max_algorithmic_gid(void)
498 return pdb_group_rid_to_gid(0xffffffff);
501 /*******************************************************************
502 converts NT Group RID to a UNIX uid.
504 warning: you must not call that function only
505 you must do a call to the group mapping first.
506 there is not anymore a direct link between the gid and the rid.
507 ********************************************************************/
509 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
511 int rid_offset = algorithmic_rid_base();
512 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
515 /*******************************************************************
516 Decides if a RID is a well known RID.
517 ********************************************************************/
519 static bool rid_is_well_known(uint32 rid)
521 /* Not using rid_offset here, because this is the actual
522 NT fixed value (1000) */
524 return (rid < BASE_RID);
527 /*******************************************************************
528 Decides if a RID is a user or group RID.
529 ********************************************************************/
531 bool algorithmic_pdb_rid_is_user(uint32 rid)
533 if ( rid_is_well_known(rid) ) {
535 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
536 * and DOMAIN_USER_RID_GUEST.
538 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
539 return True;
540 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
541 return True;
543 return False;
546 /*******************************************************************
547 Convert a name into a SID. Used in the lookup name rpc.
548 ********************************************************************/
550 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
551 enum lsa_SidType *type)
553 GROUP_MAP map;
554 bool ret;
556 /* Windows treats "MACHINE\None" as a special name for
557 rid 513 on non-DCs. You cannot create a user or group
558 name "None" on Windows. You will get an error that
559 the group already exists. */
561 if ( strequal( name, "None" ) ) {
562 *rid = DOMAIN_GROUP_RID_USERS;
563 *type = SID_NAME_DOM_GRP;
565 return True;
568 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
569 * correctly in the case where foo also exists as a user. If the flag
570 * is set, don't look for users at all. */
572 if ((flags & LOOKUP_NAME_GROUP) == 0) {
573 struct samu *sam_account = NULL;
574 DOM_SID user_sid;
576 if ( !(sam_account = samu_new( NULL )) ) {
577 return False;
580 become_root();
581 ret = pdb_getsampwnam(sam_account, name);
582 unbecome_root();
584 if (ret) {
585 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
588 TALLOC_FREE(sam_account);
590 if (ret) {
591 if (!sid_check_is_in_our_domain(&user_sid)) {
592 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
593 name, sid_string_dbg(&user_sid)));
594 return False;
597 sid_peek_rid(&user_sid, rid);
598 *type = SID_NAME_USER;
599 return True;
604 * Maybe it is a group ?
607 become_root();
608 ret = pdb_getgrnam(&map, name);
609 unbecome_root();
611 if (!ret) {
612 return False;
615 /* BUILTIN groups are looked up elsewhere */
616 if (!sid_check_is_in_our_domain(&map.sid)) {
617 DEBUG(10, ("Found group %s (%s) not in our domain -- "
618 "ignoring.", name, sid_string_dbg(&map.sid)));
619 return False;
622 /* yes it's a mapped group */
623 sid_peek_rid(&map.sid, rid);
624 *type = map.sid_name_use;
625 return True;
628 /*************************************************************
629 Change a password entry in the local passdb backend.
631 Assumptions:
632 - always called as root
633 - ignores the account type except when adding a new account
634 - will create/delete the unix account if the relative
635 add/delete user script is configured
637 *************************************************************/
639 NTSTATUS local_password_change(const char *user_name,
640 int local_flags,
641 const char *new_passwd,
642 char **pp_err_str,
643 char **pp_msg_str)
645 TALLOC_CTX *tosctx;
646 struct samu *sam_pass;
647 uint32_t acb;
648 uint32_t rid;
649 NTSTATUS result;
650 bool user_exists;
651 int ret;
653 *pp_err_str = NULL;
654 *pp_msg_str = NULL;
656 tosctx = talloc_tos();
657 if (!tosctx) {
658 return NT_STATUS_NO_MEMORY;
661 sam_pass = samu_new(tosctx);
662 if (!sam_pass) {
663 result = NT_STATUS_NO_MEMORY;
664 goto done;
667 /* Get the smb passwd entry for this user */
668 user_exists = pdb_getsampwnam(sam_pass, user_name);
670 /* Check delete first, we don't need to do anything else if we
671 * are going to delete the acocunt */
672 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
674 result = pdb_delete_user(tosctx, sam_pass);
675 if (!NT_STATUS_IS_OK(result)) {
676 ret = asprintf(pp_err_str,
677 "Failed to delete entry for user %s.\n",
678 user_name);
679 if (ret < 0) {
680 *pp_err_str = NULL;
682 result = NT_STATUS_UNSUCCESSFUL;
683 } else {
684 ret = asprintf(pp_msg_str,
685 "Deleted user %s.\n",
686 user_name);
687 if (ret < 0) {
688 *pp_msg_str = NULL;
691 goto done;
694 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
695 /* the entry already existed */
696 local_flags &= ~LOCAL_ADD_USER;
699 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
700 ret = asprintf(pp_err_str,
701 "Failed to find entry for user %s.\n",
702 user_name);
703 if (ret < 0) {
704 *pp_err_str = NULL;
706 result = NT_STATUS_NO_SUCH_USER;
707 goto done;
710 /* First thing add the new user if we are required to do so */
711 if (local_flags & LOCAL_ADD_USER) {
713 if (local_flags & LOCAL_TRUST_ACCOUNT) {
714 acb = ACB_WSTRUST;
715 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
716 acb = ACB_DOMTRUST;
717 } else {
718 acb = ACB_NORMAL;
721 result = pdb_create_user(tosctx, user_name, acb, &rid);
722 if (!NT_STATUS_IS_OK(result)) {
723 ret = asprintf(pp_err_str,
724 "Failed to add entry for user %s.\n",
725 user_name);
726 if (ret < 0) {
727 *pp_err_str = NULL;
729 result = NT_STATUS_UNSUCCESSFUL;
730 goto done;
733 sam_pass = samu_new(tosctx);
734 if (!sam_pass) {
735 result = NT_STATUS_NO_MEMORY;
736 goto done;
739 /* Now get back the smb passwd entry for this new user */
740 user_exists = pdb_getsampwnam(sam_pass, user_name);
741 if (!user_exists) {
742 ret = asprintf(pp_err_str,
743 "Failed to add entry for user %s.\n",
744 user_name);
745 if (ret < 0) {
746 *pp_err_str = NULL;
748 result = NT_STATUS_UNSUCCESSFUL;
749 goto done;
753 acb = pdb_get_acct_ctrl(sam_pass);
756 * We are root - just write the new password
757 * and the valid last change time.
759 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
760 acb |= ACB_PWNOTREQ;
761 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
762 ret = asprintf(pp_err_str,
763 "Failed to set 'no password required' "
764 "flag for user %s.\n", user_name);
765 if (ret < 0) {
766 *pp_err_str = NULL;
768 result = NT_STATUS_UNSUCCESSFUL;
769 goto done;
773 if (local_flags & LOCAL_SET_PASSWORD) {
775 * If we're dealing with setting a completely empty user account
776 * ie. One with a password of 'XXXX', but not set disabled (like
777 * an account created from scratch) then if the old password was
778 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
779 * We remove that as we're giving this user their first password
780 * and the decision hasn't really been made to disable them (ie.
781 * don't create them disabled). JRA.
783 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
784 (acb & ACB_DISABLED)) {
785 acb &= (~ACB_DISABLED);
786 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
787 ret = asprintf(pp_err_str,
788 "Failed to unset 'disabled' "
789 "flag for user %s.\n",
790 user_name);
791 if (ret < 0) {
792 *pp_err_str = NULL;
794 result = NT_STATUS_UNSUCCESSFUL;
795 goto done;
799 acb &= (~ACB_PWNOTREQ);
800 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
801 ret = asprintf(pp_err_str,
802 "Failed to unset 'no password required'"
803 " flag for user %s.\n", user_name);
804 if (ret < 0) {
805 *pp_err_str = NULL;
807 result = NT_STATUS_UNSUCCESSFUL;
808 goto done;
811 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
812 ret = asprintf(pp_err_str,
813 "Failed to set password for "
814 "user %s.\n", user_name);
815 if (ret < 0) {
816 *pp_err_str = NULL;
818 result = NT_STATUS_UNSUCCESSFUL;
819 goto done;
823 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
824 acb |= ACB_DISABLED;
825 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
826 ret = asprintf(pp_err_str,
827 "Failed to set 'disabled' flag for "
828 "user %s.\n", user_name);
829 if (ret < 0) {
830 *pp_err_str = NULL;
832 result = NT_STATUS_UNSUCCESSFUL;
833 goto done;
837 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
838 acb &= (~ACB_DISABLED);
839 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
840 ret = asprintf(pp_err_str,
841 "Failed to unset 'disabled' flag for "
842 "user %s.\n", user_name);
843 if (ret < 0) {
844 *pp_err_str = NULL;
846 result = NT_STATUS_UNSUCCESSFUL;
847 goto done;
851 /* now commit changes if any */
852 result = pdb_update_sam_account(sam_pass);
853 if (!NT_STATUS_IS_OK(result)) {
854 ret = asprintf(pp_err_str,
855 "Failed to modify entry for user %s.\n",
856 user_name);
857 if (ret < 0) {
858 *pp_err_str = NULL;
860 goto done;
863 if (local_flags & LOCAL_ADD_USER) {
864 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
865 } else if (local_flags & LOCAL_DISABLE_USER) {
866 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
867 } else if (local_flags & LOCAL_ENABLE_USER) {
868 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
869 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
870 ret = asprintf(pp_msg_str,
871 "User %s password set to none.\n", user_name);
874 if (ret < 0) {
875 *pp_msg_str = NULL;
878 result = NT_STATUS_OK;
880 done:
881 TALLOC_FREE(sam_pass);
882 return result;
885 /**********************************************************************
886 Marshall/unmarshall struct samu structs.
887 *********************************************************************/
889 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
890 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
891 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
892 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
893 /* nothing changed between V3 and V4 */
895 /*********************************************************************
896 *********************************************************************/
898 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
901 /* times are stored as 32bit integer
902 take care on system with 64bit wide time_t
903 --SSS */
904 uint32 logon_time,
905 logoff_time,
906 kickoff_time,
907 pass_last_set_time,
908 pass_can_change_time,
909 pass_must_change_time;
910 char *username = NULL;
911 char *domain = NULL;
912 char *nt_username = NULL;
913 char *dir_drive = NULL;
914 char *unknown_str = NULL;
915 char *munged_dial = NULL;
916 char *fullname = NULL;
917 char *homedir = NULL;
918 char *logon_script = NULL;
919 char *profile_path = NULL;
920 char *acct_desc = NULL;
921 char *workstations = NULL;
922 uint32 username_len, domain_len, nt_username_len,
923 dir_drive_len, unknown_str_len, munged_dial_len,
924 fullname_len, homedir_len, logon_script_len,
925 profile_path_len, acct_desc_len, workstations_len;
927 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
928 uint16 acct_ctrl, logon_divs;
929 uint16 bad_password_count, logon_count;
930 uint8 *hours = NULL;
931 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
932 uint32 len = 0;
933 uint32 lm_pw_len, nt_pw_len, hourslen;
934 bool ret = True;
936 if(sampass == NULL || buf == NULL) {
937 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
938 return False;
941 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
943 /* unpack the buffer into variables */
944 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
945 &logon_time, /* d */
946 &logoff_time, /* d */
947 &kickoff_time, /* d */
948 &pass_last_set_time, /* d */
949 &pass_can_change_time, /* d */
950 &pass_must_change_time, /* d */
951 &username_len, &username, /* B */
952 &domain_len, &domain, /* B */
953 &nt_username_len, &nt_username, /* B */
954 &fullname_len, &fullname, /* B */
955 &homedir_len, &homedir, /* B */
956 &dir_drive_len, &dir_drive, /* B */
957 &logon_script_len, &logon_script, /* B */
958 &profile_path_len, &profile_path, /* B */
959 &acct_desc_len, &acct_desc, /* B */
960 &workstations_len, &workstations, /* B */
961 &unknown_str_len, &unknown_str, /* B */
962 &munged_dial_len, &munged_dial, /* B */
963 &user_rid, /* d */
964 &group_rid, /* d */
965 &lm_pw_len, &lm_pw_ptr, /* B */
966 &nt_pw_len, &nt_pw_ptr, /* B */
967 &acct_ctrl, /* w */
968 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
969 &logon_divs, /* w */
970 &hours_len, /* d */
971 &hourslen, &hours, /* B */
972 &bad_password_count, /* w */
973 &logon_count, /* w */
974 &unknown_6); /* d */
976 if (len == (uint32) -1) {
977 ret = False;
978 goto done;
981 pdb_set_logon_time(sampass, logon_time, PDB_SET);
982 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
983 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
984 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
985 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
986 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
988 pdb_set_username(sampass, username, PDB_SET);
989 pdb_set_domain(sampass, domain, PDB_SET);
990 pdb_set_nt_username(sampass, nt_username, PDB_SET);
991 pdb_set_fullname(sampass, fullname, PDB_SET);
993 if (homedir) {
994 pdb_set_homedir(sampass, homedir, PDB_SET);
996 else {
997 pdb_set_homedir(sampass,
998 talloc_sub_basic(sampass, username, domain,
999 lp_logon_home()),
1000 PDB_DEFAULT);
1003 if (dir_drive)
1004 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1005 else {
1006 pdb_set_dir_drive(sampass,
1007 talloc_sub_basic(sampass, username, domain,
1008 lp_logon_drive()),
1009 PDB_DEFAULT);
1012 if (logon_script)
1013 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1014 else {
1015 pdb_set_logon_script(sampass,
1016 talloc_sub_basic(sampass, username, domain,
1017 lp_logon_script()),
1018 PDB_DEFAULT);
1021 if (profile_path) {
1022 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1023 } else {
1024 pdb_set_profile_path(sampass,
1025 talloc_sub_basic(sampass, username, domain,
1026 lp_logon_path()),
1027 PDB_DEFAULT);
1030 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1031 pdb_set_workstations(sampass, workstations, PDB_SET);
1032 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1034 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1035 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1036 ret = False;
1037 goto done;
1041 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1042 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1043 ret = False;
1044 goto done;
1048 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1049 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1050 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1051 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1052 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1053 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1054 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1055 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1056 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1057 pdb_set_hours(sampass, hours, PDB_SET);
1059 done:
1061 SAFE_FREE(username);
1062 SAFE_FREE(domain);
1063 SAFE_FREE(nt_username);
1064 SAFE_FREE(fullname);
1065 SAFE_FREE(homedir);
1066 SAFE_FREE(dir_drive);
1067 SAFE_FREE(logon_script);
1068 SAFE_FREE(profile_path);
1069 SAFE_FREE(acct_desc);
1070 SAFE_FREE(workstations);
1071 SAFE_FREE(munged_dial);
1072 SAFE_FREE(unknown_str);
1073 SAFE_FREE(lm_pw_ptr);
1074 SAFE_FREE(nt_pw_ptr);
1075 SAFE_FREE(hours);
1077 return ret;
1080 /*********************************************************************
1081 *********************************************************************/
1083 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1086 /* times are stored as 32bit integer
1087 take care on system with 64bit wide time_t
1088 --SSS */
1089 uint32 logon_time,
1090 logoff_time,
1091 kickoff_time,
1092 bad_password_time,
1093 pass_last_set_time,
1094 pass_can_change_time,
1095 pass_must_change_time;
1096 char *username = NULL;
1097 char *domain = NULL;
1098 char *nt_username = NULL;
1099 char *dir_drive = NULL;
1100 char *unknown_str = NULL;
1101 char *munged_dial = NULL;
1102 char *fullname = NULL;
1103 char *homedir = NULL;
1104 char *logon_script = NULL;
1105 char *profile_path = NULL;
1106 char *acct_desc = NULL;
1107 char *workstations = NULL;
1108 uint32 username_len, domain_len, nt_username_len,
1109 dir_drive_len, unknown_str_len, munged_dial_len,
1110 fullname_len, homedir_len, logon_script_len,
1111 profile_path_len, acct_desc_len, workstations_len;
1113 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1114 uint16 acct_ctrl, logon_divs;
1115 uint16 bad_password_count, logon_count;
1116 uint8 *hours = NULL;
1117 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1118 uint32 len = 0;
1119 uint32 lm_pw_len, nt_pw_len, hourslen;
1120 bool ret = True;
1122 if(sampass == NULL || buf == NULL) {
1123 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1124 return False;
1127 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1129 /* unpack the buffer into variables */
1130 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1131 &logon_time, /* d */
1132 &logoff_time, /* d */
1133 &kickoff_time, /* d */
1134 /* Change from V0 is addition of bad_password_time field. */
1135 &bad_password_time, /* d */
1136 &pass_last_set_time, /* d */
1137 &pass_can_change_time, /* d */
1138 &pass_must_change_time, /* d */
1139 &username_len, &username, /* B */
1140 &domain_len, &domain, /* B */
1141 &nt_username_len, &nt_username, /* B */
1142 &fullname_len, &fullname, /* B */
1143 &homedir_len, &homedir, /* B */
1144 &dir_drive_len, &dir_drive, /* B */
1145 &logon_script_len, &logon_script, /* B */
1146 &profile_path_len, &profile_path, /* B */
1147 &acct_desc_len, &acct_desc, /* B */
1148 &workstations_len, &workstations, /* B */
1149 &unknown_str_len, &unknown_str, /* B */
1150 &munged_dial_len, &munged_dial, /* B */
1151 &user_rid, /* d */
1152 &group_rid, /* d */
1153 &lm_pw_len, &lm_pw_ptr, /* B */
1154 &nt_pw_len, &nt_pw_ptr, /* B */
1155 &acct_ctrl, /* w */
1156 &remove_me, /* d */
1157 &logon_divs, /* w */
1158 &hours_len, /* d */
1159 &hourslen, &hours, /* B */
1160 &bad_password_count, /* w */
1161 &logon_count, /* w */
1162 &unknown_6); /* d */
1164 if (len == (uint32) -1) {
1165 ret = False;
1166 goto done;
1169 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1170 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1171 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1173 /* Change from V0 is addition of bad_password_time field. */
1174 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1175 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1176 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1177 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1179 pdb_set_username(sampass, username, PDB_SET);
1180 pdb_set_domain(sampass, domain, PDB_SET);
1181 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1182 pdb_set_fullname(sampass, fullname, PDB_SET);
1184 if (homedir) {
1185 pdb_set_homedir(sampass, homedir, PDB_SET);
1187 else {
1188 pdb_set_homedir(sampass,
1189 talloc_sub_basic(sampass, username, domain,
1190 lp_logon_home()),
1191 PDB_DEFAULT);
1194 if (dir_drive)
1195 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1196 else {
1197 pdb_set_dir_drive(sampass,
1198 talloc_sub_basic(sampass, username, domain,
1199 lp_logon_drive()),
1200 PDB_DEFAULT);
1203 if (logon_script)
1204 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1205 else {
1206 pdb_set_logon_script(sampass,
1207 talloc_sub_basic(sampass, username, domain,
1208 lp_logon_script()),
1209 PDB_DEFAULT);
1212 if (profile_path) {
1213 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1214 } else {
1215 pdb_set_profile_path(sampass,
1216 talloc_sub_basic(sampass, username, domain,
1217 lp_logon_path()),
1218 PDB_DEFAULT);
1221 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1222 pdb_set_workstations(sampass, workstations, PDB_SET);
1223 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1225 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1226 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1227 ret = False;
1228 goto done;
1232 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1233 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1234 ret = False;
1235 goto done;
1239 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1241 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1242 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1243 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1244 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1245 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1246 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1247 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1248 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1249 pdb_set_hours(sampass, hours, PDB_SET);
1251 done:
1253 SAFE_FREE(username);
1254 SAFE_FREE(domain);
1255 SAFE_FREE(nt_username);
1256 SAFE_FREE(fullname);
1257 SAFE_FREE(homedir);
1258 SAFE_FREE(dir_drive);
1259 SAFE_FREE(logon_script);
1260 SAFE_FREE(profile_path);
1261 SAFE_FREE(acct_desc);
1262 SAFE_FREE(workstations);
1263 SAFE_FREE(munged_dial);
1264 SAFE_FREE(unknown_str);
1265 SAFE_FREE(lm_pw_ptr);
1266 SAFE_FREE(nt_pw_ptr);
1267 SAFE_FREE(hours);
1269 return ret;
1272 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1275 /* times are stored as 32bit integer
1276 take care on system with 64bit wide time_t
1277 --SSS */
1278 uint32 logon_time,
1279 logoff_time,
1280 kickoff_time,
1281 bad_password_time,
1282 pass_last_set_time,
1283 pass_can_change_time,
1284 pass_must_change_time;
1285 char *username = NULL;
1286 char *domain = NULL;
1287 char *nt_username = NULL;
1288 char *dir_drive = NULL;
1289 char *unknown_str = NULL;
1290 char *munged_dial = NULL;
1291 char *fullname = NULL;
1292 char *homedir = NULL;
1293 char *logon_script = NULL;
1294 char *profile_path = NULL;
1295 char *acct_desc = NULL;
1296 char *workstations = NULL;
1297 uint32 username_len, domain_len, nt_username_len,
1298 dir_drive_len, unknown_str_len, munged_dial_len,
1299 fullname_len, homedir_len, logon_script_len,
1300 profile_path_len, acct_desc_len, workstations_len;
1302 uint32 user_rid, group_rid, hours_len, unknown_6;
1303 uint16 acct_ctrl, logon_divs;
1304 uint16 bad_password_count, logon_count;
1305 uint8 *hours = NULL;
1306 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1307 uint32 len = 0;
1308 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1309 uint32 pwHistLen = 0;
1310 bool ret = True;
1311 fstring tmp_string;
1312 bool expand_explicit = lp_passdb_expand_explicit();
1314 if(sampass == NULL || buf == NULL) {
1315 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1316 return False;
1319 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1321 /* unpack the buffer into variables */
1322 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1323 &logon_time, /* d */
1324 &logoff_time, /* d */
1325 &kickoff_time, /* d */
1326 &bad_password_time, /* d */
1327 &pass_last_set_time, /* d */
1328 &pass_can_change_time, /* d */
1329 &pass_must_change_time, /* d */
1330 &username_len, &username, /* B */
1331 &domain_len, &domain, /* B */
1332 &nt_username_len, &nt_username, /* B */
1333 &fullname_len, &fullname, /* B */
1334 &homedir_len, &homedir, /* B */
1335 &dir_drive_len, &dir_drive, /* B */
1336 &logon_script_len, &logon_script, /* B */
1337 &profile_path_len, &profile_path, /* B */
1338 &acct_desc_len, &acct_desc, /* B */
1339 &workstations_len, &workstations, /* B */
1340 &unknown_str_len, &unknown_str, /* B */
1341 &munged_dial_len, &munged_dial, /* B */
1342 &user_rid, /* d */
1343 &group_rid, /* d */
1344 &lm_pw_len, &lm_pw_ptr, /* B */
1345 &nt_pw_len, &nt_pw_ptr, /* B */
1346 /* Change from V1 is addition of password history field. */
1347 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1348 &acct_ctrl, /* w */
1349 /* Also "remove_me" field was removed. */
1350 &logon_divs, /* w */
1351 &hours_len, /* d */
1352 &hourslen, &hours, /* B */
1353 &bad_password_count, /* w */
1354 &logon_count, /* w */
1355 &unknown_6); /* d */
1357 if (len == (uint32) -1) {
1358 ret = False;
1359 goto done;
1362 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1363 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1364 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1365 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1366 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1367 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1368 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1370 pdb_set_username(sampass, username, PDB_SET);
1371 pdb_set_domain(sampass, domain, PDB_SET);
1372 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1373 pdb_set_fullname(sampass, fullname, PDB_SET);
1375 if (homedir) {
1376 fstrcpy( tmp_string, homedir );
1377 if (expand_explicit) {
1378 standard_sub_basic( username, domain, tmp_string,
1379 sizeof(tmp_string) );
1381 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1383 else {
1384 pdb_set_homedir(sampass,
1385 talloc_sub_basic(sampass, username, domain,
1386 lp_logon_home()),
1387 PDB_DEFAULT);
1390 if (dir_drive)
1391 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1392 else
1393 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1395 if (logon_script) {
1396 fstrcpy( tmp_string, logon_script );
1397 if (expand_explicit) {
1398 standard_sub_basic( username, domain, tmp_string,
1399 sizeof(tmp_string) );
1401 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1403 else {
1404 pdb_set_logon_script(sampass,
1405 talloc_sub_basic(sampass, username, domain,
1406 lp_logon_script()),
1407 PDB_DEFAULT);
1410 if (profile_path) {
1411 fstrcpy( tmp_string, profile_path );
1412 if (expand_explicit) {
1413 standard_sub_basic( username, domain, tmp_string,
1414 sizeof(tmp_string) );
1416 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1418 else {
1419 pdb_set_profile_path(sampass,
1420 talloc_sub_basic(sampass, username, domain,
1421 lp_logon_path()),
1422 PDB_DEFAULT);
1425 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1426 pdb_set_workstations(sampass, workstations, PDB_SET);
1427 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1429 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1430 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1431 ret = False;
1432 goto done;
1436 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1437 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1438 ret = False;
1439 goto done;
1443 /* Change from V1 is addition of password history field. */
1444 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1445 if (pwHistLen) {
1446 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1447 if (!pw_hist) {
1448 ret = False;
1449 goto done;
1451 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1452 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1453 int i;
1454 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1455 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1456 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1457 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1458 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1459 PW_HISTORY_ENTRY_LEN);
1462 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1463 SAFE_FREE(pw_hist);
1464 ret = False;
1465 goto done;
1467 SAFE_FREE(pw_hist);
1468 } else {
1469 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1472 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1473 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1474 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1475 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1476 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1477 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1478 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1479 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1480 pdb_set_hours(sampass, hours, PDB_SET);
1482 done:
1484 SAFE_FREE(username);
1485 SAFE_FREE(domain);
1486 SAFE_FREE(nt_username);
1487 SAFE_FREE(fullname);
1488 SAFE_FREE(homedir);
1489 SAFE_FREE(dir_drive);
1490 SAFE_FREE(logon_script);
1491 SAFE_FREE(profile_path);
1492 SAFE_FREE(acct_desc);
1493 SAFE_FREE(workstations);
1494 SAFE_FREE(munged_dial);
1495 SAFE_FREE(unknown_str);
1496 SAFE_FREE(lm_pw_ptr);
1497 SAFE_FREE(nt_pw_ptr);
1498 SAFE_FREE(nt_pw_hist_ptr);
1499 SAFE_FREE(hours);
1501 return ret;
1504 /*********************************************************************
1505 *********************************************************************/
1507 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1510 /* times are stored as 32bit integer
1511 take care on system with 64bit wide time_t
1512 --SSS */
1513 uint32 logon_time,
1514 logoff_time,
1515 kickoff_time,
1516 bad_password_time,
1517 pass_last_set_time,
1518 pass_can_change_time,
1519 pass_must_change_time;
1520 char *username = NULL;
1521 char *domain = NULL;
1522 char *nt_username = NULL;
1523 char *dir_drive = NULL;
1524 char *unknown_str = NULL;
1525 char *munged_dial = NULL;
1526 char *fullname = NULL;
1527 char *homedir = NULL;
1528 char *logon_script = NULL;
1529 char *profile_path = NULL;
1530 char *acct_desc = NULL;
1531 char *workstations = NULL;
1532 uint32 username_len, domain_len, nt_username_len,
1533 dir_drive_len, unknown_str_len, munged_dial_len,
1534 fullname_len, homedir_len, logon_script_len,
1535 profile_path_len, acct_desc_len, workstations_len;
1537 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1538 uint16 logon_divs;
1539 uint16 bad_password_count, logon_count;
1540 uint8 *hours = NULL;
1541 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1542 uint32 len = 0;
1543 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1544 uint32 pwHistLen = 0;
1545 bool ret = True;
1546 fstring tmp_string;
1547 bool expand_explicit = lp_passdb_expand_explicit();
1549 if(sampass == NULL || buf == NULL) {
1550 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1551 return False;
1554 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1556 /* unpack the buffer into variables */
1557 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1558 &logon_time, /* d */
1559 &logoff_time, /* d */
1560 &kickoff_time, /* d */
1561 &bad_password_time, /* d */
1562 &pass_last_set_time, /* d */
1563 &pass_can_change_time, /* d */
1564 &pass_must_change_time, /* d */
1565 &username_len, &username, /* B */
1566 &domain_len, &domain, /* B */
1567 &nt_username_len, &nt_username, /* B */
1568 &fullname_len, &fullname, /* B */
1569 &homedir_len, &homedir, /* B */
1570 &dir_drive_len, &dir_drive, /* B */
1571 &logon_script_len, &logon_script, /* B */
1572 &profile_path_len, &profile_path, /* B */
1573 &acct_desc_len, &acct_desc, /* B */
1574 &workstations_len, &workstations, /* B */
1575 &unknown_str_len, &unknown_str, /* B */
1576 &munged_dial_len, &munged_dial, /* B */
1577 &user_rid, /* d */
1578 &group_rid, /* d */
1579 &lm_pw_len, &lm_pw_ptr, /* B */
1580 &nt_pw_len, &nt_pw_ptr, /* B */
1581 /* Change from V1 is addition of password history field. */
1582 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1583 /* Change from V2 is the uint32 acb_mask */
1584 &acct_ctrl, /* d */
1585 /* Also "remove_me" field was removed. */
1586 &logon_divs, /* w */
1587 &hours_len, /* d */
1588 &hourslen, &hours, /* B */
1589 &bad_password_count, /* w */
1590 &logon_count, /* w */
1591 &unknown_6); /* d */
1593 if (len == (uint32) -1) {
1594 ret = False;
1595 goto done;
1598 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1599 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1600 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1601 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1602 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1603 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1604 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1606 pdb_set_username(sampass, username, PDB_SET);
1607 pdb_set_domain(sampass, domain, PDB_SET);
1608 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1609 pdb_set_fullname(sampass, fullname, PDB_SET);
1611 if (homedir) {
1612 fstrcpy( tmp_string, homedir );
1613 if (expand_explicit) {
1614 standard_sub_basic( username, domain, tmp_string,
1615 sizeof(tmp_string) );
1617 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1619 else {
1620 pdb_set_homedir(sampass,
1621 talloc_sub_basic(sampass, username, domain,
1622 lp_logon_home()),
1623 PDB_DEFAULT);
1626 if (dir_drive)
1627 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1628 else
1629 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1631 if (logon_script) {
1632 fstrcpy( tmp_string, logon_script );
1633 if (expand_explicit) {
1634 standard_sub_basic( username, domain, tmp_string,
1635 sizeof(tmp_string) );
1637 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1639 else {
1640 pdb_set_logon_script(sampass,
1641 talloc_sub_basic(sampass, username, domain,
1642 lp_logon_script()),
1643 PDB_DEFAULT);
1646 if (profile_path) {
1647 fstrcpy( tmp_string, profile_path );
1648 if (expand_explicit) {
1649 standard_sub_basic( username, domain, tmp_string,
1650 sizeof(tmp_string) );
1652 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1654 else {
1655 pdb_set_profile_path(sampass,
1656 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1657 PDB_DEFAULT);
1660 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1661 pdb_set_workstations(sampass, workstations, PDB_SET);
1662 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1664 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1665 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1666 ret = False;
1667 goto done;
1671 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1672 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1673 ret = False;
1674 goto done;
1678 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1679 if (pwHistLen) {
1680 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1681 if (!pw_hist) {
1682 ret = False;
1683 goto done;
1685 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1686 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1687 int i;
1688 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1689 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1690 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1691 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1692 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1693 PW_HISTORY_ENTRY_LEN);
1696 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1697 SAFE_FREE(pw_hist);
1698 ret = False;
1699 goto done;
1701 SAFE_FREE(pw_hist);
1702 } else {
1703 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1706 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1707 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1708 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1709 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1710 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1711 /* Change from V2 is the uint32 acct_ctrl */
1712 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1713 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1714 pdb_set_hours(sampass, hours, PDB_SET);
1716 done:
1718 SAFE_FREE(username);
1719 SAFE_FREE(domain);
1720 SAFE_FREE(nt_username);
1721 SAFE_FREE(fullname);
1722 SAFE_FREE(homedir);
1723 SAFE_FREE(dir_drive);
1724 SAFE_FREE(logon_script);
1725 SAFE_FREE(profile_path);
1726 SAFE_FREE(acct_desc);
1727 SAFE_FREE(workstations);
1728 SAFE_FREE(munged_dial);
1729 SAFE_FREE(unknown_str);
1730 SAFE_FREE(lm_pw_ptr);
1731 SAFE_FREE(nt_pw_ptr);
1732 SAFE_FREE(nt_pw_hist_ptr);
1733 SAFE_FREE(hours);
1735 return ret;
1738 /*********************************************************************
1739 *********************************************************************/
1741 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1743 size_t len, buflen;
1745 /* times are stored as 32bit integer
1746 take care on system with 64bit wide time_t
1747 --SSS */
1748 uint32 logon_time,
1749 logoff_time,
1750 kickoff_time,
1751 bad_password_time,
1752 pass_last_set_time,
1753 pass_can_change_time,
1754 pass_must_change_time;
1756 uint32 user_rid, group_rid;
1758 const char *username;
1759 const char *domain;
1760 const char *nt_username;
1761 const char *dir_drive;
1762 const char *unknown_str;
1763 const char *munged_dial;
1764 const char *fullname;
1765 const char *homedir;
1766 const char *logon_script;
1767 const char *profile_path;
1768 const char *acct_desc;
1769 const char *workstations;
1770 uint32 username_len, domain_len, nt_username_len,
1771 dir_drive_len, unknown_str_len, munged_dial_len,
1772 fullname_len, homedir_len, logon_script_len,
1773 profile_path_len, acct_desc_len, workstations_len;
1775 const uint8 *lm_pw;
1776 const uint8 *nt_pw;
1777 const uint8 *nt_pw_hist;
1778 uint32 lm_pw_len = 16;
1779 uint32 nt_pw_len = 16;
1780 uint32 nt_pw_hist_len;
1781 uint32 pwHistLen = 0;
1783 *buf = NULL;
1784 buflen = 0;
1786 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1787 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1788 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1789 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1790 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1791 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1792 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1794 user_rid = pdb_get_user_rid(sampass);
1795 group_rid = pdb_get_group_rid(sampass);
1797 username = pdb_get_username(sampass);
1798 if (username) {
1799 username_len = strlen(username) +1;
1800 } else {
1801 username_len = 0;
1804 domain = pdb_get_domain(sampass);
1805 if (domain) {
1806 domain_len = strlen(domain) +1;
1807 } else {
1808 domain_len = 0;
1811 nt_username = pdb_get_nt_username(sampass);
1812 if (nt_username) {
1813 nt_username_len = strlen(nt_username) +1;
1814 } else {
1815 nt_username_len = 0;
1818 fullname = pdb_get_fullname(sampass);
1819 if (fullname) {
1820 fullname_len = strlen(fullname) +1;
1821 } else {
1822 fullname_len = 0;
1826 * Only updates fields which have been set (not defaults from smb.conf)
1829 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1830 dir_drive = pdb_get_dir_drive(sampass);
1831 } else {
1832 dir_drive = NULL;
1834 if (dir_drive) {
1835 dir_drive_len = strlen(dir_drive) +1;
1836 } else {
1837 dir_drive_len = 0;
1840 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1841 homedir = pdb_get_homedir(sampass);
1842 } else {
1843 homedir = NULL;
1845 if (homedir) {
1846 homedir_len = strlen(homedir) +1;
1847 } else {
1848 homedir_len = 0;
1851 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1852 logon_script = pdb_get_logon_script(sampass);
1853 } else {
1854 logon_script = NULL;
1856 if (logon_script) {
1857 logon_script_len = strlen(logon_script) +1;
1858 } else {
1859 logon_script_len = 0;
1862 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1863 profile_path = pdb_get_profile_path(sampass);
1864 } else {
1865 profile_path = NULL;
1867 if (profile_path) {
1868 profile_path_len = strlen(profile_path) +1;
1869 } else {
1870 profile_path_len = 0;
1873 lm_pw = pdb_get_lanman_passwd(sampass);
1874 if (!lm_pw) {
1875 lm_pw_len = 0;
1878 nt_pw = pdb_get_nt_passwd(sampass);
1879 if (!nt_pw) {
1880 nt_pw_len = 0;
1883 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1884 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1885 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1886 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1887 } else {
1888 nt_pw_hist_len = 0;
1891 acct_desc = pdb_get_acct_desc(sampass);
1892 if (acct_desc) {
1893 acct_desc_len = strlen(acct_desc) +1;
1894 } else {
1895 acct_desc_len = 0;
1898 workstations = pdb_get_workstations(sampass);
1899 if (workstations) {
1900 workstations_len = strlen(workstations) +1;
1901 } else {
1902 workstations_len = 0;
1905 unknown_str = NULL;
1906 unknown_str_len = 0;
1908 munged_dial = pdb_get_munged_dial(sampass);
1909 if (munged_dial) {
1910 munged_dial_len = strlen(munged_dial) +1;
1911 } else {
1912 munged_dial_len = 0;
1915 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1917 /* one time to get the size needed */
1918 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1919 logon_time, /* d */
1920 logoff_time, /* d */
1921 kickoff_time, /* d */
1922 bad_password_time, /* d */
1923 pass_last_set_time, /* d */
1924 pass_can_change_time, /* d */
1925 pass_must_change_time, /* d */
1926 username_len, username, /* B */
1927 domain_len, domain, /* B */
1928 nt_username_len, nt_username, /* B */
1929 fullname_len, fullname, /* B */
1930 homedir_len, homedir, /* B */
1931 dir_drive_len, dir_drive, /* B */
1932 logon_script_len, logon_script, /* B */
1933 profile_path_len, profile_path, /* B */
1934 acct_desc_len, acct_desc, /* B */
1935 workstations_len, workstations, /* B */
1936 unknown_str_len, unknown_str, /* B */
1937 munged_dial_len, munged_dial, /* B */
1938 user_rid, /* d */
1939 group_rid, /* d */
1940 lm_pw_len, lm_pw, /* B */
1941 nt_pw_len, nt_pw, /* B */
1942 nt_pw_hist_len, nt_pw_hist, /* B */
1943 pdb_get_acct_ctrl(sampass), /* d */
1944 pdb_get_logon_divs(sampass), /* w */
1945 pdb_get_hours_len(sampass), /* d */
1946 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1947 pdb_get_bad_password_count(sampass), /* w */
1948 pdb_get_logon_count(sampass), /* w */
1949 pdb_get_unknown_6(sampass)); /* d */
1951 if (size_only) {
1952 return buflen;
1955 /* malloc the space needed */
1956 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1957 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1958 return (-1);
1961 /* now for the real call to tdb_pack() */
1962 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1963 logon_time, /* d */
1964 logoff_time, /* d */
1965 kickoff_time, /* d */
1966 bad_password_time, /* d */
1967 pass_last_set_time, /* d */
1968 pass_can_change_time, /* d */
1969 pass_must_change_time, /* d */
1970 username_len, username, /* B */
1971 domain_len, domain, /* B */
1972 nt_username_len, nt_username, /* B */
1973 fullname_len, fullname, /* B */
1974 homedir_len, homedir, /* B */
1975 dir_drive_len, dir_drive, /* B */
1976 logon_script_len, logon_script, /* B */
1977 profile_path_len, profile_path, /* B */
1978 acct_desc_len, acct_desc, /* B */
1979 workstations_len, workstations, /* B */
1980 unknown_str_len, unknown_str, /* B */
1981 munged_dial_len, munged_dial, /* B */
1982 user_rid, /* d */
1983 group_rid, /* d */
1984 lm_pw_len, lm_pw, /* B */
1985 nt_pw_len, nt_pw, /* B */
1986 nt_pw_hist_len, nt_pw_hist, /* B */
1987 pdb_get_acct_ctrl(sampass), /* d */
1988 pdb_get_logon_divs(sampass), /* w */
1989 pdb_get_hours_len(sampass), /* d */
1990 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1991 pdb_get_bad_password_count(sampass), /* w */
1992 pdb_get_logon_count(sampass), /* w */
1993 pdb_get_unknown_6(sampass)); /* d */
1995 /* check to make sure we got it correct */
1996 if (buflen != len) {
1997 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1998 (unsigned long)buflen, (unsigned long)len));
1999 /* error */
2000 SAFE_FREE (*buf);
2001 return (-1);
2004 return (buflen);
2007 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2009 /* nothing changed between V3 and V4 */
2010 return init_samu_from_buffer_v3(sampass, buf, buflen);
2013 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2015 /* nothing changed between V3 and V4 */
2016 return init_buffer_from_samu_v3(buf, sampass, size_only);
2019 /**********************************************************************
2020 Intialize a struct samu struct from a BYTE buffer of size len
2021 *********************************************************************/
2023 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2024 uint8 *buf, uint32 buflen)
2026 switch (level) {
2027 case SAMU_BUFFER_V0:
2028 return init_samu_from_buffer_v0(sampass, buf, buflen);
2029 case SAMU_BUFFER_V1:
2030 return init_samu_from_buffer_v1(sampass, buf, buflen);
2031 case SAMU_BUFFER_V2:
2032 return init_samu_from_buffer_v2(sampass, buf, buflen);
2033 case SAMU_BUFFER_V3:
2034 return init_samu_from_buffer_v3(sampass, buf, buflen);
2035 case SAMU_BUFFER_V4:
2036 return init_samu_from_buffer_v4(sampass, buf, buflen);
2039 return false;
2042 /**********************************************************************
2043 Intialize a BYTE buffer from a struct samu struct
2044 *********************************************************************/
2046 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2048 return init_buffer_from_samu_v4(buf, sampass, size_only);
2051 /*********************************************************************
2052 *********************************************************************/
2054 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2056 uint8 *buf = NULL;
2057 int len;
2059 len = init_buffer_from_samu(&buf, src, False);
2060 if (len == -1 || !buf) {
2061 SAFE_FREE(buf);
2062 return False;
2065 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2066 free(buf);
2067 return False;
2070 dst->methods = src->methods;
2072 if ( src->unix_pw ) {
2073 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2074 if (!dst->unix_pw) {
2075 free(buf);
2076 return False;
2080 free(buf);
2081 return True;
2084 /*********************************************************************
2085 Update the bad password count checking the AP_RESET_COUNT_TIME
2086 *********************************************************************/
2088 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2090 time_t LastBadPassword;
2091 uint16 BadPasswordCount;
2092 uint32 resettime;
2093 bool res;
2095 BadPasswordCount = pdb_get_bad_password_count(sampass);
2096 if (!BadPasswordCount) {
2097 DEBUG(9, ("No bad password attempts.\n"));
2098 return True;
2101 become_root();
2102 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
2103 unbecome_root();
2105 if (!res) {
2106 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2107 return False;
2110 /* First, check if there is a reset time to compare */
2111 if ((resettime == (uint32) -1) || (resettime == 0)) {
2112 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2113 return True;
2116 LastBadPassword = pdb_get_bad_password_time(sampass);
2117 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2118 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2119 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2120 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2121 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2122 if (updated) {
2123 *updated = True;
2127 return True;
2130 /*********************************************************************
2131 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
2132 *********************************************************************/
2134 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2136 uint32 duration;
2137 time_t LastBadPassword;
2138 bool res;
2140 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2141 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2142 pdb_get_username(sampass)));
2143 return True;
2146 become_root();
2147 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
2148 unbecome_root();
2150 if (!res) {
2151 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2152 return False;
2155 /* First, check if there is a duration to compare */
2156 if ((duration == (uint32) -1) || (duration == 0)) {
2157 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2158 return True;
2161 LastBadPassword = pdb_get_bad_password_time(sampass);
2162 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2163 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2165 if (LastBadPassword == (time_t)0) {
2166 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2167 "administratively locked out with no bad password "
2168 "time. Leaving locked out.\n",
2169 pdb_get_username(sampass) ));
2170 return True;
2173 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2174 pdb_set_acct_ctrl(sampass,
2175 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2176 PDB_CHANGED);
2177 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2178 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2179 if (updated) {
2180 *updated = True;
2184 return True;
2187 /*********************************************************************
2188 Increment the bad_password_count
2189 *********************************************************************/
2191 bool pdb_increment_bad_password_count(struct samu *sampass)
2193 uint32 account_policy_lockout;
2194 bool autolock_updated = False, badpw_updated = False;
2195 bool ret;
2197 /* Retrieve the account lockout policy */
2198 become_root();
2199 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2200 unbecome_root();
2201 if ( !ret ) {
2202 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2203 return False;
2206 /* If there is no policy, we don't need to continue checking */
2207 if (!account_policy_lockout) {
2208 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2209 return True;
2212 /* Check if the autolock needs to be cleared */
2213 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2214 return False;
2216 /* Check if the badpw count needs to be reset */
2217 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2218 return False;
2221 Ok, now we can assume that any resetting that needs to be
2222 done has been done, and just get on with incrementing
2223 and autolocking if necessary
2226 pdb_set_bad_password_count(sampass,
2227 pdb_get_bad_password_count(sampass)+1,
2228 PDB_CHANGED);
2229 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2232 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2233 return True;
2235 if (!pdb_set_acct_ctrl(sampass,
2236 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2237 PDB_CHANGED)) {
2238 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2239 return False;
2242 return True;
2245 bool is_dc_trusted_domain_situation(const char *domain_name)
2247 return IS_DC && !strequal(domain_name, lp_workgroup());
2250 /*******************************************************************
2251 Wrapper around retrieving the clear text trust account password.
2252 appropriate account name is stored in account_name.
2253 Caller must free password, but not account_name.
2254 *******************************************************************/
2256 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2257 const char **account_name, uint32 *channel)
2259 char *pwd;
2260 time_t last_set_time;
2262 /* if we are a DC and this is not our domain, then lookup an account
2263 * for the domain trust */
2265 if (is_dc_trusted_domain_situation(domain)) {
2266 if (!lp_allow_trusted_domains()) {
2267 return false;
2270 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2271 &last_set_time))
2273 DEBUG(0, ("get_trust_pw: could not fetch trust "
2274 "account password for trusted domain %s\n",
2275 domain));
2276 return false;
2279 if (channel != NULL) {
2280 *channel = SEC_CHAN_DOMAIN;
2283 if (account_name != NULL) {
2284 *account_name = lp_workgroup();
2287 return true;
2291 * Since we can only be member of one single domain, we are now
2292 * in a member situation:
2294 * - Either we are a DC (selfjoined) and the domain is our
2295 * own domain.
2296 * - Or we are on a member and the domain is our own or some
2297 * other (potentially trusted) domain.
2299 * In both cases, we can only get the machine account password
2300 * for our own domain to connect to our own dc. (For a member,
2301 * request to trusted domains are performed through our dc.)
2303 * So we simply use our own domain name to retrieve the
2304 * machine account passowrd and ignore the request domain here.
2307 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2309 if (pwd != NULL) {
2310 *ret_pwd = pwd;
2311 if (account_name != NULL) {
2312 *account_name = global_myname();
2315 return true;
2318 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2319 "account password for domain %s\n", domain));
2320 return false;
2323 /*******************************************************************
2324 Wrapper around retrieving the trust account password.
2325 appropriate account name is stored in account_name.
2326 *******************************************************************/
2328 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2329 const char **account_name, uint32 *channel)
2331 char *pwd = NULL;
2332 time_t last_set_time;
2334 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2335 E_md4hash(pwd, ret_pwd);
2336 SAFE_FREE(pwd);
2337 return true;
2338 } else if (is_dc_trusted_domain_situation(domain)) {
2339 return false;
2342 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2344 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2345 &last_set_time,
2346 channel))
2348 if (account_name != NULL) {
2349 *account_name = global_myname();
2352 return true;
2355 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2356 "password for domain %s\n", domain));
2357 return False;
2360 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2361 struct samu *pw)
2363 struct samr_LogonHours hours;
2364 const int units_per_week = 168;
2366 ZERO_STRUCT(hours);
2367 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2368 if (!hours.bits) {
2369 return hours;
2372 hours.units_per_week = units_per_week;
2373 memset(hours.bits, 0xFF, units_per_week);
2375 if (pdb_get_hours(pw)) {
2376 memcpy(hours.bits, pdb_get_hours(pw),
2377 MIN(pdb_get_hours_len(pw), units_per_week));
2380 return hours;
2383 /****************************************************************
2384 ****************************************************************/
2386 NTSTATUS smb_create_user(TALLOC_CTX *mem_ctx,
2387 uint32_t acct_flags,
2388 const char *account,
2389 struct passwd **passwd_p)
2391 struct passwd *passwd;
2392 char *add_script = NULL;
2394 passwd = Get_Pwnam_alloc(mem_ctx, account);
2395 if (passwd) {
2396 *passwd_p = passwd;
2397 return NT_STATUS_OK;
2400 /* Create appropriate user */
2401 if (acct_flags & ACB_NORMAL) {
2402 add_script = talloc_strdup(mem_ctx, lp_adduser_script());
2403 } else if ( (acct_flags & ACB_WSTRUST) ||
2404 (acct_flags & ACB_SVRTRUST) ||
2405 (acct_flags & ACB_DOMTRUST) ) {
2406 add_script = talloc_strdup(mem_ctx, lp_addmachine_script());
2407 } else {
2408 DEBUG(1, ("Unknown user type: %s\n",
2409 pdb_encode_acct_ctrl(acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
2410 return NT_STATUS_UNSUCCESSFUL;
2413 if (!add_script) {
2414 return NT_STATUS_NO_MEMORY;
2417 if (*add_script) {
2418 int add_ret;
2419 add_script = talloc_all_string_sub(mem_ctx, add_script,
2420 "%u", account);
2421 if (!add_script) {
2422 return NT_STATUS_NO_MEMORY;
2424 add_ret = smbrun(add_script, NULL);
2425 DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
2426 "gave %d\n", add_script, add_ret));
2427 if (add_ret == 0) {
2428 smb_nscd_flush_user_cache();
2432 /* try and find the possible unix account again */
2433 passwd = Get_Pwnam_alloc(mem_ctx, account);
2434 if (!passwd) {
2435 return NT_STATUS_NO_SUCH_USER;
2438 *passwd_p = passwd;
2440 return NT_STATUS_OK;