docs: Improve description of the share commands in man smb.conf.
[Samba/gebeck_regimport.git] / source3 / passdb / passdb.c
blobe677d429afa090c4c481646ee17c953832757d67
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. For example, if you connect
33 to a Windows member server using a bogus domain name, the
34 Windows box will map the BOGUS\user to DOMAIN\user. A
35 standalone box will map to WKS\user.
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 /* Windows domain members default to the DOMAIN
45 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;
123 return user;
126 /*********************************************************************
127 Initialize a struct samu from a struct passwd including the user
128 and group SIDs. The *user structure is filled out with the Unix
129 attributes and a user SID.
130 *********************************************************************/
132 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
134 const char *guest_account = lp_guestaccount();
135 const char *domain = global_myname();
136 uint32 urid;
138 if ( !pwd ) {
139 return NT_STATUS_NO_SUCH_USER;
142 /* Basic properties based upon the Unix account information */
144 pdb_set_username(user, pwd->pw_name, PDB_SET);
145 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
146 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
147 #if 0
148 /* This can lead to a primary group of S-1-22-2-XX which
149 will be rejected by other parts of the Samba code.
150 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
151 --jerry */
153 gid_to_sid(&group_sid, pwd->pw_gid);
154 pdb_set_group_sid(user, &group_sid, PDB_SET);
155 #endif
157 /* save the password structure for later use */
159 user->unix_pw = tcopy_passwd( user, pwd );
161 /* Special case for the guest account which must have a RID of 501 */
163 if ( strequal( pwd->pw_name, guest_account ) ) {
164 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
165 return NT_STATUS_NO_SUCH_USER;
167 return NT_STATUS_OK;
170 /* Non-guest accounts...Check for a workstation or user account */
172 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
173 /* workstation */
175 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
176 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
177 pwd->pw_name));
178 return NT_STATUS_INVALID_COMPUTER_NAME;
181 else {
182 /* user */
184 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
185 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
186 pwd->pw_name));
187 return NT_STATUS_INVALID_ACCOUNT_NAME;
190 /* set some basic attributes */
192 pdb_set_profile_path(user, talloc_sub_specified(user,
193 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
194 PDB_DEFAULT);
195 pdb_set_homedir(user, talloc_sub_specified(user,
196 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
197 PDB_DEFAULT);
198 pdb_set_dir_drive(user, talloc_sub_specified(user,
199 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
200 PDB_DEFAULT);
201 pdb_set_logon_script(user, talloc_sub_specified(user,
202 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
203 PDB_DEFAULT);
206 /* Now deal with the user SID. If we have a backend that can generate
207 RIDs, then do so. But sometimes the caller just wanted a structure
208 initialized and will fill in these fields later (such as from a
209 netr_SamInfo3 structure) */
211 if ( create && !pdb_rid_algorithm() ) {
212 uint32 user_rid;
213 DOM_SID user_sid;
215 if ( !pdb_new_rid( &user_rid ) ) {
216 DEBUG(3, ("Could not allocate a new RID\n"));
217 return NT_STATUS_ACCESS_DENIED;
220 sid_copy( &user_sid, get_global_sam_sid() );
221 sid_append_rid( &user_sid, user_rid );
223 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
224 DEBUG(3, ("pdb_set_user_sid failed\n"));
225 return NT_STATUS_INTERNAL_ERROR;
228 return NT_STATUS_OK;
231 /* generate a SID for the user with the RID algorithm */
233 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
235 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
236 return NT_STATUS_INTERNAL_ERROR;
239 return NT_STATUS_OK;
242 /********************************************************************
243 Set the Unix user attributes
244 ********************************************************************/
246 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
248 return samu_set_unix_internal( user, pwd, False );
251 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
253 return samu_set_unix_internal( user, pwd, True );
256 /**********************************************************
257 Encode the account control bits into a string.
258 length = length of string to encode into (including terminating
259 null). length *MUST BE MORE THAN 2* !
260 **********************************************************/
262 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
264 fstring acct_str;
265 char *result;
267 size_t i = 0;
269 SMB_ASSERT(length <= sizeof(acct_str));
271 acct_str[i++] = '[';
273 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
274 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
275 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
276 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
277 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
278 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
279 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
280 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
281 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
282 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
283 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
285 for ( ; i < length - 2 ; i++ )
286 acct_str[i] = ' ';
288 i = length - 2;
289 acct_str[i++] = ']';
290 acct_str[i++] = '\0';
292 result = talloc_strdup(talloc_tos(), acct_str);
293 SMB_ASSERT(result != NULL);
294 return result;
297 /**********************************************************
298 Decode the account control bits from a string.
299 **********************************************************/
301 uint32_t pdb_decode_acct_ctrl(const char *p)
303 uint32_t acct_ctrl = 0;
304 bool finished = false;
307 * Check if the account type bits have been encoded after the
308 * NT password (in the form [NDHTUWSLXI]).
311 if (*p != '[')
312 return 0;
314 for (p++; *p && !finished; p++) {
315 switch (*p) {
316 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
317 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
318 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
319 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
320 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
321 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
322 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
323 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
324 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
325 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
326 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
327 case ' ': { break; }
328 case ':':
329 case '\n':
330 case '\0':
331 case ']':
332 default: { finished = true; }
336 return acct_ctrl;
339 /*************************************************************
340 Routine to set 32 hex password characters from a 16 byte array.
341 **************************************************************/
343 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
345 if (pwd != NULL) {
346 int i;
347 for (i = 0; i < 16; i++)
348 slprintf(&p[i*2], 3, "%02X", pwd[i]);
349 } else {
350 if (acct_ctrl & ACB_PWNOTREQ)
351 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
352 else
353 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
357 /*************************************************************
358 Routine to get the 32 hex characters and turn them
359 into a 16 byte array.
360 **************************************************************/
362 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
364 int i;
365 unsigned char lonybble, hinybble;
366 const char *hexchars = "0123456789ABCDEF";
367 char *p1, *p2;
369 if (!p)
370 return false;
372 for (i = 0; i < 32; i += 2) {
373 hinybble = toupper_ascii(p[i]);
374 lonybble = toupper_ascii(p[i + 1]);
376 p1 = strchr(hexchars, hinybble);
377 p2 = strchr(hexchars, lonybble);
379 if (!p1 || !p2)
380 return false;
382 hinybble = PTR_DIFF(p1, hexchars);
383 lonybble = PTR_DIFF(p2, hexchars);
385 pwd[i / 2] = (hinybble << 4) | lonybble;
387 return true;
390 /*************************************************************
391 Routine to set 42 hex hours characters from a 21 byte array.
392 **************************************************************/
394 void pdb_sethexhours(char *p, const unsigned char *hours)
396 if (hours != NULL) {
397 int i;
398 for (i = 0; i < 21; i++) {
399 slprintf(&p[i*2], 3, "%02X", hours[i]);
401 } else {
402 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
406 /*************************************************************
407 Routine to get the 42 hex characters and turn them
408 into a 21 byte array.
409 **************************************************************/
411 bool pdb_gethexhours(const char *p, unsigned char *hours)
413 int i;
414 unsigned char lonybble, hinybble;
415 const char *hexchars = "0123456789ABCDEF";
416 char *p1, *p2;
418 if (!p) {
419 return (False);
422 for (i = 0; i < 42; i += 2) {
423 hinybble = toupper_ascii(p[i]);
424 lonybble = toupper_ascii(p[i + 1]);
426 p1 = strchr(hexchars, hinybble);
427 p2 = strchr(hexchars, lonybble);
429 if (!p1 || !p2) {
430 return (False);
433 hinybble = PTR_DIFF(p1, hexchars);
434 lonybble = PTR_DIFF(p2, hexchars);
436 hours[i / 2] = (hinybble << 4) | lonybble;
438 return (True);
441 /********************************************************************
442 ********************************************************************/
444 int algorithmic_rid_base(void)
446 int rid_offset;
448 rid_offset = lp_algorithmic_rid_base();
450 if (rid_offset < BASE_RID) {
451 /* Try to prevent admin foot-shooting, we can't put algorithmic
452 rids below 1000, that's the 'well known RIDs' on NT */
453 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
454 rid_offset = BASE_RID;
456 if (rid_offset & 1) {
457 DEBUG(0, ("algorithmic rid base must be even\n"));
458 rid_offset += 1;
460 return rid_offset;
463 /*******************************************************************
464 Converts NT user RID to a UNIX uid.
465 ********************************************************************/
467 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
469 int rid_offset = algorithmic_rid_base();
470 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
473 uid_t max_algorithmic_uid(void)
475 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
478 /*******************************************************************
479 converts UNIX uid to an NT User RID.
480 ********************************************************************/
482 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
484 int rid_offset = algorithmic_rid_base();
485 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
488 /*******************************************************************
489 Converts NT group RID to a UNIX gid.
490 ********************************************************************/
492 gid_t pdb_group_rid_to_gid(uint32 group_rid)
494 int rid_offset = algorithmic_rid_base();
495 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
498 gid_t max_algorithmic_gid(void)
500 return pdb_group_rid_to_gid(0xffffffff);
503 /*******************************************************************
504 converts NT Group RID to a UNIX uid.
506 warning: you must not call that function only
507 you must do a call to the group mapping first.
508 there is not anymore a direct link between the gid and the rid.
509 ********************************************************************/
511 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
513 int rid_offset = algorithmic_rid_base();
514 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
517 /*******************************************************************
518 Decides if a RID is a well known RID.
519 ********************************************************************/
521 static bool rid_is_well_known(uint32 rid)
523 /* Not using rid_offset here, because this is the actual
524 NT fixed value (1000) */
526 return (rid < BASE_RID);
529 /*******************************************************************
530 Decides if a RID is a user or group RID.
531 ********************************************************************/
533 bool algorithmic_pdb_rid_is_user(uint32 rid)
535 if ( rid_is_well_known(rid) ) {
537 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
538 * and DOMAIN_USER_RID_GUEST.
540 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
541 return True;
542 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
543 return True;
545 return False;
548 /*******************************************************************
549 Convert a name into a SID. Used in the lookup name rpc.
550 ********************************************************************/
552 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
553 enum lsa_SidType *type)
555 GROUP_MAP map;
556 bool ret;
558 /* Windows treats "MACHINE\None" as a special name for
559 rid 513 on non-DCs. You cannot create a user or group
560 name "None" on Windows. You will get an error that
561 the group already exists. */
563 if ( strequal( name, "None" ) ) {
564 *rid = DOMAIN_GROUP_RID_USERS;
565 *type = SID_NAME_DOM_GRP;
567 return True;
570 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
571 * correctly in the case where foo also exists as a user. If the flag
572 * is set, don't look for users at all. */
574 if ((flags & LOOKUP_NAME_GROUP) == 0) {
575 struct samu *sam_account = NULL;
576 DOM_SID user_sid;
578 if ( !(sam_account = samu_new( NULL )) ) {
579 return False;
582 become_root();
583 ret = pdb_getsampwnam(sam_account, name);
584 unbecome_root();
586 if (ret) {
587 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
590 TALLOC_FREE(sam_account);
592 if (ret) {
593 if (!sid_check_is_in_our_domain(&user_sid)) {
594 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
595 name, sid_string_dbg(&user_sid)));
596 return False;
599 sid_peek_rid(&user_sid, rid);
600 *type = SID_NAME_USER;
601 return True;
606 * Maybe it is a group ?
609 become_root();
610 ret = pdb_getgrnam(&map, name);
611 unbecome_root();
613 if (!ret) {
614 return False;
617 /* BUILTIN groups are looked up elsewhere */
618 if (!sid_check_is_in_our_domain(&map.sid)) {
619 DEBUG(10, ("Found group %s (%s) not in our domain -- "
620 "ignoring.", name, sid_string_dbg(&map.sid)));
621 return False;
624 /* yes it's a mapped group */
625 sid_peek_rid(&map.sid, rid);
626 *type = map.sid_name_use;
627 return True;
630 /*************************************************************
631 Change a password entry in the local smbpasswd file.
632 *************************************************************/
634 NTSTATUS local_password_change(const char *user_name,
635 int local_flags,
636 const char *new_passwd,
637 char **pp_err_str,
638 char **pp_msg_str)
640 struct samu *sam_pass=NULL;
641 uint32 other_acb;
642 NTSTATUS result;
644 *pp_err_str = NULL;
645 *pp_msg_str = NULL;
647 /* Get the smb passwd entry for this user */
649 if ( !(sam_pass = samu_new( NULL )) ) {
650 return NT_STATUS_NO_MEMORY;
653 become_root();
654 if(!pdb_getsampwnam(sam_pass, user_name)) {
655 unbecome_root();
656 TALLOC_FREE(sam_pass);
658 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
659 int tmp_debug = DEBUGLEVEL;
660 struct passwd *pwd;
662 /* Might not exist in /etc/passwd. */
664 if (tmp_debug < 1) {
665 DEBUGLEVEL = 1;
668 if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), user_name)) ) {
669 return NT_STATUS_NO_SUCH_USER;
672 /* create the struct samu and initialize the basic Unix properties */
674 if ( !(sam_pass = samu_new( NULL )) ) {
675 return NT_STATUS_NO_MEMORY;
678 result = samu_set_unix( sam_pass, pwd );
680 DEBUGLEVEL = tmp_debug;
682 TALLOC_FREE( pwd );
684 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
685 return result;
688 if (!NT_STATUS_IS_OK(result)) {
689 if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
690 user_name, nt_errstr(result)) < 0) {
691 *pp_err_str = NULL;
693 return result;
695 } else {
696 if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) {
697 *pp_err_str = NULL;
699 return NT_STATUS_NO_SUCH_USER;
701 } else {
702 unbecome_root();
703 /* the entry already existed */
704 local_flags &= ~LOCAL_ADD_USER;
707 /* the 'other' acb bits not being changed here */
708 other_acb = (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
709 if (local_flags & LOCAL_TRUST_ACCOUNT) {
710 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
711 if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) {
712 *pp_err_str = NULL;
714 TALLOC_FREE(sam_pass);
715 return NT_STATUS_UNSUCCESSFUL;
717 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
718 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
719 if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) {
720 *pp_err_str = NULL;
722 TALLOC_FREE(sam_pass);
723 return NT_STATUS_UNSUCCESSFUL;
725 } else {
726 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
727 if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) {
728 *pp_err_str = NULL;
730 TALLOC_FREE(sam_pass);
731 return NT_STATUS_UNSUCCESSFUL;
736 * We are root - just write the new password
737 * and the valid last change time.
740 if (local_flags & LOCAL_DISABLE_USER) {
741 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
742 if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) {
743 *pp_err_str = NULL;
745 TALLOC_FREE(sam_pass);
746 return NT_STATUS_UNSUCCESSFUL;
748 } else if (local_flags & LOCAL_ENABLE_USER) {
749 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
750 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
751 *pp_err_str = NULL;
753 TALLOC_FREE(sam_pass);
754 return NT_STATUS_UNSUCCESSFUL;
758 if (local_flags & LOCAL_SET_NO_PASSWORD) {
759 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
760 if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) {
761 *pp_err_str = NULL;
763 TALLOC_FREE(sam_pass);
764 return NT_STATUS_UNSUCCESSFUL;
766 } else if (local_flags & LOCAL_SET_PASSWORD) {
768 * If we're dealing with setting a completely empty user account
769 * ie. One with a password of 'XXXX', but not set disabled (like
770 * an account created from scratch) then if the old password was
771 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
772 * We remove that as we're giving this user their first password
773 * and the decision hasn't really been made to disable them (ie.
774 * don't create them disabled). JRA.
776 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
777 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
778 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
779 *pp_err_str = NULL;
781 TALLOC_FREE(sam_pass);
782 return NT_STATUS_UNSUCCESSFUL;
785 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
786 if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) {
787 *pp_err_str = NULL;
789 TALLOC_FREE(sam_pass);
790 return NT_STATUS_UNSUCCESSFUL;
793 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
794 if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) {
795 *pp_err_str = NULL;
797 TALLOC_FREE(sam_pass);
798 return NT_STATUS_UNSUCCESSFUL;
802 if (local_flags & LOCAL_ADD_USER) {
803 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
804 if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) {
805 *pp_msg_str = NULL;
807 TALLOC_FREE(sam_pass);
808 return NT_STATUS_OK;
809 } else {
810 if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) {
811 *pp_err_str = NULL;
813 TALLOC_FREE(sam_pass);
814 return NT_STATUS_UNSUCCESSFUL;
816 } else if (local_flags & LOCAL_DELETE_USER) {
817 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
818 if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) {
819 *pp_err_str = NULL;
821 TALLOC_FREE(sam_pass);
822 return NT_STATUS_UNSUCCESSFUL;
824 if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) {
825 *pp_msg_str = NULL;
827 } else {
828 result = pdb_update_sam_account(sam_pass);
829 if(!NT_STATUS_IS_OK(result)) {
830 if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) {
831 *pp_err_str = NULL;
833 TALLOC_FREE(sam_pass);
834 return result;
836 if(local_flags & LOCAL_DISABLE_USER) {
837 if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) {
838 *pp_msg_str = NULL;
840 } else if (local_flags & LOCAL_ENABLE_USER) {
841 if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) {
842 *pp_msg_str = NULL;
844 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
845 if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) {
846 *pp_msg_str = NULL;
851 TALLOC_FREE(sam_pass);
852 return NT_STATUS_OK;
855 /**********************************************************************
856 Marshall/unmarshall struct samu structs.
857 *********************************************************************/
859 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
860 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
861 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
862 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
863 /* nothing changed between V3 and V4 */
865 /*********************************************************************
866 *********************************************************************/
868 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
871 /* times are stored as 32bit integer
872 take care on system with 64bit wide time_t
873 --SSS */
874 uint32 logon_time,
875 logoff_time,
876 kickoff_time,
877 pass_last_set_time,
878 pass_can_change_time,
879 pass_must_change_time;
880 char *username = NULL;
881 char *domain = NULL;
882 char *nt_username = NULL;
883 char *dir_drive = NULL;
884 char *unknown_str = NULL;
885 char *munged_dial = NULL;
886 char *fullname = NULL;
887 char *homedir = NULL;
888 char *logon_script = NULL;
889 char *profile_path = NULL;
890 char *acct_desc = NULL;
891 char *workstations = NULL;
892 uint32 username_len, domain_len, nt_username_len,
893 dir_drive_len, unknown_str_len, munged_dial_len,
894 fullname_len, homedir_len, logon_script_len,
895 profile_path_len, acct_desc_len, workstations_len;
897 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
898 uint16 acct_ctrl, logon_divs;
899 uint16 bad_password_count, logon_count;
900 uint8 *hours = NULL;
901 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
902 uint32 len = 0;
903 uint32 lm_pw_len, nt_pw_len, hourslen;
904 bool ret = True;
906 if(sampass == NULL || buf == NULL) {
907 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
908 return False;
911 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
913 /* unpack the buffer into variables */
914 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
915 &logon_time, /* d */
916 &logoff_time, /* d */
917 &kickoff_time, /* d */
918 &pass_last_set_time, /* d */
919 &pass_can_change_time, /* d */
920 &pass_must_change_time, /* d */
921 &username_len, &username, /* B */
922 &domain_len, &domain, /* B */
923 &nt_username_len, &nt_username, /* B */
924 &fullname_len, &fullname, /* B */
925 &homedir_len, &homedir, /* B */
926 &dir_drive_len, &dir_drive, /* B */
927 &logon_script_len, &logon_script, /* B */
928 &profile_path_len, &profile_path, /* B */
929 &acct_desc_len, &acct_desc, /* B */
930 &workstations_len, &workstations, /* B */
931 &unknown_str_len, &unknown_str, /* B */
932 &munged_dial_len, &munged_dial, /* B */
933 &user_rid, /* d */
934 &group_rid, /* d */
935 &lm_pw_len, &lm_pw_ptr, /* B */
936 &nt_pw_len, &nt_pw_ptr, /* B */
937 &acct_ctrl, /* w */
938 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
939 &logon_divs, /* w */
940 &hours_len, /* d */
941 &hourslen, &hours, /* B */
942 &bad_password_count, /* w */
943 &logon_count, /* w */
944 &unknown_6); /* d */
946 if (len == (uint32) -1) {
947 ret = False;
948 goto done;
951 pdb_set_logon_time(sampass, logon_time, PDB_SET);
952 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
953 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
954 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
955 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
956 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
958 pdb_set_username(sampass, username, PDB_SET);
959 pdb_set_domain(sampass, domain, PDB_SET);
960 pdb_set_nt_username(sampass, nt_username, PDB_SET);
961 pdb_set_fullname(sampass, fullname, PDB_SET);
963 if (homedir) {
964 pdb_set_homedir(sampass, homedir, PDB_SET);
966 else {
967 pdb_set_homedir(sampass,
968 talloc_sub_basic(sampass, username, domain,
969 lp_logon_home()),
970 PDB_DEFAULT);
973 if (dir_drive)
974 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
975 else {
976 pdb_set_dir_drive(sampass,
977 talloc_sub_basic(sampass, username, domain,
978 lp_logon_drive()),
979 PDB_DEFAULT);
982 if (logon_script)
983 pdb_set_logon_script(sampass, logon_script, PDB_SET);
984 else {
985 pdb_set_logon_script(sampass,
986 talloc_sub_basic(sampass, username, domain,
987 lp_logon_script()),
988 PDB_DEFAULT);
991 if (profile_path) {
992 pdb_set_profile_path(sampass, profile_path, PDB_SET);
993 } else {
994 pdb_set_profile_path(sampass,
995 talloc_sub_basic(sampass, username, domain,
996 lp_logon_path()),
997 PDB_DEFAULT);
1000 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1001 pdb_set_workstations(sampass, workstations, PDB_SET);
1002 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1004 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1005 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1006 ret = False;
1007 goto done;
1011 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1012 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1013 ret = False;
1014 goto done;
1018 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1019 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1020 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1021 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1022 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1023 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1024 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1025 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1026 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1027 pdb_set_hours(sampass, hours, PDB_SET);
1029 done:
1031 SAFE_FREE(username);
1032 SAFE_FREE(domain);
1033 SAFE_FREE(nt_username);
1034 SAFE_FREE(fullname);
1035 SAFE_FREE(homedir);
1036 SAFE_FREE(dir_drive);
1037 SAFE_FREE(logon_script);
1038 SAFE_FREE(profile_path);
1039 SAFE_FREE(acct_desc);
1040 SAFE_FREE(workstations);
1041 SAFE_FREE(munged_dial);
1042 SAFE_FREE(unknown_str);
1043 SAFE_FREE(lm_pw_ptr);
1044 SAFE_FREE(nt_pw_ptr);
1045 SAFE_FREE(hours);
1047 return ret;
1050 /*********************************************************************
1051 *********************************************************************/
1053 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1056 /* times are stored as 32bit integer
1057 take care on system with 64bit wide time_t
1058 --SSS */
1059 uint32 logon_time,
1060 logoff_time,
1061 kickoff_time,
1062 bad_password_time,
1063 pass_last_set_time,
1064 pass_can_change_time,
1065 pass_must_change_time;
1066 char *username = NULL;
1067 char *domain = NULL;
1068 char *nt_username = NULL;
1069 char *dir_drive = NULL;
1070 char *unknown_str = NULL;
1071 char *munged_dial = NULL;
1072 char *fullname = NULL;
1073 char *homedir = NULL;
1074 char *logon_script = NULL;
1075 char *profile_path = NULL;
1076 char *acct_desc = NULL;
1077 char *workstations = NULL;
1078 uint32 username_len, domain_len, nt_username_len,
1079 dir_drive_len, unknown_str_len, munged_dial_len,
1080 fullname_len, homedir_len, logon_script_len,
1081 profile_path_len, acct_desc_len, workstations_len;
1083 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1084 uint16 acct_ctrl, logon_divs;
1085 uint16 bad_password_count, logon_count;
1086 uint8 *hours = NULL;
1087 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1088 uint32 len = 0;
1089 uint32 lm_pw_len, nt_pw_len, hourslen;
1090 bool ret = True;
1092 if(sampass == NULL || buf == NULL) {
1093 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1094 return False;
1097 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1099 /* unpack the buffer into variables */
1100 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1101 &logon_time, /* d */
1102 &logoff_time, /* d */
1103 &kickoff_time, /* d */
1104 /* Change from V0 is addition of bad_password_time field. */
1105 &bad_password_time, /* d */
1106 &pass_last_set_time, /* d */
1107 &pass_can_change_time, /* d */
1108 &pass_must_change_time, /* d */
1109 &username_len, &username, /* B */
1110 &domain_len, &domain, /* B */
1111 &nt_username_len, &nt_username, /* B */
1112 &fullname_len, &fullname, /* B */
1113 &homedir_len, &homedir, /* B */
1114 &dir_drive_len, &dir_drive, /* B */
1115 &logon_script_len, &logon_script, /* B */
1116 &profile_path_len, &profile_path, /* B */
1117 &acct_desc_len, &acct_desc, /* B */
1118 &workstations_len, &workstations, /* B */
1119 &unknown_str_len, &unknown_str, /* B */
1120 &munged_dial_len, &munged_dial, /* B */
1121 &user_rid, /* d */
1122 &group_rid, /* d */
1123 &lm_pw_len, &lm_pw_ptr, /* B */
1124 &nt_pw_len, &nt_pw_ptr, /* B */
1125 &acct_ctrl, /* w */
1126 &remove_me, /* d */
1127 &logon_divs, /* w */
1128 &hours_len, /* d */
1129 &hourslen, &hours, /* B */
1130 &bad_password_count, /* w */
1131 &logon_count, /* w */
1132 &unknown_6); /* d */
1134 if (len == (uint32) -1) {
1135 ret = False;
1136 goto done;
1139 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1140 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1141 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1143 /* Change from V0 is addition of bad_password_time field. */
1144 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1145 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1146 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1147 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1149 pdb_set_username(sampass, username, PDB_SET);
1150 pdb_set_domain(sampass, domain, PDB_SET);
1151 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1152 pdb_set_fullname(sampass, fullname, PDB_SET);
1154 if (homedir) {
1155 pdb_set_homedir(sampass, homedir, PDB_SET);
1157 else {
1158 pdb_set_homedir(sampass,
1159 talloc_sub_basic(sampass, username, domain,
1160 lp_logon_home()),
1161 PDB_DEFAULT);
1164 if (dir_drive)
1165 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1166 else {
1167 pdb_set_dir_drive(sampass,
1168 talloc_sub_basic(sampass, username, domain,
1169 lp_logon_drive()),
1170 PDB_DEFAULT);
1173 if (logon_script)
1174 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1175 else {
1176 pdb_set_logon_script(sampass,
1177 talloc_sub_basic(sampass, username, domain,
1178 lp_logon_script()),
1179 PDB_DEFAULT);
1182 if (profile_path) {
1183 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1184 } else {
1185 pdb_set_profile_path(sampass,
1186 talloc_sub_basic(sampass, username, domain,
1187 lp_logon_path()),
1188 PDB_DEFAULT);
1191 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1192 pdb_set_workstations(sampass, workstations, PDB_SET);
1193 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1195 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1196 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1197 ret = False;
1198 goto done;
1202 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1203 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1204 ret = False;
1205 goto done;
1209 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1211 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1212 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1213 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1214 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1215 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1216 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1217 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1218 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1219 pdb_set_hours(sampass, hours, PDB_SET);
1221 done:
1223 SAFE_FREE(username);
1224 SAFE_FREE(domain);
1225 SAFE_FREE(nt_username);
1226 SAFE_FREE(fullname);
1227 SAFE_FREE(homedir);
1228 SAFE_FREE(dir_drive);
1229 SAFE_FREE(logon_script);
1230 SAFE_FREE(profile_path);
1231 SAFE_FREE(acct_desc);
1232 SAFE_FREE(workstations);
1233 SAFE_FREE(munged_dial);
1234 SAFE_FREE(unknown_str);
1235 SAFE_FREE(lm_pw_ptr);
1236 SAFE_FREE(nt_pw_ptr);
1237 SAFE_FREE(hours);
1239 return ret;
1242 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1245 /* times are stored as 32bit integer
1246 take care on system with 64bit wide time_t
1247 --SSS */
1248 uint32 logon_time,
1249 logoff_time,
1250 kickoff_time,
1251 bad_password_time,
1252 pass_last_set_time,
1253 pass_can_change_time,
1254 pass_must_change_time;
1255 char *username = NULL;
1256 char *domain = NULL;
1257 char *nt_username = NULL;
1258 char *dir_drive = NULL;
1259 char *unknown_str = NULL;
1260 char *munged_dial = NULL;
1261 char *fullname = NULL;
1262 char *homedir = NULL;
1263 char *logon_script = NULL;
1264 char *profile_path = NULL;
1265 char *acct_desc = NULL;
1266 char *workstations = NULL;
1267 uint32 username_len, domain_len, nt_username_len,
1268 dir_drive_len, unknown_str_len, munged_dial_len,
1269 fullname_len, homedir_len, logon_script_len,
1270 profile_path_len, acct_desc_len, workstations_len;
1272 uint32 user_rid, group_rid, hours_len, unknown_6;
1273 uint16 acct_ctrl, logon_divs;
1274 uint16 bad_password_count, logon_count;
1275 uint8 *hours = NULL;
1276 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1277 uint32 len = 0;
1278 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1279 uint32 pwHistLen = 0;
1280 bool ret = True;
1281 fstring tmp_string;
1282 bool expand_explicit = lp_passdb_expand_explicit();
1284 if(sampass == NULL || buf == NULL) {
1285 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1286 return False;
1289 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1291 /* unpack the buffer into variables */
1292 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1293 &logon_time, /* d */
1294 &logoff_time, /* d */
1295 &kickoff_time, /* d */
1296 &bad_password_time, /* d */
1297 &pass_last_set_time, /* d */
1298 &pass_can_change_time, /* d */
1299 &pass_must_change_time, /* d */
1300 &username_len, &username, /* B */
1301 &domain_len, &domain, /* B */
1302 &nt_username_len, &nt_username, /* B */
1303 &fullname_len, &fullname, /* B */
1304 &homedir_len, &homedir, /* B */
1305 &dir_drive_len, &dir_drive, /* B */
1306 &logon_script_len, &logon_script, /* B */
1307 &profile_path_len, &profile_path, /* B */
1308 &acct_desc_len, &acct_desc, /* B */
1309 &workstations_len, &workstations, /* B */
1310 &unknown_str_len, &unknown_str, /* B */
1311 &munged_dial_len, &munged_dial, /* B */
1312 &user_rid, /* d */
1313 &group_rid, /* d */
1314 &lm_pw_len, &lm_pw_ptr, /* B */
1315 &nt_pw_len, &nt_pw_ptr, /* B */
1316 /* Change from V1 is addition of password history field. */
1317 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1318 &acct_ctrl, /* w */
1319 /* Also "remove_me" field was removed. */
1320 &logon_divs, /* w */
1321 &hours_len, /* d */
1322 &hourslen, &hours, /* B */
1323 &bad_password_count, /* w */
1324 &logon_count, /* w */
1325 &unknown_6); /* d */
1327 if (len == (uint32) -1) {
1328 ret = False;
1329 goto done;
1332 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1333 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1334 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1335 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1336 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1337 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1338 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1340 pdb_set_username(sampass, username, PDB_SET);
1341 pdb_set_domain(sampass, domain, PDB_SET);
1342 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1343 pdb_set_fullname(sampass, fullname, PDB_SET);
1345 if (homedir) {
1346 fstrcpy( tmp_string, homedir );
1347 if (expand_explicit) {
1348 standard_sub_basic( username, domain, tmp_string,
1349 sizeof(tmp_string) );
1351 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1353 else {
1354 pdb_set_homedir(sampass,
1355 talloc_sub_basic(sampass, username, domain,
1356 lp_logon_home()),
1357 PDB_DEFAULT);
1360 if (dir_drive)
1361 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1362 else
1363 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1365 if (logon_script) {
1366 fstrcpy( tmp_string, logon_script );
1367 if (expand_explicit) {
1368 standard_sub_basic( username, domain, tmp_string,
1369 sizeof(tmp_string) );
1371 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1373 else {
1374 pdb_set_logon_script(sampass,
1375 talloc_sub_basic(sampass, username, domain,
1376 lp_logon_script()),
1377 PDB_DEFAULT);
1380 if (profile_path) {
1381 fstrcpy( tmp_string, profile_path );
1382 if (expand_explicit) {
1383 standard_sub_basic( username, domain, tmp_string,
1384 sizeof(tmp_string) );
1386 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1388 else {
1389 pdb_set_profile_path(sampass,
1390 talloc_sub_basic(sampass, username, domain,
1391 lp_logon_path()),
1392 PDB_DEFAULT);
1395 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1396 pdb_set_workstations(sampass, workstations, PDB_SET);
1397 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1399 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1400 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1401 ret = False;
1402 goto done;
1406 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1407 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1408 ret = False;
1409 goto done;
1413 /* Change from V1 is addition of password history field. */
1414 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1415 if (pwHistLen) {
1416 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1417 if (!pw_hist) {
1418 ret = False;
1419 goto done;
1421 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1422 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1423 int i;
1424 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1425 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1426 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1427 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1428 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1429 PW_HISTORY_ENTRY_LEN);
1432 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1433 SAFE_FREE(pw_hist);
1434 ret = False;
1435 goto done;
1437 SAFE_FREE(pw_hist);
1438 } else {
1439 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1442 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1443 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1444 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1445 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1446 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1447 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1448 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1449 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1450 pdb_set_hours(sampass, hours, PDB_SET);
1452 done:
1454 SAFE_FREE(username);
1455 SAFE_FREE(domain);
1456 SAFE_FREE(nt_username);
1457 SAFE_FREE(fullname);
1458 SAFE_FREE(homedir);
1459 SAFE_FREE(dir_drive);
1460 SAFE_FREE(logon_script);
1461 SAFE_FREE(profile_path);
1462 SAFE_FREE(acct_desc);
1463 SAFE_FREE(workstations);
1464 SAFE_FREE(munged_dial);
1465 SAFE_FREE(unknown_str);
1466 SAFE_FREE(lm_pw_ptr);
1467 SAFE_FREE(nt_pw_ptr);
1468 SAFE_FREE(nt_pw_hist_ptr);
1469 SAFE_FREE(hours);
1471 return ret;
1474 /*********************************************************************
1475 *********************************************************************/
1477 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1480 /* times are stored as 32bit integer
1481 take care on system with 64bit wide time_t
1482 --SSS */
1483 uint32 logon_time,
1484 logoff_time,
1485 kickoff_time,
1486 bad_password_time,
1487 pass_last_set_time,
1488 pass_can_change_time,
1489 pass_must_change_time;
1490 char *username = NULL;
1491 char *domain = NULL;
1492 char *nt_username = NULL;
1493 char *dir_drive = NULL;
1494 char *unknown_str = NULL;
1495 char *munged_dial = NULL;
1496 char *fullname = NULL;
1497 char *homedir = NULL;
1498 char *logon_script = NULL;
1499 char *profile_path = NULL;
1500 char *acct_desc = NULL;
1501 char *workstations = NULL;
1502 uint32 username_len, domain_len, nt_username_len,
1503 dir_drive_len, unknown_str_len, munged_dial_len,
1504 fullname_len, homedir_len, logon_script_len,
1505 profile_path_len, acct_desc_len, workstations_len;
1507 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1508 uint16 logon_divs;
1509 uint16 bad_password_count, logon_count;
1510 uint8 *hours = NULL;
1511 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1512 uint32 len = 0;
1513 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1514 uint32 pwHistLen = 0;
1515 bool ret = True;
1516 fstring tmp_string;
1517 bool expand_explicit = lp_passdb_expand_explicit();
1519 if(sampass == NULL || buf == NULL) {
1520 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1521 return False;
1524 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1526 /* unpack the buffer into variables */
1527 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1528 &logon_time, /* d */
1529 &logoff_time, /* d */
1530 &kickoff_time, /* d */
1531 &bad_password_time, /* d */
1532 &pass_last_set_time, /* d */
1533 &pass_can_change_time, /* d */
1534 &pass_must_change_time, /* d */
1535 &username_len, &username, /* B */
1536 &domain_len, &domain, /* B */
1537 &nt_username_len, &nt_username, /* B */
1538 &fullname_len, &fullname, /* B */
1539 &homedir_len, &homedir, /* B */
1540 &dir_drive_len, &dir_drive, /* B */
1541 &logon_script_len, &logon_script, /* B */
1542 &profile_path_len, &profile_path, /* B */
1543 &acct_desc_len, &acct_desc, /* B */
1544 &workstations_len, &workstations, /* B */
1545 &unknown_str_len, &unknown_str, /* B */
1546 &munged_dial_len, &munged_dial, /* B */
1547 &user_rid, /* d */
1548 &group_rid, /* d */
1549 &lm_pw_len, &lm_pw_ptr, /* B */
1550 &nt_pw_len, &nt_pw_ptr, /* B */
1551 /* Change from V1 is addition of password history field. */
1552 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1553 /* Change from V2 is the uint32 acb_mask */
1554 &acct_ctrl, /* d */
1555 /* Also "remove_me" field was removed. */
1556 &logon_divs, /* w */
1557 &hours_len, /* d */
1558 &hourslen, &hours, /* B */
1559 &bad_password_count, /* w */
1560 &logon_count, /* w */
1561 &unknown_6); /* d */
1563 if (len == (uint32) -1) {
1564 ret = False;
1565 goto done;
1568 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1569 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1570 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1571 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1572 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1573 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1574 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1576 pdb_set_username(sampass, username, PDB_SET);
1577 pdb_set_domain(sampass, domain, PDB_SET);
1578 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1579 pdb_set_fullname(sampass, fullname, PDB_SET);
1581 if (homedir) {
1582 fstrcpy( tmp_string, homedir );
1583 if (expand_explicit) {
1584 standard_sub_basic( username, domain, tmp_string,
1585 sizeof(tmp_string) );
1587 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1589 else {
1590 pdb_set_homedir(sampass,
1591 talloc_sub_basic(sampass, username, domain,
1592 lp_logon_home()),
1593 PDB_DEFAULT);
1596 if (dir_drive)
1597 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1598 else
1599 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1601 if (logon_script) {
1602 fstrcpy( tmp_string, logon_script );
1603 if (expand_explicit) {
1604 standard_sub_basic( username, domain, tmp_string,
1605 sizeof(tmp_string) );
1607 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1609 else {
1610 pdb_set_logon_script(sampass,
1611 talloc_sub_basic(sampass, username, domain,
1612 lp_logon_script()),
1613 PDB_DEFAULT);
1616 if (profile_path) {
1617 fstrcpy( tmp_string, profile_path );
1618 if (expand_explicit) {
1619 standard_sub_basic( username, domain, tmp_string,
1620 sizeof(tmp_string) );
1622 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1624 else {
1625 pdb_set_profile_path(sampass,
1626 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1627 PDB_DEFAULT);
1630 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1631 pdb_set_workstations(sampass, workstations, PDB_SET);
1632 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1634 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1635 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1636 ret = False;
1637 goto done;
1641 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1642 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1643 ret = False;
1644 goto done;
1648 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1649 if (pwHistLen) {
1650 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1651 if (!pw_hist) {
1652 ret = False;
1653 goto done;
1655 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1656 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1657 int i;
1658 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1659 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1660 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1661 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1662 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1663 PW_HISTORY_ENTRY_LEN);
1666 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1667 SAFE_FREE(pw_hist);
1668 ret = False;
1669 goto done;
1671 SAFE_FREE(pw_hist);
1672 } else {
1673 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1676 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1677 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1678 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1679 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1680 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1681 /* Change from V2 is the uint32 acct_ctrl */
1682 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1683 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1684 pdb_set_hours(sampass, hours, PDB_SET);
1686 done:
1688 SAFE_FREE(username);
1689 SAFE_FREE(domain);
1690 SAFE_FREE(nt_username);
1691 SAFE_FREE(fullname);
1692 SAFE_FREE(homedir);
1693 SAFE_FREE(dir_drive);
1694 SAFE_FREE(logon_script);
1695 SAFE_FREE(profile_path);
1696 SAFE_FREE(acct_desc);
1697 SAFE_FREE(workstations);
1698 SAFE_FREE(munged_dial);
1699 SAFE_FREE(unknown_str);
1700 SAFE_FREE(lm_pw_ptr);
1701 SAFE_FREE(nt_pw_ptr);
1702 SAFE_FREE(nt_pw_hist_ptr);
1703 SAFE_FREE(hours);
1705 return ret;
1708 /*********************************************************************
1709 *********************************************************************/
1711 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1713 size_t len, buflen;
1715 /* times are stored as 32bit integer
1716 take care on system with 64bit wide time_t
1717 --SSS */
1718 uint32 logon_time,
1719 logoff_time,
1720 kickoff_time,
1721 bad_password_time,
1722 pass_last_set_time,
1723 pass_can_change_time,
1724 pass_must_change_time;
1726 uint32 user_rid, group_rid;
1728 const char *username;
1729 const char *domain;
1730 const char *nt_username;
1731 const char *dir_drive;
1732 const char *unknown_str;
1733 const char *munged_dial;
1734 const char *fullname;
1735 const char *homedir;
1736 const char *logon_script;
1737 const char *profile_path;
1738 const char *acct_desc;
1739 const char *workstations;
1740 uint32 username_len, domain_len, nt_username_len,
1741 dir_drive_len, unknown_str_len, munged_dial_len,
1742 fullname_len, homedir_len, logon_script_len,
1743 profile_path_len, acct_desc_len, workstations_len;
1745 const uint8 *lm_pw;
1746 const uint8 *nt_pw;
1747 const uint8 *nt_pw_hist;
1748 uint32 lm_pw_len = 16;
1749 uint32 nt_pw_len = 16;
1750 uint32 nt_pw_hist_len;
1751 uint32 pwHistLen = 0;
1753 *buf = NULL;
1754 buflen = 0;
1756 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1757 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1758 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1759 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1760 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1761 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1762 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1764 user_rid = pdb_get_user_rid(sampass);
1765 group_rid = pdb_get_group_rid(sampass);
1767 username = pdb_get_username(sampass);
1768 if (username) {
1769 username_len = strlen(username) +1;
1770 } else {
1771 username_len = 0;
1774 domain = pdb_get_domain(sampass);
1775 if (domain) {
1776 domain_len = strlen(domain) +1;
1777 } else {
1778 domain_len = 0;
1781 nt_username = pdb_get_nt_username(sampass);
1782 if (nt_username) {
1783 nt_username_len = strlen(nt_username) +1;
1784 } else {
1785 nt_username_len = 0;
1788 fullname = pdb_get_fullname(sampass);
1789 if (fullname) {
1790 fullname_len = strlen(fullname) +1;
1791 } else {
1792 fullname_len = 0;
1796 * Only updates fields which have been set (not defaults from smb.conf)
1799 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1800 dir_drive = pdb_get_dir_drive(sampass);
1801 } else {
1802 dir_drive = NULL;
1804 if (dir_drive) {
1805 dir_drive_len = strlen(dir_drive) +1;
1806 } else {
1807 dir_drive_len = 0;
1810 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1811 homedir = pdb_get_homedir(sampass);
1812 } else {
1813 homedir = NULL;
1815 if (homedir) {
1816 homedir_len = strlen(homedir) +1;
1817 } else {
1818 homedir_len = 0;
1821 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1822 logon_script = pdb_get_logon_script(sampass);
1823 } else {
1824 logon_script = NULL;
1826 if (logon_script) {
1827 logon_script_len = strlen(logon_script) +1;
1828 } else {
1829 logon_script_len = 0;
1832 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1833 profile_path = pdb_get_profile_path(sampass);
1834 } else {
1835 profile_path = NULL;
1837 if (profile_path) {
1838 profile_path_len = strlen(profile_path) +1;
1839 } else {
1840 profile_path_len = 0;
1843 lm_pw = pdb_get_lanman_passwd(sampass);
1844 if (!lm_pw) {
1845 lm_pw_len = 0;
1848 nt_pw = pdb_get_nt_passwd(sampass);
1849 if (!nt_pw) {
1850 nt_pw_len = 0;
1853 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1854 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1855 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1856 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1857 } else {
1858 nt_pw_hist_len = 0;
1861 acct_desc = pdb_get_acct_desc(sampass);
1862 if (acct_desc) {
1863 acct_desc_len = strlen(acct_desc) +1;
1864 } else {
1865 acct_desc_len = 0;
1868 workstations = pdb_get_workstations(sampass);
1869 if (workstations) {
1870 workstations_len = strlen(workstations) +1;
1871 } else {
1872 workstations_len = 0;
1875 unknown_str = NULL;
1876 unknown_str_len = 0;
1878 munged_dial = pdb_get_munged_dial(sampass);
1879 if (munged_dial) {
1880 munged_dial_len = strlen(munged_dial) +1;
1881 } else {
1882 munged_dial_len = 0;
1885 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1887 /* one time to get the size needed */
1888 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1889 logon_time, /* d */
1890 logoff_time, /* d */
1891 kickoff_time, /* d */
1892 bad_password_time, /* d */
1893 pass_last_set_time, /* d */
1894 pass_can_change_time, /* d */
1895 pass_must_change_time, /* d */
1896 username_len, username, /* B */
1897 domain_len, domain, /* B */
1898 nt_username_len, nt_username, /* B */
1899 fullname_len, fullname, /* B */
1900 homedir_len, homedir, /* B */
1901 dir_drive_len, dir_drive, /* B */
1902 logon_script_len, logon_script, /* B */
1903 profile_path_len, profile_path, /* B */
1904 acct_desc_len, acct_desc, /* B */
1905 workstations_len, workstations, /* B */
1906 unknown_str_len, unknown_str, /* B */
1907 munged_dial_len, munged_dial, /* B */
1908 user_rid, /* d */
1909 group_rid, /* d */
1910 lm_pw_len, lm_pw, /* B */
1911 nt_pw_len, nt_pw, /* B */
1912 nt_pw_hist_len, nt_pw_hist, /* B */
1913 pdb_get_acct_ctrl(sampass), /* d */
1914 pdb_get_logon_divs(sampass), /* w */
1915 pdb_get_hours_len(sampass), /* d */
1916 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1917 pdb_get_bad_password_count(sampass), /* w */
1918 pdb_get_logon_count(sampass), /* w */
1919 pdb_get_unknown_6(sampass)); /* d */
1921 if (size_only) {
1922 return buflen;
1925 /* malloc the space needed */
1926 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1927 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1928 return (-1);
1931 /* now for the real call to tdb_pack() */
1932 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1933 logon_time, /* d */
1934 logoff_time, /* d */
1935 kickoff_time, /* d */
1936 bad_password_time, /* d */
1937 pass_last_set_time, /* d */
1938 pass_can_change_time, /* d */
1939 pass_must_change_time, /* d */
1940 username_len, username, /* B */
1941 domain_len, domain, /* B */
1942 nt_username_len, nt_username, /* B */
1943 fullname_len, fullname, /* B */
1944 homedir_len, homedir, /* B */
1945 dir_drive_len, dir_drive, /* B */
1946 logon_script_len, logon_script, /* B */
1947 profile_path_len, profile_path, /* B */
1948 acct_desc_len, acct_desc, /* B */
1949 workstations_len, workstations, /* B */
1950 unknown_str_len, unknown_str, /* B */
1951 munged_dial_len, munged_dial, /* B */
1952 user_rid, /* d */
1953 group_rid, /* d */
1954 lm_pw_len, lm_pw, /* B */
1955 nt_pw_len, nt_pw, /* B */
1956 nt_pw_hist_len, nt_pw_hist, /* B */
1957 pdb_get_acct_ctrl(sampass), /* d */
1958 pdb_get_logon_divs(sampass), /* w */
1959 pdb_get_hours_len(sampass), /* d */
1960 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1961 pdb_get_bad_password_count(sampass), /* w */
1962 pdb_get_logon_count(sampass), /* w */
1963 pdb_get_unknown_6(sampass)); /* d */
1965 /* check to make sure we got it correct */
1966 if (buflen != len) {
1967 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
1968 (unsigned long)buflen, (unsigned long)len));
1969 /* error */
1970 SAFE_FREE (*buf);
1971 return (-1);
1974 return (buflen);
1977 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
1979 /* nothing changed between V3 and V4 */
1980 return init_samu_from_buffer_v3(sampass, buf, buflen);
1983 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
1985 /* nothing changed between V3 and V4 */
1986 return init_buffer_from_samu_v3(buf, sampass, size_only);
1989 /**********************************************************************
1990 Intialize a struct samu struct from a BYTE buffer of size len
1991 *********************************************************************/
1993 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
1994 uint8 *buf, uint32 buflen)
1996 switch (level) {
1997 case SAMU_BUFFER_V0:
1998 return init_samu_from_buffer_v0(sampass, buf, buflen);
1999 case SAMU_BUFFER_V1:
2000 return init_samu_from_buffer_v1(sampass, buf, buflen);
2001 case SAMU_BUFFER_V2:
2002 return init_samu_from_buffer_v2(sampass, buf, buflen);
2003 case SAMU_BUFFER_V3:
2004 return init_samu_from_buffer_v3(sampass, buf, buflen);
2005 case SAMU_BUFFER_V4:
2006 return init_samu_from_buffer_v4(sampass, buf, buflen);
2009 return false;
2012 /**********************************************************************
2013 Intialize a BYTE buffer from a struct samu struct
2014 *********************************************************************/
2016 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2018 return init_buffer_from_samu_v4(buf, sampass, size_only);
2021 /*********************************************************************
2022 *********************************************************************/
2024 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2026 uint8 *buf = NULL;
2027 int len;
2029 len = init_buffer_from_samu(&buf, src, False);
2030 if (len == -1 || !buf) {
2031 SAFE_FREE(buf);
2032 return False;
2035 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2036 free(buf);
2037 return False;
2040 dst->methods = src->methods;
2042 if ( src->unix_pw ) {
2043 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2044 if (!dst->unix_pw) {
2045 free(buf);
2046 return False;
2050 free(buf);
2051 return True;
2054 /*********************************************************************
2055 Update the bad password count checking the AP_RESET_COUNT_TIME
2056 *********************************************************************/
2058 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2060 time_t LastBadPassword;
2061 uint16 BadPasswordCount;
2062 uint32 resettime;
2063 bool res;
2065 BadPasswordCount = pdb_get_bad_password_count(sampass);
2066 if (!BadPasswordCount) {
2067 DEBUG(9, ("No bad password attempts.\n"));
2068 return True;
2071 become_root();
2072 res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
2073 unbecome_root();
2075 if (!res) {
2076 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2077 return False;
2080 /* First, check if there is a reset time to compare */
2081 if ((resettime == (uint32) -1) || (resettime == 0)) {
2082 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2083 return True;
2086 LastBadPassword = pdb_get_bad_password_time(sampass);
2087 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2088 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2089 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2090 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2091 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2092 if (updated) {
2093 *updated = True;
2097 return True;
2100 /*********************************************************************
2101 Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
2102 *********************************************************************/
2104 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2106 uint32 duration;
2107 time_t LastBadPassword;
2108 bool res;
2110 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2111 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2112 pdb_get_username(sampass)));
2113 return True;
2116 become_root();
2117 res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
2118 unbecome_root();
2120 if (!res) {
2121 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2122 return False;
2125 /* First, check if there is a duration to compare */
2126 if ((duration == (uint32) -1) || (duration == 0)) {
2127 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2128 return True;
2131 LastBadPassword = pdb_get_bad_password_time(sampass);
2132 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2133 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2135 if (LastBadPassword == (time_t)0) {
2136 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2137 "administratively locked out with no bad password "
2138 "time. Leaving locked out.\n",
2139 pdb_get_username(sampass) ));
2140 return True;
2143 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2144 pdb_set_acct_ctrl(sampass,
2145 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2146 PDB_CHANGED);
2147 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2148 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2149 if (updated) {
2150 *updated = True;
2154 return True;
2157 /*********************************************************************
2158 Increment the bad_password_count
2159 *********************************************************************/
2161 bool pdb_increment_bad_password_count(struct samu *sampass)
2163 uint32 account_policy_lockout;
2164 bool autolock_updated = False, badpw_updated = False;
2165 bool ret;
2167 /* Retrieve the account lockout policy */
2168 become_root();
2169 ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2170 unbecome_root();
2171 if ( !ret ) {
2172 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2173 return False;
2176 /* If there is no policy, we don't need to continue checking */
2177 if (!account_policy_lockout) {
2178 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2179 return True;
2182 /* Check if the autolock needs to be cleared */
2183 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2184 return False;
2186 /* Check if the badpw count needs to be reset */
2187 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2188 return False;
2191 Ok, now we can assume that any resetting that needs to be
2192 done has been done, and just get on with incrementing
2193 and autolocking if necessary
2196 pdb_set_bad_password_count(sampass,
2197 pdb_get_bad_password_count(sampass)+1,
2198 PDB_CHANGED);
2199 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2202 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2203 return True;
2205 if (!pdb_set_acct_ctrl(sampass,
2206 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2207 PDB_CHANGED)) {
2208 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2209 return False;
2212 return True;
2215 bool is_dc_trusted_domain_situation(const char *domain_name)
2217 return IS_DC && !strequal(domain_name, lp_workgroup());
2220 /*******************************************************************
2221 Wrapper around retrieving the clear text trust account password.
2222 appropriate account name is stored in account_name.
2223 Caller must free password, but not account_name.
2224 *******************************************************************/
2226 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2227 const char **account_name, uint32 *channel)
2229 char *pwd;
2230 time_t last_set_time;
2232 /* if we are a DC and this is not our domain, then lookup an account
2233 * for the domain trust */
2235 if (is_dc_trusted_domain_situation(domain)) {
2236 if (!lp_allow_trusted_domains()) {
2237 return false;
2240 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2241 &last_set_time))
2243 DEBUG(0, ("get_trust_pw: could not fetch trust "
2244 "account password for trusted domain %s\n",
2245 domain));
2246 return false;
2249 if (channel != NULL) {
2250 *channel = SEC_CHAN_DOMAIN;
2253 if (account_name != NULL) {
2254 *account_name = lp_workgroup();
2257 return true;
2261 * Since we can only be member of one single domain, we are now
2262 * in a member situation:
2264 * - Either we are a DC (selfjoined) and the domain is our
2265 * own domain.
2266 * - Or we are on a member and the domain is our own or some
2267 * other (potentially trusted) domain.
2269 * In both cases, we can only get the machine account password
2270 * for our own domain to connect to our own dc. (For a member,
2271 * request to trusted domains are performed through our dc.)
2273 * So we simply use our own domain name to retrieve the
2274 * machine account passowrd and ignore the request domain here.
2277 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2279 if (pwd != NULL) {
2280 *ret_pwd = pwd;
2281 if (account_name != NULL) {
2282 *account_name = global_myname();
2285 return true;
2288 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2289 "account password for domain %s\n", domain));
2290 return false;
2293 /*******************************************************************
2294 Wrapper around retrieving the trust account password.
2295 appropriate account name is stored in account_name.
2296 *******************************************************************/
2298 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2299 const char **account_name, uint32 *channel)
2301 char *pwd = NULL;
2302 time_t last_set_time;
2304 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2305 E_md4hash(pwd, ret_pwd);
2306 SAFE_FREE(pwd);
2307 return true;
2308 } else if (is_dc_trusted_domain_situation(domain)) {
2309 return false;
2312 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2314 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2315 &last_set_time,
2316 channel))
2318 if (account_name != NULL) {
2319 *account_name = global_myname();
2322 return true;
2325 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2326 "password for domain %s\n", domain));
2327 return False;
2330 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2331 struct samu *pw)
2333 struct samr_LogonHours hours;
2334 const int units_per_week = 168;
2336 ZERO_STRUCT(hours);
2337 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2338 if (!hours.bits) {
2339 return hours;
2342 hours.units_per_week = units_per_week;
2343 memset(hours.bits, 0xFF, units_per_week);
2345 if (pdb_get_hours(pw)) {
2346 memcpy(hours.bits, pdb_get_hours(pw),
2347 MIN(pdb_get_hours_len(pw), units_per_week));
2350 return hours;