s3:g_lock: remove a nested event loop, replacing the inner loop by select
[Samba.git] / source3 / passdb / passdb.c
blobf174e3b1a6af1b8c027ae2ae744b0d044704f9d4
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Jeremy Allison 1996-2001
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6 Copyright (C) Gerald (Jerry) Carter 2000-2006
7 Copyright (C) Andrew Bartlett 2001-2002
8 Copyright (C) Simo Sorce 2003
9 Copyright (C) Volker Lendecke 2006
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../libcli/auth/libcli_auth.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 /******************************************************************
32 Get the default domain/netbios name to be used when
33 testing authentication.
35 LEGACY: this function provides the legacy domain mapping used with
36 the lp_map_untrusted_to_domain() parameter
37 ******************************************************************/
39 const char *my_sam_name(void)
41 /* Standalone servers can only use the local netbios name */
42 if ( lp_server_role() == ROLE_STANDALONE )
43 return global_myname();
45 /* Default to the DOMAIN name when not specified */
46 return lp_workgroup();
49 /**********************************************************************
50 ***********************************************************************/
52 static int samu_destroy(struct samu *user)
54 data_blob_clear_free( &user->lm_pw );
55 data_blob_clear_free( &user->nt_pw );
57 if ( user->plaintext_pw )
58 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
60 return 0;
63 /**********************************************************************
64 generate a new struct samuser
65 ***********************************************************************/
67 struct samu *samu_new( TALLOC_CTX *ctx )
69 struct samu *user;
71 if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
72 DEBUG(0,("samuser_new: Talloc failed!\n"));
73 return NULL;
76 talloc_set_destructor( user, samu_destroy );
78 /* no initial methods */
80 user->methods = NULL;
82 /* Don't change these timestamp settings without a good reason.
83 They are important for NT member server compatibility. */
85 user->logon_time = (time_t)0;
86 user->pass_last_set_time = (time_t)0;
87 user->pass_can_change_time = (time_t)0;
88 user->logoff_time = get_time_t_max();
89 user->kickoff_time = get_time_t_max();
90 user->pass_must_change_time = get_time_t_max();
91 user->fields_present = 0x00ffffff;
92 user->logon_divs = 168; /* hours per week */
93 user->hours_len = 21; /* 21 times 8 bits = 168 */
94 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
95 user->bad_password_count = 0;
96 user->logon_count = 0;
97 user->unknown_6 = 0x000004ec; /* don't know */
99 /* Some parts of samba strlen their pdb_get...() returns,
100 so this keeps the interface unchanged for now. */
102 user->username = "";
103 user->domain = "";
104 user->nt_username = "";
105 user->full_name = "";
106 user->home_dir = "";
107 user->logon_script = "";
108 user->profile_path = "";
109 user->acct_desc = "";
110 user->workstations = "";
111 user->comment = "";
112 user->munged_dial = "";
114 user->plaintext_pw = NULL;
116 /* Unless we know otherwise have a Account Control Bit
117 value of 'normal user'. This helps User Manager, which
118 asks for a filtered list of users. */
120 user->acct_ctrl = ACB_NORMAL;
122 return user;
125 static int count_commas(const char *str)
127 int num_commas = 0;
128 const char *comma = str;
130 while ((comma = strchr(comma, ',')) != NULL) {
131 comma += 1;
132 num_commas += 1;
134 return num_commas;
137 /*********************************************************************
138 Initialize a struct samu from a struct passwd including the user
139 and group SIDs. The *user structure is filled out with the Unix
140 attributes and a user SID.
141 *********************************************************************/
143 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
145 const char *guest_account = lp_guestaccount();
146 const char *domain = global_myname();
147 char *fullname;
148 uint32 urid;
150 if ( !pwd ) {
151 return NT_STATUS_NO_SUCH_USER;
154 /* Basic properties based upon the Unix account information */
156 pdb_set_username(user, pwd->pw_name, PDB_SET);
158 fullname = NULL;
160 if (count_commas(pwd->pw_gecos) == 3) {
162 * Heuristic: This seems to be a gecos field that has been
163 * edited by chfn(1). Only use the part before the first
164 * comma. Fixes bug 5198.
166 fullname = talloc_strndup(
167 talloc_tos(), pwd->pw_gecos,
168 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
171 if (fullname != NULL) {
172 pdb_set_fullname(user, fullname, PDB_SET);
173 } else {
174 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
176 TALLOC_FREE(fullname);
178 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
179 #if 0
180 /* This can lead to a primary group of S-1-22-2-XX which
181 will be rejected by other parts of the Samba code.
182 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
183 --jerry */
185 gid_to_sid(&group_sid, pwd->pw_gid);
186 pdb_set_group_sid(user, &group_sid, PDB_SET);
187 #endif
189 /* save the password structure for later use */
191 user->unix_pw = tcopy_passwd( user, pwd );
193 /* Special case for the guest account which must have a RID of 501 */
195 if ( strequal( pwd->pw_name, guest_account ) ) {
196 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
197 return NT_STATUS_NO_SUCH_USER;
199 return NT_STATUS_OK;
202 /* Non-guest accounts...Check for a workstation or user account */
204 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
205 /* workstation */
207 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
208 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
209 pwd->pw_name));
210 return NT_STATUS_INVALID_COMPUTER_NAME;
213 else {
214 /* user */
216 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
217 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
218 pwd->pw_name));
219 return NT_STATUS_INVALID_ACCOUNT_NAME;
222 /* set some basic attributes */
224 pdb_set_profile_path(user, talloc_sub_specified(user,
225 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
226 PDB_DEFAULT);
227 pdb_set_homedir(user, talloc_sub_specified(user,
228 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
229 PDB_DEFAULT);
230 pdb_set_dir_drive(user, talloc_sub_specified(user,
231 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
232 PDB_DEFAULT);
233 pdb_set_logon_script(user, talloc_sub_specified(user,
234 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
235 PDB_DEFAULT);
238 /* Now deal with the user SID. If we have a backend that can generate
239 RIDs, then do so. But sometimes the caller just wanted a structure
240 initialized and will fill in these fields later (such as from a
241 netr_SamInfo3 structure) */
243 if ( create && (pdb_capabilities() & PDB_CAP_STORE_RIDS)) {
244 uint32 user_rid;
245 DOM_SID user_sid;
247 if ( !pdb_new_rid( &user_rid ) ) {
248 DEBUG(3, ("Could not allocate a new RID\n"));
249 return NT_STATUS_ACCESS_DENIED;
252 sid_copy( &user_sid, get_global_sam_sid() );
253 sid_append_rid( &user_sid, user_rid );
255 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
256 DEBUG(3, ("pdb_set_user_sid failed\n"));
257 return NT_STATUS_INTERNAL_ERROR;
260 return NT_STATUS_OK;
263 /* generate a SID for the user with the RID algorithm */
265 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
267 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
268 return NT_STATUS_INTERNAL_ERROR;
271 return NT_STATUS_OK;
274 /********************************************************************
275 Set the Unix user attributes
276 ********************************************************************/
278 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
280 return samu_set_unix_internal( user, pwd, False );
283 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
285 return samu_set_unix_internal( user, pwd, True );
288 /**********************************************************
289 Encode the account control bits into a string.
290 length = length of string to encode into (including terminating
291 null). length *MUST BE MORE THAN 2* !
292 **********************************************************/
294 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
296 fstring acct_str;
297 char *result;
299 size_t i = 0;
301 SMB_ASSERT(length <= sizeof(acct_str));
303 acct_str[i++] = '[';
305 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
306 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
307 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
308 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
309 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
310 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
311 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
312 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
313 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
314 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
315 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
317 for ( ; i < length - 2 ; i++ )
318 acct_str[i] = ' ';
320 i = length - 2;
321 acct_str[i++] = ']';
322 acct_str[i++] = '\0';
324 result = talloc_strdup(talloc_tos(), acct_str);
325 SMB_ASSERT(result != NULL);
326 return result;
329 /**********************************************************
330 Decode the account control bits from a string.
331 **********************************************************/
333 uint32_t pdb_decode_acct_ctrl(const char *p)
335 uint32_t acct_ctrl = 0;
336 bool finished = false;
339 * Check if the account type bits have been encoded after the
340 * NT password (in the form [NDHTUWSLXI]).
343 if (*p != '[')
344 return 0;
346 for (p++; *p && !finished; p++) {
347 switch (*p) {
348 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
349 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
350 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
351 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
352 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
353 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
354 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
355 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
356 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
357 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
358 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
359 case ' ': { break; }
360 case ':':
361 case '\n':
362 case '\0':
363 case ']':
364 default: { finished = true; }
368 return acct_ctrl;
371 /*************************************************************
372 Routine to set 32 hex password characters from a 16 byte array.
373 **************************************************************/
375 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
377 if (pwd != NULL) {
378 int i;
379 for (i = 0; i < 16; i++)
380 slprintf(&p[i*2], 3, "%02X", pwd[i]);
381 } else {
382 if (acct_ctrl & ACB_PWNOTREQ)
383 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
384 else
385 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
389 /*************************************************************
390 Routine to get the 32 hex characters and turn them
391 into a 16 byte array.
392 **************************************************************/
394 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
396 int i;
397 unsigned char lonybble, hinybble;
398 const char *hexchars = "0123456789ABCDEF";
399 char *p1, *p2;
401 if (!p)
402 return false;
404 for (i = 0; i < 32; i += 2) {
405 hinybble = toupper_ascii(p[i]);
406 lonybble = toupper_ascii(p[i + 1]);
408 p1 = strchr(hexchars, hinybble);
409 p2 = strchr(hexchars, lonybble);
411 if (!p1 || !p2)
412 return false;
414 hinybble = PTR_DIFF(p1, hexchars);
415 lonybble = PTR_DIFF(p2, hexchars);
417 pwd[i / 2] = (hinybble << 4) | lonybble;
419 return true;
422 /*************************************************************
423 Routine to set 42 hex hours characters from a 21 byte array.
424 **************************************************************/
426 void pdb_sethexhours(char *p, const unsigned char *hours)
428 if (hours != NULL) {
429 int i;
430 for (i = 0; i < 21; i++) {
431 slprintf(&p[i*2], 3, "%02X", hours[i]);
433 } else {
434 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
438 /*************************************************************
439 Routine to get the 42 hex characters and turn them
440 into a 21 byte array.
441 **************************************************************/
443 bool pdb_gethexhours(const char *p, unsigned char *hours)
445 int i;
446 unsigned char lonybble, hinybble;
447 const char *hexchars = "0123456789ABCDEF";
448 char *p1, *p2;
450 if (!p) {
451 return (False);
454 for (i = 0; i < 42; i += 2) {
455 hinybble = toupper_ascii(p[i]);
456 lonybble = toupper_ascii(p[i + 1]);
458 p1 = strchr(hexchars, hinybble);
459 p2 = strchr(hexchars, lonybble);
461 if (!p1 || !p2) {
462 return (False);
465 hinybble = PTR_DIFF(p1, hexchars);
466 lonybble = PTR_DIFF(p2, hexchars);
468 hours[i / 2] = (hinybble << 4) | lonybble;
470 return (True);
473 /********************************************************************
474 ********************************************************************/
476 int algorithmic_rid_base(void)
478 int rid_offset;
480 rid_offset = lp_algorithmic_rid_base();
482 if (rid_offset < BASE_RID) {
483 /* Try to prevent admin foot-shooting, we can't put algorithmic
484 rids below 1000, that's the 'well known RIDs' on NT */
485 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
486 rid_offset = BASE_RID;
488 if (rid_offset & 1) {
489 DEBUG(0, ("algorithmic rid base must be even\n"));
490 rid_offset += 1;
492 return rid_offset;
495 /*******************************************************************
496 Converts NT user RID to a UNIX uid.
497 ********************************************************************/
499 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
501 int rid_offset = algorithmic_rid_base();
502 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
505 uid_t max_algorithmic_uid(void)
507 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
510 /*******************************************************************
511 converts UNIX uid to an NT User RID.
512 ********************************************************************/
514 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
516 int rid_offset = algorithmic_rid_base();
517 return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
520 /*******************************************************************
521 Converts NT group RID to a UNIX gid.
522 ********************************************************************/
524 gid_t pdb_group_rid_to_gid(uint32 group_rid)
526 int rid_offset = algorithmic_rid_base();
527 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
530 gid_t max_algorithmic_gid(void)
532 return pdb_group_rid_to_gid(0xffffffff);
535 /*******************************************************************
536 converts NT Group RID to a UNIX uid.
538 warning: you must not call that function only
539 you must do a call to the group mapping first.
540 there is not anymore a direct link between the gid and the rid.
541 ********************************************************************/
543 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
545 int rid_offset = algorithmic_rid_base();
546 return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
549 /*******************************************************************
550 Decides if a RID is a well known RID.
551 ********************************************************************/
553 static bool rid_is_well_known(uint32 rid)
555 /* Not using rid_offset here, because this is the actual
556 NT fixed value (1000) */
558 return (rid < BASE_RID);
561 /*******************************************************************
562 Decides if a RID is a user or group RID.
563 ********************************************************************/
565 bool algorithmic_pdb_rid_is_user(uint32 rid)
567 if ( rid_is_well_known(rid) ) {
569 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
570 * and DOMAIN_USER_RID_GUEST.
572 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
573 return True;
574 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
575 return True;
577 return False;
580 /*******************************************************************
581 Convert a name into a SID. Used in the lookup name rpc.
582 ********************************************************************/
584 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
585 enum lsa_SidType *type)
587 GROUP_MAP map;
588 bool ret;
590 /* Windows treats "MACHINE\None" as a special name for
591 rid 513 on non-DCs. You cannot create a user or group
592 name "None" on Windows. You will get an error that
593 the group already exists. */
595 if ( strequal( name, "None" ) ) {
596 *rid = DOMAIN_GROUP_RID_USERS;
597 *type = SID_NAME_DOM_GRP;
599 return True;
602 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
603 * correctly in the case where foo also exists as a user. If the flag
604 * is set, don't look for users at all. */
606 if ((flags & LOOKUP_NAME_GROUP) == 0) {
607 struct samu *sam_account = NULL;
608 DOM_SID user_sid;
610 if ( !(sam_account = samu_new( NULL )) ) {
611 return False;
614 become_root();
615 ret = pdb_getsampwnam(sam_account, name);
616 unbecome_root();
618 if (ret) {
619 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
622 TALLOC_FREE(sam_account);
624 if (ret) {
625 if (!sid_check_is_in_our_domain(&user_sid)) {
626 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
627 name, sid_string_dbg(&user_sid)));
628 return False;
631 sid_peek_rid(&user_sid, rid);
632 *type = SID_NAME_USER;
633 return True;
638 * Maybe it is a group ?
641 become_root();
642 ret = pdb_getgrnam(&map, name);
643 unbecome_root();
645 if (!ret) {
646 return False;
649 /* BUILTIN groups are looked up elsewhere */
650 if (!sid_check_is_in_our_domain(&map.sid)) {
651 DEBUG(10, ("Found group %s (%s) not in our domain -- "
652 "ignoring.", name, sid_string_dbg(&map.sid)));
653 return False;
656 /* yes it's a mapped group */
657 sid_peek_rid(&map.sid, rid);
658 *type = map.sid_name_use;
659 return True;
662 /*************************************************************
663 Change a password entry in the local passdb backend.
665 Assumptions:
666 - always called as root
667 - ignores the account type except when adding a new account
668 - will create/delete the unix account if the relative
669 add/delete user script is configured
671 *************************************************************/
673 NTSTATUS local_password_change(const char *user_name,
674 int local_flags,
675 const char *new_passwd,
676 char **pp_err_str,
677 char **pp_msg_str)
679 TALLOC_CTX *tosctx;
680 struct samu *sam_pass;
681 uint32_t acb;
682 uint32_t rid;
683 NTSTATUS result;
684 bool user_exists;
685 int ret = -1;
687 *pp_err_str = NULL;
688 *pp_msg_str = NULL;
690 tosctx = talloc_tos();
692 sam_pass = samu_new(tosctx);
693 if (!sam_pass) {
694 result = NT_STATUS_NO_MEMORY;
695 goto done;
698 /* Get the smb passwd entry for this user */
699 user_exists = pdb_getsampwnam(sam_pass, user_name);
701 /* Check delete first, we don't need to do anything else if we
702 * are going to delete the acocunt */
703 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
705 result = pdb_delete_user(tosctx, sam_pass);
706 if (!NT_STATUS_IS_OK(result)) {
707 ret = asprintf(pp_err_str,
708 "Failed to delete entry for user %s.\n",
709 user_name);
710 if (ret < 0) {
711 *pp_err_str = NULL;
713 result = NT_STATUS_UNSUCCESSFUL;
714 } else {
715 ret = asprintf(pp_msg_str,
716 "Deleted user %s.\n",
717 user_name);
718 if (ret < 0) {
719 *pp_msg_str = NULL;
722 goto done;
725 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
726 /* the entry already existed */
727 local_flags &= ~LOCAL_ADD_USER;
730 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
731 ret = asprintf(pp_err_str,
732 "Failed to find entry for user %s.\n",
733 user_name);
734 if (ret < 0) {
735 *pp_err_str = NULL;
737 result = NT_STATUS_NO_SUCH_USER;
738 goto done;
741 /* First thing add the new user if we are required to do so */
742 if (local_flags & LOCAL_ADD_USER) {
744 if (local_flags & LOCAL_TRUST_ACCOUNT) {
745 acb = ACB_WSTRUST;
746 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
747 acb = ACB_DOMTRUST;
748 } else {
749 acb = ACB_NORMAL;
752 result = pdb_create_user(tosctx, user_name, acb, &rid);
753 if (!NT_STATUS_IS_OK(result)) {
754 ret = asprintf(pp_err_str,
755 "Failed to add entry for user %s.\n",
756 user_name);
757 if (ret < 0) {
758 *pp_err_str = NULL;
760 result = NT_STATUS_UNSUCCESSFUL;
761 goto done;
764 sam_pass = samu_new(tosctx);
765 if (!sam_pass) {
766 result = NT_STATUS_NO_MEMORY;
767 goto done;
770 /* Now get back the smb passwd entry for this new user */
771 user_exists = pdb_getsampwnam(sam_pass, user_name);
772 if (!user_exists) {
773 ret = asprintf(pp_err_str,
774 "Failed to add entry for user %s.\n",
775 user_name);
776 if (ret < 0) {
777 *pp_err_str = NULL;
779 result = NT_STATUS_UNSUCCESSFUL;
780 goto done;
784 acb = pdb_get_acct_ctrl(sam_pass);
787 * We are root - just write the new password
788 * and the valid last change time.
790 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
791 acb |= ACB_PWNOTREQ;
792 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
793 ret = asprintf(pp_err_str,
794 "Failed to set 'no password required' "
795 "flag for user %s.\n", user_name);
796 if (ret < 0) {
797 *pp_err_str = NULL;
799 result = NT_STATUS_UNSUCCESSFUL;
800 goto done;
804 if (local_flags & LOCAL_SET_PASSWORD) {
806 * If we're dealing with setting a completely empty user account
807 * ie. One with a password of 'XXXX', but not set disabled (like
808 * an account created from scratch) then if the old password was
809 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
810 * We remove that as we're giving this user their first password
811 * and the decision hasn't really been made to disable them (ie.
812 * don't create them disabled). JRA.
814 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
815 (acb & ACB_DISABLED)) {
816 acb &= (~ACB_DISABLED);
817 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
818 ret = asprintf(pp_err_str,
819 "Failed to unset 'disabled' "
820 "flag for user %s.\n",
821 user_name);
822 if (ret < 0) {
823 *pp_err_str = NULL;
825 result = NT_STATUS_UNSUCCESSFUL;
826 goto done;
830 acb &= (~ACB_PWNOTREQ);
831 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
832 ret = asprintf(pp_err_str,
833 "Failed to unset 'no password required'"
834 " flag for user %s.\n", user_name);
835 if (ret < 0) {
836 *pp_err_str = NULL;
838 result = NT_STATUS_UNSUCCESSFUL;
839 goto done;
842 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
843 ret = asprintf(pp_err_str,
844 "Failed to set password for "
845 "user %s.\n", user_name);
846 if (ret < 0) {
847 *pp_err_str = NULL;
849 result = NT_STATUS_UNSUCCESSFUL;
850 goto done;
854 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
855 acb |= ACB_DISABLED;
856 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
857 ret = asprintf(pp_err_str,
858 "Failed to set 'disabled' flag for "
859 "user %s.\n", user_name);
860 if (ret < 0) {
861 *pp_err_str = NULL;
863 result = NT_STATUS_UNSUCCESSFUL;
864 goto done;
868 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
869 acb &= (~ACB_DISABLED);
870 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
871 ret = asprintf(pp_err_str,
872 "Failed to unset 'disabled' flag for "
873 "user %s.\n", user_name);
874 if (ret < 0) {
875 *pp_err_str = NULL;
877 result = NT_STATUS_UNSUCCESSFUL;
878 goto done;
882 /* now commit changes if any */
883 result = pdb_update_sam_account(sam_pass);
884 if (!NT_STATUS_IS_OK(result)) {
885 ret = asprintf(pp_err_str,
886 "Failed to modify entry for user %s.\n",
887 user_name);
888 if (ret < 0) {
889 *pp_err_str = NULL;
891 goto done;
894 if (local_flags & LOCAL_ADD_USER) {
895 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
896 } else if (local_flags & LOCAL_DISABLE_USER) {
897 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
898 } else if (local_flags & LOCAL_ENABLE_USER) {
899 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
900 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
901 ret = asprintf(pp_msg_str,
902 "User %s password set to none.\n", user_name);
905 if (ret < 0) {
906 *pp_msg_str = NULL;
909 result = NT_STATUS_OK;
911 done:
912 TALLOC_FREE(sam_pass);
913 return result;
916 /**********************************************************************
917 Marshall/unmarshall struct samu structs.
918 *********************************************************************/
920 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
921 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
922 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
923 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
924 /* nothing changed between V3 and V4 */
926 /*********************************************************************
927 *********************************************************************/
929 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
932 /* times are stored as 32bit integer
933 take care on system with 64bit wide time_t
934 --SSS */
935 uint32 logon_time,
936 logoff_time,
937 kickoff_time,
938 pass_last_set_time,
939 pass_can_change_time,
940 pass_must_change_time;
941 char *username = NULL;
942 char *domain = NULL;
943 char *nt_username = NULL;
944 char *dir_drive = NULL;
945 char *unknown_str = NULL;
946 char *munged_dial = NULL;
947 char *fullname = NULL;
948 char *homedir = NULL;
949 char *logon_script = NULL;
950 char *profile_path = NULL;
951 char *acct_desc = NULL;
952 char *workstations = NULL;
953 uint32 username_len, domain_len, nt_username_len,
954 dir_drive_len, unknown_str_len, munged_dial_len,
955 fullname_len, homedir_len, logon_script_len,
956 profile_path_len, acct_desc_len, workstations_len;
958 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
959 uint16 acct_ctrl, logon_divs;
960 uint16 bad_password_count, logon_count;
961 uint8 *hours = NULL;
962 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
963 uint32 len = 0;
964 uint32 lm_pw_len, nt_pw_len, hourslen;
965 bool ret = True;
967 if(sampass == NULL || buf == NULL) {
968 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
969 return False;
972 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
974 /* unpack the buffer into variables */
975 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
976 &logon_time, /* d */
977 &logoff_time, /* d */
978 &kickoff_time, /* d */
979 &pass_last_set_time, /* d */
980 &pass_can_change_time, /* d */
981 &pass_must_change_time, /* d */
982 &username_len, &username, /* B */
983 &domain_len, &domain, /* B */
984 &nt_username_len, &nt_username, /* B */
985 &fullname_len, &fullname, /* B */
986 &homedir_len, &homedir, /* B */
987 &dir_drive_len, &dir_drive, /* B */
988 &logon_script_len, &logon_script, /* B */
989 &profile_path_len, &profile_path, /* B */
990 &acct_desc_len, &acct_desc, /* B */
991 &workstations_len, &workstations, /* B */
992 &unknown_str_len, &unknown_str, /* B */
993 &munged_dial_len, &munged_dial, /* B */
994 &user_rid, /* d */
995 &group_rid, /* d */
996 &lm_pw_len, &lm_pw_ptr, /* B */
997 &nt_pw_len, &nt_pw_ptr, /* B */
998 &acct_ctrl, /* w */
999 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
1000 &logon_divs, /* w */
1001 &hours_len, /* d */
1002 &hourslen, &hours, /* B */
1003 &bad_password_count, /* w */
1004 &logon_count, /* w */
1005 &unknown_6); /* d */
1007 if (len == (uint32) -1) {
1008 ret = False;
1009 goto done;
1012 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1013 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1014 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1015 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1016 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1017 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1019 pdb_set_username(sampass, username, PDB_SET);
1020 pdb_set_domain(sampass, domain, PDB_SET);
1021 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1022 pdb_set_fullname(sampass, fullname, PDB_SET);
1024 if (homedir) {
1025 pdb_set_homedir(sampass, homedir, PDB_SET);
1027 else {
1028 pdb_set_homedir(sampass,
1029 talloc_sub_basic(sampass, username, domain,
1030 lp_logon_home()),
1031 PDB_DEFAULT);
1034 if (dir_drive)
1035 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1036 else {
1037 pdb_set_dir_drive(sampass,
1038 talloc_sub_basic(sampass, username, domain,
1039 lp_logon_drive()),
1040 PDB_DEFAULT);
1043 if (logon_script)
1044 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1045 else {
1046 pdb_set_logon_script(sampass,
1047 talloc_sub_basic(sampass, username, domain,
1048 lp_logon_script()),
1049 PDB_DEFAULT);
1052 if (profile_path) {
1053 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1054 } else {
1055 pdb_set_profile_path(sampass,
1056 talloc_sub_basic(sampass, username, domain,
1057 lp_logon_path()),
1058 PDB_DEFAULT);
1061 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1062 pdb_set_workstations(sampass, workstations, PDB_SET);
1063 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1065 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1066 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1067 ret = False;
1068 goto done;
1072 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1073 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1074 ret = False;
1075 goto done;
1079 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1080 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1081 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1082 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1083 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1084 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1085 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1086 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1087 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1088 pdb_set_hours(sampass, hours, PDB_SET);
1090 done:
1092 SAFE_FREE(username);
1093 SAFE_FREE(domain);
1094 SAFE_FREE(nt_username);
1095 SAFE_FREE(fullname);
1096 SAFE_FREE(homedir);
1097 SAFE_FREE(dir_drive);
1098 SAFE_FREE(logon_script);
1099 SAFE_FREE(profile_path);
1100 SAFE_FREE(acct_desc);
1101 SAFE_FREE(workstations);
1102 SAFE_FREE(munged_dial);
1103 SAFE_FREE(unknown_str);
1104 SAFE_FREE(lm_pw_ptr);
1105 SAFE_FREE(nt_pw_ptr);
1106 SAFE_FREE(hours);
1108 return ret;
1111 /*********************************************************************
1112 *********************************************************************/
1114 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1117 /* times are stored as 32bit integer
1118 take care on system with 64bit wide time_t
1119 --SSS */
1120 uint32 logon_time,
1121 logoff_time,
1122 kickoff_time,
1123 bad_password_time,
1124 pass_last_set_time,
1125 pass_can_change_time,
1126 pass_must_change_time;
1127 char *username = NULL;
1128 char *domain = NULL;
1129 char *nt_username = NULL;
1130 char *dir_drive = NULL;
1131 char *unknown_str = NULL;
1132 char *munged_dial = NULL;
1133 char *fullname = NULL;
1134 char *homedir = NULL;
1135 char *logon_script = NULL;
1136 char *profile_path = NULL;
1137 char *acct_desc = NULL;
1138 char *workstations = NULL;
1139 uint32 username_len, domain_len, nt_username_len,
1140 dir_drive_len, unknown_str_len, munged_dial_len,
1141 fullname_len, homedir_len, logon_script_len,
1142 profile_path_len, acct_desc_len, workstations_len;
1144 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
1145 uint16 acct_ctrl, logon_divs;
1146 uint16 bad_password_count, logon_count;
1147 uint8 *hours = NULL;
1148 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1149 uint32 len = 0;
1150 uint32 lm_pw_len, nt_pw_len, hourslen;
1151 bool ret = True;
1153 if(sampass == NULL || buf == NULL) {
1154 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1155 return False;
1158 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1160 /* unpack the buffer into variables */
1161 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1162 &logon_time, /* d */
1163 &logoff_time, /* d */
1164 &kickoff_time, /* d */
1165 /* Change from V0 is addition of bad_password_time field. */
1166 &bad_password_time, /* d */
1167 &pass_last_set_time, /* d */
1168 &pass_can_change_time, /* d */
1169 &pass_must_change_time, /* d */
1170 &username_len, &username, /* B */
1171 &domain_len, &domain, /* B */
1172 &nt_username_len, &nt_username, /* B */
1173 &fullname_len, &fullname, /* B */
1174 &homedir_len, &homedir, /* B */
1175 &dir_drive_len, &dir_drive, /* B */
1176 &logon_script_len, &logon_script, /* B */
1177 &profile_path_len, &profile_path, /* B */
1178 &acct_desc_len, &acct_desc, /* B */
1179 &workstations_len, &workstations, /* B */
1180 &unknown_str_len, &unknown_str, /* B */
1181 &munged_dial_len, &munged_dial, /* B */
1182 &user_rid, /* d */
1183 &group_rid, /* d */
1184 &lm_pw_len, &lm_pw_ptr, /* B */
1185 &nt_pw_len, &nt_pw_ptr, /* B */
1186 &acct_ctrl, /* w */
1187 &remove_me, /* d */
1188 &logon_divs, /* w */
1189 &hours_len, /* d */
1190 &hourslen, &hours, /* B */
1191 &bad_password_count, /* w */
1192 &logon_count, /* w */
1193 &unknown_6); /* d */
1195 if (len == (uint32) -1) {
1196 ret = False;
1197 goto done;
1200 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1201 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1202 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1204 /* Change from V0 is addition of bad_password_time field. */
1205 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1206 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1207 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1208 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1210 pdb_set_username(sampass, username, PDB_SET);
1211 pdb_set_domain(sampass, domain, PDB_SET);
1212 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1213 pdb_set_fullname(sampass, fullname, PDB_SET);
1215 if (homedir) {
1216 pdb_set_homedir(sampass, homedir, PDB_SET);
1218 else {
1219 pdb_set_homedir(sampass,
1220 talloc_sub_basic(sampass, username, domain,
1221 lp_logon_home()),
1222 PDB_DEFAULT);
1225 if (dir_drive)
1226 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1227 else {
1228 pdb_set_dir_drive(sampass,
1229 talloc_sub_basic(sampass, username, domain,
1230 lp_logon_drive()),
1231 PDB_DEFAULT);
1234 if (logon_script)
1235 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1236 else {
1237 pdb_set_logon_script(sampass,
1238 talloc_sub_basic(sampass, username, domain,
1239 lp_logon_script()),
1240 PDB_DEFAULT);
1243 if (profile_path) {
1244 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1245 } else {
1246 pdb_set_profile_path(sampass,
1247 talloc_sub_basic(sampass, username, domain,
1248 lp_logon_path()),
1249 PDB_DEFAULT);
1252 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1253 pdb_set_workstations(sampass, workstations, PDB_SET);
1254 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1256 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1257 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1258 ret = False;
1259 goto done;
1263 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1264 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1265 ret = False;
1266 goto done;
1270 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1272 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1273 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1274 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1275 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1276 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1277 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1278 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1279 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1280 pdb_set_hours(sampass, hours, PDB_SET);
1282 done:
1284 SAFE_FREE(username);
1285 SAFE_FREE(domain);
1286 SAFE_FREE(nt_username);
1287 SAFE_FREE(fullname);
1288 SAFE_FREE(homedir);
1289 SAFE_FREE(dir_drive);
1290 SAFE_FREE(logon_script);
1291 SAFE_FREE(profile_path);
1292 SAFE_FREE(acct_desc);
1293 SAFE_FREE(workstations);
1294 SAFE_FREE(munged_dial);
1295 SAFE_FREE(unknown_str);
1296 SAFE_FREE(lm_pw_ptr);
1297 SAFE_FREE(nt_pw_ptr);
1298 SAFE_FREE(hours);
1300 return ret;
1303 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1306 /* times are stored as 32bit integer
1307 take care on system with 64bit wide time_t
1308 --SSS */
1309 uint32 logon_time,
1310 logoff_time,
1311 kickoff_time,
1312 bad_password_time,
1313 pass_last_set_time,
1314 pass_can_change_time,
1315 pass_must_change_time;
1316 char *username = NULL;
1317 char *domain = NULL;
1318 char *nt_username = NULL;
1319 char *dir_drive = NULL;
1320 char *unknown_str = NULL;
1321 char *munged_dial = NULL;
1322 char *fullname = NULL;
1323 char *homedir = NULL;
1324 char *logon_script = NULL;
1325 char *profile_path = NULL;
1326 char *acct_desc = NULL;
1327 char *workstations = NULL;
1328 uint32 username_len, domain_len, nt_username_len,
1329 dir_drive_len, unknown_str_len, munged_dial_len,
1330 fullname_len, homedir_len, logon_script_len,
1331 profile_path_len, acct_desc_len, workstations_len;
1333 uint32 user_rid, group_rid, hours_len, unknown_6;
1334 uint16 acct_ctrl, logon_divs;
1335 uint16 bad_password_count, logon_count;
1336 uint8 *hours = NULL;
1337 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1338 uint32 len = 0;
1339 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1340 uint32 pwHistLen = 0;
1341 bool ret = True;
1342 fstring tmp_string;
1343 bool expand_explicit = lp_passdb_expand_explicit();
1345 if(sampass == NULL || buf == NULL) {
1346 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1347 return False;
1350 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1352 /* unpack the buffer into variables */
1353 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1354 &logon_time, /* d */
1355 &logoff_time, /* d */
1356 &kickoff_time, /* d */
1357 &bad_password_time, /* d */
1358 &pass_last_set_time, /* d */
1359 &pass_can_change_time, /* d */
1360 &pass_must_change_time, /* d */
1361 &username_len, &username, /* B */
1362 &domain_len, &domain, /* B */
1363 &nt_username_len, &nt_username, /* B */
1364 &fullname_len, &fullname, /* B */
1365 &homedir_len, &homedir, /* B */
1366 &dir_drive_len, &dir_drive, /* B */
1367 &logon_script_len, &logon_script, /* B */
1368 &profile_path_len, &profile_path, /* B */
1369 &acct_desc_len, &acct_desc, /* B */
1370 &workstations_len, &workstations, /* B */
1371 &unknown_str_len, &unknown_str, /* B */
1372 &munged_dial_len, &munged_dial, /* B */
1373 &user_rid, /* d */
1374 &group_rid, /* d */
1375 &lm_pw_len, &lm_pw_ptr, /* B */
1376 &nt_pw_len, &nt_pw_ptr, /* B */
1377 /* Change from V1 is addition of password history field. */
1378 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1379 &acct_ctrl, /* w */
1380 /* Also "remove_me" field was removed. */
1381 &logon_divs, /* w */
1382 &hours_len, /* d */
1383 &hourslen, &hours, /* B */
1384 &bad_password_count, /* w */
1385 &logon_count, /* w */
1386 &unknown_6); /* d */
1388 if (len == (uint32) -1) {
1389 ret = False;
1390 goto done;
1393 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1394 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1395 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1396 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1397 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1398 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1399 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1401 pdb_set_username(sampass, username, PDB_SET);
1402 pdb_set_domain(sampass, domain, PDB_SET);
1403 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1404 pdb_set_fullname(sampass, fullname, PDB_SET);
1406 if (homedir) {
1407 fstrcpy( tmp_string, homedir );
1408 if (expand_explicit) {
1409 standard_sub_basic( username, domain, tmp_string,
1410 sizeof(tmp_string) );
1412 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1414 else {
1415 pdb_set_homedir(sampass,
1416 talloc_sub_basic(sampass, username, domain,
1417 lp_logon_home()),
1418 PDB_DEFAULT);
1421 if (dir_drive)
1422 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1423 else
1424 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1426 if (logon_script) {
1427 fstrcpy( tmp_string, logon_script );
1428 if (expand_explicit) {
1429 standard_sub_basic( username, domain, tmp_string,
1430 sizeof(tmp_string) );
1432 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1434 else {
1435 pdb_set_logon_script(sampass,
1436 talloc_sub_basic(sampass, username, domain,
1437 lp_logon_script()),
1438 PDB_DEFAULT);
1441 if (profile_path) {
1442 fstrcpy( tmp_string, profile_path );
1443 if (expand_explicit) {
1444 standard_sub_basic( username, domain, tmp_string,
1445 sizeof(tmp_string) );
1447 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1449 else {
1450 pdb_set_profile_path(sampass,
1451 talloc_sub_basic(sampass, username, domain,
1452 lp_logon_path()),
1453 PDB_DEFAULT);
1456 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1457 pdb_set_workstations(sampass, workstations, PDB_SET);
1458 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1460 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1461 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1462 ret = False;
1463 goto done;
1467 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1468 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1469 ret = False;
1470 goto done;
1474 /* Change from V1 is addition of password history field. */
1475 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1476 if (pwHistLen) {
1477 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1478 if (!pw_hist) {
1479 ret = False;
1480 goto done;
1482 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1483 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1484 int i;
1485 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1486 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1487 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1488 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1489 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1490 PW_HISTORY_ENTRY_LEN);
1493 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1494 SAFE_FREE(pw_hist);
1495 ret = False;
1496 goto done;
1498 SAFE_FREE(pw_hist);
1499 } else {
1500 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1503 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1504 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1505 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1506 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1507 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1508 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1509 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1510 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1511 pdb_set_hours(sampass, hours, PDB_SET);
1513 done:
1515 SAFE_FREE(username);
1516 SAFE_FREE(domain);
1517 SAFE_FREE(nt_username);
1518 SAFE_FREE(fullname);
1519 SAFE_FREE(homedir);
1520 SAFE_FREE(dir_drive);
1521 SAFE_FREE(logon_script);
1522 SAFE_FREE(profile_path);
1523 SAFE_FREE(acct_desc);
1524 SAFE_FREE(workstations);
1525 SAFE_FREE(munged_dial);
1526 SAFE_FREE(unknown_str);
1527 SAFE_FREE(lm_pw_ptr);
1528 SAFE_FREE(nt_pw_ptr);
1529 SAFE_FREE(nt_pw_hist_ptr);
1530 SAFE_FREE(hours);
1532 return ret;
1535 /*********************************************************************
1536 *********************************************************************/
1538 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1541 /* times are stored as 32bit integer
1542 take care on system with 64bit wide time_t
1543 --SSS */
1544 uint32 logon_time,
1545 logoff_time,
1546 kickoff_time,
1547 bad_password_time,
1548 pass_last_set_time,
1549 pass_can_change_time,
1550 pass_must_change_time;
1551 char *username = NULL;
1552 char *domain = NULL;
1553 char *nt_username = NULL;
1554 char *dir_drive = NULL;
1555 char *comment = NULL;
1556 char *munged_dial = NULL;
1557 char *fullname = NULL;
1558 char *homedir = NULL;
1559 char *logon_script = NULL;
1560 char *profile_path = NULL;
1561 char *acct_desc = NULL;
1562 char *workstations = NULL;
1563 uint32 username_len, domain_len, nt_username_len,
1564 dir_drive_len, comment_len, munged_dial_len,
1565 fullname_len, homedir_len, logon_script_len,
1566 profile_path_len, acct_desc_len, workstations_len;
1568 uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1569 uint16 logon_divs;
1570 uint16 bad_password_count, logon_count;
1571 uint8 *hours = NULL;
1572 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1573 uint32 len = 0;
1574 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1575 uint32 pwHistLen = 0;
1576 bool ret = True;
1577 fstring tmp_string;
1578 bool expand_explicit = lp_passdb_expand_explicit();
1580 if(sampass == NULL || buf == NULL) {
1581 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1582 return False;
1585 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1587 /* unpack the buffer into variables */
1588 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1589 &logon_time, /* d */
1590 &logoff_time, /* d */
1591 &kickoff_time, /* d */
1592 &bad_password_time, /* d */
1593 &pass_last_set_time, /* d */
1594 &pass_can_change_time, /* d */
1595 &pass_must_change_time, /* d */
1596 &username_len, &username, /* B */
1597 &domain_len, &domain, /* B */
1598 &nt_username_len, &nt_username, /* B */
1599 &fullname_len, &fullname, /* B */
1600 &homedir_len, &homedir, /* B */
1601 &dir_drive_len, &dir_drive, /* B */
1602 &logon_script_len, &logon_script, /* B */
1603 &profile_path_len, &profile_path, /* B */
1604 &acct_desc_len, &acct_desc, /* B */
1605 &workstations_len, &workstations, /* B */
1606 &comment_len, &comment, /* B */
1607 &munged_dial_len, &munged_dial, /* B */
1608 &user_rid, /* d */
1609 &group_rid, /* d */
1610 &lm_pw_len, &lm_pw_ptr, /* B */
1611 &nt_pw_len, &nt_pw_ptr, /* B */
1612 /* Change from V1 is addition of password history field. */
1613 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1614 /* Change from V2 is the uint32 acb_mask */
1615 &acct_ctrl, /* d */
1616 /* Also "remove_me" field was removed. */
1617 &logon_divs, /* w */
1618 &hours_len, /* d */
1619 &hourslen, &hours, /* B */
1620 &bad_password_count, /* w */
1621 &logon_count, /* w */
1622 &unknown_6); /* d */
1624 if (len == (uint32) -1) {
1625 ret = False;
1626 goto done;
1629 pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1630 pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1631 pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1632 pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1633 pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1634 pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1635 pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1637 pdb_set_username(sampass, username, PDB_SET);
1638 pdb_set_domain(sampass, domain, PDB_SET);
1639 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1640 pdb_set_fullname(sampass, fullname, PDB_SET);
1642 if (homedir) {
1643 fstrcpy( tmp_string, homedir );
1644 if (expand_explicit) {
1645 standard_sub_basic( username, domain, tmp_string,
1646 sizeof(tmp_string) );
1648 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1650 else {
1651 pdb_set_homedir(sampass,
1652 talloc_sub_basic(sampass, username, domain,
1653 lp_logon_home()),
1654 PDB_DEFAULT);
1657 if (dir_drive)
1658 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1659 else
1660 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1662 if (logon_script) {
1663 fstrcpy( tmp_string, logon_script );
1664 if (expand_explicit) {
1665 standard_sub_basic( username, domain, tmp_string,
1666 sizeof(tmp_string) );
1668 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1670 else {
1671 pdb_set_logon_script(sampass,
1672 talloc_sub_basic(sampass, username, domain,
1673 lp_logon_script()),
1674 PDB_DEFAULT);
1677 if (profile_path) {
1678 fstrcpy( tmp_string, profile_path );
1679 if (expand_explicit) {
1680 standard_sub_basic( username, domain, tmp_string,
1681 sizeof(tmp_string) );
1683 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1685 else {
1686 pdb_set_profile_path(sampass,
1687 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1688 PDB_DEFAULT);
1691 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1692 pdb_set_comment(sampass, comment, PDB_SET);
1693 pdb_set_workstations(sampass, workstations, PDB_SET);
1694 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1696 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1697 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1698 ret = False;
1699 goto done;
1703 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1704 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1705 ret = False;
1706 goto done;
1710 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1711 if (pwHistLen) {
1712 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1713 if (!pw_hist) {
1714 ret = False;
1715 goto done;
1717 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1718 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1719 int i;
1720 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1721 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1722 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1723 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1724 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1725 PW_HISTORY_ENTRY_LEN);
1728 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1729 SAFE_FREE(pw_hist);
1730 ret = False;
1731 goto done;
1733 SAFE_FREE(pw_hist);
1734 } else {
1735 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1738 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1739 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1740 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1741 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1742 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1743 /* Change from V2 is the uint32 acct_ctrl */
1744 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1745 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1746 pdb_set_hours(sampass, hours, PDB_SET);
1748 done:
1750 SAFE_FREE(username);
1751 SAFE_FREE(domain);
1752 SAFE_FREE(nt_username);
1753 SAFE_FREE(fullname);
1754 SAFE_FREE(homedir);
1755 SAFE_FREE(dir_drive);
1756 SAFE_FREE(logon_script);
1757 SAFE_FREE(profile_path);
1758 SAFE_FREE(acct_desc);
1759 SAFE_FREE(workstations);
1760 SAFE_FREE(munged_dial);
1761 SAFE_FREE(comment);
1762 SAFE_FREE(lm_pw_ptr);
1763 SAFE_FREE(nt_pw_ptr);
1764 SAFE_FREE(nt_pw_hist_ptr);
1765 SAFE_FREE(hours);
1767 return ret;
1770 /*********************************************************************
1771 *********************************************************************/
1773 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1775 size_t len, buflen;
1777 /* times are stored as 32bit integer
1778 take care on system with 64bit wide time_t
1779 --SSS */
1780 uint32 logon_time,
1781 logoff_time,
1782 kickoff_time,
1783 bad_password_time,
1784 pass_last_set_time,
1785 pass_can_change_time,
1786 pass_must_change_time;
1788 uint32 user_rid, group_rid;
1790 const char *username;
1791 const char *domain;
1792 const char *nt_username;
1793 const char *dir_drive;
1794 const char *comment;
1795 const char *munged_dial;
1796 const char *fullname;
1797 const char *homedir;
1798 const char *logon_script;
1799 const char *profile_path;
1800 const char *acct_desc;
1801 const char *workstations;
1802 uint32 username_len, domain_len, nt_username_len,
1803 dir_drive_len, comment_len, munged_dial_len,
1804 fullname_len, homedir_len, logon_script_len,
1805 profile_path_len, acct_desc_len, workstations_len;
1807 const uint8 *lm_pw;
1808 const uint8 *nt_pw;
1809 const uint8 *nt_pw_hist;
1810 uint32 lm_pw_len = 16;
1811 uint32 nt_pw_len = 16;
1812 uint32 nt_pw_hist_len;
1813 uint32 pwHistLen = 0;
1815 *buf = NULL;
1816 buflen = 0;
1818 logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1819 logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1820 kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1821 bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1822 pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1823 pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1824 pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1826 user_rid = pdb_get_user_rid(sampass);
1827 group_rid = pdb_get_group_rid(sampass);
1829 username = pdb_get_username(sampass);
1830 if (username) {
1831 username_len = strlen(username) +1;
1832 } else {
1833 username_len = 0;
1836 domain = pdb_get_domain(sampass);
1837 if (domain) {
1838 domain_len = strlen(domain) +1;
1839 } else {
1840 domain_len = 0;
1843 nt_username = pdb_get_nt_username(sampass);
1844 if (nt_username) {
1845 nt_username_len = strlen(nt_username) +1;
1846 } else {
1847 nt_username_len = 0;
1850 fullname = pdb_get_fullname(sampass);
1851 if (fullname) {
1852 fullname_len = strlen(fullname) +1;
1853 } else {
1854 fullname_len = 0;
1858 * Only updates fields which have been set (not defaults from smb.conf)
1861 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1862 dir_drive = pdb_get_dir_drive(sampass);
1863 } else {
1864 dir_drive = NULL;
1866 if (dir_drive) {
1867 dir_drive_len = strlen(dir_drive) +1;
1868 } else {
1869 dir_drive_len = 0;
1872 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1873 homedir = pdb_get_homedir(sampass);
1874 } else {
1875 homedir = NULL;
1877 if (homedir) {
1878 homedir_len = strlen(homedir) +1;
1879 } else {
1880 homedir_len = 0;
1883 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1884 logon_script = pdb_get_logon_script(sampass);
1885 } else {
1886 logon_script = NULL;
1888 if (logon_script) {
1889 logon_script_len = strlen(logon_script) +1;
1890 } else {
1891 logon_script_len = 0;
1894 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1895 profile_path = pdb_get_profile_path(sampass);
1896 } else {
1897 profile_path = NULL;
1899 if (profile_path) {
1900 profile_path_len = strlen(profile_path) +1;
1901 } else {
1902 profile_path_len = 0;
1905 lm_pw = pdb_get_lanman_passwd(sampass);
1906 if (!lm_pw) {
1907 lm_pw_len = 0;
1910 nt_pw = pdb_get_nt_passwd(sampass);
1911 if (!nt_pw) {
1912 nt_pw_len = 0;
1915 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1916 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1917 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1918 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1919 } else {
1920 nt_pw_hist_len = 0;
1923 acct_desc = pdb_get_acct_desc(sampass);
1924 if (acct_desc) {
1925 acct_desc_len = strlen(acct_desc) +1;
1926 } else {
1927 acct_desc_len = 0;
1930 workstations = pdb_get_workstations(sampass);
1931 if (workstations) {
1932 workstations_len = strlen(workstations) +1;
1933 } else {
1934 workstations_len = 0;
1937 comment = pdb_get_comment(sampass);
1938 if (comment) {
1939 comment_len = strlen(comment) +1;
1940 } else {
1941 comment_len = 0;
1944 munged_dial = pdb_get_munged_dial(sampass);
1945 if (munged_dial) {
1946 munged_dial_len = strlen(munged_dial) +1;
1947 } else {
1948 munged_dial_len = 0;
1951 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1953 /* one time to get the size needed */
1954 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1955 logon_time, /* d */
1956 logoff_time, /* d */
1957 kickoff_time, /* d */
1958 bad_password_time, /* d */
1959 pass_last_set_time, /* d */
1960 pass_can_change_time, /* d */
1961 pass_must_change_time, /* d */
1962 username_len, username, /* B */
1963 domain_len, domain, /* B */
1964 nt_username_len, nt_username, /* B */
1965 fullname_len, fullname, /* B */
1966 homedir_len, homedir, /* B */
1967 dir_drive_len, dir_drive, /* B */
1968 logon_script_len, logon_script, /* B */
1969 profile_path_len, profile_path, /* B */
1970 acct_desc_len, acct_desc, /* B */
1971 workstations_len, workstations, /* B */
1972 comment_len, comment, /* B */
1973 munged_dial_len, munged_dial, /* B */
1974 user_rid, /* d */
1975 group_rid, /* d */
1976 lm_pw_len, lm_pw, /* B */
1977 nt_pw_len, nt_pw, /* B */
1978 nt_pw_hist_len, nt_pw_hist, /* B */
1979 pdb_get_acct_ctrl(sampass), /* d */
1980 pdb_get_logon_divs(sampass), /* w */
1981 pdb_get_hours_len(sampass), /* d */
1982 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1983 pdb_get_bad_password_count(sampass), /* w */
1984 pdb_get_logon_count(sampass), /* w */
1985 pdb_get_unknown_6(sampass)); /* d */
1987 if (size_only) {
1988 return buflen;
1991 /* malloc the space needed */
1992 if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1993 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1994 return (-1);
1997 /* now for the real call to tdb_pack() */
1998 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
1999 logon_time, /* d */
2000 logoff_time, /* d */
2001 kickoff_time, /* d */
2002 bad_password_time, /* d */
2003 pass_last_set_time, /* d */
2004 pass_can_change_time, /* d */
2005 pass_must_change_time, /* d */
2006 username_len, username, /* B */
2007 domain_len, domain, /* B */
2008 nt_username_len, nt_username, /* B */
2009 fullname_len, fullname, /* B */
2010 homedir_len, homedir, /* B */
2011 dir_drive_len, dir_drive, /* B */
2012 logon_script_len, logon_script, /* B */
2013 profile_path_len, profile_path, /* B */
2014 acct_desc_len, acct_desc, /* B */
2015 workstations_len, workstations, /* B */
2016 comment_len, comment, /* B */
2017 munged_dial_len, munged_dial, /* B */
2018 user_rid, /* d */
2019 group_rid, /* d */
2020 lm_pw_len, lm_pw, /* B */
2021 nt_pw_len, nt_pw, /* B */
2022 nt_pw_hist_len, nt_pw_hist, /* B */
2023 pdb_get_acct_ctrl(sampass), /* d */
2024 pdb_get_logon_divs(sampass), /* w */
2025 pdb_get_hours_len(sampass), /* d */
2026 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2027 pdb_get_bad_password_count(sampass), /* w */
2028 pdb_get_logon_count(sampass), /* w */
2029 pdb_get_unknown_6(sampass)); /* d */
2031 /* check to make sure we got it correct */
2032 if (buflen != len) {
2033 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2034 (unsigned long)buflen, (unsigned long)len));
2035 /* error */
2036 SAFE_FREE (*buf);
2037 return (-1);
2040 return (buflen);
2043 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2045 /* nothing changed between V3 and V4 */
2046 return init_samu_from_buffer_v3(sampass, buf, buflen);
2049 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2051 /* nothing changed between V3 and V4 */
2052 return init_buffer_from_samu_v3(buf, sampass, size_only);
2055 /**********************************************************************
2056 Intialize a struct samu struct from a BYTE buffer of size len
2057 *********************************************************************/
2059 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2060 uint8 *buf, uint32 buflen)
2062 switch (level) {
2063 case SAMU_BUFFER_V0:
2064 return init_samu_from_buffer_v0(sampass, buf, buflen);
2065 case SAMU_BUFFER_V1:
2066 return init_samu_from_buffer_v1(sampass, buf, buflen);
2067 case SAMU_BUFFER_V2:
2068 return init_samu_from_buffer_v2(sampass, buf, buflen);
2069 case SAMU_BUFFER_V3:
2070 return init_samu_from_buffer_v3(sampass, buf, buflen);
2071 case SAMU_BUFFER_V4:
2072 return init_samu_from_buffer_v4(sampass, buf, buflen);
2075 return false;
2078 /**********************************************************************
2079 Intialize a BYTE buffer from a struct samu struct
2080 *********************************************************************/
2082 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2084 return init_buffer_from_samu_v4(buf, sampass, size_only);
2087 /*********************************************************************
2088 *********************************************************************/
2090 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2092 uint8 *buf = NULL;
2093 int len;
2095 len = init_buffer_from_samu(&buf, src, False);
2096 if (len == -1 || !buf) {
2097 SAFE_FREE(buf);
2098 return False;
2101 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2102 free(buf);
2103 return False;
2106 dst->methods = src->methods;
2108 if ( src->unix_pw ) {
2109 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2110 if (!dst->unix_pw) {
2111 free(buf);
2112 return False;
2116 if (src->group_sid) {
2117 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2120 free(buf);
2121 return True;
2124 /*********************************************************************
2125 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2126 *********************************************************************/
2128 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2130 time_t LastBadPassword;
2131 uint16 BadPasswordCount;
2132 uint32 resettime;
2133 bool res;
2135 BadPasswordCount = pdb_get_bad_password_count(sampass);
2136 if (!BadPasswordCount) {
2137 DEBUG(9, ("No bad password attempts.\n"));
2138 return True;
2141 become_root();
2142 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2143 unbecome_root();
2145 if (!res) {
2146 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2147 return False;
2150 /* First, check if there is a reset time to compare */
2151 if ((resettime == (uint32) -1) || (resettime == 0)) {
2152 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2153 return True;
2156 LastBadPassword = pdb_get_bad_password_time(sampass);
2157 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2158 (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2159 if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2160 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2161 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2162 if (updated) {
2163 *updated = True;
2167 return True;
2170 /*********************************************************************
2171 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2172 *********************************************************************/
2174 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2176 uint32 duration;
2177 time_t LastBadPassword;
2178 bool res;
2180 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2181 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2182 pdb_get_username(sampass)));
2183 return True;
2186 become_root();
2187 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2188 unbecome_root();
2190 if (!res) {
2191 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2192 return False;
2195 /* First, check if there is a duration to compare */
2196 if ((duration == (uint32) -1) || (duration == 0)) {
2197 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2198 return True;
2201 LastBadPassword = pdb_get_bad_password_time(sampass);
2202 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2203 pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2205 if (LastBadPassword == (time_t)0) {
2206 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2207 "administratively locked out with no bad password "
2208 "time. Leaving locked out.\n",
2209 pdb_get_username(sampass) ));
2210 return True;
2213 if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2214 pdb_set_acct_ctrl(sampass,
2215 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2216 PDB_CHANGED);
2217 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2218 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2219 if (updated) {
2220 *updated = True;
2224 return True;
2227 /*********************************************************************
2228 Increment the bad_password_count
2229 *********************************************************************/
2231 bool pdb_increment_bad_password_count(struct samu *sampass)
2233 uint32 account_policy_lockout;
2234 bool autolock_updated = False, badpw_updated = False;
2235 bool ret;
2237 /* Retrieve the account lockout policy */
2238 become_root();
2239 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2240 unbecome_root();
2241 if ( !ret ) {
2242 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2243 return False;
2246 /* If there is no policy, we don't need to continue checking */
2247 if (!account_policy_lockout) {
2248 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2249 return True;
2252 /* Check if the autolock needs to be cleared */
2253 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2254 return False;
2256 /* Check if the badpw count needs to be reset */
2257 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2258 return False;
2261 Ok, now we can assume that any resetting that needs to be
2262 done has been done, and just get on with incrementing
2263 and autolocking if necessary
2266 pdb_set_bad_password_count(sampass,
2267 pdb_get_bad_password_count(sampass)+1,
2268 PDB_CHANGED);
2269 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2272 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2273 return True;
2275 if (!pdb_set_acct_ctrl(sampass,
2276 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2277 PDB_CHANGED)) {
2278 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2279 return False;
2282 return True;
2285 bool is_dc_trusted_domain_situation(const char *domain_name)
2287 return IS_DC && !strequal(domain_name, lp_workgroup());
2290 /*******************************************************************
2291 Wrapper around retrieving the clear text trust account password.
2292 appropriate account name is stored in account_name.
2293 Caller must free password, but not account_name.
2294 *******************************************************************/
2296 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2297 const char **account_name,
2298 enum netr_SchannelType *channel)
2300 char *pwd;
2301 time_t last_set_time;
2303 /* if we are a DC and this is not our domain, then lookup an account
2304 * for the domain trust */
2306 if (is_dc_trusted_domain_situation(domain)) {
2307 if (!lp_allow_trusted_domains()) {
2308 return false;
2311 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2312 &last_set_time))
2314 DEBUG(0, ("get_trust_pw: could not fetch trust "
2315 "account password for trusted domain %s\n",
2316 domain));
2317 return false;
2320 if (channel != NULL) {
2321 *channel = SEC_CHAN_DOMAIN;
2324 if (account_name != NULL) {
2325 *account_name = lp_workgroup();
2328 return true;
2332 * Since we can only be member of one single domain, we are now
2333 * in a member situation:
2335 * - Either we are a DC (selfjoined) and the domain is our
2336 * own domain.
2337 * - Or we are on a member and the domain is our own or some
2338 * other (potentially trusted) domain.
2340 * In both cases, we can only get the machine account password
2341 * for our own domain to connect to our own dc. (For a member,
2342 * request to trusted domains are performed through our dc.)
2344 * So we simply use our own domain name to retrieve the
2345 * machine account passowrd and ignore the request domain here.
2348 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2350 if (pwd != NULL) {
2351 *ret_pwd = pwd;
2352 if (account_name != NULL) {
2353 *account_name = global_myname();
2356 return true;
2359 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2360 "account password for domain %s\n", domain));
2361 return false;
2364 /*******************************************************************
2365 Wrapper around retrieving the trust account password.
2366 appropriate account name is stored in account_name.
2367 *******************************************************************/
2369 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2370 const char **account_name,
2371 enum netr_SchannelType *channel)
2373 char *pwd = NULL;
2374 time_t last_set_time;
2376 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2377 E_md4hash(pwd, ret_pwd);
2378 SAFE_FREE(pwd);
2379 return true;
2380 } else if (is_dc_trusted_domain_situation(domain)) {
2381 return false;
2384 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2386 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2387 &last_set_time,
2388 channel))
2390 if (account_name != NULL) {
2391 *account_name = global_myname();
2394 return true;
2397 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2398 "password for domain %s\n", domain));
2399 return False;
2402 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2403 struct samu *pw)
2405 struct samr_LogonHours hours;
2406 const int units_per_week = 168;
2408 ZERO_STRUCT(hours);
2409 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2410 if (!hours.bits) {
2411 return hours;
2414 hours.units_per_week = units_per_week;
2415 memset(hours.bits, 0xFF, units_per_week);
2417 if (pdb_get_hours(pw)) {
2418 memcpy(hours.bits, pdb_get_hours(pw),
2419 MIN(pdb_get_hours_len(pw), units_per_week));
2422 return hours;