s4 dns: Move record lookup to dns_utils.c
[Samba/gebeck_regimport.git] / source3 / passdb / passdb.c
blob276e0314c84295ab636d9ac9104af5f09f8fdd1e
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"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_PASSDB
37 /******************************************************************
38 Get the default domain/netbios name to be used when
39 testing authentication.
41 LEGACY: this function provides the legacy domain mapping used with
42 the lp_map_untrusted_to_domain() parameter
43 ******************************************************************/
45 const char *my_sam_name(void)
47 /* Standalone servers can only use the local netbios name */
48 if ( lp_server_role() == ROLE_STANDALONE )
49 return lp_netbios_name();
51 /* Default to the DOMAIN name when not specified */
52 return lp_workgroup();
55 /**********************************************************************
56 ***********************************************************************/
58 static int samu_destroy(struct samu *user)
60 data_blob_clear_free( &user->lm_pw );
61 data_blob_clear_free( &user->nt_pw );
63 if ( user->plaintext_pw )
64 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
66 return 0;
69 /**********************************************************************
70 generate a new struct samuser
71 ***********************************************************************/
73 struct samu *samu_new( TALLOC_CTX *ctx )
75 struct samu *user;
77 if ( !(user = talloc_zero( ctx, struct samu )) ) {
78 DEBUG(0,("samuser_new: Talloc failed!\n"));
79 return NULL;
82 talloc_set_destructor( user, samu_destroy );
84 /* no initial methods */
86 user->methods = NULL;
88 /* Don't change these timestamp settings without a good reason.
89 They are important for NT member server compatibility. */
91 user->logon_time = (time_t)0;
92 user->pass_last_set_time = (time_t)0;
93 user->pass_can_change_time = (time_t)0;
94 user->logoff_time = get_time_t_max();
95 user->kickoff_time = get_time_t_max();
96 user->pass_must_change_time = get_time_t_max();
97 user->fields_present = 0x00ffffff;
98 user->logon_divs = 168; /* hours per week */
99 user->hours_len = 21; /* 21 times 8 bits = 168 */
100 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
101 user->bad_password_count = 0;
102 user->logon_count = 0;
103 user->unknown_6 = 0x000004ec; /* don't know */
105 /* Some parts of samba strlen their pdb_get...() returns,
106 so this keeps the interface unchanged for now. */
108 user->username = "";
109 user->domain = "";
110 user->nt_username = "";
111 user->full_name = "";
112 user->home_dir = "";
113 user->logon_script = "";
114 user->profile_path = "";
115 user->acct_desc = "";
116 user->workstations = "";
117 user->comment = "";
118 user->munged_dial = "";
120 user->plaintext_pw = NULL;
122 /* Unless we know otherwise have a Account Control Bit
123 value of 'normal user'. This helps User Manager, which
124 asks for a filtered list of users. */
126 user->acct_ctrl = ACB_NORMAL;
128 return user;
131 static int count_commas(const char *str)
133 int num_commas = 0;
134 const char *comma = str;
136 while ((comma = strchr(comma, ',')) != NULL) {
137 comma += 1;
138 num_commas += 1;
140 return num_commas;
143 /*********************************************************************
144 Initialize a struct samu from a struct passwd including the user
145 and group SIDs. The *user structure is filled out with the Unix
146 attributes and a user SID.
147 *********************************************************************/
149 static NTSTATUS samu_set_unix_internal(struct pdb_methods *methods,
150 struct samu *user, const struct passwd *pwd, bool create)
152 const char *guest_account = lp_guestaccount();
153 const char *domain = lp_netbios_name();
154 char *fullname;
155 uint32_t urid;
157 if ( !pwd ) {
158 return NT_STATUS_NO_SUCH_USER;
161 /* Basic properties based upon the Unix account information */
163 pdb_set_username(user, pwd->pw_name, PDB_SET);
165 fullname = NULL;
167 if (count_commas(pwd->pw_gecos) == 3) {
169 * Heuristic: This seems to be a gecos field that has been
170 * edited by chfn(1). Only use the part before the first
171 * comma. Fixes bug 5198.
173 fullname = talloc_strndup(
174 talloc_tos(), pwd->pw_gecos,
175 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
178 if (fullname != NULL) {
179 pdb_set_fullname(user, fullname, PDB_SET);
180 } else {
181 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
183 TALLOC_FREE(fullname);
185 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
186 #if 0
187 /* This can lead to a primary group of S-1-22-2-XX which
188 will be rejected by other parts of the Samba code.
189 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
190 --jerry */
192 gid_to_sid(&group_sid, pwd->pw_gid);
193 pdb_set_group_sid(user, &group_sid, PDB_SET);
194 #endif
196 /* save the password structure for later use */
198 user->unix_pw = tcopy_passwd( user, pwd );
200 /* Special case for the guest account which must have a RID of 501 */
202 if ( strequal( pwd->pw_name, guest_account ) ) {
203 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_RID_GUEST, PDB_DEFAULT)) {
204 return NT_STATUS_NO_SUCH_USER;
206 return NT_STATUS_OK;
209 /* Non-guest accounts...Check for a workstation or user account */
211 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
212 /* workstation */
214 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
215 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
216 pwd->pw_name));
217 return NT_STATUS_INVALID_COMPUTER_NAME;
220 else {
221 /* user */
223 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
224 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
225 pwd->pw_name));
226 return NT_STATUS_INVALID_ACCOUNT_NAME;
229 /* set some basic attributes */
231 pdb_set_profile_path(user, talloc_sub_specified(user,
232 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
233 PDB_DEFAULT);
234 pdb_set_homedir(user, talloc_sub_specified(user,
235 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
236 PDB_DEFAULT);
237 pdb_set_dir_drive(user, talloc_sub_specified(user,
238 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
239 PDB_DEFAULT);
240 pdb_set_logon_script(user, talloc_sub_specified(user,
241 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
242 PDB_DEFAULT);
245 /* Now deal with the user SID. If we have a backend that can generate
246 RIDs, then do so. But sometimes the caller just wanted a structure
247 initialized and will fill in these fields later (such as from a
248 netr_SamInfo3 structure) */
250 if ( create && (methods->capabilities(methods) & PDB_CAP_STORE_RIDS)) {
251 uint32_t user_rid;
252 struct dom_sid user_sid;
254 if ( !methods->new_rid(methods, &user_rid) ) {
255 DEBUG(3, ("Could not allocate a new RID\n"));
256 return NT_STATUS_ACCESS_DENIED;
259 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
261 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
262 DEBUG(3, ("pdb_set_user_sid failed\n"));
263 return NT_STATUS_INTERNAL_ERROR;
266 return NT_STATUS_OK;
269 /* generate a SID for the user with the RID algorithm */
271 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
273 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
274 return NT_STATUS_INTERNAL_ERROR;
277 return NT_STATUS_OK;
280 /********************************************************************
281 Set the Unix user attributes
282 ********************************************************************/
284 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
286 return samu_set_unix_internal( NULL, user, pwd, False );
289 NTSTATUS samu_alloc_rid_unix(struct pdb_methods *methods,
290 struct samu *user, const struct passwd *pwd)
292 return samu_set_unix_internal( methods, user, pwd, True );
295 /**********************************************************
296 Encode the account control bits into a string.
297 length = length of string to encode into (including terminating
298 null). length *MUST BE MORE THAN 2* !
299 **********************************************************/
301 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
303 fstring acct_str;
304 char *result;
306 size_t i = 0;
308 SMB_ASSERT(length <= sizeof(acct_str));
310 acct_str[i++] = '[';
312 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
313 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
314 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
315 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
316 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
317 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
318 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
319 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
320 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
321 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
322 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
324 for ( ; i < length - 2 ; i++ )
325 acct_str[i] = ' ';
327 i = length - 2;
328 acct_str[i++] = ']';
329 acct_str[i++] = '\0';
331 result = talloc_strdup(talloc_tos(), acct_str);
332 SMB_ASSERT(result != NULL);
333 return result;
336 /**********************************************************
337 Decode the account control bits from a string.
338 **********************************************************/
340 uint32_t pdb_decode_acct_ctrl(const char *p)
342 uint32_t acct_ctrl = 0;
343 bool finished = false;
346 * Check if the account type bits have been encoded after the
347 * NT password (in the form [NDHTUWSLXI]).
350 if (*p != '[')
351 return 0;
353 for (p++; *p && !finished; p++) {
354 switch (*p) {
355 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
356 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
357 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
358 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
359 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
360 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
361 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
362 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
363 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
364 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
365 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
366 case ' ': { break; }
367 case ':':
368 case '\n':
369 case '\0':
370 case ']':
371 default: { finished = true; }
375 return acct_ctrl;
378 /*************************************************************
379 Routine to set 32 hex password characters from a 16 byte array.
380 **************************************************************/
382 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
384 if (pwd != NULL) {
385 int i;
386 for (i = 0; i < 16; i++)
387 slprintf(&p[i*2], 3, "%02X", pwd[i]);
388 } else {
389 if (acct_ctrl & ACB_PWNOTREQ)
390 strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
391 else
392 strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
396 /*************************************************************
397 Routine to get the 32 hex characters and turn them
398 into a 16 byte array.
399 **************************************************************/
401 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
403 int i;
404 unsigned char lonybble, hinybble;
405 const char *hexchars = "0123456789ABCDEF";
406 char *p1, *p2;
408 if (!p)
409 return false;
411 for (i = 0; i < 32; i += 2) {
412 hinybble = toupper_m(p[i]);
413 lonybble = toupper_m(p[i + 1]);
415 p1 = strchr(hexchars, hinybble);
416 p2 = strchr(hexchars, lonybble);
418 if (!p1 || !p2)
419 return false;
421 hinybble = PTR_DIFF(p1, hexchars);
422 lonybble = PTR_DIFF(p2, hexchars);
424 pwd[i / 2] = (hinybble << 4) | lonybble;
426 return true;
429 /*************************************************************
430 Routine to set 42 hex hours characters from a 21 byte array.
431 **************************************************************/
433 void pdb_sethexhours(char *p, const unsigned char *hours)
435 if (hours != NULL) {
436 int i;
437 for (i = 0; i < 21; i++) {
438 slprintf(&p[i*2], 3, "%02X", hours[i]);
440 } else {
441 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
445 /*************************************************************
446 Routine to get the 42 hex characters and turn them
447 into a 21 byte array.
448 **************************************************************/
450 bool pdb_gethexhours(const char *p, unsigned char *hours)
452 int i;
453 unsigned char lonybble, hinybble;
454 const char *hexchars = "0123456789ABCDEF";
455 char *p1, *p2;
457 if (!p) {
458 return (False);
461 for (i = 0; i < 42; i += 2) {
462 hinybble = toupper_m(p[i]);
463 lonybble = toupper_m(p[i + 1]);
465 p1 = strchr(hexchars, hinybble);
466 p2 = strchr(hexchars, lonybble);
468 if (!p1 || !p2) {
469 return (False);
472 hinybble = PTR_DIFF(p1, hexchars);
473 lonybble = PTR_DIFF(p2, hexchars);
475 hours[i / 2] = (hinybble << 4) | lonybble;
477 return (True);
480 /********************************************************************
481 ********************************************************************/
483 int algorithmic_rid_base(void)
485 int rid_offset;
487 rid_offset = lp_algorithmic_rid_base();
489 if (rid_offset < BASE_RID) {
490 /* Try to prevent admin foot-shooting, we can't put algorithmic
491 rids below 1000, that's the 'well known RIDs' on NT */
492 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
493 rid_offset = BASE_RID;
495 if (rid_offset & 1) {
496 DEBUG(0, ("algorithmic rid base must be even\n"));
497 rid_offset += 1;
499 return rid_offset;
502 /*******************************************************************
503 Converts NT user RID to a UNIX uid.
504 ********************************************************************/
506 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
508 int rid_offset = algorithmic_rid_base();
509 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
512 uid_t max_algorithmic_uid(void)
514 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
517 /*******************************************************************
518 converts UNIX uid to an NT User RID.
519 ********************************************************************/
521 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
523 int rid_offset = algorithmic_rid_base();
524 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
527 /*******************************************************************
528 Converts NT group RID to a UNIX gid.
529 ********************************************************************/
531 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
533 int rid_offset = algorithmic_rid_base();
534 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
537 gid_t max_algorithmic_gid(void)
539 return pdb_group_rid_to_gid(0xffffffff);
542 /*******************************************************************
543 converts NT Group RID to a UNIX uid.
545 warning: you must not call that function only
546 you must do a call to the group mapping first.
547 there is not anymore a direct link between the gid and the rid.
548 ********************************************************************/
550 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
552 int rid_offset = algorithmic_rid_base();
553 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
556 /*******************************************************************
557 Decides if a RID is a well known RID.
558 ********************************************************************/
560 static bool rid_is_well_known(uint32_t rid)
562 /* Not using rid_offset here, because this is the actual
563 NT fixed value (1000) */
565 return (rid < BASE_RID);
568 /*******************************************************************
569 Decides if a RID is a user or group RID.
570 ********************************************************************/
572 bool algorithmic_pdb_rid_is_user(uint32_t rid)
574 if ( rid_is_well_known(rid) ) {
576 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
577 * and DOMAIN_RID_GUEST.
579 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
580 return True;
581 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
582 return True;
584 return False;
587 /*******************************************************************
588 Convert a name into a SID. Used in the lookup name rpc.
589 ********************************************************************/
591 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
592 enum lsa_SidType *type)
594 GROUP_MAP *map;
595 bool ret;
597 /* Windows treats "MACHINE\None" as a special name for
598 rid 513 on non-DCs. You cannot create a user or group
599 name "None" on Windows. You will get an error that
600 the group already exists. */
602 if ( strequal( name, "None" ) ) {
603 *rid = DOMAIN_RID_USERS;
604 *type = SID_NAME_DOM_GRP;
606 return True;
609 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
610 * correctly in the case where foo also exists as a user. If the flag
611 * is set, don't look for users at all. */
613 if ((flags & LOOKUP_NAME_GROUP) == 0) {
614 struct samu *sam_account = NULL;
615 struct dom_sid user_sid;
617 if ( !(sam_account = samu_new( NULL )) ) {
618 return False;
621 become_root();
622 ret = pdb_getsampwnam(sam_account, name);
623 unbecome_root();
625 if (ret) {
626 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
629 TALLOC_FREE(sam_account);
631 if (ret) {
632 if (!sid_check_is_in_our_domain(&user_sid)) {
633 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
634 name, sid_string_dbg(&user_sid)));
635 return False;
638 sid_peek_rid(&user_sid, rid);
639 *type = SID_NAME_USER;
640 return True;
645 * Maybe it is a group ?
648 map = talloc_zero(NULL, GROUP_MAP);
649 if (!map) {
650 return false;
653 become_root();
654 ret = pdb_getgrnam(map, name);
655 unbecome_root();
657 if (!ret) {
658 TALLOC_FREE(map);
659 return False;
662 /* BUILTIN groups are looked up elsewhere */
663 if (!sid_check_is_in_our_domain(&map->sid)) {
664 DEBUG(10, ("Found group %s (%s) not in our domain -- "
665 "ignoring.", name, sid_string_dbg(&map->sid)));
666 TALLOC_FREE(map);
667 return False;
670 /* yes it's a mapped group */
671 sid_peek_rid(&map->sid, rid);
672 *type = map->sid_name_use;
673 TALLOC_FREE(map);
674 return True;
677 /*************************************************************
678 Change a password entry in the local passdb backend.
680 Assumptions:
681 - always called as root
682 - ignores the account type except when adding a new account
683 - will create/delete the unix account if the relative
684 add/delete user script is configured
686 *************************************************************/
688 NTSTATUS local_password_change(const char *user_name,
689 int local_flags,
690 const char *new_passwd,
691 char **pp_err_str,
692 char **pp_msg_str)
694 TALLOC_CTX *tosctx;
695 struct samu *sam_pass;
696 uint32_t acb;
697 uint32_t rid;
698 NTSTATUS result;
699 bool user_exists;
700 int ret = -1;
702 *pp_err_str = NULL;
703 *pp_msg_str = NULL;
705 tosctx = talloc_tos();
707 sam_pass = samu_new(tosctx);
708 if (!sam_pass) {
709 result = NT_STATUS_NO_MEMORY;
710 goto done;
713 /* Get the smb passwd entry for this user */
714 user_exists = pdb_getsampwnam(sam_pass, user_name);
716 /* Check delete first, we don't need to do anything else if we
717 * are going to delete the acocunt */
718 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
720 result = pdb_delete_user(tosctx, sam_pass);
721 if (!NT_STATUS_IS_OK(result)) {
722 ret = asprintf(pp_err_str,
723 "Failed to delete entry for user %s.\n",
724 user_name);
725 if (ret < 0) {
726 *pp_err_str = NULL;
728 result = NT_STATUS_UNSUCCESSFUL;
729 } else {
730 ret = asprintf(pp_msg_str,
731 "Deleted user %s.\n",
732 user_name);
733 if (ret < 0) {
734 *pp_msg_str = NULL;
737 goto done;
740 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
741 /* the entry already existed */
742 local_flags &= ~LOCAL_ADD_USER;
745 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
746 ret = asprintf(pp_err_str,
747 "Failed to find entry for user %s.\n",
748 user_name);
749 if (ret < 0) {
750 *pp_err_str = NULL;
752 result = NT_STATUS_NO_SUCH_USER;
753 goto done;
756 /* First thing add the new user if we are required to do so */
757 if (local_flags & LOCAL_ADD_USER) {
759 if (local_flags & LOCAL_TRUST_ACCOUNT) {
760 acb = ACB_WSTRUST;
761 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
762 acb = ACB_DOMTRUST;
763 } else {
764 acb = ACB_NORMAL;
767 result = pdb_create_user(tosctx, user_name, acb, &rid);
768 if (!NT_STATUS_IS_OK(result)) {
769 ret = asprintf(pp_err_str,
770 "Failed to add entry for user %s.\n",
771 user_name);
772 if (ret < 0) {
773 *pp_err_str = NULL;
775 result = NT_STATUS_UNSUCCESSFUL;
776 goto done;
779 sam_pass = samu_new(tosctx);
780 if (!sam_pass) {
781 result = NT_STATUS_NO_MEMORY;
782 goto done;
785 /* Now get back the smb passwd entry for this new user */
786 user_exists = pdb_getsampwnam(sam_pass, user_name);
787 if (!user_exists) {
788 ret = asprintf(pp_err_str,
789 "Failed to add entry for user %s.\n",
790 user_name);
791 if (ret < 0) {
792 *pp_err_str = NULL;
794 result = NT_STATUS_UNSUCCESSFUL;
795 goto done;
799 acb = pdb_get_acct_ctrl(sam_pass);
802 * We are root - just write the new password
803 * and the valid last change time.
805 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
806 acb |= ACB_PWNOTREQ;
807 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
808 ret = asprintf(pp_err_str,
809 "Failed to set 'no password required' "
810 "flag for user %s.\n", user_name);
811 if (ret < 0) {
812 *pp_err_str = NULL;
814 result = NT_STATUS_UNSUCCESSFUL;
815 goto done;
819 if (local_flags & LOCAL_SET_PASSWORD) {
821 * If we're dealing with setting a completely empty user account
822 * ie. One with a password of 'XXXX', but not set disabled (like
823 * an account created from scratch) then if the old password was
824 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
825 * We remove that as we're giving this user their first password
826 * and the decision hasn't really been made to disable them (ie.
827 * don't create them disabled). JRA.
829 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
830 (acb & ACB_DISABLED)) {
831 acb &= (~ACB_DISABLED);
832 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
833 ret = asprintf(pp_err_str,
834 "Failed to unset 'disabled' "
835 "flag for user %s.\n",
836 user_name);
837 if (ret < 0) {
838 *pp_err_str = NULL;
840 result = NT_STATUS_UNSUCCESSFUL;
841 goto done;
845 acb &= (~ACB_PWNOTREQ);
846 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
847 ret = asprintf(pp_err_str,
848 "Failed to unset 'no password required'"
849 " flag for user %s.\n", user_name);
850 if (ret < 0) {
851 *pp_err_str = NULL;
853 result = NT_STATUS_UNSUCCESSFUL;
854 goto done;
857 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
858 ret = asprintf(pp_err_str,
859 "Failed to set password for "
860 "user %s.\n", user_name);
861 if (ret < 0) {
862 *pp_err_str = NULL;
864 result = NT_STATUS_UNSUCCESSFUL;
865 goto done;
869 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
870 acb |= ACB_DISABLED;
871 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
872 ret = asprintf(pp_err_str,
873 "Failed to set 'disabled' flag for "
874 "user %s.\n", user_name);
875 if (ret < 0) {
876 *pp_err_str = NULL;
878 result = NT_STATUS_UNSUCCESSFUL;
879 goto done;
883 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
884 acb &= (~ACB_DISABLED);
885 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
886 ret = asprintf(pp_err_str,
887 "Failed to unset 'disabled' flag for "
888 "user %s.\n", user_name);
889 if (ret < 0) {
890 *pp_err_str = NULL;
892 result = NT_STATUS_UNSUCCESSFUL;
893 goto done;
897 /* now commit changes if any */
898 result = pdb_update_sam_account(sam_pass);
899 if (!NT_STATUS_IS_OK(result)) {
900 ret = asprintf(pp_err_str,
901 "Failed to modify entry for user %s.\n",
902 user_name);
903 if (ret < 0) {
904 *pp_err_str = NULL;
906 goto done;
909 if (local_flags & LOCAL_ADD_USER) {
910 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
911 } else if (local_flags & LOCAL_DISABLE_USER) {
912 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
913 } else if (local_flags & LOCAL_ENABLE_USER) {
914 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
915 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
916 ret = asprintf(pp_msg_str,
917 "User %s password set to none.\n", user_name);
920 if (ret < 0) {
921 *pp_msg_str = NULL;
924 result = NT_STATUS_OK;
926 done:
927 TALLOC_FREE(sam_pass);
928 return result;
931 /**********************************************************************
932 Marshall/unmarshall struct samu structs.
933 *********************************************************************/
935 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
936 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
937 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
938 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
939 /* nothing changed between V3 and V4 */
941 /*********************************************************************
942 *********************************************************************/
944 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
947 /* times are stored as 32bit integer
948 take care on system with 64bit wide time_t
949 --SSS */
950 uint32_t logon_time,
951 logoff_time,
952 kickoff_time,
953 pass_last_set_time,
954 pass_can_change_time,
955 pass_must_change_time;
956 char *username = NULL;
957 char *domain = NULL;
958 char *nt_username = NULL;
959 char *dir_drive = NULL;
960 char *unknown_str = NULL;
961 char *munged_dial = NULL;
962 char *fullname = NULL;
963 char *homedir = NULL;
964 char *logon_script = NULL;
965 char *profile_path = NULL;
966 char *acct_desc = NULL;
967 char *workstations = NULL;
968 uint32_t username_len, domain_len, nt_username_len,
969 dir_drive_len, unknown_str_len, munged_dial_len,
970 fullname_len, homedir_len, logon_script_len,
971 profile_path_len, acct_desc_len, workstations_len;
973 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
974 uint16_t acct_ctrl, logon_divs;
975 uint16_t bad_password_count, logon_count;
976 uint8_t *hours = NULL;
977 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
978 uint32_t len = 0;
979 uint32_t lm_pw_len, nt_pw_len, hourslen;
980 bool ret = True;
982 if(sampass == NULL || buf == NULL) {
983 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
984 return False;
987 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
989 /* unpack the buffer into variables */
990 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
991 &logon_time, /* d */
992 &logoff_time, /* d */
993 &kickoff_time, /* d */
994 &pass_last_set_time, /* d */
995 &pass_can_change_time, /* d */
996 &pass_must_change_time, /* d */
997 &username_len, &username, /* B */
998 &domain_len, &domain, /* B */
999 &nt_username_len, &nt_username, /* B */
1000 &fullname_len, &fullname, /* B */
1001 &homedir_len, &homedir, /* B */
1002 &dir_drive_len, &dir_drive, /* B */
1003 &logon_script_len, &logon_script, /* B */
1004 &profile_path_len, &profile_path, /* B */
1005 &acct_desc_len, &acct_desc, /* B */
1006 &workstations_len, &workstations, /* B */
1007 &unknown_str_len, &unknown_str, /* B */
1008 &munged_dial_len, &munged_dial, /* B */
1009 &user_rid, /* d */
1010 &group_rid, /* d */
1011 &lm_pw_len, &lm_pw_ptr, /* B */
1012 &nt_pw_len, &nt_pw_ptr, /* B */
1013 &acct_ctrl, /* w */
1014 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
1015 &logon_divs, /* w */
1016 &hours_len, /* d */
1017 &hourslen, &hours, /* B */
1018 &bad_password_count, /* w */
1019 &logon_count, /* w */
1020 &unknown_6); /* d */
1022 if (len == (uint32_t) -1) {
1023 ret = False;
1024 goto done;
1027 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1028 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1029 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1030 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1031 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1032 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1034 pdb_set_username(sampass, username, PDB_SET);
1035 pdb_set_domain(sampass, domain, PDB_SET);
1036 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1037 pdb_set_fullname(sampass, fullname, PDB_SET);
1039 if (homedir) {
1040 pdb_set_homedir(sampass, homedir, PDB_SET);
1042 else {
1043 pdb_set_homedir(sampass,
1044 talloc_sub_basic(sampass, username, domain,
1045 lp_logon_home()),
1046 PDB_DEFAULT);
1049 if (dir_drive)
1050 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1051 else {
1052 pdb_set_dir_drive(sampass,
1053 talloc_sub_basic(sampass, username, domain,
1054 lp_logon_drive()),
1055 PDB_DEFAULT);
1058 if (logon_script)
1059 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1060 else {
1061 pdb_set_logon_script(sampass,
1062 talloc_sub_basic(sampass, username, domain,
1063 lp_logon_script()),
1064 PDB_DEFAULT);
1067 if (profile_path) {
1068 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1069 } else {
1070 pdb_set_profile_path(sampass,
1071 talloc_sub_basic(sampass, username, domain,
1072 lp_logon_path()),
1073 PDB_DEFAULT);
1076 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1077 pdb_set_workstations(sampass, workstations, PDB_SET);
1078 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1080 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1081 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1082 ret = False;
1083 goto done;
1087 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1088 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1089 ret = False;
1090 goto done;
1094 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1095 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1096 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1097 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1098 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1099 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1100 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1101 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1102 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1103 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1105 done:
1107 SAFE_FREE(username);
1108 SAFE_FREE(domain);
1109 SAFE_FREE(nt_username);
1110 SAFE_FREE(fullname);
1111 SAFE_FREE(homedir);
1112 SAFE_FREE(dir_drive);
1113 SAFE_FREE(logon_script);
1114 SAFE_FREE(profile_path);
1115 SAFE_FREE(acct_desc);
1116 SAFE_FREE(workstations);
1117 SAFE_FREE(munged_dial);
1118 SAFE_FREE(unknown_str);
1119 SAFE_FREE(lm_pw_ptr);
1120 SAFE_FREE(nt_pw_ptr);
1121 SAFE_FREE(hours);
1123 return ret;
1126 /*********************************************************************
1127 *********************************************************************/
1129 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1132 /* times are stored as 32bit integer
1133 take care on system with 64bit wide time_t
1134 --SSS */
1135 uint32_t logon_time,
1136 logoff_time,
1137 kickoff_time,
1138 bad_password_time,
1139 pass_last_set_time,
1140 pass_can_change_time,
1141 pass_must_change_time;
1142 char *username = NULL;
1143 char *domain = NULL;
1144 char *nt_username = NULL;
1145 char *dir_drive = NULL;
1146 char *unknown_str = NULL;
1147 char *munged_dial = NULL;
1148 char *fullname = NULL;
1149 char *homedir = NULL;
1150 char *logon_script = NULL;
1151 char *profile_path = NULL;
1152 char *acct_desc = NULL;
1153 char *workstations = NULL;
1154 uint32_t username_len, domain_len, nt_username_len,
1155 dir_drive_len, unknown_str_len, munged_dial_len,
1156 fullname_len, homedir_len, logon_script_len,
1157 profile_path_len, acct_desc_len, workstations_len;
1159 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1160 uint16_t acct_ctrl, logon_divs;
1161 uint16_t bad_password_count, logon_count;
1162 uint8_t *hours = NULL;
1163 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1164 uint32_t len = 0;
1165 uint32_t lm_pw_len, nt_pw_len, hourslen;
1166 bool ret = True;
1168 if(sampass == NULL || buf == NULL) {
1169 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1170 return False;
1173 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1175 /* unpack the buffer into variables */
1176 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1177 &logon_time, /* d */
1178 &logoff_time, /* d */
1179 &kickoff_time, /* d */
1180 /* Change from V0 is addition of bad_password_time field. */
1181 &bad_password_time, /* d */
1182 &pass_last_set_time, /* d */
1183 &pass_can_change_time, /* d */
1184 &pass_must_change_time, /* d */
1185 &username_len, &username, /* B */
1186 &domain_len, &domain, /* B */
1187 &nt_username_len, &nt_username, /* B */
1188 &fullname_len, &fullname, /* B */
1189 &homedir_len, &homedir, /* B */
1190 &dir_drive_len, &dir_drive, /* B */
1191 &logon_script_len, &logon_script, /* B */
1192 &profile_path_len, &profile_path, /* B */
1193 &acct_desc_len, &acct_desc, /* B */
1194 &workstations_len, &workstations, /* B */
1195 &unknown_str_len, &unknown_str, /* B */
1196 &munged_dial_len, &munged_dial, /* B */
1197 &user_rid, /* d */
1198 &group_rid, /* d */
1199 &lm_pw_len, &lm_pw_ptr, /* B */
1200 &nt_pw_len, &nt_pw_ptr, /* B */
1201 &acct_ctrl, /* w */
1202 &remove_me, /* d */
1203 &logon_divs, /* w */
1204 &hours_len, /* d */
1205 &hourslen, &hours, /* B */
1206 &bad_password_count, /* w */
1207 &logon_count, /* w */
1208 &unknown_6); /* d */
1210 if (len == (uint32_t) -1) {
1211 ret = False;
1212 goto done;
1215 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1216 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1217 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1219 /* Change from V0 is addition of bad_password_time field. */
1220 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1221 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1222 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1223 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1225 pdb_set_username(sampass, username, PDB_SET);
1226 pdb_set_domain(sampass, domain, PDB_SET);
1227 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1228 pdb_set_fullname(sampass, fullname, PDB_SET);
1230 if (homedir) {
1231 pdb_set_homedir(sampass, homedir, PDB_SET);
1233 else {
1234 pdb_set_homedir(sampass,
1235 talloc_sub_basic(sampass, username, domain,
1236 lp_logon_home()),
1237 PDB_DEFAULT);
1240 if (dir_drive)
1241 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1242 else {
1243 pdb_set_dir_drive(sampass,
1244 talloc_sub_basic(sampass, username, domain,
1245 lp_logon_drive()),
1246 PDB_DEFAULT);
1249 if (logon_script)
1250 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1251 else {
1252 pdb_set_logon_script(sampass,
1253 talloc_sub_basic(sampass, username, domain,
1254 lp_logon_script()),
1255 PDB_DEFAULT);
1258 if (profile_path) {
1259 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1260 } else {
1261 pdb_set_profile_path(sampass,
1262 talloc_sub_basic(sampass, username, domain,
1263 lp_logon_path()),
1264 PDB_DEFAULT);
1267 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1268 pdb_set_workstations(sampass, workstations, PDB_SET);
1269 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1271 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1272 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1273 ret = False;
1274 goto done;
1278 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1279 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1280 ret = False;
1281 goto done;
1285 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1287 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1288 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1289 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1290 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1291 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1292 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1293 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1294 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1295 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1297 done:
1299 SAFE_FREE(username);
1300 SAFE_FREE(domain);
1301 SAFE_FREE(nt_username);
1302 SAFE_FREE(fullname);
1303 SAFE_FREE(homedir);
1304 SAFE_FREE(dir_drive);
1305 SAFE_FREE(logon_script);
1306 SAFE_FREE(profile_path);
1307 SAFE_FREE(acct_desc);
1308 SAFE_FREE(workstations);
1309 SAFE_FREE(munged_dial);
1310 SAFE_FREE(unknown_str);
1311 SAFE_FREE(lm_pw_ptr);
1312 SAFE_FREE(nt_pw_ptr);
1313 SAFE_FREE(hours);
1315 return ret;
1318 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1321 /* times are stored as 32bit integer
1322 take care on system with 64bit wide time_t
1323 --SSS */
1324 uint32_t logon_time,
1325 logoff_time,
1326 kickoff_time,
1327 bad_password_time,
1328 pass_last_set_time,
1329 pass_can_change_time,
1330 pass_must_change_time;
1331 char *username = NULL;
1332 char *domain = NULL;
1333 char *nt_username = NULL;
1334 char *dir_drive = NULL;
1335 char *unknown_str = NULL;
1336 char *munged_dial = NULL;
1337 char *fullname = NULL;
1338 char *homedir = NULL;
1339 char *logon_script = NULL;
1340 char *profile_path = NULL;
1341 char *acct_desc = NULL;
1342 char *workstations = NULL;
1343 uint32_t username_len, domain_len, nt_username_len,
1344 dir_drive_len, unknown_str_len, munged_dial_len,
1345 fullname_len, homedir_len, logon_script_len,
1346 profile_path_len, acct_desc_len, workstations_len;
1348 uint32_t user_rid, group_rid, hours_len, unknown_6;
1349 uint16_t acct_ctrl, logon_divs;
1350 uint16_t bad_password_count, logon_count;
1351 uint8_t *hours = NULL;
1352 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1353 uint32_t len = 0;
1354 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1355 uint32_t pwHistLen = 0;
1356 bool ret = True;
1357 fstring tmp_string;
1358 bool expand_explicit = lp_passdb_expand_explicit();
1360 if(sampass == NULL || buf == NULL) {
1361 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1362 return False;
1365 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1367 /* unpack the buffer into variables */
1368 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1369 &logon_time, /* d */
1370 &logoff_time, /* d */
1371 &kickoff_time, /* d */
1372 &bad_password_time, /* d */
1373 &pass_last_set_time, /* d */
1374 &pass_can_change_time, /* d */
1375 &pass_must_change_time, /* d */
1376 &username_len, &username, /* B */
1377 &domain_len, &domain, /* B */
1378 &nt_username_len, &nt_username, /* B */
1379 &fullname_len, &fullname, /* B */
1380 &homedir_len, &homedir, /* B */
1381 &dir_drive_len, &dir_drive, /* B */
1382 &logon_script_len, &logon_script, /* B */
1383 &profile_path_len, &profile_path, /* B */
1384 &acct_desc_len, &acct_desc, /* B */
1385 &workstations_len, &workstations, /* B */
1386 &unknown_str_len, &unknown_str, /* B */
1387 &munged_dial_len, &munged_dial, /* B */
1388 &user_rid, /* d */
1389 &group_rid, /* d */
1390 &lm_pw_len, &lm_pw_ptr, /* B */
1391 &nt_pw_len, &nt_pw_ptr, /* B */
1392 /* Change from V1 is addition of password history field. */
1393 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1394 &acct_ctrl, /* w */
1395 /* Also "remove_me" field was removed. */
1396 &logon_divs, /* w */
1397 &hours_len, /* d */
1398 &hourslen, &hours, /* B */
1399 &bad_password_count, /* w */
1400 &logon_count, /* w */
1401 &unknown_6); /* d */
1403 if (len == (uint32_t) -1) {
1404 ret = False;
1405 goto done;
1408 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1409 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1410 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1411 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1412 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1413 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1414 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1416 pdb_set_username(sampass, username, PDB_SET);
1417 pdb_set_domain(sampass, domain, PDB_SET);
1418 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1419 pdb_set_fullname(sampass, fullname, PDB_SET);
1421 if (homedir) {
1422 fstrcpy( tmp_string, homedir );
1423 if (expand_explicit) {
1424 standard_sub_basic( username, domain, tmp_string,
1425 sizeof(tmp_string) );
1427 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1429 else {
1430 pdb_set_homedir(sampass,
1431 talloc_sub_basic(sampass, username, domain,
1432 lp_logon_home()),
1433 PDB_DEFAULT);
1436 if (dir_drive)
1437 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1438 else
1439 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1441 if (logon_script) {
1442 fstrcpy( tmp_string, logon_script );
1443 if (expand_explicit) {
1444 standard_sub_basic( username, domain, tmp_string,
1445 sizeof(tmp_string) );
1447 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1449 else {
1450 pdb_set_logon_script(sampass,
1451 talloc_sub_basic(sampass, username, domain,
1452 lp_logon_script()),
1453 PDB_DEFAULT);
1456 if (profile_path) {
1457 fstrcpy( tmp_string, profile_path );
1458 if (expand_explicit) {
1459 standard_sub_basic( username, domain, tmp_string,
1460 sizeof(tmp_string) );
1462 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1464 else {
1465 pdb_set_profile_path(sampass,
1466 talloc_sub_basic(sampass, username, domain,
1467 lp_logon_path()),
1468 PDB_DEFAULT);
1471 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1472 pdb_set_workstations(sampass, workstations, PDB_SET);
1473 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1475 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1476 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1477 ret = False;
1478 goto done;
1482 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1483 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1484 ret = False;
1485 goto done;
1489 /* Change from V1 is addition of password history field. */
1490 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1491 if (pwHistLen) {
1492 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1493 if (!pw_hist) {
1494 ret = False;
1495 goto done;
1497 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1498 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1499 int i;
1500 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1501 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1502 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1503 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1504 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1505 PW_HISTORY_ENTRY_LEN);
1508 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1509 SAFE_FREE(pw_hist);
1510 ret = False;
1511 goto done;
1513 SAFE_FREE(pw_hist);
1514 } else {
1515 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1518 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1519 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1520 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1521 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1522 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1523 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1524 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1525 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1526 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1528 done:
1530 SAFE_FREE(username);
1531 SAFE_FREE(domain);
1532 SAFE_FREE(nt_username);
1533 SAFE_FREE(fullname);
1534 SAFE_FREE(homedir);
1535 SAFE_FREE(dir_drive);
1536 SAFE_FREE(logon_script);
1537 SAFE_FREE(profile_path);
1538 SAFE_FREE(acct_desc);
1539 SAFE_FREE(workstations);
1540 SAFE_FREE(munged_dial);
1541 SAFE_FREE(unknown_str);
1542 SAFE_FREE(lm_pw_ptr);
1543 SAFE_FREE(nt_pw_ptr);
1544 SAFE_FREE(nt_pw_hist_ptr);
1545 SAFE_FREE(hours);
1547 return ret;
1550 /*********************************************************************
1551 *********************************************************************/
1553 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1556 /* times are stored as 32bit integer
1557 take care on system with 64bit wide time_t
1558 --SSS */
1559 uint32_t logon_time,
1560 logoff_time,
1561 kickoff_time,
1562 bad_password_time,
1563 pass_last_set_time,
1564 pass_can_change_time,
1565 pass_must_change_time;
1566 char *username = NULL;
1567 char *domain = NULL;
1568 char *nt_username = NULL;
1569 char *dir_drive = NULL;
1570 char *comment = NULL;
1571 char *munged_dial = NULL;
1572 char *fullname = NULL;
1573 char *homedir = NULL;
1574 char *logon_script = NULL;
1575 char *profile_path = NULL;
1576 char *acct_desc = NULL;
1577 char *workstations = NULL;
1578 uint32_t username_len, domain_len, nt_username_len,
1579 dir_drive_len, comment_len, munged_dial_len,
1580 fullname_len, homedir_len, logon_script_len,
1581 profile_path_len, acct_desc_len, workstations_len;
1583 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1584 uint16_t logon_divs;
1585 uint16_t bad_password_count, logon_count;
1586 uint8_t *hours = NULL;
1587 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1588 uint32_t len = 0;
1589 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1590 uint32_t pwHistLen = 0;
1591 bool ret = True;
1592 fstring tmp_string;
1593 bool expand_explicit = lp_passdb_expand_explicit();
1595 if(sampass == NULL || buf == NULL) {
1596 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1597 return False;
1600 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1602 /* unpack the buffer into variables */
1603 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1604 &logon_time, /* d */
1605 &logoff_time, /* d */
1606 &kickoff_time, /* d */
1607 &bad_password_time, /* d */
1608 &pass_last_set_time, /* d */
1609 &pass_can_change_time, /* d */
1610 &pass_must_change_time, /* d */
1611 &username_len, &username, /* B */
1612 &domain_len, &domain, /* B */
1613 &nt_username_len, &nt_username, /* B */
1614 &fullname_len, &fullname, /* B */
1615 &homedir_len, &homedir, /* B */
1616 &dir_drive_len, &dir_drive, /* B */
1617 &logon_script_len, &logon_script, /* B */
1618 &profile_path_len, &profile_path, /* B */
1619 &acct_desc_len, &acct_desc, /* B */
1620 &workstations_len, &workstations, /* B */
1621 &comment_len, &comment, /* B */
1622 &munged_dial_len, &munged_dial, /* B */
1623 &user_rid, /* d */
1624 &group_rid, /* d */
1625 &lm_pw_len, &lm_pw_ptr, /* B */
1626 &nt_pw_len, &nt_pw_ptr, /* B */
1627 /* Change from V1 is addition of password history field. */
1628 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1629 /* Change from V2 is the uint32_t acb_mask */
1630 &acct_ctrl, /* d */
1631 /* Also "remove_me" field was removed. */
1632 &logon_divs, /* w */
1633 &hours_len, /* d */
1634 &hourslen, &hours, /* B */
1635 &bad_password_count, /* w */
1636 &logon_count, /* w */
1637 &unknown_6); /* d */
1639 if (len == (uint32_t) -1) {
1640 ret = False;
1641 goto done;
1644 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1645 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1646 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1647 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1648 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1649 pdb_set_pass_must_change_time(sampass, convert_uint32_t_to_time_t(pass_must_change_time), PDB_SET);
1650 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1652 pdb_set_username(sampass, username, PDB_SET);
1653 pdb_set_domain(sampass, domain, PDB_SET);
1654 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1655 pdb_set_fullname(sampass, fullname, PDB_SET);
1657 if (homedir) {
1658 fstrcpy( tmp_string, homedir );
1659 if (expand_explicit) {
1660 standard_sub_basic( username, domain, tmp_string,
1661 sizeof(tmp_string) );
1663 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1665 else {
1666 pdb_set_homedir(sampass,
1667 talloc_sub_basic(sampass, username, domain,
1668 lp_logon_home()),
1669 PDB_DEFAULT);
1672 if (dir_drive)
1673 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1674 else
1675 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1677 if (logon_script) {
1678 fstrcpy( tmp_string, logon_script );
1679 if (expand_explicit) {
1680 standard_sub_basic( username, domain, tmp_string,
1681 sizeof(tmp_string) );
1683 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1685 else {
1686 pdb_set_logon_script(sampass,
1687 talloc_sub_basic(sampass, username, domain,
1688 lp_logon_script()),
1689 PDB_DEFAULT);
1692 if (profile_path) {
1693 fstrcpy( tmp_string, profile_path );
1694 if (expand_explicit) {
1695 standard_sub_basic( username, domain, tmp_string,
1696 sizeof(tmp_string) );
1698 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1700 else {
1701 pdb_set_profile_path(sampass,
1702 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1703 PDB_DEFAULT);
1706 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1707 pdb_set_comment(sampass, comment, PDB_SET);
1708 pdb_set_workstations(sampass, workstations, PDB_SET);
1709 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1711 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1712 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1713 ret = False;
1714 goto done;
1718 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1719 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1720 ret = False;
1721 goto done;
1725 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1726 if (pwHistLen) {
1727 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1728 if (!pw_hist) {
1729 ret = False;
1730 goto done;
1732 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1733 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1734 int i;
1735 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1736 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1737 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1738 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1739 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1740 PW_HISTORY_ENTRY_LEN);
1743 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1744 SAFE_FREE(pw_hist);
1745 ret = False;
1746 goto done;
1748 SAFE_FREE(pw_hist);
1749 } else {
1750 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1753 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1754 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1755 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1756 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1757 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1758 /* Change from V2 is the uint32_t acct_ctrl */
1759 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1760 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1761 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1763 done:
1765 SAFE_FREE(username);
1766 SAFE_FREE(domain);
1767 SAFE_FREE(nt_username);
1768 SAFE_FREE(fullname);
1769 SAFE_FREE(homedir);
1770 SAFE_FREE(dir_drive);
1771 SAFE_FREE(logon_script);
1772 SAFE_FREE(profile_path);
1773 SAFE_FREE(acct_desc);
1774 SAFE_FREE(workstations);
1775 SAFE_FREE(munged_dial);
1776 SAFE_FREE(comment);
1777 SAFE_FREE(lm_pw_ptr);
1778 SAFE_FREE(nt_pw_ptr);
1779 SAFE_FREE(nt_pw_hist_ptr);
1780 SAFE_FREE(hours);
1782 return ret;
1785 /*********************************************************************
1786 *********************************************************************/
1788 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1790 size_t len, buflen;
1792 /* times are stored as 32bit integer
1793 take care on system with 64bit wide time_t
1794 --SSS */
1795 uint32_t logon_time,
1796 logoff_time,
1797 kickoff_time,
1798 bad_password_time,
1799 pass_last_set_time,
1800 pass_can_change_time,
1801 pass_must_change_time;
1803 uint32_t user_rid, group_rid;
1805 const char *username;
1806 const char *domain;
1807 const char *nt_username;
1808 const char *dir_drive;
1809 const char *comment;
1810 const char *munged_dial;
1811 const char *fullname;
1812 const char *homedir;
1813 const char *logon_script;
1814 const char *profile_path;
1815 const char *acct_desc;
1816 const char *workstations;
1817 uint32_t username_len, domain_len, nt_username_len,
1818 dir_drive_len, comment_len, munged_dial_len,
1819 fullname_len, homedir_len, logon_script_len,
1820 profile_path_len, acct_desc_len, workstations_len;
1822 const uint8_t *lm_pw;
1823 const uint8_t *nt_pw;
1824 const uint8_t *nt_pw_hist;
1825 uint32_t lm_pw_len = 16;
1826 uint32_t nt_pw_len = 16;
1827 uint32_t nt_pw_hist_len;
1828 uint32_t pwHistLen = 0;
1830 *buf = NULL;
1831 buflen = 0;
1833 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1834 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1835 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1836 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1837 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1838 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1839 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1841 user_rid = pdb_get_user_rid(sampass);
1842 group_rid = pdb_get_group_rid(sampass);
1844 username = pdb_get_username(sampass);
1845 if (username) {
1846 username_len = strlen(username) +1;
1847 } else {
1848 username_len = 0;
1851 domain = pdb_get_domain(sampass);
1852 if (domain) {
1853 domain_len = strlen(domain) +1;
1854 } else {
1855 domain_len = 0;
1858 nt_username = pdb_get_nt_username(sampass);
1859 if (nt_username) {
1860 nt_username_len = strlen(nt_username) +1;
1861 } else {
1862 nt_username_len = 0;
1865 fullname = pdb_get_fullname(sampass);
1866 if (fullname) {
1867 fullname_len = strlen(fullname) +1;
1868 } else {
1869 fullname_len = 0;
1873 * Only updates fields which have been set (not defaults from smb.conf)
1876 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1877 dir_drive = pdb_get_dir_drive(sampass);
1878 } else {
1879 dir_drive = NULL;
1881 if (dir_drive) {
1882 dir_drive_len = strlen(dir_drive) +1;
1883 } else {
1884 dir_drive_len = 0;
1887 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1888 homedir = pdb_get_homedir(sampass);
1889 } else {
1890 homedir = NULL;
1892 if (homedir) {
1893 homedir_len = strlen(homedir) +1;
1894 } else {
1895 homedir_len = 0;
1898 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1899 logon_script = pdb_get_logon_script(sampass);
1900 } else {
1901 logon_script = NULL;
1903 if (logon_script) {
1904 logon_script_len = strlen(logon_script) +1;
1905 } else {
1906 logon_script_len = 0;
1909 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1910 profile_path = pdb_get_profile_path(sampass);
1911 } else {
1912 profile_path = NULL;
1914 if (profile_path) {
1915 profile_path_len = strlen(profile_path) +1;
1916 } else {
1917 profile_path_len = 0;
1920 lm_pw = pdb_get_lanman_passwd(sampass);
1921 if (!lm_pw) {
1922 lm_pw_len = 0;
1925 nt_pw = pdb_get_nt_passwd(sampass);
1926 if (!nt_pw) {
1927 nt_pw_len = 0;
1930 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1931 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1932 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1933 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1934 } else {
1935 nt_pw_hist_len = 0;
1938 acct_desc = pdb_get_acct_desc(sampass);
1939 if (acct_desc) {
1940 acct_desc_len = strlen(acct_desc) +1;
1941 } else {
1942 acct_desc_len = 0;
1945 workstations = pdb_get_workstations(sampass);
1946 if (workstations) {
1947 workstations_len = strlen(workstations) +1;
1948 } else {
1949 workstations_len = 0;
1952 comment = pdb_get_comment(sampass);
1953 if (comment) {
1954 comment_len = strlen(comment) +1;
1955 } else {
1956 comment_len = 0;
1959 munged_dial = pdb_get_munged_dial(sampass);
1960 if (munged_dial) {
1961 munged_dial_len = strlen(munged_dial) +1;
1962 } else {
1963 munged_dial_len = 0;
1966 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1968 /* one time to get the size needed */
1969 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1970 logon_time, /* d */
1971 logoff_time, /* d */
1972 kickoff_time, /* d */
1973 bad_password_time, /* d */
1974 pass_last_set_time, /* d */
1975 pass_can_change_time, /* d */
1976 pass_must_change_time, /* d */
1977 username_len, username, /* B */
1978 domain_len, domain, /* B */
1979 nt_username_len, nt_username, /* B */
1980 fullname_len, fullname, /* B */
1981 homedir_len, homedir, /* B */
1982 dir_drive_len, dir_drive, /* B */
1983 logon_script_len, logon_script, /* B */
1984 profile_path_len, profile_path, /* B */
1985 acct_desc_len, acct_desc, /* B */
1986 workstations_len, workstations, /* B */
1987 comment_len, comment, /* B */
1988 munged_dial_len, munged_dial, /* B */
1989 user_rid, /* d */
1990 group_rid, /* d */
1991 lm_pw_len, lm_pw, /* B */
1992 nt_pw_len, nt_pw, /* B */
1993 nt_pw_hist_len, nt_pw_hist, /* B */
1994 pdb_get_acct_ctrl(sampass), /* d */
1995 pdb_get_logon_divs(sampass), /* w */
1996 pdb_get_hours_len(sampass), /* d */
1997 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1998 pdb_get_bad_password_count(sampass), /* w */
1999 pdb_get_logon_count(sampass), /* w */
2000 pdb_get_unknown_6(sampass)); /* d */
2002 if (size_only) {
2003 return buflen;
2006 /* malloc the space needed */
2007 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
2008 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
2009 return (-1);
2012 /* now for the real call to tdb_pack() */
2013 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2014 logon_time, /* d */
2015 logoff_time, /* d */
2016 kickoff_time, /* d */
2017 bad_password_time, /* d */
2018 pass_last_set_time, /* d */
2019 pass_can_change_time, /* d */
2020 pass_must_change_time, /* d */
2021 username_len, username, /* B */
2022 domain_len, domain, /* B */
2023 nt_username_len, nt_username, /* B */
2024 fullname_len, fullname, /* B */
2025 homedir_len, homedir, /* B */
2026 dir_drive_len, dir_drive, /* B */
2027 logon_script_len, logon_script, /* B */
2028 profile_path_len, profile_path, /* B */
2029 acct_desc_len, acct_desc, /* B */
2030 workstations_len, workstations, /* B */
2031 comment_len, comment, /* B */
2032 munged_dial_len, munged_dial, /* B */
2033 user_rid, /* d */
2034 group_rid, /* d */
2035 lm_pw_len, lm_pw, /* B */
2036 nt_pw_len, nt_pw, /* B */
2037 nt_pw_hist_len, nt_pw_hist, /* B */
2038 pdb_get_acct_ctrl(sampass), /* d */
2039 pdb_get_logon_divs(sampass), /* w */
2040 pdb_get_hours_len(sampass), /* d */
2041 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2042 pdb_get_bad_password_count(sampass), /* w */
2043 pdb_get_logon_count(sampass), /* w */
2044 pdb_get_unknown_6(sampass)); /* d */
2046 /* check to make sure we got it correct */
2047 if (buflen != len) {
2048 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2049 (unsigned long)buflen, (unsigned long)len));
2050 /* error */
2051 SAFE_FREE (*buf);
2052 return (-1);
2055 return (buflen);
2058 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2060 /* nothing changed between V3 and V4 */
2061 return init_samu_from_buffer_v3(sampass, buf, buflen);
2064 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2066 /* nothing changed between V3 and V4 */
2067 return init_buffer_from_samu_v3(buf, sampass, size_only);
2070 /**********************************************************************
2071 Intialize a struct samu struct from a BYTE buffer of size len
2072 *********************************************************************/
2074 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2075 uint8_t *buf, uint32_t buflen)
2077 switch (level) {
2078 case SAMU_BUFFER_V0:
2079 return init_samu_from_buffer_v0(sampass, buf, buflen);
2080 case SAMU_BUFFER_V1:
2081 return init_samu_from_buffer_v1(sampass, buf, buflen);
2082 case SAMU_BUFFER_V2:
2083 return init_samu_from_buffer_v2(sampass, buf, buflen);
2084 case SAMU_BUFFER_V3:
2085 return init_samu_from_buffer_v3(sampass, buf, buflen);
2086 case SAMU_BUFFER_V4:
2087 return init_samu_from_buffer_v4(sampass, buf, buflen);
2090 return false;
2093 /**********************************************************************
2094 Intialize a BYTE buffer from a struct samu struct
2095 *********************************************************************/
2097 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2099 return init_buffer_from_samu_v4(buf, sampass, size_only);
2102 /*********************************************************************
2103 *********************************************************************/
2105 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2107 uint8_t *buf = NULL;
2108 int len;
2110 len = init_buffer_from_samu(&buf, src, False);
2111 if (len == -1 || !buf) {
2112 SAFE_FREE(buf);
2113 return False;
2116 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2117 free(buf);
2118 return False;
2121 dst->methods = src->methods;
2123 if ( src->unix_pw ) {
2124 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2125 if (!dst->unix_pw) {
2126 free(buf);
2127 return False;
2131 if (src->group_sid) {
2132 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2135 free(buf);
2136 return True;
2139 /*********************************************************************
2140 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2141 *********************************************************************/
2143 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2145 time_t LastBadPassword;
2146 uint16_t BadPasswordCount;
2147 uint32_t resettime;
2148 bool res;
2150 BadPasswordCount = pdb_get_bad_password_count(sampass);
2151 if (!BadPasswordCount) {
2152 DEBUG(9, ("No bad password attempts.\n"));
2153 return True;
2156 become_root();
2157 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2158 unbecome_root();
2160 if (!res) {
2161 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2162 return False;
2165 /* First, check if there is a reset time to compare */
2166 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2167 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2168 return True;
2171 LastBadPassword = pdb_get_bad_password_time(sampass);
2172 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2173 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2174 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2175 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2176 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2177 if (updated) {
2178 *updated = True;
2182 return True;
2185 /*********************************************************************
2186 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2187 *********************************************************************/
2189 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2191 uint32_t duration;
2192 time_t LastBadPassword;
2193 bool res;
2195 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2196 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2197 pdb_get_username(sampass)));
2198 return True;
2201 become_root();
2202 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2203 unbecome_root();
2205 if (!res) {
2206 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2207 return False;
2210 /* First, check if there is a duration to compare */
2211 if ((duration == (uint32_t) -1) || (duration == 0)) {
2212 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2213 return True;
2216 LastBadPassword = pdb_get_bad_password_time(sampass);
2217 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2218 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2220 if (LastBadPassword == (time_t)0) {
2221 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2222 "administratively locked out with no bad password "
2223 "time. Leaving locked out.\n",
2224 pdb_get_username(sampass) ));
2225 return True;
2228 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2229 pdb_set_acct_ctrl(sampass,
2230 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2231 PDB_CHANGED);
2232 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2233 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2234 if (updated) {
2235 *updated = True;
2239 return True;
2242 /*********************************************************************
2243 Increment the bad_password_count
2244 *********************************************************************/
2246 bool pdb_increment_bad_password_count(struct samu *sampass)
2248 uint32_t account_policy_lockout;
2249 bool autolock_updated = False, badpw_updated = False;
2250 bool ret;
2252 /* Retrieve the account lockout policy */
2253 become_root();
2254 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2255 unbecome_root();
2256 if ( !ret ) {
2257 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2258 return False;
2261 /* If there is no policy, we don't need to continue checking */
2262 if (!account_policy_lockout) {
2263 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2264 return True;
2267 /* Check if the autolock needs to be cleared */
2268 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2269 return False;
2271 /* Check if the badpw count needs to be reset */
2272 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2273 return False;
2276 Ok, now we can assume that any resetting that needs to be
2277 done has been done, and just get on with incrementing
2278 and autolocking if necessary
2281 pdb_set_bad_password_count(sampass,
2282 pdb_get_bad_password_count(sampass)+1,
2283 PDB_CHANGED);
2284 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2287 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2288 return True;
2290 if (!pdb_set_acct_ctrl(sampass,
2291 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2292 PDB_CHANGED)) {
2293 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2294 return False;
2297 return True;
2300 bool is_dc_trusted_domain_situation(const char *domain_name)
2302 return IS_DC && !strequal(domain_name, lp_workgroup());
2305 /*******************************************************************
2306 Wrapper around retrieving the clear text trust account password.
2307 appropriate account name is stored in account_name.
2308 Caller must free password, but not account_name.
2309 *******************************************************************/
2311 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2312 const char **account_name,
2313 enum netr_SchannelType *channel)
2315 char *pwd;
2316 time_t last_set_time;
2318 /* if we are a DC and this is not our domain, then lookup an account
2319 * for the domain trust */
2321 if (is_dc_trusted_domain_situation(domain)) {
2322 if (!lp_allow_trusted_domains()) {
2323 return false;
2326 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2327 &last_set_time))
2329 DEBUG(0, ("get_trust_pw: could not fetch trust "
2330 "account password for trusted domain %s\n",
2331 domain));
2332 return false;
2335 if (channel != NULL) {
2336 *channel = SEC_CHAN_DOMAIN;
2339 if (account_name != NULL) {
2340 *account_name = lp_workgroup();
2343 return true;
2347 * Since we can only be member of one single domain, we are now
2348 * in a member situation:
2350 * - Either we are a DC (selfjoined) and the domain is our
2351 * own domain.
2352 * - Or we are on a member and the domain is our own or some
2353 * other (potentially trusted) domain.
2355 * In both cases, we can only get the machine account password
2356 * for our own domain to connect to our own dc. (For a member,
2357 * request to trusted domains are performed through our dc.)
2359 * So we simply use our own domain name to retrieve the
2360 * machine account passowrd and ignore the request domain here.
2363 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2365 if (pwd != NULL) {
2366 *ret_pwd = pwd;
2367 if (account_name != NULL) {
2368 *account_name = lp_netbios_name();
2371 return true;
2374 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2375 "account password for domain %s\n", domain));
2376 return false;
2379 /*******************************************************************
2380 Wrapper around retrieving the trust account password.
2381 appropriate account name is stored in account_name.
2382 *******************************************************************/
2384 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2385 const char **account_name,
2386 enum netr_SchannelType *channel)
2388 char *pwd = NULL;
2389 time_t last_set_time;
2391 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2392 E_md4hash(pwd, ret_pwd);
2393 SAFE_FREE(pwd);
2394 return true;
2395 } else if (is_dc_trusted_domain_situation(domain)) {
2396 return false;
2399 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2401 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2402 &last_set_time,
2403 channel))
2405 if (account_name != NULL) {
2406 *account_name = lp_netbios_name();
2409 return true;
2412 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2413 "password for domain %s\n", domain));
2414 return False;