s3:idmap_ad: add support for ADS_AUTH_SASL_{STARTTLS,LDAPS}
[Samba.git] / source3 / passdb / passdb.c
blob4bc48f63ee8cdf1cf1b0c3cfc8fd3d911c5474c7
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Jeremy Allison 1996-2001
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6 Copyright (C) Gerald (Jerry) Carter 2000-2006
7 Copyright (C) Andrew Bartlett 2001-2002
8 Copyright (C) Simo Sorce 2003
9 Copyright (C) Volker Lendecke 2006
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "passdb.h"
27 #include "system/passwd.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "secrets.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "util_tdb.h"
33 #include "auth/credentials/credentials.h"
34 #include "lib/param/param.h"
35 #include "lib/util/string_wrappers.h"
36 #include "source3/lib/substitute.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_PASSDB
41 /**********************************************************************
42 ***********************************************************************/
44 static int samu_destroy(struct samu *user)
46 data_blob_clear_free( &user->lm_pw );
47 data_blob_clear_free( &user->nt_pw );
49 if ( user->plaintext_pw )
50 BURN_STR(user->plaintext_pw);
52 return 0;
55 /**********************************************************************
56 generate a new struct samuser
57 ***********************************************************************/
59 struct samu *samu_new( TALLOC_CTX *ctx )
61 struct samu *user;
63 if ( !(user = talloc_zero( ctx, struct samu )) ) {
64 DEBUG(0,("samuser_new: Talloc failed!\n"));
65 return NULL;
68 talloc_set_destructor( user, samu_destroy );
70 /* no initial methods */
72 user->methods = NULL;
74 /* Don't change these timestamp settings without a good reason.
75 They are important for NT member server compatibility. */
77 user->logon_time = (time_t)0;
78 user->pass_last_set_time = (time_t)0;
79 user->pass_can_change_time = (time_t)0;
80 user->logoff_time = get_time_t_max();
81 user->kickoff_time = get_time_t_max();
82 user->fields_present = 0x00ffffff;
83 user->logon_divs = 168; /* hours per week */
84 user->hours_len = 21; /* 21 times 8 bits = 168 */
85 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
86 user->bad_password_count = 0;
87 user->logon_count = 0;
88 user->unknown_6 = 0x000004ec; /* don't know */
90 /* Some parts of samba strlen their pdb_get...() returns,
91 so this keeps the interface unchanged for now. */
93 user->username = "";
94 user->domain = "";
95 user->nt_username = "";
96 user->full_name = "";
97 user->home_dir = "";
98 user->logon_script = "";
99 user->profile_path = "";
100 user->acct_desc = "";
101 user->workstations = "";
102 user->comment = "";
103 user->munged_dial = "";
105 user->plaintext_pw = NULL;
107 /* Unless we know otherwise have a Account Control Bit
108 value of 'normal user'. This helps User Manager, which
109 asks for a filtered list of users. */
111 user->acct_ctrl = ACB_NORMAL;
113 return user;
116 static int count_commas(const char *str)
118 int num_commas = 0;
119 const char *comma = str;
121 while ((comma = strchr(comma, ',')) != NULL) {
122 comma += 1;
123 num_commas += 1;
125 return num_commas;
128 /*********************************************************************
129 Initialize a struct samu from a struct passwd including the user
130 and group SIDs. The *user structure is filled out with the Unix
131 attributes and a user SID.
132 *********************************************************************/
134 static NTSTATUS samu_set_unix_internal(struct pdb_methods *methods,
135 struct samu *user, const struct passwd *pwd, bool create)
137 const char *guest_account = lp_guest_account();
138 const char *domain = lp_netbios_name();
139 char *fullname;
140 uint32_t urid;
141 bool ok;
143 if ( !pwd ) {
144 return NT_STATUS_NO_SUCH_USER;
147 /* Basic properties based upon the Unix account information */
149 ok = pdb_set_username(user, pwd->pw_name, PDB_SET);
150 if (!ok) {
151 return NT_STATUS_NO_MEMORY;
154 fullname = NULL;
156 if (count_commas(pwd->pw_gecos) == 3) {
158 * Heuristic: This seems to be a gecos field that has been
159 * edited by chfn(1). Only use the part before the first
160 * comma. Fixes bug 5198.
162 fullname = talloc_strndup(
163 talloc_tos(), pwd->pw_gecos,
164 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
165 if (fullname == NULL) {
166 return NT_STATUS_NO_MEMORY;
170 if (fullname != NULL) {
171 ok = pdb_set_fullname(user, fullname, PDB_SET);
172 } else {
173 ok = pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
175 TALLOC_FREE(fullname);
177 if (!ok) {
178 return NT_STATUS_NO_MEMORY;
181 ok = pdb_set_domain(user, get_global_sam_name(), PDB_DEFAULT);
182 if (!ok) {
183 return NT_STATUS_NO_MEMORY;
185 #if 0
186 /* This can lead to a primary group of S-1-22-2-XX which
187 will be rejected by other parts of the Samba code.
188 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
189 --jerry */
191 gid_to_sid(&group_sid, pwd->pw_gid);
192 pdb_set_group_sid(user, &group_sid, PDB_SET);
193 #endif
195 /* save the password structure for later use */
197 user->unix_pw = tcopy_passwd( user, pwd );
198 if (user->unix_pw == NULL) {
199 return NT_STATUS_NO_MEMORY;
202 /* Special case for the guest account which must have a RID of 501 */
204 if ( strequal( pwd->pw_name, guest_account ) ) {
205 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_RID_GUEST, PDB_DEFAULT)) {
206 return NT_STATUS_NO_SUCH_USER;
208 return NT_STATUS_OK;
211 /* Non-guest accounts...Check for a workstation or user account */
213 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
214 /* workstation */
216 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
217 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
218 pwd->pw_name));
219 return NT_STATUS_INVALID_COMPUTER_NAME;
222 else {
223 /* user */
225 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
226 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
227 pwd->pw_name));
228 return NT_STATUS_INVALID_ACCOUNT_NAME;
231 /* set some basic attributes */
233 ok = pdb_set_profile_path(
234 user,
235 talloc_sub_specified(
236 user,
237 lp_logon_path(),
238 pwd->pw_name,
239 NULL,
240 domain,
241 pwd->pw_uid,
242 pwd->pw_gid),
243 PDB_DEFAULT);
244 ok &= pdb_set_homedir(
245 user,
246 talloc_sub_specified(
247 user,
248 lp_logon_home(),
249 pwd->pw_name,
250 NULL,
251 domain,
252 pwd->pw_uid,
253 pwd->pw_gid),
254 PDB_DEFAULT);
255 ok &= pdb_set_dir_drive(
256 user,
257 talloc_sub_specified(
258 user,
259 lp_logon_drive(),
260 pwd->pw_name,
261 NULL,
262 domain,
263 pwd->pw_uid,
264 pwd->pw_gid),
265 PDB_DEFAULT);
266 ok &= pdb_set_logon_script(
267 user,
268 talloc_sub_specified(
269 user,
270 lp_logon_script(),
271 pwd->pw_name,
272 NULL,
273 domain,
274 pwd->pw_uid,
275 pwd->pw_gid),
276 PDB_DEFAULT);
277 if (!ok) {
278 return NT_STATUS_NO_MEMORY;
282 /* Now deal with the user SID. If we have a backend that can generate
283 RIDs, then do so. But sometimes the caller just wanted a structure
284 initialized and will fill in these fields later (such as from a
285 netr_SamInfo3 structure) */
287 if ( create && (methods->capabilities(methods) & PDB_CAP_STORE_RIDS)) {
288 uint32_t user_rid;
289 struct dom_sid user_sid;
291 if ( !methods->new_rid(methods, &user_rid) ) {
292 DEBUG(3, ("Could not allocate a new RID\n"));
293 return NT_STATUS_ACCESS_DENIED;
296 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
298 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
299 DEBUG(3, ("pdb_set_user_sid failed\n"));
300 return NT_STATUS_INTERNAL_ERROR;
303 return NT_STATUS_OK;
306 /* generate a SID for the user with the RID algorithm */
308 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
310 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
311 return NT_STATUS_INTERNAL_ERROR;
314 return NT_STATUS_OK;
317 /********************************************************************
318 Set the Unix user attributes
319 ********************************************************************/
321 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
323 return samu_set_unix_internal( NULL, user, pwd, False );
326 NTSTATUS samu_alloc_rid_unix(struct pdb_methods *methods,
327 struct samu *user, const struct passwd *pwd)
329 return samu_set_unix_internal( methods, user, pwd, True );
332 /**********************************************************
333 Encode the account control bits into a string.
334 length = length of string to encode into (including terminating
335 null). length *MUST BE MORE THAN 2* !
336 **********************************************************/
338 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
340 fstring acct_str;
341 char *result;
343 size_t i = 0;
345 SMB_ASSERT(length <= sizeof(acct_str));
347 acct_str[i++] = '[';
349 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
350 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
351 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
352 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
353 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
354 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
355 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
356 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
357 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
358 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
359 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
361 for ( ; i < length - 2 ; i++ )
362 acct_str[i] = ' ';
364 i = length - 2;
365 acct_str[i++] = ']';
366 acct_str[i++] = '\0';
368 result = talloc_strdup(talloc_tos(), acct_str);
369 SMB_ASSERT(result != NULL);
370 return result;
373 /**********************************************************
374 Decode the account control bits from a string.
375 **********************************************************/
377 uint32_t pdb_decode_acct_ctrl(const char *p)
379 uint32_t acct_ctrl = 0;
380 bool finished = false;
383 * Check if the account type bits have been encoded after the
384 * NT password (in the form [NDHTUWSLXI]).
387 if (*p != '[')
388 return 0;
390 for (p++; *p && !finished; p++) {
391 switch (*p) {
392 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
393 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
394 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
395 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
396 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
397 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
398 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
399 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
400 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
401 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
402 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
403 case ' ': { break; }
404 case ':':
405 case '\n':
406 case '\0':
407 case ']':
408 default: { finished = true; }
412 return acct_ctrl;
415 /*************************************************************
416 Routine to set 32 hex password characters from a 16 byte array.
417 **************************************************************/
419 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
421 if (pwd != NULL) {
422 hex_encode_buf(p, pwd, 16);
423 } else {
424 if (acct_ctrl & ACB_PWNOTREQ)
425 strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
426 else
427 strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
431 /*************************************************************
432 Routine to get the 32 hex characters and turn them
433 into a 16 byte array.
434 **************************************************************/
436 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
438 int i;
439 unsigned char lonybble, hinybble;
440 const char *hexchars = "0123456789ABCDEF";
441 char *p1, *p2;
443 if (!p)
444 return false;
446 for (i = 0; i < 32; i += 2) {
447 hinybble = toupper_m(p[i]);
448 lonybble = toupper_m(p[i + 1]);
450 p1 = strchr(hexchars, hinybble);
451 p2 = strchr(hexchars, lonybble);
453 if (!p1 || !p2)
454 return false;
456 hinybble = PTR_DIFF(p1, hexchars);
457 lonybble = PTR_DIFF(p2, hexchars);
459 pwd[i / 2] = (hinybble << 4) | lonybble;
461 return true;
464 /*************************************************************
465 Routine to set 42 hex hours characters from a 21 byte array.
466 **************************************************************/
468 void pdb_sethexhours(char *p, const unsigned char *hours)
470 if (hours != NULL) {
471 hex_encode_buf(p, hours, 21);
472 } else {
473 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
477 /*************************************************************
478 Routine to get the 42 hex characters and turn them
479 into a 21 byte array.
480 **************************************************************/
482 bool pdb_gethexhours(const char *p, unsigned char *hours)
484 int i;
485 unsigned char lonybble, hinybble;
486 const char *hexchars = "0123456789ABCDEF";
487 char *p1, *p2;
489 if (!p) {
490 return (False);
493 for (i = 0; i < 42; i += 2) {
494 hinybble = toupper_m(p[i]);
495 lonybble = toupper_m(p[i + 1]);
497 p1 = strchr(hexchars, hinybble);
498 p2 = strchr(hexchars, lonybble);
500 if (!p1 || !p2) {
501 return (False);
504 hinybble = PTR_DIFF(p1, hexchars);
505 lonybble = PTR_DIFF(p2, hexchars);
507 hours[i / 2] = (hinybble << 4) | lonybble;
509 return (True);
512 /********************************************************************
513 ********************************************************************/
515 int algorithmic_rid_base(void)
517 int rid_offset;
519 rid_offset = lp_algorithmic_rid_base();
521 if (rid_offset < BASE_RID) {
522 /* Try to prevent admin foot-shooting, we can't put algorithmic
523 rids below 1000, that's the 'well known RIDs' on NT */
524 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
525 rid_offset = BASE_RID;
527 if (rid_offset & 1) {
528 DEBUG(0, ("algorithmic rid base must be even\n"));
529 rid_offset += 1;
531 return rid_offset;
534 /*******************************************************************
535 Converts NT user RID to a UNIX uid.
536 ********************************************************************/
538 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
540 int rid_offset = algorithmic_rid_base();
541 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
544 uid_t max_algorithmic_uid(void)
546 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
549 /*******************************************************************
550 converts UNIX uid to an NT User RID.
551 ********************************************************************/
553 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
555 int rid_offset = algorithmic_rid_base();
556 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
559 /*******************************************************************
560 Converts NT group RID to a UNIX gid.
561 ********************************************************************/
563 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
565 int rid_offset = algorithmic_rid_base();
566 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
569 gid_t max_algorithmic_gid(void)
571 return pdb_group_rid_to_gid(0xffffffff);
574 /*******************************************************************
575 converts NT Group RID to a UNIX uid.
577 warning: you must not call that function only
578 you must do a call to the group mapping first.
579 there is not anymore a direct link between the gid and the rid.
580 ********************************************************************/
582 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
584 int rid_offset = algorithmic_rid_base();
585 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
588 /*******************************************************************
589 Decides if a RID is a well known RID.
590 ********************************************************************/
592 static bool rid_is_well_known(uint32_t rid)
594 /* Not using rid_offset here, because this is the actual
595 NT fixed value (1000) */
597 return (rid < BASE_RID);
600 /*******************************************************************
601 Decides if a RID is a user or group RID.
602 ********************************************************************/
604 bool algorithmic_pdb_rid_is_user(uint32_t rid)
606 if ( rid_is_well_known(rid) ) {
608 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
609 * and DOMAIN_RID_GUEST.
611 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
612 return True;
613 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
614 return True;
616 return False;
619 /*******************************************************************
620 Convert a name into a SID. Used in the lookup name rpc.
621 ********************************************************************/
623 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
624 enum lsa_SidType *type)
626 GROUP_MAP *map;
627 bool ret;
629 /* Windows treats "MACHINE\None" as a special name for
630 rid 513 on non-DCs. You cannot create a user or group
631 name "None" on Windows. You will get an error that
632 the group already exists. */
634 if ( strequal( name, "None" ) ) {
635 *rid = DOMAIN_RID_USERS;
636 *type = SID_NAME_DOM_GRP;
638 return True;
641 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
642 * correctly in the case where foo also exists as a user. If the flag
643 * is set, don't look for users at all. */
645 if ((flags & LOOKUP_NAME_GROUP) == 0) {
646 struct samu *sam_account = NULL;
647 struct dom_sid user_sid;
649 if ( !(sam_account = samu_new( NULL )) ) {
650 return False;
653 become_root();
654 ret = pdb_getsampwnam(sam_account, name);
655 unbecome_root();
657 if (ret) {
658 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
661 TALLOC_FREE(sam_account);
663 if (ret) {
664 if (!sid_check_is_in_our_sam(&user_sid)) {
665 struct dom_sid_buf buf;
666 DBG_ERR("User %s with invalid SID %s"
667 " in passdb\n",
668 name,
669 dom_sid_str_buf(&user_sid, &buf));
670 return False;
673 sid_peek_rid(&user_sid, rid);
674 *type = SID_NAME_USER;
675 return True;
680 * Maybe it is a group ?
683 map = talloc_zero(NULL, GROUP_MAP);
684 if (!map) {
685 return false;
688 become_root();
689 ret = pdb_getgrnam(map, name);
690 unbecome_root();
692 if (!ret) {
693 TALLOC_FREE(map);
694 return False;
697 /* BUILTIN groups are looked up elsewhere */
698 if (!sid_check_is_in_our_sam(&map->sid)) {
699 struct dom_sid_buf buf;
700 DEBUG(10, ("Found group %s (%s) not in our domain -- "
701 "ignoring.\n",
702 name,
703 dom_sid_str_buf(&map->sid, &buf)));
704 TALLOC_FREE(map);
705 return False;
708 /* yes it's a mapped group */
709 sid_peek_rid(&map->sid, rid);
710 *type = map->sid_name_use;
711 TALLOC_FREE(map);
712 return True;
715 /*************************************************************
716 Change a password entry in the local passdb backend.
718 Assumptions:
719 - always called as root
720 - ignores the account type except when adding a new account
721 - will create/delete the unix account if the relative
722 add/delete user script is configured
724 *************************************************************/
726 NTSTATUS local_password_change(const char *user_name,
727 int local_flags,
728 const char *new_passwd,
729 char **pp_err_str,
730 char **pp_msg_str)
732 TALLOC_CTX *tosctx;
733 struct samu *sam_pass;
734 uint32_t acb;
735 uint32_t rid;
736 NTSTATUS result;
737 bool user_exists;
738 int ret = -1;
740 *pp_err_str = NULL;
741 *pp_msg_str = NULL;
743 tosctx = talloc_tos();
745 sam_pass = samu_new(tosctx);
746 if (!sam_pass) {
747 result = NT_STATUS_NO_MEMORY;
748 goto done;
751 /* Get the smb passwd entry for this user */
752 user_exists = pdb_getsampwnam(sam_pass, user_name);
754 /* Check delete first, we don't need to do anything else if we
755 * are going to delete the account */
756 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
758 result = pdb_delete_user(tosctx, sam_pass);
759 if (!NT_STATUS_IS_OK(result)) {
760 ret = asprintf(pp_err_str,
761 "Failed to delete entry for user %s.\n",
762 user_name);
763 if (ret < 0) {
764 *pp_err_str = NULL;
766 result = NT_STATUS_UNSUCCESSFUL;
767 } else {
768 ret = asprintf(pp_msg_str,
769 "Deleted user %s.\n",
770 user_name);
771 if (ret < 0) {
772 *pp_msg_str = NULL;
775 goto done;
778 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
779 /* the entry already existed */
780 local_flags &= ~LOCAL_ADD_USER;
783 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
784 ret = asprintf(pp_err_str,
785 "Failed to find entry for user %s.\n",
786 user_name);
787 if (ret < 0) {
788 *pp_err_str = NULL;
790 result = NT_STATUS_NO_SUCH_USER;
791 goto done;
794 /* First thing add the new user if we are required to do so */
795 if (local_flags & LOCAL_ADD_USER) {
797 if (local_flags & LOCAL_TRUST_ACCOUNT) {
798 acb = ACB_WSTRUST;
799 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
800 acb = ACB_DOMTRUST;
801 } else {
802 acb = ACB_NORMAL;
805 result = pdb_create_user(tosctx, user_name, acb, &rid);
806 if (!NT_STATUS_IS_OK(result)) {
807 ret = asprintf(pp_err_str,
808 "Failed to add entry for user %s.\n",
809 user_name);
810 if (ret < 0) {
811 *pp_err_str = NULL;
813 result = NT_STATUS_UNSUCCESSFUL;
814 goto done;
817 sam_pass = samu_new(tosctx);
818 if (!sam_pass) {
819 result = NT_STATUS_NO_MEMORY;
820 goto done;
823 /* Now get back the smb passwd entry for this new user */
824 user_exists = pdb_getsampwnam(sam_pass, user_name);
825 if (!user_exists) {
826 ret = asprintf(pp_err_str,
827 "Failed to add entry for user %s.\n",
828 user_name);
829 if (ret < 0) {
830 *pp_err_str = NULL;
832 result = NT_STATUS_UNSUCCESSFUL;
833 goto done;
837 acb = pdb_get_acct_ctrl(sam_pass);
840 * We are root - just write the new password
841 * and the valid last change time.
843 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
844 acb |= ACB_PWNOTREQ;
845 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
846 ret = asprintf(pp_err_str,
847 "Failed to set 'no password required' "
848 "flag for user %s.\n", user_name);
849 if (ret < 0) {
850 *pp_err_str = NULL;
852 result = NT_STATUS_UNSUCCESSFUL;
853 goto done;
857 if (local_flags & LOCAL_SET_PASSWORD) {
859 * If we're dealing with setting a completely empty user account
860 * ie. One with a password of 'XXXX', but not set disabled (like
861 * an account created from scratch) then if the old password was
862 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
863 * We remove that as we're giving this user their first password
864 * and the decision hasn't really been made to disable them (ie.
865 * don't create them disabled). JRA.
867 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
868 (acb & ACB_DISABLED)) {
869 acb &= (~ACB_DISABLED);
870 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
871 ret = asprintf(pp_err_str,
872 "Failed to unset 'disabled' "
873 "flag for user %s.\n",
874 user_name);
875 if (ret < 0) {
876 *pp_err_str = NULL;
878 result = NT_STATUS_UNSUCCESSFUL;
879 goto done;
883 acb &= (~ACB_PWNOTREQ);
884 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
885 ret = asprintf(pp_err_str,
886 "Failed to unset 'no password required'"
887 " flag for user %s.\n", user_name);
888 if (ret < 0) {
889 *pp_err_str = NULL;
891 result = NT_STATUS_UNSUCCESSFUL;
892 goto done;
895 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
896 ret = asprintf(pp_err_str,
897 "Failed to set password for "
898 "user %s.\n", user_name);
899 if (ret < 0) {
900 *pp_err_str = NULL;
902 result = NT_STATUS_UNSUCCESSFUL;
903 goto done;
907 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
908 acb |= ACB_DISABLED;
909 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
910 ret = asprintf(pp_err_str,
911 "Failed to set 'disabled' flag for "
912 "user %s.\n", user_name);
913 if (ret < 0) {
914 *pp_err_str = NULL;
916 result = NT_STATUS_UNSUCCESSFUL;
917 goto done;
921 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
922 acb &= (~ACB_DISABLED);
923 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
924 ret = asprintf(pp_err_str,
925 "Failed to unset 'disabled' flag for "
926 "user %s.\n", user_name);
927 if (ret < 0) {
928 *pp_err_str = NULL;
930 result = NT_STATUS_UNSUCCESSFUL;
931 goto done;
935 /* now commit changes if any */
936 result = pdb_update_sam_account(sam_pass);
937 if (!NT_STATUS_IS_OK(result)) {
938 ret = asprintf(pp_err_str,
939 "Failed to modify entry for user %s.\n",
940 user_name);
941 if (ret < 0) {
942 *pp_err_str = NULL;
944 goto done;
947 if (local_flags & LOCAL_ADD_USER) {
948 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
949 } else if (local_flags & LOCAL_DISABLE_USER) {
950 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
951 } else if (local_flags & LOCAL_ENABLE_USER) {
952 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
953 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
954 ret = asprintf(pp_msg_str,
955 "User %s password set to none.\n", user_name);
958 if (ret < 0) {
959 *pp_msg_str = NULL;
962 result = NT_STATUS_OK;
964 done:
965 TALLOC_FREE(sam_pass);
966 return result;
969 /**********************************************************************
970 Marshall/unmarshall struct samu structs.
971 *********************************************************************/
973 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
974 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
975 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
976 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
977 /* nothing changed between V3 and V4 */
979 /*********************************************************************
980 *********************************************************************/
982 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
985 /* times are stored as 32bit integer
986 take care on system with 64bit wide time_t
987 --SSS */
988 uint32_t logon_time,
989 logoff_time,
990 kickoff_time,
991 pass_last_set_time,
992 pass_can_change_time,
993 pass_must_change_time;
994 char *username = NULL;
995 char *domain = NULL;
996 char *nt_username = NULL;
997 char *dir_drive = NULL;
998 char *unknown_str = NULL;
999 char *munged_dial = NULL;
1000 char *fullname = NULL;
1001 char *homedir = NULL;
1002 char *logon_script = NULL;
1003 char *profile_path = NULL;
1004 char *acct_desc = NULL;
1005 char *workstations = NULL;
1006 uint32_t username_len, domain_len, nt_username_len,
1007 dir_drive_len, unknown_str_len, munged_dial_len,
1008 fullname_len, homedir_len, logon_script_len,
1009 profile_path_len, acct_desc_len, workstations_len;
1011 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1012 uint16_t acct_ctrl, logon_divs;
1013 uint16_t bad_password_count, logon_count;
1014 uint8_t *hours = NULL;
1015 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1016 uint32_t len = 0;
1017 uint32_t lm_pw_len, nt_pw_len, hourslen;
1018 bool ret = True;
1020 if(sampass == NULL || buf == NULL) {
1021 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
1022 return False;
1025 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1027 /* unpack the buffer into variables */
1028 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
1029 &logon_time, /* d */
1030 &logoff_time, /* d */
1031 &kickoff_time, /* d */
1032 &pass_last_set_time, /* d */
1033 &pass_can_change_time, /* d */
1034 &pass_must_change_time, /* d */
1035 &username_len, &username, /* B */
1036 &domain_len, &domain, /* B */
1037 &nt_username_len, &nt_username, /* B */
1038 &fullname_len, &fullname, /* B */
1039 &homedir_len, &homedir, /* B */
1040 &dir_drive_len, &dir_drive, /* B */
1041 &logon_script_len, &logon_script, /* B */
1042 &profile_path_len, &profile_path, /* B */
1043 &acct_desc_len, &acct_desc, /* B */
1044 &workstations_len, &workstations, /* B */
1045 &unknown_str_len, &unknown_str, /* B */
1046 &munged_dial_len, &munged_dial, /* B */
1047 &user_rid, /* d */
1048 &group_rid, /* d */
1049 &lm_pw_len, &lm_pw_ptr, /* B */
1050 &nt_pw_len, &nt_pw_ptr, /* B */
1051 &acct_ctrl, /* w */
1052 &remove_me, /* remove on the next TDB_FORMAT upgrade */ /* d */
1053 &logon_divs, /* w */
1054 &hours_len, /* d */
1055 &hourslen, &hours, /* B */
1056 &bad_password_count, /* w */
1057 &logon_count, /* w */
1058 &unknown_6); /* d */
1060 if (len == (uint32_t) -1) {
1061 ret = False;
1062 goto done;
1065 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1066 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1067 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1068 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1069 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1071 pdb_set_username(sampass, username, PDB_SET);
1072 pdb_set_domain(sampass, domain, PDB_SET);
1073 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1074 pdb_set_fullname(sampass, fullname, PDB_SET);
1076 if (homedir) {
1077 pdb_set_homedir(sampass, homedir, PDB_SET);
1079 else {
1080 pdb_set_homedir(sampass,
1081 talloc_sub_basic(sampass, username, domain,
1082 lp_logon_home()),
1083 PDB_DEFAULT);
1086 if (dir_drive)
1087 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1088 else {
1089 pdb_set_dir_drive(sampass,
1090 talloc_sub_basic(sampass, username, domain,
1091 lp_logon_drive()),
1092 PDB_DEFAULT);
1095 if (logon_script)
1096 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1097 else {
1098 pdb_set_logon_script(sampass,
1099 talloc_sub_basic(sampass, username, domain,
1100 lp_logon_script()),
1101 PDB_DEFAULT);
1104 if (profile_path) {
1105 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1106 } else {
1107 pdb_set_profile_path(sampass,
1108 talloc_sub_basic(sampass, username, domain,
1109 lp_logon_path()),
1110 PDB_DEFAULT);
1113 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1114 pdb_set_workstations(sampass, workstations, PDB_SET);
1115 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1117 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1118 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1119 ret = False;
1120 goto done;
1124 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1125 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1126 ret = False;
1127 goto done;
1131 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1132 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1133 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1134 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1135 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1136 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1137 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1138 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1139 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1140 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1142 done:
1144 SAFE_FREE(username);
1145 SAFE_FREE(domain);
1146 SAFE_FREE(nt_username);
1147 SAFE_FREE(fullname);
1148 SAFE_FREE(homedir);
1149 SAFE_FREE(dir_drive);
1150 SAFE_FREE(logon_script);
1151 SAFE_FREE(profile_path);
1152 SAFE_FREE(acct_desc);
1153 SAFE_FREE(workstations);
1154 SAFE_FREE(munged_dial);
1155 SAFE_FREE(unknown_str);
1156 SAFE_FREE(lm_pw_ptr);
1157 SAFE_FREE(nt_pw_ptr);
1158 SAFE_FREE(hours);
1160 return ret;
1163 /*********************************************************************
1164 *********************************************************************/
1166 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1169 /* times are stored as 32bit integer
1170 take care on system with 64bit wide time_t
1171 --SSS */
1172 uint32_t logon_time,
1173 logoff_time,
1174 kickoff_time,
1175 bad_password_time,
1176 pass_last_set_time,
1177 pass_can_change_time,
1178 pass_must_change_time;
1179 char *username = NULL;
1180 char *domain = NULL;
1181 char *nt_username = NULL;
1182 char *dir_drive = NULL;
1183 char *unknown_str = NULL;
1184 char *munged_dial = NULL;
1185 char *fullname = NULL;
1186 char *homedir = NULL;
1187 char *logon_script = NULL;
1188 char *profile_path = NULL;
1189 char *acct_desc = NULL;
1190 char *workstations = NULL;
1191 uint32_t username_len, domain_len, nt_username_len,
1192 dir_drive_len, unknown_str_len, munged_dial_len,
1193 fullname_len, homedir_len, logon_script_len,
1194 profile_path_len, acct_desc_len, workstations_len;
1196 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1197 uint16_t acct_ctrl, logon_divs;
1198 uint16_t bad_password_count, logon_count;
1199 uint8_t *hours = NULL;
1200 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1201 uint32_t len = 0;
1202 uint32_t lm_pw_len, nt_pw_len, hourslen;
1203 bool ret = True;
1205 if(sampass == NULL || buf == NULL) {
1206 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1207 return False;
1210 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1212 /* unpack the buffer into variables */
1213 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1214 &logon_time, /* d */
1215 &logoff_time, /* d */
1216 &kickoff_time, /* d */
1217 /* Change from V0 is addition of bad_password_time field. */
1218 &bad_password_time, /* d */
1219 &pass_last_set_time, /* d */
1220 &pass_can_change_time, /* d */
1221 &pass_must_change_time, /* d */
1222 &username_len, &username, /* B */
1223 &domain_len, &domain, /* B */
1224 &nt_username_len, &nt_username, /* B */
1225 &fullname_len, &fullname, /* B */
1226 &homedir_len, &homedir, /* B */
1227 &dir_drive_len, &dir_drive, /* B */
1228 &logon_script_len, &logon_script, /* B */
1229 &profile_path_len, &profile_path, /* B */
1230 &acct_desc_len, &acct_desc, /* B */
1231 &workstations_len, &workstations, /* B */
1232 &unknown_str_len, &unknown_str, /* B */
1233 &munged_dial_len, &munged_dial, /* B */
1234 &user_rid, /* d */
1235 &group_rid, /* d */
1236 &lm_pw_len, &lm_pw_ptr, /* B */
1237 &nt_pw_len, &nt_pw_ptr, /* B */
1238 &acct_ctrl, /* w */
1239 &remove_me, /* d */
1240 &logon_divs, /* w */
1241 &hours_len, /* d */
1242 &hourslen, &hours, /* B */
1243 &bad_password_count, /* w */
1244 &logon_count, /* w */
1245 &unknown_6); /* d */
1247 if (len == (uint32_t) -1) {
1248 ret = False;
1249 goto done;
1252 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1253 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1254 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1256 /* Change from V0 is addition of bad_password_time field. */
1257 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1258 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1259 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1261 pdb_set_username(sampass, username, PDB_SET);
1262 pdb_set_domain(sampass, domain, PDB_SET);
1263 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1264 pdb_set_fullname(sampass, fullname, PDB_SET);
1266 if (homedir) {
1267 pdb_set_homedir(sampass, homedir, PDB_SET);
1269 else {
1270 pdb_set_homedir(sampass,
1271 talloc_sub_basic(sampass, username, domain,
1272 lp_logon_home()),
1273 PDB_DEFAULT);
1276 if (dir_drive)
1277 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1278 else {
1279 pdb_set_dir_drive(sampass,
1280 talloc_sub_basic(sampass, username, domain,
1281 lp_logon_drive()),
1282 PDB_DEFAULT);
1285 if (logon_script)
1286 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1287 else {
1288 pdb_set_logon_script(sampass,
1289 talloc_sub_basic(sampass, username, domain,
1290 lp_logon_script()),
1291 PDB_DEFAULT);
1294 if (profile_path) {
1295 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1296 } else {
1297 pdb_set_profile_path(sampass,
1298 talloc_sub_basic(sampass, username, domain,
1299 lp_logon_path()),
1300 PDB_DEFAULT);
1303 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1304 pdb_set_workstations(sampass, workstations, PDB_SET);
1305 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1307 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1308 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1309 ret = False;
1310 goto done;
1314 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1315 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1316 ret = False;
1317 goto done;
1321 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1323 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1324 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1325 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1326 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1327 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1328 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1329 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1330 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1331 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1333 done:
1335 SAFE_FREE(username);
1336 SAFE_FREE(domain);
1337 SAFE_FREE(nt_username);
1338 SAFE_FREE(fullname);
1339 SAFE_FREE(homedir);
1340 SAFE_FREE(dir_drive);
1341 SAFE_FREE(logon_script);
1342 SAFE_FREE(profile_path);
1343 SAFE_FREE(acct_desc);
1344 SAFE_FREE(workstations);
1345 SAFE_FREE(munged_dial);
1346 SAFE_FREE(unknown_str);
1347 SAFE_FREE(lm_pw_ptr);
1348 SAFE_FREE(nt_pw_ptr);
1349 SAFE_FREE(hours);
1351 return ret;
1354 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1357 /* times are stored as 32bit integer
1358 take care on system with 64bit wide time_t
1359 --SSS */
1360 uint32_t logon_time,
1361 logoff_time,
1362 kickoff_time,
1363 bad_password_time,
1364 pass_last_set_time,
1365 pass_can_change_time,
1366 pass_must_change_time;
1367 char *username = NULL;
1368 char *domain = NULL;
1369 char *nt_username = NULL;
1370 char *dir_drive = NULL;
1371 char *unknown_str = NULL;
1372 char *munged_dial = NULL;
1373 char *fullname = NULL;
1374 char *homedir = NULL;
1375 char *logon_script = NULL;
1376 char *profile_path = NULL;
1377 char *acct_desc = NULL;
1378 char *workstations = NULL;
1379 uint32_t username_len, domain_len, nt_username_len,
1380 dir_drive_len, unknown_str_len, munged_dial_len,
1381 fullname_len, homedir_len, logon_script_len,
1382 profile_path_len, acct_desc_len, workstations_len;
1384 uint32_t user_rid, group_rid, hours_len, unknown_6;
1385 uint16_t acct_ctrl, logon_divs;
1386 uint16_t bad_password_count, logon_count;
1387 uint8_t *hours = NULL;
1388 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1389 uint32_t len = 0;
1390 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1391 uint32_t pwHistLen = 0;
1392 bool ret = True;
1393 fstring tmp_string;
1394 bool expand_explicit = lp_passdb_expand_explicit();
1396 if(sampass == NULL || buf == NULL) {
1397 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1398 return False;
1401 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1403 /* unpack the buffer into variables */
1404 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1405 &logon_time, /* d */
1406 &logoff_time, /* d */
1407 &kickoff_time, /* d */
1408 &bad_password_time, /* d */
1409 &pass_last_set_time, /* d */
1410 &pass_can_change_time, /* d */
1411 &pass_must_change_time, /* d */
1412 &username_len, &username, /* B */
1413 &domain_len, &domain, /* B */
1414 &nt_username_len, &nt_username, /* B */
1415 &fullname_len, &fullname, /* B */
1416 &homedir_len, &homedir, /* B */
1417 &dir_drive_len, &dir_drive, /* B */
1418 &logon_script_len, &logon_script, /* B */
1419 &profile_path_len, &profile_path, /* B */
1420 &acct_desc_len, &acct_desc, /* B */
1421 &workstations_len, &workstations, /* B */
1422 &unknown_str_len, &unknown_str, /* B */
1423 &munged_dial_len, &munged_dial, /* B */
1424 &user_rid, /* d */
1425 &group_rid, /* d */
1426 &lm_pw_len, &lm_pw_ptr, /* B */
1427 &nt_pw_len, &nt_pw_ptr, /* B */
1428 /* Change from V1 is addition of password history field. */
1429 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1430 &acct_ctrl, /* w */
1431 /* Also "remove_me" field was removed. */
1432 &logon_divs, /* w */
1433 &hours_len, /* d */
1434 &hourslen, &hours, /* B */
1435 &bad_password_count, /* w */
1436 &logon_count, /* w */
1437 &unknown_6); /* d */
1439 if (len == (uint32_t) -1) {
1440 ret = False;
1441 goto done;
1444 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1445 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1446 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1447 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1448 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1449 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1451 pdb_set_username(sampass, username, PDB_SET);
1452 pdb_set_domain(sampass, domain, PDB_SET);
1453 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1454 pdb_set_fullname(sampass, fullname, PDB_SET);
1456 if (homedir) {
1457 fstrcpy( tmp_string, homedir );
1458 if (expand_explicit) {
1459 standard_sub_basic( username, domain, tmp_string,
1460 sizeof(tmp_string) );
1462 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1464 else {
1465 pdb_set_homedir(sampass,
1466 talloc_sub_basic(sampass, username, domain,
1467 lp_logon_home()),
1468 PDB_DEFAULT);
1471 if (dir_drive)
1472 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1473 else
1474 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1476 if (logon_script) {
1477 fstrcpy( tmp_string, logon_script );
1478 if (expand_explicit) {
1479 standard_sub_basic( username, domain, tmp_string,
1480 sizeof(tmp_string) );
1482 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1484 else {
1485 pdb_set_logon_script(sampass,
1486 talloc_sub_basic(sampass, username, domain,
1487 lp_logon_script()),
1488 PDB_DEFAULT);
1491 if (profile_path) {
1492 fstrcpy( tmp_string, profile_path );
1493 if (expand_explicit) {
1494 standard_sub_basic( username, domain, tmp_string,
1495 sizeof(tmp_string) );
1497 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1499 else {
1500 pdb_set_profile_path(sampass,
1501 talloc_sub_basic(sampass, username, domain,
1502 lp_logon_path()),
1503 PDB_DEFAULT);
1506 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1507 pdb_set_workstations(sampass, workstations, PDB_SET);
1508 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1510 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1511 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1512 ret = False;
1513 goto done;
1517 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1518 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1519 ret = False;
1520 goto done;
1524 /* Change from V1 is addition of password history field. */
1525 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1526 if (pwHistLen) {
1527 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1528 if (!pw_hist) {
1529 ret = False;
1530 goto done;
1532 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1533 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1534 int i;
1535 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1536 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1537 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1538 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1539 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1540 PW_HISTORY_ENTRY_LEN);
1543 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1544 SAFE_FREE(pw_hist);
1545 ret = False;
1546 goto done;
1548 SAFE_FREE(pw_hist);
1549 } else {
1550 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1553 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1554 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1555 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1556 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1557 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1558 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1559 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1560 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1561 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1563 done:
1565 SAFE_FREE(username);
1566 SAFE_FREE(domain);
1567 SAFE_FREE(nt_username);
1568 SAFE_FREE(fullname);
1569 SAFE_FREE(homedir);
1570 SAFE_FREE(dir_drive);
1571 SAFE_FREE(logon_script);
1572 SAFE_FREE(profile_path);
1573 SAFE_FREE(acct_desc);
1574 SAFE_FREE(workstations);
1575 SAFE_FREE(munged_dial);
1576 SAFE_FREE(unknown_str);
1577 SAFE_FREE(lm_pw_ptr);
1578 SAFE_FREE(nt_pw_ptr);
1579 SAFE_FREE(nt_pw_hist_ptr);
1580 SAFE_FREE(hours);
1582 return ret;
1585 /*********************************************************************
1586 *********************************************************************/
1588 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1591 /* times are stored as 32bit integer
1592 take care on system with 64bit wide time_t
1593 --SSS */
1594 uint32_t logon_time,
1595 logoff_time,
1596 kickoff_time,
1597 bad_password_time,
1598 pass_last_set_time,
1599 pass_can_change_time,
1600 pass_must_change_time;
1601 char *username = NULL;
1602 char *domain = NULL;
1603 char *nt_username = NULL;
1604 char *dir_drive = NULL;
1605 char *comment = NULL;
1606 char *munged_dial = NULL;
1607 char *fullname = NULL;
1608 char *homedir = NULL;
1609 char *logon_script = NULL;
1610 char *profile_path = NULL;
1611 char *acct_desc = NULL;
1612 char *workstations = NULL;
1613 uint32_t username_len, domain_len, nt_username_len,
1614 dir_drive_len, comment_len, munged_dial_len,
1615 fullname_len, homedir_len, logon_script_len,
1616 profile_path_len, acct_desc_len, workstations_len;
1618 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1619 uint16_t logon_divs;
1620 uint16_t bad_password_count, logon_count;
1621 uint8_t *hours = NULL;
1622 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1623 uint32_t len = 0;
1624 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1625 uint32_t pwHistLen = 0;
1626 bool ret = True;
1627 fstring tmp_string;
1628 bool expand_explicit = lp_passdb_expand_explicit();
1630 if(sampass == NULL || buf == NULL) {
1631 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1632 return False;
1635 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1637 /* unpack the buffer into variables */
1638 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1639 &logon_time, /* d */
1640 &logoff_time, /* d */
1641 &kickoff_time, /* d */
1642 &bad_password_time, /* d */
1643 &pass_last_set_time, /* d */
1644 &pass_can_change_time, /* d */
1645 &pass_must_change_time, /* d */
1646 &username_len, &username, /* B */
1647 &domain_len, &domain, /* B */
1648 &nt_username_len, &nt_username, /* B */
1649 &fullname_len, &fullname, /* B */
1650 &homedir_len, &homedir, /* B */
1651 &dir_drive_len, &dir_drive, /* B */
1652 &logon_script_len, &logon_script, /* B */
1653 &profile_path_len, &profile_path, /* B */
1654 &acct_desc_len, &acct_desc, /* B */
1655 &workstations_len, &workstations, /* B */
1656 &comment_len, &comment, /* B */
1657 &munged_dial_len, &munged_dial, /* B */
1658 &user_rid, /* d */
1659 &group_rid, /* d */
1660 &lm_pw_len, &lm_pw_ptr, /* B */
1661 &nt_pw_len, &nt_pw_ptr, /* B */
1662 /* Change from V1 is addition of password history field. */
1663 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1664 /* Change from V2 is the uint32_t acb_mask */
1665 &acct_ctrl, /* d */
1666 /* Also "remove_me" field was removed. */
1667 &logon_divs, /* w */
1668 &hours_len, /* d */
1669 &hourslen, &hours, /* B */
1670 &bad_password_count, /* w */
1671 &logon_count, /* w */
1672 &unknown_6); /* d */
1674 if (len == (uint32_t) -1) {
1675 ret = False;
1676 goto done;
1679 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1680 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1681 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1682 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1683 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1684 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1686 pdb_set_username(sampass, username, PDB_SET);
1687 pdb_set_domain(sampass, domain, PDB_SET);
1688 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1689 pdb_set_fullname(sampass, fullname, PDB_SET);
1691 if (homedir) {
1692 fstrcpy( tmp_string, homedir );
1693 if (expand_explicit) {
1694 standard_sub_basic( username, domain, tmp_string,
1695 sizeof(tmp_string) );
1697 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1699 else {
1700 pdb_set_homedir(sampass,
1701 talloc_sub_basic(sampass, username, domain,
1702 lp_logon_home()),
1703 PDB_DEFAULT);
1706 if (dir_drive)
1707 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1708 else
1709 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1711 if (logon_script) {
1712 fstrcpy( tmp_string, logon_script );
1713 if (expand_explicit) {
1714 standard_sub_basic( username, domain, tmp_string,
1715 sizeof(tmp_string) );
1717 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1719 else {
1720 pdb_set_logon_script(sampass,
1721 talloc_sub_basic(sampass, username, domain,
1722 lp_logon_script()),
1723 PDB_DEFAULT);
1726 if (profile_path) {
1727 fstrcpy( tmp_string, profile_path );
1728 if (expand_explicit) {
1729 standard_sub_basic( username, domain, tmp_string,
1730 sizeof(tmp_string) );
1732 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1734 else {
1735 pdb_set_profile_path(sampass,
1736 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1737 PDB_DEFAULT);
1740 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1741 pdb_set_comment(sampass, comment, PDB_SET);
1742 pdb_set_workstations(sampass, workstations, PDB_SET);
1743 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1745 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1746 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1747 ret = False;
1748 goto done;
1752 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1753 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1754 ret = False;
1755 goto done;
1759 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1760 if (pwHistLen) {
1761 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1762 if (!pw_hist) {
1763 ret = False;
1764 goto done;
1766 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1767 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1768 int i;
1769 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1770 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1771 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1772 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1773 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1774 PW_HISTORY_ENTRY_LEN);
1777 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1778 SAFE_FREE(pw_hist);
1779 ret = False;
1780 goto done;
1782 SAFE_FREE(pw_hist);
1783 } else {
1784 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1787 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1788 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1789 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1790 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1791 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1792 /* Change from V2 is the uint32_t acct_ctrl */
1793 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1794 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1795 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1797 done:
1799 SAFE_FREE(username);
1800 SAFE_FREE(domain);
1801 SAFE_FREE(nt_username);
1802 SAFE_FREE(fullname);
1803 SAFE_FREE(homedir);
1804 SAFE_FREE(dir_drive);
1805 SAFE_FREE(logon_script);
1806 SAFE_FREE(profile_path);
1807 SAFE_FREE(acct_desc);
1808 SAFE_FREE(workstations);
1809 SAFE_FREE(munged_dial);
1810 SAFE_FREE(comment);
1811 SAFE_FREE(lm_pw_ptr);
1812 SAFE_FREE(nt_pw_ptr);
1813 SAFE_FREE(nt_pw_hist_ptr);
1814 SAFE_FREE(hours);
1816 return ret;
1819 /*********************************************************************
1820 *********************************************************************/
1822 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1824 size_t len, buflen;
1826 /* times are stored as 32bit integer
1827 take care on system with 64bit wide time_t
1828 --SSS */
1829 uint32_t logon_time,
1830 logoff_time,
1831 kickoff_time,
1832 bad_password_time,
1833 pass_last_set_time,
1834 pass_can_change_time,
1835 pass_must_change_time;
1837 uint32_t user_rid, group_rid;
1839 const char *username;
1840 const char *domain;
1841 const char *nt_username;
1842 const char *dir_drive;
1843 const char *comment;
1844 const char *munged_dial;
1845 const char *fullname;
1846 const char *homedir;
1847 const char *logon_script;
1848 const char *profile_path;
1849 const char *acct_desc;
1850 const char *workstations;
1851 uint32_t username_len, domain_len, nt_username_len,
1852 dir_drive_len, comment_len, munged_dial_len,
1853 fullname_len, homedir_len, logon_script_len,
1854 profile_path_len, acct_desc_len, workstations_len;
1856 const uint8_t *lm_pw;
1857 const uint8_t *nt_pw;
1858 const uint8_t *nt_pw_hist;
1859 uint32_t lm_pw_len = 16;
1860 uint32_t nt_pw_len = 16;
1861 uint32_t nt_pw_hist_len;
1862 uint32_t pwHistLen = 0;
1864 *buf = NULL;
1865 buflen = 0;
1867 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1868 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1869 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1870 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1871 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1872 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1873 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1875 user_rid = pdb_get_user_rid(sampass);
1876 group_rid = pdb_get_group_rid(sampass);
1878 username = pdb_get_username(sampass);
1879 if (username) {
1880 username_len = strlen(username) +1;
1881 } else {
1882 username_len = 0;
1885 domain = pdb_get_domain(sampass);
1886 if (domain) {
1887 domain_len = strlen(domain) +1;
1888 } else {
1889 domain_len = 0;
1892 nt_username = pdb_get_nt_username(sampass);
1893 if (nt_username) {
1894 nt_username_len = strlen(nt_username) +1;
1895 } else {
1896 nt_username_len = 0;
1899 fullname = pdb_get_fullname(sampass);
1900 if (fullname) {
1901 fullname_len = strlen(fullname) +1;
1902 } else {
1903 fullname_len = 0;
1907 * Only updates fields which have been set (not defaults from smb.conf)
1910 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1911 dir_drive = pdb_get_dir_drive(sampass);
1912 } else {
1913 dir_drive = NULL;
1915 if (dir_drive) {
1916 dir_drive_len = strlen(dir_drive) +1;
1917 } else {
1918 dir_drive_len = 0;
1921 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1922 homedir = pdb_get_homedir(sampass);
1923 } else {
1924 homedir = NULL;
1926 if (homedir) {
1927 homedir_len = strlen(homedir) +1;
1928 } else {
1929 homedir_len = 0;
1932 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1933 logon_script = pdb_get_logon_script(sampass);
1934 } else {
1935 logon_script = NULL;
1937 if (logon_script) {
1938 logon_script_len = strlen(logon_script) +1;
1939 } else {
1940 logon_script_len = 0;
1943 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1944 profile_path = pdb_get_profile_path(sampass);
1945 } else {
1946 profile_path = NULL;
1948 if (profile_path) {
1949 profile_path_len = strlen(profile_path) +1;
1950 } else {
1951 profile_path_len = 0;
1954 lm_pw = pdb_get_lanman_passwd(sampass);
1955 if (!lm_pw) {
1956 lm_pw_len = 0;
1959 nt_pw = pdb_get_nt_passwd(sampass);
1960 if (!nt_pw) {
1961 nt_pw_len = 0;
1964 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1965 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1966 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1967 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1968 } else {
1969 nt_pw_hist_len = 0;
1972 acct_desc = pdb_get_acct_desc(sampass);
1973 if (acct_desc) {
1974 acct_desc_len = strlen(acct_desc) +1;
1975 } else {
1976 acct_desc_len = 0;
1979 workstations = pdb_get_workstations(sampass);
1980 if (workstations) {
1981 workstations_len = strlen(workstations) +1;
1982 } else {
1983 workstations_len = 0;
1986 comment = pdb_get_comment(sampass);
1987 if (comment) {
1988 comment_len = strlen(comment) +1;
1989 } else {
1990 comment_len = 0;
1993 munged_dial = pdb_get_munged_dial(sampass);
1994 if (munged_dial) {
1995 munged_dial_len = strlen(munged_dial) +1;
1996 } else {
1997 munged_dial_len = 0;
2000 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
2002 /* one time to get the size needed */
2003 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
2004 logon_time, /* d */
2005 logoff_time, /* d */
2006 kickoff_time, /* d */
2007 bad_password_time, /* d */
2008 pass_last_set_time, /* d */
2009 pass_can_change_time, /* d */
2010 pass_must_change_time, /* d */
2011 username_len, username, /* B */
2012 domain_len, domain, /* B */
2013 nt_username_len, nt_username, /* B */
2014 fullname_len, fullname, /* B */
2015 homedir_len, homedir, /* B */
2016 dir_drive_len, dir_drive, /* B */
2017 logon_script_len, logon_script, /* B */
2018 profile_path_len, profile_path, /* B */
2019 acct_desc_len, acct_desc, /* B */
2020 workstations_len, workstations, /* B */
2021 comment_len, comment, /* B */
2022 munged_dial_len, munged_dial, /* B */
2023 user_rid, /* d */
2024 group_rid, /* d */
2025 lm_pw_len, lm_pw, /* B */
2026 nt_pw_len, nt_pw, /* B */
2027 nt_pw_hist_len, nt_pw_hist, /* B */
2028 pdb_get_acct_ctrl(sampass), /* d */
2029 pdb_get_logon_divs(sampass), /* w */
2030 pdb_get_hours_len(sampass), /* d */
2031 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2032 pdb_get_bad_password_count(sampass), /* w */
2033 pdb_get_logon_count(sampass), /* w */
2034 pdb_get_unknown_6(sampass)); /* d */
2036 if (size_only) {
2037 return buflen;
2040 /* malloc the space needed */
2041 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
2042 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
2043 return (-1);
2046 /* now for the real call to tdb_pack() */
2047 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2048 logon_time, /* d */
2049 logoff_time, /* d */
2050 kickoff_time, /* d */
2051 bad_password_time, /* d */
2052 pass_last_set_time, /* d */
2053 pass_can_change_time, /* d */
2054 pass_must_change_time, /* d */
2055 username_len, username, /* B */
2056 domain_len, domain, /* B */
2057 nt_username_len, nt_username, /* B */
2058 fullname_len, fullname, /* B */
2059 homedir_len, homedir, /* B */
2060 dir_drive_len, dir_drive, /* B */
2061 logon_script_len, logon_script, /* B */
2062 profile_path_len, profile_path, /* B */
2063 acct_desc_len, acct_desc, /* B */
2064 workstations_len, workstations, /* B */
2065 comment_len, comment, /* B */
2066 munged_dial_len, munged_dial, /* B */
2067 user_rid, /* d */
2068 group_rid, /* d */
2069 lm_pw_len, lm_pw, /* B */
2070 nt_pw_len, nt_pw, /* B */
2071 nt_pw_hist_len, nt_pw_hist, /* B */
2072 pdb_get_acct_ctrl(sampass), /* d */
2073 pdb_get_logon_divs(sampass), /* w */
2074 pdb_get_hours_len(sampass), /* d */
2075 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2076 pdb_get_bad_password_count(sampass), /* w */
2077 pdb_get_logon_count(sampass), /* w */
2078 pdb_get_unknown_6(sampass)); /* d */
2080 /* check to make sure we got it correct */
2081 if (buflen != len) {
2082 DEBUG(0, ("init_buffer_from_samu_v3: something odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2083 (unsigned long)buflen, (unsigned long)len));
2084 /* error */
2085 SAFE_FREE (*buf);
2086 return (-1);
2089 return (buflen);
2092 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2094 /* nothing changed between V3 and V4 */
2095 return init_samu_from_buffer_v3(sampass, buf, buflen);
2098 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2100 /* nothing changed between V3 and V4 */
2101 return init_buffer_from_samu_v3(buf, sampass, size_only);
2104 /**********************************************************************
2105 Initialize a struct samu struct from a BYTE buffer of size len
2106 *********************************************************************/
2108 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2109 uint8_t *buf, uint32_t buflen)
2111 switch (level) {
2112 case SAMU_BUFFER_V0:
2113 return init_samu_from_buffer_v0(sampass, buf, buflen);
2114 case SAMU_BUFFER_V1:
2115 return init_samu_from_buffer_v1(sampass, buf, buflen);
2116 case SAMU_BUFFER_V2:
2117 return init_samu_from_buffer_v2(sampass, buf, buflen);
2118 case SAMU_BUFFER_V3:
2119 return init_samu_from_buffer_v3(sampass, buf, buflen);
2120 case SAMU_BUFFER_V4:
2121 return init_samu_from_buffer_v4(sampass, buf, buflen);
2124 return false;
2127 /**********************************************************************
2128 Initialize a BYTE buffer from a struct samu struct
2129 *********************************************************************/
2131 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2133 return init_buffer_from_samu_v4(buf, sampass, size_only);
2136 /*********************************************************************
2137 *********************************************************************/
2139 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2141 uint8_t *buf = NULL;
2142 int len;
2144 len = init_buffer_from_samu(&buf, src, False);
2145 if (len == -1 || !buf) {
2146 SAFE_FREE(buf);
2147 return False;
2150 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2151 free(buf);
2152 return False;
2155 dst->methods = src->methods;
2157 if ( src->unix_pw ) {
2158 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2159 if (!dst->unix_pw) {
2160 free(buf);
2161 return False;
2165 if (src->group_sid) {
2166 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2169 free(buf);
2170 return True;
2173 /*********************************************************************
2174 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2175 *********************************************************************/
2177 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2179 time_t LastBadPassword;
2180 uint16_t BadPasswordCount;
2181 uint32_t resettime;
2182 bool res;
2184 BadPasswordCount = pdb_get_bad_password_count(sampass);
2185 if (!BadPasswordCount) {
2186 DEBUG(9, ("No bad password attempts.\n"));
2187 return True;
2190 become_root();
2191 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2192 unbecome_root();
2194 if (!res) {
2195 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2196 return False;
2199 /* First, check if there is a reset time to compare */
2200 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2201 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2202 return True;
2205 LastBadPassword = pdb_get_bad_password_time(sampass);
2206 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2207 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2208 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2209 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2210 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2211 if (updated) {
2212 *updated = True;
2216 return True;
2219 /*********************************************************************
2220 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2221 *********************************************************************/
2223 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2225 uint32_t duration;
2226 time_t LastBadPassword;
2227 bool res;
2229 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2230 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2231 pdb_get_username(sampass)));
2232 return True;
2235 become_root();
2236 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2237 unbecome_root();
2239 if (!res) {
2240 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2241 return False;
2244 /* First, check if there is a duration to compare */
2245 if ((duration == (uint32_t) -1) || (duration == 0)) {
2246 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2247 return True;
2250 LastBadPassword = pdb_get_bad_password_time(sampass);
2251 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2252 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2254 if (LastBadPassword == (time_t)0) {
2255 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2256 "administratively locked out with no bad password "
2257 "time. Leaving locked out.\n",
2258 pdb_get_username(sampass) ));
2259 return True;
2262 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2263 pdb_set_acct_ctrl(sampass,
2264 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2265 PDB_CHANGED);
2266 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2267 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2268 if (updated) {
2269 *updated = True;
2273 return True;
2276 /*********************************************************************
2277 Increment the bad_password_count
2278 *********************************************************************/
2280 bool pdb_increment_bad_password_count(struct samu *sampass)
2282 uint32_t account_policy_lockout;
2283 bool autolock_updated = False, badpw_updated = False;
2284 bool ret;
2286 /* Retrieve the account lockout policy */
2287 become_root();
2288 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2289 unbecome_root();
2290 if ( !ret ) {
2291 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2292 return False;
2295 /* If there is no policy, we don't need to continue checking */
2296 if (!account_policy_lockout) {
2297 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2298 return True;
2301 /* Check if the autolock needs to be cleared */
2302 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2303 return False;
2305 /* Check if the badpw count needs to be reset */
2306 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2307 return False;
2310 Ok, now we can assume that any resetting that needs to be
2311 done has been done, and just get on with incrementing
2312 and autolocking if necessary
2315 pdb_set_bad_password_count(sampass,
2316 pdb_get_bad_password_count(sampass)+1,
2317 PDB_CHANGED);
2318 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2321 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2322 return True;
2324 if (!pdb_set_acct_ctrl(sampass,
2325 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2326 PDB_CHANGED)) {
2327 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2328 return False;
2331 return True;
2334 bool is_dc_trusted_domain_situation(const char *domain_name)
2336 return IS_DC && !strequal(domain_name, lp_workgroup());
2339 /*******************************************************************
2340 Wrapper around retrieving the clear text trust account password.
2341 appropriate account name is stored in account_name.
2342 Caller must free password, but not account_name.
2343 *******************************************************************/
2345 static bool get_trust_pw_clear2(const char *domain,
2346 const char **account_name,
2347 enum netr_SchannelType *channel,
2348 char **cur_pw,
2349 time_t *_last_set_time,
2350 char **prev_pw)
2352 char *pwd;
2353 time_t last_set_time;
2355 if (cur_pw != NULL) {
2356 *cur_pw = NULL;
2358 if (_last_set_time != NULL) {
2359 *_last_set_time = 0;
2361 if (prev_pw != NULL) {
2362 *prev_pw = NULL;
2365 /* if we are a DC and this is not our domain, then lookup an account
2366 * for the domain trust */
2368 if (is_dc_trusted_domain_situation(domain)) {
2369 if (!lp_allow_trusted_domains()) {
2370 return false;
2373 if (!pdb_get_trusteddom_pw(domain, cur_pw, NULL,
2374 &last_set_time))
2376 DEBUG(0, ("get_trust_pw: could not fetch trust "
2377 "account password for trusted domain %s\n",
2378 domain));
2379 return false;
2382 if (channel != NULL) {
2383 *channel = SEC_CHAN_DOMAIN;
2386 if (account_name != NULL) {
2387 *account_name = lp_workgroup();
2390 if (_last_set_time != NULL) {
2391 *_last_set_time = last_set_time;
2394 return true;
2398 * Since we can only be member of one single domain, we are now
2399 * in a member situation:
2401 * - Either we are a DC (selfjoined) and the domain is our
2402 * own domain.
2403 * - Or we are on a member and the domain is our own or some
2404 * other (potentially trusted) domain.
2406 * In both cases, we can only get the machine account password
2407 * for our own domain to connect to our own dc. (For a member,
2408 * request to trusted domains are performed through our dc.)
2410 * So we simply use our own domain name to retrieve the
2411 * machine account password and ignore the request domain here.
2414 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2416 if (pwd != NULL) {
2417 struct timeval expire;
2419 *cur_pw = pwd;
2421 if (account_name != NULL) {
2422 *account_name = lp_netbios_name();
2425 if (_last_set_time != NULL) {
2426 *_last_set_time = last_set_time;
2429 if (prev_pw == NULL) {
2430 return true;
2433 ZERO_STRUCT(expire);
2434 expire.tv_sec = lp_machine_password_timeout();
2435 expire.tv_sec /= 2;
2436 expire.tv_sec += last_set_time;
2437 if (timeval_expired(&expire)) {
2438 return true;
2441 pwd = secrets_fetch_prev_machine_password(lp_workgroup());
2442 if (pwd != NULL) {
2443 *prev_pw = pwd;
2446 return true;
2449 DEBUG(5, ("get_trust_pw_clear2: could not fetch clear text trust "
2450 "account password for domain %s\n", domain));
2451 return false;
2454 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2455 const char **account_name,
2456 enum netr_SchannelType *channel)
2458 return get_trust_pw_clear2(domain,
2459 account_name,
2460 channel,
2461 ret_pwd,
2462 NULL,
2463 NULL);
2466 /*******************************************************************
2467 Wrapper around retrieving the trust account password.
2468 appropriate account name is stored in account_name.
2469 *******************************************************************/
2471 static bool get_trust_pw_hash2(const char *domain,
2472 const char **account_name,
2473 enum netr_SchannelType *channel,
2474 struct samr_Password *current_nt_hash,
2475 time_t *last_set_time,
2476 struct samr_Password **_previous_nt_hash)
2478 char *cur_pw = NULL;
2479 char *prev_pw = NULL;
2480 char **_prev_pw = NULL;
2481 bool ok;
2483 if (_previous_nt_hash != NULL) {
2484 *_previous_nt_hash = NULL;
2485 _prev_pw = &prev_pw;
2488 ok = get_trust_pw_clear2(domain, account_name, channel,
2489 &cur_pw, last_set_time, _prev_pw);
2490 if (ok) {
2491 struct samr_Password *previous_nt_hash = NULL;
2493 E_md4hash(cur_pw, current_nt_hash->hash);
2494 BURN_FREE_STR(cur_pw);
2496 if (prev_pw == NULL) {
2497 return true;
2500 previous_nt_hash = SMB_MALLOC_P(struct samr_Password);
2501 if (previous_nt_hash == NULL) {
2502 return false;
2505 E_md4hash(prev_pw, previous_nt_hash->hash);
2506 BURN_FREE_STR(prev_pw);
2508 *_previous_nt_hash = previous_nt_hash;
2509 return true;
2510 } else if (is_dc_trusted_domain_situation(domain)) {
2511 return false;
2514 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2516 if (secrets_fetch_trust_account_password_legacy(domain,
2517 current_nt_hash->hash,
2518 last_set_time,
2519 channel))
2521 if (account_name != NULL) {
2522 *account_name = lp_netbios_name();
2525 return true;
2528 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2529 "password for domain %s\n", domain));
2530 return False;
2533 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2534 const char **account_name,
2535 enum netr_SchannelType *channel)
2537 struct samr_Password current_nt_hash;
2538 bool ok;
2540 ok = get_trust_pw_hash2(domain, account_name, channel,
2541 &current_nt_hash, NULL, NULL);
2542 if (!ok) {
2543 return false;
2546 memcpy(ret_pwd, current_nt_hash.hash, sizeof(current_nt_hash.hash));
2547 return true;
2550 NTSTATUS pdb_get_trust_credentials(const char *netbios_domain,
2551 const char *dns_domain, /* optional */
2552 TALLOC_CTX *mem_ctx,
2553 struct cli_credentials **_creds)
2555 TALLOC_CTX *frame = talloc_stackframe();
2556 NTSTATUS status;
2557 struct loadparm_context *lp_ctx;
2558 enum netr_SchannelType channel;
2559 time_t last_set_time;
2560 const char *_account_name;
2561 const char *account_name;
2562 char *cur_pw = NULL;
2563 char *prev_pw = NULL;
2564 struct samr_Password cur_nt_hash;
2565 struct cli_credentials *creds = NULL;
2566 bool ok;
2569 * If this is our primary trust relationship, use the common
2570 * code to read the secrets.ldb or secrets.tdb file.
2572 if (strequal(netbios_domain, lp_workgroup())) {
2573 struct db_context *db_ctx = secrets_db_ctx();
2574 if (db_ctx == NULL) {
2575 DEBUG(1, ("failed to open secrets.tdb to obtain our trust credentials for %s\n",
2576 netbios_domain));
2577 status = NT_STATUS_INTERNAL_ERROR;
2578 goto fail;
2581 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2582 if (lp_ctx == NULL) {
2583 DEBUG(1, ("loadparm_init_s3 failed\n"));
2584 status = NT_STATUS_INTERNAL_ERROR;
2585 goto fail;
2588 creds = cli_credentials_init(mem_ctx);
2589 if (creds == NULL) {
2590 status = NT_STATUS_NO_MEMORY;
2591 goto fail;
2594 ok = cli_credentials_set_conf(creds, lp_ctx);
2595 if (!ok) {
2596 status = NT_STATUS_INTERNAL_ERROR;
2597 goto fail;
2600 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2601 if (!ok) {
2602 status = NT_STATUS_NO_MEMORY;
2603 goto fail;
2606 status = cli_credentials_set_machine_account_db_ctx(creds,
2607 lp_ctx,
2608 db_ctx);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 goto fail;
2612 goto done;
2613 } else if (!IS_DC) {
2614 DEBUG(1, ("Refusing to get trust account info for %s, "
2615 "which is not our primary domain %s, "
2616 "as we are not a DC\n",
2617 netbios_domain, lp_workgroup()));
2618 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2619 goto fail;
2622 status = pdb_get_trusteddom_creds(netbios_domain, mem_ctx, &creds);
2623 if (NT_STATUS_IS_OK(status)) {
2624 goto done;
2626 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
2627 goto fail;
2630 ok = get_trust_pw_clear2(netbios_domain,
2631 &_account_name,
2632 &channel,
2633 &cur_pw,
2634 &last_set_time,
2635 &prev_pw);
2636 if (!ok) {
2637 ok = get_trust_pw_hash2(netbios_domain,
2638 &_account_name,
2639 &channel,
2640 &cur_nt_hash,
2641 &last_set_time,
2642 NULL);
2643 if (!ok) {
2644 DEBUG(1, ("get_trust_pw_*2 failed for domain[%s]\n",
2645 netbios_domain));
2646 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2647 goto fail;
2651 account_name = talloc_asprintf(frame, "%s$", _account_name);
2652 if (account_name == NULL) {
2653 status = NT_STATUS_NO_MEMORY;
2654 goto fail;
2657 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2658 if (lp_ctx == NULL) {
2659 DEBUG(1, ("loadparm_init_s3 failed\n"));
2660 status = NT_STATUS_INTERNAL_ERROR;
2661 goto fail;
2664 creds = cli_credentials_init(mem_ctx);
2665 if (creds == NULL) {
2666 status = NT_STATUS_NO_MEMORY;
2667 goto fail;
2670 ok = cli_credentials_set_conf(creds, lp_ctx);
2671 if (!ok) {
2672 status = NT_STATUS_INTERNAL_ERROR;
2673 goto fail;
2676 cli_credentials_set_secure_channel_type(creds, channel);
2677 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2679 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2680 if (!ok) {
2681 status = NT_STATUS_NO_MEMORY;
2682 goto fail;
2685 if (dns_domain != NULL) {
2686 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2687 if (!ok) {
2688 status = NT_STATUS_NO_MEMORY;
2689 goto fail;
2693 * It's not possible to use NTLMSSP with a domain trust account.
2695 cli_credentials_set_kerberos_state(creds,
2696 CRED_USE_KERBEROS_REQUIRED,
2697 CRED_SPECIFIED);
2698 } else {
2700 * We can't use kerberos against an NT4 domain.
2702 * We should have a mode that also disallows NTLMSSP here,
2703 * as only NETLOGON SCHANNEL is possible.
2705 cli_credentials_set_kerberos_state(creds,
2706 CRED_USE_KERBEROS_DISABLED,
2707 CRED_SPECIFIED);
2710 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2711 if (!ok) {
2712 status = NT_STATUS_NO_MEMORY;
2713 goto fail;
2716 if (cur_pw == NULL) {
2717 ok = cli_credentials_set_nt_hash(creds, &cur_nt_hash, CRED_SPECIFIED);
2718 if (!ok) {
2719 status = NT_STATUS_NO_MEMORY;
2720 goto fail;
2723 * We currently can't do kerberos just with an NTHASH.
2725 cli_credentials_set_kerberos_state(creds,
2726 CRED_USE_KERBEROS_DISABLED,
2727 CRED_SPECIFIED);
2728 goto done;
2731 ok = cli_credentials_set_password(creds, cur_pw, CRED_SPECIFIED);
2732 if (!ok) {
2733 status = NT_STATUS_NO_MEMORY;
2734 goto fail;
2737 if (prev_pw != NULL) {
2738 ok = cli_credentials_set_old_password(creds, prev_pw, CRED_SPECIFIED);
2739 if (!ok) {
2740 status = NT_STATUS_NO_MEMORY;
2741 goto fail;
2745 done:
2746 *_creds = creds;
2747 creds = NULL;
2748 status = NT_STATUS_OK;
2749 fail:
2750 TALLOC_FREE(creds);
2751 SAFE_FREE(cur_pw);
2752 SAFE_FREE(prev_pw);
2753 TALLOC_FREE(frame);
2754 return status;