s3-nss_wins: Fix unresolved ldb symbols in libnss_wins.so.
[Samba.git] / source3 / passdb / passdb.c
blobfd715d201f91d7f655a18bac8bc296153cea3199
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"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
30 /******************************************************************
31 Get the default domain/netbios name to be used when
32 testing authentication.
34 LEGACY: this function provides the legacy domain mapping used with
35 the lp_map_untrusted_to_domain() parameter
36 ******************************************************************/
38 const char *my_sam_name(void)
40 /* Standalone servers can only use the local netbios name */
41 if ( lp_server_role() == ROLE_STANDALONE )
42 return global_myname();
44 /* Default to the DOMAIN name when not specified */
45 return lp_workgroup();
48 /**********************************************************************
49 ***********************************************************************/
51 static int samu_destroy(struct samu *user)
53 data_blob_clear_free( &user->lm_pw );
54 data_blob_clear_free( &user->nt_pw );
56 if ( user->plaintext_pw )
57 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
59 return 0;
62 /**********************************************************************
63 generate a new struct samuser
64 ***********************************************************************/
66 struct samu *samu_new( TALLOC_CTX *ctx )
68 struct samu *user;
70 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
71 DEBUG(0,("samuser_new: Talloc failed!\n"));
72 return NULL;
75 talloc_set_destructor( user, samu_destroy );
77 /* no initial methods */
79 user->methods = NULL;
81 /* Don't change these timestamp settings without a good reason.
82 They are important for NT member server compatibility. */
84 user->logon_time = (time_t)0;
85 user->pass_last_set_time = (time_t)0;
86 user->pass_can_change_time = (time_t)0;
87 user->logoff_time = get_time_t_max();
88 user->kickoff_time = get_time_t_max();
89 user->pass_must_change_time = get_time_t_max();
90 user->fields_present = 0x00ffffff;
91 user->logon_divs = 168; /* hours per week */
92 user->hours_len = 21; /* 21 times 8 bits = 168 */
93 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
94 user->bad_password_count = 0;
95 user->logon_count = 0;
96 user->unknown_6 = 0x000004ec; /* don't know */
98 /* Some parts of samba strlen their pdb_get...() returns,
99 so this keeps the interface unchanged for now. */
101 user->username = "";
102 user->domain = "";
103 user->nt_username = "";
104 user->full_name = "";
105 user->home_dir = "";
106 user->logon_script = "";
107 user->profile_path = "";
108 user->acct_desc = "";
109 user->workstations = "";
110 user->comment = "";
111 user->munged_dial = "";
113 user->plaintext_pw = NULL;
115 /* Unless we know otherwise have a Account Control Bit
116 value of 'normal user'. This helps User Manager, which
117 asks for a filtered list of users. */
119 user->acct_ctrl = ACB_NORMAL;
121 return user;
124 /*********************************************************************
125 Initialize a struct samu from a struct passwd including the user
126 and group SIDs. The *user structure is filled out with the Unix
127 attributes and a user SID.
128 *********************************************************************/
130 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
132 const char *guest_account = lp_guestaccount();
133 const char *domain = global_myname();
134 uint32 urid;
136 if ( !pwd ) {
137 return NT_STATUS_NO_SUCH_USER;
140 /* Basic properties based upon the Unix account information */
142 pdb_set_username(user, pwd->pw_name, PDB_SET);
143 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
144 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
145 #if 0
146 /* This can lead to a primary group of S-1-22-2-XX which
147 will be rejected by other parts of the Samba code.
148 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
149 --jerry */
151 gid_to_sid(&group_sid, pwd->pw_gid);
152 pdb_set_group_sid(user, &group_sid, PDB_SET);
153 #endif
155 /* save the password structure for later use */
157 user->unix_pw = tcopy_passwd( user, pwd );
159 /* Special case for the guest account which must have a RID of 501 */
161 if ( strequal( pwd->pw_name, guest_account ) ) {
162 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
163 return NT_STATUS_NO_SUCH_USER;
165 return NT_STATUS_OK;
168 /* Non-guest accounts...Check for a workstation or user account */
170 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
171 /* workstation */
173 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
174 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
175 pwd->pw_name));
176 return NT_STATUS_INVALID_COMPUTER_NAME;
179 else {
180 /* user */
182 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
183 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
184 pwd->pw_name));
185 return NT_STATUS_INVALID_ACCOUNT_NAME;
188 /* set some basic attributes */
190 pdb_set_profile_path(user, talloc_sub_specified(user,
191 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
192 PDB_DEFAULT);
193 pdb_set_homedir(user, talloc_sub_specified(user,
194 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
195 PDB_DEFAULT);
196 pdb_set_dir_drive(user, talloc_sub_specified(user,
197 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
198 PDB_DEFAULT);
199 pdb_set_logon_script(user, talloc_sub_specified(user,
200 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
201 PDB_DEFAULT);
204 /* Now deal with the user SID. If we have a backend that can generate
205 RIDs, then do so. But sometimes the caller just wanted a structure
206 initialized and will fill in these fields later (such as from a
207 netr_SamInfo3 structure) */
209 if ( create && !pdb_rid_algorithm() ) {
210 uint32 user_rid;
211 DOM_SID user_sid;
213 if ( !pdb_new_rid( &user_rid ) ) {
214 DEBUG(3, ("Could not allocate a new RID\n"));
215 return NT_STATUS_ACCESS_DENIED;
218 sid_copy( &user_sid, get_global_sam_sid() );
219 sid_append_rid( &user_sid, user_rid );
221 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
222 DEBUG(3, ("pdb_set_user_sid failed\n"));
223 return NT_STATUS_INTERNAL_ERROR;
226 return NT_STATUS_OK;
229 /* generate a SID for the user with the RID algorithm */
231 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
233 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
234 return NT_STATUS_INTERNAL_ERROR;
237 return NT_STATUS_OK;
240 /********************************************************************
241 Set the Unix user attributes
242 ********************************************************************/
244 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
246 return samu_set_unix_internal( user, pwd, False );
249 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
251 return samu_set_unix_internal( user, pwd, True );
254 /**********************************************************
255 Encode the account control bits into a string.
256 length = length of string to encode into (including terminating
257 null). length *MUST BE MORE THAN 2* !
258 **********************************************************/
260 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
262 fstring acct_str;
263 char *result;
265 size_t i = 0;
267 SMB_ASSERT(length <= sizeof(acct_str));
269 acct_str[i++] = '[';
271 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
272 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
273 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
274 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
275 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
276 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
277 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
278 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
279 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
280 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
281 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
283 for ( ; i < length - 2 ; i++ )
284 acct_str[i] = ' ';
286 i = length - 2;
287 acct_str[i++] = ']';
288 acct_str[i++] = '\0';
290 result = talloc_strdup(talloc_tos(), acct_str);
291 SMB_ASSERT(result != NULL);
292 return result;
295 /**********************************************************
296 Decode the account control bits from a string.
297 **********************************************************/
299 uint32_t pdb_decode_acct_ctrl(const char *p)
301 uint32_t acct_ctrl = 0;
302 bool finished = false;
305 * Check if the account type bits have been encoded after the
306 * NT password (in the form [NDHTUWSLXI]).
309 if (*p != '[')
310 return 0;
312 for (p++; *p && !finished; p++) {
313 switch (*p) {
314 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
315 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
316 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
317 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
318 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
319 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
320 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
321 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
322 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
323 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
324 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
325 case ' ': { break; }
326 case ':':
327 case '\n':
328 case '\0':
329 case ']':
330 default: { finished = true; }
334 return acct_ctrl;
337 /*************************************************************
338 Routine to set 32 hex password characters from a 16 byte array.
339 **************************************************************/
341 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
343 if (pwd != NULL) {
344 int i;
345 for (i = 0; i < 16; i++)
346 slprintf(&p[i*2], 3, "%02X", pwd[i]);
347 } else {
348 if (acct_ctrl & ACB_PWNOTREQ)
349 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
350 else
351 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
355 /*************************************************************
356 Routine to get the 32 hex characters and turn them
357 into a 16 byte array.
358 **************************************************************/
360 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
362 int i;
363 unsigned char lonybble, hinybble;
364 const char *hexchars = "0123456789ABCDEF";
365 char *p1, *p2;
367 if (!p)
368 return false;
370 for (i = 0; i < 32; i += 2) {
371 hinybble = toupper_ascii(p[i]);
372 lonybble = toupper_ascii(p[i + 1]);
374 p1 = strchr(hexchars, hinybble);
375 p2 = strchr(hexchars, lonybble);
377 if (!p1 || !p2)
378 return false;
380 hinybble = PTR_DIFF(p1, hexchars);
381 lonybble = PTR_DIFF(p2, hexchars);
383 pwd[i / 2] = (hinybble << 4) | lonybble;
385 return true;
388 /*************************************************************
389 Routine to set 42 hex hours characters from a 21 byte array.
390 **************************************************************/
392 void pdb_sethexhours(char *p, const unsigned char *hours)
394 if (hours != NULL) {
395 int i;
396 for (i = 0; i < 21; i++) {
397 slprintf(&p[i*2], 3, "%02X", hours[i]);
399 } else {
400 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
404 /*************************************************************
405 Routine to get the 42 hex characters and turn them
406 into a 21 byte array.
407 **************************************************************/
409 bool pdb_gethexhours(const char *p, unsigned char *hours)
411 int i;
412 unsigned char lonybble, hinybble;
413 const char *hexchars = "0123456789ABCDEF";
414 char *p1, *p2;
416 if (!p) {
417 return (False);
420 for (i = 0; i < 42; i += 2) {
421 hinybble = toupper_ascii(p[i]);
422 lonybble = toupper_ascii(p[i + 1]);
424 p1 = strchr(hexchars, hinybble);
425 p2 = strchr(hexchars, lonybble);
427 if (!p1 || !p2) {
428 return (False);
431 hinybble = PTR_DIFF(p1, hexchars);
432 lonybble = PTR_DIFF(p2, hexchars);
434 hours[i / 2] = (hinybble << 4) | lonybble;
436 return (True);
439 /********************************************************************
440 ********************************************************************/
442 int algorithmic_rid_base(void)
444 int rid_offset;
446 rid_offset = lp_algorithmic_rid_base();
448 if (rid_offset < BASE_RID) {
449 /* Try to prevent admin foot-shooting, we can't put algorithmic
450 rids below 1000, that's the 'well known RIDs' on NT */
451 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
452 rid_offset = BASE_RID;
454 if (rid_offset & 1) {
455 DEBUG(0, ("algorithmic rid base must be even\n"));
456 rid_offset += 1;
458 return rid_offset;
461 /*******************************************************************
462 Converts NT user RID to a UNIX uid.
463 ********************************************************************/
465 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
467 int rid_offset = algorithmic_rid_base();
468 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
471 uid_t max_algorithmic_uid(void)
473 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
476 /*******************************************************************
477 converts UNIX uid to an NT User RID.
478 ********************************************************************/
480 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
482 int rid_offset = algorithmic_rid_base();
483 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
486 /*******************************************************************
487 Converts NT group RID to a UNIX gid.
488 ********************************************************************/
490 gid_t pdb_group_rid_to_gid(uint32 group_rid)
492 int rid_offset = algorithmic_rid_base();
493 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
496 gid_t max_algorithmic_gid(void)
498 return pdb_group_rid_to_gid(0xffffffff);
501 /*******************************************************************
502 converts NT Group RID to a UNIX uid.
504 warning: you must not call that function only
505 you must do a call to the group mapping first.
506 there is not anymore a direct link between the gid and the rid.
507 ********************************************************************/
509 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
511 int rid_offset = algorithmic_rid_base();
512 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
515 /*******************************************************************
516 Decides if a RID is a well known RID.
517 ********************************************************************/
519 static bool rid_is_well_known(uint32 rid)
521 /* Not using rid_offset here, because this is the actual
522 NT fixed value (1000) */
524 return (rid < BASE_RID);
527 /*******************************************************************
528 Decides if a RID is a user or group RID.
529 ********************************************************************/
531 bool algorithmic_pdb_rid_is_user(uint32 rid)
533 if ( rid_is_well_known(rid) ) {
535 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
536 * and DOMAIN_USER_RID_GUEST.
538 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
539 return True;
540 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
541 return True;
543 return False;
546 /*******************************************************************
547 Convert a name into a SID. Used in the lookup name rpc.
548 ********************************************************************/
550 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
551 enum lsa_SidType *type)
553 GROUP_MAP map;
554 bool ret;
556 /* Windows treats "MACHINE\None" as a special name for
557 rid 513 on non-DCs. You cannot create a user or group
558 name "None" on Windows. You will get an error that
559 the group already exists. */
561 if ( strequal( name, "None" ) ) {
562 *rid = DOMAIN_GROUP_RID_USERS;
563 *type = SID_NAME_DOM_GRP;
565 return True;
568 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
569 * correctly in the case where foo also exists as a user. If the flag
570 * is set, don't look for users at all. */
572 if ((flags & LOOKUP_NAME_GROUP) == 0) {
573 struct samu *sam_account = NULL;
574 DOM_SID user_sid;
576 if ( !(sam_account = samu_new( NULL )) ) {
577 return False;
580 become_root();
581 ret = pdb_getsampwnam(sam_account, name);
582 unbecome_root();
584 if (ret) {
585 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
588 TALLOC_FREE(sam_account);
590 if (ret) {
591 if (!sid_check_is_in_our_domain(&user_sid)) {
592 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
593 name, sid_string_dbg(&user_sid)));
594 return False;
597 sid_peek_rid(&user_sid, rid);
598 *type = SID_NAME_USER;
599 return True;
604 * Maybe it is a group ?
607 become_root();
608 ret = pdb_getgrnam(&map, name);
609 unbecome_root();
611 if (!ret) {
612 return False;
615 /* BUILTIN groups are looked up elsewhere */
616 if (!sid_check_is_in_our_domain(&map.sid)) {
617 DEBUG(10, ("Found group %s (%s) not in our domain -- "
618 "ignoring.", name, sid_string_dbg(&map.sid)));
619 return False;
622 /* yes it's a mapped group */
623 sid_peek_rid(&map.sid, rid);
624 *type = map.sid_name_use;
625 return True;
628 /*************************************************************
629 Change a password entry in the local smbpasswd file.
630 *************************************************************/
632 NTSTATUS local_password_change(const char *user_name,
633 int local_flags,
634 const char *new_passwd,
635 char **pp_err_str,
636 char **pp_msg_str)
638 struct samu *sam_pass=NULL;
639 uint32 other_acb;
640 NTSTATUS result;
642 *pp_err_str = NULL;
643 *pp_msg_str = NULL;
645 /* Get the smb passwd entry for this user */
647 if ( !(sam_pass = samu_new( NULL )) ) {
648 return NT_STATUS_NO_MEMORY;
651 become_root();
652 if(!pdb_getsampwnam(sam_pass, user_name)) {
653 unbecome_root();
654 TALLOC_FREE(sam_pass);
656 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
657 int tmp_debug = DEBUGLEVEL;
658 struct passwd *pwd;
660 /* Might not exist in /etc/passwd. */
662 if (tmp_debug < 1) {
663 DEBUGLEVEL = 1;
666 if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), user_name)) ) {
667 return NT_STATUS_NO_SUCH_USER;
670 /* create the struct samu and initialize the basic Unix properties */
672 if ( !(sam_pass = samu_new( NULL )) ) {
673 return NT_STATUS_NO_MEMORY;
676 result = samu_set_unix( sam_pass, pwd );
678 DEBUGLEVEL = tmp_debug;
680 TALLOC_FREE( pwd );
682 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
683 return result;
686 if (!NT_STATUS_IS_OK(result)) {
687 if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
688 user_name, nt_errstr(result)) < 0) {
689 *pp_err_str = NULL;
691 return result;
693 } else {
694 if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) {
695 *pp_err_str = NULL;
697 return NT_STATUS_NO_SUCH_USER;
699 } else {
700 unbecome_root();
701 /* the entry already existed */
702 local_flags &= ~LOCAL_ADD_USER;
705 /* the 'other' acb bits not being changed here */
706 other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
707 if (local_flags & LOCAL_TRUST_ACCOUNT) {
708 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
709 if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) {
710 *pp_err_str = NULL;
712 TALLOC_FREE(sam_pass);
713 return NT_STATUS_UNSUCCESSFUL;
715 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
716 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
717 if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) {
718 *pp_err_str = NULL;
720 TALLOC_FREE(sam_pass);
721 return NT_STATUS_UNSUCCESSFUL;
723 } else {
724 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
725 if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) {
726 *pp_err_str = NULL;
728 TALLOC_FREE(sam_pass);
729 return NT_STATUS_UNSUCCESSFUL;
734 * We are root - just write the new password
735 * and the valid last change time.
738 if (local_flags & LOCAL_DISABLE_USER) {
739 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
740 if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) {
741 *pp_err_str = NULL;
743 TALLOC_FREE(sam_pass);
744 return NT_STATUS_UNSUCCESSFUL;
746 } else if (local_flags & LOCAL_ENABLE_USER) {
747 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
748 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
749 *pp_err_str = NULL;
751 TALLOC_FREE(sam_pass);
752 return NT_STATUS_UNSUCCESSFUL;
756 if (local_flags & LOCAL_SET_NO_PASSWORD) {
757 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
758 if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) {
759 *pp_err_str = NULL;
761 TALLOC_FREE(sam_pass);
762 return NT_STATUS_UNSUCCESSFUL;
764 } else if (local_flags & LOCAL_SET_PASSWORD) {
766 * If we're dealing with setting a completely empty user account
767 * ie. One with a password of 'XXXX', but not set disabled (like
768 * an account created from scratch) then if the old password was
769 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
770 * We remove that as we're giving this user their first password
771 * and the decision hasn't really been made to disable them (ie.
772 * don't create them disabled). JRA.
774 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
775 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
776 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
777 *pp_err_str = NULL;
779 TALLOC_FREE(sam_pass);
780 return NT_STATUS_UNSUCCESSFUL;
783 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
784 if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) {
785 *pp_err_str = NULL;
787 TALLOC_FREE(sam_pass);
788 return NT_STATUS_UNSUCCESSFUL;
791 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
792 if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) {
793 *pp_err_str = NULL;
795 TALLOC_FREE(sam_pass);
796 return NT_STATUS_UNSUCCESSFUL;
800 if (local_flags & LOCAL_ADD_USER) {
801 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
802 if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) {
803 *pp_msg_str = NULL;
805 TALLOC_FREE(sam_pass);
806 return NT_STATUS_OK;
807 } else {
808 if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) {
809 *pp_err_str = NULL;
811 TALLOC_FREE(sam_pass);
812 return NT_STATUS_UNSUCCESSFUL;
814 } else if (local_flags & LOCAL_DELETE_USER) {
815 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
816 if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) {
817 *pp_err_str = NULL;
819 TALLOC_FREE(sam_pass);
820 return NT_STATUS_UNSUCCESSFUL;
822 if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) {
823 *pp_msg_str = NULL;
825 } else {
826 result = pdb_update_sam_account(sam_pass);
827 if(!NT_STATUS_IS_OK(result)) {
828 if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) {
829 *pp_err_str = NULL;
831 TALLOC_FREE(sam_pass);
832 return result;
834 if(local_flags & LOCAL_DISABLE_USER) {
835 if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) {
836 *pp_msg_str = NULL;
838 } else if (local_flags & LOCAL_ENABLE_USER) {
839 if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) {
840 *pp_msg_str = NULL;
842 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
843 if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) {
844 *pp_msg_str = NULL;
849 TALLOC_FREE(sam_pass);
850 return NT_STATUS_OK;
853 /**********************************************************************
854 Marshall/unmarshall struct samu structs.
855 *********************************************************************/
857 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
858 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
859 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
860 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
861 /* nothing changed between V3 and V4 */
863 /*********************************************************************
864 *********************************************************************/
866 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
869 /* times are stored as 32bit integer
870 take care on system with 64bit wide time_t
871 --SSS */
872 uint32 logon_time,
873 logoff_time,
874 kickoff_time,
875 pass_last_set_time,
876 pass_can_change_time,
877 pass_must_change_time;
878 char *username = NULL;
879 char *domain = NULL;
880 char *nt_username = NULL;
881 char *dir_drive = NULL;
882 char *unknown_str = NULL;
883 char *munged_dial = NULL;
884 char *fullname = NULL;
885 char *homedir = NULL;
886 char *logon_script = NULL;
887 char *profile_path = NULL;
888 char *acct_desc = NULL;
889 char *workstations = NULL;
890 uint32 username_len, domain_len, nt_username_len,
891 dir_drive_len, unknown_str_len, munged_dial_len,
892 fullname_len, homedir_len, logon_script_len,
893 profile_path_len, acct_desc_len, workstations_len;
895 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
896 uint16 acct_ctrl, logon_divs;
897 uint16 bad_password_count, logon_count;
898 uint8 *hours = NULL;
899 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
900 uint32 len = 0;
901 uint32 lm_pw_len, nt_pw_len, hourslen;
902 bool ret = True;
904 if(sampass == NULL || buf == NULL) {
905 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
906 return False;
909 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
911 /* unpack the buffer into variables */
912 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
913 &logon_time, /* d */
914 &logoff_time, /* d */
915 &kickoff_time, /* d */
916 &pass_last_set_time, /* d */
917 &pass_can_change_time, /* d */
918 &pass_must_change_time, /* d */
919 &username_len, &username, /* B */
920 &domain_len, &domain, /* B */
921 &nt_username_len, &nt_username, /* B */
922 &fullname_len, &fullname, /* B */
923 &homedir_len, &homedir, /* B */
924 &dir_drive_len, &dir_drive, /* B */
925 &logon_script_len, &logon_script, /* B */
926 &profile_path_len, &profile_path, /* B */
927 &acct_desc_len, &acct_desc, /* B */
928 &workstations_len, &workstations, /* B */
929 &unknown_str_len, &unknown_str, /* B */
930 &munged_dial_len, &munged_dial, /* B */
931 &user_rid, /* d */
932 &group_rid, /* d */
933 &lm_pw_len, &lm_pw_ptr, /* B */
934 &nt_pw_len, &nt_pw_ptr, /* B */
935 &acct_ctrl, /* w */
936 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
937 &logon_divs, /* w */
938 &hours_len, /* d */
939 &hourslen, &hours, /* B */
940 &bad_password_count, /* w */
941 &logon_count, /* w */
942 &unknown_6); /* d */
944 if (len == (uint32) -1) {
945 ret = False;
946 goto done;
949 pdb_set_logon_time(sampass, logon_time, PDB_SET);
950 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
951 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
952 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
953 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
954 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
956 pdb_set_username(sampass, username, PDB_SET);
957 pdb_set_domain(sampass, domain, PDB_SET);
958 pdb_set_nt_username(sampass, nt_username, PDB_SET);
959 pdb_set_fullname(sampass, fullname, PDB_SET);
961 if (homedir) {
962 pdb_set_homedir(sampass, homedir, PDB_SET);
964 else {
965 pdb_set_homedir(sampass,
966 talloc_sub_basic(sampass, username, domain,
967 lp_logon_home()),
968 PDB_DEFAULT);
971 if (dir_drive)
972 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
973 else {
974 pdb_set_dir_drive(sampass,
975 talloc_sub_basic(sampass, username, domain,
976 lp_logon_drive()),
977 PDB_DEFAULT);
980 if (logon_script)
981 pdb_set_logon_script(sampass, logon_script, PDB_SET);
982 else {
983 pdb_set_logon_script(sampass,
984 talloc_sub_basic(sampass, username, domain,
985 lp_logon_script()),
986 PDB_DEFAULT);
989 if (profile_path) {
990 pdb_set_profile_path(sampass, profile_path, PDB_SET);
991 } else {
992 pdb_set_profile_path(sampass,
993 talloc_sub_basic(sampass, username, domain,
994 lp_logon_path()),
995 PDB_DEFAULT);
998 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
999 pdb_set_workstations(sampass, workstations, PDB_SET);
1000 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1002 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1003 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1004 ret = False;
1005 goto done;
1009 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1010 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1011 ret = False;
1012 goto done;
1016 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1017 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1018 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1019 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1020 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1021 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1022 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1023 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1024 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1025 pdb_set_hours(sampass, hours, PDB_SET);
1027 done:
1029 SAFE_FREE(username);
1030 SAFE_FREE(domain);
1031 SAFE_FREE(nt_username);
1032 SAFE_FREE(fullname);
1033 SAFE_FREE(homedir);
1034 SAFE_FREE(dir_drive);
1035 SAFE_FREE(logon_script);
1036 SAFE_FREE(profile_path);
1037 SAFE_FREE(acct_desc);
1038 SAFE_FREE(workstations);
1039 SAFE_FREE(munged_dial);
1040 SAFE_FREE(unknown_str);
1041 SAFE_FREE(lm_pw_ptr);
1042 SAFE_FREE(nt_pw_ptr);
1043 SAFE_FREE(hours);
1045 return ret;
1048 /*********************************************************************
1049 *********************************************************************/
1051 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1054 /* times are stored as 32bit integer
1055 take care on system with 64bit wide time_t
1056 --SSS */
1057 uint32 logon_time,
1058 logoff_time,
1059 kickoff_time,
1060 bad_password_time,
1061 pass_last_set_time,
1062 pass_can_change_time,
1063 pass_must_change_time;
1064 char *username = NULL;
1065 char *domain = NULL;
1066 char *nt_username = NULL;
1067 char *dir_drive = NULL;
1068 char *unknown_str = NULL;
1069 char *munged_dial = NULL;
1070 char *fullname = NULL;
1071 char *homedir = NULL;
1072 char *logon_script = NULL;
1073 char *profile_path = NULL;
1074 char *acct_desc = NULL;
1075 char *workstations = NULL;
1076 uint32 username_len, domain_len, nt_username_len,
1077 dir_drive_len, unknown_str_len, munged_dial_len,
1078 fullname_len, homedir_len, logon_script_len,
1079 profile_path_len, acct_desc_len, workstations_len;
1081 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1082 uint16 acct_ctrl, logon_divs;
1083 uint16 bad_password_count, logon_count;
1084 uint8 *hours = NULL;
1085 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1086 uint32 len = 0;
1087 uint32 lm_pw_len, nt_pw_len, hourslen;
1088 bool ret = True;
1090 if(sampass == NULL || buf == NULL) {
1091 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1092 return False;
1095 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1097 /* unpack the buffer into variables */
1098 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1099 &logon_time, /* d */
1100 &logoff_time, /* d */
1101 &kickoff_time, /* d */
1102 /* Change from V0 is addition of bad_password_time field. */
1103 &bad_password_time, /* d */
1104 &pass_last_set_time, /* d */
1105 &pass_can_change_time, /* d */
1106 &pass_must_change_time, /* d */
1107 &username_len, &username, /* B */
1108 &domain_len, &domain, /* B */
1109 &nt_username_len, &nt_username, /* B */
1110 &fullname_len, &fullname, /* B */
1111 &homedir_len, &homedir, /* B */
1112 &dir_drive_len, &dir_drive, /* B */
1113 &logon_script_len, &logon_script, /* B */
1114 &profile_path_len, &profile_path, /* B */
1115 &acct_desc_len, &acct_desc, /* B */
1116 &workstations_len, &workstations, /* B */
1117 &unknown_str_len, &unknown_str, /* B */
1118 &munged_dial_len, &munged_dial, /* B */
1119 &user_rid, /* d */
1120 &group_rid, /* d */
1121 &lm_pw_len, &lm_pw_ptr, /* B */
1122 &nt_pw_len, &nt_pw_ptr, /* B */
1123 &acct_ctrl, /* w */
1124 &remove_me, /* d */
1125 &logon_divs, /* w */
1126 &hours_len, /* d */
1127 &hourslen, &hours, /* B */
1128 &bad_password_count, /* w */
1129 &logon_count, /* w */
1130 &unknown_6); /* d */
1132 if (len == (uint32) -1) {
1133 ret = False;
1134 goto done;
1137 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1138 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1139 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1141 /* Change from V0 is addition of bad_password_time field. */
1142 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1143 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1144 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1145 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1147 pdb_set_username(sampass, username, PDB_SET);
1148 pdb_set_domain(sampass, domain, PDB_SET);
1149 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1150 pdb_set_fullname(sampass, fullname, PDB_SET);
1152 if (homedir) {
1153 pdb_set_homedir(sampass, homedir, PDB_SET);
1155 else {
1156 pdb_set_homedir(sampass,
1157 talloc_sub_basic(sampass, username, domain,
1158 lp_logon_home()),
1159 PDB_DEFAULT);
1162 if (dir_drive)
1163 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1164 else {
1165 pdb_set_dir_drive(sampass,
1166 talloc_sub_basic(sampass, username, domain,
1167 lp_logon_drive()),
1168 PDB_DEFAULT);
1171 if (logon_script)
1172 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1173 else {
1174 pdb_set_logon_script(sampass,
1175 talloc_sub_basic(sampass, username, domain,
1176 lp_logon_script()),
1177 PDB_DEFAULT);
1180 if (profile_path) {
1181 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1182 } else {
1183 pdb_set_profile_path(sampass,
1184 talloc_sub_basic(sampass, username, domain,
1185 lp_logon_path()),
1186 PDB_DEFAULT);
1189 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1190 pdb_set_workstations(sampass, workstations, PDB_SET);
1191 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1193 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1194 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1195 ret = False;
1196 goto done;
1200 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1201 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1202 ret = False;
1203 goto done;
1207 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1209 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1210 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1211 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1212 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1213 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1214 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1215 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1216 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1217 pdb_set_hours(sampass, hours, PDB_SET);
1219 done:
1221 SAFE_FREE(username);
1222 SAFE_FREE(domain);
1223 SAFE_FREE(nt_username);
1224 SAFE_FREE(fullname);
1225 SAFE_FREE(homedir);
1226 SAFE_FREE(dir_drive);
1227 SAFE_FREE(logon_script);
1228 SAFE_FREE(profile_path);
1229 SAFE_FREE(acct_desc);
1230 SAFE_FREE(workstations);
1231 SAFE_FREE(munged_dial);
1232 SAFE_FREE(unknown_str);
1233 SAFE_FREE(lm_pw_ptr);
1234 SAFE_FREE(nt_pw_ptr);
1235 SAFE_FREE(hours);
1237 return ret;
1240 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1243 /* times are stored as 32bit integer
1244 take care on system with 64bit wide time_t
1245 --SSS */
1246 uint32 logon_time,
1247 logoff_time,
1248 kickoff_time,
1249 bad_password_time,
1250 pass_last_set_time,
1251 pass_can_change_time,
1252 pass_must_change_time;
1253 char *username = NULL;
1254 char *domain = NULL;
1255 char *nt_username = NULL;
1256 char *dir_drive = NULL;
1257 char *unknown_str = NULL;
1258 char *munged_dial = NULL;
1259 char *fullname = NULL;
1260 char *homedir = NULL;
1261 char *logon_script = NULL;
1262 char *profile_path = NULL;
1263 char *acct_desc = NULL;
1264 char *workstations = NULL;
1265 uint32 username_len, domain_len, nt_username_len,
1266 dir_drive_len, unknown_str_len, munged_dial_len,
1267 fullname_len, homedir_len, logon_script_len,
1268 profile_path_len, acct_desc_len, workstations_len;
1270 uint32 user_rid, group_rid, hours_len, unknown_6;
1271 uint16 acct_ctrl, logon_divs;
1272 uint16 bad_password_count, logon_count;
1273 uint8 *hours = NULL;
1274 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1275 uint32 len = 0;
1276 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1277 uint32 pwHistLen = 0;
1278 bool ret = True;
1279 fstring tmp_string;
1280 bool expand_explicit = lp_passdb_expand_explicit();
1282 if(sampass == NULL || buf == NULL) {
1283 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1284 return False;
1287 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1289 /* unpack the buffer into variables */
1290 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1291 &logon_time, /* d */
1292 &logoff_time, /* d */
1293 &kickoff_time, /* d */
1294 &bad_password_time, /* d */
1295 &pass_last_set_time, /* d */
1296 &pass_can_change_time, /* d */
1297 &pass_must_change_time, /* d */
1298 &username_len, &username, /* B */
1299 &domain_len, &domain, /* B */
1300 &nt_username_len, &nt_username, /* B */
1301 &fullname_len, &fullname, /* B */
1302 &homedir_len, &homedir, /* B */
1303 &dir_drive_len, &dir_drive, /* B */
1304 &logon_script_len, &logon_script, /* B */
1305 &profile_path_len, &profile_path, /* B */
1306 &acct_desc_len, &acct_desc, /* B */
1307 &workstations_len, &workstations, /* B */
1308 &unknown_str_len, &unknown_str, /* B */
1309 &munged_dial_len, &munged_dial, /* B */
1310 &user_rid, /* d */
1311 &group_rid, /* d */
1312 &lm_pw_len, &lm_pw_ptr, /* B */
1313 &nt_pw_len, &nt_pw_ptr, /* B */
1314 /* Change from V1 is addition of password history field. */
1315 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1316 &acct_ctrl, /* w */
1317 /* Also "remove_me" field was removed. */
1318 &logon_divs, /* w */
1319 &hours_len, /* d */
1320 &hourslen, &hours, /* B */
1321 &bad_password_count, /* w */
1322 &logon_count, /* w */
1323 &unknown_6); /* d */
1325 if (len == (uint32) -1) {
1326 ret = False;
1327 goto done;
1330 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1331 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1332 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1333 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1334 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1335 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1336 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1338 pdb_set_username(sampass, username, PDB_SET);
1339 pdb_set_domain(sampass, domain, PDB_SET);
1340 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1341 pdb_set_fullname(sampass, fullname, PDB_SET);
1343 if (homedir) {
1344 fstrcpy( tmp_string, homedir );
1345 if (expand_explicit) {
1346 standard_sub_basic( username, domain, tmp_string,
1347 sizeof(tmp_string) );
1349 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1351 else {
1352 pdb_set_homedir(sampass,
1353 talloc_sub_basic(sampass, username, domain,
1354 lp_logon_home()),
1355 PDB_DEFAULT);
1358 if (dir_drive)
1359 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1360 else
1361 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1363 if (logon_script) {
1364 fstrcpy( tmp_string, logon_script );
1365 if (expand_explicit) {
1366 standard_sub_basic( username, domain, tmp_string,
1367 sizeof(tmp_string) );
1369 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1371 else {
1372 pdb_set_logon_script(sampass,
1373 talloc_sub_basic(sampass, username, domain,
1374 lp_logon_script()),
1375 PDB_DEFAULT);
1378 if (profile_path) {
1379 fstrcpy( tmp_string, profile_path );
1380 if (expand_explicit) {
1381 standard_sub_basic( username, domain, tmp_string,
1382 sizeof(tmp_string) );
1384 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1386 else {
1387 pdb_set_profile_path(sampass,
1388 talloc_sub_basic(sampass, username, domain,
1389 lp_logon_path()),
1390 PDB_DEFAULT);
1393 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1394 pdb_set_workstations(sampass, workstations, PDB_SET);
1395 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1397 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1398 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1399 ret = False;
1400 goto done;
1404 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1405 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1406 ret = False;
1407 goto done;
1411 /* Change from V1 is addition of password history field. */
1412 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1413 if (pwHistLen) {
1414 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1415 if (!pw_hist) {
1416 ret = False;
1417 goto done;
1419 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1420 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1421 int i;
1422 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1423 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1424 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1425 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1426 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1427 PW_HISTORY_ENTRY_LEN);
1430 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1431 SAFE_FREE(pw_hist);
1432 ret = False;
1433 goto done;
1435 SAFE_FREE(pw_hist);
1436 } else {
1437 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1440 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1441 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1442 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1443 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1444 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1445 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1446 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1447 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1448 pdb_set_hours(sampass, hours, PDB_SET);
1450 done:
1452 SAFE_FREE(username);
1453 SAFE_FREE(domain);
1454 SAFE_FREE(nt_username);
1455 SAFE_FREE(fullname);
1456 SAFE_FREE(homedir);
1457 SAFE_FREE(dir_drive);
1458 SAFE_FREE(logon_script);
1459 SAFE_FREE(profile_path);
1460 SAFE_FREE(acct_desc);
1461 SAFE_FREE(workstations);
1462 SAFE_FREE(munged_dial);
1463 SAFE_FREE(unknown_str);
1464 SAFE_FREE(lm_pw_ptr);
1465 SAFE_FREE(nt_pw_ptr);
1466 SAFE_FREE(nt_pw_hist_ptr);
1467 SAFE_FREE(hours);
1469 return ret;
1472 /*********************************************************************
1473 *********************************************************************/
1475 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1478 /* times are stored as 32bit integer
1479 take care on system with 64bit wide time_t
1480 --SSS */
1481 uint32 logon_time,
1482 logoff_time,
1483 kickoff_time,
1484 bad_password_time,
1485 pass_last_set_time,
1486 pass_can_change_time,
1487 pass_must_change_time;
1488 char *username = NULL;
1489 char *domain = NULL;
1490 char *nt_username = NULL;
1491 char *dir_drive = NULL;
1492 char *unknown_str = NULL;
1493 char *munged_dial = NULL;
1494 char *fullname = NULL;
1495 char *homedir = NULL;
1496 char *logon_script = NULL;
1497 char *profile_path = NULL;
1498 char *acct_desc = NULL;
1499 char *workstations = NULL;
1500 uint32 username_len, domain_len, nt_username_len,
1501 dir_drive_len, unknown_str_len, munged_dial_len,
1502 fullname_len, homedir_len, logon_script_len,
1503 profile_path_len, acct_desc_len, workstations_len;
1505 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1506 uint16 logon_divs;
1507 uint16 bad_password_count, logon_count;
1508 uint8 *hours = NULL;
1509 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1510 uint32 len = 0;
1511 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1512 uint32 pwHistLen = 0;
1513 bool ret = True;
1514 fstring tmp_string;
1515 bool expand_explicit = lp_passdb_expand_explicit();
1517 if(sampass == NULL || buf == NULL) {
1518 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1519 return False;
1522 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1524 /* unpack the buffer into variables */
1525 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1526 &logon_time, /* d */
1527 &logoff_time, /* d */
1528 &kickoff_time, /* d */
1529 &bad_password_time, /* d */
1530 &pass_last_set_time, /* d */
1531 &pass_can_change_time, /* d */
1532 &pass_must_change_time, /* d */
1533 &username_len, &username, /* B */
1534 &domain_len, &domain, /* B */
1535 &nt_username_len, &nt_username, /* B */
1536 &fullname_len, &fullname, /* B */
1537 &homedir_len, &homedir, /* B */
1538 &dir_drive_len, &dir_drive, /* B */
1539 &logon_script_len, &logon_script, /* B */
1540 &profile_path_len, &profile_path, /* B */
1541 &acct_desc_len, &acct_desc, /* B */
1542 &workstations_len, &workstations, /* B */
1543 &unknown_str_len, &unknown_str, /* B */
1544 &munged_dial_len, &munged_dial, /* B */
1545 &user_rid, /* d */
1546 &group_rid, /* d */
1547 &lm_pw_len, &lm_pw_ptr, /* B */
1548 &nt_pw_len, &nt_pw_ptr, /* B */
1549 /* Change from V1 is addition of password history field. */
1550 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1551 /* Change from V2 is the uint32 acb_mask */
1552 &acct_ctrl, /* d */
1553 /* Also "remove_me" field was removed. */
1554 &logon_divs, /* w */
1555 &hours_len, /* d */
1556 &hourslen, &hours, /* B */
1557 &bad_password_count, /* w */
1558 &logon_count, /* w */
1559 &unknown_6); /* d */
1561 if (len == (uint32) -1) {
1562 ret = False;
1563 goto done;
1566 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1567 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1568 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1569 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1570 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1571 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1572 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1574 pdb_set_username(sampass, username, PDB_SET);
1575 pdb_set_domain(sampass, domain, PDB_SET);
1576 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1577 pdb_set_fullname(sampass, fullname, PDB_SET);
1579 if (homedir) {
1580 fstrcpy( tmp_string, homedir );
1581 if (expand_explicit) {
1582 standard_sub_basic( username, domain, tmp_string,
1583 sizeof(tmp_string) );
1585 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1587 else {
1588 pdb_set_homedir(sampass,
1589 talloc_sub_basic(sampass, username, domain,
1590 lp_logon_home()),
1591 PDB_DEFAULT);
1594 if (dir_drive)
1595 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1596 else
1597 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1599 if (logon_script) {
1600 fstrcpy( tmp_string, logon_script );
1601 if (expand_explicit) {
1602 standard_sub_basic( username, domain, tmp_string,
1603 sizeof(tmp_string) );
1605 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1607 else {
1608 pdb_set_logon_script(sampass,
1609 talloc_sub_basic(sampass, username, domain,
1610 lp_logon_script()),
1611 PDB_DEFAULT);
1614 if (profile_path) {
1615 fstrcpy( tmp_string, profile_path );
1616 if (expand_explicit) {
1617 standard_sub_basic( username, domain, tmp_string,
1618 sizeof(tmp_string) );
1620 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1622 else {
1623 pdb_set_profile_path(sampass,
1624 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1625 PDB_DEFAULT);
1628 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1629 pdb_set_workstations(sampass, workstations, PDB_SET);
1630 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1632 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1633 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1634 ret = False;
1635 goto done;
1639 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1640 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1641 ret = False;
1642 goto done;
1646 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1647 if (pwHistLen) {
1648 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1649 if (!pw_hist) {
1650 ret = False;
1651 goto done;
1653 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1654 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1655 int i;
1656 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1657 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1658 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1659 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1660 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1661 PW_HISTORY_ENTRY_LEN);
1664 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1665 SAFE_FREE(pw_hist);
1666 ret = False;
1667 goto done;
1669 SAFE_FREE(pw_hist);
1670 } else {
1671 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1674 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1675 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1676 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1677 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1678 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1679 /* Change from V2 is the uint32 acct_ctrl */
1680 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1681 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1682 pdb_set_hours(sampass, hours, PDB_SET);
1684 done:
1686 SAFE_FREE(username);
1687 SAFE_FREE(domain);
1688 SAFE_FREE(nt_username);
1689 SAFE_FREE(fullname);
1690 SAFE_FREE(homedir);
1691 SAFE_FREE(dir_drive);
1692 SAFE_FREE(logon_script);
1693 SAFE_FREE(profile_path);
1694 SAFE_FREE(acct_desc);
1695 SAFE_FREE(workstations);
1696 SAFE_FREE(munged_dial);
1697 SAFE_FREE(unknown_str);
1698 SAFE_FREE(lm_pw_ptr);
1699 SAFE_FREE(nt_pw_ptr);
1700 SAFE_FREE(nt_pw_hist_ptr);
1701 SAFE_FREE(hours);
1703 return ret;
1706 /*********************************************************************
1707 *********************************************************************/
1709 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1711 size_t len, buflen;
1713 /* times are stored as 32bit integer
1714 take care on system with 64bit wide time_t
1715 --SSS */
1716 uint32 logon_time,
1717 logoff_time,
1718 kickoff_time,
1719 bad_password_time,
1720 pass_last_set_time,
1721 pass_can_change_time,
1722 pass_must_change_time;
1724 uint32 user_rid, group_rid;
1726 const char *username;
1727 const char *domain;
1728 const char *nt_username;
1729 const char *dir_drive;
1730 const char *unknown_str;
1731 const char *munged_dial;
1732 const char *fullname;
1733 const char *homedir;
1734 const char *logon_script;
1735 const char *profile_path;
1736 const char *acct_desc;
1737 const char *workstations;
1738 uint32 username_len, domain_len, nt_username_len,
1739 dir_drive_len, unknown_str_len, munged_dial_len,
1740 fullname_len, homedir_len, logon_script_len,
1741 profile_path_len, acct_desc_len, workstations_len;
1743 const uint8 *lm_pw;
1744 const uint8 *nt_pw;
1745 const uint8 *nt_pw_hist;
1746 uint32 lm_pw_len = 16;
1747 uint32 nt_pw_len = 16;
1748 uint32 nt_pw_hist_len;
1749 uint32 pwHistLen = 0;
1751 *buf = NULL;
1752 buflen = 0;
1754 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1755 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1756 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1757 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1758 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1759 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1760 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1762 user_rid = pdb_get_user_rid(sampass);
1763 group_rid = pdb_get_group_rid(sampass);
1765 username = pdb_get_username(sampass);
1766 if (username) {
1767 username_len = strlen(username) +1;
1768 } else {
1769 username_len = 0;
1772 domain = pdb_get_domain(sampass);
1773 if (domain) {
1774 domain_len = strlen(domain) +1;
1775 } else {
1776 domain_len = 0;
1779 nt_username = pdb_get_nt_username(sampass);
1780 if (nt_username) {
1781 nt_username_len = strlen(nt_username) +1;
1782 } else {
1783 nt_username_len = 0;
1786 fullname = pdb_get_fullname(sampass);
1787 if (fullname) {
1788 fullname_len = strlen(fullname) +1;
1789 } else {
1790 fullname_len = 0;
1794 * Only updates fields which have been set (not defaults from smb.conf)
1797 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1798 dir_drive = pdb_get_dir_drive(sampass);
1799 } else {
1800 dir_drive = NULL;
1802 if (dir_drive) {
1803 dir_drive_len = strlen(dir_drive) +1;
1804 } else {
1805 dir_drive_len = 0;
1808 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1809 homedir = pdb_get_homedir(sampass);
1810 } else {
1811 homedir = NULL;
1813 if (homedir) {
1814 homedir_len = strlen(homedir) +1;
1815 } else {
1816 homedir_len = 0;
1819 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1820 logon_script = pdb_get_logon_script(sampass);
1821 } else {
1822 logon_script = NULL;
1824 if (logon_script) {
1825 logon_script_len = strlen(logon_script) +1;
1826 } else {
1827 logon_script_len = 0;
1830 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1831 profile_path = pdb_get_profile_path(sampass);
1832 } else {
1833 profile_path = NULL;
1835 if (profile_path) {
1836 profile_path_len = strlen(profile_path) +1;
1837 } else {
1838 profile_path_len = 0;
1841 lm_pw = pdb_get_lanman_passwd(sampass);
1842 if (!lm_pw) {
1843 lm_pw_len = 0;
1846 nt_pw = pdb_get_nt_passwd(sampass);
1847 if (!nt_pw) {
1848 nt_pw_len = 0;
1851 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1852 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1853 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1854 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1855 } else {
1856 nt_pw_hist_len = 0;
1859 acct_desc = pdb_get_acct_desc(sampass);
1860 if (acct_desc) {
1861 acct_desc_len = strlen(acct_desc) +1;
1862 } else {
1863 acct_desc_len = 0;
1866 workstations = pdb_get_workstations(sampass);
1867 if (workstations) {
1868 workstations_len = strlen(workstations) +1;
1869 } else {
1870 workstations_len = 0;
1873 unknown_str = NULL;
1874 unknown_str_len = 0;
1876 munged_dial = pdb_get_munged_dial(sampass);
1877 if (munged_dial) {
1878 munged_dial_len = strlen(munged_dial) +1;
1879 } else {
1880 munged_dial_len = 0;
1883 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1885 /* one time to get the size needed */
1886 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1887 logon_time, /* d */
1888 logoff_time, /* d */
1889 kickoff_time, /* d */
1890 bad_password_time, /* d */
1891 pass_last_set_time, /* d */
1892 pass_can_change_time, /* d */
1893 pass_must_change_time, /* d */
1894 username_len, username, /* B */
1895 domain_len, domain, /* B */
1896 nt_username_len, nt_username, /* B */
1897 fullname_len, fullname, /* B */
1898 homedir_len, homedir, /* B */
1899 dir_drive_len, dir_drive, /* B */
1900 logon_script_len, logon_script, /* B */
1901 profile_path_len, profile_path, /* B */
1902 acct_desc_len, acct_desc, /* B */
1903 workstations_len, workstations, /* B */
1904 unknown_str_len, unknown_str, /* B */
1905 munged_dial_len, munged_dial, /* B */
1906 user_rid, /* d */
1907 group_rid, /* d */
1908 lm_pw_len, lm_pw, /* B */
1909 nt_pw_len, nt_pw, /* B */
1910 nt_pw_hist_len, nt_pw_hist, /* B */
1911 pdb_get_acct_ctrl(sampass), /* d */
1912 pdb_get_logon_divs(sampass), /* w */
1913 pdb_get_hours_len(sampass), /* d */
1914 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1915 pdb_get_bad_password_count(sampass), /* w */
1916 pdb_get_logon_count(sampass), /* w */
1917 pdb_get_unknown_6(sampass)); /* d */
1919 if (size_only) {
1920 return buflen;
1923 /* malloc the space needed */
1924 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1925 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1926 return (-1);
1929 /* now for the real call to tdb_pack() */
1930 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1931 logon_time, /* d */
1932 logoff_time, /* d */
1933 kickoff_time, /* d */
1934 bad_password_time, /* d */
1935 pass_last_set_time, /* d */
1936 pass_can_change_time, /* d */
1937 pass_must_change_time, /* d */
1938 username_len, username, /* B */
1939 domain_len, domain, /* B */
1940 nt_username_len, nt_username, /* B */
1941 fullname_len, fullname, /* B */
1942 homedir_len, homedir, /* B */
1943 dir_drive_len, dir_drive, /* B */
1944 logon_script_len, logon_script, /* B */
1945 profile_path_len, profile_path, /* B */
1946 acct_desc_len, acct_desc, /* B */
1947 workstations_len, workstations, /* B */
1948 unknown_str_len, unknown_str, /* B */
1949 munged_dial_len, munged_dial, /* B */
1950 user_rid, /* d */
1951 group_rid, /* d */
1952 lm_pw_len, lm_pw, /* B */
1953 nt_pw_len, nt_pw, /* B */
1954 nt_pw_hist_len, nt_pw_hist, /* B */
1955 pdb_get_acct_ctrl(sampass), /* d */
1956 pdb_get_logon_divs(sampass), /* w */
1957 pdb_get_hours_len(sampass), /* d */
1958 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1959 pdb_get_bad_password_count(sampass), /* w */
1960 pdb_get_logon_count(sampass), /* w */
1961 pdb_get_unknown_6(sampass)); /* d */
1963 /* check to make sure we got it correct */
1964 if (buflen != len) {
1965 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1966 (unsigned long)buflen, (unsigned long)len));
1967 /* error */
1968 SAFE_FREE (*buf);
1969 return (-1);
1972 return (buflen);
1975 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
1977 /* nothing changed between V3 and V4 */
1978 return init_samu_from_buffer_v3(sampass, buf, buflen);
1981 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
1983 /* nothing changed between V3 and V4 */
1984 return init_buffer_from_samu_v3(buf, sampass, size_only);
1987 /**********************************************************************
1988 Intialize a struct samu struct from a BYTE buffer of size len
1989 *********************************************************************/
1991 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
1992 uint8 *buf, uint32 buflen)
1994 switch (level) {
1995 case SAMU_BUFFER_V0:
1996 return init_samu_from_buffer_v0(sampass, buf, buflen);
1997 case SAMU_BUFFER_V1:
1998 return init_samu_from_buffer_v1(sampass, buf, buflen);
1999 case SAMU_BUFFER_V2:
2000 return init_samu_from_buffer_v2(sampass, buf, buflen);
2001 case SAMU_BUFFER_V3:
2002 return init_samu_from_buffer_v3(sampass, buf, buflen);
2003 case SAMU_BUFFER_V4:
2004 return init_samu_from_buffer_v4(sampass, buf, buflen);
2007 return false;
2010 /**********************************************************************
2011 Intialize a BYTE buffer from a struct samu struct
2012 *********************************************************************/
2014 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2016 return init_buffer_from_samu_v4(buf, sampass, size_only);
2019 /*********************************************************************
2020 *********************************************************************/
2022 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2024 uint8 *buf = NULL;
2025 int len;
2027 len = init_buffer_from_samu(&buf, src, False);
2028 if (len == -1 || !buf) {
2029 SAFE_FREE(buf);
2030 return False;
2033 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2034 free(buf);
2035 return False;
2038 dst->methods = src->methods;
2040 if ( src->unix_pw ) {
2041 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2042 if (!dst->unix_pw) {
2043 free(buf);
2044 return False;
2048 free(buf);
2049 return True;
2052 /*********************************************************************
2053 Update the bad password count checking the AP_RESET_COUNT_TIME
2054 *********************************************************************/
2056 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2058 time_t LastBadPassword;
2059 uint16 BadPasswordCount;
2060 uint32 resettime;
2061 bool res;
2063 BadPasswordCount = pdb_get_bad_password_count(sampass);
2064 if (!BadPasswordCount) {
2065 DEBUG(9, ("No bad password attempts.\n"));
2066 return True;
2069 become_root();
2070 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
2071 unbecome_root();
2073 if (!res) {
2074 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2075 return False;
2078 /* First, check if there is a reset time to compare */
2079 if ((resettime == (uint32) -1) || (resettime == 0)) {
2080 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2081 return True;
2084 LastBadPassword = pdb_get_bad_password_time(sampass);
2085 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2086 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2087 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2088 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2089 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2090 if (updated) {
2091 *updated = True;
2095 return True;
2098 /*********************************************************************
2099 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
2100 *********************************************************************/
2102 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2104 uint32 duration;
2105 time_t LastBadPassword;
2106 bool res;
2108 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2109 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2110 pdb_get_username(sampass)));
2111 return True;
2114 become_root();
2115 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
2116 unbecome_root();
2118 if (!res) {
2119 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2120 return False;
2123 /* First, check if there is a duration to compare */
2124 if ((duration == (uint32) -1) || (duration == 0)) {
2125 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2126 return True;
2129 LastBadPassword = pdb_get_bad_password_time(sampass);
2130 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2131 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2133 if (LastBadPassword == (time_t)0) {
2134 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2135 "administratively locked out with no bad password "
2136 "time. Leaving locked out.\n",
2137 pdb_get_username(sampass) ));
2138 return True;
2141 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2142 pdb_set_acct_ctrl(sampass,
2143 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2144 PDB_CHANGED);
2145 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2146 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2147 if (updated) {
2148 *updated = True;
2152 return True;
2155 /*********************************************************************
2156 Increment the bad_password_count
2157 *********************************************************************/
2159 bool pdb_increment_bad_password_count(struct samu *sampass)
2161 uint32 account_policy_lockout;
2162 bool autolock_updated = False, badpw_updated = False;
2163 bool ret;
2165 /* Retrieve the account lockout policy */
2166 become_root();
2167 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2168 unbecome_root();
2169 if ( !ret ) {
2170 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2171 return False;
2174 /* If there is no policy, we don't need to continue checking */
2175 if (!account_policy_lockout) {
2176 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2177 return True;
2180 /* Check if the autolock needs to be cleared */
2181 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2182 return False;
2184 /* Check if the badpw count needs to be reset */
2185 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2186 return False;
2189 Ok, now we can assume that any resetting that needs to be
2190 done has been done, and just get on with incrementing
2191 and autolocking if necessary
2194 pdb_set_bad_password_count(sampass,
2195 pdb_get_bad_password_count(sampass)+1,
2196 PDB_CHANGED);
2197 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2200 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2201 return True;
2203 if (!pdb_set_acct_ctrl(sampass,
2204 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2205 PDB_CHANGED)) {
2206 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2207 return False;
2210 return True;
2213 bool is_dc_trusted_domain_situation(const char *domain_name)
2215 return IS_DC && !strequal(domain_name, lp_workgroup());
2218 /*******************************************************************
2219 Wrapper around retrieving the clear text trust account password.
2220 appropriate account name is stored in account_name.
2221 Caller must free password, but not account_name.
2222 *******************************************************************/
2224 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2225 const char **account_name, uint32 *channel)
2227 char *pwd;
2228 time_t last_set_time;
2230 /* if we are a DC and this is not our domain, then lookup an account
2231 * for the domain trust */
2233 if (is_dc_trusted_domain_situation(domain)) {
2234 if (!lp_allow_trusted_domains()) {
2235 return false;
2238 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2239 &last_set_time))
2241 DEBUG(0, ("get_trust_pw: could not fetch trust "
2242 "account password for trusted domain %s\n",
2243 domain));
2244 return false;
2247 if (channel != NULL) {
2248 *channel = SEC_CHAN_DOMAIN;
2251 if (account_name != NULL) {
2252 *account_name = lp_workgroup();
2255 return true;
2259 * Since we can only be member of one single domain, we are now
2260 * in a member situation:
2262 * - Either we are a DC (selfjoined) and the domain is our
2263 * own domain.
2264 * - Or we are on a member and the domain is our own or some
2265 * other (potentially trusted) domain.
2267 * In both cases, we can only get the machine account password
2268 * for our own domain to connect to our own dc. (For a member,
2269 * request to trusted domains are performed through our dc.)
2271 * So we simply use our own domain name to retrieve the
2272 * machine account passowrd and ignore the request domain here.
2275 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2277 if (pwd != NULL) {
2278 *ret_pwd = pwd;
2279 if (account_name != NULL) {
2280 *account_name = global_myname();
2283 return true;
2286 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2287 "account password for domain %s\n", domain));
2288 return false;
2291 /*******************************************************************
2292 Wrapper around retrieving the trust account password.
2293 appropriate account name is stored in account_name.
2294 *******************************************************************/
2296 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2297 const char **account_name, uint32 *channel)
2299 char *pwd = NULL;
2300 time_t last_set_time;
2302 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2303 E_md4hash(pwd, ret_pwd);
2304 SAFE_FREE(pwd);
2305 return true;
2306 } else if (is_dc_trusted_domain_situation(domain)) {
2307 return false;
2310 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2312 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2313 &last_set_time,
2314 channel))
2316 if (account_name != NULL) {
2317 *account_name = global_myname();
2320 return true;
2323 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2324 "password for domain %s\n", domain));
2325 return False;
2328 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2329 struct samu *pw)
2331 struct samr_LogonHours hours;
2332 const int units_per_week = 168;
2334 ZERO_STRUCT(hours);
2335 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2336 if (!hours.bits) {
2337 return hours;
2340 hours.units_per_week = units_per_week;
2341 memset(hours.bits, 0xFF, units_per_week);
2343 if (pdb_get_hours(pw)) {
2344 memcpy(hours.bits, pdb_get_hours(pw),
2345 MIN(pdb_get_hours_len(pw), units_per_week));
2348 return hours;
2351 /****************************************************************
2352 ****************************************************************/
2354 NTSTATUS smb_create_user(TALLOC_CTX *mem_ctx,
2355 uint32_t acct_flags,
2356 const char *account,
2357 struct passwd **passwd_p)
2359 struct passwd *passwd;
2360 char *add_script = NULL;
2362 passwd = Get_Pwnam_alloc(mem_ctx, account);
2363 if (passwd) {
2364 *passwd_p = passwd;
2365 return NT_STATUS_OK;
2368 /* Create appropriate user */
2369 if (acct_flags & ACB_NORMAL) {
2370 add_script = talloc_strdup(mem_ctx, lp_adduser_script());
2371 } else if ( (acct_flags & ACB_WSTRUST) ||
2372 (acct_flags & ACB_SVRTRUST) ||
2373 (acct_flags & ACB_DOMTRUST) ) {
2374 add_script = talloc_strdup(mem_ctx, lp_addmachine_script());
2375 } else {
2376 DEBUG(1, ("Unknown user type: %s\n",
2377 pdb_encode_acct_ctrl(acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
2378 return NT_STATUS_UNSUCCESSFUL;
2381 if (!add_script) {
2382 return NT_STATUS_NO_MEMORY;
2385 if (*add_script) {
2386 int add_ret;
2387 add_script = talloc_all_string_sub(mem_ctx, add_script,
2388 "%u", account);
2389 if (!add_script) {
2390 return NT_STATUS_NO_MEMORY;
2392 add_ret = smbrun(add_script, NULL);
2393 DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
2394 "gave %d\n", add_script, add_ret));
2395 if (add_ret == 0) {
2396 smb_nscd_flush_user_cache();
2400 /* try and find the possible unix account again */
2401 passwd = Get_Pwnam_alloc(mem_ctx, account);
2402 if (!passwd) {
2403 return NT_STATUS_NO_SUCH_USER;
2406 *passwd_p = passwd;
2408 return NT_STATUS_OK;