Consolidate user create/delete paths in smbpasswd
[Samba.git] / source3 / passdb / passdb.c
blob9654e79d7a5f47b0f141ab5e87fbcadc34ade829
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"
26 #include "../libcli/auth/libcli_auth.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 /******************************************************************
32 Get the default domain/netbios name to be used when
33 testing authentication.
35 LEGACY: this function provides the legacy domain mapping used with
36 the lp_map_untrusted_to_domain() parameter
37 ******************************************************************/
39 const char *my_sam_name(void)
41 /* Standalone servers can only use the local netbios name */
42 if ( lp_server_role() == ROLE_STANDALONE )
43 return global_myname();
45 /* Default to the DOMAIN 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;
122 return user;
125 /*********************************************************************
126 Initialize a struct samu from a struct passwd including the user
127 and group SIDs. The *user structure is filled out with the Unix
128 attributes and a user SID.
129 *********************************************************************/
131 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
133 const char *guest_account = lp_guestaccount();
134 const char *domain = global_myname();
135 uint32 urid;
137 if ( !pwd ) {
138 return NT_STATUS_NO_SUCH_USER;
141 /* Basic properties based upon the Unix account information */
143 pdb_set_username(user, pwd->pw_name, PDB_SET);
144 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
145 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
146 #if 0
147 /* This can lead to a primary group of S-1-22-2-XX which
148 will be rejected by other parts of the Samba code.
149 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
150 --jerry */
152 gid_to_sid(&group_sid, pwd->pw_gid);
153 pdb_set_group_sid(user, &group_sid, PDB_SET);
154 #endif
156 /* save the password structure for later use */
158 user->unix_pw = tcopy_passwd( user, pwd );
160 /* Special case for the guest account which must have a RID of 501 */
162 if ( strequal( pwd->pw_name, guest_account ) ) {
163 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
164 return NT_STATUS_NO_SUCH_USER;
166 return NT_STATUS_OK;
169 /* Non-guest accounts...Check for a workstation or user account */
171 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
172 /* workstation */
174 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
175 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
176 pwd->pw_name));
177 return NT_STATUS_INVALID_COMPUTER_NAME;
180 else {
181 /* user */
183 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
184 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
185 pwd->pw_name));
186 return NT_STATUS_INVALID_ACCOUNT_NAME;
189 /* set some basic attributes */
191 pdb_set_profile_path(user, talloc_sub_specified(user,
192 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
193 PDB_DEFAULT);
194 pdb_set_homedir(user, talloc_sub_specified(user,
195 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
196 PDB_DEFAULT);
197 pdb_set_dir_drive(user, talloc_sub_specified(user,
198 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
199 PDB_DEFAULT);
200 pdb_set_logon_script(user, talloc_sub_specified(user,
201 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
202 PDB_DEFAULT);
205 /* Now deal with the user SID. If we have a backend that can generate
206 RIDs, then do so. But sometimes the caller just wanted a structure
207 initialized and will fill in these fields later (such as from a
208 netr_SamInfo3 structure) */
210 if ( create && !pdb_rid_algorithm() ) {
211 uint32 user_rid;
212 DOM_SID user_sid;
214 if ( !pdb_new_rid( &user_rid ) ) {
215 DEBUG(3, ("Could not allocate a new RID\n"));
216 return NT_STATUS_ACCESS_DENIED;
219 sid_copy( &user_sid, get_global_sam_sid() );
220 sid_append_rid( &user_sid, user_rid );
222 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
223 DEBUG(3, ("pdb_set_user_sid failed\n"));
224 return NT_STATUS_INTERNAL_ERROR;
227 return NT_STATUS_OK;
230 /* generate a SID for the user with the RID algorithm */
232 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
234 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
235 return NT_STATUS_INTERNAL_ERROR;
238 return NT_STATUS_OK;
241 /********************************************************************
242 Set the Unix user attributes
243 ********************************************************************/
245 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
247 return samu_set_unix_internal( user, pwd, False );
250 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
252 return samu_set_unix_internal( user, pwd, True );
255 /**********************************************************
256 Encode the account control bits into a string.
257 length = length of string to encode into (including terminating
258 null). length *MUST BE MORE THAN 2* !
259 **********************************************************/
261 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
263 fstring acct_str;
264 char *result;
266 size_t i = 0;
268 SMB_ASSERT(length <= sizeof(acct_str));
270 acct_str[i++] = '[';
272 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
273 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
274 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
275 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
276 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
277 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
278 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
279 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
280 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
281 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
282 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
284 for ( ; i < length - 2 ; i++ )
285 acct_str[i] = ' ';
287 i = length - 2;
288 acct_str[i++] = ']';
289 acct_str[i++] = '\0';
291 result = talloc_strdup(talloc_tos(), acct_str);
292 SMB_ASSERT(result != NULL);
293 return result;
296 /**********************************************************
297 Decode the account control bits from a string.
298 **********************************************************/
300 uint32_t pdb_decode_acct_ctrl(const char *p)
302 uint32_t acct_ctrl = 0;
303 bool finished = false;
306 * Check if the account type bits have been encoded after the
307 * NT password (in the form [NDHTUWSLXI]).
310 if (*p != '[')
311 return 0;
313 for (p++; *p && !finished; p++) {
314 switch (*p) {
315 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
316 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
317 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
318 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
319 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
320 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
321 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
322 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
323 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
324 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
325 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
326 case ' ': { break; }
327 case ':':
328 case '\n':
329 case '\0':
330 case ']':
331 default: { finished = true; }
335 return acct_ctrl;
338 /*************************************************************
339 Routine to set 32 hex password characters from a 16 byte array.
340 **************************************************************/
342 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
344 if (pwd != NULL) {
345 int i;
346 for (i = 0; i < 16; i++)
347 slprintf(&p[i*2], 3, "%02X", pwd[i]);
348 } else {
349 if (acct_ctrl & ACB_PWNOTREQ)
350 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
351 else
352 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
356 /*************************************************************
357 Routine to get the 32 hex characters and turn them
358 into a 16 byte array.
359 **************************************************************/
361 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
363 int i;
364 unsigned char lonybble, hinybble;
365 const char *hexchars = "0123456789ABCDEF";
366 char *p1, *p2;
368 if (!p)
369 return false;
371 for (i = 0; i < 32; i += 2) {
372 hinybble = toupper_ascii(p[i]);
373 lonybble = toupper_ascii(p[i + 1]);
375 p1 = strchr(hexchars, hinybble);
376 p2 = strchr(hexchars, lonybble);
378 if (!p1 || !p2)
379 return false;
381 hinybble = PTR_DIFF(p1, hexchars);
382 lonybble = PTR_DIFF(p2, hexchars);
384 pwd[i / 2] = (hinybble << 4) | lonybble;
386 return true;
389 /*************************************************************
390 Routine to set 42 hex hours characters from a 21 byte array.
391 **************************************************************/
393 void pdb_sethexhours(char *p, const unsigned char *hours)
395 if (hours != NULL) {
396 int i;
397 for (i = 0; i < 21; i++) {
398 slprintf(&p[i*2], 3, "%02X", hours[i]);
400 } else {
401 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
405 /*************************************************************
406 Routine to get the 42 hex characters and turn them
407 into a 21 byte array.
408 **************************************************************/
410 bool pdb_gethexhours(const char *p, unsigned char *hours)
412 int i;
413 unsigned char lonybble, hinybble;
414 const char *hexchars = "0123456789ABCDEF";
415 char *p1, *p2;
417 if (!p) {
418 return (False);
421 for (i = 0; i < 42; i += 2) {
422 hinybble = toupper_ascii(p[i]);
423 lonybble = toupper_ascii(p[i + 1]);
425 p1 = strchr(hexchars, hinybble);
426 p2 = strchr(hexchars, lonybble);
428 if (!p1 || !p2) {
429 return (False);
432 hinybble = PTR_DIFF(p1, hexchars);
433 lonybble = PTR_DIFF(p2, hexchars);
435 hours[i / 2] = (hinybble << 4) | lonybble;
437 return (True);
440 /********************************************************************
441 ********************************************************************/
443 int algorithmic_rid_base(void)
445 int rid_offset;
447 rid_offset = lp_algorithmic_rid_base();
449 if (rid_offset < BASE_RID) {
450 /* Try to prevent admin foot-shooting, we can't put algorithmic
451 rids below 1000, that's the 'well known RIDs' on NT */
452 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
453 rid_offset = BASE_RID;
455 if (rid_offset & 1) {
456 DEBUG(0, ("algorithmic rid base must be even\n"));
457 rid_offset += 1;
459 return rid_offset;
462 /*******************************************************************
463 Converts NT user RID to a UNIX uid.
464 ********************************************************************/
466 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
468 int rid_offset = algorithmic_rid_base();
469 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
472 uid_t max_algorithmic_uid(void)
474 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
477 /*******************************************************************
478 converts UNIX uid to an NT User RID.
479 ********************************************************************/
481 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
483 int rid_offset = algorithmic_rid_base();
484 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
487 /*******************************************************************
488 Converts NT group RID to a UNIX gid.
489 ********************************************************************/
491 gid_t pdb_group_rid_to_gid(uint32 group_rid)
493 int rid_offset = algorithmic_rid_base();
494 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
497 gid_t max_algorithmic_gid(void)
499 return pdb_group_rid_to_gid(0xffffffff);
502 /*******************************************************************
503 converts NT Group RID to a UNIX uid.
505 warning: you must not call that function only
506 you must do a call to the group mapping first.
507 there is not anymore a direct link between the gid and the rid.
508 ********************************************************************/
510 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
512 int rid_offset = algorithmic_rid_base();
513 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
516 /*******************************************************************
517 Decides if a RID is a well known RID.
518 ********************************************************************/
520 static bool rid_is_well_known(uint32 rid)
522 /* Not using rid_offset here, because this is the actual
523 NT fixed value (1000) */
525 return (rid < BASE_RID);
528 /*******************************************************************
529 Decides if a RID is a user or group RID.
530 ********************************************************************/
532 bool algorithmic_pdb_rid_is_user(uint32 rid)
534 if ( rid_is_well_known(rid) ) {
536 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
537 * and DOMAIN_USER_RID_GUEST.
539 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
540 return True;
541 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
542 return True;
544 return False;
547 /*******************************************************************
548 Convert a name into a SID. Used in the lookup name rpc.
549 ********************************************************************/
551 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
552 enum lsa_SidType *type)
554 GROUP_MAP map;
555 bool ret;
557 /* Windows treats "MACHINE\None" as a special name for
558 rid 513 on non-DCs. You cannot create a user or group
559 name "None" on Windows. You will get an error that
560 the group already exists. */
562 if ( strequal( name, "None" ) ) {
563 *rid = DOMAIN_GROUP_RID_USERS;
564 *type = SID_NAME_DOM_GRP;
566 return True;
569 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
570 * correctly in the case where foo also exists as a user. If the flag
571 * is set, don't look for users at all. */
573 if ((flags & LOOKUP_NAME_GROUP) == 0) {
574 struct samu *sam_account = NULL;
575 DOM_SID user_sid;
577 if ( !(sam_account = samu_new( NULL )) ) {
578 return False;
581 become_root();
582 ret = pdb_getsampwnam(sam_account, name);
583 unbecome_root();
585 if (ret) {
586 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
589 TALLOC_FREE(sam_account);
591 if (ret) {
592 if (!sid_check_is_in_our_domain(&user_sid)) {
593 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
594 name, sid_string_dbg(&user_sid)));
595 return False;
598 sid_peek_rid(&user_sid, rid);
599 *type = SID_NAME_USER;
600 return True;
605 * Maybe it is a group ?
608 become_root();
609 ret = pdb_getgrnam(&map, name);
610 unbecome_root();
612 if (!ret) {
613 return False;
616 /* BUILTIN groups are looked up elsewhere */
617 if (!sid_check_is_in_our_domain(&map.sid)) {
618 DEBUG(10, ("Found group %s (%s) not in our domain -- "
619 "ignoring.", name, sid_string_dbg(&map.sid)));
620 return False;
623 /* yes it's a mapped group */
624 sid_peek_rid(&map.sid, rid);
625 *type = map.sid_name_use;
626 return True;
629 /*************************************************************
630 Change a password entry in the local passdb backend.
632 Assumptions:
633 - always called as root
634 - ignores the account type except when adding a new account
635 - will create/delete the unix account if the relative
636 add/delete user script is configured
638 *************************************************************/
640 NTSTATUS local_password_change(const char *user_name,
641 int local_flags,
642 const char *new_passwd,
643 char **pp_err_str,
644 char **pp_msg_str)
646 TALLOC_CTX *tosctx;
647 struct samu *sam_pass;
648 uint32_t acb;
649 uint32_t rid;
650 NTSTATUS result;
651 bool user_exists;
652 int ret;
654 *pp_err_str = NULL;
655 *pp_msg_str = NULL;
657 tosctx = talloc_tos();
658 if (!tosctx) {
659 return NT_STATUS_NO_MEMORY;
662 sam_pass = samu_new(tosctx);
663 if (!sam_pass) {
664 result = NT_STATUS_NO_MEMORY;
665 goto done;
668 /* Get the smb passwd entry for this user */
669 user_exists = pdb_getsampwnam(sam_pass, user_name);
671 /* Check delete first, we don't need to do anything else if we
672 * are going to delete the acocunt */
673 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
675 result = pdb_delete_user(tosctx, sam_pass);
676 if (!NT_STATUS_IS_OK(result)) {
677 ret = asprintf(pp_err_str,
678 "Failed to delete entry for user %s.\n",
679 user_name);
680 if (ret < 0) {
681 *pp_err_str = NULL;
683 result = NT_STATUS_UNSUCCESSFUL;
684 } else {
685 ret = asprintf(pp_msg_str,
686 "Deleted user %s.\n",
687 user_name);
688 if (ret < 0) {
689 *pp_msg_str = NULL;
692 goto done;
695 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
696 /* the entry already existed */
697 local_flags &= ~LOCAL_ADD_USER;
700 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
701 ret = asprintf(pp_err_str,
702 "Failed to find entry for user %s.\n",
703 user_name);
704 if (ret < 0) {
705 *pp_err_str = NULL;
707 result = NT_STATUS_NO_SUCH_USER;
708 goto done;
711 /* First thing add the new user if we are required to do so */
712 if (local_flags & LOCAL_ADD_USER) {
714 if (local_flags & LOCAL_TRUST_ACCOUNT) {
715 acb = ACB_WSTRUST;
716 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
717 acb = ACB_DOMTRUST;
718 } else {
719 acb = ACB_NORMAL;
722 result = pdb_create_user(tosctx, user_name, acb, &rid);
723 if (!NT_STATUS_IS_OK(result)) {
724 ret = asprintf(pp_err_str,
725 "Failed to add entry for user %s.\n",
726 user_name);
727 if (ret < 0) {
728 *pp_err_str = NULL;
730 result = NT_STATUS_UNSUCCESSFUL;
731 goto done;
734 sam_pass = samu_new(tosctx);
735 if (!sam_pass) {
736 result = NT_STATUS_NO_MEMORY;
737 goto done;
740 /* Now get back the smb passwd entry for this new user */
741 user_exists = pdb_getsampwnam(sam_pass, user_name);
742 if (!user_exists) {
743 ret = asprintf(pp_err_str,
744 "Failed to add entry for user %s.\n",
745 user_name);
746 if (ret < 0) {
747 *pp_err_str = NULL;
749 result = NT_STATUS_UNSUCCESSFUL;
750 goto done;
754 acb = pdb_get_acct_ctrl(sam_pass);
757 * We are root - just write the new password
758 * and the valid last change time.
760 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
761 acb |= ACB_PWNOTREQ;
762 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
763 ret = asprintf(pp_err_str,
764 "Failed to set 'no password required' "
765 "flag for user %s.\n", user_name);
766 if (ret < 0) {
767 *pp_err_str = NULL;
769 result = NT_STATUS_UNSUCCESSFUL;
770 goto done;
774 if (local_flags & LOCAL_SET_PASSWORD) {
776 * If we're dealing with setting a completely empty user account
777 * ie. One with a password of 'XXXX', but not set disabled (like
778 * an account created from scratch) then if the old password was
779 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
780 * We remove that as we're giving this user their first password
781 * and the decision hasn't really been made to disable them (ie.
782 * don't create them disabled). JRA.
784 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
785 (acb & ACB_DISABLED)) {
786 acb &= (~ACB_DISABLED);
787 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
788 ret = asprintf(pp_err_str,
789 "Failed to unset 'disabled' "
790 "flag for user %s.\n",
791 user_name);
792 if (ret < 0) {
793 *pp_err_str = NULL;
795 result = NT_STATUS_UNSUCCESSFUL;
796 goto done;
800 acb &= (~ACB_PWNOTREQ);
801 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
802 ret = asprintf(pp_err_str,
803 "Failed to unset 'no password required'"
804 " flag for user %s.\n", user_name);
805 if (ret < 0) {
806 *pp_err_str = NULL;
808 result = NT_STATUS_UNSUCCESSFUL;
809 goto done;
812 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
813 ret = asprintf(pp_err_str,
814 "Failed to set password for "
815 "user %s.\n", user_name);
816 if (ret < 0) {
817 *pp_err_str = NULL;
819 result = NT_STATUS_UNSUCCESSFUL;
820 goto done;
824 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
825 acb |= ACB_DISABLED;
826 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
827 ret = asprintf(pp_err_str,
828 "Failed to set 'disabled' flag for "
829 "user %s.\n", user_name);
830 if (ret < 0) {
831 *pp_err_str = NULL;
833 result = NT_STATUS_UNSUCCESSFUL;
834 goto done;
838 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
839 acb &= (~ACB_DISABLED);
840 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
841 ret = asprintf(pp_err_str,
842 "Failed to unset 'disabled' flag for "
843 "user %s.\n", user_name);
844 if (ret < 0) {
845 *pp_err_str = NULL;
847 result = NT_STATUS_UNSUCCESSFUL;
848 goto done;
852 /* now commit changes if any */
853 result = pdb_update_sam_account(sam_pass);
854 if (!NT_STATUS_IS_OK(result)) {
855 ret = asprintf(pp_err_str,
856 "Failed to modify entry for user %s.\n",
857 user_name);
858 if (ret < 0) {
859 *pp_err_str = NULL;
861 goto done;
864 if (local_flags & LOCAL_ADD_USER) {
865 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
866 } else if (local_flags & LOCAL_DISABLE_USER) {
867 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
868 } else if (local_flags & LOCAL_ENABLE_USER) {
869 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
870 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
871 ret = asprintf(pp_msg_str,
872 "User %s password set to none.\n", user_name);
875 if (ret < 0) {
876 *pp_msg_str = NULL;
879 result = NT_STATUS_OK;
881 done:
882 TALLOC_FREE(sam_pass);
883 return result;
886 /**********************************************************************
887 Marshall/unmarshall struct samu structs.
888 *********************************************************************/
890 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
891 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
892 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
893 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
894 /* nothing changed between V3 and V4 */
896 /*********************************************************************
897 *********************************************************************/
899 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
902 /* times are stored as 32bit integer
903 take care on system with 64bit wide time_t
904 --SSS */
905 uint32 logon_time,
906 logoff_time,
907 kickoff_time,
908 pass_last_set_time,
909 pass_can_change_time,
910 pass_must_change_time;
911 char *username = NULL;
912 char *domain = NULL;
913 char *nt_username = NULL;
914 char *dir_drive = NULL;
915 char *unknown_str = NULL;
916 char *munged_dial = NULL;
917 char *fullname = NULL;
918 char *homedir = NULL;
919 char *logon_script = NULL;
920 char *profile_path = NULL;
921 char *acct_desc = NULL;
922 char *workstations = NULL;
923 uint32 username_len, domain_len, nt_username_len,
924 dir_drive_len, unknown_str_len, munged_dial_len,
925 fullname_len, homedir_len, logon_script_len,
926 profile_path_len, acct_desc_len, workstations_len;
928 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
929 uint16 acct_ctrl, logon_divs;
930 uint16 bad_password_count, logon_count;
931 uint8 *hours = NULL;
932 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
933 uint32 len = 0;
934 uint32 lm_pw_len, nt_pw_len, hourslen;
935 bool ret = True;
937 if(sampass == NULL || buf == NULL) {
938 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
939 return False;
942 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
944 /* unpack the buffer into variables */
945 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
946 &logon_time, /* d */
947 &logoff_time, /* d */
948 &kickoff_time, /* d */
949 &pass_last_set_time, /* d */
950 &pass_can_change_time, /* d */
951 &pass_must_change_time, /* d */
952 &username_len, &username, /* B */
953 &domain_len, &domain, /* B */
954 &nt_username_len, &nt_username, /* B */
955 &fullname_len, &fullname, /* B */
956 &homedir_len, &homedir, /* B */
957 &dir_drive_len, &dir_drive, /* B */
958 &logon_script_len, &logon_script, /* B */
959 &profile_path_len, &profile_path, /* B */
960 &acct_desc_len, &acct_desc, /* B */
961 &workstations_len, &workstations, /* B */
962 &unknown_str_len, &unknown_str, /* B */
963 &munged_dial_len, &munged_dial, /* B */
964 &user_rid, /* d */
965 &group_rid, /* d */
966 &lm_pw_len, &lm_pw_ptr, /* B */
967 &nt_pw_len, &nt_pw_ptr, /* B */
968 &acct_ctrl, /* w */
969 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
970 &logon_divs, /* w */
971 &hours_len, /* d */
972 &hourslen, &hours, /* B */
973 &bad_password_count, /* w */
974 &logon_count, /* w */
975 &unknown_6); /* d */
977 if (len == (uint32) -1) {
978 ret = False;
979 goto done;
982 pdb_set_logon_time(sampass, logon_time, PDB_SET);
983 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
984 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
985 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
986 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
987 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
989 pdb_set_username(sampass, username, PDB_SET);
990 pdb_set_domain(sampass, domain, PDB_SET);
991 pdb_set_nt_username(sampass, nt_username, PDB_SET);
992 pdb_set_fullname(sampass, fullname, PDB_SET);
994 if (homedir) {
995 pdb_set_homedir(sampass, homedir, PDB_SET);
997 else {
998 pdb_set_homedir(sampass,
999 talloc_sub_basic(sampass, username, domain,
1000 lp_logon_home()),
1001 PDB_DEFAULT);
1004 if (dir_drive)
1005 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1006 else {
1007 pdb_set_dir_drive(sampass,
1008 talloc_sub_basic(sampass, username, domain,
1009 lp_logon_drive()),
1010 PDB_DEFAULT);
1013 if (logon_script)
1014 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1015 else {
1016 pdb_set_logon_script(sampass,
1017 talloc_sub_basic(sampass, username, domain,
1018 lp_logon_script()),
1019 PDB_DEFAULT);
1022 if (profile_path) {
1023 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1024 } else {
1025 pdb_set_profile_path(sampass,
1026 talloc_sub_basic(sampass, username, domain,
1027 lp_logon_path()),
1028 PDB_DEFAULT);
1031 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1032 pdb_set_workstations(sampass, workstations, PDB_SET);
1033 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1035 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1036 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1037 ret = False;
1038 goto done;
1042 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1043 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1044 ret = False;
1045 goto done;
1049 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1050 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1051 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1052 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1053 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1054 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1055 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1056 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1057 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1058 pdb_set_hours(sampass, hours, PDB_SET);
1060 done:
1062 SAFE_FREE(username);
1063 SAFE_FREE(domain);
1064 SAFE_FREE(nt_username);
1065 SAFE_FREE(fullname);
1066 SAFE_FREE(homedir);
1067 SAFE_FREE(dir_drive);
1068 SAFE_FREE(logon_script);
1069 SAFE_FREE(profile_path);
1070 SAFE_FREE(acct_desc);
1071 SAFE_FREE(workstations);
1072 SAFE_FREE(munged_dial);
1073 SAFE_FREE(unknown_str);
1074 SAFE_FREE(lm_pw_ptr);
1075 SAFE_FREE(nt_pw_ptr);
1076 SAFE_FREE(hours);
1078 return ret;
1081 /*********************************************************************
1082 *********************************************************************/
1084 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1087 /* times are stored as 32bit integer
1088 take care on system with 64bit wide time_t
1089 --SSS */
1090 uint32 logon_time,
1091 logoff_time,
1092 kickoff_time,
1093 bad_password_time,
1094 pass_last_set_time,
1095 pass_can_change_time,
1096 pass_must_change_time;
1097 char *username = NULL;
1098 char *domain = NULL;
1099 char *nt_username = NULL;
1100 char *dir_drive = NULL;
1101 char *unknown_str = NULL;
1102 char *munged_dial = NULL;
1103 char *fullname = NULL;
1104 char *homedir = NULL;
1105 char *logon_script = NULL;
1106 char *profile_path = NULL;
1107 char *acct_desc = NULL;
1108 char *workstations = NULL;
1109 uint32 username_len, domain_len, nt_username_len,
1110 dir_drive_len, unknown_str_len, munged_dial_len,
1111 fullname_len, homedir_len, logon_script_len,
1112 profile_path_len, acct_desc_len, workstations_len;
1114 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1115 uint16 acct_ctrl, logon_divs;
1116 uint16 bad_password_count, logon_count;
1117 uint8 *hours = NULL;
1118 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1119 uint32 len = 0;
1120 uint32 lm_pw_len, nt_pw_len, hourslen;
1121 bool ret = True;
1123 if(sampass == NULL || buf == NULL) {
1124 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1125 return False;
1128 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1130 /* unpack the buffer into variables */
1131 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1132 &logon_time, /* d */
1133 &logoff_time, /* d */
1134 &kickoff_time, /* d */
1135 /* Change from V0 is addition of bad_password_time field. */
1136 &bad_password_time, /* d */
1137 &pass_last_set_time, /* d */
1138 &pass_can_change_time, /* d */
1139 &pass_must_change_time, /* d */
1140 &username_len, &username, /* B */
1141 &domain_len, &domain, /* B */
1142 &nt_username_len, &nt_username, /* B */
1143 &fullname_len, &fullname, /* B */
1144 &homedir_len, &homedir, /* B */
1145 &dir_drive_len, &dir_drive, /* B */
1146 &logon_script_len, &logon_script, /* B */
1147 &profile_path_len, &profile_path, /* B */
1148 &acct_desc_len, &acct_desc, /* B */
1149 &workstations_len, &workstations, /* B */
1150 &unknown_str_len, &unknown_str, /* B */
1151 &munged_dial_len, &munged_dial, /* B */
1152 &user_rid, /* d */
1153 &group_rid, /* d */
1154 &lm_pw_len, &lm_pw_ptr, /* B */
1155 &nt_pw_len, &nt_pw_ptr, /* B */
1156 &acct_ctrl, /* w */
1157 &remove_me, /* d */
1158 &logon_divs, /* w */
1159 &hours_len, /* d */
1160 &hourslen, &hours, /* B */
1161 &bad_password_count, /* w */
1162 &logon_count, /* w */
1163 &unknown_6); /* d */
1165 if (len == (uint32) -1) {
1166 ret = False;
1167 goto done;
1170 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1171 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1172 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1174 /* Change from V0 is addition of bad_password_time field. */
1175 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1176 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1177 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1178 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1180 pdb_set_username(sampass, username, PDB_SET);
1181 pdb_set_domain(sampass, domain, PDB_SET);
1182 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1183 pdb_set_fullname(sampass, fullname, PDB_SET);
1185 if (homedir) {
1186 pdb_set_homedir(sampass, homedir, PDB_SET);
1188 else {
1189 pdb_set_homedir(sampass,
1190 talloc_sub_basic(sampass, username, domain,
1191 lp_logon_home()),
1192 PDB_DEFAULT);
1195 if (dir_drive)
1196 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1197 else {
1198 pdb_set_dir_drive(sampass,
1199 talloc_sub_basic(sampass, username, domain,
1200 lp_logon_drive()),
1201 PDB_DEFAULT);
1204 if (logon_script)
1205 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1206 else {
1207 pdb_set_logon_script(sampass,
1208 talloc_sub_basic(sampass, username, domain,
1209 lp_logon_script()),
1210 PDB_DEFAULT);
1213 if (profile_path) {
1214 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1215 } else {
1216 pdb_set_profile_path(sampass,
1217 talloc_sub_basic(sampass, username, domain,
1218 lp_logon_path()),
1219 PDB_DEFAULT);
1222 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1223 pdb_set_workstations(sampass, workstations, PDB_SET);
1224 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1226 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1227 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1228 ret = False;
1229 goto done;
1233 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1234 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1235 ret = False;
1236 goto done;
1240 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1242 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1243 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1244 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1245 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1246 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1247 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1248 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1249 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1250 pdb_set_hours(sampass, hours, PDB_SET);
1252 done:
1254 SAFE_FREE(username);
1255 SAFE_FREE(domain);
1256 SAFE_FREE(nt_username);
1257 SAFE_FREE(fullname);
1258 SAFE_FREE(homedir);
1259 SAFE_FREE(dir_drive);
1260 SAFE_FREE(logon_script);
1261 SAFE_FREE(profile_path);
1262 SAFE_FREE(acct_desc);
1263 SAFE_FREE(workstations);
1264 SAFE_FREE(munged_dial);
1265 SAFE_FREE(unknown_str);
1266 SAFE_FREE(lm_pw_ptr);
1267 SAFE_FREE(nt_pw_ptr);
1268 SAFE_FREE(hours);
1270 return ret;
1273 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1276 /* times are stored as 32bit integer
1277 take care on system with 64bit wide time_t
1278 --SSS */
1279 uint32 logon_time,
1280 logoff_time,
1281 kickoff_time,
1282 bad_password_time,
1283 pass_last_set_time,
1284 pass_can_change_time,
1285 pass_must_change_time;
1286 char *username = NULL;
1287 char *domain = NULL;
1288 char *nt_username = NULL;
1289 char *dir_drive = NULL;
1290 char *unknown_str = NULL;
1291 char *munged_dial = NULL;
1292 char *fullname = NULL;
1293 char *homedir = NULL;
1294 char *logon_script = NULL;
1295 char *profile_path = NULL;
1296 char *acct_desc = NULL;
1297 char *workstations = NULL;
1298 uint32 username_len, domain_len, nt_username_len,
1299 dir_drive_len, unknown_str_len, munged_dial_len,
1300 fullname_len, homedir_len, logon_script_len,
1301 profile_path_len, acct_desc_len, workstations_len;
1303 uint32 user_rid, group_rid, hours_len, unknown_6;
1304 uint16 acct_ctrl, logon_divs;
1305 uint16 bad_password_count, logon_count;
1306 uint8 *hours = NULL;
1307 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1308 uint32 len = 0;
1309 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1310 uint32 pwHistLen = 0;
1311 bool ret = True;
1312 fstring tmp_string;
1313 bool expand_explicit = lp_passdb_expand_explicit();
1315 if(sampass == NULL || buf == NULL) {
1316 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1317 return False;
1320 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1322 /* unpack the buffer into variables */
1323 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1324 &logon_time, /* d */
1325 &logoff_time, /* d */
1326 &kickoff_time, /* d */
1327 &bad_password_time, /* d */
1328 &pass_last_set_time, /* d */
1329 &pass_can_change_time, /* d */
1330 &pass_must_change_time, /* d */
1331 &username_len, &username, /* B */
1332 &domain_len, &domain, /* B */
1333 &nt_username_len, &nt_username, /* B */
1334 &fullname_len, &fullname, /* B */
1335 &homedir_len, &homedir, /* B */
1336 &dir_drive_len, &dir_drive, /* B */
1337 &logon_script_len, &logon_script, /* B */
1338 &profile_path_len, &profile_path, /* B */
1339 &acct_desc_len, &acct_desc, /* B */
1340 &workstations_len, &workstations, /* B */
1341 &unknown_str_len, &unknown_str, /* B */
1342 &munged_dial_len, &munged_dial, /* B */
1343 &user_rid, /* d */
1344 &group_rid, /* d */
1345 &lm_pw_len, &lm_pw_ptr, /* B */
1346 &nt_pw_len, &nt_pw_ptr, /* B */
1347 /* Change from V1 is addition of password history field. */
1348 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1349 &acct_ctrl, /* w */
1350 /* Also "remove_me" field was removed. */
1351 &logon_divs, /* w */
1352 &hours_len, /* d */
1353 &hourslen, &hours, /* B */
1354 &bad_password_count, /* w */
1355 &logon_count, /* w */
1356 &unknown_6); /* d */
1358 if (len == (uint32) -1) {
1359 ret = False;
1360 goto done;
1363 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1364 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1365 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1366 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1367 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1368 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1369 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1371 pdb_set_username(sampass, username, PDB_SET);
1372 pdb_set_domain(sampass, domain, PDB_SET);
1373 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1374 pdb_set_fullname(sampass, fullname, PDB_SET);
1376 if (homedir) {
1377 fstrcpy( tmp_string, homedir );
1378 if (expand_explicit) {
1379 standard_sub_basic( username, domain, tmp_string,
1380 sizeof(tmp_string) );
1382 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1384 else {
1385 pdb_set_homedir(sampass,
1386 talloc_sub_basic(sampass, username, domain,
1387 lp_logon_home()),
1388 PDB_DEFAULT);
1391 if (dir_drive)
1392 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1393 else
1394 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1396 if (logon_script) {
1397 fstrcpy( tmp_string, logon_script );
1398 if (expand_explicit) {
1399 standard_sub_basic( username, domain, tmp_string,
1400 sizeof(tmp_string) );
1402 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1404 else {
1405 pdb_set_logon_script(sampass,
1406 talloc_sub_basic(sampass, username, domain,
1407 lp_logon_script()),
1408 PDB_DEFAULT);
1411 if (profile_path) {
1412 fstrcpy( tmp_string, profile_path );
1413 if (expand_explicit) {
1414 standard_sub_basic( username, domain, tmp_string,
1415 sizeof(tmp_string) );
1417 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1419 else {
1420 pdb_set_profile_path(sampass,
1421 talloc_sub_basic(sampass, username, domain,
1422 lp_logon_path()),
1423 PDB_DEFAULT);
1426 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1427 pdb_set_workstations(sampass, workstations, PDB_SET);
1428 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1430 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1431 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1432 ret = False;
1433 goto done;
1437 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1438 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1439 ret = False;
1440 goto done;
1444 /* Change from V1 is addition of password history field. */
1445 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1446 if (pwHistLen) {
1447 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1448 if (!pw_hist) {
1449 ret = False;
1450 goto done;
1452 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1453 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1454 int i;
1455 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1456 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1457 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1458 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1459 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1460 PW_HISTORY_ENTRY_LEN);
1463 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1464 SAFE_FREE(pw_hist);
1465 ret = False;
1466 goto done;
1468 SAFE_FREE(pw_hist);
1469 } else {
1470 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1473 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1474 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1475 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1476 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1477 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1478 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1479 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1480 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1481 pdb_set_hours(sampass, hours, PDB_SET);
1483 done:
1485 SAFE_FREE(username);
1486 SAFE_FREE(domain);
1487 SAFE_FREE(nt_username);
1488 SAFE_FREE(fullname);
1489 SAFE_FREE(homedir);
1490 SAFE_FREE(dir_drive);
1491 SAFE_FREE(logon_script);
1492 SAFE_FREE(profile_path);
1493 SAFE_FREE(acct_desc);
1494 SAFE_FREE(workstations);
1495 SAFE_FREE(munged_dial);
1496 SAFE_FREE(unknown_str);
1497 SAFE_FREE(lm_pw_ptr);
1498 SAFE_FREE(nt_pw_ptr);
1499 SAFE_FREE(nt_pw_hist_ptr);
1500 SAFE_FREE(hours);
1502 return ret;
1505 /*********************************************************************
1506 *********************************************************************/
1508 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1511 /* times are stored as 32bit integer
1512 take care on system with 64bit wide time_t
1513 --SSS */
1514 uint32 logon_time,
1515 logoff_time,
1516 kickoff_time,
1517 bad_password_time,
1518 pass_last_set_time,
1519 pass_can_change_time,
1520 pass_must_change_time;
1521 char *username = NULL;
1522 char *domain = NULL;
1523 char *nt_username = NULL;
1524 char *dir_drive = NULL;
1525 char *unknown_str = NULL;
1526 char *munged_dial = NULL;
1527 char *fullname = NULL;
1528 char *homedir = NULL;
1529 char *logon_script = NULL;
1530 char *profile_path = NULL;
1531 char *acct_desc = NULL;
1532 char *workstations = NULL;
1533 uint32 username_len, domain_len, nt_username_len,
1534 dir_drive_len, unknown_str_len, munged_dial_len,
1535 fullname_len, homedir_len, logon_script_len,
1536 profile_path_len, acct_desc_len, workstations_len;
1538 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1539 uint16 logon_divs;
1540 uint16 bad_password_count, logon_count;
1541 uint8 *hours = NULL;
1542 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1543 uint32 len = 0;
1544 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1545 uint32 pwHistLen = 0;
1546 bool ret = True;
1547 fstring tmp_string;
1548 bool expand_explicit = lp_passdb_expand_explicit();
1550 if(sampass == NULL || buf == NULL) {
1551 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1552 return False;
1555 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1557 /* unpack the buffer into variables */
1558 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1559 &logon_time, /* d */
1560 &logoff_time, /* d */
1561 &kickoff_time, /* d */
1562 &bad_password_time, /* d */
1563 &pass_last_set_time, /* d */
1564 &pass_can_change_time, /* d */
1565 &pass_must_change_time, /* d */
1566 &username_len, &username, /* B */
1567 &domain_len, &domain, /* B */
1568 &nt_username_len, &nt_username, /* B */
1569 &fullname_len, &fullname, /* B */
1570 &homedir_len, &homedir, /* B */
1571 &dir_drive_len, &dir_drive, /* B */
1572 &logon_script_len, &logon_script, /* B */
1573 &profile_path_len, &profile_path, /* B */
1574 &acct_desc_len, &acct_desc, /* B */
1575 &workstations_len, &workstations, /* B */
1576 &unknown_str_len, &unknown_str, /* B */
1577 &munged_dial_len, &munged_dial, /* B */
1578 &user_rid, /* d */
1579 &group_rid, /* d */
1580 &lm_pw_len, &lm_pw_ptr, /* B */
1581 &nt_pw_len, &nt_pw_ptr, /* B */
1582 /* Change from V1 is addition of password history field. */
1583 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1584 /* Change from V2 is the uint32 acb_mask */
1585 &acct_ctrl, /* d */
1586 /* Also "remove_me" field was removed. */
1587 &logon_divs, /* w */
1588 &hours_len, /* d */
1589 &hourslen, &hours, /* B */
1590 &bad_password_count, /* w */
1591 &logon_count, /* w */
1592 &unknown_6); /* d */
1594 if (len == (uint32) -1) {
1595 ret = False;
1596 goto done;
1599 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1600 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1601 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1602 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1603 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1604 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1605 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1607 pdb_set_username(sampass, username, PDB_SET);
1608 pdb_set_domain(sampass, domain, PDB_SET);
1609 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1610 pdb_set_fullname(sampass, fullname, PDB_SET);
1612 if (homedir) {
1613 fstrcpy( tmp_string, homedir );
1614 if (expand_explicit) {
1615 standard_sub_basic( username, domain, tmp_string,
1616 sizeof(tmp_string) );
1618 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1620 else {
1621 pdb_set_homedir(sampass,
1622 talloc_sub_basic(sampass, username, domain,
1623 lp_logon_home()),
1624 PDB_DEFAULT);
1627 if (dir_drive)
1628 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1629 else
1630 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1632 if (logon_script) {
1633 fstrcpy( tmp_string, logon_script );
1634 if (expand_explicit) {
1635 standard_sub_basic( username, domain, tmp_string,
1636 sizeof(tmp_string) );
1638 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1640 else {
1641 pdb_set_logon_script(sampass,
1642 talloc_sub_basic(sampass, username, domain,
1643 lp_logon_script()),
1644 PDB_DEFAULT);
1647 if (profile_path) {
1648 fstrcpy( tmp_string, profile_path );
1649 if (expand_explicit) {
1650 standard_sub_basic( username, domain, tmp_string,
1651 sizeof(tmp_string) );
1653 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1655 else {
1656 pdb_set_profile_path(sampass,
1657 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1658 PDB_DEFAULT);
1661 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1662 pdb_set_workstations(sampass, workstations, PDB_SET);
1663 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1665 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1666 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1667 ret = False;
1668 goto done;
1672 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1673 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1674 ret = False;
1675 goto done;
1679 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1680 if (pwHistLen) {
1681 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1682 if (!pw_hist) {
1683 ret = False;
1684 goto done;
1686 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1687 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1688 int i;
1689 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1690 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1691 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1692 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1693 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1694 PW_HISTORY_ENTRY_LEN);
1697 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1698 SAFE_FREE(pw_hist);
1699 ret = False;
1700 goto done;
1702 SAFE_FREE(pw_hist);
1703 } else {
1704 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1707 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1708 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1709 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1710 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1711 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1712 /* Change from V2 is the uint32 acct_ctrl */
1713 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1714 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1715 pdb_set_hours(sampass, hours, PDB_SET);
1717 done:
1719 SAFE_FREE(username);
1720 SAFE_FREE(domain);
1721 SAFE_FREE(nt_username);
1722 SAFE_FREE(fullname);
1723 SAFE_FREE(homedir);
1724 SAFE_FREE(dir_drive);
1725 SAFE_FREE(logon_script);
1726 SAFE_FREE(profile_path);
1727 SAFE_FREE(acct_desc);
1728 SAFE_FREE(workstations);
1729 SAFE_FREE(munged_dial);
1730 SAFE_FREE(unknown_str);
1731 SAFE_FREE(lm_pw_ptr);
1732 SAFE_FREE(nt_pw_ptr);
1733 SAFE_FREE(nt_pw_hist_ptr);
1734 SAFE_FREE(hours);
1736 return ret;
1739 /*********************************************************************
1740 *********************************************************************/
1742 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1744 size_t len, buflen;
1746 /* times are stored as 32bit integer
1747 take care on system with 64bit wide time_t
1748 --SSS */
1749 uint32 logon_time,
1750 logoff_time,
1751 kickoff_time,
1752 bad_password_time,
1753 pass_last_set_time,
1754 pass_can_change_time,
1755 pass_must_change_time;
1757 uint32 user_rid, group_rid;
1759 const char *username;
1760 const char *domain;
1761 const char *nt_username;
1762 const char *dir_drive;
1763 const char *unknown_str;
1764 const char *munged_dial;
1765 const char *fullname;
1766 const char *homedir;
1767 const char *logon_script;
1768 const char *profile_path;
1769 const char *acct_desc;
1770 const char *workstations;
1771 uint32 username_len, domain_len, nt_username_len,
1772 dir_drive_len, unknown_str_len, munged_dial_len,
1773 fullname_len, homedir_len, logon_script_len,
1774 profile_path_len, acct_desc_len, workstations_len;
1776 const uint8 *lm_pw;
1777 const uint8 *nt_pw;
1778 const uint8 *nt_pw_hist;
1779 uint32 lm_pw_len = 16;
1780 uint32 nt_pw_len = 16;
1781 uint32 nt_pw_hist_len;
1782 uint32 pwHistLen = 0;
1784 *buf = NULL;
1785 buflen = 0;
1787 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1788 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1789 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1790 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1791 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1792 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1793 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1795 user_rid = pdb_get_user_rid(sampass);
1796 group_rid = pdb_get_group_rid(sampass);
1798 username = pdb_get_username(sampass);
1799 if (username) {
1800 username_len = strlen(username) +1;
1801 } else {
1802 username_len = 0;
1805 domain = pdb_get_domain(sampass);
1806 if (domain) {
1807 domain_len = strlen(domain) +1;
1808 } else {
1809 domain_len = 0;
1812 nt_username = pdb_get_nt_username(sampass);
1813 if (nt_username) {
1814 nt_username_len = strlen(nt_username) +1;
1815 } else {
1816 nt_username_len = 0;
1819 fullname = pdb_get_fullname(sampass);
1820 if (fullname) {
1821 fullname_len = strlen(fullname) +1;
1822 } else {
1823 fullname_len = 0;
1827 * Only updates fields which have been set (not defaults from smb.conf)
1830 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1831 dir_drive = pdb_get_dir_drive(sampass);
1832 } else {
1833 dir_drive = NULL;
1835 if (dir_drive) {
1836 dir_drive_len = strlen(dir_drive) +1;
1837 } else {
1838 dir_drive_len = 0;
1841 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1842 homedir = pdb_get_homedir(sampass);
1843 } else {
1844 homedir = NULL;
1846 if (homedir) {
1847 homedir_len = strlen(homedir) +1;
1848 } else {
1849 homedir_len = 0;
1852 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1853 logon_script = pdb_get_logon_script(sampass);
1854 } else {
1855 logon_script = NULL;
1857 if (logon_script) {
1858 logon_script_len = strlen(logon_script) +1;
1859 } else {
1860 logon_script_len = 0;
1863 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1864 profile_path = pdb_get_profile_path(sampass);
1865 } else {
1866 profile_path = NULL;
1868 if (profile_path) {
1869 profile_path_len = strlen(profile_path) +1;
1870 } else {
1871 profile_path_len = 0;
1874 lm_pw = pdb_get_lanman_passwd(sampass);
1875 if (!lm_pw) {
1876 lm_pw_len = 0;
1879 nt_pw = pdb_get_nt_passwd(sampass);
1880 if (!nt_pw) {
1881 nt_pw_len = 0;
1884 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1885 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1886 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1887 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1888 } else {
1889 nt_pw_hist_len = 0;
1892 acct_desc = pdb_get_acct_desc(sampass);
1893 if (acct_desc) {
1894 acct_desc_len = strlen(acct_desc) +1;
1895 } else {
1896 acct_desc_len = 0;
1899 workstations = pdb_get_workstations(sampass);
1900 if (workstations) {
1901 workstations_len = strlen(workstations) +1;
1902 } else {
1903 workstations_len = 0;
1906 unknown_str = NULL;
1907 unknown_str_len = 0;
1909 munged_dial = pdb_get_munged_dial(sampass);
1910 if (munged_dial) {
1911 munged_dial_len = strlen(munged_dial) +1;
1912 } else {
1913 munged_dial_len = 0;
1916 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1918 /* one time to get the size needed */
1919 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1920 logon_time, /* d */
1921 logoff_time, /* d */
1922 kickoff_time, /* d */
1923 bad_password_time, /* d */
1924 pass_last_set_time, /* d */
1925 pass_can_change_time, /* d */
1926 pass_must_change_time, /* d */
1927 username_len, username, /* B */
1928 domain_len, domain, /* B */
1929 nt_username_len, nt_username, /* B */
1930 fullname_len, fullname, /* B */
1931 homedir_len, homedir, /* B */
1932 dir_drive_len, dir_drive, /* B */
1933 logon_script_len, logon_script, /* B */
1934 profile_path_len, profile_path, /* B */
1935 acct_desc_len, acct_desc, /* B */
1936 workstations_len, workstations, /* B */
1937 unknown_str_len, unknown_str, /* B */
1938 munged_dial_len, munged_dial, /* B */
1939 user_rid, /* d */
1940 group_rid, /* d */
1941 lm_pw_len, lm_pw, /* B */
1942 nt_pw_len, nt_pw, /* B */
1943 nt_pw_hist_len, nt_pw_hist, /* B */
1944 pdb_get_acct_ctrl(sampass), /* d */
1945 pdb_get_logon_divs(sampass), /* w */
1946 pdb_get_hours_len(sampass), /* d */
1947 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1948 pdb_get_bad_password_count(sampass), /* w */
1949 pdb_get_logon_count(sampass), /* w */
1950 pdb_get_unknown_6(sampass)); /* d */
1952 if (size_only) {
1953 return buflen;
1956 /* malloc the space needed */
1957 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1958 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1959 return (-1);
1962 /* now for the real call to tdb_pack() */
1963 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1964 logon_time, /* d */
1965 logoff_time, /* d */
1966 kickoff_time, /* d */
1967 bad_password_time, /* d */
1968 pass_last_set_time, /* d */
1969 pass_can_change_time, /* d */
1970 pass_must_change_time, /* d */
1971 username_len, username, /* B */
1972 domain_len, domain, /* B */
1973 nt_username_len, nt_username, /* B */
1974 fullname_len, fullname, /* B */
1975 homedir_len, homedir, /* B */
1976 dir_drive_len, dir_drive, /* B */
1977 logon_script_len, logon_script, /* B */
1978 profile_path_len, profile_path, /* B */
1979 acct_desc_len, acct_desc, /* B */
1980 workstations_len, workstations, /* B */
1981 unknown_str_len, unknown_str, /* B */
1982 munged_dial_len, munged_dial, /* B */
1983 user_rid, /* d */
1984 group_rid, /* d */
1985 lm_pw_len, lm_pw, /* B */
1986 nt_pw_len, nt_pw, /* B */
1987 nt_pw_hist_len, nt_pw_hist, /* B */
1988 pdb_get_acct_ctrl(sampass), /* d */
1989 pdb_get_logon_divs(sampass), /* w */
1990 pdb_get_hours_len(sampass), /* d */
1991 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1992 pdb_get_bad_password_count(sampass), /* w */
1993 pdb_get_logon_count(sampass), /* w */
1994 pdb_get_unknown_6(sampass)); /* d */
1996 /* check to make sure we got it correct */
1997 if (buflen != len) {
1998 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1999 (unsigned long)buflen, (unsigned long)len));
2000 /* error */
2001 SAFE_FREE (*buf);
2002 return (-1);
2005 return (buflen);
2008 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2010 /* nothing changed between V3 and V4 */
2011 return init_samu_from_buffer_v3(sampass, buf, buflen);
2014 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2016 /* nothing changed between V3 and V4 */
2017 return init_buffer_from_samu_v3(buf, sampass, size_only);
2020 /**********************************************************************
2021 Intialize a struct samu struct from a BYTE buffer of size len
2022 *********************************************************************/
2024 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2025 uint8 *buf, uint32 buflen)
2027 switch (level) {
2028 case SAMU_BUFFER_V0:
2029 return init_samu_from_buffer_v0(sampass, buf, buflen);
2030 case SAMU_BUFFER_V1:
2031 return init_samu_from_buffer_v1(sampass, buf, buflen);
2032 case SAMU_BUFFER_V2:
2033 return init_samu_from_buffer_v2(sampass, buf, buflen);
2034 case SAMU_BUFFER_V3:
2035 return init_samu_from_buffer_v3(sampass, buf, buflen);
2036 case SAMU_BUFFER_V4:
2037 return init_samu_from_buffer_v4(sampass, buf, buflen);
2040 return false;
2043 /**********************************************************************
2044 Intialize a BYTE buffer from a struct samu struct
2045 *********************************************************************/
2047 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2049 return init_buffer_from_samu_v4(buf, sampass, size_only);
2052 /*********************************************************************
2053 *********************************************************************/
2055 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2057 uint8 *buf = NULL;
2058 int len;
2060 len = init_buffer_from_samu(&buf, src, False);
2061 if (len == -1 || !buf) {
2062 SAFE_FREE(buf);
2063 return False;
2066 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2067 free(buf);
2068 return False;
2071 dst->methods = src->methods;
2073 if ( src->unix_pw ) {
2074 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2075 if (!dst->unix_pw) {
2076 free(buf);
2077 return False;
2081 free(buf);
2082 return True;
2085 /*********************************************************************
2086 Update the bad password count checking the AP_RESET_COUNT_TIME
2087 *********************************************************************/
2089 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2091 time_t LastBadPassword;
2092 uint16 BadPasswordCount;
2093 uint32 resettime;
2094 bool res;
2096 BadPasswordCount = pdb_get_bad_password_count(sampass);
2097 if (!BadPasswordCount) {
2098 DEBUG(9, ("No bad password attempts.\n"));
2099 return True;
2102 become_root();
2103 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
2104 unbecome_root();
2106 if (!res) {
2107 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2108 return False;
2111 /* First, check if there is a reset time to compare */
2112 if ((resettime == (uint32) -1) || (resettime == 0)) {
2113 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2114 return True;
2117 LastBadPassword = pdb_get_bad_password_time(sampass);
2118 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2119 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2120 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2121 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2122 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2123 if (updated) {
2124 *updated = True;
2128 return True;
2131 /*********************************************************************
2132 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
2133 *********************************************************************/
2135 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2137 uint32 duration;
2138 time_t LastBadPassword;
2139 bool res;
2141 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2142 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2143 pdb_get_username(sampass)));
2144 return True;
2147 become_root();
2148 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
2149 unbecome_root();
2151 if (!res) {
2152 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2153 return False;
2156 /* First, check if there is a duration to compare */
2157 if ((duration == (uint32) -1) || (duration == 0)) {
2158 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2159 return True;
2162 LastBadPassword = pdb_get_bad_password_time(sampass);
2163 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2164 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2166 if (LastBadPassword == (time_t)0) {
2167 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2168 "administratively locked out with no bad password "
2169 "time. Leaving locked out.\n",
2170 pdb_get_username(sampass) ));
2171 return True;
2174 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2175 pdb_set_acct_ctrl(sampass,
2176 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2177 PDB_CHANGED);
2178 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2179 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2180 if (updated) {
2181 *updated = True;
2185 return True;
2188 /*********************************************************************
2189 Increment the bad_password_count
2190 *********************************************************************/
2192 bool pdb_increment_bad_password_count(struct samu *sampass)
2194 uint32 account_policy_lockout;
2195 bool autolock_updated = False, badpw_updated = False;
2196 bool ret;
2198 /* Retrieve the account lockout policy */
2199 become_root();
2200 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2201 unbecome_root();
2202 if ( !ret ) {
2203 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2204 return False;
2207 /* If there is no policy, we don't need to continue checking */
2208 if (!account_policy_lockout) {
2209 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2210 return True;
2213 /* Check if the autolock needs to be cleared */
2214 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2215 return False;
2217 /* Check if the badpw count needs to be reset */
2218 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2219 return False;
2222 Ok, now we can assume that any resetting that needs to be
2223 done has been done, and just get on with incrementing
2224 and autolocking if necessary
2227 pdb_set_bad_password_count(sampass,
2228 pdb_get_bad_password_count(sampass)+1,
2229 PDB_CHANGED);
2230 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2233 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2234 return True;
2236 if (!pdb_set_acct_ctrl(sampass,
2237 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2238 PDB_CHANGED)) {
2239 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2240 return False;
2243 return True;
2246 bool is_dc_trusted_domain_situation(const char *domain_name)
2248 return IS_DC && !strequal(domain_name, lp_workgroup());
2251 /*******************************************************************
2252 Wrapper around retrieving the clear text trust account password.
2253 appropriate account name is stored in account_name.
2254 Caller must free password, but not account_name.
2255 *******************************************************************/
2257 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2258 const char **account_name, uint32 *channel)
2260 char *pwd;
2261 time_t last_set_time;
2263 /* if we are a DC and this is not our domain, then lookup an account
2264 * for the domain trust */
2266 if (is_dc_trusted_domain_situation(domain)) {
2267 if (!lp_allow_trusted_domains()) {
2268 return false;
2271 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2272 &last_set_time))
2274 DEBUG(0, ("get_trust_pw: could not fetch trust "
2275 "account password for trusted domain %s\n",
2276 domain));
2277 return false;
2280 if (channel != NULL) {
2281 *channel = SEC_CHAN_DOMAIN;
2284 if (account_name != NULL) {
2285 *account_name = lp_workgroup();
2288 return true;
2292 * Since we can only be member of one single domain, we are now
2293 * in a member situation:
2295 * - Either we are a DC (selfjoined) and the domain is our
2296 * own domain.
2297 * - Or we are on a member and the domain is our own or some
2298 * other (potentially trusted) domain.
2300 * In both cases, we can only get the machine account password
2301 * for our own domain to connect to our own dc. (For a member,
2302 * request to trusted domains are performed through our dc.)
2304 * So we simply use our own domain name to retrieve the
2305 * machine account passowrd and ignore the request domain here.
2308 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2310 if (pwd != NULL) {
2311 *ret_pwd = pwd;
2312 if (account_name != NULL) {
2313 *account_name = global_myname();
2316 return true;
2319 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2320 "account password for domain %s\n", domain));
2321 return false;
2324 /*******************************************************************
2325 Wrapper around retrieving the trust account password.
2326 appropriate account name is stored in account_name.
2327 *******************************************************************/
2329 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2330 const char **account_name, uint32 *channel)
2332 char *pwd = NULL;
2333 time_t last_set_time;
2335 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2336 E_md4hash(pwd, ret_pwd);
2337 SAFE_FREE(pwd);
2338 return true;
2339 } else if (is_dc_trusted_domain_situation(domain)) {
2340 return false;
2343 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2345 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2346 &last_set_time,
2347 channel))
2349 if (account_name != NULL) {
2350 *account_name = global_myname();
2353 return true;
2356 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2357 "password for domain %s\n", domain));
2358 return False;
2361 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2362 struct samu *pw)
2364 struct samr_LogonHours hours;
2365 const int units_per_week = 168;
2367 ZERO_STRUCT(hours);
2368 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2369 if (!hours.bits) {
2370 return hours;
2373 hours.units_per_week = units_per_week;
2374 memset(hours.bits, 0xFF, units_per_week);
2376 if (pdb_get_hours(pw)) {
2377 memcpy(hours.bits, pdb_get_hours(pw),
2378 MIN(pdb_get_hours_len(pw), units_per_week));
2381 return hours;