build: check for pam headers
[Samba.git] / source3 / passdb / passdb.c
blob0adefd5c6de478fbe31cedd93ac32a7a6db6a456
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 "../libcli/auth/libcli_auth.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 /******************************************************************
32 Get the default domain/netbios name to be used when
33 testing authentication.
35 LEGACY: this function provides the legacy domain mapping used with
36 the lp_map_untrusted_to_domain() parameter
37 ******************************************************************/
39 const char *my_sam_name(void)
41 /* Standalone servers can only use the local netbios name */
42 if ( lp_server_role() == ROLE_STANDALONE )
43 return global_myname();
45 /* Default to the DOMAIN name when not specified */
46 return lp_workgroup();
49 /**********************************************************************
50 ***********************************************************************/
52 static int samu_destroy(struct samu *user)
54 data_blob_clear_free( &user->lm_pw );
55 data_blob_clear_free( &user->nt_pw );
57 if ( user->plaintext_pw )
58 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
60 return 0;
63 /**********************************************************************
64 generate a new struct samuser
65 ***********************************************************************/
67 struct samu *samu_new( TALLOC_CTX *ctx )
69 struct samu *user;
71 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
72 DEBUG(0,("samuser_new: Talloc failed!\n"));
73 return NULL;
76 talloc_set_destructor( user, samu_destroy );
78 /* no initial methods */
80 user->methods = NULL;
82 /* Don't change these timestamp settings without a good reason.
83 They are important for NT member server compatibility. */
85 user->logon_time = (time_t)0;
86 user->pass_last_set_time = (time_t)0;
87 user->pass_can_change_time = (time_t)0;
88 user->logoff_time = get_time_t_max();
89 user->kickoff_time = get_time_t_max();
90 user->pass_must_change_time = get_time_t_max();
91 user->fields_present = 0x00ffffff;
92 user->logon_divs = 168; /* hours per week */
93 user->hours_len = 21; /* 21 times 8 bits = 168 */
94 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
95 user->bad_password_count = 0;
96 user->logon_count = 0;
97 user->unknown_6 = 0x000004ec; /* don't know */
99 /* Some parts of samba strlen their pdb_get...() returns,
100 so this keeps the interface unchanged for now. */
102 user->username = "";
103 user->domain = "";
104 user->nt_username = "";
105 user->full_name = "";
106 user->home_dir = "";
107 user->logon_script = "";
108 user->profile_path = "";
109 user->acct_desc = "";
110 user->workstations = "";
111 user->comment = "";
112 user->munged_dial = "";
114 user->plaintext_pw = NULL;
116 /* Unless we know otherwise have a Account Control Bit
117 value of 'normal user'. This helps User Manager, which
118 asks for a filtered list of users. */
120 user->acct_ctrl = ACB_NORMAL;
122 return user;
125 static int count_commas(const char *str)
127 int num_commas = 0;
128 const char *comma = str;
130 while ((comma = strchr(comma, ',')) != NULL) {
131 comma += 1;
132 num_commas += 1;
134 return num_commas;
137 /*********************************************************************
138 Initialize a struct samu from a struct passwd including the user
139 and group SIDs. The *user structure is filled out with the Unix
140 attributes and a user SID.
141 *********************************************************************/
143 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
145 const char *guest_account = lp_guestaccount();
146 const char *domain = global_myname();
147 char *fullname;
148 uint32 urid;
150 if ( !pwd ) {
151 return NT_STATUS_NO_SUCH_USER;
154 /* Basic properties based upon the Unix account information */
156 pdb_set_username(user, pwd->pw_name, PDB_SET);
158 fullname = NULL;
160 if (count_commas(pwd->pw_gecos) == 3) {
162 * Heuristic: This seems to be a gecos field that has been
163 * edited by chfn(1). Only use the part before the first
164 * comma. Fixes bug 5198.
166 fullname = talloc_strndup(
167 talloc_tos(), pwd->pw_gecos,
168 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
171 if (fullname != NULL) {
172 pdb_set_fullname(user, fullname, PDB_SET);
173 } else {
174 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
176 TALLOC_FREE(fullname);
178 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
179 #if 0
180 /* This can lead to a primary group of S-1-22-2-XX which
181 will be rejected by other parts of the Samba code.
182 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
183 --jerry */
185 gid_to_sid(&group_sid, pwd->pw_gid);
186 pdb_set_group_sid(user, &group_sid, PDB_SET);
187 #endif
189 /* save the password structure for later use */
191 user->unix_pw = tcopy_passwd( user, pwd );
193 /* Special case for the guest account which must have a RID of 501 */
195 if ( strequal( pwd->pw_name, guest_account ) ) {
196 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
197 return NT_STATUS_NO_SUCH_USER;
199 return NT_STATUS_OK;
202 /* Non-guest accounts...Check for a workstation or user account */
204 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
205 /* workstation */
207 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
208 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
209 pwd->pw_name));
210 return NT_STATUS_INVALID_COMPUTER_NAME;
213 else {
214 /* user */
216 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
217 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
218 pwd->pw_name));
219 return NT_STATUS_INVALID_ACCOUNT_NAME;
222 /* set some basic attributes */
224 pdb_set_profile_path(user, talloc_sub_specified(user,
225 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
226 PDB_DEFAULT);
227 pdb_set_homedir(user, talloc_sub_specified(user,
228 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
229 PDB_DEFAULT);
230 pdb_set_dir_drive(user, talloc_sub_specified(user,
231 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
232 PDB_DEFAULT);
233 pdb_set_logon_script(user, talloc_sub_specified(user,
234 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
235 PDB_DEFAULT);
238 /* Now deal with the user SID. If we have a backend that can generate
239 RIDs, then do so. But sometimes the caller just wanted a structure
240 initialized and will fill in these fields later (such as from a
241 netr_SamInfo3 structure) */
243 if ( create && (pdb_capabilities() & PDB_CAP_STORE_RIDS)) {
244 uint32 user_rid;
245 DOM_SID user_sid;
247 if ( !pdb_new_rid( &user_rid ) ) {
248 DEBUG(3, ("Could not allocate a new RID\n"));
249 return NT_STATUS_ACCESS_DENIED;
252 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
254 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
255 DEBUG(3, ("pdb_set_user_sid failed\n"));
256 return NT_STATUS_INTERNAL_ERROR;
259 return NT_STATUS_OK;
262 /* generate a SID for the user with the RID algorithm */
264 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
266 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
267 return NT_STATUS_INTERNAL_ERROR;
270 return NT_STATUS_OK;
273 /********************************************************************
274 Set the Unix user attributes
275 ********************************************************************/
277 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
279 return samu_set_unix_internal( user, pwd, False );
282 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
284 return samu_set_unix_internal( user, pwd, True );
287 /**********************************************************
288 Encode the account control bits into a string.
289 length = length of string to encode into (including terminating
290 null). length *MUST BE MORE THAN 2* !
291 **********************************************************/
293 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
295 fstring acct_str;
296 char *result;
298 size_t i = 0;
300 SMB_ASSERT(length <= sizeof(acct_str));
302 acct_str[i++] = '[';
304 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
305 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
306 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
307 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
308 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
309 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
310 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
311 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
312 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
313 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
314 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
316 for ( ; i < length - 2 ; i++ )
317 acct_str[i] = ' ';
319 i = length - 2;
320 acct_str[i++] = ']';
321 acct_str[i++] = '\0';
323 result = talloc_strdup(talloc_tos(), acct_str);
324 SMB_ASSERT(result != NULL);
325 return result;
328 /**********************************************************
329 Decode the account control bits from a string.
330 **********************************************************/
332 uint32_t pdb_decode_acct_ctrl(const char *p)
334 uint32_t acct_ctrl = 0;
335 bool finished = false;
338 * Check if the account type bits have been encoded after the
339 * NT password (in the form [NDHTUWSLXI]).
342 if (*p != '[')
343 return 0;
345 for (p++; *p && !finished; p++) {
346 switch (*p) {
347 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
348 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
349 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
350 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
351 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
352 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
353 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
354 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
355 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
356 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
357 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
358 case ' ': { break; }
359 case ':':
360 case '\n':
361 case '\0':
362 case ']':
363 default: { finished = true; }
367 return acct_ctrl;
370 /*************************************************************
371 Routine to set 32 hex password characters from a 16 byte array.
372 **************************************************************/
374 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
376 if (pwd != NULL) {
377 int i;
378 for (i = 0; i < 16; i++)
379 slprintf(&p[i*2], 3, "%02X", pwd[i]);
380 } else {
381 if (acct_ctrl & ACB_PWNOTREQ)
382 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
383 else
384 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
388 /*************************************************************
389 Routine to get the 32 hex characters and turn them
390 into a 16 byte array.
391 **************************************************************/
393 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
395 int i;
396 unsigned char lonybble, hinybble;
397 const char *hexchars = "0123456789ABCDEF";
398 char *p1, *p2;
400 if (!p)
401 return false;
403 for (i = 0; i < 32; i += 2) {
404 hinybble = toupper_ascii(p[i]);
405 lonybble = toupper_ascii(p[i + 1]);
407 p1 = strchr(hexchars, hinybble);
408 p2 = strchr(hexchars, lonybble);
410 if (!p1 || !p2)
411 return false;
413 hinybble = PTR_DIFF(p1, hexchars);
414 lonybble = PTR_DIFF(p2, hexchars);
416 pwd[i / 2] = (hinybble << 4) | lonybble;
418 return true;
421 /*************************************************************
422 Routine to set 42 hex hours characters from a 21 byte array.
423 **************************************************************/
425 void pdb_sethexhours(char *p, const unsigned char *hours)
427 if (hours != NULL) {
428 int i;
429 for (i = 0; i < 21; i++) {
430 slprintf(&p[i*2], 3, "%02X", hours[i]);
432 } else {
433 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
437 /*************************************************************
438 Routine to get the 42 hex characters and turn them
439 into a 21 byte array.
440 **************************************************************/
442 bool pdb_gethexhours(const char *p, unsigned char *hours)
444 int i;
445 unsigned char lonybble, hinybble;
446 const char *hexchars = "0123456789ABCDEF";
447 char *p1, *p2;
449 if (!p) {
450 return (False);
453 for (i = 0; i < 42; i += 2) {
454 hinybble = toupper_ascii(p[i]);
455 lonybble = toupper_ascii(p[i + 1]);
457 p1 = strchr(hexchars, hinybble);
458 p2 = strchr(hexchars, lonybble);
460 if (!p1 || !p2) {
461 return (False);
464 hinybble = PTR_DIFF(p1, hexchars);
465 lonybble = PTR_DIFF(p2, hexchars);
467 hours[i / 2] = (hinybble << 4) | lonybble;
469 return (True);
472 /********************************************************************
473 ********************************************************************/
475 int algorithmic_rid_base(void)
477 int rid_offset;
479 rid_offset = lp_algorithmic_rid_base();
481 if (rid_offset < BASE_RID) {
482 /* Try to prevent admin foot-shooting, we can't put algorithmic
483 rids below 1000, that's the 'well known RIDs' on NT */
484 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
485 rid_offset = BASE_RID;
487 if (rid_offset & 1) {
488 DEBUG(0, ("algorithmic rid base must be even\n"));
489 rid_offset += 1;
491 return rid_offset;
494 /*******************************************************************
495 Converts NT user RID to a UNIX uid.
496 ********************************************************************/
498 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
500 int rid_offset = algorithmic_rid_base();
501 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
504 uid_t max_algorithmic_uid(void)
506 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
509 /*******************************************************************
510 converts UNIX uid to an NT User RID.
511 ********************************************************************/
513 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
515 int rid_offset = algorithmic_rid_base();
516 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
519 /*******************************************************************
520 Converts NT group RID to a UNIX gid.
521 ********************************************************************/
523 gid_t pdb_group_rid_to_gid(uint32 group_rid)
525 int rid_offset = algorithmic_rid_base();
526 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
529 gid_t max_algorithmic_gid(void)
531 return pdb_group_rid_to_gid(0xffffffff);
534 /*******************************************************************
535 converts NT Group RID to a UNIX uid.
537 warning: you must not call that function only
538 you must do a call to the group mapping first.
539 there is not anymore a direct link between the gid and the rid.
540 ********************************************************************/
542 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
544 int rid_offset = algorithmic_rid_base();
545 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
548 /*******************************************************************
549 Decides if a RID is a well known RID.
550 ********************************************************************/
552 static bool rid_is_well_known(uint32 rid)
554 /* Not using rid_offset here, because this is the actual
555 NT fixed value (1000) */
557 return (rid < BASE_RID);
560 /*******************************************************************
561 Decides if a RID is a user or group RID.
562 ********************************************************************/
564 bool algorithmic_pdb_rid_is_user(uint32 rid)
566 if ( rid_is_well_known(rid) ) {
568 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
569 * and DOMAIN_USER_RID_GUEST.
571 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
572 return True;
573 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
574 return True;
576 return False;
579 /*******************************************************************
580 Convert a name into a SID. Used in the lookup name rpc.
581 ********************************************************************/
583 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
584 enum lsa_SidType *type)
586 GROUP_MAP map;
587 bool ret;
589 /* Windows treats "MACHINE\None" as a special name for
590 rid 513 on non-DCs. You cannot create a user or group
591 name "None" on Windows. You will get an error that
592 the group already exists. */
594 if ( strequal( name, "None" ) ) {
595 *rid = DOMAIN_GROUP_RID_USERS;
596 *type = SID_NAME_DOM_GRP;
598 return True;
601 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
602 * correctly in the case where foo also exists as a user. If the flag
603 * is set, don't look for users at all. */
605 if ((flags & LOOKUP_NAME_GROUP) == 0) {
606 struct samu *sam_account = NULL;
607 DOM_SID user_sid;
609 if ( !(sam_account = samu_new( NULL )) ) {
610 return False;
613 become_root();
614 ret = pdb_getsampwnam(sam_account, name);
615 unbecome_root();
617 if (ret) {
618 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
621 TALLOC_FREE(sam_account);
623 if (ret) {
624 if (!sid_check_is_in_our_domain(&user_sid)) {
625 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
626 name, sid_string_dbg(&user_sid)));
627 return False;
630 sid_peek_rid(&user_sid, rid);
631 *type = SID_NAME_USER;
632 return True;
637 * Maybe it is a group ?
640 become_root();
641 ret = pdb_getgrnam(&map, name);
642 unbecome_root();
644 if (!ret) {
645 return False;
648 /* BUILTIN groups are looked up elsewhere */
649 if (!sid_check_is_in_our_domain(&map.sid)) {
650 DEBUG(10, ("Found group %s (%s) not in our domain -- "
651 "ignoring.", name, sid_string_dbg(&map.sid)));
652 return False;
655 /* yes it's a mapped group */
656 sid_peek_rid(&map.sid, rid);
657 *type = map.sid_name_use;
658 return True;
661 /*************************************************************
662 Change a password entry in the local passdb backend.
664 Assumptions:
665 - always called as root
666 - ignores the account type except when adding a new account
667 - will create/delete the unix account if the relative
668 add/delete user script is configured
670 *************************************************************/
672 NTSTATUS local_password_change(const char *user_name,
673 int local_flags,
674 const char *new_passwd,
675 char **pp_err_str,
676 char **pp_msg_str)
678 TALLOC_CTX *tosctx;
679 struct samu *sam_pass;
680 uint32_t acb;
681 uint32_t rid;
682 NTSTATUS result;
683 bool user_exists;
684 int ret = -1;
686 *pp_err_str = NULL;
687 *pp_msg_str = NULL;
689 tosctx = talloc_tos();
691 sam_pass = samu_new(tosctx);
692 if (!sam_pass) {
693 result = NT_STATUS_NO_MEMORY;
694 goto done;
697 /* Get the smb passwd entry for this user */
698 user_exists = pdb_getsampwnam(sam_pass, user_name);
700 /* Check delete first, we don't need to do anything else if we
701 * are going to delete the acocunt */
702 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
704 result = pdb_delete_user(tosctx, sam_pass);
705 if (!NT_STATUS_IS_OK(result)) {
706 ret = asprintf(pp_err_str,
707 "Failed to delete entry for user %s.\n",
708 user_name);
709 if (ret < 0) {
710 *pp_err_str = NULL;
712 result = NT_STATUS_UNSUCCESSFUL;
713 } else {
714 ret = asprintf(pp_msg_str,
715 "Deleted user %s.\n",
716 user_name);
717 if (ret < 0) {
718 *pp_msg_str = NULL;
721 goto done;
724 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
725 /* the entry already existed */
726 local_flags &= ~LOCAL_ADD_USER;
729 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
730 ret = asprintf(pp_err_str,
731 "Failed to find entry for user %s.\n",
732 user_name);
733 if (ret < 0) {
734 *pp_err_str = NULL;
736 result = NT_STATUS_NO_SUCH_USER;
737 goto done;
740 /* First thing add the new user if we are required to do so */
741 if (local_flags & LOCAL_ADD_USER) {
743 if (local_flags & LOCAL_TRUST_ACCOUNT) {
744 acb = ACB_WSTRUST;
745 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
746 acb = ACB_DOMTRUST;
747 } else {
748 acb = ACB_NORMAL;
751 result = pdb_create_user(tosctx, user_name, acb, &rid);
752 if (!NT_STATUS_IS_OK(result)) {
753 ret = asprintf(pp_err_str,
754 "Failed to add entry for user %s.\n",
755 user_name);
756 if (ret < 0) {
757 *pp_err_str = NULL;
759 result = NT_STATUS_UNSUCCESSFUL;
760 goto done;
763 sam_pass = samu_new(tosctx);
764 if (!sam_pass) {
765 result = NT_STATUS_NO_MEMORY;
766 goto done;
769 /* Now get back the smb passwd entry for this new user */
770 user_exists = pdb_getsampwnam(sam_pass, user_name);
771 if (!user_exists) {
772 ret = asprintf(pp_err_str,
773 "Failed to add entry for user %s.\n",
774 user_name);
775 if (ret < 0) {
776 *pp_err_str = NULL;
778 result = NT_STATUS_UNSUCCESSFUL;
779 goto done;
783 acb = pdb_get_acct_ctrl(sam_pass);
786 * We are root - just write the new password
787 * and the valid last change time.
789 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
790 acb |= ACB_PWNOTREQ;
791 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
792 ret = asprintf(pp_err_str,
793 "Failed to set 'no password required' "
794 "flag for user %s.\n", user_name);
795 if (ret < 0) {
796 *pp_err_str = NULL;
798 result = NT_STATUS_UNSUCCESSFUL;
799 goto done;
803 if (local_flags & LOCAL_SET_PASSWORD) {
805 * If we're dealing with setting a completely empty user account
806 * ie. One with a password of 'XXXX', but not set disabled (like
807 * an account created from scratch) then if the old password was
808 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
809 * We remove that as we're giving this user their first password
810 * and the decision hasn't really been made to disable them (ie.
811 * don't create them disabled). JRA.
813 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
814 (acb & ACB_DISABLED)) {
815 acb &= (~ACB_DISABLED);
816 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
817 ret = asprintf(pp_err_str,
818 "Failed to unset 'disabled' "
819 "flag for user %s.\n",
820 user_name);
821 if (ret < 0) {
822 *pp_err_str = NULL;
824 result = NT_STATUS_UNSUCCESSFUL;
825 goto done;
829 acb &= (~ACB_PWNOTREQ);
830 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
831 ret = asprintf(pp_err_str,
832 "Failed to unset 'no password required'"
833 " flag for user %s.\n", user_name);
834 if (ret < 0) {
835 *pp_err_str = NULL;
837 result = NT_STATUS_UNSUCCESSFUL;
838 goto done;
841 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
842 ret = asprintf(pp_err_str,
843 "Failed to set password for "
844 "user %s.\n", user_name);
845 if (ret < 0) {
846 *pp_err_str = NULL;
848 result = NT_STATUS_UNSUCCESSFUL;
849 goto done;
853 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
854 acb |= ACB_DISABLED;
855 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
856 ret = asprintf(pp_err_str,
857 "Failed to set 'disabled' flag for "
858 "user %s.\n", user_name);
859 if (ret < 0) {
860 *pp_err_str = NULL;
862 result = NT_STATUS_UNSUCCESSFUL;
863 goto done;
867 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
868 acb &= (~ACB_DISABLED);
869 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
870 ret = asprintf(pp_err_str,
871 "Failed to unset 'disabled' flag for "
872 "user %s.\n", user_name);
873 if (ret < 0) {
874 *pp_err_str = NULL;
876 result = NT_STATUS_UNSUCCESSFUL;
877 goto done;
881 /* now commit changes if any */
882 result = pdb_update_sam_account(sam_pass);
883 if (!NT_STATUS_IS_OK(result)) {
884 ret = asprintf(pp_err_str,
885 "Failed to modify entry for user %s.\n",
886 user_name);
887 if (ret < 0) {
888 *pp_err_str = NULL;
890 goto done;
893 if (local_flags & LOCAL_ADD_USER) {
894 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
895 } else if (local_flags & LOCAL_DISABLE_USER) {
896 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
897 } else if (local_flags & LOCAL_ENABLE_USER) {
898 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
899 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
900 ret = asprintf(pp_msg_str,
901 "User %s password set to none.\n", user_name);
904 if (ret < 0) {
905 *pp_msg_str = NULL;
908 result = NT_STATUS_OK;
910 done:
911 TALLOC_FREE(sam_pass);
912 return result;
915 /**********************************************************************
916 Marshall/unmarshall struct samu structs.
917 *********************************************************************/
919 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
920 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
921 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
922 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
923 /* nothing changed between V3 and V4 */
925 /*********************************************************************
926 *********************************************************************/
928 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
931 /* times are stored as 32bit integer
932 take care on system with 64bit wide time_t
933 --SSS */
934 uint32 logon_time,
935 logoff_time,
936 kickoff_time,
937 pass_last_set_time,
938 pass_can_change_time,
939 pass_must_change_time;
940 char *username = NULL;
941 char *domain = NULL;
942 char *nt_username = NULL;
943 char *dir_drive = NULL;
944 char *unknown_str = NULL;
945 char *munged_dial = NULL;
946 char *fullname = NULL;
947 char *homedir = NULL;
948 char *logon_script = NULL;
949 char *profile_path = NULL;
950 char *acct_desc = NULL;
951 char *workstations = NULL;
952 uint32 username_len, domain_len, nt_username_len,
953 dir_drive_len, unknown_str_len, munged_dial_len,
954 fullname_len, homedir_len, logon_script_len,
955 profile_path_len, acct_desc_len, workstations_len;
957 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
958 uint16 acct_ctrl, logon_divs;
959 uint16 bad_password_count, logon_count;
960 uint8 *hours = NULL;
961 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
962 uint32 len = 0;
963 uint32 lm_pw_len, nt_pw_len, hourslen;
964 bool ret = True;
966 if(sampass == NULL || buf == NULL) {
967 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
968 return False;
971 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
973 /* unpack the buffer into variables */
974 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
975 &logon_time, /* d */
976 &logoff_time, /* d */
977 &kickoff_time, /* d */
978 &pass_last_set_time, /* d */
979 &pass_can_change_time, /* d */
980 &pass_must_change_time, /* d */
981 &username_len, &username, /* B */
982 &domain_len, &domain, /* B */
983 &nt_username_len, &nt_username, /* B */
984 &fullname_len, &fullname, /* B */
985 &homedir_len, &homedir, /* B */
986 &dir_drive_len, &dir_drive, /* B */
987 &logon_script_len, &logon_script, /* B */
988 &profile_path_len, &profile_path, /* B */
989 &acct_desc_len, &acct_desc, /* B */
990 &workstations_len, &workstations, /* B */
991 &unknown_str_len, &unknown_str, /* B */
992 &munged_dial_len, &munged_dial, /* B */
993 &user_rid, /* d */
994 &group_rid, /* d */
995 &lm_pw_len, &lm_pw_ptr, /* B */
996 &nt_pw_len, &nt_pw_ptr, /* B */
997 &acct_ctrl, /* w */
998 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
999 &logon_divs, /* w */
1000 &hours_len, /* d */
1001 &hourslen, &hours, /* B */
1002 &bad_password_count, /* w */
1003 &logon_count, /* w */
1004 &unknown_6); /* d */
1006 if (len == (uint32) -1) {
1007 ret = False;
1008 goto done;
1011 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1012 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1013 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1014 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1015 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1016 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1018 pdb_set_username(sampass, username, PDB_SET);
1019 pdb_set_domain(sampass, domain, PDB_SET);
1020 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1021 pdb_set_fullname(sampass, fullname, PDB_SET);
1023 if (homedir) {
1024 pdb_set_homedir(sampass, homedir, PDB_SET);
1026 else {
1027 pdb_set_homedir(sampass,
1028 talloc_sub_basic(sampass, username, domain,
1029 lp_logon_home()),
1030 PDB_DEFAULT);
1033 if (dir_drive)
1034 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1035 else {
1036 pdb_set_dir_drive(sampass,
1037 talloc_sub_basic(sampass, username, domain,
1038 lp_logon_drive()),
1039 PDB_DEFAULT);
1042 if (logon_script)
1043 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1044 else {
1045 pdb_set_logon_script(sampass,
1046 talloc_sub_basic(sampass, username, domain,
1047 lp_logon_script()),
1048 PDB_DEFAULT);
1051 if (profile_path) {
1052 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1053 } else {
1054 pdb_set_profile_path(sampass,
1055 talloc_sub_basic(sampass, username, domain,
1056 lp_logon_path()),
1057 PDB_DEFAULT);
1060 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1061 pdb_set_workstations(sampass, workstations, PDB_SET);
1062 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1064 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1065 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1066 ret = False;
1067 goto done;
1071 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1072 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1073 ret = False;
1074 goto done;
1078 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1079 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1080 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1081 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1082 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1083 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1084 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1085 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1086 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1087 pdb_set_hours(sampass, hours, PDB_SET);
1089 done:
1091 SAFE_FREE(username);
1092 SAFE_FREE(domain);
1093 SAFE_FREE(nt_username);
1094 SAFE_FREE(fullname);
1095 SAFE_FREE(homedir);
1096 SAFE_FREE(dir_drive);
1097 SAFE_FREE(logon_script);
1098 SAFE_FREE(profile_path);
1099 SAFE_FREE(acct_desc);
1100 SAFE_FREE(workstations);
1101 SAFE_FREE(munged_dial);
1102 SAFE_FREE(unknown_str);
1103 SAFE_FREE(lm_pw_ptr);
1104 SAFE_FREE(nt_pw_ptr);
1105 SAFE_FREE(hours);
1107 return ret;
1110 /*********************************************************************
1111 *********************************************************************/
1113 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1116 /* times are stored as 32bit integer
1117 take care on system with 64bit wide time_t
1118 --SSS */
1119 uint32 logon_time,
1120 logoff_time,
1121 kickoff_time,
1122 bad_password_time,
1123 pass_last_set_time,
1124 pass_can_change_time,
1125 pass_must_change_time;
1126 char *username = NULL;
1127 char *domain = NULL;
1128 char *nt_username = NULL;
1129 char *dir_drive = NULL;
1130 char *unknown_str = NULL;
1131 char *munged_dial = NULL;
1132 char *fullname = NULL;
1133 char *homedir = NULL;
1134 char *logon_script = NULL;
1135 char *profile_path = NULL;
1136 char *acct_desc = NULL;
1137 char *workstations = NULL;
1138 uint32 username_len, domain_len, nt_username_len,
1139 dir_drive_len, unknown_str_len, munged_dial_len,
1140 fullname_len, homedir_len, logon_script_len,
1141 profile_path_len, acct_desc_len, workstations_len;
1143 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1144 uint16 acct_ctrl, logon_divs;
1145 uint16 bad_password_count, logon_count;
1146 uint8 *hours = NULL;
1147 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1148 uint32 len = 0;
1149 uint32 lm_pw_len, nt_pw_len, hourslen;
1150 bool ret = True;
1152 if(sampass == NULL || buf == NULL) {
1153 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1154 return False;
1157 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1159 /* unpack the buffer into variables */
1160 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1161 &logon_time, /* d */
1162 &logoff_time, /* d */
1163 &kickoff_time, /* d */
1164 /* Change from V0 is addition of bad_password_time field. */
1165 &bad_password_time, /* d */
1166 &pass_last_set_time, /* d */
1167 &pass_can_change_time, /* d */
1168 &pass_must_change_time, /* d */
1169 &username_len, &username, /* B */
1170 &domain_len, &domain, /* B */
1171 &nt_username_len, &nt_username, /* B */
1172 &fullname_len, &fullname, /* B */
1173 &homedir_len, &homedir, /* B */
1174 &dir_drive_len, &dir_drive, /* B */
1175 &logon_script_len, &logon_script, /* B */
1176 &profile_path_len, &profile_path, /* B */
1177 &acct_desc_len, &acct_desc, /* B */
1178 &workstations_len, &workstations, /* B */
1179 &unknown_str_len, &unknown_str, /* B */
1180 &munged_dial_len, &munged_dial, /* B */
1181 &user_rid, /* d */
1182 &group_rid, /* d */
1183 &lm_pw_len, &lm_pw_ptr, /* B */
1184 &nt_pw_len, &nt_pw_ptr, /* B */
1185 &acct_ctrl, /* w */
1186 &remove_me, /* d */
1187 &logon_divs, /* w */
1188 &hours_len, /* d */
1189 &hourslen, &hours, /* B */
1190 &bad_password_count, /* w */
1191 &logon_count, /* w */
1192 &unknown_6); /* d */
1194 if (len == (uint32) -1) {
1195 ret = False;
1196 goto done;
1199 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1200 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1201 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1203 /* Change from V0 is addition of bad_password_time field. */
1204 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1205 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1206 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1207 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1209 pdb_set_username(sampass, username, PDB_SET);
1210 pdb_set_domain(sampass, domain, PDB_SET);
1211 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1212 pdb_set_fullname(sampass, fullname, PDB_SET);
1214 if (homedir) {
1215 pdb_set_homedir(sampass, homedir, PDB_SET);
1217 else {
1218 pdb_set_homedir(sampass,
1219 talloc_sub_basic(sampass, username, domain,
1220 lp_logon_home()),
1221 PDB_DEFAULT);
1224 if (dir_drive)
1225 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1226 else {
1227 pdb_set_dir_drive(sampass,
1228 talloc_sub_basic(sampass, username, domain,
1229 lp_logon_drive()),
1230 PDB_DEFAULT);
1233 if (logon_script)
1234 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1235 else {
1236 pdb_set_logon_script(sampass,
1237 talloc_sub_basic(sampass, username, domain,
1238 lp_logon_script()),
1239 PDB_DEFAULT);
1242 if (profile_path) {
1243 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1244 } else {
1245 pdb_set_profile_path(sampass,
1246 talloc_sub_basic(sampass, username, domain,
1247 lp_logon_path()),
1248 PDB_DEFAULT);
1251 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1252 pdb_set_workstations(sampass, workstations, PDB_SET);
1253 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1255 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1256 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1257 ret = False;
1258 goto done;
1262 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1263 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1264 ret = False;
1265 goto done;
1269 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1271 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1272 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1273 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1274 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1275 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1276 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1277 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1278 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1279 pdb_set_hours(sampass, hours, PDB_SET);
1281 done:
1283 SAFE_FREE(username);
1284 SAFE_FREE(domain);
1285 SAFE_FREE(nt_username);
1286 SAFE_FREE(fullname);
1287 SAFE_FREE(homedir);
1288 SAFE_FREE(dir_drive);
1289 SAFE_FREE(logon_script);
1290 SAFE_FREE(profile_path);
1291 SAFE_FREE(acct_desc);
1292 SAFE_FREE(workstations);
1293 SAFE_FREE(munged_dial);
1294 SAFE_FREE(unknown_str);
1295 SAFE_FREE(lm_pw_ptr);
1296 SAFE_FREE(nt_pw_ptr);
1297 SAFE_FREE(hours);
1299 return ret;
1302 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1305 /* times are stored as 32bit integer
1306 take care on system with 64bit wide time_t
1307 --SSS */
1308 uint32 logon_time,
1309 logoff_time,
1310 kickoff_time,
1311 bad_password_time,
1312 pass_last_set_time,
1313 pass_can_change_time,
1314 pass_must_change_time;
1315 char *username = NULL;
1316 char *domain = NULL;
1317 char *nt_username = NULL;
1318 char *dir_drive = NULL;
1319 char *unknown_str = NULL;
1320 char *munged_dial = NULL;
1321 char *fullname = NULL;
1322 char *homedir = NULL;
1323 char *logon_script = NULL;
1324 char *profile_path = NULL;
1325 char *acct_desc = NULL;
1326 char *workstations = NULL;
1327 uint32 username_len, domain_len, nt_username_len,
1328 dir_drive_len, unknown_str_len, munged_dial_len,
1329 fullname_len, homedir_len, logon_script_len,
1330 profile_path_len, acct_desc_len, workstations_len;
1332 uint32 user_rid, group_rid, hours_len, unknown_6;
1333 uint16 acct_ctrl, logon_divs;
1334 uint16 bad_password_count, logon_count;
1335 uint8 *hours = NULL;
1336 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1337 uint32 len = 0;
1338 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1339 uint32 pwHistLen = 0;
1340 bool ret = True;
1341 fstring tmp_string;
1342 bool expand_explicit = lp_passdb_expand_explicit();
1344 if(sampass == NULL || buf == NULL) {
1345 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1346 return False;
1349 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1351 /* unpack the buffer into variables */
1352 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1353 &logon_time, /* d */
1354 &logoff_time, /* d */
1355 &kickoff_time, /* d */
1356 &bad_password_time, /* d */
1357 &pass_last_set_time, /* d */
1358 &pass_can_change_time, /* d */
1359 &pass_must_change_time, /* d */
1360 &username_len, &username, /* B */
1361 &domain_len, &domain, /* B */
1362 &nt_username_len, &nt_username, /* B */
1363 &fullname_len, &fullname, /* B */
1364 &homedir_len, &homedir, /* B */
1365 &dir_drive_len, &dir_drive, /* B */
1366 &logon_script_len, &logon_script, /* B */
1367 &profile_path_len, &profile_path, /* B */
1368 &acct_desc_len, &acct_desc, /* B */
1369 &workstations_len, &workstations, /* B */
1370 &unknown_str_len, &unknown_str, /* B */
1371 &munged_dial_len, &munged_dial, /* B */
1372 &user_rid, /* d */
1373 &group_rid, /* d */
1374 &lm_pw_len, &lm_pw_ptr, /* B */
1375 &nt_pw_len, &nt_pw_ptr, /* B */
1376 /* Change from V1 is addition of password history field. */
1377 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1378 &acct_ctrl, /* w */
1379 /* Also "remove_me" field was removed. */
1380 &logon_divs, /* w */
1381 &hours_len, /* d */
1382 &hourslen, &hours, /* B */
1383 &bad_password_count, /* w */
1384 &logon_count, /* w */
1385 &unknown_6); /* d */
1387 if (len == (uint32) -1) {
1388 ret = False;
1389 goto done;
1392 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1393 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1394 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1395 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1396 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1397 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1398 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1400 pdb_set_username(sampass, username, PDB_SET);
1401 pdb_set_domain(sampass, domain, PDB_SET);
1402 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1403 pdb_set_fullname(sampass, fullname, PDB_SET);
1405 if (homedir) {
1406 fstrcpy( tmp_string, homedir );
1407 if (expand_explicit) {
1408 standard_sub_basic( username, domain, tmp_string,
1409 sizeof(tmp_string) );
1411 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1413 else {
1414 pdb_set_homedir(sampass,
1415 talloc_sub_basic(sampass, username, domain,
1416 lp_logon_home()),
1417 PDB_DEFAULT);
1420 if (dir_drive)
1421 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1422 else
1423 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1425 if (logon_script) {
1426 fstrcpy( tmp_string, logon_script );
1427 if (expand_explicit) {
1428 standard_sub_basic( username, domain, tmp_string,
1429 sizeof(tmp_string) );
1431 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1433 else {
1434 pdb_set_logon_script(sampass,
1435 talloc_sub_basic(sampass, username, domain,
1436 lp_logon_script()),
1437 PDB_DEFAULT);
1440 if (profile_path) {
1441 fstrcpy( tmp_string, profile_path );
1442 if (expand_explicit) {
1443 standard_sub_basic( username, domain, tmp_string,
1444 sizeof(tmp_string) );
1446 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1448 else {
1449 pdb_set_profile_path(sampass,
1450 talloc_sub_basic(sampass, username, domain,
1451 lp_logon_path()),
1452 PDB_DEFAULT);
1455 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1456 pdb_set_workstations(sampass, workstations, PDB_SET);
1457 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1459 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1460 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1461 ret = False;
1462 goto done;
1466 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1467 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1468 ret = False;
1469 goto done;
1473 /* Change from V1 is addition of password history field. */
1474 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1475 if (pwHistLen) {
1476 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1477 if (!pw_hist) {
1478 ret = False;
1479 goto done;
1481 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1482 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1483 int i;
1484 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1485 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1486 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1487 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1488 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1489 PW_HISTORY_ENTRY_LEN);
1492 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1493 SAFE_FREE(pw_hist);
1494 ret = False;
1495 goto done;
1497 SAFE_FREE(pw_hist);
1498 } else {
1499 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1502 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1503 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1504 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1505 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1506 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1507 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1508 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1509 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1510 pdb_set_hours(sampass, hours, PDB_SET);
1512 done:
1514 SAFE_FREE(username);
1515 SAFE_FREE(domain);
1516 SAFE_FREE(nt_username);
1517 SAFE_FREE(fullname);
1518 SAFE_FREE(homedir);
1519 SAFE_FREE(dir_drive);
1520 SAFE_FREE(logon_script);
1521 SAFE_FREE(profile_path);
1522 SAFE_FREE(acct_desc);
1523 SAFE_FREE(workstations);
1524 SAFE_FREE(munged_dial);
1525 SAFE_FREE(unknown_str);
1526 SAFE_FREE(lm_pw_ptr);
1527 SAFE_FREE(nt_pw_ptr);
1528 SAFE_FREE(nt_pw_hist_ptr);
1529 SAFE_FREE(hours);
1531 return ret;
1534 /*********************************************************************
1535 *********************************************************************/
1537 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1540 /* times are stored as 32bit integer
1541 take care on system with 64bit wide time_t
1542 --SSS */
1543 uint32 logon_time,
1544 logoff_time,
1545 kickoff_time,
1546 bad_password_time,
1547 pass_last_set_time,
1548 pass_can_change_time,
1549 pass_must_change_time;
1550 char *username = NULL;
1551 char *domain = NULL;
1552 char *nt_username = NULL;
1553 char *dir_drive = NULL;
1554 char *comment = NULL;
1555 char *munged_dial = NULL;
1556 char *fullname = NULL;
1557 char *homedir = NULL;
1558 char *logon_script = NULL;
1559 char *profile_path = NULL;
1560 char *acct_desc = NULL;
1561 char *workstations = NULL;
1562 uint32 username_len, domain_len, nt_username_len,
1563 dir_drive_len, comment_len, munged_dial_len,
1564 fullname_len, homedir_len, logon_script_len,
1565 profile_path_len, acct_desc_len, workstations_len;
1567 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1568 uint16 logon_divs;
1569 uint16 bad_password_count, logon_count;
1570 uint8 *hours = NULL;
1571 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1572 uint32 len = 0;
1573 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1574 uint32 pwHistLen = 0;
1575 bool ret = True;
1576 fstring tmp_string;
1577 bool expand_explicit = lp_passdb_expand_explicit();
1579 if(sampass == NULL || buf == NULL) {
1580 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1581 return False;
1584 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1586 /* unpack the buffer into variables */
1587 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1588 &logon_time, /* d */
1589 &logoff_time, /* d */
1590 &kickoff_time, /* d */
1591 &bad_password_time, /* d */
1592 &pass_last_set_time, /* d */
1593 &pass_can_change_time, /* d */
1594 &pass_must_change_time, /* d */
1595 &username_len, &username, /* B */
1596 &domain_len, &domain, /* B */
1597 &nt_username_len, &nt_username, /* B */
1598 &fullname_len, &fullname, /* B */
1599 &homedir_len, &homedir, /* B */
1600 &dir_drive_len, &dir_drive, /* B */
1601 &logon_script_len, &logon_script, /* B */
1602 &profile_path_len, &profile_path, /* B */
1603 &acct_desc_len, &acct_desc, /* B */
1604 &workstations_len, &workstations, /* B */
1605 &comment_len, &comment, /* B */
1606 &munged_dial_len, &munged_dial, /* B */
1607 &user_rid, /* d */
1608 &group_rid, /* d */
1609 &lm_pw_len, &lm_pw_ptr, /* B */
1610 &nt_pw_len, &nt_pw_ptr, /* B */
1611 /* Change from V1 is addition of password history field. */
1612 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1613 /* Change from V2 is the uint32 acb_mask */
1614 &acct_ctrl, /* d */
1615 /* Also "remove_me" field was removed. */
1616 &logon_divs, /* w */
1617 &hours_len, /* d */
1618 &hourslen, &hours, /* B */
1619 &bad_password_count, /* w */
1620 &logon_count, /* w */
1621 &unknown_6); /* d */
1623 if (len == (uint32) -1) {
1624 ret = False;
1625 goto done;
1628 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1629 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1630 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1631 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1632 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1633 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1634 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1636 pdb_set_username(sampass, username, PDB_SET);
1637 pdb_set_domain(sampass, domain, PDB_SET);
1638 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1639 pdb_set_fullname(sampass, fullname, PDB_SET);
1641 if (homedir) {
1642 fstrcpy( tmp_string, homedir );
1643 if (expand_explicit) {
1644 standard_sub_basic( username, domain, tmp_string,
1645 sizeof(tmp_string) );
1647 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1649 else {
1650 pdb_set_homedir(sampass,
1651 talloc_sub_basic(sampass, username, domain,
1652 lp_logon_home()),
1653 PDB_DEFAULT);
1656 if (dir_drive)
1657 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1658 else
1659 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1661 if (logon_script) {
1662 fstrcpy( tmp_string, logon_script );
1663 if (expand_explicit) {
1664 standard_sub_basic( username, domain, tmp_string,
1665 sizeof(tmp_string) );
1667 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1669 else {
1670 pdb_set_logon_script(sampass,
1671 talloc_sub_basic(sampass, username, domain,
1672 lp_logon_script()),
1673 PDB_DEFAULT);
1676 if (profile_path) {
1677 fstrcpy( tmp_string, profile_path );
1678 if (expand_explicit) {
1679 standard_sub_basic( username, domain, tmp_string,
1680 sizeof(tmp_string) );
1682 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1684 else {
1685 pdb_set_profile_path(sampass,
1686 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1687 PDB_DEFAULT);
1690 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1691 pdb_set_comment(sampass, comment, PDB_SET);
1692 pdb_set_workstations(sampass, workstations, PDB_SET);
1693 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1695 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1696 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1697 ret = False;
1698 goto done;
1702 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1703 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1704 ret = False;
1705 goto done;
1709 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1710 if (pwHistLen) {
1711 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1712 if (!pw_hist) {
1713 ret = False;
1714 goto done;
1716 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1717 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1718 int i;
1719 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1720 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1721 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1722 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1723 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1724 PW_HISTORY_ENTRY_LEN);
1727 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1728 SAFE_FREE(pw_hist);
1729 ret = False;
1730 goto done;
1732 SAFE_FREE(pw_hist);
1733 } else {
1734 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1737 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1738 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1739 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1740 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1741 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1742 /* Change from V2 is the uint32 acct_ctrl */
1743 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1744 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1745 pdb_set_hours(sampass, hours, PDB_SET);
1747 done:
1749 SAFE_FREE(username);
1750 SAFE_FREE(domain);
1751 SAFE_FREE(nt_username);
1752 SAFE_FREE(fullname);
1753 SAFE_FREE(homedir);
1754 SAFE_FREE(dir_drive);
1755 SAFE_FREE(logon_script);
1756 SAFE_FREE(profile_path);
1757 SAFE_FREE(acct_desc);
1758 SAFE_FREE(workstations);
1759 SAFE_FREE(munged_dial);
1760 SAFE_FREE(comment);
1761 SAFE_FREE(lm_pw_ptr);
1762 SAFE_FREE(nt_pw_ptr);
1763 SAFE_FREE(nt_pw_hist_ptr);
1764 SAFE_FREE(hours);
1766 return ret;
1769 /*********************************************************************
1770 *********************************************************************/
1772 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1774 size_t len, buflen;
1776 /* times are stored as 32bit integer
1777 take care on system with 64bit wide time_t
1778 --SSS */
1779 uint32 logon_time,
1780 logoff_time,
1781 kickoff_time,
1782 bad_password_time,
1783 pass_last_set_time,
1784 pass_can_change_time,
1785 pass_must_change_time;
1787 uint32 user_rid, group_rid;
1789 const char *username;
1790 const char *domain;
1791 const char *nt_username;
1792 const char *dir_drive;
1793 const char *comment;
1794 const char *munged_dial;
1795 const char *fullname;
1796 const char *homedir;
1797 const char *logon_script;
1798 const char *profile_path;
1799 const char *acct_desc;
1800 const char *workstations;
1801 uint32 username_len, domain_len, nt_username_len,
1802 dir_drive_len, comment_len, munged_dial_len,
1803 fullname_len, homedir_len, logon_script_len,
1804 profile_path_len, acct_desc_len, workstations_len;
1806 const uint8 *lm_pw;
1807 const uint8 *nt_pw;
1808 const uint8 *nt_pw_hist;
1809 uint32 lm_pw_len = 16;
1810 uint32 nt_pw_len = 16;
1811 uint32 nt_pw_hist_len;
1812 uint32 pwHistLen = 0;
1814 *buf = NULL;
1815 buflen = 0;
1817 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1818 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1819 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1820 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1821 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1822 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1823 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1825 user_rid = pdb_get_user_rid(sampass);
1826 group_rid = pdb_get_group_rid(sampass);
1828 username = pdb_get_username(sampass);
1829 if (username) {
1830 username_len = strlen(username) +1;
1831 } else {
1832 username_len = 0;
1835 domain = pdb_get_domain(sampass);
1836 if (domain) {
1837 domain_len = strlen(domain) +1;
1838 } else {
1839 domain_len = 0;
1842 nt_username = pdb_get_nt_username(sampass);
1843 if (nt_username) {
1844 nt_username_len = strlen(nt_username) +1;
1845 } else {
1846 nt_username_len = 0;
1849 fullname = pdb_get_fullname(sampass);
1850 if (fullname) {
1851 fullname_len = strlen(fullname) +1;
1852 } else {
1853 fullname_len = 0;
1857 * Only updates fields which have been set (not defaults from smb.conf)
1860 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1861 dir_drive = pdb_get_dir_drive(sampass);
1862 } else {
1863 dir_drive = NULL;
1865 if (dir_drive) {
1866 dir_drive_len = strlen(dir_drive) +1;
1867 } else {
1868 dir_drive_len = 0;
1871 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1872 homedir = pdb_get_homedir(sampass);
1873 } else {
1874 homedir = NULL;
1876 if (homedir) {
1877 homedir_len = strlen(homedir) +1;
1878 } else {
1879 homedir_len = 0;
1882 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1883 logon_script = pdb_get_logon_script(sampass);
1884 } else {
1885 logon_script = NULL;
1887 if (logon_script) {
1888 logon_script_len = strlen(logon_script) +1;
1889 } else {
1890 logon_script_len = 0;
1893 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1894 profile_path = pdb_get_profile_path(sampass);
1895 } else {
1896 profile_path = NULL;
1898 if (profile_path) {
1899 profile_path_len = strlen(profile_path) +1;
1900 } else {
1901 profile_path_len = 0;
1904 lm_pw = pdb_get_lanman_passwd(sampass);
1905 if (!lm_pw) {
1906 lm_pw_len = 0;
1909 nt_pw = pdb_get_nt_passwd(sampass);
1910 if (!nt_pw) {
1911 nt_pw_len = 0;
1914 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1915 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1916 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1917 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1918 } else {
1919 nt_pw_hist_len = 0;
1922 acct_desc = pdb_get_acct_desc(sampass);
1923 if (acct_desc) {
1924 acct_desc_len = strlen(acct_desc) +1;
1925 } else {
1926 acct_desc_len = 0;
1929 workstations = pdb_get_workstations(sampass);
1930 if (workstations) {
1931 workstations_len = strlen(workstations) +1;
1932 } else {
1933 workstations_len = 0;
1936 comment = pdb_get_comment(sampass);
1937 if (comment) {
1938 comment_len = strlen(comment) +1;
1939 } else {
1940 comment_len = 0;
1943 munged_dial = pdb_get_munged_dial(sampass);
1944 if (munged_dial) {
1945 munged_dial_len = strlen(munged_dial) +1;
1946 } else {
1947 munged_dial_len = 0;
1950 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1952 /* one time to get the size needed */
1953 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1954 logon_time, /* d */
1955 logoff_time, /* d */
1956 kickoff_time, /* d */
1957 bad_password_time, /* d */
1958 pass_last_set_time, /* d */
1959 pass_can_change_time, /* d */
1960 pass_must_change_time, /* d */
1961 username_len, username, /* B */
1962 domain_len, domain, /* B */
1963 nt_username_len, nt_username, /* B */
1964 fullname_len, fullname, /* B */
1965 homedir_len, homedir, /* B */
1966 dir_drive_len, dir_drive, /* B */
1967 logon_script_len, logon_script, /* B */
1968 profile_path_len, profile_path, /* B */
1969 acct_desc_len, acct_desc, /* B */
1970 workstations_len, workstations, /* B */
1971 comment_len, comment, /* B */
1972 munged_dial_len, munged_dial, /* B */
1973 user_rid, /* d */
1974 group_rid, /* d */
1975 lm_pw_len, lm_pw, /* B */
1976 nt_pw_len, nt_pw, /* B */
1977 nt_pw_hist_len, nt_pw_hist, /* B */
1978 pdb_get_acct_ctrl(sampass), /* d */
1979 pdb_get_logon_divs(sampass), /* w */
1980 pdb_get_hours_len(sampass), /* d */
1981 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1982 pdb_get_bad_password_count(sampass), /* w */
1983 pdb_get_logon_count(sampass), /* w */
1984 pdb_get_unknown_6(sampass)); /* d */
1986 if (size_only) {
1987 return buflen;
1990 /* malloc the space needed */
1991 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1992 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1993 return (-1);
1996 /* now for the real call to tdb_pack() */
1997 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1998 logon_time, /* d */
1999 logoff_time, /* d */
2000 kickoff_time, /* d */
2001 bad_password_time, /* d */
2002 pass_last_set_time, /* d */
2003 pass_can_change_time, /* d */
2004 pass_must_change_time, /* d */
2005 username_len, username, /* B */
2006 domain_len, domain, /* B */
2007 nt_username_len, nt_username, /* B */
2008 fullname_len, fullname, /* B */
2009 homedir_len, homedir, /* B */
2010 dir_drive_len, dir_drive, /* B */
2011 logon_script_len, logon_script, /* B */
2012 profile_path_len, profile_path, /* B */
2013 acct_desc_len, acct_desc, /* B */
2014 workstations_len, workstations, /* B */
2015 comment_len, comment, /* B */
2016 munged_dial_len, munged_dial, /* B */
2017 user_rid, /* d */
2018 group_rid, /* d */
2019 lm_pw_len, lm_pw, /* B */
2020 nt_pw_len, nt_pw, /* B */
2021 nt_pw_hist_len, nt_pw_hist, /* B */
2022 pdb_get_acct_ctrl(sampass), /* d */
2023 pdb_get_logon_divs(sampass), /* w */
2024 pdb_get_hours_len(sampass), /* d */
2025 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2026 pdb_get_bad_password_count(sampass), /* w */
2027 pdb_get_logon_count(sampass), /* w */
2028 pdb_get_unknown_6(sampass)); /* d */
2030 /* check to make sure we got it correct */
2031 if (buflen != len) {
2032 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2033 (unsigned long)buflen, (unsigned long)len));
2034 /* error */
2035 SAFE_FREE (*buf);
2036 return (-1);
2039 return (buflen);
2042 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2044 /* nothing changed between V3 and V4 */
2045 return init_samu_from_buffer_v3(sampass, buf, buflen);
2048 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2050 /* nothing changed between V3 and V4 */
2051 return init_buffer_from_samu_v3(buf, sampass, size_only);
2054 /**********************************************************************
2055 Intialize a struct samu struct from a BYTE buffer of size len
2056 *********************************************************************/
2058 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2059 uint8 *buf, uint32 buflen)
2061 switch (level) {
2062 case SAMU_BUFFER_V0:
2063 return init_samu_from_buffer_v0(sampass, buf, buflen);
2064 case SAMU_BUFFER_V1:
2065 return init_samu_from_buffer_v1(sampass, buf, buflen);
2066 case SAMU_BUFFER_V2:
2067 return init_samu_from_buffer_v2(sampass, buf, buflen);
2068 case SAMU_BUFFER_V3:
2069 return init_samu_from_buffer_v3(sampass, buf, buflen);
2070 case SAMU_BUFFER_V4:
2071 return init_samu_from_buffer_v4(sampass, buf, buflen);
2074 return false;
2077 /**********************************************************************
2078 Intialize a BYTE buffer from a struct samu struct
2079 *********************************************************************/
2081 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2083 return init_buffer_from_samu_v4(buf, sampass, size_only);
2086 /*********************************************************************
2087 *********************************************************************/
2089 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2091 uint8 *buf = NULL;
2092 int len;
2094 len = init_buffer_from_samu(&buf, src, False);
2095 if (len == -1 || !buf) {
2096 SAFE_FREE(buf);
2097 return False;
2100 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2101 free(buf);
2102 return False;
2105 dst->methods = src->methods;
2107 if ( src->unix_pw ) {
2108 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2109 if (!dst->unix_pw) {
2110 free(buf);
2111 return False;
2115 if (src->group_sid) {
2116 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2119 free(buf);
2120 return True;
2123 /*********************************************************************
2124 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2125 *********************************************************************/
2127 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2129 time_t LastBadPassword;
2130 uint16 BadPasswordCount;
2131 uint32 resettime;
2132 bool res;
2134 BadPasswordCount = pdb_get_bad_password_count(sampass);
2135 if (!BadPasswordCount) {
2136 DEBUG(9, ("No bad password attempts.\n"));
2137 return True;
2140 become_root();
2141 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2142 unbecome_root();
2144 if (!res) {
2145 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2146 return False;
2149 /* First, check if there is a reset time to compare */
2150 if ((resettime == (uint32) -1) || (resettime == 0)) {
2151 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2152 return True;
2155 LastBadPassword = pdb_get_bad_password_time(sampass);
2156 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2157 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2158 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2159 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2160 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2161 if (updated) {
2162 *updated = True;
2166 return True;
2169 /*********************************************************************
2170 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2171 *********************************************************************/
2173 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2175 uint32 duration;
2176 time_t LastBadPassword;
2177 bool res;
2179 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2180 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2181 pdb_get_username(sampass)));
2182 return True;
2185 become_root();
2186 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2187 unbecome_root();
2189 if (!res) {
2190 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2191 return False;
2194 /* First, check if there is a duration to compare */
2195 if ((duration == (uint32) -1) || (duration == 0)) {
2196 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2197 return True;
2200 LastBadPassword = pdb_get_bad_password_time(sampass);
2201 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2202 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2204 if (LastBadPassword == (time_t)0) {
2205 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2206 "administratively locked out with no bad password "
2207 "time. Leaving locked out.\n",
2208 pdb_get_username(sampass) ));
2209 return True;
2212 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2213 pdb_set_acct_ctrl(sampass,
2214 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2215 PDB_CHANGED);
2216 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2217 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2218 if (updated) {
2219 *updated = True;
2223 return True;
2226 /*********************************************************************
2227 Increment the bad_password_count
2228 *********************************************************************/
2230 bool pdb_increment_bad_password_count(struct samu *sampass)
2232 uint32 account_policy_lockout;
2233 bool autolock_updated = False, badpw_updated = False;
2234 bool ret;
2236 /* Retrieve the account lockout policy */
2237 become_root();
2238 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2239 unbecome_root();
2240 if ( !ret ) {
2241 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2242 return False;
2245 /* If there is no policy, we don't need to continue checking */
2246 if (!account_policy_lockout) {
2247 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2248 return True;
2251 /* Check if the autolock needs to be cleared */
2252 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2253 return False;
2255 /* Check if the badpw count needs to be reset */
2256 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2257 return False;
2260 Ok, now we can assume that any resetting that needs to be
2261 done has been done, and just get on with incrementing
2262 and autolocking if necessary
2265 pdb_set_bad_password_count(sampass,
2266 pdb_get_bad_password_count(sampass)+1,
2267 PDB_CHANGED);
2268 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2271 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2272 return True;
2274 if (!pdb_set_acct_ctrl(sampass,
2275 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2276 PDB_CHANGED)) {
2277 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2278 return False;
2281 return True;
2284 bool is_dc_trusted_domain_situation(const char *domain_name)
2286 return IS_DC && !strequal(domain_name, lp_workgroup());
2289 /*******************************************************************
2290 Wrapper around retrieving the clear text trust account password.
2291 appropriate account name is stored in account_name.
2292 Caller must free password, but not account_name.
2293 *******************************************************************/
2295 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2296 const char **account_name,
2297 enum netr_SchannelType *channel)
2299 char *pwd;
2300 time_t last_set_time;
2302 /* if we are a DC and this is not our domain, then lookup an account
2303 * for the domain trust */
2305 if (is_dc_trusted_domain_situation(domain)) {
2306 if (!lp_allow_trusted_domains()) {
2307 return false;
2310 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2311 &last_set_time))
2313 DEBUG(0, ("get_trust_pw: could not fetch trust "
2314 "account password for trusted domain %s\n",
2315 domain));
2316 return false;
2319 if (channel != NULL) {
2320 *channel = SEC_CHAN_DOMAIN;
2323 if (account_name != NULL) {
2324 *account_name = lp_workgroup();
2327 return true;
2331 * Since we can only be member of one single domain, we are now
2332 * in a member situation:
2334 * - Either we are a DC (selfjoined) and the domain is our
2335 * own domain.
2336 * - Or we are on a member and the domain is our own or some
2337 * other (potentially trusted) domain.
2339 * In both cases, we can only get the machine account password
2340 * for our own domain to connect to our own dc. (For a member,
2341 * request to trusted domains are performed through our dc.)
2343 * So we simply use our own domain name to retrieve the
2344 * machine account passowrd and ignore the request domain here.
2347 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2349 if (pwd != NULL) {
2350 *ret_pwd = pwd;
2351 if (account_name != NULL) {
2352 *account_name = global_myname();
2355 return true;
2358 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2359 "account password for domain %s\n", domain));
2360 return false;
2363 /*******************************************************************
2364 Wrapper around retrieving the trust account password.
2365 appropriate account name is stored in account_name.
2366 *******************************************************************/
2368 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2369 const char **account_name,
2370 enum netr_SchannelType *channel)
2372 char *pwd = NULL;
2373 time_t last_set_time;
2375 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2376 E_md4hash(pwd, ret_pwd);
2377 SAFE_FREE(pwd);
2378 return true;
2379 } else if (is_dc_trusted_domain_situation(domain)) {
2380 return false;
2383 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2385 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2386 &last_set_time,
2387 channel))
2389 if (account_name != NULL) {
2390 *account_name = global_myname();
2393 return true;
2396 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2397 "password for domain %s\n", domain));
2398 return False;
2401 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2402 struct samu *pw)
2404 struct samr_LogonHours hours;
2405 const int units_per_week = 168;
2407 ZERO_STRUCT(hours);
2408 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2409 if (!hours.bits) {
2410 return hours;
2413 hours.units_per_week = units_per_week;
2414 memset(hours.bits, 0xFF, units_per_week);
2416 if (pdb_get_hours(pw)) {
2417 memcpy(hours.bits, pdb_get_hours(pw),
2418 MIN(pdb_get_hours_len(pw), units_per_week));
2421 return hours;