passdb: Use common code in cli_credentials_set_machine_account_db_ctx()
[Samba.git] / source3 / passdb / passdb.c
blob02f0a78e226ede4da6b9995f46b87663e6de0aab
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"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_PASSDB
39 /******************************************************************
40 Get the default domain/netbios name to be used when
41 testing authentication.
43 LEGACY: this function provides the legacy domain mapping used with
44 the lp_map_untrusted_to_domain() parameter
45 ******************************************************************/
47 const char *my_sam_name(void)
49 /* Standalone servers can only use the local netbios name */
50 if ( lp_server_role() == ROLE_STANDALONE )
51 return lp_netbios_name();
53 /* Default to the DOMAIN name when not specified */
54 return lp_workgroup();
57 /**********************************************************************
58 ***********************************************************************/
60 static int samu_destroy(struct samu *user)
62 data_blob_clear_free( &user->lm_pw );
63 data_blob_clear_free( &user->nt_pw );
65 if ( user->plaintext_pw )
66 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
68 return 0;
71 /**********************************************************************
72 generate a new struct samuser
73 ***********************************************************************/
75 struct samu *samu_new( TALLOC_CTX *ctx )
77 struct samu *user;
79 if ( !(user = talloc_zero( ctx, struct samu )) ) {
80 DEBUG(0,("samuser_new: Talloc failed!\n"));
81 return NULL;
84 talloc_set_destructor( user, samu_destroy );
86 /* no initial methods */
88 user->methods = NULL;
90 /* Don't change these timestamp settings without a good reason.
91 They are important for NT member server compatibility. */
93 user->logon_time = (time_t)0;
94 user->pass_last_set_time = (time_t)0;
95 user->pass_can_change_time = (time_t)0;
96 user->logoff_time = get_time_t_max();
97 user->kickoff_time = get_time_t_max();
98 user->fields_present = 0x00ffffff;
99 user->logon_divs = 168; /* hours per week */
100 user->hours_len = 21; /* 21 times 8 bits = 168 */
101 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
102 user->bad_password_count = 0;
103 user->logon_count = 0;
104 user->unknown_6 = 0x000004ec; /* don't know */
106 /* Some parts of samba strlen their pdb_get...() returns,
107 so this keeps the interface unchanged for now. */
109 user->username = "";
110 user->domain = "";
111 user->nt_username = "";
112 user->full_name = "";
113 user->home_dir = "";
114 user->logon_script = "";
115 user->profile_path = "";
116 user->acct_desc = "";
117 user->workstations = "";
118 user->comment = "";
119 user->munged_dial = "";
121 user->plaintext_pw = NULL;
123 /* Unless we know otherwise have a Account Control Bit
124 value of 'normal user'. This helps User Manager, which
125 asks for a filtered list of users. */
127 user->acct_ctrl = ACB_NORMAL;
129 return user;
132 static int count_commas(const char *str)
134 int num_commas = 0;
135 const char *comma = str;
137 while ((comma = strchr(comma, ',')) != NULL) {
138 comma += 1;
139 num_commas += 1;
141 return num_commas;
144 /*********************************************************************
145 Initialize a struct samu from a struct passwd including the user
146 and group SIDs. The *user structure is filled out with the Unix
147 attributes and a user SID.
148 *********************************************************************/
150 static NTSTATUS samu_set_unix_internal(struct pdb_methods *methods,
151 struct samu *user, const struct passwd *pwd, bool create)
153 const char *guest_account = lp_guest_account();
154 const char *domain = lp_netbios_name();
155 char *fullname;
156 uint32_t urid;
158 if ( !pwd ) {
159 return NT_STATUS_NO_SUCH_USER;
162 /* Basic properties based upon the Unix account information */
164 pdb_set_username(user, pwd->pw_name, PDB_SET);
166 fullname = NULL;
168 if (count_commas(pwd->pw_gecos) == 3) {
170 * Heuristic: This seems to be a gecos field that has been
171 * edited by chfn(1). Only use the part before the first
172 * comma. Fixes bug 5198.
174 fullname = talloc_strndup(
175 talloc_tos(), pwd->pw_gecos,
176 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
179 if (fullname != NULL) {
180 pdb_set_fullname(user, fullname, PDB_SET);
181 } else {
182 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
184 TALLOC_FREE(fullname);
186 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
187 #if 0
188 /* This can lead to a primary group of S-1-22-2-XX which
189 will be rejected by other parts of the Samba code.
190 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
191 --jerry */
193 gid_to_sid(&group_sid, pwd->pw_gid);
194 pdb_set_group_sid(user, &group_sid, PDB_SET);
195 #endif
197 /* save the password structure for later use */
199 user->unix_pw = tcopy_passwd( user, pwd );
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 pdb_set_profile_path(user, talloc_sub_specified(user,
233 lp_logon_path(), pwd->pw_name, NULL, domain, pwd->pw_uid, pwd->pw_gid),
234 PDB_DEFAULT);
235 pdb_set_homedir(user, talloc_sub_specified(user,
236 lp_logon_home(), pwd->pw_name, NULL, domain, pwd->pw_uid, pwd->pw_gid),
237 PDB_DEFAULT);
238 pdb_set_dir_drive(user, talloc_sub_specified(user,
239 lp_logon_drive(), pwd->pw_name, NULL, domain, pwd->pw_uid, pwd->pw_gid),
240 PDB_DEFAULT);
241 pdb_set_logon_script(user, talloc_sub_specified(user,
242 lp_logon_script(), pwd->pw_name, NULL, domain, pwd->pw_uid, pwd->pw_gid),
243 PDB_DEFAULT);
246 /* Now deal with the user SID. If we have a backend that can generate
247 RIDs, then do so. But sometimes the caller just wanted a structure
248 initialized and will fill in these fields later (such as from a
249 netr_SamInfo3 structure) */
251 if ( create && (methods->capabilities(methods) & PDB_CAP_STORE_RIDS)) {
252 uint32_t user_rid;
253 struct dom_sid user_sid;
255 if ( !methods->new_rid(methods, &user_rid) ) {
256 DEBUG(3, ("Could not allocate a new RID\n"));
257 return NT_STATUS_ACCESS_DENIED;
260 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
262 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
263 DEBUG(3, ("pdb_set_user_sid failed\n"));
264 return NT_STATUS_INTERNAL_ERROR;
267 return NT_STATUS_OK;
270 /* generate a SID for the user with the RID algorithm */
272 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
274 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
275 return NT_STATUS_INTERNAL_ERROR;
278 return NT_STATUS_OK;
281 /********************************************************************
282 Set the Unix user attributes
283 ********************************************************************/
285 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
287 return samu_set_unix_internal( NULL, user, pwd, False );
290 NTSTATUS samu_alloc_rid_unix(struct pdb_methods *methods,
291 struct samu *user, const struct passwd *pwd)
293 return samu_set_unix_internal( methods, user, pwd, True );
296 /**********************************************************
297 Encode the account control bits into a string.
298 length = length of string to encode into (including terminating
299 null). length *MUST BE MORE THAN 2* !
300 **********************************************************/
302 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
304 fstring acct_str;
305 char *result;
307 size_t i = 0;
309 SMB_ASSERT(length <= sizeof(acct_str));
311 acct_str[i++] = '[';
313 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
314 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
315 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
316 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
317 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
318 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
319 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
320 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
321 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
322 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
323 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
325 for ( ; i < length - 2 ; i++ )
326 acct_str[i] = ' ';
328 i = length - 2;
329 acct_str[i++] = ']';
330 acct_str[i++] = '\0';
332 result = talloc_strdup(talloc_tos(), acct_str);
333 SMB_ASSERT(result != NULL);
334 return result;
337 /**********************************************************
338 Decode the account control bits from a string.
339 **********************************************************/
341 uint32_t pdb_decode_acct_ctrl(const char *p)
343 uint32_t acct_ctrl = 0;
344 bool finished = false;
347 * Check if the account type bits have been encoded after the
348 * NT password (in the form [NDHTUWSLXI]).
351 if (*p != '[')
352 return 0;
354 for (p++; *p && !finished; p++) {
355 switch (*p) {
356 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
357 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
358 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
359 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
360 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
361 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
362 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
363 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
364 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
365 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
366 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
367 case ' ': { break; }
368 case ':':
369 case '\n':
370 case '\0':
371 case ']':
372 default: { finished = true; }
376 return acct_ctrl;
379 /*************************************************************
380 Routine to set 32 hex password characters from a 16 byte array.
381 **************************************************************/
383 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
385 if (pwd != NULL) {
386 hex_encode_buf(p, pwd, 16);
387 } else {
388 if (acct_ctrl & ACB_PWNOTREQ)
389 strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
390 else
391 strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
395 /*************************************************************
396 Routine to get the 32 hex characters and turn them
397 into a 16 byte array.
398 **************************************************************/
400 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
402 int i;
403 unsigned char lonybble, hinybble;
404 const char *hexchars = "0123456789ABCDEF";
405 char *p1, *p2;
407 if (!p)
408 return false;
410 for (i = 0; i < 32; i += 2) {
411 hinybble = toupper_m(p[i]);
412 lonybble = toupper_m(p[i + 1]);
414 p1 = strchr(hexchars, hinybble);
415 p2 = strchr(hexchars, lonybble);
417 if (!p1 || !p2)
418 return false;
420 hinybble = PTR_DIFF(p1, hexchars);
421 lonybble = PTR_DIFF(p2, hexchars);
423 pwd[i / 2] = (hinybble << 4) | lonybble;
425 return true;
428 /*************************************************************
429 Routine to set 42 hex hours characters from a 21 byte array.
430 **************************************************************/
432 void pdb_sethexhours(char *p, const unsigned char *hours)
434 if (hours != NULL) {
435 hex_encode_buf(p, hours, 21);
436 } else {
437 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
441 /*************************************************************
442 Routine to get the 42 hex characters and turn them
443 into a 21 byte array.
444 **************************************************************/
446 bool pdb_gethexhours(const char *p, unsigned char *hours)
448 int i;
449 unsigned char lonybble, hinybble;
450 const char *hexchars = "0123456789ABCDEF";
451 char *p1, *p2;
453 if (!p) {
454 return (False);
457 for (i = 0; i < 42; i += 2) {
458 hinybble = toupper_m(p[i]);
459 lonybble = toupper_m(p[i + 1]);
461 p1 = strchr(hexchars, hinybble);
462 p2 = strchr(hexchars, lonybble);
464 if (!p1 || !p2) {
465 return (False);
468 hinybble = PTR_DIFF(p1, hexchars);
469 lonybble = PTR_DIFF(p2, hexchars);
471 hours[i / 2] = (hinybble << 4) | lonybble;
473 return (True);
476 /********************************************************************
477 ********************************************************************/
479 int algorithmic_rid_base(void)
481 int rid_offset;
483 rid_offset = lp_algorithmic_rid_base();
485 if (rid_offset < BASE_RID) {
486 /* Try to prevent admin foot-shooting, we can't put algorithmic
487 rids below 1000, that's the 'well known RIDs' on NT */
488 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
489 rid_offset = BASE_RID;
491 if (rid_offset & 1) {
492 DEBUG(0, ("algorithmic rid base must be even\n"));
493 rid_offset += 1;
495 return rid_offset;
498 /*******************************************************************
499 Converts NT user RID to a UNIX uid.
500 ********************************************************************/
502 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
504 int rid_offset = algorithmic_rid_base();
505 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
508 uid_t max_algorithmic_uid(void)
510 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
513 /*******************************************************************
514 converts UNIX uid to an NT User RID.
515 ********************************************************************/
517 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
519 int rid_offset = algorithmic_rid_base();
520 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
523 /*******************************************************************
524 Converts NT group RID to a UNIX gid.
525 ********************************************************************/
527 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
529 int rid_offset = algorithmic_rid_base();
530 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
533 gid_t max_algorithmic_gid(void)
535 return pdb_group_rid_to_gid(0xffffffff);
538 /*******************************************************************
539 converts NT Group RID to a UNIX uid.
541 warning: you must not call that function only
542 you must do a call to the group mapping first.
543 there is not anymore a direct link between the gid and the rid.
544 ********************************************************************/
546 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
548 int rid_offset = algorithmic_rid_base();
549 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
552 /*******************************************************************
553 Decides if a RID is a well known RID.
554 ********************************************************************/
556 static bool rid_is_well_known(uint32_t rid)
558 /* Not using rid_offset here, because this is the actual
559 NT fixed value (1000) */
561 return (rid < BASE_RID);
564 /*******************************************************************
565 Decides if a RID is a user or group RID.
566 ********************************************************************/
568 bool algorithmic_pdb_rid_is_user(uint32_t rid)
570 if ( rid_is_well_known(rid) ) {
572 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
573 * and DOMAIN_RID_GUEST.
575 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
576 return True;
577 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
578 return True;
580 return False;
583 /*******************************************************************
584 Convert a name into a SID. Used in the lookup name rpc.
585 ********************************************************************/
587 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
588 enum lsa_SidType *type)
590 GROUP_MAP *map;
591 bool ret;
593 /* Windows treats "MACHINE\None" as a special name for
594 rid 513 on non-DCs. You cannot create a user or group
595 name "None" on Windows. You will get an error that
596 the group already exists. */
598 if ( strequal( name, "None" ) ) {
599 *rid = DOMAIN_RID_USERS;
600 *type = SID_NAME_DOM_GRP;
602 return True;
605 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
606 * correctly in the case where foo also exists as a user. If the flag
607 * is set, don't look for users at all. */
609 if ((flags & LOOKUP_NAME_GROUP) == 0) {
610 struct samu *sam_account = NULL;
611 struct dom_sid user_sid;
613 if ( !(sam_account = samu_new( NULL )) ) {
614 return False;
617 become_root();
618 ret = pdb_getsampwnam(sam_account, name);
619 unbecome_root();
621 if (ret) {
622 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
625 TALLOC_FREE(sam_account);
627 if (ret) {
628 if (!sid_check_is_in_our_sam(&user_sid)) {
629 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
630 name, sid_string_dbg(&user_sid)));
631 return False;
634 sid_peek_rid(&user_sid, rid);
635 *type = SID_NAME_USER;
636 return True;
641 * Maybe it is a group ?
644 map = talloc_zero(NULL, GROUP_MAP);
645 if (!map) {
646 return false;
649 become_root();
650 ret = pdb_getgrnam(map, name);
651 unbecome_root();
653 if (!ret) {
654 TALLOC_FREE(map);
655 return False;
658 /* BUILTIN groups are looked up elsewhere */
659 if (!sid_check_is_in_our_sam(&map->sid)) {
660 DEBUG(10, ("Found group %s (%s) not in our domain -- "
661 "ignoring.", name, sid_string_dbg(&map->sid)));
662 TALLOC_FREE(map);
663 return False;
666 /* yes it's a mapped group */
667 sid_peek_rid(&map->sid, rid);
668 *type = map->sid_name_use;
669 TALLOC_FREE(map);
670 return True;
673 /*************************************************************
674 Change a password entry in the local passdb backend.
676 Assumptions:
677 - always called as root
678 - ignores the account type except when adding a new account
679 - will create/delete the unix account if the relative
680 add/delete user script is configured
682 *************************************************************/
684 NTSTATUS local_password_change(const char *user_name,
685 int local_flags,
686 const char *new_passwd,
687 char **pp_err_str,
688 char **pp_msg_str)
690 TALLOC_CTX *tosctx;
691 struct samu *sam_pass;
692 uint32_t acb;
693 uint32_t rid;
694 NTSTATUS result;
695 bool user_exists;
696 int ret = -1;
698 *pp_err_str = NULL;
699 *pp_msg_str = NULL;
701 tosctx = talloc_tos();
703 sam_pass = samu_new(tosctx);
704 if (!sam_pass) {
705 result = NT_STATUS_NO_MEMORY;
706 goto done;
709 /* Get the smb passwd entry for this user */
710 user_exists = pdb_getsampwnam(sam_pass, user_name);
712 /* Check delete first, we don't need to do anything else if we
713 * are going to delete the acocunt */
714 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
716 result = pdb_delete_user(tosctx, sam_pass);
717 if (!NT_STATUS_IS_OK(result)) {
718 ret = asprintf(pp_err_str,
719 "Failed to delete entry for user %s.\n",
720 user_name);
721 if (ret < 0) {
722 *pp_err_str = NULL;
724 result = NT_STATUS_UNSUCCESSFUL;
725 } else {
726 ret = asprintf(pp_msg_str,
727 "Deleted user %s.\n",
728 user_name);
729 if (ret < 0) {
730 *pp_msg_str = NULL;
733 goto done;
736 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
737 /* the entry already existed */
738 local_flags &= ~LOCAL_ADD_USER;
741 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
742 ret = asprintf(pp_err_str,
743 "Failed to find entry for user %s.\n",
744 user_name);
745 if (ret < 0) {
746 *pp_err_str = NULL;
748 result = NT_STATUS_NO_SUCH_USER;
749 goto done;
752 /* First thing add the new user if we are required to do so */
753 if (local_flags & LOCAL_ADD_USER) {
755 if (local_flags & LOCAL_TRUST_ACCOUNT) {
756 acb = ACB_WSTRUST;
757 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
758 acb = ACB_DOMTRUST;
759 } else {
760 acb = ACB_NORMAL;
763 result = pdb_create_user(tosctx, user_name, acb, &rid);
764 if (!NT_STATUS_IS_OK(result)) {
765 ret = asprintf(pp_err_str,
766 "Failed to add entry for user %s.\n",
767 user_name);
768 if (ret < 0) {
769 *pp_err_str = NULL;
771 result = NT_STATUS_UNSUCCESSFUL;
772 goto done;
775 sam_pass = samu_new(tosctx);
776 if (!sam_pass) {
777 result = NT_STATUS_NO_MEMORY;
778 goto done;
781 /* Now get back the smb passwd entry for this new user */
782 user_exists = pdb_getsampwnam(sam_pass, user_name);
783 if (!user_exists) {
784 ret = asprintf(pp_err_str,
785 "Failed to add entry for user %s.\n",
786 user_name);
787 if (ret < 0) {
788 *pp_err_str = NULL;
790 result = NT_STATUS_UNSUCCESSFUL;
791 goto done;
795 acb = pdb_get_acct_ctrl(sam_pass);
798 * We are root - just write the new password
799 * and the valid last change time.
801 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
802 acb |= ACB_PWNOTREQ;
803 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
804 ret = asprintf(pp_err_str,
805 "Failed to set 'no password required' "
806 "flag for user %s.\n", user_name);
807 if (ret < 0) {
808 *pp_err_str = NULL;
810 result = NT_STATUS_UNSUCCESSFUL;
811 goto done;
815 if (local_flags & LOCAL_SET_PASSWORD) {
817 * If we're dealing with setting a completely empty user account
818 * ie. One with a password of 'XXXX', but not set disabled (like
819 * an account created from scratch) then if the old password was
820 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
821 * We remove that as we're giving this user their first password
822 * and the decision hasn't really been made to disable them (ie.
823 * don't create them disabled). JRA.
825 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
826 (acb & ACB_DISABLED)) {
827 acb &= (~ACB_DISABLED);
828 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
829 ret = asprintf(pp_err_str,
830 "Failed to unset 'disabled' "
831 "flag for user %s.\n",
832 user_name);
833 if (ret < 0) {
834 *pp_err_str = NULL;
836 result = NT_STATUS_UNSUCCESSFUL;
837 goto done;
841 acb &= (~ACB_PWNOTREQ);
842 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
843 ret = asprintf(pp_err_str,
844 "Failed to unset 'no password required'"
845 " flag for user %s.\n", user_name);
846 if (ret < 0) {
847 *pp_err_str = NULL;
849 result = NT_STATUS_UNSUCCESSFUL;
850 goto done;
853 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
854 ret = asprintf(pp_err_str,
855 "Failed to set password for "
856 "user %s.\n", user_name);
857 if (ret < 0) {
858 *pp_err_str = NULL;
860 result = NT_STATUS_UNSUCCESSFUL;
861 goto done;
865 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
866 acb |= ACB_DISABLED;
867 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
868 ret = asprintf(pp_err_str,
869 "Failed to set 'disabled' flag for "
870 "user %s.\n", user_name);
871 if (ret < 0) {
872 *pp_err_str = NULL;
874 result = NT_STATUS_UNSUCCESSFUL;
875 goto done;
879 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
880 acb &= (~ACB_DISABLED);
881 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
882 ret = asprintf(pp_err_str,
883 "Failed to unset 'disabled' flag for "
884 "user %s.\n", user_name);
885 if (ret < 0) {
886 *pp_err_str = NULL;
888 result = NT_STATUS_UNSUCCESSFUL;
889 goto done;
893 /* now commit changes if any */
894 result = pdb_update_sam_account(sam_pass);
895 if (!NT_STATUS_IS_OK(result)) {
896 ret = asprintf(pp_err_str,
897 "Failed to modify entry for user %s.\n",
898 user_name);
899 if (ret < 0) {
900 *pp_err_str = NULL;
902 goto done;
905 if (local_flags & LOCAL_ADD_USER) {
906 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
907 } else if (local_flags & LOCAL_DISABLE_USER) {
908 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
909 } else if (local_flags & LOCAL_ENABLE_USER) {
910 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
911 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
912 ret = asprintf(pp_msg_str,
913 "User %s password set to none.\n", user_name);
916 if (ret < 0) {
917 *pp_msg_str = NULL;
920 result = NT_STATUS_OK;
922 done:
923 TALLOC_FREE(sam_pass);
924 return result;
927 /**********************************************************************
928 Marshall/unmarshall struct samu structs.
929 *********************************************************************/
931 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
932 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
933 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
934 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
935 /* nothing changed between V3 and V4 */
937 /*********************************************************************
938 *********************************************************************/
940 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
943 /* times are stored as 32bit integer
944 take care on system with 64bit wide time_t
945 --SSS */
946 uint32_t logon_time,
947 logoff_time,
948 kickoff_time,
949 pass_last_set_time,
950 pass_can_change_time,
951 pass_must_change_time;
952 char *username = NULL;
953 char *domain = NULL;
954 char *nt_username = NULL;
955 char *dir_drive = NULL;
956 char *unknown_str = NULL;
957 char *munged_dial = NULL;
958 char *fullname = NULL;
959 char *homedir = NULL;
960 char *logon_script = NULL;
961 char *profile_path = NULL;
962 char *acct_desc = NULL;
963 char *workstations = NULL;
964 uint32_t username_len, domain_len, nt_username_len,
965 dir_drive_len, unknown_str_len, munged_dial_len,
966 fullname_len, homedir_len, logon_script_len,
967 profile_path_len, acct_desc_len, workstations_len;
969 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
970 uint16_t acct_ctrl, logon_divs;
971 uint16_t bad_password_count, logon_count;
972 uint8_t *hours = NULL;
973 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
974 uint32_t len = 0;
975 uint32_t lm_pw_len, nt_pw_len, hourslen;
976 bool ret = True;
978 if(sampass == NULL || buf == NULL) {
979 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
980 return False;
983 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
985 /* unpack the buffer into variables */
986 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
987 &logon_time, /* d */
988 &logoff_time, /* d */
989 &kickoff_time, /* d */
990 &pass_last_set_time, /* d */
991 &pass_can_change_time, /* d */
992 &pass_must_change_time, /* d */
993 &username_len, &username, /* B */
994 &domain_len, &domain, /* B */
995 &nt_username_len, &nt_username, /* B */
996 &fullname_len, &fullname, /* B */
997 &homedir_len, &homedir, /* B */
998 &dir_drive_len, &dir_drive, /* B */
999 &logon_script_len, &logon_script, /* B */
1000 &profile_path_len, &profile_path, /* B */
1001 &acct_desc_len, &acct_desc, /* B */
1002 &workstations_len, &workstations, /* B */
1003 &unknown_str_len, &unknown_str, /* B */
1004 &munged_dial_len, &munged_dial, /* B */
1005 &user_rid, /* d */
1006 &group_rid, /* d */
1007 &lm_pw_len, &lm_pw_ptr, /* B */
1008 &nt_pw_len, &nt_pw_ptr, /* B */
1009 &acct_ctrl, /* w */
1010 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
1011 &logon_divs, /* w */
1012 &hours_len, /* d */
1013 &hourslen, &hours, /* B */
1014 &bad_password_count, /* w */
1015 &logon_count, /* w */
1016 &unknown_6); /* d */
1018 if (len == (uint32_t) -1) {
1019 ret = False;
1020 goto done;
1023 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1024 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1025 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1026 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1027 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1029 pdb_set_username(sampass, username, PDB_SET);
1030 pdb_set_domain(sampass, domain, PDB_SET);
1031 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1032 pdb_set_fullname(sampass, fullname, PDB_SET);
1034 if (homedir) {
1035 pdb_set_homedir(sampass, homedir, PDB_SET);
1037 else {
1038 pdb_set_homedir(sampass,
1039 talloc_sub_basic(sampass, username, domain,
1040 lp_logon_home()),
1041 PDB_DEFAULT);
1044 if (dir_drive)
1045 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1046 else {
1047 pdb_set_dir_drive(sampass,
1048 talloc_sub_basic(sampass, username, domain,
1049 lp_logon_drive()),
1050 PDB_DEFAULT);
1053 if (logon_script)
1054 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1055 else {
1056 pdb_set_logon_script(sampass,
1057 talloc_sub_basic(sampass, username, domain,
1058 lp_logon_script()),
1059 PDB_DEFAULT);
1062 if (profile_path) {
1063 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1064 } else {
1065 pdb_set_profile_path(sampass,
1066 talloc_sub_basic(sampass, username, domain,
1067 lp_logon_path()),
1068 PDB_DEFAULT);
1071 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1072 pdb_set_workstations(sampass, workstations, PDB_SET);
1073 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1075 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1076 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1077 ret = False;
1078 goto done;
1082 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1083 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1084 ret = False;
1085 goto done;
1089 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1090 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1091 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1092 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1093 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1094 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1095 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1096 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1097 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1098 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1100 done:
1102 SAFE_FREE(username);
1103 SAFE_FREE(domain);
1104 SAFE_FREE(nt_username);
1105 SAFE_FREE(fullname);
1106 SAFE_FREE(homedir);
1107 SAFE_FREE(dir_drive);
1108 SAFE_FREE(logon_script);
1109 SAFE_FREE(profile_path);
1110 SAFE_FREE(acct_desc);
1111 SAFE_FREE(workstations);
1112 SAFE_FREE(munged_dial);
1113 SAFE_FREE(unknown_str);
1114 SAFE_FREE(lm_pw_ptr);
1115 SAFE_FREE(nt_pw_ptr);
1116 SAFE_FREE(hours);
1118 return ret;
1121 /*********************************************************************
1122 *********************************************************************/
1124 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1127 /* times are stored as 32bit integer
1128 take care on system with 64bit wide time_t
1129 --SSS */
1130 uint32_t logon_time,
1131 logoff_time,
1132 kickoff_time,
1133 bad_password_time,
1134 pass_last_set_time,
1135 pass_can_change_time,
1136 pass_must_change_time;
1137 char *username = NULL;
1138 char *domain = NULL;
1139 char *nt_username = NULL;
1140 char *dir_drive = NULL;
1141 char *unknown_str = NULL;
1142 char *munged_dial = NULL;
1143 char *fullname = NULL;
1144 char *homedir = NULL;
1145 char *logon_script = NULL;
1146 char *profile_path = NULL;
1147 char *acct_desc = NULL;
1148 char *workstations = NULL;
1149 uint32_t username_len, domain_len, nt_username_len,
1150 dir_drive_len, unknown_str_len, munged_dial_len,
1151 fullname_len, homedir_len, logon_script_len,
1152 profile_path_len, acct_desc_len, workstations_len;
1154 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1155 uint16_t acct_ctrl, logon_divs;
1156 uint16_t bad_password_count, logon_count;
1157 uint8_t *hours = NULL;
1158 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1159 uint32_t len = 0;
1160 uint32_t lm_pw_len, nt_pw_len, hourslen;
1161 bool ret = True;
1163 if(sampass == NULL || buf == NULL) {
1164 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1165 return False;
1168 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1170 /* unpack the buffer into variables */
1171 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1172 &logon_time, /* d */
1173 &logoff_time, /* d */
1174 &kickoff_time, /* d */
1175 /* Change from V0 is addition of bad_password_time field. */
1176 &bad_password_time, /* d */
1177 &pass_last_set_time, /* d */
1178 &pass_can_change_time, /* d */
1179 &pass_must_change_time, /* d */
1180 &username_len, &username, /* B */
1181 &domain_len, &domain, /* B */
1182 &nt_username_len, &nt_username, /* B */
1183 &fullname_len, &fullname, /* B */
1184 &homedir_len, &homedir, /* B */
1185 &dir_drive_len, &dir_drive, /* B */
1186 &logon_script_len, &logon_script, /* B */
1187 &profile_path_len, &profile_path, /* B */
1188 &acct_desc_len, &acct_desc, /* B */
1189 &workstations_len, &workstations, /* B */
1190 &unknown_str_len, &unknown_str, /* B */
1191 &munged_dial_len, &munged_dial, /* B */
1192 &user_rid, /* d */
1193 &group_rid, /* d */
1194 &lm_pw_len, &lm_pw_ptr, /* B */
1195 &nt_pw_len, &nt_pw_ptr, /* B */
1196 &acct_ctrl, /* w */
1197 &remove_me, /* d */
1198 &logon_divs, /* w */
1199 &hours_len, /* d */
1200 &hourslen, &hours, /* B */
1201 &bad_password_count, /* w */
1202 &logon_count, /* w */
1203 &unknown_6); /* d */
1205 if (len == (uint32_t) -1) {
1206 ret = False;
1207 goto done;
1210 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1211 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1212 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1214 /* Change from V0 is addition of bad_password_time field. */
1215 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1216 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1217 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1219 pdb_set_username(sampass, username, PDB_SET);
1220 pdb_set_domain(sampass, domain, PDB_SET);
1221 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1222 pdb_set_fullname(sampass, fullname, PDB_SET);
1224 if (homedir) {
1225 pdb_set_homedir(sampass, homedir, PDB_SET);
1227 else {
1228 pdb_set_homedir(sampass,
1229 talloc_sub_basic(sampass, username, domain,
1230 lp_logon_home()),
1231 PDB_DEFAULT);
1234 if (dir_drive)
1235 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1236 else {
1237 pdb_set_dir_drive(sampass,
1238 talloc_sub_basic(sampass, username, domain,
1239 lp_logon_drive()),
1240 PDB_DEFAULT);
1243 if (logon_script)
1244 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1245 else {
1246 pdb_set_logon_script(sampass,
1247 talloc_sub_basic(sampass, username, domain,
1248 lp_logon_script()),
1249 PDB_DEFAULT);
1252 if (profile_path) {
1253 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1254 } else {
1255 pdb_set_profile_path(sampass,
1256 talloc_sub_basic(sampass, username, domain,
1257 lp_logon_path()),
1258 PDB_DEFAULT);
1261 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1262 pdb_set_workstations(sampass, workstations, PDB_SET);
1263 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1265 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1266 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1267 ret = False;
1268 goto done;
1272 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1273 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1274 ret = False;
1275 goto done;
1279 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1281 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1282 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1283 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1284 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1285 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1286 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1287 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1288 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1289 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1291 done:
1293 SAFE_FREE(username);
1294 SAFE_FREE(domain);
1295 SAFE_FREE(nt_username);
1296 SAFE_FREE(fullname);
1297 SAFE_FREE(homedir);
1298 SAFE_FREE(dir_drive);
1299 SAFE_FREE(logon_script);
1300 SAFE_FREE(profile_path);
1301 SAFE_FREE(acct_desc);
1302 SAFE_FREE(workstations);
1303 SAFE_FREE(munged_dial);
1304 SAFE_FREE(unknown_str);
1305 SAFE_FREE(lm_pw_ptr);
1306 SAFE_FREE(nt_pw_ptr);
1307 SAFE_FREE(hours);
1309 return ret;
1312 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1315 /* times are stored as 32bit integer
1316 take care on system with 64bit wide time_t
1317 --SSS */
1318 uint32_t logon_time,
1319 logoff_time,
1320 kickoff_time,
1321 bad_password_time,
1322 pass_last_set_time,
1323 pass_can_change_time,
1324 pass_must_change_time;
1325 char *username = NULL;
1326 char *domain = NULL;
1327 char *nt_username = NULL;
1328 char *dir_drive = NULL;
1329 char *unknown_str = NULL;
1330 char *munged_dial = NULL;
1331 char *fullname = NULL;
1332 char *homedir = NULL;
1333 char *logon_script = NULL;
1334 char *profile_path = NULL;
1335 char *acct_desc = NULL;
1336 char *workstations = NULL;
1337 uint32_t username_len, domain_len, nt_username_len,
1338 dir_drive_len, unknown_str_len, munged_dial_len,
1339 fullname_len, homedir_len, logon_script_len,
1340 profile_path_len, acct_desc_len, workstations_len;
1342 uint32_t user_rid, group_rid, hours_len, unknown_6;
1343 uint16_t acct_ctrl, logon_divs;
1344 uint16_t bad_password_count, logon_count;
1345 uint8_t *hours = NULL;
1346 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1347 uint32_t len = 0;
1348 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1349 uint32_t pwHistLen = 0;
1350 bool ret = True;
1351 fstring tmp_string;
1352 bool expand_explicit = lp_passdb_expand_explicit();
1354 if(sampass == NULL || buf == NULL) {
1355 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1356 return False;
1359 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1361 /* unpack the buffer into variables */
1362 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1363 &logon_time, /* d */
1364 &logoff_time, /* d */
1365 &kickoff_time, /* d */
1366 &bad_password_time, /* d */
1367 &pass_last_set_time, /* d */
1368 &pass_can_change_time, /* d */
1369 &pass_must_change_time, /* d */
1370 &username_len, &username, /* B */
1371 &domain_len, &domain, /* B */
1372 &nt_username_len, &nt_username, /* B */
1373 &fullname_len, &fullname, /* B */
1374 &homedir_len, &homedir, /* B */
1375 &dir_drive_len, &dir_drive, /* B */
1376 &logon_script_len, &logon_script, /* B */
1377 &profile_path_len, &profile_path, /* B */
1378 &acct_desc_len, &acct_desc, /* B */
1379 &workstations_len, &workstations, /* B */
1380 &unknown_str_len, &unknown_str, /* B */
1381 &munged_dial_len, &munged_dial, /* B */
1382 &user_rid, /* d */
1383 &group_rid, /* d */
1384 &lm_pw_len, &lm_pw_ptr, /* B */
1385 &nt_pw_len, &nt_pw_ptr, /* B */
1386 /* Change from V1 is addition of password history field. */
1387 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1388 &acct_ctrl, /* w */
1389 /* Also "remove_me" field was removed. */
1390 &logon_divs, /* w */
1391 &hours_len, /* d */
1392 &hourslen, &hours, /* B */
1393 &bad_password_count, /* w */
1394 &logon_count, /* w */
1395 &unknown_6); /* d */
1397 if (len == (uint32_t) -1) {
1398 ret = False;
1399 goto done;
1402 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1403 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1404 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1405 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1406 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1407 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1409 pdb_set_username(sampass, username, PDB_SET);
1410 pdb_set_domain(sampass, domain, PDB_SET);
1411 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1412 pdb_set_fullname(sampass, fullname, PDB_SET);
1414 if (homedir) {
1415 fstrcpy( tmp_string, homedir );
1416 if (expand_explicit) {
1417 standard_sub_basic( username, domain, tmp_string,
1418 sizeof(tmp_string) );
1420 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1422 else {
1423 pdb_set_homedir(sampass,
1424 talloc_sub_basic(sampass, username, domain,
1425 lp_logon_home()),
1426 PDB_DEFAULT);
1429 if (dir_drive)
1430 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1431 else
1432 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1434 if (logon_script) {
1435 fstrcpy( tmp_string, logon_script );
1436 if (expand_explicit) {
1437 standard_sub_basic( username, domain, tmp_string,
1438 sizeof(tmp_string) );
1440 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1442 else {
1443 pdb_set_logon_script(sampass,
1444 talloc_sub_basic(sampass, username, domain,
1445 lp_logon_script()),
1446 PDB_DEFAULT);
1449 if (profile_path) {
1450 fstrcpy( tmp_string, profile_path );
1451 if (expand_explicit) {
1452 standard_sub_basic( username, domain, tmp_string,
1453 sizeof(tmp_string) );
1455 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1457 else {
1458 pdb_set_profile_path(sampass,
1459 talloc_sub_basic(sampass, username, domain,
1460 lp_logon_path()),
1461 PDB_DEFAULT);
1464 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1465 pdb_set_workstations(sampass, workstations, PDB_SET);
1466 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1468 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1469 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1470 ret = False;
1471 goto done;
1475 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1476 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1477 ret = False;
1478 goto done;
1482 /* Change from V1 is addition of password history field. */
1483 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1484 if (pwHistLen) {
1485 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1486 if (!pw_hist) {
1487 ret = False;
1488 goto done;
1490 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1491 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1492 int i;
1493 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1494 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1495 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1496 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1497 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1498 PW_HISTORY_ENTRY_LEN);
1501 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1502 SAFE_FREE(pw_hist);
1503 ret = False;
1504 goto done;
1506 SAFE_FREE(pw_hist);
1507 } else {
1508 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1511 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1512 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1513 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1514 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1515 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1516 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1517 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1518 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1519 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1521 done:
1523 SAFE_FREE(username);
1524 SAFE_FREE(domain);
1525 SAFE_FREE(nt_username);
1526 SAFE_FREE(fullname);
1527 SAFE_FREE(homedir);
1528 SAFE_FREE(dir_drive);
1529 SAFE_FREE(logon_script);
1530 SAFE_FREE(profile_path);
1531 SAFE_FREE(acct_desc);
1532 SAFE_FREE(workstations);
1533 SAFE_FREE(munged_dial);
1534 SAFE_FREE(unknown_str);
1535 SAFE_FREE(lm_pw_ptr);
1536 SAFE_FREE(nt_pw_ptr);
1537 SAFE_FREE(nt_pw_hist_ptr);
1538 SAFE_FREE(hours);
1540 return ret;
1543 /*********************************************************************
1544 *********************************************************************/
1546 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1549 /* times are stored as 32bit integer
1550 take care on system with 64bit wide time_t
1551 --SSS */
1552 uint32_t logon_time,
1553 logoff_time,
1554 kickoff_time,
1555 bad_password_time,
1556 pass_last_set_time,
1557 pass_can_change_time,
1558 pass_must_change_time;
1559 char *username = NULL;
1560 char *domain = NULL;
1561 char *nt_username = NULL;
1562 char *dir_drive = NULL;
1563 char *comment = NULL;
1564 char *munged_dial = NULL;
1565 char *fullname = NULL;
1566 char *homedir = NULL;
1567 char *logon_script = NULL;
1568 char *profile_path = NULL;
1569 char *acct_desc = NULL;
1570 char *workstations = NULL;
1571 uint32_t username_len, domain_len, nt_username_len,
1572 dir_drive_len, comment_len, munged_dial_len,
1573 fullname_len, homedir_len, logon_script_len,
1574 profile_path_len, acct_desc_len, workstations_len;
1576 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1577 uint16_t logon_divs;
1578 uint16_t bad_password_count, logon_count;
1579 uint8_t *hours = NULL;
1580 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1581 uint32_t len = 0;
1582 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1583 uint32_t pwHistLen = 0;
1584 bool ret = True;
1585 fstring tmp_string;
1586 bool expand_explicit = lp_passdb_expand_explicit();
1588 if(sampass == NULL || buf == NULL) {
1589 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1590 return False;
1593 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1595 /* unpack the buffer into variables */
1596 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1597 &logon_time, /* d */
1598 &logoff_time, /* d */
1599 &kickoff_time, /* d */
1600 &bad_password_time, /* d */
1601 &pass_last_set_time, /* d */
1602 &pass_can_change_time, /* d */
1603 &pass_must_change_time, /* d */
1604 &username_len, &username, /* B */
1605 &domain_len, &domain, /* B */
1606 &nt_username_len, &nt_username, /* B */
1607 &fullname_len, &fullname, /* B */
1608 &homedir_len, &homedir, /* B */
1609 &dir_drive_len, &dir_drive, /* B */
1610 &logon_script_len, &logon_script, /* B */
1611 &profile_path_len, &profile_path, /* B */
1612 &acct_desc_len, &acct_desc, /* B */
1613 &workstations_len, &workstations, /* B */
1614 &comment_len, &comment, /* B */
1615 &munged_dial_len, &munged_dial, /* B */
1616 &user_rid, /* d */
1617 &group_rid, /* d */
1618 &lm_pw_len, &lm_pw_ptr, /* B */
1619 &nt_pw_len, &nt_pw_ptr, /* B */
1620 /* Change from V1 is addition of password history field. */
1621 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1622 /* Change from V2 is the uint32_t acb_mask */
1623 &acct_ctrl, /* d */
1624 /* Also "remove_me" field was removed. */
1625 &logon_divs, /* w */
1626 &hours_len, /* d */
1627 &hourslen, &hours, /* B */
1628 &bad_password_count, /* w */
1629 &logon_count, /* w */
1630 &unknown_6); /* d */
1632 if (len == (uint32_t) -1) {
1633 ret = False;
1634 goto done;
1637 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1638 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1639 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1640 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1641 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1642 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1644 pdb_set_username(sampass, username, PDB_SET);
1645 pdb_set_domain(sampass, domain, PDB_SET);
1646 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1647 pdb_set_fullname(sampass, fullname, PDB_SET);
1649 if (homedir) {
1650 fstrcpy( tmp_string, homedir );
1651 if (expand_explicit) {
1652 standard_sub_basic( username, domain, tmp_string,
1653 sizeof(tmp_string) );
1655 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1657 else {
1658 pdb_set_homedir(sampass,
1659 talloc_sub_basic(sampass, username, domain,
1660 lp_logon_home()),
1661 PDB_DEFAULT);
1664 if (dir_drive)
1665 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1666 else
1667 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1669 if (logon_script) {
1670 fstrcpy( tmp_string, logon_script );
1671 if (expand_explicit) {
1672 standard_sub_basic( username, domain, tmp_string,
1673 sizeof(tmp_string) );
1675 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1677 else {
1678 pdb_set_logon_script(sampass,
1679 talloc_sub_basic(sampass, username, domain,
1680 lp_logon_script()),
1681 PDB_DEFAULT);
1684 if (profile_path) {
1685 fstrcpy( tmp_string, profile_path );
1686 if (expand_explicit) {
1687 standard_sub_basic( username, domain, tmp_string,
1688 sizeof(tmp_string) );
1690 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1692 else {
1693 pdb_set_profile_path(sampass,
1694 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1695 PDB_DEFAULT);
1698 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1699 pdb_set_comment(sampass, comment, PDB_SET);
1700 pdb_set_workstations(sampass, workstations, PDB_SET);
1701 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1703 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1704 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1705 ret = False;
1706 goto done;
1710 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1711 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1712 ret = False;
1713 goto done;
1717 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1718 if (pwHistLen) {
1719 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1720 if (!pw_hist) {
1721 ret = False;
1722 goto done;
1724 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1725 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1726 int i;
1727 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1728 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1729 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1730 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1731 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1732 PW_HISTORY_ENTRY_LEN);
1735 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1736 SAFE_FREE(pw_hist);
1737 ret = False;
1738 goto done;
1740 SAFE_FREE(pw_hist);
1741 } else {
1742 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1745 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1746 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1747 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1748 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1749 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1750 /* Change from V2 is the uint32_t acct_ctrl */
1751 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1752 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1753 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1755 done:
1757 SAFE_FREE(username);
1758 SAFE_FREE(domain);
1759 SAFE_FREE(nt_username);
1760 SAFE_FREE(fullname);
1761 SAFE_FREE(homedir);
1762 SAFE_FREE(dir_drive);
1763 SAFE_FREE(logon_script);
1764 SAFE_FREE(profile_path);
1765 SAFE_FREE(acct_desc);
1766 SAFE_FREE(workstations);
1767 SAFE_FREE(munged_dial);
1768 SAFE_FREE(comment);
1769 SAFE_FREE(lm_pw_ptr);
1770 SAFE_FREE(nt_pw_ptr);
1771 SAFE_FREE(nt_pw_hist_ptr);
1772 SAFE_FREE(hours);
1774 return ret;
1777 /*********************************************************************
1778 *********************************************************************/
1780 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1782 size_t len, buflen;
1784 /* times are stored as 32bit integer
1785 take care on system with 64bit wide time_t
1786 --SSS */
1787 uint32_t logon_time,
1788 logoff_time,
1789 kickoff_time,
1790 bad_password_time,
1791 pass_last_set_time,
1792 pass_can_change_time,
1793 pass_must_change_time;
1795 uint32_t user_rid, group_rid;
1797 const char *username;
1798 const char *domain;
1799 const char *nt_username;
1800 const char *dir_drive;
1801 const char *comment;
1802 const char *munged_dial;
1803 const char *fullname;
1804 const char *homedir;
1805 const char *logon_script;
1806 const char *profile_path;
1807 const char *acct_desc;
1808 const char *workstations;
1809 uint32_t username_len, domain_len, nt_username_len,
1810 dir_drive_len, comment_len, munged_dial_len,
1811 fullname_len, homedir_len, logon_script_len,
1812 profile_path_len, acct_desc_len, workstations_len;
1814 const uint8_t *lm_pw;
1815 const uint8_t *nt_pw;
1816 const uint8_t *nt_pw_hist;
1817 uint32_t lm_pw_len = 16;
1818 uint32_t nt_pw_len = 16;
1819 uint32_t nt_pw_hist_len;
1820 uint32_t pwHistLen = 0;
1822 *buf = NULL;
1823 buflen = 0;
1825 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1826 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1827 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1828 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1829 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1830 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1831 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1833 user_rid = pdb_get_user_rid(sampass);
1834 group_rid = pdb_get_group_rid(sampass);
1836 username = pdb_get_username(sampass);
1837 if (username) {
1838 username_len = strlen(username) +1;
1839 } else {
1840 username_len = 0;
1843 domain = pdb_get_domain(sampass);
1844 if (domain) {
1845 domain_len = strlen(domain) +1;
1846 } else {
1847 domain_len = 0;
1850 nt_username = pdb_get_nt_username(sampass);
1851 if (nt_username) {
1852 nt_username_len = strlen(nt_username) +1;
1853 } else {
1854 nt_username_len = 0;
1857 fullname = pdb_get_fullname(sampass);
1858 if (fullname) {
1859 fullname_len = strlen(fullname) +1;
1860 } else {
1861 fullname_len = 0;
1865 * Only updates fields which have been set (not defaults from smb.conf)
1868 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1869 dir_drive = pdb_get_dir_drive(sampass);
1870 } else {
1871 dir_drive = NULL;
1873 if (dir_drive) {
1874 dir_drive_len = strlen(dir_drive) +1;
1875 } else {
1876 dir_drive_len = 0;
1879 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1880 homedir = pdb_get_homedir(sampass);
1881 } else {
1882 homedir = NULL;
1884 if (homedir) {
1885 homedir_len = strlen(homedir) +1;
1886 } else {
1887 homedir_len = 0;
1890 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1891 logon_script = pdb_get_logon_script(sampass);
1892 } else {
1893 logon_script = NULL;
1895 if (logon_script) {
1896 logon_script_len = strlen(logon_script) +1;
1897 } else {
1898 logon_script_len = 0;
1901 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1902 profile_path = pdb_get_profile_path(sampass);
1903 } else {
1904 profile_path = NULL;
1906 if (profile_path) {
1907 profile_path_len = strlen(profile_path) +1;
1908 } else {
1909 profile_path_len = 0;
1912 lm_pw = pdb_get_lanman_passwd(sampass);
1913 if (!lm_pw) {
1914 lm_pw_len = 0;
1917 nt_pw = pdb_get_nt_passwd(sampass);
1918 if (!nt_pw) {
1919 nt_pw_len = 0;
1922 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1923 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1924 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1925 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1926 } else {
1927 nt_pw_hist_len = 0;
1930 acct_desc = pdb_get_acct_desc(sampass);
1931 if (acct_desc) {
1932 acct_desc_len = strlen(acct_desc) +1;
1933 } else {
1934 acct_desc_len = 0;
1937 workstations = pdb_get_workstations(sampass);
1938 if (workstations) {
1939 workstations_len = strlen(workstations) +1;
1940 } else {
1941 workstations_len = 0;
1944 comment = pdb_get_comment(sampass);
1945 if (comment) {
1946 comment_len = strlen(comment) +1;
1947 } else {
1948 comment_len = 0;
1951 munged_dial = pdb_get_munged_dial(sampass);
1952 if (munged_dial) {
1953 munged_dial_len = strlen(munged_dial) +1;
1954 } else {
1955 munged_dial_len = 0;
1958 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1960 /* one time to get the size needed */
1961 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1962 logon_time, /* d */
1963 logoff_time, /* d */
1964 kickoff_time, /* d */
1965 bad_password_time, /* d */
1966 pass_last_set_time, /* d */
1967 pass_can_change_time, /* d */
1968 pass_must_change_time, /* d */
1969 username_len, username, /* B */
1970 domain_len, domain, /* B */
1971 nt_username_len, nt_username, /* B */
1972 fullname_len, fullname, /* B */
1973 homedir_len, homedir, /* B */
1974 dir_drive_len, dir_drive, /* B */
1975 logon_script_len, logon_script, /* B */
1976 profile_path_len, profile_path, /* B */
1977 acct_desc_len, acct_desc, /* B */
1978 workstations_len, workstations, /* B */
1979 comment_len, comment, /* B */
1980 munged_dial_len, munged_dial, /* B */
1981 user_rid, /* d */
1982 group_rid, /* d */
1983 lm_pw_len, lm_pw, /* B */
1984 nt_pw_len, nt_pw, /* B */
1985 nt_pw_hist_len, nt_pw_hist, /* B */
1986 pdb_get_acct_ctrl(sampass), /* d */
1987 pdb_get_logon_divs(sampass), /* w */
1988 pdb_get_hours_len(sampass), /* d */
1989 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1990 pdb_get_bad_password_count(sampass), /* w */
1991 pdb_get_logon_count(sampass), /* w */
1992 pdb_get_unknown_6(sampass)); /* d */
1994 if (size_only) {
1995 return buflen;
1998 /* malloc the space needed */
1999 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
2000 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
2001 return (-1);
2004 /* now for the real call to tdb_pack() */
2005 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2006 logon_time, /* d */
2007 logoff_time, /* d */
2008 kickoff_time, /* d */
2009 bad_password_time, /* d */
2010 pass_last_set_time, /* d */
2011 pass_can_change_time, /* d */
2012 pass_must_change_time, /* d */
2013 username_len, username, /* B */
2014 domain_len, domain, /* B */
2015 nt_username_len, nt_username, /* B */
2016 fullname_len, fullname, /* B */
2017 homedir_len, homedir, /* B */
2018 dir_drive_len, dir_drive, /* B */
2019 logon_script_len, logon_script, /* B */
2020 profile_path_len, profile_path, /* B */
2021 acct_desc_len, acct_desc, /* B */
2022 workstations_len, workstations, /* B */
2023 comment_len, comment, /* B */
2024 munged_dial_len, munged_dial, /* B */
2025 user_rid, /* d */
2026 group_rid, /* d */
2027 lm_pw_len, lm_pw, /* B */
2028 nt_pw_len, nt_pw, /* B */
2029 nt_pw_hist_len, nt_pw_hist, /* B */
2030 pdb_get_acct_ctrl(sampass), /* d */
2031 pdb_get_logon_divs(sampass), /* w */
2032 pdb_get_hours_len(sampass), /* d */
2033 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2034 pdb_get_bad_password_count(sampass), /* w */
2035 pdb_get_logon_count(sampass), /* w */
2036 pdb_get_unknown_6(sampass)); /* d */
2038 /* check to make sure we got it correct */
2039 if (buflen != len) {
2040 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2041 (unsigned long)buflen, (unsigned long)len));
2042 /* error */
2043 SAFE_FREE (*buf);
2044 return (-1);
2047 return (buflen);
2050 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2052 /* nothing changed between V3 and V4 */
2053 return init_samu_from_buffer_v3(sampass, buf, buflen);
2056 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2058 /* nothing changed between V3 and V4 */
2059 return init_buffer_from_samu_v3(buf, sampass, size_only);
2062 /**********************************************************************
2063 Intialize a struct samu struct from a BYTE buffer of size len
2064 *********************************************************************/
2066 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2067 uint8_t *buf, uint32_t buflen)
2069 switch (level) {
2070 case SAMU_BUFFER_V0:
2071 return init_samu_from_buffer_v0(sampass, buf, buflen);
2072 case SAMU_BUFFER_V1:
2073 return init_samu_from_buffer_v1(sampass, buf, buflen);
2074 case SAMU_BUFFER_V2:
2075 return init_samu_from_buffer_v2(sampass, buf, buflen);
2076 case SAMU_BUFFER_V3:
2077 return init_samu_from_buffer_v3(sampass, buf, buflen);
2078 case SAMU_BUFFER_V4:
2079 return init_samu_from_buffer_v4(sampass, buf, buflen);
2082 return false;
2085 /**********************************************************************
2086 Intialize a BYTE buffer from a struct samu struct
2087 *********************************************************************/
2089 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2091 return init_buffer_from_samu_v4(buf, sampass, size_only);
2094 /*********************************************************************
2095 *********************************************************************/
2097 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2099 uint8_t *buf = NULL;
2100 int len;
2102 len = init_buffer_from_samu(&buf, src, False);
2103 if (len == -1 || !buf) {
2104 SAFE_FREE(buf);
2105 return False;
2108 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2109 free(buf);
2110 return False;
2113 dst->methods = src->methods;
2115 if ( src->unix_pw ) {
2116 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2117 if (!dst->unix_pw) {
2118 free(buf);
2119 return False;
2123 if (src->group_sid) {
2124 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2127 free(buf);
2128 return True;
2131 /*********************************************************************
2132 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2133 *********************************************************************/
2135 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2137 time_t LastBadPassword;
2138 uint16_t BadPasswordCount;
2139 uint32_t resettime;
2140 bool res;
2142 BadPasswordCount = pdb_get_bad_password_count(sampass);
2143 if (!BadPasswordCount) {
2144 DEBUG(9, ("No bad password attempts.\n"));
2145 return True;
2148 become_root();
2149 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2150 unbecome_root();
2152 if (!res) {
2153 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2154 return False;
2157 /* First, check if there is a reset time to compare */
2158 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2159 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2160 return True;
2163 LastBadPassword = pdb_get_bad_password_time(sampass);
2164 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2165 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2166 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2167 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2168 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2169 if (updated) {
2170 *updated = True;
2174 return True;
2177 /*********************************************************************
2178 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2179 *********************************************************************/
2181 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2183 uint32_t duration;
2184 time_t LastBadPassword;
2185 bool res;
2187 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2188 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2189 pdb_get_username(sampass)));
2190 return True;
2193 become_root();
2194 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2195 unbecome_root();
2197 if (!res) {
2198 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2199 return False;
2202 /* First, check if there is a duration to compare */
2203 if ((duration == (uint32_t) -1) || (duration == 0)) {
2204 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2205 return True;
2208 LastBadPassword = pdb_get_bad_password_time(sampass);
2209 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2210 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2212 if (LastBadPassword == (time_t)0) {
2213 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2214 "administratively locked out with no bad password "
2215 "time. Leaving locked out.\n",
2216 pdb_get_username(sampass) ));
2217 return True;
2220 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2221 pdb_set_acct_ctrl(sampass,
2222 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2223 PDB_CHANGED);
2224 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2225 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2226 if (updated) {
2227 *updated = True;
2231 return True;
2234 /*********************************************************************
2235 Increment the bad_password_count
2236 *********************************************************************/
2238 bool pdb_increment_bad_password_count(struct samu *sampass)
2240 uint32_t account_policy_lockout;
2241 bool autolock_updated = False, badpw_updated = False;
2242 bool ret;
2244 /* Retrieve the account lockout policy */
2245 become_root();
2246 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2247 unbecome_root();
2248 if ( !ret ) {
2249 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2250 return False;
2253 /* If there is no policy, we don't need to continue checking */
2254 if (!account_policy_lockout) {
2255 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2256 return True;
2259 /* Check if the autolock needs to be cleared */
2260 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2261 return False;
2263 /* Check if the badpw count needs to be reset */
2264 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2265 return False;
2268 Ok, now we can assume that any resetting that needs to be
2269 done has been done, and just get on with incrementing
2270 and autolocking if necessary
2273 pdb_set_bad_password_count(sampass,
2274 pdb_get_bad_password_count(sampass)+1,
2275 PDB_CHANGED);
2276 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2279 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2280 return True;
2282 if (!pdb_set_acct_ctrl(sampass,
2283 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2284 PDB_CHANGED)) {
2285 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2286 return False;
2289 return True;
2292 bool is_dc_trusted_domain_situation(const char *domain_name)
2294 return IS_DC && !strequal(domain_name, lp_workgroup());
2297 /*******************************************************************
2298 Wrapper around retrieving the clear text trust account password.
2299 appropriate account name is stored in account_name.
2300 Caller must free password, but not account_name.
2301 *******************************************************************/
2303 static bool get_trust_pw_clear2(const char *domain,
2304 const char **account_name,
2305 enum netr_SchannelType *channel,
2306 char **cur_pw,
2307 time_t *_last_set_time,
2308 char **prev_pw)
2310 char *pwd;
2311 time_t last_set_time;
2313 if (cur_pw != NULL) {
2314 *cur_pw = NULL;
2316 if (_last_set_time != NULL) {
2317 *_last_set_time = 0;
2319 if (prev_pw != NULL) {
2320 *prev_pw = NULL;
2323 /* if we are a DC and this is not our domain, then lookup an account
2324 * for the domain trust */
2326 if (is_dc_trusted_domain_situation(domain)) {
2327 if (!lp_allow_trusted_domains()) {
2328 return false;
2331 if (!pdb_get_trusteddom_pw(domain, cur_pw, NULL,
2332 &last_set_time))
2334 DEBUG(0, ("get_trust_pw: could not fetch trust "
2335 "account password for trusted domain %s\n",
2336 domain));
2337 return false;
2340 if (channel != NULL) {
2341 *channel = SEC_CHAN_DOMAIN;
2344 if (account_name != NULL) {
2345 *account_name = lp_workgroup();
2348 if (_last_set_time != NULL) {
2349 *_last_set_time = last_set_time;
2352 return true;
2356 * Since we can only be member of one single domain, we are now
2357 * in a member situation:
2359 * - Either we are a DC (selfjoined) and the domain is our
2360 * own domain.
2361 * - Or we are on a member and the domain is our own or some
2362 * other (potentially trusted) domain.
2364 * In both cases, we can only get the machine account password
2365 * for our own domain to connect to our own dc. (For a member,
2366 * request to trusted domains are performed through our dc.)
2368 * So we simply use our own domain name to retrieve the
2369 * machine account passowrd and ignore the request domain here.
2372 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2374 if (pwd != NULL) {
2375 struct timeval expire;
2377 *cur_pw = pwd;
2379 if (account_name != NULL) {
2380 *account_name = lp_netbios_name();
2383 if (_last_set_time != NULL) {
2384 *_last_set_time = last_set_time;
2387 if (prev_pw == NULL) {
2388 return true;
2391 ZERO_STRUCT(expire);
2392 expire.tv_sec = lp_machine_password_timeout();
2393 expire.tv_sec /= 2;
2394 expire.tv_sec += last_set_time;
2395 if (timeval_expired(&expire)) {
2396 return true;
2399 pwd = secrets_fetch_prev_machine_password(lp_workgroup());
2400 if (pwd != NULL) {
2401 *prev_pw = pwd;
2404 return true;
2407 DEBUG(5, ("get_trust_pw_clear2: could not fetch clear text trust "
2408 "account password for domain %s\n", domain));
2409 return false;
2412 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2413 const char **account_name,
2414 enum netr_SchannelType *channel)
2416 return get_trust_pw_clear2(domain,
2417 account_name,
2418 channel,
2419 ret_pwd,
2420 NULL,
2421 NULL);
2424 /*******************************************************************
2425 Wrapper around retrieving the trust account password.
2426 appropriate account name is stored in account_name.
2427 *******************************************************************/
2429 static bool get_trust_pw_hash2(const char *domain,
2430 const char **account_name,
2431 enum netr_SchannelType *channel,
2432 struct samr_Password *current_nt_hash,
2433 time_t *last_set_time,
2434 struct samr_Password **_previous_nt_hash)
2436 char *cur_pw = NULL;
2437 char *prev_pw = NULL;
2438 char **_prev_pw = NULL;
2439 bool ok;
2441 if (_previous_nt_hash != NULL) {
2442 *_previous_nt_hash = NULL;
2443 _prev_pw = &prev_pw;
2446 ok = get_trust_pw_clear2(domain, account_name, channel,
2447 &cur_pw, last_set_time, _prev_pw);
2448 if (ok) {
2449 struct samr_Password *previous_nt_hash = NULL;
2451 E_md4hash(cur_pw, current_nt_hash->hash);
2452 SAFE_FREE(cur_pw);
2454 if (prev_pw == NULL) {
2455 return true;
2458 previous_nt_hash = SMB_MALLOC_P(struct samr_Password);
2459 if (previous_nt_hash == NULL) {
2460 return false;
2463 E_md4hash(prev_pw, previous_nt_hash->hash);
2464 SAFE_FREE(prev_pw);
2466 *_previous_nt_hash = previous_nt_hash;
2467 return true;
2468 } else if (is_dc_trusted_domain_situation(domain)) {
2469 return false;
2472 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2474 if (secrets_fetch_trust_account_password_legacy(domain,
2475 current_nt_hash->hash,
2476 last_set_time,
2477 channel))
2479 if (account_name != NULL) {
2480 *account_name = lp_netbios_name();
2483 return true;
2486 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2487 "password for domain %s\n", domain));
2488 return False;
2491 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2492 const char **account_name,
2493 enum netr_SchannelType *channel)
2495 struct samr_Password current_nt_hash;
2496 bool ok;
2498 ok = get_trust_pw_hash2(domain, account_name, channel,
2499 &current_nt_hash, NULL, NULL);
2500 if (!ok) {
2501 return false;
2504 memcpy(ret_pwd, current_nt_hash.hash, sizeof(current_nt_hash.hash));
2505 return true;
2508 NTSTATUS pdb_get_trust_credentials(const char *netbios_domain,
2509 const char *dns_domain, /* optional */
2510 TALLOC_CTX *mem_ctx,
2511 struct cli_credentials **_creds)
2513 TALLOC_CTX *frame = talloc_stackframe();
2514 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
2515 struct loadparm_context *lp_ctx;
2516 enum netr_SchannelType channel;
2517 time_t last_set_time;
2518 const char *_account_name;
2519 const char *account_name;
2520 char *cur_pw = NULL;
2521 char *prev_pw = NULL;
2522 struct samr_Password cur_nt_hash;
2523 struct cli_credentials *creds = NULL;
2524 bool ok;
2526 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2527 if (lp_ctx == NULL) {
2528 DEBUG(1, ("loadparm_init_s3 failed\n"));
2529 status = NT_STATUS_INTERNAL_ERROR;
2530 goto fail;
2533 creds = cli_credentials_init(mem_ctx);
2534 if (creds == NULL) {
2535 status = NT_STATUS_NO_MEMORY;
2536 goto fail;
2539 cli_credentials_set_conf(creds, lp_ctx);
2541 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2542 if (!ok) {
2543 status = NT_STATUS_NO_MEMORY;
2544 goto fail;
2548 * If this is our primary trust relationship, use the common
2549 * code to read the secrets.ldb or secrets.tdb file.
2551 if (strequal(netbios_domain, lp_workgroup())) {
2552 struct db_context *db_ctx = secrets_db_ctx();
2553 if (db_ctx == NULL) {
2554 DEBUG(1, ("failed to open secrets.tdb to obtain our trust credentials for %s\n",
2555 netbios_domain));
2556 status = NT_STATUS_INTERNAL_ERROR;
2557 goto fail;
2560 status = cli_credentials_set_machine_account_db_ctx(creds,
2561 lp_ctx,
2562 db_ctx);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 goto fail;
2566 goto done;
2567 } else if (!IS_DC) {
2568 DEBUG(1, ("Refusing to get trust account info for %s, "
2569 "which is not our primary domain %s, "
2570 "as we are not a DC\n",
2571 netbios_domain, lp_workgroup()));
2572 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2573 goto fail;
2576 ok = get_trust_pw_clear2(netbios_domain,
2577 &_account_name,
2578 &channel,
2579 &cur_pw,
2580 &last_set_time,
2581 &prev_pw);
2582 if (!ok) {
2583 ok = get_trust_pw_hash2(netbios_domain,
2584 &_account_name,
2585 &channel,
2586 &cur_nt_hash,
2587 &last_set_time,
2588 NULL);
2589 if (!ok) {
2590 DEBUG(1, ("get_trust_pw_*2 failed for domain[%s]\n",
2591 netbios_domain));
2592 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2593 goto fail;
2597 account_name = talloc_asprintf(frame, "%s$", _account_name);
2598 if (account_name == NULL) {
2599 status = NT_STATUS_NO_MEMORY;
2600 goto fail;
2603 cli_credentials_set_secure_channel_type(creds, channel);
2604 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2606 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2607 if (!ok) {
2608 status = NT_STATUS_NO_MEMORY;
2609 goto fail;
2612 if (dns_domain != NULL) {
2613 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2614 if (!ok) {
2615 status = NT_STATUS_NO_MEMORY;
2616 goto fail;
2620 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2621 if (!ok) {
2622 status = NT_STATUS_NO_MEMORY;
2623 goto fail;
2626 if (cur_pw == NULL) {
2627 ok = cli_credentials_set_nt_hash(creds, &cur_nt_hash, CRED_SPECIFIED);
2628 if (!ok) {
2629 status = NT_STATUS_NO_MEMORY;
2630 goto fail;
2632 goto done;
2635 ok = cli_credentials_set_password(creds, cur_pw, CRED_SPECIFIED);
2636 if (!ok) {
2637 status = NT_STATUS_NO_MEMORY;
2638 goto fail;
2641 if (prev_pw != NULL) {
2642 ok = cli_credentials_set_old_password(creds, prev_pw, CRED_SPECIFIED);
2643 if (!ok) {
2644 status = NT_STATUS_NO_MEMORY;
2645 goto fail;
2649 done:
2650 *_creds = creds;
2651 creds = NULL;
2652 status = NT_STATUS_OK;
2653 fail:
2654 TALLOC_FREE(creds);
2655 SAFE_FREE(cur_pw);
2656 SAFE_FREE(prev_pw);
2657 TALLOC_FREE(frame);
2658 return status;