s3-utils/net_rpc_printer.c: print more info on write error
[Samba/gebeck_regimport.git] / source3 / passdb / passdb.c
blobfaa608cc7851019c6b81d30af3dc8fdefd47fc00
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Jeremy Allison 1996-2001
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6 Copyright (C) Gerald (Jerry) Carter 2000-2006
7 Copyright (C) Andrew Bartlett 2001-2002
8 Copyright (C) Simo Sorce 2003
9 Copyright (C) Volker Lendecke 2006
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "passdb.h"
27 #include "system/passwd.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "secrets.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "util_tdb.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_PASSDB
37 /******************************************************************
38 Get the default domain/netbios name to be used when
39 testing authentication.
41 LEGACY: this function provides the legacy domain mapping used with
42 the lp_map_untrusted_to_domain() parameter
43 ******************************************************************/
45 const char *my_sam_name(void)
47 /* Standalone servers can only use the local netbios name */
48 if ( lp_server_role() == ROLE_STANDALONE )
49 return lp_netbios_name();
51 /* Default to the DOMAIN name when not specified */
52 return lp_workgroup();
55 /**********************************************************************
56 ***********************************************************************/
58 static int samu_destroy(struct samu *user)
60 data_blob_clear_free( &user->lm_pw );
61 data_blob_clear_free( &user->nt_pw );
63 if ( user->plaintext_pw )
64 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
66 return 0;
69 /**********************************************************************
70 generate a new struct samuser
71 ***********************************************************************/
73 struct samu *samu_new( TALLOC_CTX *ctx )
75 struct samu *user;
77 if ( !(user = talloc_zero( ctx, struct samu )) ) {
78 DEBUG(0,("samuser_new: Talloc failed!\n"));
79 return NULL;
82 talloc_set_destructor( user, samu_destroy );
84 /* no initial methods */
86 user->methods = NULL;
88 /* Don't change these timestamp settings without a good reason.
89 They are important for NT member server compatibility. */
91 user->logon_time = (time_t)0;
92 user->pass_last_set_time = (time_t)0;
93 user->pass_can_change_time = (time_t)0;
94 user->logoff_time = get_time_t_max();
95 user->kickoff_time = get_time_t_max();
96 user->pass_must_change_time = get_time_t_max();
97 user->fields_present = 0x00ffffff;
98 user->logon_divs = 168; /* hours per week */
99 user->hours_len = 21; /* 21 times 8 bits = 168 */
100 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
101 user->bad_password_count = 0;
102 user->logon_count = 0;
103 user->unknown_6 = 0x000004ec; /* don't know */
105 /* Some parts of samba strlen their pdb_get...() returns,
106 so this keeps the interface unchanged for now. */
108 user->username = "";
109 user->domain = "";
110 user->nt_username = "";
111 user->full_name = "";
112 user->home_dir = "";
113 user->logon_script = "";
114 user->profile_path = "";
115 user->acct_desc = "";
116 user->workstations = "";
117 user->comment = "";
118 user->munged_dial = "";
120 user->plaintext_pw = NULL;
122 /* Unless we know otherwise have a Account Control Bit
123 value of 'normal user'. This helps User Manager, which
124 asks for a filtered list of users. */
126 user->acct_ctrl = ACB_NORMAL;
128 return user;
131 static int count_commas(const char *str)
133 int num_commas = 0;
134 const char *comma = str;
136 while ((comma = strchr(comma, ',')) != NULL) {
137 comma += 1;
138 num_commas += 1;
140 return num_commas;
143 /*********************************************************************
144 Initialize a struct samu from a struct passwd including the user
145 and group SIDs. The *user structure is filled out with the Unix
146 attributes and a user SID.
147 *********************************************************************/
149 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
151 const char *guest_account = lp_guestaccount();
152 const char *domain = lp_netbios_name();
153 char *fullname;
154 uint32_t urid;
156 if ( !pwd ) {
157 return NT_STATUS_NO_SUCH_USER;
160 /* Basic properties based upon the Unix account information */
162 pdb_set_username(user, pwd->pw_name, PDB_SET);
164 fullname = NULL;
166 if (count_commas(pwd->pw_gecos) == 3) {
168 * Heuristic: This seems to be a gecos field that has been
169 * edited by chfn(1). Only use the part before the first
170 * comma. Fixes bug 5198.
172 fullname = talloc_strndup(
173 talloc_tos(), pwd->pw_gecos,
174 strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
177 if (fullname != NULL) {
178 pdb_set_fullname(user, fullname, PDB_SET);
179 } else {
180 pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
182 TALLOC_FREE(fullname);
184 pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
185 #if 0
186 /* This can lead to a primary group of S-1-22-2-XX which
187 will be rejected by other parts of the Samba code.
188 Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
189 --jerry */
191 gid_to_sid(&group_sid, pwd->pw_gid);
192 pdb_set_group_sid(user, &group_sid, PDB_SET);
193 #endif
195 /* save the password structure for later use */
197 user->unix_pw = tcopy_passwd( user, pwd );
199 /* Special case for the guest account which must have a RID of 501 */
201 if ( strequal( pwd->pw_name, guest_account ) ) {
202 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_RID_GUEST, PDB_DEFAULT)) {
203 return NT_STATUS_NO_SUCH_USER;
205 return NT_STATUS_OK;
208 /* Non-guest accounts...Check for a workstation or user account */
210 if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
211 /* workstation */
213 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
214 DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
215 pwd->pw_name));
216 return NT_STATUS_INVALID_COMPUTER_NAME;
219 else {
220 /* user */
222 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
223 DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
224 pwd->pw_name));
225 return NT_STATUS_INVALID_ACCOUNT_NAME;
228 /* set some basic attributes */
230 pdb_set_profile_path(user, talloc_sub_specified(user,
231 lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
232 PDB_DEFAULT);
233 pdb_set_homedir(user, talloc_sub_specified(user,
234 lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
235 PDB_DEFAULT);
236 pdb_set_dir_drive(user, talloc_sub_specified(user,
237 lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
238 PDB_DEFAULT);
239 pdb_set_logon_script(user, talloc_sub_specified(user,
240 lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
241 PDB_DEFAULT);
244 /* Now deal with the user SID. If we have a backend that can generate
245 RIDs, then do so. But sometimes the caller just wanted a structure
246 initialized and will fill in these fields later (such as from a
247 netr_SamInfo3 structure) */
249 if ( create && (pdb_capabilities() & PDB_CAP_STORE_RIDS)) {
250 uint32_t user_rid;
251 struct dom_sid user_sid;
253 if ( !pdb_new_rid( &user_rid ) ) {
254 DEBUG(3, ("Could not allocate a new RID\n"));
255 return NT_STATUS_ACCESS_DENIED;
258 sid_compose(&user_sid, get_global_sam_sid(), user_rid);
260 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
261 DEBUG(3, ("pdb_set_user_sid failed\n"));
262 return NT_STATUS_INTERNAL_ERROR;
265 return NT_STATUS_OK;
268 /* generate a SID for the user with the RID algorithm */
270 urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
272 if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
273 return NT_STATUS_INTERNAL_ERROR;
276 return NT_STATUS_OK;
279 /********************************************************************
280 Set the Unix user attributes
281 ********************************************************************/
283 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
285 return samu_set_unix_internal( user, pwd, False );
288 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
290 return samu_set_unix_internal( user, pwd, True );
293 /**********************************************************
294 Encode the account control bits into a string.
295 length = length of string to encode into (including terminating
296 null). length *MUST BE MORE THAN 2* !
297 **********************************************************/
299 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
301 fstring acct_str;
302 char *result;
304 size_t i = 0;
306 SMB_ASSERT(length <= sizeof(acct_str));
308 acct_str[i++] = '[';
310 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
311 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
312 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
313 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
314 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
315 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
316 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
317 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
318 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
319 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
320 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
322 for ( ; i < length - 2 ; i++ )
323 acct_str[i] = ' ';
325 i = length - 2;
326 acct_str[i++] = ']';
327 acct_str[i++] = '\0';
329 result = talloc_strdup(talloc_tos(), acct_str);
330 SMB_ASSERT(result != NULL);
331 return result;
334 /**********************************************************
335 Decode the account control bits from a string.
336 **********************************************************/
338 uint32_t pdb_decode_acct_ctrl(const char *p)
340 uint32_t acct_ctrl = 0;
341 bool finished = false;
344 * Check if the account type bits have been encoded after the
345 * NT password (in the form [NDHTUWSLXI]).
348 if (*p != '[')
349 return 0;
351 for (p++; *p && !finished; p++) {
352 switch (*p) {
353 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
354 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
355 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
356 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
357 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
358 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
359 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
360 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
361 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
362 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
363 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
364 case ' ': { break; }
365 case ':':
366 case '\n':
367 case '\0':
368 case ']':
369 default: { finished = true; }
373 return acct_ctrl;
376 /*************************************************************
377 Routine to set 32 hex password characters from a 16 byte array.
378 **************************************************************/
380 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
382 if (pwd != NULL) {
383 int i;
384 for (i = 0; i < 16; i++)
385 slprintf(&p[i*2], 3, "%02X", pwd[i]);
386 } else {
387 if (acct_ctrl & ACB_PWNOTREQ)
388 strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
389 else
390 strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
394 /*************************************************************
395 Routine to get the 32 hex characters and turn them
396 into a 16 byte array.
397 **************************************************************/
399 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
401 int i;
402 unsigned char lonybble, hinybble;
403 const char *hexchars = "0123456789ABCDEF";
404 char *p1, *p2;
406 if (!p)
407 return false;
409 for (i = 0; i < 32; i += 2) {
410 hinybble = toupper_m(p[i]);
411 lonybble = toupper_m(p[i + 1]);
413 p1 = strchr(hexchars, hinybble);
414 p2 = strchr(hexchars, lonybble);
416 if (!p1 || !p2)
417 return false;
419 hinybble = PTR_DIFF(p1, hexchars);
420 lonybble = PTR_DIFF(p2, hexchars);
422 pwd[i / 2] = (hinybble << 4) | lonybble;
424 return true;
427 /*************************************************************
428 Routine to set 42 hex hours characters from a 21 byte array.
429 **************************************************************/
431 void pdb_sethexhours(char *p, const unsigned char *hours)
433 if (hours != NULL) {
434 int i;
435 for (i = 0; i < 21; i++) {
436 slprintf(&p[i*2], 3, "%02X", hours[i]);
438 } else {
439 strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
443 /*************************************************************
444 Routine to get the 42 hex characters and turn them
445 into a 21 byte array.
446 **************************************************************/
448 bool pdb_gethexhours(const char *p, unsigned char *hours)
450 int i;
451 unsigned char lonybble, hinybble;
452 const char *hexchars = "0123456789ABCDEF";
453 char *p1, *p2;
455 if (!p) {
456 return (False);
459 for (i = 0; i < 42; i += 2) {
460 hinybble = toupper_m(p[i]);
461 lonybble = toupper_m(p[i + 1]);
463 p1 = strchr(hexchars, hinybble);
464 p2 = strchr(hexchars, lonybble);
466 if (!p1 || !p2) {
467 return (False);
470 hinybble = PTR_DIFF(p1, hexchars);
471 lonybble = PTR_DIFF(p2, hexchars);
473 hours[i / 2] = (hinybble << 4) | lonybble;
475 return (True);
478 /********************************************************************
479 ********************************************************************/
481 int algorithmic_rid_base(void)
483 int rid_offset;
485 rid_offset = lp_algorithmic_rid_base();
487 if (rid_offset < BASE_RID) {
488 /* Try to prevent admin foot-shooting, we can't put algorithmic
489 rids below 1000, that's the 'well known RIDs' on NT */
490 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
491 rid_offset = BASE_RID;
493 if (rid_offset & 1) {
494 DEBUG(0, ("algorithmic rid base must be even\n"));
495 rid_offset += 1;
497 return rid_offset;
500 /*******************************************************************
501 Converts NT user RID to a UNIX uid.
502 ********************************************************************/
504 uid_t algorithmic_pdb_user_rid_to_uid(uint32_t user_rid)
506 int rid_offset = algorithmic_rid_base();
507 return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
510 uid_t max_algorithmic_uid(void)
512 return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
515 /*******************************************************************
516 converts UNIX uid to an NT User RID.
517 ********************************************************************/
519 uint32_t algorithmic_pdb_uid_to_user_rid(uid_t uid)
521 int rid_offset = algorithmic_rid_base();
522 return (((((uint32_t)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
525 /*******************************************************************
526 Converts NT group RID to a UNIX gid.
527 ********************************************************************/
529 gid_t pdb_group_rid_to_gid(uint32_t group_rid)
531 int rid_offset = algorithmic_rid_base();
532 return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
535 gid_t max_algorithmic_gid(void)
537 return pdb_group_rid_to_gid(0xffffffff);
540 /*******************************************************************
541 converts NT Group RID to a UNIX uid.
543 warning: you must not call that function only
544 you must do a call to the group mapping first.
545 there is not anymore a direct link between the gid and the rid.
546 ********************************************************************/
548 uint32_t algorithmic_pdb_gid_to_group_rid(gid_t gid)
550 int rid_offset = algorithmic_rid_base();
551 return (((((uint32_t)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
554 /*******************************************************************
555 Decides if a RID is a well known RID.
556 ********************************************************************/
558 static bool rid_is_well_known(uint32_t rid)
560 /* Not using rid_offset here, because this is the actual
561 NT fixed value (1000) */
563 return (rid < BASE_RID);
566 /*******************************************************************
567 Decides if a RID is a user or group RID.
568 ********************************************************************/
570 bool algorithmic_pdb_rid_is_user(uint32_t rid)
572 if ( rid_is_well_known(rid) ) {
574 * The only well known user RIDs are DOMAIN_RID_ADMINISTRATOR
575 * and DOMAIN_RID_GUEST.
577 if(rid == DOMAIN_RID_ADMINISTRATOR || rid == DOMAIN_RID_GUEST)
578 return True;
579 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
580 return True;
582 return False;
585 /*******************************************************************
586 Convert a name into a SID. Used in the lookup name rpc.
587 ********************************************************************/
589 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
590 enum lsa_SidType *type)
592 GROUP_MAP map;
593 bool ret;
595 /* Windows treats "MACHINE\None" as a special name for
596 rid 513 on non-DCs. You cannot create a user or group
597 name "None" on Windows. You will get an error that
598 the group already exists. */
600 if ( strequal( name, "None" ) ) {
601 *rid = DOMAIN_RID_USERS;
602 *type = SID_NAME_DOM_GRP;
604 return True;
607 /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
608 * correctly in the case where foo also exists as a user. If the flag
609 * is set, don't look for users at all. */
611 if ((flags & LOOKUP_NAME_GROUP) == 0) {
612 struct samu *sam_account = NULL;
613 struct dom_sid user_sid;
615 if ( !(sam_account = samu_new( NULL )) ) {
616 return False;
619 become_root();
620 ret = pdb_getsampwnam(sam_account, name);
621 unbecome_root();
623 if (ret) {
624 sid_copy(&user_sid, pdb_get_user_sid(sam_account));
627 TALLOC_FREE(sam_account);
629 if (ret) {
630 if (!sid_check_is_in_our_domain(&user_sid)) {
631 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
632 name, sid_string_dbg(&user_sid)));
633 return False;
636 sid_peek_rid(&user_sid, rid);
637 *type = SID_NAME_USER;
638 return True;
643 * Maybe it is a group ?
646 become_root();
647 ret = pdb_getgrnam(&map, name);
648 unbecome_root();
650 if (!ret) {
651 return False;
654 /* BUILTIN groups are looked up elsewhere */
655 if (!sid_check_is_in_our_domain(&map.sid)) {
656 DEBUG(10, ("Found group %s (%s) not in our domain -- "
657 "ignoring.", name, sid_string_dbg(&map.sid)));
658 return False;
661 /* yes it's a mapped group */
662 sid_peek_rid(&map.sid, rid);
663 *type = map.sid_name_use;
664 return True;
667 /*************************************************************
668 Change a password entry in the local passdb backend.
670 Assumptions:
671 - always called as root
672 - ignores the account type except when adding a new account
673 - will create/delete the unix account if the relative
674 add/delete user script is configured
676 *************************************************************/
678 NTSTATUS local_password_change(const char *user_name,
679 int local_flags,
680 const char *new_passwd,
681 char **pp_err_str,
682 char **pp_msg_str)
684 TALLOC_CTX *tosctx;
685 struct samu *sam_pass;
686 uint32_t acb;
687 uint32_t rid;
688 NTSTATUS result;
689 bool user_exists;
690 int ret = -1;
692 *pp_err_str = NULL;
693 *pp_msg_str = NULL;
695 tosctx = talloc_tos();
697 sam_pass = samu_new(tosctx);
698 if (!sam_pass) {
699 result = NT_STATUS_NO_MEMORY;
700 goto done;
703 /* Get the smb passwd entry for this user */
704 user_exists = pdb_getsampwnam(sam_pass, user_name);
706 /* Check delete first, we don't need to do anything else if we
707 * are going to delete the acocunt */
708 if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
710 result = pdb_delete_user(tosctx, sam_pass);
711 if (!NT_STATUS_IS_OK(result)) {
712 ret = asprintf(pp_err_str,
713 "Failed to delete entry for user %s.\n",
714 user_name);
715 if (ret < 0) {
716 *pp_err_str = NULL;
718 result = NT_STATUS_UNSUCCESSFUL;
719 } else {
720 ret = asprintf(pp_msg_str,
721 "Deleted user %s.\n",
722 user_name);
723 if (ret < 0) {
724 *pp_msg_str = NULL;
727 goto done;
730 if (user_exists && (local_flags & LOCAL_ADD_USER)) {
731 /* the entry already existed */
732 local_flags &= ~LOCAL_ADD_USER;
735 if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
736 ret = asprintf(pp_err_str,
737 "Failed to find entry for user %s.\n",
738 user_name);
739 if (ret < 0) {
740 *pp_err_str = NULL;
742 result = NT_STATUS_NO_SUCH_USER;
743 goto done;
746 /* First thing add the new user if we are required to do so */
747 if (local_flags & LOCAL_ADD_USER) {
749 if (local_flags & LOCAL_TRUST_ACCOUNT) {
750 acb = ACB_WSTRUST;
751 } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
752 acb = ACB_DOMTRUST;
753 } else {
754 acb = ACB_NORMAL;
757 result = pdb_create_user(tosctx, user_name, acb, &rid);
758 if (!NT_STATUS_IS_OK(result)) {
759 ret = asprintf(pp_err_str,
760 "Failed to add entry for user %s.\n",
761 user_name);
762 if (ret < 0) {
763 *pp_err_str = NULL;
765 result = NT_STATUS_UNSUCCESSFUL;
766 goto done;
769 sam_pass = samu_new(tosctx);
770 if (!sam_pass) {
771 result = NT_STATUS_NO_MEMORY;
772 goto done;
775 /* Now get back the smb passwd entry for this new user */
776 user_exists = pdb_getsampwnam(sam_pass, user_name);
777 if (!user_exists) {
778 ret = asprintf(pp_err_str,
779 "Failed to add entry for user %s.\n",
780 user_name);
781 if (ret < 0) {
782 *pp_err_str = NULL;
784 result = NT_STATUS_UNSUCCESSFUL;
785 goto done;
789 acb = pdb_get_acct_ctrl(sam_pass);
792 * We are root - just write the new password
793 * and the valid last change time.
795 if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
796 acb |= ACB_PWNOTREQ;
797 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
798 ret = asprintf(pp_err_str,
799 "Failed to set 'no password required' "
800 "flag for user %s.\n", user_name);
801 if (ret < 0) {
802 *pp_err_str = NULL;
804 result = NT_STATUS_UNSUCCESSFUL;
805 goto done;
809 if (local_flags & LOCAL_SET_PASSWORD) {
811 * If we're dealing with setting a completely empty user account
812 * ie. One with a password of 'XXXX', but not set disabled (like
813 * an account created from scratch) then if the old password was
814 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
815 * We remove that as we're giving this user their first password
816 * and the decision hasn't really been made to disable them (ie.
817 * don't create them disabled). JRA.
819 if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
820 (acb & ACB_DISABLED)) {
821 acb &= (~ACB_DISABLED);
822 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
823 ret = asprintf(pp_err_str,
824 "Failed to unset 'disabled' "
825 "flag for user %s.\n",
826 user_name);
827 if (ret < 0) {
828 *pp_err_str = NULL;
830 result = NT_STATUS_UNSUCCESSFUL;
831 goto done;
835 acb &= (~ACB_PWNOTREQ);
836 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
837 ret = asprintf(pp_err_str,
838 "Failed to unset 'no password required'"
839 " flag for user %s.\n", user_name);
840 if (ret < 0) {
841 *pp_err_str = NULL;
843 result = NT_STATUS_UNSUCCESSFUL;
844 goto done;
847 if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
848 ret = asprintf(pp_err_str,
849 "Failed to set password for "
850 "user %s.\n", user_name);
851 if (ret < 0) {
852 *pp_err_str = NULL;
854 result = NT_STATUS_UNSUCCESSFUL;
855 goto done;
859 if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
860 acb |= ACB_DISABLED;
861 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
862 ret = asprintf(pp_err_str,
863 "Failed to set 'disabled' flag for "
864 "user %s.\n", user_name);
865 if (ret < 0) {
866 *pp_err_str = NULL;
868 result = NT_STATUS_UNSUCCESSFUL;
869 goto done;
873 if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
874 acb &= (~ACB_DISABLED);
875 if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
876 ret = asprintf(pp_err_str,
877 "Failed to unset 'disabled' flag for "
878 "user %s.\n", user_name);
879 if (ret < 0) {
880 *pp_err_str = NULL;
882 result = NT_STATUS_UNSUCCESSFUL;
883 goto done;
887 /* now commit changes if any */
888 result = pdb_update_sam_account(sam_pass);
889 if (!NT_STATUS_IS_OK(result)) {
890 ret = asprintf(pp_err_str,
891 "Failed to modify entry for user %s.\n",
892 user_name);
893 if (ret < 0) {
894 *pp_err_str = NULL;
896 goto done;
899 if (local_flags & LOCAL_ADD_USER) {
900 ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
901 } else if (local_flags & LOCAL_DISABLE_USER) {
902 ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
903 } else if (local_flags & LOCAL_ENABLE_USER) {
904 ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
905 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
906 ret = asprintf(pp_msg_str,
907 "User %s password set to none.\n", user_name);
910 if (ret < 0) {
911 *pp_msg_str = NULL;
914 result = NT_STATUS_OK;
916 done:
917 TALLOC_FREE(sam_pass);
918 return result;
921 /**********************************************************************
922 Marshall/unmarshall struct samu structs.
923 *********************************************************************/
925 #define SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
926 #define SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
927 #define SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
928 #define SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
929 /* nothing changed between V3 and V4 */
931 /*********************************************************************
932 *********************************************************************/
934 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8_t *buf, uint32_t buflen)
937 /* times are stored as 32bit integer
938 take care on system with 64bit wide time_t
939 --SSS */
940 uint32_t logon_time,
941 logoff_time,
942 kickoff_time,
943 pass_last_set_time,
944 pass_can_change_time,
945 pass_must_change_time;
946 char *username = NULL;
947 char *domain = NULL;
948 char *nt_username = NULL;
949 char *dir_drive = NULL;
950 char *unknown_str = NULL;
951 char *munged_dial = NULL;
952 char *fullname = NULL;
953 char *homedir = NULL;
954 char *logon_script = NULL;
955 char *profile_path = NULL;
956 char *acct_desc = NULL;
957 char *workstations = NULL;
958 uint32_t username_len, domain_len, nt_username_len,
959 dir_drive_len, unknown_str_len, munged_dial_len,
960 fullname_len, homedir_len, logon_script_len,
961 profile_path_len, acct_desc_len, workstations_len;
963 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
964 uint16_t acct_ctrl, logon_divs;
965 uint16_t bad_password_count, logon_count;
966 uint8_t *hours = NULL;
967 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
968 uint32_t len = 0;
969 uint32_t lm_pw_len, nt_pw_len, hourslen;
970 bool ret = True;
972 if(sampass == NULL || buf == NULL) {
973 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
974 return False;
977 /* SAMU_BUFFER_FORMAT_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
979 /* unpack the buffer into variables */
980 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
981 &logon_time, /* d */
982 &logoff_time, /* d */
983 &kickoff_time, /* d */
984 &pass_last_set_time, /* d */
985 &pass_can_change_time, /* d */
986 &pass_must_change_time, /* d */
987 &username_len, &username, /* B */
988 &domain_len, &domain, /* B */
989 &nt_username_len, &nt_username, /* B */
990 &fullname_len, &fullname, /* B */
991 &homedir_len, &homedir, /* B */
992 &dir_drive_len, &dir_drive, /* B */
993 &logon_script_len, &logon_script, /* B */
994 &profile_path_len, &profile_path, /* B */
995 &acct_desc_len, &acct_desc, /* B */
996 &workstations_len, &workstations, /* B */
997 &unknown_str_len, &unknown_str, /* B */
998 &munged_dial_len, &munged_dial, /* B */
999 &user_rid, /* d */
1000 &group_rid, /* d */
1001 &lm_pw_len, &lm_pw_ptr, /* B */
1002 &nt_pw_len, &nt_pw_ptr, /* B */
1003 &acct_ctrl, /* w */
1004 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
1005 &logon_divs, /* w */
1006 &hours_len, /* d */
1007 &hourslen, &hours, /* B */
1008 &bad_password_count, /* w */
1009 &logon_count, /* w */
1010 &unknown_6); /* d */
1012 if (len == (uint32_t) -1) {
1013 ret = False;
1014 goto done;
1017 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1018 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1019 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1020 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1021 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1022 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1024 pdb_set_username(sampass, username, PDB_SET);
1025 pdb_set_domain(sampass, domain, PDB_SET);
1026 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1027 pdb_set_fullname(sampass, fullname, PDB_SET);
1029 if (homedir) {
1030 pdb_set_homedir(sampass, homedir, PDB_SET);
1032 else {
1033 pdb_set_homedir(sampass,
1034 talloc_sub_basic(sampass, username, domain,
1035 lp_logon_home()),
1036 PDB_DEFAULT);
1039 if (dir_drive)
1040 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1041 else {
1042 pdb_set_dir_drive(sampass,
1043 talloc_sub_basic(sampass, username, domain,
1044 lp_logon_drive()),
1045 PDB_DEFAULT);
1048 if (logon_script)
1049 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1050 else {
1051 pdb_set_logon_script(sampass,
1052 talloc_sub_basic(sampass, username, domain,
1053 lp_logon_script()),
1054 PDB_DEFAULT);
1057 if (profile_path) {
1058 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1059 } else {
1060 pdb_set_profile_path(sampass,
1061 talloc_sub_basic(sampass, username, domain,
1062 lp_logon_path()),
1063 PDB_DEFAULT);
1066 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1067 pdb_set_workstations(sampass, workstations, PDB_SET);
1068 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1070 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1071 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1072 ret = False;
1073 goto done;
1077 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1078 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1079 ret = False;
1080 goto done;
1084 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1085 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1086 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1087 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1088 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1089 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1090 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1091 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1092 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1093 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1095 done:
1097 SAFE_FREE(username);
1098 SAFE_FREE(domain);
1099 SAFE_FREE(nt_username);
1100 SAFE_FREE(fullname);
1101 SAFE_FREE(homedir);
1102 SAFE_FREE(dir_drive);
1103 SAFE_FREE(logon_script);
1104 SAFE_FREE(profile_path);
1105 SAFE_FREE(acct_desc);
1106 SAFE_FREE(workstations);
1107 SAFE_FREE(munged_dial);
1108 SAFE_FREE(unknown_str);
1109 SAFE_FREE(lm_pw_ptr);
1110 SAFE_FREE(nt_pw_ptr);
1111 SAFE_FREE(hours);
1113 return ret;
1116 /*********************************************************************
1117 *********************************************************************/
1119 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1122 /* times are stored as 32bit integer
1123 take care on system with 64bit wide time_t
1124 --SSS */
1125 uint32_t logon_time,
1126 logoff_time,
1127 kickoff_time,
1128 bad_password_time,
1129 pass_last_set_time,
1130 pass_can_change_time,
1131 pass_must_change_time;
1132 char *username = NULL;
1133 char *domain = NULL;
1134 char *nt_username = NULL;
1135 char *dir_drive = NULL;
1136 char *unknown_str = NULL;
1137 char *munged_dial = NULL;
1138 char *fullname = NULL;
1139 char *homedir = NULL;
1140 char *logon_script = NULL;
1141 char *profile_path = NULL;
1142 char *acct_desc = NULL;
1143 char *workstations = NULL;
1144 uint32_t username_len, domain_len, nt_username_len,
1145 dir_drive_len, unknown_str_len, munged_dial_len,
1146 fullname_len, homedir_len, logon_script_len,
1147 profile_path_len, acct_desc_len, workstations_len;
1149 uint32_t user_rid, group_rid, remove_me, hours_len, unknown_6;
1150 uint16_t acct_ctrl, logon_divs;
1151 uint16_t bad_password_count, logon_count;
1152 uint8_t *hours = NULL;
1153 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1154 uint32_t len = 0;
1155 uint32_t lm_pw_len, nt_pw_len, hourslen;
1156 bool ret = True;
1158 if(sampass == NULL || buf == NULL) {
1159 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1160 return False;
1163 /* SAMU_BUFFER_FORMAT_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1165 /* unpack the buffer into variables */
1166 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1167 &logon_time, /* d */
1168 &logoff_time, /* d */
1169 &kickoff_time, /* d */
1170 /* Change from V0 is addition of bad_password_time field. */
1171 &bad_password_time, /* d */
1172 &pass_last_set_time, /* d */
1173 &pass_can_change_time, /* d */
1174 &pass_must_change_time, /* d */
1175 &username_len, &username, /* B */
1176 &domain_len, &domain, /* B */
1177 &nt_username_len, &nt_username, /* B */
1178 &fullname_len, &fullname, /* B */
1179 &homedir_len, &homedir, /* B */
1180 &dir_drive_len, &dir_drive, /* B */
1181 &logon_script_len, &logon_script, /* B */
1182 &profile_path_len, &profile_path, /* B */
1183 &acct_desc_len, &acct_desc, /* B */
1184 &workstations_len, &workstations, /* B */
1185 &unknown_str_len, &unknown_str, /* B */
1186 &munged_dial_len, &munged_dial, /* B */
1187 &user_rid, /* d */
1188 &group_rid, /* d */
1189 &lm_pw_len, &lm_pw_ptr, /* B */
1190 &nt_pw_len, &nt_pw_ptr, /* B */
1191 &acct_ctrl, /* w */
1192 &remove_me, /* d */
1193 &logon_divs, /* w */
1194 &hours_len, /* d */
1195 &hourslen, &hours, /* B */
1196 &bad_password_count, /* w */
1197 &logon_count, /* w */
1198 &unknown_6); /* d */
1200 if (len == (uint32_t) -1) {
1201 ret = False;
1202 goto done;
1205 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1206 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1207 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1209 /* Change from V0 is addition of bad_password_time field. */
1210 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1211 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1212 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1213 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1215 pdb_set_username(sampass, username, PDB_SET);
1216 pdb_set_domain(sampass, domain, PDB_SET);
1217 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1218 pdb_set_fullname(sampass, fullname, PDB_SET);
1220 if (homedir) {
1221 pdb_set_homedir(sampass, homedir, PDB_SET);
1223 else {
1224 pdb_set_homedir(sampass,
1225 talloc_sub_basic(sampass, username, domain,
1226 lp_logon_home()),
1227 PDB_DEFAULT);
1230 if (dir_drive)
1231 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1232 else {
1233 pdb_set_dir_drive(sampass,
1234 talloc_sub_basic(sampass, username, domain,
1235 lp_logon_drive()),
1236 PDB_DEFAULT);
1239 if (logon_script)
1240 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1241 else {
1242 pdb_set_logon_script(sampass,
1243 talloc_sub_basic(sampass, username, domain,
1244 lp_logon_script()),
1245 PDB_DEFAULT);
1248 if (profile_path) {
1249 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1250 } else {
1251 pdb_set_profile_path(sampass,
1252 talloc_sub_basic(sampass, username, domain,
1253 lp_logon_path()),
1254 PDB_DEFAULT);
1257 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1258 pdb_set_workstations(sampass, workstations, PDB_SET);
1259 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1261 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1262 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1263 ret = False;
1264 goto done;
1268 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1269 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1270 ret = False;
1271 goto done;
1275 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1277 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1278 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1279 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1280 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1281 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1282 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1283 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1284 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1285 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1287 done:
1289 SAFE_FREE(username);
1290 SAFE_FREE(domain);
1291 SAFE_FREE(nt_username);
1292 SAFE_FREE(fullname);
1293 SAFE_FREE(homedir);
1294 SAFE_FREE(dir_drive);
1295 SAFE_FREE(logon_script);
1296 SAFE_FREE(profile_path);
1297 SAFE_FREE(acct_desc);
1298 SAFE_FREE(workstations);
1299 SAFE_FREE(munged_dial);
1300 SAFE_FREE(unknown_str);
1301 SAFE_FREE(lm_pw_ptr);
1302 SAFE_FREE(nt_pw_ptr);
1303 SAFE_FREE(hours);
1305 return ret;
1308 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1311 /* times are stored as 32bit integer
1312 take care on system with 64bit wide time_t
1313 --SSS */
1314 uint32_t logon_time,
1315 logoff_time,
1316 kickoff_time,
1317 bad_password_time,
1318 pass_last_set_time,
1319 pass_can_change_time,
1320 pass_must_change_time;
1321 char *username = NULL;
1322 char *domain = NULL;
1323 char *nt_username = NULL;
1324 char *dir_drive = NULL;
1325 char *unknown_str = NULL;
1326 char *munged_dial = NULL;
1327 char *fullname = NULL;
1328 char *homedir = NULL;
1329 char *logon_script = NULL;
1330 char *profile_path = NULL;
1331 char *acct_desc = NULL;
1332 char *workstations = NULL;
1333 uint32_t username_len, domain_len, nt_username_len,
1334 dir_drive_len, unknown_str_len, munged_dial_len,
1335 fullname_len, homedir_len, logon_script_len,
1336 profile_path_len, acct_desc_len, workstations_len;
1338 uint32_t user_rid, group_rid, hours_len, unknown_6;
1339 uint16_t acct_ctrl, logon_divs;
1340 uint16_t bad_password_count, logon_count;
1341 uint8_t *hours = NULL;
1342 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1343 uint32_t len = 0;
1344 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1345 uint32_t pwHistLen = 0;
1346 bool ret = True;
1347 fstring tmp_string;
1348 bool expand_explicit = lp_passdb_expand_explicit();
1350 if(sampass == NULL || buf == NULL) {
1351 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1352 return False;
1355 /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1357 /* unpack the buffer into variables */
1358 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1359 &logon_time, /* d */
1360 &logoff_time, /* d */
1361 &kickoff_time, /* d */
1362 &bad_password_time, /* d */
1363 &pass_last_set_time, /* d */
1364 &pass_can_change_time, /* d */
1365 &pass_must_change_time, /* d */
1366 &username_len, &username, /* B */
1367 &domain_len, &domain, /* B */
1368 &nt_username_len, &nt_username, /* B */
1369 &fullname_len, &fullname, /* B */
1370 &homedir_len, &homedir, /* B */
1371 &dir_drive_len, &dir_drive, /* B */
1372 &logon_script_len, &logon_script, /* B */
1373 &profile_path_len, &profile_path, /* B */
1374 &acct_desc_len, &acct_desc, /* B */
1375 &workstations_len, &workstations, /* B */
1376 &unknown_str_len, &unknown_str, /* B */
1377 &munged_dial_len, &munged_dial, /* B */
1378 &user_rid, /* d */
1379 &group_rid, /* d */
1380 &lm_pw_len, &lm_pw_ptr, /* B */
1381 &nt_pw_len, &nt_pw_ptr, /* B */
1382 /* Change from V1 is addition of password history field. */
1383 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1384 &acct_ctrl, /* w */
1385 /* Also "remove_me" field was removed. */
1386 &logon_divs, /* w */
1387 &hours_len, /* d */
1388 &hourslen, &hours, /* B */
1389 &bad_password_count, /* w */
1390 &logon_count, /* w */
1391 &unknown_6); /* d */
1393 if (len == (uint32_t) -1) {
1394 ret = False;
1395 goto done;
1398 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1399 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1400 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1401 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1402 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1403 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1404 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1406 pdb_set_username(sampass, username, PDB_SET);
1407 pdb_set_domain(sampass, domain, PDB_SET);
1408 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1409 pdb_set_fullname(sampass, fullname, PDB_SET);
1411 if (homedir) {
1412 fstrcpy( tmp_string, homedir );
1413 if (expand_explicit) {
1414 standard_sub_basic( username, domain, tmp_string,
1415 sizeof(tmp_string) );
1417 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1419 else {
1420 pdb_set_homedir(sampass,
1421 talloc_sub_basic(sampass, username, domain,
1422 lp_logon_home()),
1423 PDB_DEFAULT);
1426 if (dir_drive)
1427 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1428 else
1429 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1431 if (logon_script) {
1432 fstrcpy( tmp_string, logon_script );
1433 if (expand_explicit) {
1434 standard_sub_basic( username, domain, tmp_string,
1435 sizeof(tmp_string) );
1437 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1439 else {
1440 pdb_set_logon_script(sampass,
1441 talloc_sub_basic(sampass, username, domain,
1442 lp_logon_script()),
1443 PDB_DEFAULT);
1446 if (profile_path) {
1447 fstrcpy( tmp_string, profile_path );
1448 if (expand_explicit) {
1449 standard_sub_basic( username, domain, tmp_string,
1450 sizeof(tmp_string) );
1452 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1454 else {
1455 pdb_set_profile_path(sampass,
1456 talloc_sub_basic(sampass, username, domain,
1457 lp_logon_path()),
1458 PDB_DEFAULT);
1461 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1462 pdb_set_workstations(sampass, workstations, PDB_SET);
1463 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1465 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1466 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1467 ret = False;
1468 goto done;
1472 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1473 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1474 ret = False;
1475 goto done;
1479 /* Change from V1 is addition of password history field. */
1480 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1481 if (pwHistLen) {
1482 uint8_t *pw_hist = SMB_MALLOC_ARRAY(uint8_t, pwHistLen * PW_HISTORY_ENTRY_LEN);
1483 if (!pw_hist) {
1484 ret = False;
1485 goto done;
1487 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1488 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1489 int i;
1490 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1491 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1492 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1493 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1494 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1495 PW_HISTORY_ENTRY_LEN);
1498 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1499 SAFE_FREE(pw_hist);
1500 ret = False;
1501 goto done;
1503 SAFE_FREE(pw_hist);
1504 } else {
1505 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1508 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1509 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1510 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1511 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1512 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1513 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1514 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1515 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1516 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1518 done:
1520 SAFE_FREE(username);
1521 SAFE_FREE(domain);
1522 SAFE_FREE(nt_username);
1523 SAFE_FREE(fullname);
1524 SAFE_FREE(homedir);
1525 SAFE_FREE(dir_drive);
1526 SAFE_FREE(logon_script);
1527 SAFE_FREE(profile_path);
1528 SAFE_FREE(acct_desc);
1529 SAFE_FREE(workstations);
1530 SAFE_FREE(munged_dial);
1531 SAFE_FREE(unknown_str);
1532 SAFE_FREE(lm_pw_ptr);
1533 SAFE_FREE(nt_pw_ptr);
1534 SAFE_FREE(nt_pw_hist_ptr);
1535 SAFE_FREE(hours);
1537 return ret;
1540 /*********************************************************************
1541 *********************************************************************/
1543 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8_t *buf, uint32_t buflen)
1546 /* times are stored as 32bit integer
1547 take care on system with 64bit wide time_t
1548 --SSS */
1549 uint32_t logon_time,
1550 logoff_time,
1551 kickoff_time,
1552 bad_password_time,
1553 pass_last_set_time,
1554 pass_can_change_time,
1555 pass_must_change_time;
1556 char *username = NULL;
1557 char *domain = NULL;
1558 char *nt_username = NULL;
1559 char *dir_drive = NULL;
1560 char *comment = NULL;
1561 char *munged_dial = NULL;
1562 char *fullname = NULL;
1563 char *homedir = NULL;
1564 char *logon_script = NULL;
1565 char *profile_path = NULL;
1566 char *acct_desc = NULL;
1567 char *workstations = NULL;
1568 uint32_t username_len, domain_len, nt_username_len,
1569 dir_drive_len, comment_len, munged_dial_len,
1570 fullname_len, homedir_len, logon_script_len,
1571 profile_path_len, acct_desc_len, workstations_len;
1573 uint32_t user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1574 uint16_t logon_divs;
1575 uint16_t bad_password_count, logon_count;
1576 uint8_t *hours = NULL;
1577 uint8_t *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1578 uint32_t len = 0;
1579 uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1580 uint32_t pwHistLen = 0;
1581 bool ret = True;
1582 fstring tmp_string;
1583 bool expand_explicit = lp_passdb_expand_explicit();
1585 if(sampass == NULL || buf == NULL) {
1586 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1587 return False;
1590 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1592 /* unpack the buffer into variables */
1593 len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1594 &logon_time, /* d */
1595 &logoff_time, /* d */
1596 &kickoff_time, /* d */
1597 &bad_password_time, /* d */
1598 &pass_last_set_time, /* d */
1599 &pass_can_change_time, /* d */
1600 &pass_must_change_time, /* d */
1601 &username_len, &username, /* B */
1602 &domain_len, &domain, /* B */
1603 &nt_username_len, &nt_username, /* B */
1604 &fullname_len, &fullname, /* B */
1605 &homedir_len, &homedir, /* B */
1606 &dir_drive_len, &dir_drive, /* B */
1607 &logon_script_len, &logon_script, /* B */
1608 &profile_path_len, &profile_path, /* B */
1609 &acct_desc_len, &acct_desc, /* B */
1610 &workstations_len, &workstations, /* B */
1611 &comment_len, &comment, /* B */
1612 &munged_dial_len, &munged_dial, /* B */
1613 &user_rid, /* d */
1614 &group_rid, /* d */
1615 &lm_pw_len, &lm_pw_ptr, /* B */
1616 &nt_pw_len, &nt_pw_ptr, /* B */
1617 /* Change from V1 is addition of password history field. */
1618 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
1619 /* Change from V2 is the uint32_t acb_mask */
1620 &acct_ctrl, /* d */
1621 /* Also "remove_me" field was removed. */
1622 &logon_divs, /* w */
1623 &hours_len, /* d */
1624 &hourslen, &hours, /* B */
1625 &bad_password_count, /* w */
1626 &logon_count, /* w */
1627 &unknown_6); /* d */
1629 if (len == (uint32_t) -1) {
1630 ret = False;
1631 goto done;
1634 pdb_set_logon_time(sampass, convert_uint32_t_to_time_t(logon_time), PDB_SET);
1635 pdb_set_logoff_time(sampass, convert_uint32_t_to_time_t(logoff_time), PDB_SET);
1636 pdb_set_kickoff_time(sampass, convert_uint32_t_to_time_t(kickoff_time), PDB_SET);
1637 pdb_set_bad_password_time(sampass, convert_uint32_t_to_time_t(bad_password_time), PDB_SET);
1638 pdb_set_pass_can_change_time(sampass, convert_uint32_t_to_time_t(pass_can_change_time), PDB_SET);
1639 pdb_set_pass_must_change_time(sampass, convert_uint32_t_to_time_t(pass_must_change_time), PDB_SET);
1640 pdb_set_pass_last_set_time(sampass, convert_uint32_t_to_time_t(pass_last_set_time), PDB_SET);
1642 pdb_set_username(sampass, username, PDB_SET);
1643 pdb_set_domain(sampass, domain, PDB_SET);
1644 pdb_set_nt_username(sampass, nt_username, PDB_SET);
1645 pdb_set_fullname(sampass, fullname, PDB_SET);
1647 if (homedir) {
1648 fstrcpy( tmp_string, homedir );
1649 if (expand_explicit) {
1650 standard_sub_basic( username, domain, tmp_string,
1651 sizeof(tmp_string) );
1653 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1655 else {
1656 pdb_set_homedir(sampass,
1657 talloc_sub_basic(sampass, username, domain,
1658 lp_logon_home()),
1659 PDB_DEFAULT);
1662 if (dir_drive)
1663 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1664 else
1665 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1667 if (logon_script) {
1668 fstrcpy( tmp_string, logon_script );
1669 if (expand_explicit) {
1670 standard_sub_basic( username, domain, tmp_string,
1671 sizeof(tmp_string) );
1673 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1675 else {
1676 pdb_set_logon_script(sampass,
1677 talloc_sub_basic(sampass, username, domain,
1678 lp_logon_script()),
1679 PDB_DEFAULT);
1682 if (profile_path) {
1683 fstrcpy( tmp_string, profile_path );
1684 if (expand_explicit) {
1685 standard_sub_basic( username, domain, tmp_string,
1686 sizeof(tmp_string) );
1688 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1690 else {
1691 pdb_set_profile_path(sampass,
1692 talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1693 PDB_DEFAULT);
1696 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1697 pdb_set_comment(sampass, comment, PDB_SET);
1698 pdb_set_workstations(sampass, workstations, PDB_SET);
1699 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1701 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1702 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1703 ret = False;
1704 goto done;
1708 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1709 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1710 ret = False;
1711 goto done;
1715 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1716 if (pwHistLen) {
1717 uint8_t *pw_hist = (uint8_t *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1718 if (!pw_hist) {
1719 ret = False;
1720 goto done;
1722 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1723 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1724 int i;
1725 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1726 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1727 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1728 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1729 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1730 PW_HISTORY_ENTRY_LEN);
1733 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1734 SAFE_FREE(pw_hist);
1735 ret = False;
1736 goto done;
1738 SAFE_FREE(pw_hist);
1739 } else {
1740 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1743 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1744 pdb_set_hours_len(sampass, hours_len, PDB_SET);
1745 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1746 pdb_set_logon_count(sampass, logon_count, PDB_SET);
1747 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1748 /* Change from V2 is the uint32_t acct_ctrl */
1749 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1750 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1751 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1753 done:
1755 SAFE_FREE(username);
1756 SAFE_FREE(domain);
1757 SAFE_FREE(nt_username);
1758 SAFE_FREE(fullname);
1759 SAFE_FREE(homedir);
1760 SAFE_FREE(dir_drive);
1761 SAFE_FREE(logon_script);
1762 SAFE_FREE(profile_path);
1763 SAFE_FREE(acct_desc);
1764 SAFE_FREE(workstations);
1765 SAFE_FREE(munged_dial);
1766 SAFE_FREE(comment);
1767 SAFE_FREE(lm_pw_ptr);
1768 SAFE_FREE(nt_pw_ptr);
1769 SAFE_FREE(nt_pw_hist_ptr);
1770 SAFE_FREE(hours);
1772 return ret;
1775 /*********************************************************************
1776 *********************************************************************/
1778 static uint32_t init_buffer_from_samu_v3 (uint8_t **buf, struct samu *sampass, bool size_only)
1780 size_t len, buflen;
1782 /* times are stored as 32bit integer
1783 take care on system with 64bit wide time_t
1784 --SSS */
1785 uint32_t logon_time,
1786 logoff_time,
1787 kickoff_time,
1788 bad_password_time,
1789 pass_last_set_time,
1790 pass_can_change_time,
1791 pass_must_change_time;
1793 uint32_t user_rid, group_rid;
1795 const char *username;
1796 const char *domain;
1797 const char *nt_username;
1798 const char *dir_drive;
1799 const char *comment;
1800 const char *munged_dial;
1801 const char *fullname;
1802 const char *homedir;
1803 const char *logon_script;
1804 const char *profile_path;
1805 const char *acct_desc;
1806 const char *workstations;
1807 uint32_t username_len, domain_len, nt_username_len,
1808 dir_drive_len, comment_len, munged_dial_len,
1809 fullname_len, homedir_len, logon_script_len,
1810 profile_path_len, acct_desc_len, workstations_len;
1812 const uint8_t *lm_pw;
1813 const uint8_t *nt_pw;
1814 const uint8_t *nt_pw_hist;
1815 uint32_t lm_pw_len = 16;
1816 uint32_t nt_pw_len = 16;
1817 uint32_t nt_pw_hist_len;
1818 uint32_t pwHistLen = 0;
1820 *buf = NULL;
1821 buflen = 0;
1823 logon_time = convert_time_t_to_uint32_t(pdb_get_logon_time(sampass));
1824 logoff_time = convert_time_t_to_uint32_t(pdb_get_logoff_time(sampass));
1825 kickoff_time = convert_time_t_to_uint32_t(pdb_get_kickoff_time(sampass));
1826 bad_password_time = convert_time_t_to_uint32_t(pdb_get_bad_password_time(sampass));
1827 pass_can_change_time = convert_time_t_to_uint32_t(pdb_get_pass_can_change_time_noncalc(sampass));
1828 pass_must_change_time = convert_time_t_to_uint32_t(pdb_get_pass_must_change_time(sampass));
1829 pass_last_set_time = convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sampass));
1831 user_rid = pdb_get_user_rid(sampass);
1832 group_rid = pdb_get_group_rid(sampass);
1834 username = pdb_get_username(sampass);
1835 if (username) {
1836 username_len = strlen(username) +1;
1837 } else {
1838 username_len = 0;
1841 domain = pdb_get_domain(sampass);
1842 if (domain) {
1843 domain_len = strlen(domain) +1;
1844 } else {
1845 domain_len = 0;
1848 nt_username = pdb_get_nt_username(sampass);
1849 if (nt_username) {
1850 nt_username_len = strlen(nt_username) +1;
1851 } else {
1852 nt_username_len = 0;
1855 fullname = pdb_get_fullname(sampass);
1856 if (fullname) {
1857 fullname_len = strlen(fullname) +1;
1858 } else {
1859 fullname_len = 0;
1863 * Only updates fields which have been set (not defaults from smb.conf)
1866 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1867 dir_drive = pdb_get_dir_drive(sampass);
1868 } else {
1869 dir_drive = NULL;
1871 if (dir_drive) {
1872 dir_drive_len = strlen(dir_drive) +1;
1873 } else {
1874 dir_drive_len = 0;
1877 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1878 homedir = pdb_get_homedir(sampass);
1879 } else {
1880 homedir = NULL;
1882 if (homedir) {
1883 homedir_len = strlen(homedir) +1;
1884 } else {
1885 homedir_len = 0;
1888 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1889 logon_script = pdb_get_logon_script(sampass);
1890 } else {
1891 logon_script = NULL;
1893 if (logon_script) {
1894 logon_script_len = strlen(logon_script) +1;
1895 } else {
1896 logon_script_len = 0;
1899 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1900 profile_path = pdb_get_profile_path(sampass);
1901 } else {
1902 profile_path = NULL;
1904 if (profile_path) {
1905 profile_path_len = strlen(profile_path) +1;
1906 } else {
1907 profile_path_len = 0;
1910 lm_pw = pdb_get_lanman_passwd(sampass);
1911 if (!lm_pw) {
1912 lm_pw_len = 0;
1915 nt_pw = pdb_get_nt_passwd(sampass);
1916 if (!nt_pw) {
1917 nt_pw_len = 0;
1920 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1921 nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
1922 if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1923 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1924 } else {
1925 nt_pw_hist_len = 0;
1928 acct_desc = pdb_get_acct_desc(sampass);
1929 if (acct_desc) {
1930 acct_desc_len = strlen(acct_desc) +1;
1931 } else {
1932 acct_desc_len = 0;
1935 workstations = pdb_get_workstations(sampass);
1936 if (workstations) {
1937 workstations_len = strlen(workstations) +1;
1938 } else {
1939 workstations_len = 0;
1942 comment = pdb_get_comment(sampass);
1943 if (comment) {
1944 comment_len = strlen(comment) +1;
1945 } else {
1946 comment_len = 0;
1949 munged_dial = pdb_get_munged_dial(sampass);
1950 if (munged_dial) {
1951 munged_dial_len = strlen(munged_dial) +1;
1952 } else {
1953 munged_dial_len = 0;
1956 /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1958 /* one time to get the size needed */
1959 len = tdb_pack(NULL, 0, SAMU_BUFFER_FORMAT_V3,
1960 logon_time, /* d */
1961 logoff_time, /* d */
1962 kickoff_time, /* d */
1963 bad_password_time, /* d */
1964 pass_last_set_time, /* d */
1965 pass_can_change_time, /* d */
1966 pass_must_change_time, /* d */
1967 username_len, username, /* B */
1968 domain_len, domain, /* B */
1969 nt_username_len, nt_username, /* B */
1970 fullname_len, fullname, /* B */
1971 homedir_len, homedir, /* B */
1972 dir_drive_len, dir_drive, /* B */
1973 logon_script_len, logon_script, /* B */
1974 profile_path_len, profile_path, /* B */
1975 acct_desc_len, acct_desc, /* B */
1976 workstations_len, workstations, /* B */
1977 comment_len, comment, /* B */
1978 munged_dial_len, munged_dial, /* B */
1979 user_rid, /* d */
1980 group_rid, /* d */
1981 lm_pw_len, lm_pw, /* B */
1982 nt_pw_len, nt_pw, /* B */
1983 nt_pw_hist_len, nt_pw_hist, /* B */
1984 pdb_get_acct_ctrl(sampass), /* d */
1985 pdb_get_logon_divs(sampass), /* w */
1986 pdb_get_hours_len(sampass), /* d */
1987 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
1988 pdb_get_bad_password_count(sampass), /* w */
1989 pdb_get_logon_count(sampass), /* w */
1990 pdb_get_unknown_6(sampass)); /* d */
1992 if (size_only) {
1993 return buflen;
1996 /* malloc the space needed */
1997 if ( (*buf=(uint8_t*)SMB_MALLOC(len)) == NULL) {
1998 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1999 return (-1);
2002 /* now for the real call to tdb_pack() */
2003 buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3,
2004 logon_time, /* d */
2005 logoff_time, /* d */
2006 kickoff_time, /* d */
2007 bad_password_time, /* d */
2008 pass_last_set_time, /* d */
2009 pass_can_change_time, /* d */
2010 pass_must_change_time, /* d */
2011 username_len, username, /* B */
2012 domain_len, domain, /* B */
2013 nt_username_len, nt_username, /* B */
2014 fullname_len, fullname, /* B */
2015 homedir_len, homedir, /* B */
2016 dir_drive_len, dir_drive, /* B */
2017 logon_script_len, logon_script, /* B */
2018 profile_path_len, profile_path, /* B */
2019 acct_desc_len, acct_desc, /* B */
2020 workstations_len, workstations, /* B */
2021 comment_len, comment, /* B */
2022 munged_dial_len, munged_dial, /* B */
2023 user_rid, /* d */
2024 group_rid, /* d */
2025 lm_pw_len, lm_pw, /* B */
2026 nt_pw_len, nt_pw, /* B */
2027 nt_pw_hist_len, nt_pw_hist, /* B */
2028 pdb_get_acct_ctrl(sampass), /* d */
2029 pdb_get_logon_divs(sampass), /* w */
2030 pdb_get_hours_len(sampass), /* d */
2031 MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
2032 pdb_get_bad_password_count(sampass), /* w */
2033 pdb_get_logon_count(sampass), /* w */
2034 pdb_get_unknown_6(sampass)); /* d */
2036 /* check to make sure we got it correct */
2037 if (buflen != len) {
2038 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2039 (unsigned long)buflen, (unsigned long)len));
2040 /* error */
2041 SAFE_FREE (*buf);
2042 return (-1);
2045 return (buflen);
2048 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8_t *buf, uint32_t buflen)
2050 /* nothing changed between V3 and V4 */
2051 return init_samu_from_buffer_v3(sampass, buf, buflen);
2054 static uint32_t init_buffer_from_samu_v4(uint8_t **buf, struct samu *sampass, bool size_only)
2056 /* nothing changed between V3 and V4 */
2057 return init_buffer_from_samu_v3(buf, sampass, size_only);
2060 /**********************************************************************
2061 Intialize a struct samu struct from a BYTE buffer of size len
2062 *********************************************************************/
2064 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2065 uint8_t *buf, uint32_t buflen)
2067 switch (level) {
2068 case SAMU_BUFFER_V0:
2069 return init_samu_from_buffer_v0(sampass, buf, buflen);
2070 case SAMU_BUFFER_V1:
2071 return init_samu_from_buffer_v1(sampass, buf, buflen);
2072 case SAMU_BUFFER_V2:
2073 return init_samu_from_buffer_v2(sampass, buf, buflen);
2074 case SAMU_BUFFER_V3:
2075 return init_samu_from_buffer_v3(sampass, buf, buflen);
2076 case SAMU_BUFFER_V4:
2077 return init_samu_from_buffer_v4(sampass, buf, buflen);
2080 return false;
2083 /**********************************************************************
2084 Intialize a BYTE buffer from a struct samu struct
2085 *********************************************************************/
2087 uint32_t init_buffer_from_samu (uint8_t **buf, struct samu *sampass, bool size_only)
2089 return init_buffer_from_samu_v4(buf, sampass, size_only);
2092 /*********************************************************************
2093 *********************************************************************/
2095 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2097 uint8_t *buf = NULL;
2098 int len;
2100 len = init_buffer_from_samu(&buf, src, False);
2101 if (len == -1 || !buf) {
2102 SAFE_FREE(buf);
2103 return False;
2106 if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2107 free(buf);
2108 return False;
2111 dst->methods = src->methods;
2113 if ( src->unix_pw ) {
2114 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2115 if (!dst->unix_pw) {
2116 free(buf);
2117 return False;
2121 if (src->group_sid) {
2122 pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2125 free(buf);
2126 return True;
2129 /*********************************************************************
2130 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2131 *********************************************************************/
2133 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2135 time_t LastBadPassword;
2136 uint16_t BadPasswordCount;
2137 uint32_t resettime;
2138 bool res;
2140 BadPasswordCount = pdb_get_bad_password_count(sampass);
2141 if (!BadPasswordCount) {
2142 DEBUG(9, ("No bad password attempts.\n"));
2143 return True;
2146 become_root();
2147 res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2148 unbecome_root();
2150 if (!res) {
2151 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2152 return False;
2155 /* First, check if there is a reset time to compare */
2156 if ((resettime == (uint32_t) -1) || (resettime == 0)) {
2157 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2158 return True;
2161 LastBadPassword = pdb_get_bad_password_time(sampass);
2162 DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2163 (uint32_t) LastBadPassword, resettime, (uint32_t)time(NULL)));
2164 if (time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(resettime)*60)){
2165 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2166 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2167 if (updated) {
2168 *updated = True;
2172 return True;
2175 /*********************************************************************
2176 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2177 *********************************************************************/
2179 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2181 uint32_t duration;
2182 time_t LastBadPassword;
2183 bool res;
2185 if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2186 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2187 pdb_get_username(sampass)));
2188 return True;
2191 become_root();
2192 res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2193 unbecome_root();
2195 if (!res) {
2196 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2197 return False;
2200 /* First, check if there is a duration to compare */
2201 if ((duration == (uint32_t) -1) || (duration == 0)) {
2202 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2203 return True;
2206 LastBadPassword = pdb_get_bad_password_time(sampass);
2207 DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2208 pdb_get_username(sampass), (uint32_t)LastBadPassword, duration*60, (uint32_t)time(NULL)));
2210 if (LastBadPassword == (time_t)0) {
2211 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2212 "administratively locked out with no bad password "
2213 "time. Leaving locked out.\n",
2214 pdb_get_username(sampass) ));
2215 return True;
2218 if ((time(NULL) > (LastBadPassword + convert_uint32_t_to_time_t(duration) * 60))) {
2219 pdb_set_acct_ctrl(sampass,
2220 pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2221 PDB_CHANGED);
2222 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2223 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2224 if (updated) {
2225 *updated = True;
2229 return True;
2232 /*********************************************************************
2233 Increment the bad_password_count
2234 *********************************************************************/
2236 bool pdb_increment_bad_password_count(struct samu *sampass)
2238 uint32_t account_policy_lockout;
2239 bool autolock_updated = False, badpw_updated = False;
2240 bool ret;
2242 /* Retrieve the account lockout policy */
2243 become_root();
2244 ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2245 unbecome_root();
2246 if ( !ret ) {
2247 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2248 return False;
2251 /* If there is no policy, we don't need to continue checking */
2252 if (!account_policy_lockout) {
2253 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2254 return True;
2257 /* Check if the autolock needs to be cleared */
2258 if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2259 return False;
2261 /* Check if the badpw count needs to be reset */
2262 if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2263 return False;
2266 Ok, now we can assume that any resetting that needs to be
2267 done has been done, and just get on with incrementing
2268 and autolocking if necessary
2271 pdb_set_bad_password_count(sampass,
2272 pdb_get_bad_password_count(sampass)+1,
2273 PDB_CHANGED);
2274 pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2277 if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2278 return True;
2280 if (!pdb_set_acct_ctrl(sampass,
2281 pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2282 PDB_CHANGED)) {
2283 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2284 return False;
2287 return True;
2290 bool is_dc_trusted_domain_situation(const char *domain_name)
2292 return IS_DC && !strequal(domain_name, lp_workgroup());
2295 /*******************************************************************
2296 Wrapper around retrieving the clear text trust account password.
2297 appropriate account name is stored in account_name.
2298 Caller must free password, but not account_name.
2299 *******************************************************************/
2301 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2302 const char **account_name,
2303 enum netr_SchannelType *channel)
2305 char *pwd;
2306 time_t last_set_time;
2308 /* if we are a DC and this is not our domain, then lookup an account
2309 * for the domain trust */
2311 if (is_dc_trusted_domain_situation(domain)) {
2312 if (!lp_allow_trusted_domains()) {
2313 return false;
2316 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2317 &last_set_time))
2319 DEBUG(0, ("get_trust_pw: could not fetch trust "
2320 "account password for trusted domain %s\n",
2321 domain));
2322 return false;
2325 if (channel != NULL) {
2326 *channel = SEC_CHAN_DOMAIN;
2329 if (account_name != NULL) {
2330 *account_name = lp_workgroup();
2333 return true;
2337 * Since we can only be member of one single domain, we are now
2338 * in a member situation:
2340 * - Either we are a DC (selfjoined) and the domain is our
2341 * own domain.
2342 * - Or we are on a member and the domain is our own or some
2343 * other (potentially trusted) domain.
2345 * In both cases, we can only get the machine account password
2346 * for our own domain to connect to our own dc. (For a member,
2347 * request to trusted domains are performed through our dc.)
2349 * So we simply use our own domain name to retrieve the
2350 * machine account passowrd and ignore the request domain here.
2353 pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2355 if (pwd != NULL) {
2356 *ret_pwd = pwd;
2357 if (account_name != NULL) {
2358 *account_name = lp_netbios_name();
2361 return true;
2364 DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2365 "account password for domain %s\n", domain));
2366 return false;
2369 /*******************************************************************
2370 Wrapper around retrieving the trust account password.
2371 appropriate account name is stored in account_name.
2372 *******************************************************************/
2374 bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
2375 const char **account_name,
2376 enum netr_SchannelType *channel)
2378 char *pwd = NULL;
2379 time_t last_set_time;
2381 if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2382 E_md4hash(pwd, ret_pwd);
2383 SAFE_FREE(pwd);
2384 return true;
2385 } else if (is_dc_trusted_domain_situation(domain)) {
2386 return false;
2389 /* as a fallback, try to get the hashed pwd directly from the tdb... */
2391 if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2392 &last_set_time,
2393 channel))
2395 if (account_name != NULL) {
2396 *account_name = lp_netbios_name();
2399 return true;
2402 DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2403 "password for domain %s\n", domain));
2404 return False;