ctdb-server: Remove duplicate logic
[samba4-gss.git] / source3 / passdb / passdb.c
blobf0ce8b2352dc8ca4db99c6a37612946745e0c851
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;
440 if (!p)
441 return false;
443 for (i = 0; i < 32; i += 2) {
444 bool ok = hex_byte(p + i, &pwd[i / 2]);
445 if (!ok) {
446 return false;
449 return true;
452 /*************************************************************
453 Routine to set 42 hex hours characters from a 21 byte array.
454 **************************************************************/
456 void pdb_sethexhours(char *p, const unsigned char *hours)
458 if (hours != NULL) {
459 hex_encode_buf(p, hours, 21);
460 } else {
461 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
465 /*************************************************************
466 Routine to get the 42 hex characters and turn them
467 into a 21 byte array.
468 **************************************************************/
470 bool pdb_gethexhours(const char *p, unsigned char *hours)
472 int i;
474 if (!p) {
475 return (False);
478 for (i = 0; i < 42; i += 2) {
479 bool ok = hex_byte(p, (uint8_t *)&hours[i / 2]);
480 if (!ok) {
481 return false;
484 return (True);
487 /********************************************************************
488 ********************************************************************/
490 int algorithmic_rid_base(void)
492 int rid_offset;
494 rid_offset = lp_algorithmic_rid_base();
496 if (rid_offset < BASE_RID) {
497 /* Try to prevent admin foot-shooting, we can't put algorithmic
498 rids below 1000, that's the 'well known RIDs' on NT */
499 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
500 rid_offset = BASE_RID;
502 if (rid_offset & 1) {
503 DEBUG(0, ("algorithmic rid base must be even\n"));
504 rid_offset += 1;
506 return rid_offset;
509 /*******************************************************************
510 Converts NT user RID to a UNIX uid.
511 ********************************************************************/
513 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
515 int rid_offset = algorithmic_rid_base();
516 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
519 uid_t max_algorithmic_uid(void)
521 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
524 /*******************************************************************
525 converts UNIX uid to an NT User RID.
526 ********************************************************************/
528 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
530 int rid_offset = algorithmic_rid_base();
531 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
534 /*******************************************************************
535 Converts NT group RID to a UNIX gid.
536 ********************************************************************/
538 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
540 int rid_offset = algorithmic_rid_base();
541 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
544 gid_t max_algorithmic_gid(void)
546 return pdb_group_rid_to_gid(0xffffffff);
549 /*******************************************************************
550 converts NT Group RID to a UNIX uid.
552 warning: you must not call that function only
553 you must do a call to the group mapping first.
554 there is not anymore a direct link between the gid and the rid.
555 ********************************************************************/
557 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
559 int rid_offset = algorithmic_rid_base();
560 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
563 /*******************************************************************
564 Decides if a RID is a well known RID.
565 ********************************************************************/
567 static bool rid_is_well_known(uint32_t rid)
569 /* Not using rid_offset here, because this is the actual
570 NT fixed value (1000) */
572 return (rid < BASE_RID);
575 /*******************************************************************
576 Decides if a RID is a user or group RID.
577 ********************************************************************/
579 bool algorithmic_pdb_rid_is_user(uint32_t rid)
581 if ( rid_is_well_known(rid) ) {
583 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
584 * and DOMAIN_RID_GUEST.
586 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
587 return True;
588 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
589 return True;
591 return False;
594 /*******************************************************************
595 Convert a name into a SID. Used in the lookup name rpc.
596 ********************************************************************/
598 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
599 enum lsa_SidType *type)
601 GROUP_MAP *map;
602 bool ret;
604 /* Windows treats "MACHINE\None" as a special name for
605 rid 513 on non-DCs. You cannot create a user or group
606 name "None" on Windows. You will get an error that
607 the group already exists. */
609 if ( strequal( name, "None" ) ) {
610 *rid = DOMAIN_RID_USERS;
611 *type = SID_NAME_DOM_GRP;
613 return True;
616 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
617 * correctly in the case where foo also exists as a user. If the flag
618 * is set, don't look for users at all. */
620 if ((flags & LOOKUP_NAME_GROUP) == 0) {
621 struct samu *sam_account = NULL;
622 struct dom_sid user_sid;
624 if ( !(sam_account = samu_new( NULL )) ) {
625 return False;
628 become_root();
629 ret = pdb_getsampwnam(sam_account, name);
630 unbecome_root();
632 if (ret) {
633 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
636 TALLOC_FREE(sam_account);
638 if (ret) {
639 if (!sid_check_is_in_our_sam(&user_sid)) {
640 struct dom_sid_buf buf;
641 DBG_ERR("User %s with invalid SID %s"
642 " in passdb\n",
643 name,
644 dom_sid_str_buf(&user_sid, &buf));
645 return False;
648 sid_peek_rid(&user_sid, rid);
649 *type = SID_NAME_USER;
650 return True;
655 * Maybe it is a group ?
658 map = talloc_zero(NULL, GROUP_MAP);
659 if (!map) {
660 return false;
663 become_root();
664 ret = pdb_getgrnam(map, name);
665 unbecome_root();
667 if (!ret) {
668 TALLOC_FREE(map);
669 return False;
672 /* BUILTIN groups are looked up elsewhere */
673 if (!sid_check_is_in_our_sam(&map->sid)) {
674 struct dom_sid_buf buf;
675 DEBUG(10, ("Found group %s (%s) not in our domain -- "
676 "ignoring.\n",
677 name,
678 dom_sid_str_buf(&map->sid, &buf)));
679 TALLOC_FREE(map);
680 return False;
683 /* yes it's a mapped group */
684 sid_peek_rid(&map->sid, rid);
685 *type = map->sid_name_use;
686 TALLOC_FREE(map);
687 return True;
690 /*************************************************************
691 Change a password entry in the local passdb backend.
693 Assumptions:
694 - always called as root
695 - ignores the account type except when adding a new account
696 - will create/delete the unix account if the relative
697 add/delete user script is configured
699 *************************************************************/
701 NTSTATUS local_password_change(const char *user_name,
702 int local_flags,
703 const char *new_passwd,
704 char **pp_err_str,
705 char **pp_msg_str)
707 TALLOC_CTX *tosctx;
708 struct samu *sam_pass;
709 uint32_t acb;
710 uint32_t rid;
711 NTSTATUS result;
712 bool user_exists;
713 int ret = -1;
715 *pp_err_str = NULL;
716 *pp_msg_str = NULL;
718 tosctx = talloc_tos();
720 sam_pass = samu_new(tosctx);
721 if (!sam_pass) {
722 result = NT_STATUS_NO_MEMORY;
723 goto done;
726 /* Get the smb passwd entry for this user */
727 user_exists = pdb_getsampwnam(sam_pass, user_name);
729 /* Check delete first, we don't need to do anything else if we
730 * are going to delete the account */
731 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
733 result = pdb_delete_user(tosctx, sam_pass);
734 if (!NT_STATUS_IS_OK(result)) {
735 ret = asprintf(pp_err_str,
736 "Failed to delete entry for user %s.\n",
737 user_name);
738 if (ret < 0) {
739 *pp_err_str = NULL;
741 result = NT_STATUS_UNSUCCESSFUL;
742 } else {
743 ret = asprintf(pp_msg_str,
744 "Deleted user %s.\n",
745 user_name);
746 if (ret < 0) {
747 *pp_msg_str = NULL;
750 goto done;
753 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
754 /* the entry already existed */
755 local_flags &= ~LOCAL_ADD_USER;
758 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
759 ret = asprintf(pp_err_str,
760 "Failed to find entry for user %s.\n",
761 user_name);
762 if (ret < 0) {
763 *pp_err_str = NULL;
765 result = NT_STATUS_NO_SUCH_USER;
766 goto done;
769 /* First thing add the new user if we are required to do so */
770 if (local_flags & LOCAL_ADD_USER) {
772 if (local_flags & LOCAL_TRUST_ACCOUNT) {
773 acb = ACB_WSTRUST;
774 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
775 acb = ACB_DOMTRUST;
776 } else {
777 acb = ACB_NORMAL;
780 result = pdb_create_user(tosctx, user_name, acb, &rid);
781 if (!NT_STATUS_IS_OK(result)) {
782 ret = asprintf(pp_err_str,
783 "Failed to add entry for user %s.\n",
784 user_name);
785 if (ret < 0) {
786 *pp_err_str = NULL;
788 result = NT_STATUS_UNSUCCESSFUL;
789 goto done;
792 sam_pass = samu_new(tosctx);
793 if (!sam_pass) {
794 result = NT_STATUS_NO_MEMORY;
795 goto done;
798 /* Now get back the smb passwd entry for this new user */
799 user_exists = pdb_getsampwnam(sam_pass, user_name);
800 if (!user_exists) {
801 ret = asprintf(pp_err_str,
802 "Failed to add entry for user %s.\n",
803 user_name);
804 if (ret < 0) {
805 *pp_err_str = NULL;
807 result = NT_STATUS_UNSUCCESSFUL;
808 goto done;
812 acb = pdb_get_acct_ctrl(sam_pass);
815 * We are root - just write the new password
816 * and the valid last change time.
818 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
819 acb |= ACB_PWNOTREQ;
820 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
821 ret = asprintf(pp_err_str,
822 "Failed to set 'no password required' "
823 "flag for user %s.\n", user_name);
824 if (ret < 0) {
825 *pp_err_str = NULL;
827 result = NT_STATUS_UNSUCCESSFUL;
828 goto done;
832 if (local_flags & LOCAL_SET_PASSWORD) {
834 * If we're dealing with setting a completely empty user account
835 * ie. One with a password of 'XXXX', but not set disabled (like
836 * an account created from scratch) then if the old password was
837 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
838 * We remove that as we're giving this user their first password
839 * and the decision hasn't really been made to disable them (ie.
840 * don't create them disabled). JRA.
842 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
843 (acb & ACB_DISABLED)) {
844 acb &= (~ACB_DISABLED);
845 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
846 ret = asprintf(pp_err_str,
847 "Failed to unset 'disabled' "
848 "flag for user %s.\n",
849 user_name);
850 if (ret < 0) {
851 *pp_err_str = NULL;
853 result = NT_STATUS_UNSUCCESSFUL;
854 goto done;
858 acb &= (~ACB_PWNOTREQ);
859 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
860 ret = asprintf(pp_err_str,
861 "Failed to unset 'no password required'"
862 " flag for user %s.\n", user_name);
863 if (ret < 0) {
864 *pp_err_str = NULL;
866 result = NT_STATUS_UNSUCCESSFUL;
867 goto done;
870 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
871 ret = asprintf(pp_err_str,
872 "Failed to set password for "
873 "user %s.\n", user_name);
874 if (ret < 0) {
875 *pp_err_str = NULL;
877 result = NT_STATUS_UNSUCCESSFUL;
878 goto done;
882 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
883 acb |= ACB_DISABLED;
884 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
885 ret = asprintf(pp_err_str,
886 "Failed to set 'disabled' flag for "
887 "user %s.\n", user_name);
888 if (ret < 0) {
889 *pp_err_str = NULL;
891 result = NT_STATUS_UNSUCCESSFUL;
892 goto done;
896 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
897 acb &= (~ACB_DISABLED);
898 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
899 ret = asprintf(pp_err_str,
900 "Failed to unset 'disabled' flag for "
901 "user %s.\n", user_name);
902 if (ret < 0) {
903 *pp_err_str = NULL;
905 result = NT_STATUS_UNSUCCESSFUL;
906 goto done;
910 /* now commit changes if any */
911 result = pdb_update_sam_account(sam_pass);
912 if (!NT_STATUS_IS_OK(result)) {
913 ret = asprintf(pp_err_str,
914 "Failed to modify entry for user %s.\n",
915 user_name);
916 if (ret < 0) {
917 *pp_err_str = NULL;
919 goto done;
922 if (local_flags & LOCAL_ADD_USER) {
923 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
924 } else if (local_flags & LOCAL_DISABLE_USER) {
925 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
926 } else if (local_flags & LOCAL_ENABLE_USER) {
927 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
928 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
929 ret = asprintf(pp_msg_str,
930 "User %s password set to none.\n", user_name);
933 if (ret < 0) {
934 *pp_msg_str = NULL;
937 result = NT_STATUS_OK;
939 done:
940 TALLOC_FREE(sam_pass);
941 return result;
944 /**********************************************************************
945 Marshall/unmarshall struct samu structs.
946 *********************************************************************/
948 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
949 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
950 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
951 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
952 /* nothing changed between V3 and V4 */
954 /*********************************************************************
955 *********************************************************************/
957 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
960 /* times are stored as 32bit integer
961 take care on system with 64bit wide time_t
962 --SSS */
963 uint32_t logon_time,
964 logoff_time,
965 kickoff_time,
966 pass_last_set_time,
967 pass_can_change_time,
968 pass_must_change_time;
969 char *username = NULL;
970 char *domain = NULL;
971 char *nt_username = NULL;
972 char *dir_drive = NULL;
973 char *unknown_str = NULL;
974 char *munged_dial = NULL;
975 char *fullname = NULL;
976 char *homedir = NULL;
977 char *logon_script = NULL;
978 char *profile_path = NULL;
979 char *acct_desc = NULL;
980 char *workstations = NULL;
981 uint32_t username_len, domain_len, nt_username_len,
982 dir_drive_len, unknown_str_len, munged_dial_len,
983 fullname_len, homedir_len, logon_script_len,
984 profile_path_len, acct_desc_len, workstations_len;
986 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
987 uint16_t acct_ctrl, logon_divs;
988 uint16_t bad_password_count, logon_count;
989 uint8_t *hours = NULL;
990 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
991 uint32_t len = 0;
992 uint32_t lm_pw_len, nt_pw_len, hourslen;
993 bool ret = True;
995 if(sampass == NULL || buf == NULL) {
996 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
997 return False;
1000 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1002 /* unpack the buffer into variables */
1003 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
1004 &logon_time, /* d */
1005 &logoff_time, /* d */
1006 &kickoff_time, /* d */
1007 &pass_last_set_time, /* d */
1008 &pass_can_change_time, /* d */
1009 &pass_must_change_time, /* d */
1010 &username_len, &username, /* B */
1011 &domain_len, &domain, /* B */
1012 &nt_username_len, &nt_username, /* B */
1013 &fullname_len, &fullname, /* B */
1014 &homedir_len, &homedir, /* B */
1015 &dir_drive_len, &dir_drive, /* B */
1016 &logon_script_len, &logon_script, /* B */
1017 &profile_path_len, &profile_path, /* B */
1018 &acct_desc_len, &acct_desc, /* B */
1019 &workstations_len, &workstations, /* B */
1020 &unknown_str_len, &unknown_str, /* B */
1021 &munged_dial_len, &munged_dial, /* B */
1022 &user_rid, /* d */
1023 &group_rid, /* d */
1024 &lm_pw_len, &lm_pw_ptr, /* B */
1025 &nt_pw_len, &nt_pw_ptr, /* B */
1026 &acct_ctrl, /* w */
1027 &remove_me, /* remove on the next TDB_FORMAT upgrade */ /* d */
1028 &logon_divs, /* w */
1029 &hours_len, /* d */
1030 &hourslen, &hours, /* B */
1031 &bad_password_count, /* w */
1032 &logon_count, /* w */
1033 &unknown_6); /* d */
1035 if (len == (uint32_t) -1) {
1036 ret = False;
1037 goto done;
1040 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1041 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1042 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1043 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1044 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1046 pdb_set_username(sampass, username, PDB_SET);
1047 pdb_set_domain(sampass, domain, PDB_SET);
1048 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1049 pdb_set_fullname(sampass, fullname, PDB_SET);
1051 if (homedir) {
1052 pdb_set_homedir(sampass, homedir, PDB_SET);
1054 else {
1055 pdb_set_homedir(sampass,
1056 talloc_sub_basic(sampass, username, domain,
1057 lp_logon_home()),
1058 PDB_DEFAULT);
1061 if (dir_drive)
1062 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1063 else {
1064 pdb_set_dir_drive(sampass,
1065 talloc_sub_basic(sampass, username, domain,
1066 lp_logon_drive()),
1067 PDB_DEFAULT);
1070 if (logon_script)
1071 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1072 else {
1073 pdb_set_logon_script(sampass,
1074 talloc_sub_basic(sampass, username, domain,
1075 lp_logon_script()),
1076 PDB_DEFAULT);
1079 if (profile_path) {
1080 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1081 } else {
1082 pdb_set_profile_path(sampass,
1083 talloc_sub_basic(sampass, username, domain,
1084 lp_logon_path()),
1085 PDB_DEFAULT);
1088 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1089 pdb_set_workstations(sampass, workstations, PDB_SET);
1090 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1092 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1093 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1094 ret = False;
1095 goto done;
1099 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1100 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1101 ret = False;
1102 goto done;
1106 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1107 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1108 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1109 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1110 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1111 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1112 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1113 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1114 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1115 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1117 done:
1119 SAFE_FREE(username);
1120 SAFE_FREE(domain);
1121 SAFE_FREE(nt_username);
1122 SAFE_FREE(fullname);
1123 SAFE_FREE(homedir);
1124 SAFE_FREE(dir_drive);
1125 SAFE_FREE(logon_script);
1126 SAFE_FREE(profile_path);
1127 SAFE_FREE(acct_desc);
1128 SAFE_FREE(workstations);
1129 SAFE_FREE(munged_dial);
1130 SAFE_FREE(unknown_str);
1131 SAFE_FREE(lm_pw_ptr);
1132 SAFE_FREE(nt_pw_ptr);
1133 SAFE_FREE(hours);
1135 return ret;
1138 /*********************************************************************
1139 *********************************************************************/
1141 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1144 /* times are stored as 32bit integer
1145 take care on system with 64bit wide time_t
1146 --SSS */
1147 uint32_t logon_time,
1148 logoff_time,
1149 kickoff_time,
1150 bad_password_time,
1151 pass_last_set_time,
1152 pass_can_change_time,
1153 pass_must_change_time;
1154 char *username = NULL;
1155 char *domain = NULL;
1156 char *nt_username = NULL;
1157 char *dir_drive = NULL;
1158 char *unknown_str = NULL;
1159 char *munged_dial = NULL;
1160 char *fullname = NULL;
1161 char *homedir = NULL;
1162 char *logon_script = NULL;
1163 char *profile_path = NULL;
1164 char *acct_desc = NULL;
1165 char *workstations = NULL;
1166 uint32_t username_len, domain_len, nt_username_len,
1167 dir_drive_len, unknown_str_len, munged_dial_len,
1168 fullname_len, homedir_len, logon_script_len,
1169 profile_path_len, acct_desc_len, workstations_len;
1171 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1172 uint16_t acct_ctrl, logon_divs;
1173 uint16_t bad_password_count, logon_count;
1174 uint8_t *hours = NULL;
1175 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1176 uint32_t len = 0;
1177 uint32_t lm_pw_len, nt_pw_len, hourslen;
1178 bool ret = True;
1180 if(sampass == NULL || buf == NULL) {
1181 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1182 return False;
1185 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1187 /* unpack the buffer into variables */
1188 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1189 &logon_time, /* d */
1190 &logoff_time, /* d */
1191 &kickoff_time, /* d */
1192 /* Change from V0 is addition of bad_password_time field. */
1193 &bad_password_time, /* d */
1194 &pass_last_set_time, /* d */
1195 &pass_can_change_time, /* d */
1196 &pass_must_change_time, /* d */
1197 &username_len, &username, /* B */
1198 &domain_len, &domain, /* B */
1199 &nt_username_len, &nt_username, /* B */
1200 &fullname_len, &fullname, /* B */
1201 &homedir_len, &homedir, /* B */
1202 &dir_drive_len, &dir_drive, /* B */
1203 &logon_script_len, &logon_script, /* B */
1204 &profile_path_len, &profile_path, /* B */
1205 &acct_desc_len, &acct_desc, /* B */
1206 &workstations_len, &workstations, /* B */
1207 &unknown_str_len, &unknown_str, /* B */
1208 &munged_dial_len, &munged_dial, /* B */
1209 &user_rid, /* d */
1210 &group_rid, /* d */
1211 &lm_pw_len, &lm_pw_ptr, /* B */
1212 &nt_pw_len, &nt_pw_ptr, /* B */
1213 &acct_ctrl, /* w */
1214 &remove_me, /* d */
1215 &logon_divs, /* w */
1216 &hours_len, /* d */
1217 &hourslen, &hours, /* B */
1218 &bad_password_count, /* w */
1219 &logon_count, /* w */
1220 &unknown_6); /* d */
1222 if (len == (uint32_t) -1) {
1223 ret = False;
1224 goto done;
1227 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1228 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1229 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1231 /* Change from V0 is addition of bad_password_time field. */
1232 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1233 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1234 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1236 pdb_set_username(sampass, username, PDB_SET);
1237 pdb_set_domain(sampass, domain, PDB_SET);
1238 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1239 pdb_set_fullname(sampass, fullname, PDB_SET);
1241 if (homedir) {
1242 pdb_set_homedir(sampass, homedir, PDB_SET);
1244 else {
1245 pdb_set_homedir(sampass,
1246 talloc_sub_basic(sampass, username, domain,
1247 lp_logon_home()),
1248 PDB_DEFAULT);
1251 if (dir_drive)
1252 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1253 else {
1254 pdb_set_dir_drive(sampass,
1255 talloc_sub_basic(sampass, username, domain,
1256 lp_logon_drive()),
1257 PDB_DEFAULT);
1260 if (logon_script)
1261 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1262 else {
1263 pdb_set_logon_script(sampass,
1264 talloc_sub_basic(sampass, username, domain,
1265 lp_logon_script()),
1266 PDB_DEFAULT);
1269 if (profile_path) {
1270 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1271 } else {
1272 pdb_set_profile_path(sampass,
1273 talloc_sub_basic(sampass, username, domain,
1274 lp_logon_path()),
1275 PDB_DEFAULT);
1278 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1279 pdb_set_workstations(sampass, workstations, PDB_SET);
1280 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1282 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1283 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1284 ret = False;
1285 goto done;
1289 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1290 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1291 ret = False;
1292 goto done;
1296 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1298 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1299 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1300 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1301 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1302 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1303 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1304 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1305 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1306 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1308 done:
1310 SAFE_FREE(username);
1311 SAFE_FREE(domain);
1312 SAFE_FREE(nt_username);
1313 SAFE_FREE(fullname);
1314 SAFE_FREE(homedir);
1315 SAFE_FREE(dir_drive);
1316 SAFE_FREE(logon_script);
1317 SAFE_FREE(profile_path);
1318 SAFE_FREE(acct_desc);
1319 SAFE_FREE(workstations);
1320 SAFE_FREE(munged_dial);
1321 SAFE_FREE(unknown_str);
1322 SAFE_FREE(lm_pw_ptr);
1323 SAFE_FREE(nt_pw_ptr);
1324 SAFE_FREE(hours);
1326 return ret;
1329 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1332 /* times are stored as 32bit integer
1333 take care on system with 64bit wide time_t
1334 --SSS */
1335 uint32_t logon_time,
1336 logoff_time,
1337 kickoff_time,
1338 bad_password_time,
1339 pass_last_set_time,
1340 pass_can_change_time,
1341 pass_must_change_time;
1342 char *username = NULL;
1343 char *domain = NULL;
1344 char *nt_username = NULL;
1345 char *dir_drive = NULL;
1346 char *unknown_str = NULL;
1347 char *munged_dial = NULL;
1348 char *fullname = NULL;
1349 char *homedir = NULL;
1350 char *logon_script = NULL;
1351 char *profile_path = NULL;
1352 char *acct_desc = NULL;
1353 char *workstations = NULL;
1354 uint32_t username_len, domain_len, nt_username_len,
1355 dir_drive_len, unknown_str_len, munged_dial_len,
1356 fullname_len, homedir_len, logon_script_len,
1357 profile_path_len, acct_desc_len, workstations_len;
1359 uint32_t user_rid, group_rid, hours_len, unknown_6;
1360 uint16_t acct_ctrl, logon_divs;
1361 uint16_t bad_password_count, logon_count;
1362 uint8_t *hours = NULL;
1363 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1364 uint32_t len = 0;
1365 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1366 uint32_t pwHistLen = 0;
1367 bool ret = True;
1368 fstring tmp_string;
1369 bool expand_explicit = lp_passdb_expand_explicit();
1371 if(sampass == NULL || buf == NULL) {
1372 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1373 return False;
1376 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1378 /* unpack the buffer into variables */
1379 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1380 &logon_time, /* d */
1381 &logoff_time, /* d */
1382 &kickoff_time, /* d */
1383 &bad_password_time, /* d */
1384 &pass_last_set_time, /* d */
1385 &pass_can_change_time, /* d */
1386 &pass_must_change_time, /* d */
1387 &username_len, &username, /* B */
1388 &domain_len, &domain, /* B */
1389 &nt_username_len, &nt_username, /* B */
1390 &fullname_len, &fullname, /* B */
1391 &homedir_len, &homedir, /* B */
1392 &dir_drive_len, &dir_drive, /* B */
1393 &logon_script_len, &logon_script, /* B */
1394 &profile_path_len, &profile_path, /* B */
1395 &acct_desc_len, &acct_desc, /* B */
1396 &workstations_len, &workstations, /* B */
1397 &unknown_str_len, &unknown_str, /* B */
1398 &munged_dial_len, &munged_dial, /* B */
1399 &user_rid, /* d */
1400 &group_rid, /* d */
1401 &lm_pw_len, &lm_pw_ptr, /* B */
1402 &nt_pw_len, &nt_pw_ptr, /* B */
1403 /* Change from V1 is addition of password history field. */
1404 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1405 &acct_ctrl, /* w */
1406 /* Also "remove_me" field was removed. */
1407 &logon_divs, /* w */
1408 &hours_len, /* d */
1409 &hourslen, &hours, /* B */
1410 &bad_password_count, /* w */
1411 &logon_count, /* w */
1412 &unknown_6); /* d */
1414 if (len == (uint32_t) -1) {
1415 ret = False;
1416 goto done;
1419 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1420 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1421 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1422 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1423 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1424 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1426 pdb_set_username(sampass, username, PDB_SET);
1427 pdb_set_domain(sampass, domain, PDB_SET);
1428 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1429 pdb_set_fullname(sampass, fullname, PDB_SET);
1431 if (homedir) {
1432 fstrcpy( tmp_string, homedir );
1433 if (expand_explicit) {
1434 standard_sub_basic( username, domain, tmp_string,
1435 sizeof(tmp_string) );
1437 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1439 else {
1440 pdb_set_homedir(sampass,
1441 talloc_sub_basic(sampass, username, domain,
1442 lp_logon_home()),
1443 PDB_DEFAULT);
1446 if (dir_drive)
1447 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1448 else
1449 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1451 if (logon_script) {
1452 fstrcpy( tmp_string, logon_script );
1453 if (expand_explicit) {
1454 standard_sub_basic( username, domain, tmp_string,
1455 sizeof(tmp_string) );
1457 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1459 else {
1460 pdb_set_logon_script(sampass,
1461 talloc_sub_basic(sampass, username, domain,
1462 lp_logon_script()),
1463 PDB_DEFAULT);
1466 if (profile_path) {
1467 fstrcpy( tmp_string, profile_path );
1468 if (expand_explicit) {
1469 standard_sub_basic( username, domain, tmp_string,
1470 sizeof(tmp_string) );
1472 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1474 else {
1475 pdb_set_profile_path(sampass,
1476 talloc_sub_basic(sampass, username, domain,
1477 lp_logon_path()),
1478 PDB_DEFAULT);
1481 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1482 pdb_set_workstations(sampass, workstations, PDB_SET);
1483 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1485 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1486 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1487 ret = False;
1488 goto done;
1492 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1493 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1494 ret = False;
1495 goto done;
1499 /* Change from V1 is addition of password history field. */
1500 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1501 if (pwHistLen) {
1502 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1503 if (!pw_hist) {
1504 ret = False;
1505 goto done;
1507 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1508 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1509 int i;
1510 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1511 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1512 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1513 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1514 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1515 PW_HISTORY_ENTRY_LEN);
1518 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1519 SAFE_FREE(pw_hist);
1520 ret = False;
1521 goto done;
1523 SAFE_FREE(pw_hist);
1524 } else {
1525 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1528 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1529 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1530 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1531 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1532 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1533 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1534 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1535 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1536 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1538 done:
1540 SAFE_FREE(username);
1541 SAFE_FREE(domain);
1542 SAFE_FREE(nt_username);
1543 SAFE_FREE(fullname);
1544 SAFE_FREE(homedir);
1545 SAFE_FREE(dir_drive);
1546 SAFE_FREE(logon_script);
1547 SAFE_FREE(profile_path);
1548 SAFE_FREE(acct_desc);
1549 SAFE_FREE(workstations);
1550 SAFE_FREE(munged_dial);
1551 SAFE_FREE(unknown_str);
1552 SAFE_FREE(lm_pw_ptr);
1553 SAFE_FREE(nt_pw_ptr);
1554 SAFE_FREE(nt_pw_hist_ptr);
1555 SAFE_FREE(hours);
1557 return ret;
1560 /*********************************************************************
1561 *********************************************************************/
1563 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1566 /* times are stored as 32bit integer
1567 take care on system with 64bit wide time_t
1568 --SSS */
1569 uint32_t logon_time,
1570 logoff_time,
1571 kickoff_time,
1572 bad_password_time,
1573 pass_last_set_time,
1574 pass_can_change_time,
1575 pass_must_change_time;
1576 char *username = NULL;
1577 char *domain = NULL;
1578 char *nt_username = NULL;
1579 char *dir_drive = NULL;
1580 char *comment = NULL;
1581 char *munged_dial = NULL;
1582 char *fullname = NULL;
1583 char *homedir = NULL;
1584 char *logon_script = NULL;
1585 char *profile_path = NULL;
1586 char *acct_desc = NULL;
1587 char *workstations = NULL;
1588 uint32_t username_len, domain_len, nt_username_len,
1589 dir_drive_len, comment_len, munged_dial_len,
1590 fullname_len, homedir_len, logon_script_len,
1591 profile_path_len, acct_desc_len, workstations_len;
1593 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1594 uint16_t logon_divs;
1595 uint16_t bad_password_count, logon_count;
1596 uint8_t *hours = NULL;
1597 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1598 uint32_t len = 0;
1599 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1600 uint32_t pwHistLen = 0;
1601 bool ret = True;
1602 fstring tmp_string;
1603 bool expand_explicit = lp_passdb_expand_explicit();
1605 if(sampass == NULL || buf == NULL) {
1606 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1607 return False;
1610 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1612 /* unpack the buffer into variables */
1613 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1614 &logon_time, /* d */
1615 &logoff_time, /* d */
1616 &kickoff_time, /* d */
1617 &bad_password_time, /* d */
1618 &pass_last_set_time, /* d */
1619 &pass_can_change_time, /* d */
1620 &pass_must_change_time, /* d */
1621 &username_len, &username, /* B */
1622 &domain_len, &domain, /* B */
1623 &nt_username_len, &nt_username, /* B */
1624 &fullname_len, &fullname, /* B */
1625 &homedir_len, &homedir, /* B */
1626 &dir_drive_len, &dir_drive, /* B */
1627 &logon_script_len, &logon_script, /* B */
1628 &profile_path_len, &profile_path, /* B */
1629 &acct_desc_len, &acct_desc, /* B */
1630 &workstations_len, &workstations, /* B */
1631 &comment_len, &comment, /* B */
1632 &munged_dial_len, &munged_dial, /* B */
1633 &user_rid, /* d */
1634 &group_rid, /* d */
1635 &lm_pw_len, &lm_pw_ptr, /* B */
1636 &nt_pw_len, &nt_pw_ptr, /* B */
1637 /* Change from V1 is addition of password history field. */
1638 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1639 /* Change from V2 is the uint32_t acb_mask */
1640 &acct_ctrl, /* d */
1641 /* Also "remove_me" field was removed. */
1642 &logon_divs, /* w */
1643 &hours_len, /* d */
1644 &hourslen, &hours, /* B */
1645 &bad_password_count, /* w */
1646 &logon_count, /* w */
1647 &unknown_6); /* d */
1649 if (len == (uint32_t) -1) {
1650 ret = False;
1651 goto done;
1654 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1655 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1656 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1657 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1658 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1659 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1661 pdb_set_username(sampass, username, PDB_SET);
1662 pdb_set_domain(sampass, domain, PDB_SET);
1663 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1664 pdb_set_fullname(sampass, fullname, PDB_SET);
1666 if (homedir) {
1667 fstrcpy( tmp_string, homedir );
1668 if (expand_explicit) {
1669 standard_sub_basic( username, domain, tmp_string,
1670 sizeof(tmp_string) );
1672 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1674 else {
1675 pdb_set_homedir(sampass,
1676 talloc_sub_basic(sampass, username, domain,
1677 lp_logon_home()),
1678 PDB_DEFAULT);
1681 if (dir_drive)
1682 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1683 else
1684 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1686 if (logon_script) {
1687 fstrcpy( tmp_string, logon_script );
1688 if (expand_explicit) {
1689 standard_sub_basic( username, domain, tmp_string,
1690 sizeof(tmp_string) );
1692 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1694 else {
1695 pdb_set_logon_script(sampass,
1696 talloc_sub_basic(sampass, username, domain,
1697 lp_logon_script()),
1698 PDB_DEFAULT);
1701 if (profile_path) {
1702 fstrcpy( tmp_string, profile_path );
1703 if (expand_explicit) {
1704 standard_sub_basic( username, domain, tmp_string,
1705 sizeof(tmp_string) );
1707 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1709 else {
1710 pdb_set_profile_path(sampass,
1711 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1712 PDB_DEFAULT);
1715 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1716 pdb_set_comment(sampass, comment, PDB_SET);
1717 pdb_set_workstations(sampass, workstations, PDB_SET);
1718 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1720 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1721 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1722 ret = False;
1723 goto done;
1727 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1728 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1729 ret = False;
1730 goto done;
1734 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1735 if (pwHistLen) {
1736 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1737 if (!pw_hist) {
1738 ret = False;
1739 goto done;
1741 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1742 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1743 int i;
1744 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1745 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1746 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1747 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1748 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1749 PW_HISTORY_ENTRY_LEN);
1752 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1753 SAFE_FREE(pw_hist);
1754 ret = False;
1755 goto done;
1757 SAFE_FREE(pw_hist);
1758 } else {
1759 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1762 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1763 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1764 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1765 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1766 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1767 /* Change from V2 is the uint32_t acct_ctrl */
1768 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1769 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1770 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1772 done:
1774 SAFE_FREE(username);
1775 SAFE_FREE(domain);
1776 SAFE_FREE(nt_username);
1777 SAFE_FREE(fullname);
1778 SAFE_FREE(homedir);
1779 SAFE_FREE(dir_drive);
1780 SAFE_FREE(logon_script);
1781 SAFE_FREE(profile_path);
1782 SAFE_FREE(acct_desc);
1783 SAFE_FREE(workstations);
1784 SAFE_FREE(munged_dial);
1785 SAFE_FREE(comment);
1786 SAFE_FREE(lm_pw_ptr);
1787 SAFE_FREE(nt_pw_ptr);
1788 SAFE_FREE(nt_pw_hist_ptr);
1789 SAFE_FREE(hours);
1791 return ret;
1794 /*********************************************************************
1795 *********************************************************************/
1797 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1799 size_t len, buflen;
1801 /* times are stored as 32bit integer
1802 take care on system with 64bit wide time_t
1803 --SSS */
1804 uint32_t logon_time,
1805 logoff_time,
1806 kickoff_time,
1807 bad_password_time,
1808 pass_last_set_time,
1809 pass_can_change_time,
1810 pass_must_change_time;
1812 uint32_t user_rid, group_rid;
1814 const char *username;
1815 const char *domain;
1816 const char *nt_username;
1817 const char *dir_drive;
1818 const char *comment;
1819 const char *munged_dial;
1820 const char *fullname;
1821 const char *homedir;
1822 const char *logon_script;
1823 const char *profile_path;
1824 const char *acct_desc;
1825 const char *workstations;
1826 uint32_t username_len, domain_len, nt_username_len,
1827 dir_drive_len, comment_len, munged_dial_len,
1828 fullname_len, homedir_len, logon_script_len,
1829 profile_path_len, acct_desc_len, workstations_len;
1831 const uint8_t *lm_pw;
1832 const uint8_t *nt_pw;
1833 const uint8_t *nt_pw_hist;
1834 uint32_t lm_pw_len = 16;
1835 uint32_t nt_pw_len = 16;
1836 uint32_t nt_pw_hist_len;
1837 uint32_t pwHistLen = 0;
1839 *buf = NULL;
1840 buflen = 0;
1842 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1843 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1844 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1845 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1846 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1847 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1848 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1850 user_rid = pdb_get_user_rid(sampass);
1851 group_rid = pdb_get_group_rid(sampass);
1853 username = pdb_get_username(sampass);
1854 if (username) {
1855 username_len = strlen(username) +1;
1856 } else {
1857 username_len = 0;
1860 domain = pdb_get_domain(sampass);
1861 if (domain) {
1862 domain_len = strlen(domain) +1;
1863 } else {
1864 domain_len = 0;
1867 nt_username = pdb_get_nt_username(sampass);
1868 if (nt_username) {
1869 nt_username_len = strlen(nt_username) +1;
1870 } else {
1871 nt_username_len = 0;
1874 fullname = pdb_get_fullname(sampass);
1875 if (fullname) {
1876 fullname_len = strlen(fullname) +1;
1877 } else {
1878 fullname_len = 0;
1882 * Only updates fields which have been set (not defaults from smb.conf)
1885 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1886 dir_drive = pdb_get_dir_drive(sampass);
1887 } else {
1888 dir_drive = NULL;
1890 if (dir_drive) {
1891 dir_drive_len = strlen(dir_drive) +1;
1892 } else {
1893 dir_drive_len = 0;
1896 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1897 homedir = pdb_get_homedir(sampass);
1898 } else {
1899 homedir = NULL;
1901 if (homedir) {
1902 homedir_len = strlen(homedir) +1;
1903 } else {
1904 homedir_len = 0;
1907 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1908 logon_script = pdb_get_logon_script(sampass);
1909 } else {
1910 logon_script = NULL;
1912 if (logon_script) {
1913 logon_script_len = strlen(logon_script) +1;
1914 } else {
1915 logon_script_len = 0;
1918 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1919 profile_path = pdb_get_profile_path(sampass);
1920 } else {
1921 profile_path = NULL;
1923 if (profile_path) {
1924 profile_path_len = strlen(profile_path) +1;
1925 } else {
1926 profile_path_len = 0;
1929 lm_pw = pdb_get_lanman_passwd(sampass);
1930 if (!lm_pw) {
1931 lm_pw_len = 0;
1934 nt_pw = pdb_get_nt_passwd(sampass);
1935 if (!nt_pw) {
1936 nt_pw_len = 0;
1939 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1940 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1941 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1942 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1943 } else {
1944 nt_pw_hist_len = 0;
1947 acct_desc = pdb_get_acct_desc(sampass);
1948 if (acct_desc) {
1949 acct_desc_len = strlen(acct_desc) +1;
1950 } else {
1951 acct_desc_len = 0;
1954 workstations = pdb_get_workstations(sampass);
1955 if (workstations) {
1956 workstations_len = strlen(workstations) +1;
1957 } else {
1958 workstations_len = 0;
1961 comment = pdb_get_comment(sampass);
1962 if (comment) {
1963 comment_len = strlen(comment) +1;
1964 } else {
1965 comment_len = 0;
1968 munged_dial = pdb_get_munged_dial(sampass);
1969 if (munged_dial) {
1970 munged_dial_len = strlen(munged_dial) +1;
1971 } else {
1972 munged_dial_len = 0;
1975 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1977 /* one time to get the size needed */
1978 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1979 logon_time, /* d */
1980 logoff_time, /* d */
1981 kickoff_time, /* d */
1982 bad_password_time, /* d */
1983 pass_last_set_time, /* d */
1984 pass_can_change_time, /* d */
1985 pass_must_change_time, /* d */
1986 username_len, username, /* B */
1987 domain_len, domain, /* B */
1988 nt_username_len, nt_username, /* B */
1989 fullname_len, fullname, /* B */
1990 homedir_len, homedir, /* B */
1991 dir_drive_len, dir_drive, /* B */
1992 logon_script_len, logon_script, /* B */
1993 profile_path_len, profile_path, /* B */
1994 acct_desc_len, acct_desc, /* B */
1995 workstations_len, workstations, /* B */
1996 comment_len, comment, /* B */
1997 munged_dial_len, munged_dial, /* B */
1998 user_rid, /* d */
1999 group_rid, /* d */
2000 lm_pw_len, lm_pw, /* B */
2001 nt_pw_len, nt_pw, /* B */
2002 nt_pw_hist_len, nt_pw_hist, /* B */
2003 pdb_get_acct_ctrl(sampass), /* d */
2004 pdb_get_logon_divs(sampass), /* w */
2005 pdb_get_hours_len(sampass), /* d */
2006 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2007 pdb_get_bad_password_count(sampass), /* w */
2008 pdb_get_logon_count(sampass), /* w */
2009 pdb_get_unknown_6(sampass)); /* d */
2011 if (size_only) {
2012 return buflen;
2015 /* malloc the space needed */
2016 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
2017 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
2018 return (-1);
2021 /* now for the real call to tdb_pack() */
2022 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2023 logon_time, /* d */
2024 logoff_time, /* d */
2025 kickoff_time, /* d */
2026 bad_password_time, /* d */
2027 pass_last_set_time, /* d */
2028 pass_can_change_time, /* d */
2029 pass_must_change_time, /* d */
2030 username_len, username, /* B */
2031 domain_len, domain, /* B */
2032 nt_username_len, nt_username, /* B */
2033 fullname_len, fullname, /* B */
2034 homedir_len, homedir, /* B */
2035 dir_drive_len, dir_drive, /* B */
2036 logon_script_len, logon_script, /* B */
2037 profile_path_len, profile_path, /* B */
2038 acct_desc_len, acct_desc, /* B */
2039 workstations_len, workstations, /* B */
2040 comment_len, comment, /* B */
2041 munged_dial_len, munged_dial, /* B */
2042 user_rid, /* d */
2043 group_rid, /* d */
2044 lm_pw_len, lm_pw, /* B */
2045 nt_pw_len, nt_pw, /* B */
2046 nt_pw_hist_len, nt_pw_hist, /* B */
2047 pdb_get_acct_ctrl(sampass), /* d */
2048 pdb_get_logon_divs(sampass), /* w */
2049 pdb_get_hours_len(sampass), /* d */
2050 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2051 pdb_get_bad_password_count(sampass), /* w */
2052 pdb_get_logon_count(sampass), /* w */
2053 pdb_get_unknown_6(sampass)); /* d */
2055 /* check to make sure we got it correct */
2056 if (buflen != len) {
2057 DEBUG(0, ("init_buffer_from_samu_v3: something odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2058 (unsigned long)buflen, (unsigned long)len));
2059 /* error */
2060 SAFE_FREE (*buf);
2061 return (-1);
2064 return (buflen);
2067 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2069 /* nothing changed between V3 and V4 */
2070 return init_samu_from_buffer_v3(sampass, buf, buflen);
2073 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2075 /* nothing changed between V3 and V4 */
2076 return init_buffer_from_samu_v3(buf, sampass, size_only);
2079 /**********************************************************************
2080 Initialize a struct samu struct from a BYTE buffer of size len
2081 *********************************************************************/
2083 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2084 uint8_t *buf, uint32_t buflen)
2086 switch (level) {
2087 case SAMU_BUFFER_V0:
2088 return init_samu_from_buffer_v0(sampass, buf, buflen);
2089 case SAMU_BUFFER_V1:
2090 return init_samu_from_buffer_v1(sampass, buf, buflen);
2091 case SAMU_BUFFER_V2:
2092 return init_samu_from_buffer_v2(sampass, buf, buflen);
2093 case SAMU_BUFFER_V3:
2094 return init_samu_from_buffer_v3(sampass, buf, buflen);
2095 case SAMU_BUFFER_V4:
2096 return init_samu_from_buffer_v4(sampass, buf, buflen);
2099 return false;
2102 /**********************************************************************
2103 Initialize a BYTE buffer from a struct samu struct
2104 *********************************************************************/
2106 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2108 return init_buffer_from_samu_v4(buf, sampass, size_only);
2111 /*********************************************************************
2112 *********************************************************************/
2114 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2116 uint8_t *buf = NULL;
2117 int len;
2119 len = init_buffer_from_samu(&buf, src, False);
2120 if (len == -1 || !buf) {
2121 SAFE_FREE(buf);
2122 return False;
2125 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2126 free(buf);
2127 return False;
2130 dst->methods = src->methods;
2132 if ( src->unix_pw ) {
2133 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2134 if (!dst->unix_pw) {
2135 free(buf);
2136 return False;
2140 if (src->group_sid) {
2141 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2144 free(buf);
2145 return True;
2148 /*********************************************************************
2149 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2150 *********************************************************************/
2152 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2154 time_t LastBadPassword;
2155 uint16_t BadPasswordCount;
2156 uint32_t resettime;
2157 bool res;
2159 BadPasswordCount = pdb_get_bad_password_count(sampass);
2160 if (!BadPasswordCount) {
2161 DEBUG(9, ("No bad password attempts.\n"));
2162 return True;
2165 become_root();
2166 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2167 unbecome_root();
2169 if (!res) {
2170 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2171 return False;
2174 /* First, check if there is a reset time to compare */
2175 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2176 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2177 return True;
2180 LastBadPassword = pdb_get_bad_password_time(sampass);
2181 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2182 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2183 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2184 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2185 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2186 if (updated) {
2187 *updated = True;
2191 return True;
2194 /*********************************************************************
2195 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2196 *********************************************************************/
2198 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2200 uint32_t duration;
2201 time_t LastBadPassword;
2202 bool res;
2204 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2205 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2206 pdb_get_username(sampass)));
2207 return True;
2210 become_root();
2211 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2212 unbecome_root();
2214 if (!res) {
2215 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2216 return False;
2219 /* First, check if there is a duration to compare */
2220 if ((duration == (uint32_t) -1) || (duration == 0)) {
2221 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2222 return True;
2225 LastBadPassword = pdb_get_bad_password_time(sampass);
2226 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2227 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2229 if (LastBadPassword == (time_t)0) {
2230 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2231 "administratively locked out with no bad password "
2232 "time. Leaving locked out.\n",
2233 pdb_get_username(sampass) ));
2234 return True;
2237 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2238 pdb_set_acct_ctrl(sampass,
2239 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2240 PDB_CHANGED);
2241 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2242 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2243 if (updated) {
2244 *updated = True;
2248 return True;
2251 /*********************************************************************
2252 Increment the bad_password_count
2253 *********************************************************************/
2255 bool pdb_increment_bad_password_count(struct samu *sampass)
2257 uint32_t account_policy_lockout;
2258 bool autolock_updated = False, badpw_updated = False;
2259 bool ret;
2261 /* Retrieve the account lockout policy */
2262 become_root();
2263 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2264 unbecome_root();
2265 if ( !ret ) {
2266 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2267 return False;
2270 /* If there is no policy, we don't need to continue checking */
2271 if (!account_policy_lockout) {
2272 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2273 return True;
2276 /* Check if the autolock needs to be cleared */
2277 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2278 return False;
2280 /* Check if the badpw count needs to be reset */
2281 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2282 return False;
2285 Ok, now we can assume that any resetting that needs to be
2286 done has been done, and just get on with incrementing
2287 and autolocking if necessary
2290 pdb_set_bad_password_count(sampass,
2291 pdb_get_bad_password_count(sampass)+1,
2292 PDB_CHANGED);
2293 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2296 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2297 return True;
2299 if (!pdb_set_acct_ctrl(sampass,
2300 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2301 PDB_CHANGED)) {
2302 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2303 return False;
2306 return True;
2309 bool is_dc_trusted_domain_situation(const char *domain_name)
2311 return IS_DC && !strequal(domain_name, lp_workgroup());
2314 /*******************************************************************
2315 Wrapper around retrieving the clear text trust account password.
2316 appropriate account name is stored in account_name.
2317 Caller must free password, but not account_name.
2318 *******************************************************************/
2320 static bool get_trust_pw_clear2(const char *domain,
2321 const char **account_name,
2322 enum netr_SchannelType *channel,
2323 char **cur_pw,
2324 time_t *_last_set_time,
2325 char **prev_pw)
2327 char *pwd;
2328 time_t last_set_time;
2330 if (cur_pw != NULL) {
2331 *cur_pw = NULL;
2333 if (_last_set_time != NULL) {
2334 *_last_set_time = 0;
2336 if (prev_pw != NULL) {
2337 *prev_pw = NULL;
2340 /* if we are a DC and this is not our domain, then lookup an account
2341 * for the domain trust */
2343 if (is_dc_trusted_domain_situation(domain)) {
2344 if (!lp_allow_trusted_domains()) {
2345 return false;
2348 if (!pdb_get_trusteddom_pw(domain, cur_pw, NULL,
2349 &last_set_time))
2351 DEBUG(0, ("get_trust_pw: could not fetch trust "
2352 "account password for trusted domain %s\n",
2353 domain));
2354 return false;
2357 if (channel != NULL) {
2358 *channel = SEC_CHAN_DOMAIN;
2361 if (account_name != NULL) {
2362 *account_name = lp_workgroup();
2365 if (_last_set_time != NULL) {
2366 *_last_set_time = last_set_time;
2369 return true;
2373 * Since we can only be member of one single domain, we are now
2374 * in a member situation:
2376 * - Either we are a DC (selfjoined) and the domain is our
2377 * own domain.
2378 * - Or we are on a member and the domain is our own or some
2379 * other (potentially trusted) domain.
2381 * In both cases, we can only get the machine account password
2382 * for our own domain to connect to our own dc. (For a member,
2383 * request to trusted domains are performed through our dc.)
2385 * So we simply use our own domain name to retrieve the
2386 * machine account password and ignore the request domain here.
2389 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2391 if (pwd != NULL) {
2392 struct timeval expire;
2394 *cur_pw = pwd;
2396 if (account_name != NULL) {
2397 *account_name = lp_netbios_name();
2400 if (_last_set_time != NULL) {
2401 *_last_set_time = last_set_time;
2404 if (prev_pw == NULL) {
2405 return true;
2408 ZERO_STRUCT(expire);
2409 expire.tv_sec = lp_machine_password_timeout();
2410 expire.tv_sec /= 2;
2411 expire.tv_sec += last_set_time;
2412 if (timeval_expired(&expire)) {
2413 return true;
2416 pwd = secrets_fetch_prev_machine_password(lp_workgroup());
2417 if (pwd != NULL) {
2418 *prev_pw = pwd;
2421 return true;
2424 DEBUG(5, ("get_trust_pw_clear2: could not fetch clear text trust "
2425 "account password for domain %s\n", domain));
2426 return false;
2429 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2430 const char **account_name,
2431 enum netr_SchannelType *channel)
2433 return get_trust_pw_clear2(domain,
2434 account_name,
2435 channel,
2436 ret_pwd,
2437 NULL,
2438 NULL);
2441 /*******************************************************************
2442 Wrapper around retrieving the trust account password.
2443 appropriate account name is stored in account_name.
2444 *******************************************************************/
2446 static bool get_trust_pw_hash2(const char *domain,
2447 const char **account_name,
2448 enum netr_SchannelType *channel,
2449 struct samr_Password *current_nt_hash,
2450 time_t *last_set_time,
2451 struct samr_Password **_previous_nt_hash)
2453 char *cur_pw = NULL;
2454 char *prev_pw = NULL;
2455 char **_prev_pw = NULL;
2456 bool ok;
2458 if (_previous_nt_hash != NULL) {
2459 *_previous_nt_hash = NULL;
2460 _prev_pw = &prev_pw;
2463 ok = get_trust_pw_clear2(domain, account_name, channel,
2464 &cur_pw, last_set_time, _prev_pw);
2465 if (ok) {
2466 struct samr_Password *previous_nt_hash = NULL;
2468 E_md4hash(cur_pw, current_nt_hash->hash);
2469 BURN_FREE_STR(cur_pw);
2471 if (prev_pw == NULL) {
2472 return true;
2475 previous_nt_hash = SMB_MALLOC_P(struct samr_Password);
2476 if (previous_nt_hash == NULL) {
2477 return false;
2480 E_md4hash(prev_pw, previous_nt_hash->hash);
2481 BURN_FREE_STR(prev_pw);
2483 *_previous_nt_hash = previous_nt_hash;
2484 return true;
2485 } else if (is_dc_trusted_domain_situation(domain)) {
2486 return false;
2489 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2491 if (secrets_fetch_trust_account_password_legacy(domain,
2492 current_nt_hash->hash,
2493 last_set_time,
2494 channel))
2496 if (account_name != NULL) {
2497 *account_name = lp_netbios_name();
2500 return true;
2503 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2504 "password for domain %s\n", domain));
2505 return False;
2508 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2509 const char **account_name,
2510 enum netr_SchannelType *channel)
2512 struct samr_Password current_nt_hash;
2513 bool ok;
2515 ok = get_trust_pw_hash2(domain, account_name, channel,
2516 &current_nt_hash, NULL, NULL);
2517 if (!ok) {
2518 return false;
2521 memcpy(ret_pwd, current_nt_hash.hash, sizeof(current_nt_hash.hash));
2522 return true;
2525 NTSTATUS pdb_get_trust_credentials(const char *netbios_domain,
2526 const char *dns_domain, /* optional */
2527 TALLOC_CTX *mem_ctx,
2528 struct cli_credentials **_creds)
2530 TALLOC_CTX *frame = talloc_stackframe();
2531 NTSTATUS status;
2532 struct loadparm_context *lp_ctx;
2533 enum netr_SchannelType channel;
2534 time_t last_set_time;
2535 const char *_account_name;
2536 const char *account_name;
2537 char *cur_pw = NULL;
2538 char *prev_pw = NULL;
2539 struct samr_Password cur_nt_hash;
2540 struct cli_credentials *creds = NULL;
2541 bool ok;
2544 * If this is our primary trust relationship, use the common
2545 * code to read the secrets.ldb or secrets.tdb file.
2547 if (strequal(netbios_domain, lp_workgroup())) {
2548 struct db_context *db_ctx = secrets_db_ctx();
2549 if (db_ctx == NULL) {
2550 DEBUG(1, ("failed to open secrets.tdb to obtain our trust credentials for %s\n",
2551 netbios_domain));
2552 status = NT_STATUS_INTERNAL_ERROR;
2553 goto fail;
2556 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2557 if (lp_ctx == NULL) {
2558 DEBUG(1, ("loadparm_init_s3 failed\n"));
2559 status = NT_STATUS_INTERNAL_ERROR;
2560 goto fail;
2563 creds = cli_credentials_init(mem_ctx);
2564 if (creds == NULL) {
2565 status = NT_STATUS_NO_MEMORY;
2566 goto fail;
2569 ok = cli_credentials_set_conf(creds, lp_ctx);
2570 if (!ok) {
2571 status = NT_STATUS_INTERNAL_ERROR;
2572 goto fail;
2575 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2576 if (!ok) {
2577 status = NT_STATUS_NO_MEMORY;
2578 goto fail;
2581 status = cli_credentials_set_machine_account_db_ctx(creds,
2582 lp_ctx,
2583 db_ctx);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 goto fail;
2587 goto done;
2588 } else if (!IS_DC) {
2589 DEBUG(1, ("Refusing to get trust account info for %s, "
2590 "which is not our primary domain %s, "
2591 "as we are not a DC\n",
2592 netbios_domain, lp_workgroup()));
2593 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2594 goto fail;
2597 status = pdb_get_trusteddom_creds(netbios_domain, mem_ctx, &creds);
2598 if (NT_STATUS_IS_OK(status)) {
2599 goto done;
2601 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
2602 goto fail;
2605 ok = get_trust_pw_clear2(netbios_domain,
2606 &_account_name,
2607 &channel,
2608 &cur_pw,
2609 &last_set_time,
2610 &prev_pw);
2611 if (!ok) {
2612 ok = get_trust_pw_hash2(netbios_domain,
2613 &_account_name,
2614 &channel,
2615 &cur_nt_hash,
2616 &last_set_time,
2617 NULL);
2618 if (!ok) {
2619 DEBUG(1, ("get_trust_pw_*2 failed for domain[%s]\n",
2620 netbios_domain));
2621 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2622 goto fail;
2626 account_name = talloc_asprintf(frame, "%s$", _account_name);
2627 if (account_name == NULL) {
2628 status = NT_STATUS_NO_MEMORY;
2629 goto fail;
2632 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
2633 if (lp_ctx == NULL) {
2634 DEBUG(1, ("loadparm_init_s3 failed\n"));
2635 status = NT_STATUS_INTERNAL_ERROR;
2636 goto fail;
2639 creds = cli_credentials_init(mem_ctx);
2640 if (creds == NULL) {
2641 status = NT_STATUS_NO_MEMORY;
2642 goto fail;
2645 ok = cli_credentials_set_conf(creds, lp_ctx);
2646 if (!ok) {
2647 status = NT_STATUS_INTERNAL_ERROR;
2648 goto fail;
2651 cli_credentials_set_secure_channel_type(creds, channel);
2652 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2654 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2655 if (!ok) {
2656 status = NT_STATUS_NO_MEMORY;
2657 goto fail;
2660 if (dns_domain != NULL) {
2661 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2662 if (!ok) {
2663 status = NT_STATUS_NO_MEMORY;
2664 goto fail;
2668 * It's not possible to use NTLMSSP with a domain trust account.
2670 cli_credentials_set_kerberos_state(creds,
2671 CRED_USE_KERBEROS_REQUIRED,
2672 CRED_SPECIFIED);
2673 } else {
2675 * We can't use kerberos against an NT4 domain.
2677 * We should have a mode that also disallows NTLMSSP here,
2678 * as only NETLOGON SCHANNEL is possible.
2680 cli_credentials_set_kerberos_state(creds,
2681 CRED_USE_KERBEROS_DISABLED,
2682 CRED_SPECIFIED);
2685 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2686 if (!ok) {
2687 status = NT_STATUS_NO_MEMORY;
2688 goto fail;
2691 if (cur_pw == NULL) {
2692 ok = cli_credentials_set_nt_hash(creds, &cur_nt_hash, CRED_SPECIFIED);
2693 if (!ok) {
2694 status = NT_STATUS_NO_MEMORY;
2695 goto fail;
2698 * We currently can't do kerberos just with an NTHASH.
2700 cli_credentials_set_kerberos_state(creds,
2701 CRED_USE_KERBEROS_DISABLED,
2702 CRED_SPECIFIED);
2703 goto done;
2706 ok = cli_credentials_set_password(creds, cur_pw, CRED_SPECIFIED);
2707 if (!ok) {
2708 status = NT_STATUS_NO_MEMORY;
2709 goto fail;
2712 if (prev_pw != NULL) {
2713 ok = cli_credentials_set_old_password(creds, prev_pw, CRED_SPECIFIED);
2714 if (!ok) {
2715 status = NT_STATUS_NO_MEMORY;
2716 goto fail;
2720 done:
2721 *_creds = creds;
2722 creds = NULL;
2723 status = NT_STATUS_OK;
2724 fail:
2725 TALLOC_FREE(creds);
2726 SAFE_FREE(cur_pw);
2727 SAFE_FREE(prev_pw);
2728 TALLOC_FREE(frame);
2729 return status;