CVE-2020-25719 kdc: Avoid races and multiple DB lookups in s4u2self check
[Samba.git] / source3 / passdb / passdb.c
blob068c5a5ea70c115fe780e778658fb7146714f516
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 "passdb.h"
27 #include "system/passwd.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "secrets.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "util_tdb.h"
33 #include "auth/credentials/credentials.h"
34 #include "lib/param/param.h"
35 #include "lib/util/string_wrappers.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_PASSDB
40 /**********************************************************************
41 ***********************************************************************/
43 static int samu_destroy(struct samu *user)
45 data_blob_clear_free( &user->lm_pw );
46 data_blob_clear_free( &user->nt_pw );
48 if ( user->plaintext_pw )
49 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
51 return 0;
54 /**********************************************************************
55 generate a new struct samuser
56 ***********************************************************************/
58 struct samu *samu_new( TALLOC_CTX *ctx )
60 struct samu *user;
62 if ( !(user = talloc_zero( ctx, struct samu )) ) {
63 DEBUG(0,("samuser_new: Talloc failed!\n"));
64 return NULL;
67 talloc_set_destructor( user, samu_destroy );
69 /* no initial methods */
71 user->methods = NULL;
73 /* Don't change these timestamp settings without a good reason.
74 They are important for NT member server compatibility. */
76 user->logon_time = (time_t)0;
77 user->pass_last_set_time = (time_t)0;
78 user->pass_can_change_time = (time_t)0;
79 user->logoff_time = get_time_t_max();
80 user->kickoff_time = get_time_t_max();
81 user->fields_present = 0x00ffffff;
82 user->logon_divs = 168; /* hours per week */
83 user->hours_len = 21; /* 21 times 8 bits = 168 */
84 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
85 user->bad_password_count = 0;
86 user->logon_count = 0;
87 user->unknown_6 = 0x000004ec; /* don't know */
89 /* Some parts of samba strlen their pdb_get...() returns,
90 so this keeps the interface unchanged for now. */
92 user->username = "";
93 user->domain = "";
94 user->nt_username = "";
95 user->full_name = "";
96 user->home_dir = "";
97 user->logon_script = "";
98 user->profile_path = "";
99 user->acct_desc = "";
100 user->workstations = "";
101 user->comment = "";
102 user->munged_dial = "";
104 user->plaintext_pw = NULL;
106 /* Unless we know otherwise have a Account Control Bit
107 value of 'normal user'. This helps User Manager, which
108 asks for a filtered list of users. */
110 user->acct_ctrl = ACB_NORMAL;
112 return user;
115 static int count_commas(const char *str)
117 int num_commas = 0;
118 const char *comma = str;
120 while ((comma = strchr(comma, ',')) != NULL) {
121 comma += 1;
122 num_commas += 1;
124 return num_commas;
127 /*********************************************************************
128 Initialize a struct samu from a struct passwd including the user
129 and group SIDs. The *user structure is filled out with the Unix
130 attributes and a user SID.
131 *********************************************************************/
133 static NTSTATUS samu_set_unix_internal(struct pdb_methods *methods,
134 struct samu *user, const struct passwd *pwd, bool create)
136 const char *guest_account = lp_guest_account();
137 const char *domain = lp_netbios_name();
138 char *fullname;
139 uint32_t urid;
140 bool ok;
142 if ( !pwd ) {
143 return NT_STATUS_NO_SUCH_USER;
146 /* Basic properties based upon the Unix account information */
148 ok = pdb_set_username(user, pwd->pw_name, PDB_SET);
149 if (!ok) {
150 return NT_STATUS_NO_MEMORY;
153 fullname = NULL;
155 if (count_commas(pwd->pw_gecos) == 3) {
157 * Heuristic: This seems to be a gecos field that has been
158 * edited by chfn(1). Only use the part before the first
159 * comma. Fixes bug 5198.
161 fullname = talloc_strndup(
162 talloc_tos(), pwd->pw_gecos,
163 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
164 if (fullname == NULL) {
165 return NT_STATUS_NO_MEMORY;
169 if (fullname != NULL) {
170 ok = pdb_set_fullname(user, fullname, PDB_SET);
171 } else {
172 ok = pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
174 TALLOC_FREE(fullname);
176 if (!ok) {
177 return NT_STATUS_NO_MEMORY;
180 ok = pdb_set_domain(user, get_global_sam_name(), PDB_DEFAULT);
181 if (!ok) {
182 return NT_STATUS_NO_MEMORY;
184 #if 0
185 /* This can lead to a primary group of S-1-22-2-XX which
186 will be rejected by other parts of the Samba code.
187 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
188 --jerry */
190 gid_to_sid(&group_sid, pwd->pw_gid);
191 pdb_set_group_sid(user, &group_sid, PDB_SET);
192 #endif
194 /* save the password structure for later use */
196 user->unix_pw = tcopy_passwd( user, pwd );
197 if (user->unix_pw == NULL) {
198 return NT_STATUS_NO_MEMORY;
201 /* Special case for the guest account which must have a RID of 501 */
203 if ( strequal( pwd->pw_name, guest_account ) ) {
204 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_RID_GUEST, PDB_DEFAULT)) {
205 return NT_STATUS_NO_SUCH_USER;
207 return NT_STATUS_OK;
210 /* Non-guest accounts...Check for a workstation or user account */
212 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
213 /* workstation */
215 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
216 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
217 pwd->pw_name));
218 return NT_STATUS_INVALID_COMPUTER_NAME;
221 else {
222 /* user */
224 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
225 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
226 pwd->pw_name));
227 return NT_STATUS_INVALID_ACCOUNT_NAME;
230 /* set some basic attributes */
232 ok = pdb_set_profile_path(
233 user,
234 talloc_sub_specified(
235 user,
236 lp_logon_path(),
237 pwd->pw_name,
238 NULL,
239 domain,
240 pwd->pw_uid,
241 pwd->pw_gid),
242 PDB_DEFAULT);
243 ok &= pdb_set_homedir(
244 user,
245 talloc_sub_specified(
246 user,
247 lp_logon_home(),
248 pwd->pw_name,
249 NULL,
250 domain,
251 pwd->pw_uid,
252 pwd->pw_gid),
253 PDB_DEFAULT);
254 ok &= pdb_set_dir_drive(
255 user,
256 talloc_sub_specified(
257 user,
258 lp_logon_drive(),
259 pwd->pw_name,
260 NULL,
261 domain,
262 pwd->pw_uid,
263 pwd->pw_gid),
264 PDB_DEFAULT);
265 ok &= pdb_set_logon_script(
266 user,
267 talloc_sub_specified(
268 user,
269 lp_logon_script(),
270 pwd->pw_name,
271 NULL,
272 domain,
273 pwd->pw_uid,
274 pwd->pw_gid),
275 PDB_DEFAULT);
276 if (!ok) {
277 return NT_STATUS_NO_MEMORY;
281 /* Now deal with the user SID. If we have a backend that can generate
282 RIDs, then do so. But sometimes the caller just wanted a structure
283 initialized and will fill in these fields later (such as from a
284 netr_SamInfo3 structure) */
286 if ( create && (methods->capabilities(methods) & PDB_CAP_STORE_RIDS)) {
287 uint32_t user_rid;
288 struct dom_sid user_sid;
290 if ( !methods->new_rid(methods, &user_rid) ) {
291 DEBUG(3, ("Could not allocate a new RID\n"));
292 return NT_STATUS_ACCESS_DENIED;
295 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
297 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
298 DEBUG(3, ("pdb_set_user_sid failed\n"));
299 return NT_STATUS_INTERNAL_ERROR;
302 return NT_STATUS_OK;
305 /* generate a SID for the user with the RID algorithm */
307 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
309 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
310 return NT_STATUS_INTERNAL_ERROR;
313 return NT_STATUS_OK;
316 /********************************************************************
317 Set the Unix user attributes
318 ********************************************************************/
320 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
322 return samu_set_unix_internal( NULL, user, pwd, False );
325 NTSTATUS samu_alloc_rid_unix(struct pdb_methods *methods,
326 struct samu *user, const struct passwd *pwd)
328 return samu_set_unix_internal( methods, user, pwd, True );
331 /**********************************************************
332 Encode the account control bits into a string.
333 length = length of string to encode into (including terminating
334 null). length *MUST BE MORE THAN 2* !
335 **********************************************************/
337 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
339 fstring acct_str;
340 char *result;
342 size_t i = 0;
344 SMB_ASSERT(length <= sizeof(acct_str));
346 acct_str[i++] = '[';
348 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
349 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
350 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
351 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
352 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
353 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
354 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
355 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
356 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
357 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
358 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
360 for ( ; i < length - 2 ; i++ )
361 acct_str[i] = ' ';
363 i = length - 2;
364 acct_str[i++] = ']';
365 acct_str[i++] = '\0';
367 result = talloc_strdup(talloc_tos(), acct_str);
368 SMB_ASSERT(result != NULL);
369 return result;
372 /**********************************************************
373 Decode the account control bits from a string.
374 **********************************************************/
376 uint32_t pdb_decode_acct_ctrl(const char *p)
378 uint32_t acct_ctrl = 0;
379 bool finished = false;
382 * Check if the account type bits have been encoded after the
383 * NT password (in the form [NDHTUWSLXI]).
386 if (*p != '[')
387 return 0;
389 for (p++; *p && !finished; p++) {
390 switch (*p) {
391 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
392 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
393 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
394 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
395 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
396 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
397 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
398 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
399 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
400 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
401 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
402 case ' ': { break; }
403 case ':':
404 case '\n':
405 case '\0':
406 case ']':
407 default: { finished = true; }
411 return acct_ctrl;
414 /*************************************************************
415 Routine to set 32 hex password characters from a 16 byte array.
416 **************************************************************/
418 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
420 if (pwd != NULL) {
421 hex_encode_buf(p, pwd, 16);
422 } else {
423 if (acct_ctrl & ACB_PWNOTREQ)
424 strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
425 else
426 strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
430 /*************************************************************
431 Routine to get the 32 hex characters and turn them
432 into a 16 byte array.
433 **************************************************************/
435 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
437 int i;
438 unsigned char lonybble, hinybble;
439 const char *hexchars = "0123456789ABCDEF";
440 char *p1, *p2;
442 if (!p)
443 return false;
445 for (i = 0; i < 32; i += 2) {
446 hinybble = toupper_m(p[i]);
447 lonybble = toupper_m(p[i + 1]);
449 p1 = strchr(hexchars, hinybble);
450 p2 = strchr(hexchars, lonybble);
452 if (!p1 || !p2)
453 return false;
455 hinybble = PTR_DIFF(p1, hexchars);
456 lonybble = PTR_DIFF(p2, hexchars);
458 pwd[i / 2] = (hinybble << 4) | lonybble;
460 return true;
463 /*************************************************************
464 Routine to set 42 hex hours characters from a 21 byte array.
465 **************************************************************/
467 void pdb_sethexhours(char *p, const unsigned char *hours)
469 if (hours != NULL) {
470 hex_encode_buf(p, hours, 21);
471 } else {
472 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
476 /*************************************************************
477 Routine to get the 42 hex characters and turn them
478 into a 21 byte array.
479 **************************************************************/
481 bool pdb_gethexhours(const char *p, unsigned char *hours)
483 int i;
484 unsigned char lonybble, hinybble;
485 const char *hexchars = "0123456789ABCDEF";
486 char *p1, *p2;
488 if (!p) {
489 return (False);
492 for (i = 0; i < 42; i += 2) {
493 hinybble = toupper_m(p[i]);
494 lonybble = toupper_m(p[i + 1]);
496 p1 = strchr(hexchars, hinybble);
497 p2 = strchr(hexchars, lonybble);
499 if (!p1 || !p2) {
500 return (False);
503 hinybble = PTR_DIFF(p1, hexchars);
504 lonybble = PTR_DIFF(p2, hexchars);
506 hours[i / 2] = (hinybble << 4) | lonybble;
508 return (True);
511 /********************************************************************
512 ********************************************************************/
514 int algorithmic_rid_base(void)
516 int rid_offset;
518 rid_offset = lp_algorithmic_rid_base();
520 if (rid_offset < BASE_RID) {
521 /* Try to prevent admin foot-shooting, we can't put algorithmic
522 rids below 1000, that's the 'well known RIDs' on NT */
523 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
524 rid_offset = BASE_RID;
526 if (rid_offset & 1) {
527 DEBUG(0, ("algorithmic rid base must be even\n"));
528 rid_offset += 1;
530 return rid_offset;
533 /*******************************************************************
534 Converts NT user RID to a UNIX uid.
535 ********************************************************************/
537 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
539 int rid_offset = algorithmic_rid_base();
540 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
543 uid_t max_algorithmic_uid(void)
545 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
548 /*******************************************************************
549 converts UNIX uid to an NT User RID.
550 ********************************************************************/
552 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
554 int rid_offset = algorithmic_rid_base();
555 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
558 /*******************************************************************
559 Converts NT group RID to a UNIX gid.
560 ********************************************************************/
562 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
564 int rid_offset = algorithmic_rid_base();
565 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
568 gid_t max_algorithmic_gid(void)
570 return pdb_group_rid_to_gid(0xffffffff);
573 /*******************************************************************
574 converts NT Group RID to a UNIX uid.
576 warning: you must not call that function only
577 you must do a call to the group mapping first.
578 there is not anymore a direct link between the gid and the rid.
579 ********************************************************************/
581 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
583 int rid_offset = algorithmic_rid_base();
584 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
587 /*******************************************************************
588 Decides if a RID is a well known RID.
589 ********************************************************************/
591 static bool rid_is_well_known(uint32_t rid)
593 /* Not using rid_offset here, because this is the actual
594 NT fixed value (1000) */
596 return (rid < BASE_RID);
599 /*******************************************************************
600 Decides if a RID is a user or group RID.
601 ********************************************************************/
603 bool algorithmic_pdb_rid_is_user(uint32_t rid)
605 if ( rid_is_well_known(rid) ) {
607 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
608 * and DOMAIN_RID_GUEST.
610 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
611 return True;
612 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
613 return True;
615 return False;
618 /*******************************************************************
619 Convert a name into a SID. Used in the lookup name rpc.
620 ********************************************************************/
622 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
623 enum lsa_SidType *type)
625 GROUP_MAP *map;
626 bool ret;
628 /* Windows treats "MACHINE\None" as a special name for
629 rid 513 on non-DCs. You cannot create a user or group
630 name "None" on Windows. You will get an error that
631 the group already exists. */
633 if ( strequal( name, "None" ) ) {
634 *rid = DOMAIN_RID_USERS;
635 *type = SID_NAME_DOM_GRP;
637 return True;
640 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
641 * correctly in the case where foo also exists as a user. If the flag
642 * is set, don't look for users at all. */
644 if ((flags & LOOKUP_NAME_GROUP) == 0) {
645 struct samu *sam_account = NULL;
646 struct dom_sid user_sid;
648 if ( !(sam_account = samu_new( NULL )) ) {
649 return False;
652 become_root();
653 ret = pdb_getsampwnam(sam_account, name);
654 unbecome_root();
656 if (ret) {
657 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
660 TALLOC_FREE(sam_account);
662 if (ret) {
663 if (!sid_check_is_in_our_sam(&user_sid)) {
664 struct dom_sid_buf buf;
665 DBG_ERR("User %s with invalid SID %s"
666 " in passdb\n",
667 name,
668 dom_sid_str_buf(&user_sid, &buf));
669 return False;
672 sid_peek_rid(&user_sid, rid);
673 *type = SID_NAME_USER;
674 return True;
679 * Maybe it is a group ?
682 map = talloc_zero(NULL, GROUP_MAP);
683 if (!map) {
684 return false;
687 become_root();
688 ret = pdb_getgrnam(map, name);
689 unbecome_root();
691 if (!ret) {
692 TALLOC_FREE(map);
693 return False;
696 /* BUILTIN groups are looked up elsewhere */
697 if (!sid_check_is_in_our_sam(&map->sid)) {
698 struct dom_sid_buf buf;
699 DEBUG(10, ("Found group %s (%s) not in our domain -- "
700 "ignoring.\n",
701 name,
702 dom_sid_str_buf(&map->sid, &buf)));
703 TALLOC_FREE(map);
704 return False;
707 /* yes it's a mapped group */
708 sid_peek_rid(&map->sid, rid);
709 *type = map->sid_name_use;
710 TALLOC_FREE(map);
711 return True;
714 /*************************************************************
715 Change a password entry in the local passdb backend.
717 Assumptions:
718 - always called as root
719 - ignores the account type except when adding a new account
720 - will create/delete the unix account if the relative
721 add/delete user script is configured
723 *************************************************************/
725 NTSTATUS local_password_change(const char *user_name,
726 int local_flags,
727 const char *new_passwd,
728 char **pp_err_str,
729 char **pp_msg_str)
731 TALLOC_CTX *tosctx;
732 struct samu *sam_pass;
733 uint32_t acb;
734 uint32_t rid;
735 NTSTATUS result;
736 bool user_exists;
737 int ret = -1;
739 *pp_err_str = NULL;
740 *pp_msg_str = NULL;
742 tosctx = talloc_tos();
744 sam_pass = samu_new(tosctx);
745 if (!sam_pass) {
746 result = NT_STATUS_NO_MEMORY;
747 goto done;
750 /* Get the smb passwd entry for this user */
751 user_exists = pdb_getsampwnam(sam_pass, user_name);
753 /* Check delete first, we don't need to do anything else if we
754 * are going to delete the account */
755 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
757 result = pdb_delete_user(tosctx, sam_pass);
758 if (!NT_STATUS_IS_OK(result)) {
759 ret = asprintf(pp_err_str,
760 "Failed to delete entry for user %s.\n",
761 user_name);
762 if (ret < 0) {
763 *pp_err_str = NULL;
765 result = NT_STATUS_UNSUCCESSFUL;
766 } else {
767 ret = asprintf(pp_msg_str,
768 "Deleted user %s.\n",
769 user_name);
770 if (ret < 0) {
771 *pp_msg_str = NULL;
774 goto done;
777 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
778 /* the entry already existed */
779 local_flags &= ~LOCAL_ADD_USER;
782 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
783 ret = asprintf(pp_err_str,
784 "Failed to find entry for user %s.\n",
785 user_name);
786 if (ret < 0) {
787 *pp_err_str = NULL;
789 result = NT_STATUS_NO_SUCH_USER;
790 goto done;
793 /* First thing add the new user if we are required to do so */
794 if (local_flags & LOCAL_ADD_USER) {
796 if (local_flags & LOCAL_TRUST_ACCOUNT) {
797 acb = ACB_WSTRUST;
798 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
799 acb = ACB_DOMTRUST;
800 } else {
801 acb = ACB_NORMAL;
804 result = pdb_create_user(tosctx, user_name, acb, &rid);
805 if (!NT_STATUS_IS_OK(result)) {
806 ret = asprintf(pp_err_str,
807 "Failed to add entry for user %s.\n",
808 user_name);
809 if (ret < 0) {
810 *pp_err_str = NULL;
812 result = NT_STATUS_UNSUCCESSFUL;
813 goto done;
816 sam_pass = samu_new(tosctx);
817 if (!sam_pass) {
818 result = NT_STATUS_NO_MEMORY;
819 goto done;
822 /* Now get back the smb passwd entry for this new user */
823 user_exists = pdb_getsampwnam(sam_pass, user_name);
824 if (!user_exists) {
825 ret = asprintf(pp_err_str,
826 "Failed to add entry for user %s.\n",
827 user_name);
828 if (ret < 0) {
829 *pp_err_str = NULL;
831 result = NT_STATUS_UNSUCCESSFUL;
832 goto done;
836 acb = pdb_get_acct_ctrl(sam_pass);
839 * We are root - just write the new password
840 * and the valid last change time.
842 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
843 acb |= ACB_PWNOTREQ;
844 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
845 ret = asprintf(pp_err_str,
846 "Failed to set 'no password required' "
847 "flag for user %s.\n", user_name);
848 if (ret < 0) {
849 *pp_err_str = NULL;
851 result = NT_STATUS_UNSUCCESSFUL;
852 goto done;
856 if (local_flags & LOCAL_SET_PASSWORD) {
858 * If we're dealing with setting a completely empty user account
859 * ie. One with a password of 'XXXX', but not set disabled (like
860 * an account created from scratch) then if the old password was
861 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
862 * We remove that as we're giving this user their first password
863 * and the decision hasn't really been made to disable them (ie.
864 * don't create them disabled). JRA.
866 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
867 (acb & ACB_DISABLED)) {
868 acb &= (~ACB_DISABLED);
869 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
870 ret = asprintf(pp_err_str,
871 "Failed to unset 'disabled' "
872 "flag for user %s.\n",
873 user_name);
874 if (ret < 0) {
875 *pp_err_str = NULL;
877 result = NT_STATUS_UNSUCCESSFUL;
878 goto done;
882 acb &= (~ACB_PWNOTREQ);
883 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
884 ret = asprintf(pp_err_str,
885 "Failed to unset 'no password required'"
886 " flag for user %s.\n", user_name);
887 if (ret < 0) {
888 *pp_err_str = NULL;
890 result = NT_STATUS_UNSUCCESSFUL;
891 goto done;
894 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
895 ret = asprintf(pp_err_str,
896 "Failed to set password for "
897 "user %s.\n", user_name);
898 if (ret < 0) {
899 *pp_err_str = NULL;
901 result = NT_STATUS_UNSUCCESSFUL;
902 goto done;
906 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
907 acb |= ACB_DISABLED;
908 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
909 ret = asprintf(pp_err_str,
910 "Failed to set 'disabled' flag for "
911 "user %s.\n", user_name);
912 if (ret < 0) {
913 *pp_err_str = NULL;
915 result = NT_STATUS_UNSUCCESSFUL;
916 goto done;
920 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
921 acb &= (~ACB_DISABLED);
922 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
923 ret = asprintf(pp_err_str,
924 "Failed to unset 'disabled' flag for "
925 "user %s.\n", user_name);
926 if (ret < 0) {
927 *pp_err_str = NULL;
929 result = NT_STATUS_UNSUCCESSFUL;
930 goto done;
934 /* now commit changes if any */
935 result = pdb_update_sam_account(sam_pass);
936 if (!NT_STATUS_IS_OK(result)) {
937 ret = asprintf(pp_err_str,
938 "Failed to modify entry for user %s.\n",
939 user_name);
940 if (ret < 0) {
941 *pp_err_str = NULL;
943 goto done;
946 if (local_flags & LOCAL_ADD_USER) {
947 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
948 } else if (local_flags & LOCAL_DISABLE_USER) {
949 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
950 } else if (local_flags & LOCAL_ENABLE_USER) {
951 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
952 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
953 ret = asprintf(pp_msg_str,
954 "User %s password set to none.\n", user_name);
957 if (ret < 0) {
958 *pp_msg_str = NULL;
961 result = NT_STATUS_OK;
963 done:
964 TALLOC_FREE(sam_pass);
965 return result;
968 /**********************************************************************
969 Marshall/unmarshall struct samu structs.
970 *********************************************************************/
972 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
973 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
974 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
975 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
976 /* nothing changed between V3 and V4 */
978 /*********************************************************************
979 *********************************************************************/
981 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
984 /* times are stored as 32bit integer
985 take care on system with 64bit wide time_t
986 --SSS */
987 uint32_t logon_time,
988 logoff_time,
989 kickoff_time,
990 pass_last_set_time,
991 pass_can_change_time,
992 pass_must_change_time;
993 char *username = NULL;
994 char *domain = NULL;
995 char *nt_username = NULL;
996 char *dir_drive = NULL;
997 char *unknown_str = NULL;
998 char *munged_dial = NULL;
999 char *fullname = NULL;
1000 char *homedir = NULL;
1001 char *logon_script = NULL;
1002 char *profile_path = NULL;
1003 char *acct_desc = NULL;
1004 char *workstations = NULL;
1005 uint32_t username_len, domain_len, nt_username_len,
1006 dir_drive_len, unknown_str_len, munged_dial_len,
1007 fullname_len, homedir_len, logon_script_len,
1008 profile_path_len, acct_desc_len, workstations_len;
1010 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1011 uint16_t acct_ctrl, logon_divs;
1012 uint16_t bad_password_count, logon_count;
1013 uint8_t *hours = NULL;
1014 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1015 uint32_t len = 0;
1016 uint32_t lm_pw_len, nt_pw_len, hourslen;
1017 bool ret = True;
1019 if(sampass == NULL || buf == NULL) {
1020 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
1021 return False;
1024 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1026 /* unpack the buffer into variables */
1027 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
1028 &logon_time, /* d */
1029 &logoff_time, /* d */
1030 &kickoff_time, /* d */
1031 &pass_last_set_time, /* d */
1032 &pass_can_change_time, /* d */
1033 &pass_must_change_time, /* d */
1034 &username_len, &username, /* B */
1035 &domain_len, &domain, /* B */
1036 &nt_username_len, &nt_username, /* B */
1037 &fullname_len, &fullname, /* B */
1038 &homedir_len, &homedir, /* B */
1039 &dir_drive_len, &dir_drive, /* B */
1040 &logon_script_len, &logon_script, /* B */
1041 &profile_path_len, &profile_path, /* B */
1042 &acct_desc_len, &acct_desc, /* B */
1043 &workstations_len, &workstations, /* B */
1044 &unknown_str_len, &unknown_str, /* B */
1045 &munged_dial_len, &munged_dial, /* B */
1046 &user_rid, /* d */
1047 &group_rid, /* d */
1048 &lm_pw_len, &lm_pw_ptr, /* B */
1049 &nt_pw_len, &nt_pw_ptr, /* B */
1050 &acct_ctrl, /* w */
1051 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
1052 &logon_divs, /* w */
1053 &hours_len, /* d */
1054 &hourslen, &hours, /* B */
1055 &bad_password_count, /* w */
1056 &logon_count, /* w */
1057 &unknown_6); /* d */
1059 if (len == (uint32_t) -1) {
1060 ret = False;
1061 goto done;
1064 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1065 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1066 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1067 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1068 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1070 pdb_set_username(sampass, username, PDB_SET);
1071 pdb_set_domain(sampass, domain, PDB_SET);
1072 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1073 pdb_set_fullname(sampass, fullname, PDB_SET);
1075 if (homedir) {
1076 pdb_set_homedir(sampass, homedir, PDB_SET);
1078 else {
1079 pdb_set_homedir(sampass,
1080 talloc_sub_basic(sampass, username, domain,
1081 lp_logon_home()),
1082 PDB_DEFAULT);
1085 if (dir_drive)
1086 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1087 else {
1088 pdb_set_dir_drive(sampass,
1089 talloc_sub_basic(sampass, username, domain,
1090 lp_logon_drive()),
1091 PDB_DEFAULT);
1094 if (logon_script)
1095 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1096 else {
1097 pdb_set_logon_script(sampass,
1098 talloc_sub_basic(sampass, username, domain,
1099 lp_logon_script()),
1100 PDB_DEFAULT);
1103 if (profile_path) {
1104 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1105 } else {
1106 pdb_set_profile_path(sampass,
1107 talloc_sub_basic(sampass, username, domain,
1108 lp_logon_path()),
1109 PDB_DEFAULT);
1112 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1113 pdb_set_workstations(sampass, workstations, PDB_SET);
1114 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1116 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1117 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1118 ret = False;
1119 goto done;
1123 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1124 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1125 ret = False;
1126 goto done;
1130 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1131 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1132 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1133 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1134 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1135 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1136 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1137 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1138 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1139 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1141 done:
1143 SAFE_FREE(username);
1144 SAFE_FREE(domain);
1145 SAFE_FREE(nt_username);
1146 SAFE_FREE(fullname);
1147 SAFE_FREE(homedir);
1148 SAFE_FREE(dir_drive);
1149 SAFE_FREE(logon_script);
1150 SAFE_FREE(profile_path);
1151 SAFE_FREE(acct_desc);
1152 SAFE_FREE(workstations);
1153 SAFE_FREE(munged_dial);
1154 SAFE_FREE(unknown_str);
1155 SAFE_FREE(lm_pw_ptr);
1156 SAFE_FREE(nt_pw_ptr);
1157 SAFE_FREE(hours);
1159 return ret;
1162 /*********************************************************************
1163 *********************************************************************/
1165 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1168 /* times are stored as 32bit integer
1169 take care on system with 64bit wide time_t
1170 --SSS */
1171 uint32_t logon_time,
1172 logoff_time,
1173 kickoff_time,
1174 bad_password_time,
1175 pass_last_set_time,
1176 pass_can_change_time,
1177 pass_must_change_time;
1178 char *username = NULL;
1179 char *domain = NULL;
1180 char *nt_username = NULL;
1181 char *dir_drive = NULL;
1182 char *unknown_str = NULL;
1183 char *munged_dial = NULL;
1184 char *fullname = NULL;
1185 char *homedir = NULL;
1186 char *logon_script = NULL;
1187 char *profile_path = NULL;
1188 char *acct_desc = NULL;
1189 char *workstations = NULL;
1190 uint32_t username_len, domain_len, nt_username_len,
1191 dir_drive_len, unknown_str_len, munged_dial_len,
1192 fullname_len, homedir_len, logon_script_len,
1193 profile_path_len, acct_desc_len, workstations_len;
1195 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1196 uint16_t acct_ctrl, logon_divs;
1197 uint16_t bad_password_count, logon_count;
1198 uint8_t *hours = NULL;
1199 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1200 uint32_t len = 0;
1201 uint32_t lm_pw_len, nt_pw_len, hourslen;
1202 bool ret = True;
1204 if(sampass == NULL || buf == NULL) {
1205 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1206 return False;
1209 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1211 /* unpack the buffer into variables */
1212 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1213 &logon_time, /* d */
1214 &logoff_time, /* d */
1215 &kickoff_time, /* d */
1216 /* Change from V0 is addition of bad_password_time field. */
1217 &bad_password_time, /* d */
1218 &pass_last_set_time, /* d */
1219 &pass_can_change_time, /* d */
1220 &pass_must_change_time, /* d */
1221 &username_len, &username, /* B */
1222 &domain_len, &domain, /* B */
1223 &nt_username_len, &nt_username, /* B */
1224 &fullname_len, &fullname, /* B */
1225 &homedir_len, &homedir, /* B */
1226 &dir_drive_len, &dir_drive, /* B */
1227 &logon_script_len, &logon_script, /* B */
1228 &profile_path_len, &profile_path, /* B */
1229 &acct_desc_len, &acct_desc, /* B */
1230 &workstations_len, &workstations, /* B */
1231 &unknown_str_len, &unknown_str, /* B */
1232 &munged_dial_len, &munged_dial, /* B */
1233 &user_rid, /* d */
1234 &group_rid, /* d */
1235 &lm_pw_len, &lm_pw_ptr, /* B */
1236 &nt_pw_len, &nt_pw_ptr, /* B */
1237 &acct_ctrl, /* w */
1238 &remove_me, /* d */
1239 &logon_divs, /* w */
1240 &hours_len, /* d */
1241 &hourslen, &hours, /* B */
1242 &bad_password_count, /* w */
1243 &logon_count, /* w */
1244 &unknown_6); /* d */
1246 if (len == (uint32_t) -1) {
1247 ret = False;
1248 goto done;
1251 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1252 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1253 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1255 /* Change from V0 is addition of bad_password_time field. */
1256 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1257 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1258 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1260 pdb_set_username(sampass, username, PDB_SET);
1261 pdb_set_domain(sampass, domain, PDB_SET);
1262 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1263 pdb_set_fullname(sampass, fullname, PDB_SET);
1265 if (homedir) {
1266 pdb_set_homedir(sampass, homedir, PDB_SET);
1268 else {
1269 pdb_set_homedir(sampass,
1270 talloc_sub_basic(sampass, username, domain,
1271 lp_logon_home()),
1272 PDB_DEFAULT);
1275 if (dir_drive)
1276 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1277 else {
1278 pdb_set_dir_drive(sampass,
1279 talloc_sub_basic(sampass, username, domain,
1280 lp_logon_drive()),
1281 PDB_DEFAULT);
1284 if (logon_script)
1285 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1286 else {
1287 pdb_set_logon_script(sampass,
1288 talloc_sub_basic(sampass, username, domain,
1289 lp_logon_script()),
1290 PDB_DEFAULT);
1293 if (profile_path) {
1294 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1295 } else {
1296 pdb_set_profile_path(sampass,
1297 talloc_sub_basic(sampass, username, domain,
1298 lp_logon_path()),
1299 PDB_DEFAULT);
1302 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1303 pdb_set_workstations(sampass, workstations, PDB_SET);
1304 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1306 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1307 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1308 ret = False;
1309 goto done;
1313 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1314 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1315 ret = False;
1316 goto done;
1320 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1322 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1323 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1324 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1325 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1326 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1327 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1328 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1329 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1330 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1332 done:
1334 SAFE_FREE(username);
1335 SAFE_FREE(domain);
1336 SAFE_FREE(nt_username);
1337 SAFE_FREE(fullname);
1338 SAFE_FREE(homedir);
1339 SAFE_FREE(dir_drive);
1340 SAFE_FREE(logon_script);
1341 SAFE_FREE(profile_path);
1342 SAFE_FREE(acct_desc);
1343 SAFE_FREE(workstations);
1344 SAFE_FREE(munged_dial);
1345 SAFE_FREE(unknown_str);
1346 SAFE_FREE(lm_pw_ptr);
1347 SAFE_FREE(nt_pw_ptr);
1348 SAFE_FREE(hours);
1350 return ret;
1353 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1356 /* times are stored as 32bit integer
1357 take care on system with 64bit wide time_t
1358 --SSS */
1359 uint32_t logon_time,
1360 logoff_time,
1361 kickoff_time,
1362 bad_password_time,
1363 pass_last_set_time,
1364 pass_can_change_time,
1365 pass_must_change_time;
1366 char *username = NULL;
1367 char *domain = NULL;
1368 char *nt_username = NULL;
1369 char *dir_drive = NULL;
1370 char *unknown_str = NULL;
1371 char *munged_dial = NULL;
1372 char *fullname = NULL;
1373 char *homedir = NULL;
1374 char *logon_script = NULL;
1375 char *profile_path = NULL;
1376 char *acct_desc = NULL;
1377 char *workstations = NULL;
1378 uint32_t username_len, domain_len, nt_username_len,
1379 dir_drive_len, unknown_str_len, munged_dial_len,
1380 fullname_len, homedir_len, logon_script_len,
1381 profile_path_len, acct_desc_len, workstations_len;
1383 uint32_t user_rid, group_rid, hours_len, unknown_6;
1384 uint16_t acct_ctrl, logon_divs;
1385 uint16_t bad_password_count, logon_count;
1386 uint8_t *hours = NULL;
1387 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1388 uint32_t len = 0;
1389 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1390 uint32_t pwHistLen = 0;
1391 bool ret = True;
1392 fstring tmp_string;
1393 bool expand_explicit = lp_passdb_expand_explicit();
1395 if(sampass == NULL || buf == NULL) {
1396 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1397 return False;
1400 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1402 /* unpack the buffer into variables */
1403 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1404 &logon_time, /* d */
1405 &logoff_time, /* d */
1406 &kickoff_time, /* d */
1407 &bad_password_time, /* d */
1408 &pass_last_set_time, /* d */
1409 &pass_can_change_time, /* d */
1410 &pass_must_change_time, /* d */
1411 &username_len, &username, /* B */
1412 &domain_len, &domain, /* B */
1413 &nt_username_len, &nt_username, /* B */
1414 &fullname_len, &fullname, /* B */
1415 &homedir_len, &homedir, /* B */
1416 &dir_drive_len, &dir_drive, /* B */
1417 &logon_script_len, &logon_script, /* B */
1418 &profile_path_len, &profile_path, /* B */
1419 &acct_desc_len, &acct_desc, /* B */
1420 &workstations_len, &workstations, /* B */
1421 &unknown_str_len, &unknown_str, /* B */
1422 &munged_dial_len, &munged_dial, /* B */
1423 &user_rid, /* d */
1424 &group_rid, /* d */
1425 &lm_pw_len, &lm_pw_ptr, /* B */
1426 &nt_pw_len, &nt_pw_ptr, /* B */
1427 /* Change from V1 is addition of password history field. */
1428 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1429 &acct_ctrl, /* w */
1430 /* Also "remove_me" field was removed. */
1431 &logon_divs, /* w */
1432 &hours_len, /* d */
1433 &hourslen, &hours, /* B */
1434 &bad_password_count, /* w */
1435 &logon_count, /* w */
1436 &unknown_6); /* d */
1438 if (len == (uint32_t) -1) {
1439 ret = False;
1440 goto done;
1443 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1444 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1445 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1446 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1447 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1448 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1450 pdb_set_username(sampass, username, PDB_SET);
1451 pdb_set_domain(sampass, domain, PDB_SET);
1452 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1453 pdb_set_fullname(sampass, fullname, PDB_SET);
1455 if (homedir) {
1456 fstrcpy( tmp_string, homedir );
1457 if (expand_explicit) {
1458 standard_sub_basic( username, domain, tmp_string,
1459 sizeof(tmp_string) );
1461 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1463 else {
1464 pdb_set_homedir(sampass,
1465 talloc_sub_basic(sampass, username, domain,
1466 lp_logon_home()),
1467 PDB_DEFAULT);
1470 if (dir_drive)
1471 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1472 else
1473 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1475 if (logon_script) {
1476 fstrcpy( tmp_string, logon_script );
1477 if (expand_explicit) {
1478 standard_sub_basic( username, domain, tmp_string,
1479 sizeof(tmp_string) );
1481 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1483 else {
1484 pdb_set_logon_script(sampass,
1485 talloc_sub_basic(sampass, username, domain,
1486 lp_logon_script()),
1487 PDB_DEFAULT);
1490 if (profile_path) {
1491 fstrcpy( tmp_string, profile_path );
1492 if (expand_explicit) {
1493 standard_sub_basic( username, domain, tmp_string,
1494 sizeof(tmp_string) );
1496 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1498 else {
1499 pdb_set_profile_path(sampass,
1500 talloc_sub_basic(sampass, username, domain,
1501 lp_logon_path()),
1502 PDB_DEFAULT);
1505 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1506 pdb_set_workstations(sampass, workstations, PDB_SET);
1507 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1509 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1510 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1511 ret = False;
1512 goto done;
1516 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1517 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1518 ret = False;
1519 goto done;
1523 /* Change from V1 is addition of password history field. */
1524 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1525 if (pwHistLen) {
1526 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1527 if (!pw_hist) {
1528 ret = False;
1529 goto done;
1531 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1532 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1533 int i;
1534 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1535 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1536 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1537 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1538 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1539 PW_HISTORY_ENTRY_LEN);
1542 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1543 SAFE_FREE(pw_hist);
1544 ret = False;
1545 goto done;
1547 SAFE_FREE(pw_hist);
1548 } else {
1549 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1552 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1553 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1554 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1555 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1556 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1557 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1558 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1559 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1560 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1562 done:
1564 SAFE_FREE(username);
1565 SAFE_FREE(domain);
1566 SAFE_FREE(nt_username);
1567 SAFE_FREE(fullname);
1568 SAFE_FREE(homedir);
1569 SAFE_FREE(dir_drive);
1570 SAFE_FREE(logon_script);
1571 SAFE_FREE(profile_path);
1572 SAFE_FREE(acct_desc);
1573 SAFE_FREE(workstations);
1574 SAFE_FREE(munged_dial);
1575 SAFE_FREE(unknown_str);
1576 SAFE_FREE(lm_pw_ptr);
1577 SAFE_FREE(nt_pw_ptr);
1578 SAFE_FREE(nt_pw_hist_ptr);
1579 SAFE_FREE(hours);
1581 return ret;
1584 /*********************************************************************
1585 *********************************************************************/
1587 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1590 /* times are stored as 32bit integer
1591 take care on system with 64bit wide time_t
1592 --SSS */
1593 uint32_t logon_time,
1594 logoff_time,
1595 kickoff_time,
1596 bad_password_time,
1597 pass_last_set_time,
1598 pass_can_change_time,
1599 pass_must_change_time;
1600 char *username = NULL;
1601 char *domain = NULL;
1602 char *nt_username = NULL;
1603 char *dir_drive = NULL;
1604 char *comment = NULL;
1605 char *munged_dial = NULL;
1606 char *fullname = NULL;
1607 char *homedir = NULL;
1608 char *logon_script = NULL;
1609 char *profile_path = NULL;
1610 char *acct_desc = NULL;
1611 char *workstations = NULL;
1612 uint32_t username_len, domain_len, nt_username_len,
1613 dir_drive_len, comment_len, munged_dial_len,
1614 fullname_len, homedir_len, logon_script_len,
1615 profile_path_len, acct_desc_len, workstations_len;
1617 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1618 uint16_t logon_divs;
1619 uint16_t bad_password_count, logon_count;
1620 uint8_t *hours = NULL;
1621 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1622 uint32_t len = 0;
1623 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1624 uint32_t pwHistLen = 0;
1625 bool ret = True;
1626 fstring tmp_string;
1627 bool expand_explicit = lp_passdb_expand_explicit();
1629 if(sampass == NULL || buf == NULL) {
1630 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1631 return False;
1634 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1636 /* unpack the buffer into variables */
1637 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1638 &logon_time, /* d */
1639 &logoff_time, /* d */
1640 &kickoff_time, /* d */
1641 &bad_password_time, /* d */
1642 &pass_last_set_time, /* d */
1643 &pass_can_change_time, /* d */
1644 &pass_must_change_time, /* d */
1645 &username_len, &username, /* B */
1646 &domain_len, &domain, /* B */
1647 &nt_username_len, &nt_username, /* B */
1648 &fullname_len, &fullname, /* B */
1649 &homedir_len, &homedir, /* B */
1650 &dir_drive_len, &dir_drive, /* B */
1651 &logon_script_len, &logon_script, /* B */
1652 &profile_path_len, &profile_path, /* B */
1653 &acct_desc_len, &acct_desc, /* B */
1654 &workstations_len, &workstations, /* B */
1655 &comment_len, &comment, /* B */
1656 &munged_dial_len, &munged_dial, /* B */
1657 &user_rid, /* d */
1658 &group_rid, /* d */
1659 &lm_pw_len, &lm_pw_ptr, /* B */
1660 &nt_pw_len, &nt_pw_ptr, /* B */
1661 /* Change from V1 is addition of password history field. */
1662 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1663 /* Change from V2 is the uint32_t acb_mask */
1664 &acct_ctrl, /* d */
1665 /* Also "remove_me" field was removed. */
1666 &logon_divs, /* w */
1667 &hours_len, /* d */
1668 &hourslen, &hours, /* B */
1669 &bad_password_count, /* w */
1670 &logon_count, /* w */
1671 &unknown_6); /* d */
1673 if (len == (uint32_t) -1) {
1674 ret = False;
1675 goto done;
1678 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1679 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1680 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1681 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1682 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1683 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1685 pdb_set_username(sampass, username, PDB_SET);
1686 pdb_set_domain(sampass, domain, PDB_SET);
1687 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1688 pdb_set_fullname(sampass, fullname, PDB_SET);
1690 if (homedir) {
1691 fstrcpy( tmp_string, homedir );
1692 if (expand_explicit) {
1693 standard_sub_basic( username, domain, tmp_string,
1694 sizeof(tmp_string) );
1696 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1698 else {
1699 pdb_set_homedir(sampass,
1700 talloc_sub_basic(sampass, username, domain,
1701 lp_logon_home()),
1702 PDB_DEFAULT);
1705 if (dir_drive)
1706 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1707 else
1708 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1710 if (logon_script) {
1711 fstrcpy( tmp_string, logon_script );
1712 if (expand_explicit) {
1713 standard_sub_basic( username, domain, tmp_string,
1714 sizeof(tmp_string) );
1716 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1718 else {
1719 pdb_set_logon_script(sampass,
1720 talloc_sub_basic(sampass, username, domain,
1721 lp_logon_script()),
1722 PDB_DEFAULT);
1725 if (profile_path) {
1726 fstrcpy( tmp_string, profile_path );
1727 if (expand_explicit) {
1728 standard_sub_basic( username, domain, tmp_string,
1729 sizeof(tmp_string) );
1731 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1733 else {
1734 pdb_set_profile_path(sampass,
1735 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1736 PDB_DEFAULT);
1739 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1740 pdb_set_comment(sampass, comment, PDB_SET);
1741 pdb_set_workstations(sampass, workstations, PDB_SET);
1742 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1744 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1745 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1746 ret = False;
1747 goto done;
1751 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1752 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1753 ret = False;
1754 goto done;
1758 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1759 if (pwHistLen) {
1760 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1761 if (!pw_hist) {
1762 ret = False;
1763 goto done;
1765 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1766 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1767 int i;
1768 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1769 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1770 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1771 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1772 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1773 PW_HISTORY_ENTRY_LEN);
1776 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1777 SAFE_FREE(pw_hist);
1778 ret = False;
1779 goto done;
1781 SAFE_FREE(pw_hist);
1782 } else {
1783 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1786 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1787 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1788 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1789 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1790 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1791 /* Change from V2 is the uint32_t acct_ctrl */
1792 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1793 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1794 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1796 done:
1798 SAFE_FREE(username);
1799 SAFE_FREE(domain);
1800 SAFE_FREE(nt_username);
1801 SAFE_FREE(fullname);
1802 SAFE_FREE(homedir);
1803 SAFE_FREE(dir_drive);
1804 SAFE_FREE(logon_script);
1805 SAFE_FREE(profile_path);
1806 SAFE_FREE(acct_desc);
1807 SAFE_FREE(workstations);
1808 SAFE_FREE(munged_dial);
1809 SAFE_FREE(comment);
1810 SAFE_FREE(lm_pw_ptr);
1811 SAFE_FREE(nt_pw_ptr);
1812 SAFE_FREE(nt_pw_hist_ptr);
1813 SAFE_FREE(hours);
1815 return ret;
1818 /*********************************************************************
1819 *********************************************************************/
1821 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1823 size_t len, buflen;
1825 /* times are stored as 32bit integer
1826 take care on system with 64bit wide time_t
1827 --SSS */
1828 uint32_t logon_time,
1829 logoff_time,
1830 kickoff_time,
1831 bad_password_time,
1832 pass_last_set_time,
1833 pass_can_change_time,
1834 pass_must_change_time;
1836 uint32_t user_rid, group_rid;
1838 const char *username;
1839 const char *domain;
1840 const char *nt_username;
1841 const char *dir_drive;
1842 const char *comment;
1843 const char *munged_dial;
1844 const char *fullname;
1845 const char *homedir;
1846 const char *logon_script;
1847 const char *profile_path;
1848 const char *acct_desc;
1849 const char *workstations;
1850 uint32_t username_len, domain_len, nt_username_len,
1851 dir_drive_len, comment_len, munged_dial_len,
1852 fullname_len, homedir_len, logon_script_len,
1853 profile_path_len, acct_desc_len, workstations_len;
1855 const uint8_t *lm_pw;
1856 const uint8_t *nt_pw;
1857 const uint8_t *nt_pw_hist;
1858 uint32_t lm_pw_len = 16;
1859 uint32_t nt_pw_len = 16;
1860 uint32_t nt_pw_hist_len;
1861 uint32_t pwHistLen = 0;
1863 *buf = NULL;
1864 buflen = 0;
1866 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1867 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1868 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1869 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1870 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1871 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1872 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1874 user_rid = pdb_get_user_rid(sampass);
1875 group_rid = pdb_get_group_rid(sampass);
1877 username = pdb_get_username(sampass);
1878 if (username) {
1879 username_len = strlen(username) +1;
1880 } else {
1881 username_len = 0;
1884 domain = pdb_get_domain(sampass);
1885 if (domain) {
1886 domain_len = strlen(domain) +1;
1887 } else {
1888 domain_len = 0;
1891 nt_username = pdb_get_nt_username(sampass);
1892 if (nt_username) {
1893 nt_username_len = strlen(nt_username) +1;
1894 } else {
1895 nt_username_len = 0;
1898 fullname = pdb_get_fullname(sampass);
1899 if (fullname) {
1900 fullname_len = strlen(fullname) +1;
1901 } else {
1902 fullname_len = 0;
1906 * Only updates fields which have been set (not defaults from smb.conf)
1909 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1910 dir_drive = pdb_get_dir_drive(sampass);
1911 } else {
1912 dir_drive = NULL;
1914 if (dir_drive) {
1915 dir_drive_len = strlen(dir_drive) +1;
1916 } else {
1917 dir_drive_len = 0;
1920 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1921 homedir = pdb_get_homedir(sampass);
1922 } else {
1923 homedir = NULL;
1925 if (homedir) {
1926 homedir_len = strlen(homedir) +1;
1927 } else {
1928 homedir_len = 0;
1931 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1932 logon_script = pdb_get_logon_script(sampass);
1933 } else {
1934 logon_script = NULL;
1936 if (logon_script) {
1937 logon_script_len = strlen(logon_script) +1;
1938 } else {
1939 logon_script_len = 0;
1942 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1943 profile_path = pdb_get_profile_path(sampass);
1944 } else {
1945 profile_path = NULL;
1947 if (profile_path) {
1948 profile_path_len = strlen(profile_path) +1;
1949 } else {
1950 profile_path_len = 0;
1953 lm_pw = pdb_get_lanman_passwd(sampass);
1954 if (!lm_pw) {
1955 lm_pw_len = 0;
1958 nt_pw = pdb_get_nt_passwd(sampass);
1959 if (!nt_pw) {
1960 nt_pw_len = 0;
1963 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1964 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1965 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1966 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1967 } else {
1968 nt_pw_hist_len = 0;
1971 acct_desc = pdb_get_acct_desc(sampass);
1972 if (acct_desc) {
1973 acct_desc_len = strlen(acct_desc) +1;
1974 } else {
1975 acct_desc_len = 0;
1978 workstations = pdb_get_workstations(sampass);
1979 if (workstations) {
1980 workstations_len = strlen(workstations) +1;
1981 } else {
1982 workstations_len = 0;
1985 comment = pdb_get_comment(sampass);
1986 if (comment) {
1987 comment_len = strlen(comment) +1;
1988 } else {
1989 comment_len = 0;
1992 munged_dial = pdb_get_munged_dial(sampass);
1993 if (munged_dial) {
1994 munged_dial_len = strlen(munged_dial) +1;
1995 } else {
1996 munged_dial_len = 0;
1999 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
2001 /* one time to get the size needed */
2002 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
2003 logon_time, /* d */
2004 logoff_time, /* d */
2005 kickoff_time, /* d */
2006 bad_password_time, /* d */
2007 pass_last_set_time, /* d */
2008 pass_can_change_time, /* d */
2009 pass_must_change_time, /* d */
2010 username_len, username, /* B */
2011 domain_len, domain, /* B */
2012 nt_username_len, nt_username, /* B */
2013 fullname_len, fullname, /* B */
2014 homedir_len, homedir, /* B */
2015 dir_drive_len, dir_drive, /* B */
2016 logon_script_len, logon_script, /* B */
2017 profile_path_len, profile_path, /* B */
2018 acct_desc_len, acct_desc, /* B */
2019 workstations_len, workstations, /* B */
2020 comment_len, comment, /* B */
2021 munged_dial_len, munged_dial, /* B */
2022 user_rid, /* d */
2023 group_rid, /* d */
2024 lm_pw_len, lm_pw, /* B */
2025 nt_pw_len, nt_pw, /* B */
2026 nt_pw_hist_len, nt_pw_hist, /* B */
2027 pdb_get_acct_ctrl(sampass), /* d */
2028 pdb_get_logon_divs(sampass), /* w */
2029 pdb_get_hours_len(sampass), /* d */
2030 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2031 pdb_get_bad_password_count(sampass), /* w */
2032 pdb_get_logon_count(sampass), /* w */
2033 pdb_get_unknown_6(sampass)); /* d */
2035 if (size_only) {
2036 return buflen;
2039 /* malloc the space needed */
2040 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
2041 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
2042 return (-1);
2045 /* now for the real call to tdb_pack() */
2046 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2047 logon_time, /* d */
2048 logoff_time, /* d */
2049 kickoff_time, /* d */
2050 bad_password_time, /* d */
2051 pass_last_set_time, /* d */
2052 pass_can_change_time, /* d */
2053 pass_must_change_time, /* d */
2054 username_len, username, /* B */
2055 domain_len, domain, /* B */
2056 nt_username_len, nt_username, /* B */
2057 fullname_len, fullname, /* B */
2058 homedir_len, homedir, /* B */
2059 dir_drive_len, dir_drive, /* B */
2060 logon_script_len, logon_script, /* B */
2061 profile_path_len, profile_path, /* B */
2062 acct_desc_len, acct_desc, /* B */
2063 workstations_len, workstations, /* B */
2064 comment_len, comment, /* B */
2065 munged_dial_len, munged_dial, /* B */
2066 user_rid, /* d */
2067 group_rid, /* d */
2068 lm_pw_len, lm_pw, /* B */
2069 nt_pw_len, nt_pw, /* B */
2070 nt_pw_hist_len, nt_pw_hist, /* B */
2071 pdb_get_acct_ctrl(sampass), /* d */
2072 pdb_get_logon_divs(sampass), /* w */
2073 pdb_get_hours_len(sampass), /* d */
2074 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2075 pdb_get_bad_password_count(sampass), /* w */
2076 pdb_get_logon_count(sampass), /* w */
2077 pdb_get_unknown_6(sampass)); /* d */
2079 /* check to make sure we got it correct */
2080 if (buflen != len) {
2081 DEBUG(0, ("init_buffer_from_samu_v3: something odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2082 (unsigned long)buflen, (unsigned long)len));
2083 /* error */
2084 SAFE_FREE (*buf);
2085 return (-1);
2088 return (buflen);
2091 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2093 /* nothing changed between V3 and V4 */
2094 return init_samu_from_buffer_v3(sampass, buf, buflen);
2097 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2099 /* nothing changed between V3 and V4 */
2100 return init_buffer_from_samu_v3(buf, sampass, size_only);
2103 /**********************************************************************
2104 Intialize a struct samu struct from a BYTE buffer of size len
2105 *********************************************************************/
2107 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2108 uint8_t *buf, uint32_t buflen)
2110 switch (level) {
2111 case SAMU_BUFFER_V0:
2112 return init_samu_from_buffer_v0(sampass, buf, buflen);
2113 case SAMU_BUFFER_V1:
2114 return init_samu_from_buffer_v1(sampass, buf, buflen);
2115 case SAMU_BUFFER_V2:
2116 return init_samu_from_buffer_v2(sampass, buf, buflen);
2117 case SAMU_BUFFER_V3:
2118 return init_samu_from_buffer_v3(sampass, buf, buflen);
2119 case SAMU_BUFFER_V4:
2120 return init_samu_from_buffer_v4(sampass, buf, buflen);
2123 return false;
2126 /**********************************************************************
2127 Intialize a BYTE buffer from a struct samu struct
2128 *********************************************************************/
2130 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2132 return init_buffer_from_samu_v4(buf, sampass, size_only);
2135 /*********************************************************************
2136 *********************************************************************/
2138 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2140 uint8_t *buf = NULL;
2141 int len;
2143 len = init_buffer_from_samu(&buf, src, False);
2144 if (len == -1 || !buf) {
2145 SAFE_FREE(buf);
2146 return False;
2149 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2150 free(buf);
2151 return False;
2154 dst->methods = src->methods;
2156 if ( src->unix_pw ) {
2157 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2158 if (!dst->unix_pw) {
2159 free(buf);
2160 return False;
2164 if (src->group_sid) {
2165 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2168 free(buf);
2169 return True;
2172 /*********************************************************************
2173 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2174 *********************************************************************/
2176 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2178 time_t LastBadPassword;
2179 uint16_t BadPasswordCount;
2180 uint32_t resettime;
2181 bool res;
2183 BadPasswordCount = pdb_get_bad_password_count(sampass);
2184 if (!BadPasswordCount) {
2185 DEBUG(9, ("No bad password attempts.\n"));
2186 return True;
2189 become_root();
2190 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2191 unbecome_root();
2193 if (!res) {
2194 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2195 return False;
2198 /* First, check if there is a reset time to compare */
2199 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2200 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2201 return True;
2204 LastBadPassword = pdb_get_bad_password_time(sampass);
2205 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2206 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2207 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2208 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2209 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2210 if (updated) {
2211 *updated = True;
2215 return True;
2218 /*********************************************************************
2219 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2220 *********************************************************************/
2222 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2224 uint32_t duration;
2225 time_t LastBadPassword;
2226 bool res;
2228 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2229 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2230 pdb_get_username(sampass)));
2231 return True;
2234 become_root();
2235 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2236 unbecome_root();
2238 if (!res) {
2239 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2240 return False;
2243 /* First, check if there is a duration to compare */
2244 if ((duration == (uint32_t) -1) || (duration == 0)) {
2245 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2246 return True;
2249 LastBadPassword = pdb_get_bad_password_time(sampass);
2250 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2251 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2253 if (LastBadPassword == (time_t)0) {
2254 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2255 "administratively locked out with no bad password "
2256 "time. Leaving locked out.\n",
2257 pdb_get_username(sampass) ));
2258 return True;
2261 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2262 pdb_set_acct_ctrl(sampass,
2263 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2264 PDB_CHANGED);
2265 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2266 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2267 if (updated) {
2268 *updated = True;
2272 return True;
2275 /*********************************************************************
2276 Increment the bad_password_count
2277 *********************************************************************/
2279 bool pdb_increment_bad_password_count(struct samu *sampass)
2281 uint32_t account_policy_lockout;
2282 bool autolock_updated = False, badpw_updated = False;
2283 bool ret;
2285 /* Retrieve the account lockout policy */
2286 become_root();
2287 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2288 unbecome_root();
2289 if ( !ret ) {
2290 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2291 return False;
2294 /* If there is no policy, we don't need to continue checking */
2295 if (!account_policy_lockout) {
2296 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2297 return True;
2300 /* Check if the autolock needs to be cleared */
2301 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2302 return False;
2304 /* Check if the badpw count needs to be reset */
2305 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2306 return False;
2309 Ok, now we can assume that any resetting that needs to be
2310 done has been done, and just get on with incrementing
2311 and autolocking if necessary
2314 pdb_set_bad_password_count(sampass,
2315 pdb_get_bad_password_count(sampass)+1,
2316 PDB_CHANGED);
2317 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2320 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2321 return True;
2323 if (!pdb_set_acct_ctrl(sampass,
2324 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2325 PDB_CHANGED)) {
2326 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2327 return False;
2330 return True;
2333 bool is_dc_trusted_domain_situation(const char *domain_name)
2335 return IS_DC && !strequal(domain_name, lp_workgroup());
2338 /*******************************************************************
2339 Wrapper around retrieving the clear text trust account password.
2340 appropriate account name is stored in account_name.
2341 Caller must free password, but not account_name.
2342 *******************************************************************/
2344 static bool get_trust_pw_clear2(const char *domain,
2345 const char **account_name,
2346 enum netr_SchannelType *channel,
2347 char **cur_pw,
2348 time_t *_last_set_time,
2349 char **prev_pw)
2351 char *pwd;
2352 time_t last_set_time;
2354 if (cur_pw != NULL) {
2355 *cur_pw = NULL;
2357 if (_last_set_time != NULL) {
2358 *_last_set_time = 0;
2360 if (prev_pw != NULL) {
2361 *prev_pw = NULL;
2364 /* if we are a DC and this is not our domain, then lookup an account
2365 * for the domain trust */
2367 if (is_dc_trusted_domain_situation(domain)) {
2368 if (!lp_allow_trusted_domains()) {
2369 return false;
2372 if (!pdb_get_trusteddom_pw(domain, cur_pw, NULL,
2373 &last_set_time))
2375 DEBUG(0, ("get_trust_pw: could not fetch trust "
2376 "account password for trusted domain %s\n",
2377 domain));
2378 return false;
2381 if (channel != NULL) {
2382 *channel = SEC_CHAN_DOMAIN;
2385 if (account_name != NULL) {
2386 *account_name = lp_workgroup();
2389 if (_last_set_time != NULL) {
2390 *_last_set_time = last_set_time;
2393 return true;
2397 * Since we can only be member of one single domain, we are now
2398 * in a member situation:
2400 * - Either we are a DC (selfjoined) and the domain is our
2401 * own domain.
2402 * - Or we are on a member and the domain is our own or some
2403 * other (potentially trusted) domain.
2405 * In both cases, we can only get the machine account password
2406 * for our own domain to connect to our own dc. (For a member,
2407 * request to trusted domains are performed through our dc.)
2409 * So we simply use our own domain name to retrieve the
2410 * machine account passowrd and ignore the request domain here.
2413 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2415 if (pwd != NULL) {
2416 struct timeval expire;
2418 *cur_pw = pwd;
2420 if (account_name != NULL) {
2421 *account_name = lp_netbios_name();
2424 if (_last_set_time != NULL) {
2425 *_last_set_time = last_set_time;
2428 if (prev_pw == NULL) {
2429 return true;
2432 ZERO_STRUCT(expire);
2433 expire.tv_sec = lp_machine_password_timeout();
2434 expire.tv_sec /= 2;
2435 expire.tv_sec += last_set_time;
2436 if (timeval_expired(&expire)) {
2437 return true;
2440 pwd = secrets_fetch_prev_machine_password(lp_workgroup());
2441 if (pwd != NULL) {
2442 *prev_pw = pwd;
2445 return true;
2448 DEBUG(5, ("get_trust_pw_clear2: could not fetch clear text trust "
2449 "account password for domain %s\n", domain));
2450 return false;
2453 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2454 const char **account_name,
2455 enum netr_SchannelType *channel)
2457 return get_trust_pw_clear2(domain,
2458 account_name,
2459 channel,
2460 ret_pwd,
2461 NULL,
2462 NULL);
2465 /*******************************************************************
2466 Wrapper around retrieving the trust account password.
2467 appropriate account name is stored in account_name.
2468 *******************************************************************/
2470 static bool get_trust_pw_hash2(const char *domain,
2471 const char **account_name,
2472 enum netr_SchannelType *channel,
2473 struct samr_Password *current_nt_hash,
2474 time_t *last_set_time,
2475 struct samr_Password **_previous_nt_hash)
2477 char *cur_pw = NULL;
2478 char *prev_pw = NULL;
2479 char **_prev_pw = NULL;
2480 bool ok;
2482 if (_previous_nt_hash != NULL) {
2483 *_previous_nt_hash = NULL;
2484 _prev_pw = &prev_pw;
2487 ok = get_trust_pw_clear2(domain, account_name, channel,
2488 &cur_pw, last_set_time, _prev_pw);
2489 if (ok) {
2490 struct samr_Password *previous_nt_hash = NULL;
2492 E_md4hash(cur_pw, current_nt_hash->hash);
2493 SAFE_FREE(cur_pw);
2495 if (prev_pw == NULL) {
2496 return true;
2499 previous_nt_hash = SMB_MALLOC_P(struct samr_Password);
2500 if (previous_nt_hash == NULL) {
2501 return false;
2504 E_md4hash(prev_pw, previous_nt_hash->hash);
2505 SAFE_FREE(prev_pw);
2507 *_previous_nt_hash = previous_nt_hash;
2508 return true;
2509 } else if (is_dc_trusted_domain_situation(domain)) {
2510 return false;
2513 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2515 if (secrets_fetch_trust_account_password_legacy(domain,
2516 current_nt_hash->hash,
2517 last_set_time,
2518 channel))
2520 if (account_name != NULL) {
2521 *account_name = lp_netbios_name();
2524 return true;
2527 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2528 "password for domain %s\n", domain));
2529 return False;
2532 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2533 const char **account_name,
2534 enum netr_SchannelType *channel)
2536 struct samr_Password current_nt_hash;
2537 bool ok;
2539 ok = get_trust_pw_hash2(domain, account_name, channel,
2540 &current_nt_hash, NULL, NULL);
2541 if (!ok) {
2542 return false;
2545 memcpy(ret_pwd, current_nt_hash.hash, sizeof(current_nt_hash.hash));
2546 return true;
2549 NTSTATUS pdb_get_trust_credentials(const char *netbios_domain,
2550 const char *dns_domain, /* optional */
2551 TALLOC_CTX *mem_ctx,
2552 struct cli_credentials **_creds)
2554 TALLOC_CTX *frame = talloc_stackframe();
2555 NTSTATUS status;
2556 struct loadparm_context *lp_ctx;
2557 enum netr_SchannelType channel;
2558 time_t last_set_time;
2559 const char *_account_name;
2560 const char *account_name;
2561 char *cur_pw = NULL;
2562 char *prev_pw = NULL;
2563 struct samr_Password cur_nt_hash;
2564 struct cli_credentials *creds = NULL;
2565 bool ok;
2568 * If this is our primary trust relationship, use the common
2569 * code to read the secrets.ldb or secrets.tdb file.
2571 if (strequal(netbios_domain, lp_workgroup())) {
2572 struct db_context *db_ctx = secrets_db_ctx();
2573 if (db_ctx == NULL) {
2574 DEBUG(1, ("failed to open secrets.tdb to obtain our trust credentials for %s\n",
2575 netbios_domain));
2576 status = NT_STATUS_INTERNAL_ERROR;
2577 goto fail;
2580 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2581 if (lp_ctx == NULL) {
2582 DEBUG(1, ("loadparm_init_s3 failed\n"));
2583 status = NT_STATUS_INTERNAL_ERROR;
2584 goto fail;
2587 creds = cli_credentials_init(mem_ctx);
2588 if (creds == NULL) {
2589 status = NT_STATUS_NO_MEMORY;
2590 goto fail;
2593 ok = cli_credentials_set_conf(creds, lp_ctx);
2594 if (!ok) {
2595 status = NT_STATUS_INTERNAL_ERROR;
2596 goto fail;
2599 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2600 if (!ok) {
2601 status = NT_STATUS_NO_MEMORY;
2602 goto fail;
2605 status = cli_credentials_set_machine_account_db_ctx(creds,
2606 lp_ctx,
2607 db_ctx);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 goto fail;
2611 goto done;
2612 } else if (!IS_DC) {
2613 DEBUG(1, ("Refusing to get trust account info for %s, "
2614 "which is not our primary domain %s, "
2615 "as we are not a DC\n",
2616 netbios_domain, lp_workgroup()));
2617 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2618 goto fail;
2621 status = pdb_get_trusteddom_creds(netbios_domain, mem_ctx, &creds);
2622 if (NT_STATUS_IS_OK(status)) {
2623 goto done;
2625 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
2626 goto fail;
2629 ok = get_trust_pw_clear2(netbios_domain,
2630 &_account_name,
2631 &channel,
2632 &cur_pw,
2633 &last_set_time,
2634 &prev_pw);
2635 if (!ok) {
2636 ok = get_trust_pw_hash2(netbios_domain,
2637 &_account_name,
2638 &channel,
2639 &cur_nt_hash,
2640 &last_set_time,
2641 NULL);
2642 if (!ok) {
2643 DEBUG(1, ("get_trust_pw_*2 failed for domain[%s]\n",
2644 netbios_domain));
2645 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2646 goto fail;
2650 account_name = talloc_asprintf(frame, "%s$", _account_name);
2651 if (account_name == NULL) {
2652 status = NT_STATUS_NO_MEMORY;
2653 goto fail;
2656 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2657 if (lp_ctx == NULL) {
2658 DEBUG(1, ("loadparm_init_s3 failed\n"));
2659 status = NT_STATUS_INTERNAL_ERROR;
2660 goto fail;
2663 creds = cli_credentials_init(mem_ctx);
2664 if (creds == NULL) {
2665 status = NT_STATUS_NO_MEMORY;
2666 goto fail;
2669 ok = cli_credentials_set_conf(creds, lp_ctx);
2670 if (!ok) {
2671 status = NT_STATUS_INTERNAL_ERROR;
2672 goto fail;
2675 cli_credentials_set_secure_channel_type(creds, channel);
2676 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2678 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2679 if (!ok) {
2680 status = NT_STATUS_NO_MEMORY;
2681 goto fail;
2684 if (dns_domain != NULL) {
2685 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2686 if (!ok) {
2687 status = NT_STATUS_NO_MEMORY;
2688 goto fail;
2692 * It's not possible to use NTLMSSP with a domain trust account.
2694 cli_credentials_set_kerberos_state(creds,
2695 CRED_USE_KERBEROS_REQUIRED,
2696 CRED_SPECIFIED);
2697 } else {
2699 * We can't use kerberos against an NT4 domain.
2701 * We should have a mode that also disallows NTLMSSP here,
2702 * as only NETLOGON SCHANNEL is possible.
2704 cli_credentials_set_kerberos_state(creds,
2705 CRED_USE_KERBEROS_DISABLED,
2706 CRED_SPECIFIED);
2709 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2710 if (!ok) {
2711 status = NT_STATUS_NO_MEMORY;
2712 goto fail;
2715 if (cur_pw == NULL) {
2716 ok = cli_credentials_set_nt_hash(creds, &cur_nt_hash, CRED_SPECIFIED);
2717 if (!ok) {
2718 status = NT_STATUS_NO_MEMORY;
2719 goto fail;
2722 * We currently can't do kerberos just with an NTHASH.
2724 cli_credentials_set_kerberos_state(creds,
2725 CRED_USE_KERBEROS_DISABLED,
2726 CRED_SPECIFIED);
2727 goto done;
2730 ok = cli_credentials_set_password(creds, cur_pw, CRED_SPECIFIED);
2731 if (!ok) {
2732 status = NT_STATUS_NO_MEMORY;
2733 goto fail;
2736 if (prev_pw != NULL) {
2737 ok = cli_credentials_set_old_password(creds, prev_pw, CRED_SPECIFIED);
2738 if (!ok) {
2739 status = NT_STATUS_NO_MEMORY;
2740 goto fail;
2744 done:
2745 *_creds = creds;
2746 creds = NULL;
2747 status = NT_STATUS_OK;
2748 fail:
2749 TALLOC_FREE(creds);
2750 SAFE_FREE(cur_pw);
2751 SAFE_FREE(prev_pw);
2752 TALLOC_FREE(frame);
2753 return status;