Fixed a compiler warning.
[Samba/nivanova.git] / source3 / passdb / passdb.c
blob0678181669d3e9259f2bc07650143359ed1f84bb
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_capabilities() & PDB_CAP_STORE_RIDS)) {
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 = -1;
654 *pp_err_str = NULL;
655 *pp_msg_str = NULL;
657 tosctx = talloc_tos();
659 sam_pass = samu_new(tosctx);
660 if (!sam_pass) {
661 result = NT_STATUS_NO_MEMORY;
662 goto done;
665 /* Get the smb passwd entry for this user */
666 user_exists = pdb_getsampwnam(sam_pass, user_name);
668 /* Check delete first, we don't need to do anything else if we
669 * are going to delete the acocunt */
670 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
672 result = pdb_delete_user(tosctx, sam_pass);
673 if (!NT_STATUS_IS_OK(result)) {
674 ret = asprintf(pp_err_str,
675 "Failed to delete entry for user %s.\n",
676 user_name);
677 if (ret < 0) {
678 *pp_err_str = NULL;
680 result = NT_STATUS_UNSUCCESSFUL;
681 } else {
682 ret = asprintf(pp_msg_str,
683 "Deleted user %s.\n",
684 user_name);
685 if (ret < 0) {
686 *pp_msg_str = NULL;
689 goto done;
692 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
693 /* the entry already existed */
694 local_flags &= ~LOCAL_ADD_USER;
697 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
698 ret = asprintf(pp_err_str,
699 "Failed to find entry for user %s.\n",
700 user_name);
701 if (ret < 0) {
702 *pp_err_str = NULL;
704 result = NT_STATUS_NO_SUCH_USER;
705 goto done;
708 /* First thing add the new user if we are required to do so */
709 if (local_flags & LOCAL_ADD_USER) {
711 if (local_flags & LOCAL_TRUST_ACCOUNT) {
712 acb = ACB_WSTRUST;
713 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
714 acb = ACB_DOMTRUST;
715 } else {
716 acb = ACB_NORMAL;
719 result = pdb_create_user(tosctx, user_name, acb, &rid);
720 if (!NT_STATUS_IS_OK(result)) {
721 ret = asprintf(pp_err_str,
722 "Failed to add entry for user %s.\n",
723 user_name);
724 if (ret < 0) {
725 *pp_err_str = NULL;
727 result = NT_STATUS_UNSUCCESSFUL;
728 goto done;
731 sam_pass = samu_new(tosctx);
732 if (!sam_pass) {
733 result = NT_STATUS_NO_MEMORY;
734 goto done;
737 /* Now get back the smb passwd entry for this new user */
738 user_exists = pdb_getsampwnam(sam_pass, user_name);
739 if (!user_exists) {
740 ret = asprintf(pp_err_str,
741 "Failed to add entry for user %s.\n",
742 user_name);
743 if (ret < 0) {
744 *pp_err_str = NULL;
746 result = NT_STATUS_UNSUCCESSFUL;
747 goto done;
751 acb = pdb_get_acct_ctrl(sam_pass);
754 * We are root - just write the new password
755 * and the valid last change time.
757 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
758 acb |= ACB_PWNOTREQ;
759 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
760 ret = asprintf(pp_err_str,
761 "Failed to set 'no password required' "
762 "flag for user %s.\n", user_name);
763 if (ret < 0) {
764 *pp_err_str = NULL;
766 result = NT_STATUS_UNSUCCESSFUL;
767 goto done;
771 if (local_flags & LOCAL_SET_PASSWORD) {
773 * If we're dealing with setting a completely empty user account
774 * ie. One with a password of 'XXXX', but not set disabled (like
775 * an account created from scratch) then if the old password was
776 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
777 * We remove that as we're giving this user their first password
778 * and the decision hasn't really been made to disable them (ie.
779 * don't create them disabled). JRA.
781 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
782 (acb & ACB_DISABLED)) {
783 acb &= (~ACB_DISABLED);
784 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
785 ret = asprintf(pp_err_str,
786 "Failed to unset 'disabled' "
787 "flag for user %s.\n",
788 user_name);
789 if (ret < 0) {
790 *pp_err_str = NULL;
792 result = NT_STATUS_UNSUCCESSFUL;
793 goto done;
797 acb &= (~ACB_PWNOTREQ);
798 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
799 ret = asprintf(pp_err_str,
800 "Failed to unset 'no password required'"
801 " flag for user %s.\n", user_name);
802 if (ret < 0) {
803 *pp_err_str = NULL;
805 result = NT_STATUS_UNSUCCESSFUL;
806 goto done;
809 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
810 ret = asprintf(pp_err_str,
811 "Failed to set password for "
812 "user %s.\n", user_name);
813 if (ret < 0) {
814 *pp_err_str = NULL;
816 result = NT_STATUS_UNSUCCESSFUL;
817 goto done;
821 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
822 acb |= ACB_DISABLED;
823 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
824 ret = asprintf(pp_err_str,
825 "Failed to set 'disabled' flag for "
826 "user %s.\n", user_name);
827 if (ret < 0) {
828 *pp_err_str = NULL;
830 result = NT_STATUS_UNSUCCESSFUL;
831 goto done;
835 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
836 acb &= (~ACB_DISABLED);
837 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
838 ret = asprintf(pp_err_str,
839 "Failed to unset 'disabled' flag for "
840 "user %s.\n", user_name);
841 if (ret < 0) {
842 *pp_err_str = NULL;
844 result = NT_STATUS_UNSUCCESSFUL;
845 goto done;
849 /* now commit changes if any */
850 result = pdb_update_sam_account(sam_pass);
851 if (!NT_STATUS_IS_OK(result)) {
852 ret = asprintf(pp_err_str,
853 "Failed to modify entry for user %s.\n",
854 user_name);
855 if (ret < 0) {
856 *pp_err_str = NULL;
858 goto done;
861 if (local_flags & LOCAL_ADD_USER) {
862 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
863 } else if (local_flags & LOCAL_DISABLE_USER) {
864 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
865 } else if (local_flags & LOCAL_ENABLE_USER) {
866 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
867 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
868 ret = asprintf(pp_msg_str,
869 "User %s password set to none.\n", user_name);
872 if (ret < 0) {
873 *pp_msg_str = NULL;
876 result = NT_STATUS_OK;
878 done:
879 TALLOC_FREE(sam_pass);
880 return result;
883 /**********************************************************************
884 Marshall/unmarshall struct samu structs.
885 *********************************************************************/
887 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
888 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
889 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
890 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
891 /* nothing changed between V3 and V4 */
893 /*********************************************************************
894 *********************************************************************/
896 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
899 /* times are stored as 32bit integer
900 take care on system with 64bit wide time_t
901 --SSS */
902 uint32 logon_time,
903 logoff_time,
904 kickoff_time,
905 pass_last_set_time,
906 pass_can_change_time,
907 pass_must_change_time;
908 char *username = NULL;
909 char *domain = NULL;
910 char *nt_username = NULL;
911 char *dir_drive = NULL;
912 char *unknown_str = NULL;
913 char *munged_dial = NULL;
914 char *fullname = NULL;
915 char *homedir = NULL;
916 char *logon_script = NULL;
917 char *profile_path = NULL;
918 char *acct_desc = NULL;
919 char *workstations = NULL;
920 uint32 username_len, domain_len, nt_username_len,
921 dir_drive_len, unknown_str_len, munged_dial_len,
922 fullname_len, homedir_len, logon_script_len,
923 profile_path_len, acct_desc_len, workstations_len;
925 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
926 uint16 acct_ctrl, logon_divs;
927 uint16 bad_password_count, logon_count;
928 uint8 *hours = NULL;
929 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
930 uint32 len = 0;
931 uint32 lm_pw_len, nt_pw_len, hourslen;
932 bool ret = True;
934 if(sampass == NULL || buf == NULL) {
935 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
936 return False;
939 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
941 /* unpack the buffer into variables */
942 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
943 &logon_time, /* d */
944 &logoff_time, /* d */
945 &kickoff_time, /* d */
946 &pass_last_set_time, /* d */
947 &pass_can_change_time, /* d */
948 &pass_must_change_time, /* d */
949 &username_len, &username, /* B */
950 &domain_len, &domain, /* B */
951 &nt_username_len, &nt_username, /* B */
952 &fullname_len, &fullname, /* B */
953 &homedir_len, &homedir, /* B */
954 &dir_drive_len, &dir_drive, /* B */
955 &logon_script_len, &logon_script, /* B */
956 &profile_path_len, &profile_path, /* B */
957 &acct_desc_len, &acct_desc, /* B */
958 &workstations_len, &workstations, /* B */
959 &unknown_str_len, &unknown_str, /* B */
960 &munged_dial_len, &munged_dial, /* B */
961 &user_rid, /* d */
962 &group_rid, /* d */
963 &lm_pw_len, &lm_pw_ptr, /* B */
964 &nt_pw_len, &nt_pw_ptr, /* B */
965 &acct_ctrl, /* w */
966 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
967 &logon_divs, /* w */
968 &hours_len, /* d */
969 &hourslen, &hours, /* B */
970 &bad_password_count, /* w */
971 &logon_count, /* w */
972 &unknown_6); /* d */
974 if (len == (uint32) -1) {
975 ret = False;
976 goto done;
979 pdb_set_logon_time(sampass, logon_time, PDB_SET);
980 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
981 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
982 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
983 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
984 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
986 pdb_set_username(sampass, username, PDB_SET);
987 pdb_set_domain(sampass, domain, PDB_SET);
988 pdb_set_nt_username(sampass, nt_username, PDB_SET);
989 pdb_set_fullname(sampass, fullname, PDB_SET);
991 if (homedir) {
992 pdb_set_homedir(sampass, homedir, PDB_SET);
994 else {
995 pdb_set_homedir(sampass,
996 talloc_sub_basic(sampass, username, domain,
997 lp_logon_home()),
998 PDB_DEFAULT);
1001 if (dir_drive)
1002 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1003 else {
1004 pdb_set_dir_drive(sampass,
1005 talloc_sub_basic(sampass, username, domain,
1006 lp_logon_drive()),
1007 PDB_DEFAULT);
1010 if (logon_script)
1011 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1012 else {
1013 pdb_set_logon_script(sampass,
1014 talloc_sub_basic(sampass, username, domain,
1015 lp_logon_script()),
1016 PDB_DEFAULT);
1019 if (profile_path) {
1020 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1021 } else {
1022 pdb_set_profile_path(sampass,
1023 talloc_sub_basic(sampass, username, domain,
1024 lp_logon_path()),
1025 PDB_DEFAULT);
1028 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1029 pdb_set_workstations(sampass, workstations, PDB_SET);
1030 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1032 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1033 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1034 ret = False;
1035 goto done;
1039 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1040 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1041 ret = False;
1042 goto done;
1046 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1047 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1048 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1049 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1050 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1051 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1052 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1053 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1054 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1055 pdb_set_hours(sampass, hours, PDB_SET);
1057 done:
1059 SAFE_FREE(username);
1060 SAFE_FREE(domain);
1061 SAFE_FREE(nt_username);
1062 SAFE_FREE(fullname);
1063 SAFE_FREE(homedir);
1064 SAFE_FREE(dir_drive);
1065 SAFE_FREE(logon_script);
1066 SAFE_FREE(profile_path);
1067 SAFE_FREE(acct_desc);
1068 SAFE_FREE(workstations);
1069 SAFE_FREE(munged_dial);
1070 SAFE_FREE(unknown_str);
1071 SAFE_FREE(lm_pw_ptr);
1072 SAFE_FREE(nt_pw_ptr);
1073 SAFE_FREE(hours);
1075 return ret;
1078 /*********************************************************************
1079 *********************************************************************/
1081 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1084 /* times are stored as 32bit integer
1085 take care on system with 64bit wide time_t
1086 --SSS */
1087 uint32 logon_time,
1088 logoff_time,
1089 kickoff_time,
1090 bad_password_time,
1091 pass_last_set_time,
1092 pass_can_change_time,
1093 pass_must_change_time;
1094 char *username = NULL;
1095 char *domain = NULL;
1096 char *nt_username = NULL;
1097 char *dir_drive = NULL;
1098 char *unknown_str = NULL;
1099 char *munged_dial = NULL;
1100 char *fullname = NULL;
1101 char *homedir = NULL;
1102 char *logon_script = NULL;
1103 char *profile_path = NULL;
1104 char *acct_desc = NULL;
1105 char *workstations = NULL;
1106 uint32 username_len, domain_len, nt_username_len,
1107 dir_drive_len, unknown_str_len, munged_dial_len,
1108 fullname_len, homedir_len, logon_script_len,
1109 profile_path_len, acct_desc_len, workstations_len;
1111 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1112 uint16 acct_ctrl, logon_divs;
1113 uint16 bad_password_count, logon_count;
1114 uint8 *hours = NULL;
1115 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1116 uint32 len = 0;
1117 uint32 lm_pw_len, nt_pw_len, hourslen;
1118 bool ret = True;
1120 if(sampass == NULL || buf == NULL) {
1121 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1122 return False;
1125 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1127 /* unpack the buffer into variables */
1128 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1129 &logon_time, /* d */
1130 &logoff_time, /* d */
1131 &kickoff_time, /* d */
1132 /* Change from V0 is addition of bad_password_time field. */
1133 &bad_password_time, /* d */
1134 &pass_last_set_time, /* d */
1135 &pass_can_change_time, /* d */
1136 &pass_must_change_time, /* d */
1137 &username_len, &username, /* B */
1138 &domain_len, &domain, /* B */
1139 &nt_username_len, &nt_username, /* B */
1140 &fullname_len, &fullname, /* B */
1141 &homedir_len, &homedir, /* B */
1142 &dir_drive_len, &dir_drive, /* B */
1143 &logon_script_len, &logon_script, /* B */
1144 &profile_path_len, &profile_path, /* B */
1145 &acct_desc_len, &acct_desc, /* B */
1146 &workstations_len, &workstations, /* B */
1147 &unknown_str_len, &unknown_str, /* B */
1148 &munged_dial_len, &munged_dial, /* B */
1149 &user_rid, /* d */
1150 &group_rid, /* d */
1151 &lm_pw_len, &lm_pw_ptr, /* B */
1152 &nt_pw_len, &nt_pw_ptr, /* B */
1153 &acct_ctrl, /* w */
1154 &remove_me, /* d */
1155 &logon_divs, /* w */
1156 &hours_len, /* d */
1157 &hourslen, &hours, /* B */
1158 &bad_password_count, /* w */
1159 &logon_count, /* w */
1160 &unknown_6); /* d */
1162 if (len == (uint32) -1) {
1163 ret = False;
1164 goto done;
1167 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1168 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1169 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1171 /* Change from V0 is addition of bad_password_time field. */
1172 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1173 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1174 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1175 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1177 pdb_set_username(sampass, username, PDB_SET);
1178 pdb_set_domain(sampass, domain, PDB_SET);
1179 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1180 pdb_set_fullname(sampass, fullname, PDB_SET);
1182 if (homedir) {
1183 pdb_set_homedir(sampass, homedir, PDB_SET);
1185 else {
1186 pdb_set_homedir(sampass,
1187 talloc_sub_basic(sampass, username, domain,
1188 lp_logon_home()),
1189 PDB_DEFAULT);
1192 if (dir_drive)
1193 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1194 else {
1195 pdb_set_dir_drive(sampass,
1196 talloc_sub_basic(sampass, username, domain,
1197 lp_logon_drive()),
1198 PDB_DEFAULT);
1201 if (logon_script)
1202 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1203 else {
1204 pdb_set_logon_script(sampass,
1205 talloc_sub_basic(sampass, username, domain,
1206 lp_logon_script()),
1207 PDB_DEFAULT);
1210 if (profile_path) {
1211 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1212 } else {
1213 pdb_set_profile_path(sampass,
1214 talloc_sub_basic(sampass, username, domain,
1215 lp_logon_path()),
1216 PDB_DEFAULT);
1219 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1220 pdb_set_workstations(sampass, workstations, PDB_SET);
1221 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1223 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1224 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1225 ret = False;
1226 goto done;
1230 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1231 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1232 ret = False;
1233 goto done;
1237 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1239 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1240 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1241 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1242 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1243 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1244 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1245 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1246 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1247 pdb_set_hours(sampass, hours, PDB_SET);
1249 done:
1251 SAFE_FREE(username);
1252 SAFE_FREE(domain);
1253 SAFE_FREE(nt_username);
1254 SAFE_FREE(fullname);
1255 SAFE_FREE(homedir);
1256 SAFE_FREE(dir_drive);
1257 SAFE_FREE(logon_script);
1258 SAFE_FREE(profile_path);
1259 SAFE_FREE(acct_desc);
1260 SAFE_FREE(workstations);
1261 SAFE_FREE(munged_dial);
1262 SAFE_FREE(unknown_str);
1263 SAFE_FREE(lm_pw_ptr);
1264 SAFE_FREE(nt_pw_ptr);
1265 SAFE_FREE(hours);
1267 return ret;
1270 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1273 /* times are stored as 32bit integer
1274 take care on system with 64bit wide time_t
1275 --SSS */
1276 uint32 logon_time,
1277 logoff_time,
1278 kickoff_time,
1279 bad_password_time,
1280 pass_last_set_time,
1281 pass_can_change_time,
1282 pass_must_change_time;
1283 char *username = NULL;
1284 char *domain = NULL;
1285 char *nt_username = NULL;
1286 char *dir_drive = NULL;
1287 char *unknown_str = NULL;
1288 char *munged_dial = NULL;
1289 char *fullname = NULL;
1290 char *homedir = NULL;
1291 char *logon_script = NULL;
1292 char *profile_path = NULL;
1293 char *acct_desc = NULL;
1294 char *workstations = NULL;
1295 uint32 username_len, domain_len, nt_username_len,
1296 dir_drive_len, unknown_str_len, munged_dial_len,
1297 fullname_len, homedir_len, logon_script_len,
1298 profile_path_len, acct_desc_len, workstations_len;
1300 uint32 user_rid, group_rid, hours_len, unknown_6;
1301 uint16 acct_ctrl, logon_divs;
1302 uint16 bad_password_count, logon_count;
1303 uint8 *hours = NULL;
1304 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1305 uint32 len = 0;
1306 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1307 uint32 pwHistLen = 0;
1308 bool ret = True;
1309 fstring tmp_string;
1310 bool expand_explicit = lp_passdb_expand_explicit();
1312 if(sampass == NULL || buf == NULL) {
1313 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1314 return False;
1317 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1319 /* unpack the buffer into variables */
1320 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1321 &logon_time, /* d */
1322 &logoff_time, /* d */
1323 &kickoff_time, /* d */
1324 &bad_password_time, /* d */
1325 &pass_last_set_time, /* d */
1326 &pass_can_change_time, /* d */
1327 &pass_must_change_time, /* d */
1328 &username_len, &username, /* B */
1329 &domain_len, &domain, /* B */
1330 &nt_username_len, &nt_username, /* B */
1331 &fullname_len, &fullname, /* B */
1332 &homedir_len, &homedir, /* B */
1333 &dir_drive_len, &dir_drive, /* B */
1334 &logon_script_len, &logon_script, /* B */
1335 &profile_path_len, &profile_path, /* B */
1336 &acct_desc_len, &acct_desc, /* B */
1337 &workstations_len, &workstations, /* B */
1338 &unknown_str_len, &unknown_str, /* B */
1339 &munged_dial_len, &munged_dial, /* B */
1340 &user_rid, /* d */
1341 &group_rid, /* d */
1342 &lm_pw_len, &lm_pw_ptr, /* B */
1343 &nt_pw_len, &nt_pw_ptr, /* B */
1344 /* Change from V1 is addition of password history field. */
1345 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1346 &acct_ctrl, /* w */
1347 /* Also "remove_me" field was removed. */
1348 &logon_divs, /* w */
1349 &hours_len, /* d */
1350 &hourslen, &hours, /* B */
1351 &bad_password_count, /* w */
1352 &logon_count, /* w */
1353 &unknown_6); /* d */
1355 if (len == (uint32) -1) {
1356 ret = False;
1357 goto done;
1360 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1361 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1362 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1363 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1364 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1365 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1366 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1368 pdb_set_username(sampass, username, PDB_SET);
1369 pdb_set_domain(sampass, domain, PDB_SET);
1370 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1371 pdb_set_fullname(sampass, fullname, PDB_SET);
1373 if (homedir) {
1374 fstrcpy( tmp_string, homedir );
1375 if (expand_explicit) {
1376 standard_sub_basic( username, domain, tmp_string,
1377 sizeof(tmp_string) );
1379 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1381 else {
1382 pdb_set_homedir(sampass,
1383 talloc_sub_basic(sampass, username, domain,
1384 lp_logon_home()),
1385 PDB_DEFAULT);
1388 if (dir_drive)
1389 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1390 else
1391 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1393 if (logon_script) {
1394 fstrcpy( tmp_string, logon_script );
1395 if (expand_explicit) {
1396 standard_sub_basic( username, domain, tmp_string,
1397 sizeof(tmp_string) );
1399 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1401 else {
1402 pdb_set_logon_script(sampass,
1403 talloc_sub_basic(sampass, username, domain,
1404 lp_logon_script()),
1405 PDB_DEFAULT);
1408 if (profile_path) {
1409 fstrcpy( tmp_string, profile_path );
1410 if (expand_explicit) {
1411 standard_sub_basic( username, domain, tmp_string,
1412 sizeof(tmp_string) );
1414 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1416 else {
1417 pdb_set_profile_path(sampass,
1418 talloc_sub_basic(sampass, username, domain,
1419 lp_logon_path()),
1420 PDB_DEFAULT);
1423 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1424 pdb_set_workstations(sampass, workstations, PDB_SET);
1425 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1427 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1428 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1429 ret = False;
1430 goto done;
1434 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1435 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1436 ret = False;
1437 goto done;
1441 /* Change from V1 is addition of password history field. */
1442 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1443 if (pwHistLen) {
1444 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1445 if (!pw_hist) {
1446 ret = False;
1447 goto done;
1449 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1450 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1451 int i;
1452 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1453 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1454 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1455 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1456 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1457 PW_HISTORY_ENTRY_LEN);
1460 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1461 SAFE_FREE(pw_hist);
1462 ret = False;
1463 goto done;
1465 SAFE_FREE(pw_hist);
1466 } else {
1467 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1470 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1471 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1472 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1473 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1474 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1475 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1476 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1477 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1478 pdb_set_hours(sampass, hours, PDB_SET);
1480 done:
1482 SAFE_FREE(username);
1483 SAFE_FREE(domain);
1484 SAFE_FREE(nt_username);
1485 SAFE_FREE(fullname);
1486 SAFE_FREE(homedir);
1487 SAFE_FREE(dir_drive);
1488 SAFE_FREE(logon_script);
1489 SAFE_FREE(profile_path);
1490 SAFE_FREE(acct_desc);
1491 SAFE_FREE(workstations);
1492 SAFE_FREE(munged_dial);
1493 SAFE_FREE(unknown_str);
1494 SAFE_FREE(lm_pw_ptr);
1495 SAFE_FREE(nt_pw_ptr);
1496 SAFE_FREE(nt_pw_hist_ptr);
1497 SAFE_FREE(hours);
1499 return ret;
1502 /*********************************************************************
1503 *********************************************************************/
1505 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1508 /* times are stored as 32bit integer
1509 take care on system with 64bit wide time_t
1510 --SSS */
1511 uint32 logon_time,
1512 logoff_time,
1513 kickoff_time,
1514 bad_password_time,
1515 pass_last_set_time,
1516 pass_can_change_time,
1517 pass_must_change_time;
1518 char *username = NULL;
1519 char *domain = NULL;
1520 char *nt_username = NULL;
1521 char *dir_drive = NULL;
1522 char *comment = NULL;
1523 char *munged_dial = NULL;
1524 char *fullname = NULL;
1525 char *homedir = NULL;
1526 char *logon_script = NULL;
1527 char *profile_path = NULL;
1528 char *acct_desc = NULL;
1529 char *workstations = NULL;
1530 uint32 username_len, domain_len, nt_username_len,
1531 dir_drive_len, comment_len, munged_dial_len,
1532 fullname_len, homedir_len, logon_script_len,
1533 profile_path_len, acct_desc_len, workstations_len;
1535 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1536 uint16 logon_divs;
1537 uint16 bad_password_count, logon_count;
1538 uint8 *hours = NULL;
1539 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1540 uint32 len = 0;
1541 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1542 uint32 pwHistLen = 0;
1543 bool ret = True;
1544 fstring tmp_string;
1545 bool expand_explicit = lp_passdb_expand_explicit();
1547 if(sampass == NULL || buf == NULL) {
1548 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1549 return False;
1552 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1554 /* unpack the buffer into variables */
1555 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1556 &logon_time, /* d */
1557 &logoff_time, /* d */
1558 &kickoff_time, /* d */
1559 &bad_password_time, /* d */
1560 &pass_last_set_time, /* d */
1561 &pass_can_change_time, /* d */
1562 &pass_must_change_time, /* d */
1563 &username_len, &username, /* B */
1564 &domain_len, &domain, /* B */
1565 &nt_username_len, &nt_username, /* B */
1566 &fullname_len, &fullname, /* B */
1567 &homedir_len, &homedir, /* B */
1568 &dir_drive_len, &dir_drive, /* B */
1569 &logon_script_len, &logon_script, /* B */
1570 &profile_path_len, &profile_path, /* B */
1571 &acct_desc_len, &acct_desc, /* B */
1572 &workstations_len, &workstations, /* B */
1573 &comment_len, &comment, /* B */
1574 &munged_dial_len, &munged_dial, /* B */
1575 &user_rid, /* d */
1576 &group_rid, /* d */
1577 &lm_pw_len, &lm_pw_ptr, /* B */
1578 &nt_pw_len, &nt_pw_ptr, /* B */
1579 /* Change from V1 is addition of password history field. */
1580 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1581 /* Change from V2 is the uint32 acb_mask */
1582 &acct_ctrl, /* d */
1583 /* Also "remove_me" field was removed. */
1584 &logon_divs, /* w */
1585 &hours_len, /* d */
1586 &hourslen, &hours, /* B */
1587 &bad_password_count, /* w */
1588 &logon_count, /* w */
1589 &unknown_6); /* d */
1591 if (len == (uint32) -1) {
1592 ret = False;
1593 goto done;
1596 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1597 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1598 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1599 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1600 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1601 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1602 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1604 pdb_set_username(sampass, username, PDB_SET);
1605 pdb_set_domain(sampass, domain, PDB_SET);
1606 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1607 pdb_set_fullname(sampass, fullname, PDB_SET);
1609 if (homedir) {
1610 fstrcpy( tmp_string, homedir );
1611 if (expand_explicit) {
1612 standard_sub_basic( username, domain, tmp_string,
1613 sizeof(tmp_string) );
1615 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1617 else {
1618 pdb_set_homedir(sampass,
1619 talloc_sub_basic(sampass, username, domain,
1620 lp_logon_home()),
1621 PDB_DEFAULT);
1624 if (dir_drive)
1625 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1626 else
1627 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1629 if (logon_script) {
1630 fstrcpy( tmp_string, logon_script );
1631 if (expand_explicit) {
1632 standard_sub_basic( username, domain, tmp_string,
1633 sizeof(tmp_string) );
1635 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1637 else {
1638 pdb_set_logon_script(sampass,
1639 talloc_sub_basic(sampass, username, domain,
1640 lp_logon_script()),
1641 PDB_DEFAULT);
1644 if (profile_path) {
1645 fstrcpy( tmp_string, profile_path );
1646 if (expand_explicit) {
1647 standard_sub_basic( username, domain, tmp_string,
1648 sizeof(tmp_string) );
1650 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1652 else {
1653 pdb_set_profile_path(sampass,
1654 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1655 PDB_DEFAULT);
1658 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1659 pdb_set_comment(sampass, comment, PDB_SET);
1660 pdb_set_workstations(sampass, workstations, PDB_SET);
1661 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1663 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1664 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1665 ret = False;
1666 goto done;
1670 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1671 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1672 ret = False;
1673 goto done;
1677 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1678 if (pwHistLen) {
1679 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1680 if (!pw_hist) {
1681 ret = False;
1682 goto done;
1684 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1685 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1686 int i;
1687 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1688 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1689 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1690 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1691 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1692 PW_HISTORY_ENTRY_LEN);
1695 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1696 SAFE_FREE(pw_hist);
1697 ret = False;
1698 goto done;
1700 SAFE_FREE(pw_hist);
1701 } else {
1702 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1705 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1706 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1707 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1708 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1709 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1710 /* Change from V2 is the uint32 acct_ctrl */
1711 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1712 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1713 pdb_set_hours(sampass, hours, PDB_SET);
1715 done:
1717 SAFE_FREE(username);
1718 SAFE_FREE(domain);
1719 SAFE_FREE(nt_username);
1720 SAFE_FREE(fullname);
1721 SAFE_FREE(homedir);
1722 SAFE_FREE(dir_drive);
1723 SAFE_FREE(logon_script);
1724 SAFE_FREE(profile_path);
1725 SAFE_FREE(acct_desc);
1726 SAFE_FREE(workstations);
1727 SAFE_FREE(munged_dial);
1728 SAFE_FREE(comment);
1729 SAFE_FREE(lm_pw_ptr);
1730 SAFE_FREE(nt_pw_ptr);
1731 SAFE_FREE(nt_pw_hist_ptr);
1732 SAFE_FREE(hours);
1734 return ret;
1737 /*********************************************************************
1738 *********************************************************************/
1740 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1742 size_t len, buflen;
1744 /* times are stored as 32bit integer
1745 take care on system with 64bit wide time_t
1746 --SSS */
1747 uint32 logon_time,
1748 logoff_time,
1749 kickoff_time,
1750 bad_password_time,
1751 pass_last_set_time,
1752 pass_can_change_time,
1753 pass_must_change_time;
1755 uint32 user_rid, group_rid;
1757 const char *username;
1758 const char *domain;
1759 const char *nt_username;
1760 const char *dir_drive;
1761 const char *comment;
1762 const char *munged_dial;
1763 const char *fullname;
1764 const char *homedir;
1765 const char *logon_script;
1766 const char *profile_path;
1767 const char *acct_desc;
1768 const char *workstations;
1769 uint32 username_len, domain_len, nt_username_len,
1770 dir_drive_len, comment_len, munged_dial_len,
1771 fullname_len, homedir_len, logon_script_len,
1772 profile_path_len, acct_desc_len, workstations_len;
1774 const uint8 *lm_pw;
1775 const uint8 *nt_pw;
1776 const uint8 *nt_pw_hist;
1777 uint32 lm_pw_len = 16;
1778 uint32 nt_pw_len = 16;
1779 uint32 nt_pw_hist_len;
1780 uint32 pwHistLen = 0;
1782 *buf = NULL;
1783 buflen = 0;
1785 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1786 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1787 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1788 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1789 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1790 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1791 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1793 user_rid = pdb_get_user_rid(sampass);
1794 group_rid = pdb_get_group_rid(sampass);
1796 username = pdb_get_username(sampass);
1797 if (username) {
1798 username_len = strlen(username) +1;
1799 } else {
1800 username_len = 0;
1803 domain = pdb_get_domain(sampass);
1804 if (domain) {
1805 domain_len = strlen(domain) +1;
1806 } else {
1807 domain_len = 0;
1810 nt_username = pdb_get_nt_username(sampass);
1811 if (nt_username) {
1812 nt_username_len = strlen(nt_username) +1;
1813 } else {
1814 nt_username_len = 0;
1817 fullname = pdb_get_fullname(sampass);
1818 if (fullname) {
1819 fullname_len = strlen(fullname) +1;
1820 } else {
1821 fullname_len = 0;
1825 * Only updates fields which have been set (not defaults from smb.conf)
1828 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1829 dir_drive = pdb_get_dir_drive(sampass);
1830 } else {
1831 dir_drive = NULL;
1833 if (dir_drive) {
1834 dir_drive_len = strlen(dir_drive) +1;
1835 } else {
1836 dir_drive_len = 0;
1839 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1840 homedir = pdb_get_homedir(sampass);
1841 } else {
1842 homedir = NULL;
1844 if (homedir) {
1845 homedir_len = strlen(homedir) +1;
1846 } else {
1847 homedir_len = 0;
1850 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1851 logon_script = pdb_get_logon_script(sampass);
1852 } else {
1853 logon_script = NULL;
1855 if (logon_script) {
1856 logon_script_len = strlen(logon_script) +1;
1857 } else {
1858 logon_script_len = 0;
1861 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1862 profile_path = pdb_get_profile_path(sampass);
1863 } else {
1864 profile_path = NULL;
1866 if (profile_path) {
1867 profile_path_len = strlen(profile_path) +1;
1868 } else {
1869 profile_path_len = 0;
1872 lm_pw = pdb_get_lanman_passwd(sampass);
1873 if (!lm_pw) {
1874 lm_pw_len = 0;
1877 nt_pw = pdb_get_nt_passwd(sampass);
1878 if (!nt_pw) {
1879 nt_pw_len = 0;
1882 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1883 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1884 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1885 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1886 } else {
1887 nt_pw_hist_len = 0;
1890 acct_desc = pdb_get_acct_desc(sampass);
1891 if (acct_desc) {
1892 acct_desc_len = strlen(acct_desc) +1;
1893 } else {
1894 acct_desc_len = 0;
1897 workstations = pdb_get_workstations(sampass);
1898 if (workstations) {
1899 workstations_len = strlen(workstations) +1;
1900 } else {
1901 workstations_len = 0;
1904 comment = pdb_get_comment(sampass);
1905 if (comment) {
1906 comment_len = strlen(comment) +1;
1907 } else {
1908 comment_len = 0;
1911 munged_dial = pdb_get_munged_dial(sampass);
1912 if (munged_dial) {
1913 munged_dial_len = strlen(munged_dial) +1;
1914 } else {
1915 munged_dial_len = 0;
1918 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1920 /* one time to get the size needed */
1921 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1922 logon_time, /* d */
1923 logoff_time, /* d */
1924 kickoff_time, /* d */
1925 bad_password_time, /* d */
1926 pass_last_set_time, /* d */
1927 pass_can_change_time, /* d */
1928 pass_must_change_time, /* d */
1929 username_len, username, /* B */
1930 domain_len, domain, /* B */
1931 nt_username_len, nt_username, /* B */
1932 fullname_len, fullname, /* B */
1933 homedir_len, homedir, /* B */
1934 dir_drive_len, dir_drive, /* B */
1935 logon_script_len, logon_script, /* B */
1936 profile_path_len, profile_path, /* B */
1937 acct_desc_len, acct_desc, /* B */
1938 workstations_len, workstations, /* B */
1939 comment_len, comment, /* B */
1940 munged_dial_len, munged_dial, /* B */
1941 user_rid, /* d */
1942 group_rid, /* d */
1943 lm_pw_len, lm_pw, /* B */
1944 nt_pw_len, nt_pw, /* B */
1945 nt_pw_hist_len, nt_pw_hist, /* B */
1946 pdb_get_acct_ctrl(sampass), /* d */
1947 pdb_get_logon_divs(sampass), /* w */
1948 pdb_get_hours_len(sampass), /* d */
1949 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1950 pdb_get_bad_password_count(sampass), /* w */
1951 pdb_get_logon_count(sampass), /* w */
1952 pdb_get_unknown_6(sampass)); /* d */
1954 if (size_only) {
1955 return buflen;
1958 /* malloc the space needed */
1959 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1960 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1961 return (-1);
1964 /* now for the real call to tdb_pack() */
1965 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1966 logon_time, /* d */
1967 logoff_time, /* d */
1968 kickoff_time, /* d */
1969 bad_password_time, /* d */
1970 pass_last_set_time, /* d */
1971 pass_can_change_time, /* d */
1972 pass_must_change_time, /* d */
1973 username_len, username, /* B */
1974 domain_len, domain, /* B */
1975 nt_username_len, nt_username, /* B */
1976 fullname_len, fullname, /* B */
1977 homedir_len, homedir, /* B */
1978 dir_drive_len, dir_drive, /* B */
1979 logon_script_len, logon_script, /* B */
1980 profile_path_len, profile_path, /* B */
1981 acct_desc_len, acct_desc, /* B */
1982 workstations_len, workstations, /* B */
1983 comment_len, comment, /* B */
1984 munged_dial_len, munged_dial, /* B */
1985 user_rid, /* d */
1986 group_rid, /* d */
1987 lm_pw_len, lm_pw, /* B */
1988 nt_pw_len, nt_pw, /* B */
1989 nt_pw_hist_len, nt_pw_hist, /* B */
1990 pdb_get_acct_ctrl(sampass), /* d */
1991 pdb_get_logon_divs(sampass), /* w */
1992 pdb_get_hours_len(sampass), /* d */
1993 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1994 pdb_get_bad_password_count(sampass), /* w */
1995 pdb_get_logon_count(sampass), /* w */
1996 pdb_get_unknown_6(sampass)); /* d */
1998 /* check to make sure we got it correct */
1999 if (buflen != len) {
2000 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2001 (unsigned long)buflen, (unsigned long)len));
2002 /* error */
2003 SAFE_FREE (*buf);
2004 return (-1);
2007 return (buflen);
2010 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2012 /* nothing changed between V3 and V4 */
2013 return init_samu_from_buffer_v3(sampass, buf, buflen);
2016 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2018 /* nothing changed between V3 and V4 */
2019 return init_buffer_from_samu_v3(buf, sampass, size_only);
2022 /**********************************************************************
2023 Intialize a struct samu struct from a BYTE buffer of size len
2024 *********************************************************************/
2026 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2027 uint8 *buf, uint32 buflen)
2029 switch (level) {
2030 case SAMU_BUFFER_V0:
2031 return init_samu_from_buffer_v0(sampass, buf, buflen);
2032 case SAMU_BUFFER_V1:
2033 return init_samu_from_buffer_v1(sampass, buf, buflen);
2034 case SAMU_BUFFER_V2:
2035 return init_samu_from_buffer_v2(sampass, buf, buflen);
2036 case SAMU_BUFFER_V3:
2037 return init_samu_from_buffer_v3(sampass, buf, buflen);
2038 case SAMU_BUFFER_V4:
2039 return init_samu_from_buffer_v4(sampass, buf, buflen);
2042 return false;
2045 /**********************************************************************
2046 Intialize a BYTE buffer from a struct samu struct
2047 *********************************************************************/
2049 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2051 return init_buffer_from_samu_v4(buf, sampass, size_only);
2054 /*********************************************************************
2055 *********************************************************************/
2057 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2059 uint8 *buf = NULL;
2060 int len;
2062 len = init_buffer_from_samu(&buf, src, False);
2063 if (len == -1 || !buf) {
2064 SAFE_FREE(buf);
2065 return False;
2068 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2069 free(buf);
2070 return False;
2073 dst->methods = src->methods;
2075 if ( src->unix_pw ) {
2076 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2077 if (!dst->unix_pw) {
2078 free(buf);
2079 return False;
2083 free(buf);
2084 return True;
2087 /*********************************************************************
2088 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2089 *********************************************************************/
2091 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2093 time_t LastBadPassword;
2094 uint16 BadPasswordCount;
2095 uint32 resettime;
2096 bool res;
2098 BadPasswordCount = pdb_get_bad_password_count(sampass);
2099 if (!BadPasswordCount) {
2100 DEBUG(9, ("No bad password attempts.\n"));
2101 return True;
2104 become_root();
2105 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2106 unbecome_root();
2108 if (!res) {
2109 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2110 return False;
2113 /* First, check if there is a reset time to compare */
2114 if ((resettime == (uint32) -1) || (resettime == 0)) {
2115 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2116 return True;
2119 LastBadPassword = pdb_get_bad_password_time(sampass);
2120 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2121 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2122 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2123 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2124 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2125 if (updated) {
2126 *updated = True;
2130 return True;
2133 /*********************************************************************
2134 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2135 *********************************************************************/
2137 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2139 uint32 duration;
2140 time_t LastBadPassword;
2141 bool res;
2143 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2144 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2145 pdb_get_username(sampass)));
2146 return True;
2149 become_root();
2150 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2151 unbecome_root();
2153 if (!res) {
2154 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2155 return False;
2158 /* First, check if there is a duration to compare */
2159 if ((duration == (uint32) -1) || (duration == 0)) {
2160 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2161 return True;
2164 LastBadPassword = pdb_get_bad_password_time(sampass);
2165 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2166 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2168 if (LastBadPassword == (time_t)0) {
2169 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2170 "administratively locked out with no bad password "
2171 "time. Leaving locked out.\n",
2172 pdb_get_username(sampass) ));
2173 return True;
2176 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2177 pdb_set_acct_ctrl(sampass,
2178 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2179 PDB_CHANGED);
2180 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2181 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2182 if (updated) {
2183 *updated = True;
2187 return True;
2190 /*********************************************************************
2191 Increment the bad_password_count
2192 *********************************************************************/
2194 bool pdb_increment_bad_password_count(struct samu *sampass)
2196 uint32 account_policy_lockout;
2197 bool autolock_updated = False, badpw_updated = False;
2198 bool ret;
2200 /* Retrieve the account lockout policy */
2201 become_root();
2202 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2203 unbecome_root();
2204 if ( !ret ) {
2205 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2206 return False;
2209 /* If there is no policy, we don't need to continue checking */
2210 if (!account_policy_lockout) {
2211 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2212 return True;
2215 /* Check if the autolock needs to be cleared */
2216 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2217 return False;
2219 /* Check if the badpw count needs to be reset */
2220 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2221 return False;
2224 Ok, now we can assume that any resetting that needs to be
2225 done has been done, and just get on with incrementing
2226 and autolocking if necessary
2229 pdb_set_bad_password_count(sampass,
2230 pdb_get_bad_password_count(sampass)+1,
2231 PDB_CHANGED);
2232 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2235 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2236 return True;
2238 if (!pdb_set_acct_ctrl(sampass,
2239 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2240 PDB_CHANGED)) {
2241 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2242 return False;
2245 return True;
2248 bool is_dc_trusted_domain_situation(const char *domain_name)
2250 return IS_DC && !strequal(domain_name, lp_workgroup());
2253 /*******************************************************************
2254 Wrapper around retrieving the clear text trust account password.
2255 appropriate account name is stored in account_name.
2256 Caller must free password, but not account_name.
2257 *******************************************************************/
2259 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2260 const char **account_name, uint32 *channel)
2262 char *pwd;
2263 time_t last_set_time;
2265 /* if we are a DC and this is not our domain, then lookup an account
2266 * for the domain trust */
2268 if (is_dc_trusted_domain_situation(domain)) {
2269 if (!lp_allow_trusted_domains()) {
2270 return false;
2273 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2274 &last_set_time))
2276 DEBUG(0, ("get_trust_pw: could not fetch trust "
2277 "account password for trusted domain %s\n",
2278 domain));
2279 return false;
2282 if (channel != NULL) {
2283 *channel = SEC_CHAN_DOMAIN;
2286 if (account_name != NULL) {
2287 *account_name = lp_workgroup();
2290 return true;
2294 * Since we can only be member of one single domain, we are now
2295 * in a member situation:
2297 * - Either we are a DC (selfjoined) and the domain is our
2298 * own domain.
2299 * - Or we are on a member and the domain is our own or some
2300 * other (potentially trusted) domain.
2302 * In both cases, we can only get the machine account password
2303 * for our own domain to connect to our own dc. (For a member,
2304 * request to trusted domains are performed through our dc.)
2306 * So we simply use our own domain name to retrieve the
2307 * machine account passowrd and ignore the request domain here.
2310 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2312 if (pwd != NULL) {
2313 *ret_pwd = pwd;
2314 if (account_name != NULL) {
2315 *account_name = global_myname();
2318 return true;
2321 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2322 "account password for domain %s\n", domain));
2323 return false;
2326 /*******************************************************************
2327 Wrapper around retrieving the trust account password.
2328 appropriate account name is stored in account_name.
2329 *******************************************************************/
2331 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2332 const char **account_name, uint32 *channel)
2334 char *pwd = NULL;
2335 time_t last_set_time;
2337 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2338 E_md4hash(pwd, ret_pwd);
2339 SAFE_FREE(pwd);
2340 return true;
2341 } else if (is_dc_trusted_domain_situation(domain)) {
2342 return false;
2345 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2347 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2348 &last_set_time,
2349 channel))
2351 if (account_name != NULL) {
2352 *account_name = global_myname();
2355 return true;
2358 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2359 "password for domain %s\n", domain));
2360 return False;
2363 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2364 struct samu *pw)
2366 struct samr_LogonHours hours;
2367 const int units_per_week = 168;
2369 ZERO_STRUCT(hours);
2370 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2371 if (!hours.bits) {
2372 return hours;
2375 hours.units_per_week = units_per_week;
2376 memset(hours.bits, 0xFF, units_per_week);
2378 if (pdb_get_hours(pw)) {
2379 memcpy(hours.bits, pdb_get_hours(pw),
2380 MIN(pdb_get_hours_len(pw), units_per_week));
2383 return hours;