return lp_workgroup();
}
-/******************************************************************
- get the default domain/netbios name to be used when dealing
- with our passdb list of accounts
-******************************************************************/
-
-const char *get_global_sam_name(void)
-{
- if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) {
- return lp_workgroup();
- }
- return global_myname();
-}
-
/************************************************************
Fill the SAM_ACCOUNT with default values.
***********************************************************/
user->private.logoff_time =
user->private.kickoff_time =
user->private.pass_must_change_time = get_time_t_max();
- user->private.unknown_3 = 0x00ffffff; /* don't know */
+ user->private.fields_present = 0x00ffffff;
user->private.logon_divs = 168; /* hours per week */
user->private.hours_len = 21; /* 21 times 8 bits = 168 */
memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */
- user->private.unknown_5 = 0x00000000; /* don't know */
+ user->private.bad_password_count = 0;
+ user->private.logon_count = 0;
user->private.unknown_6 = 0x000004ec; /* don't know */
/* Some parts of samba strlen their pdb_get...() returns,
user->private.plaintext_pw = NULL;
+ /*
+ Unless we know otherwise have a Account Control Bit
+ value of 'normal user'. This helps User Manager, which
+ asks for a filtered list of users.
+ */
+
+ user->private.acct_ctrl = ACB_NORMAL;
}
static void destroy_pdb_talloc(SAM_ACCOUNT **user)
/**********************************************************************
- Alloc memory and initialises a struct sam_passwd on supplied mem_ctx.
+ Allocates memory and initialises a struct sam_passwd on supplied mem_ctx.
***********************************************************************/
NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user)
return NT_STATUS_UNSUCCESSFUL;
}
- *user=(SAM_ACCOUNT *)talloc(mem_ctx, sizeof(SAM_ACCOUNT));
+ *user=TALLOC_P(mem_ctx, SAM_ACCOUNT);
if (*user==NULL) {
DEBUG(0,("pdb_init_sam_talloc: error while allocating memory\n"));
/*************************************************************
- Alloc memory and initialises a struct sam_passwd.
+ Allocates memory and initialises a struct sam_passwd.
************************************************************/
NTSTATUS pdb_init_sam(SAM_ACCOUNT **user)
return NT_STATUS_OK;
}
+/**************************************************************************
+ * This function will take care of all the steps needed to correctly
+ * allocate and set the user SID, please do use this function to create new
+ * users, messing with SIDs is not good.
+ *
+ * account_data must be provided initialized, pwd may be null.
+ * SSS
+ ***************************************************************************/
+
+static NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd)
+{
+ const char *guest_account = lp_guestaccount();
+ GROUP_MAP map;
+ BOOL ret;
+
+ if (!account_data || !pwd) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* this is a hack this thing should not be set
+ this way --SSS */
+ if (!(guest_account && *guest_account)) {
+ DEBUG(1, ("NULL guest account!?!?\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ /* Ensure this *must* be set right */
+ if (strcmp(pwd->pw_name, guest_account) == 0) {
+ if (!pdb_set_user_sid_from_rid(account_data, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (!pdb_set_group_sid_from_rid(account_data, DOMAIN_GROUP_RID_GUESTS, PDB_DEFAULT)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ return NT_STATUS_OK;
+ }
+ }
+
+ if (!pdb_set_user_sid_from_rid(account_data, algorithmic_pdb_uid_to_user_rid(pwd->pw_uid), PDB_SET)) {
+ DEBUG(0,("Can't set User SID from RID!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* call the mapping code here */
+ become_root();
+ ret = pdb_getgrgid(&map, pwd->pw_gid);
+ unbecome_root();
+
+ if( ret ) {
+ if (!pdb_set_group_sid(account_data, &map.sid, PDB_SET)){
+ DEBUG(0,("Can't set Group SID!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ else {
+ if (!pdb_set_group_sid_from_rid(account_data, pdb_gid_to_group_rid(pwd->pw_gid), PDB_SET)) {
+ DEBUG(0,("Can't set Group SID\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
/*************************************************************
Initialises a struct sam_passwd with sane values.
/* see if we need to generate a new rid using the 2.2 algorithm */
if ( rid == 0 && lp_enable_rid_algorithm() ) {
DEBUG(10,("pdb_init_sam_new: no RID specified. Generating one via old algorithm\n"));
- rid = fallback_pdb_uid_to_user_rid(pwd->pw_uid);
+ rid = algorithmic_pdb_uid_to_user_rid(pwd->pw_uid);
}
/* set the new SID */
return NT_STATUS_OK;
}
-/**************************************************************************
- * This function will take care of all the steps needed to correctly
- * allocate and set the user SID, please do use this function to create new
- * users, messing with SIDs is not good.
- *
- * account_data must be provided initialized, pwd may be null.
- * SSS
- ***************************************************************************/
-
-NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd)
-{
- const char *guest_account = lp_guestaccount();
- GROUP_MAP map;
-
- if (!account_data || !pwd) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* this is a hack this thing should not be set
- this way --SSS */
- if (!(guest_account && *guest_account)) {
- DEBUG(1, ("NULL guest account!?!?\n"));
- return NT_STATUS_UNSUCCESSFUL;
- } else {
- /* Ensure this *must* be set right */
- if (strcmp(pwd->pw_name, guest_account) == 0) {
- if (!pdb_set_user_sid_from_rid(account_data, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (!pdb_set_group_sid_from_rid(account_data, DOMAIN_GROUP_RID_GUESTS, PDB_DEFAULT)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- return NT_STATUS_OK;
- }
- }
-
- if (!pdb_set_user_sid_from_rid(account_data, fallback_pdb_uid_to_user_rid(pwd->pw_uid), PDB_SET)) {
- DEBUG(0,("Can't set User SID from RID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* call the mapping code here */
- if(pdb_getgrgid(&map, pwd->pw_gid)) {
- if (!pdb_set_group_sid(account_data, &map.sid, PDB_SET)){
- DEBUG(0,("Can't set Group SID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- else {
- if (!pdb_set_group_sid_from_rid(account_data, pdb_gid_to_group_rid(pwd->pw_gid), PDB_SET)) {
- DEBUG(0,("Can't set Group SID\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
-
- return NT_STATUS_OK;
-}
-
/**********************************************************
Encode the account control bits into a string.
length = length of string to encode into (including terminating
char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
{
static fstring acct_str;
+
size_t i = 0;
+ SMB_ASSERT(length <= sizeof(acct_str));
+
acct_str[i++] = '[';
if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
return (True);
}
+/*************************************************************
+ Routine to set 42 hex hours characters from a 21 byte array.
+**************************************************************/
+
+void pdb_sethexhours(char *p, const unsigned char *hours)
+{
+ if (hours != NULL) {
+ int i;
+ for (i = 0; i < 21; i++) {
+ slprintf(&p[i*2], 3, "%02X", hours[i]);
+ }
+ } else {
+ safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
+ }
+}
+
+/*************************************************************
+ Routine to get the 42 hex characters and turn them
+ into a 21 byte array.
+**************************************************************/
+
+BOOL pdb_gethexhours(const char *p, unsigned char *hours)
+{
+ int i;
+ unsigned char lonybble, hinybble;
+ const char *hexchars = "0123456789ABCDEF";
+ char *p1, *p2;
+
+ if (!p) {
+ return (False);
+ }
+
+ for (i = 0; i < 42; i += 2) {
+ hinybble = toupper(p[i]);
+ lonybble = toupper(p[i + 1]);
+
+ p1 = strchr(hexchars, hinybble);
+ p2 = strchr(hexchars, lonybble);
+
+ if (!p1 || !p2) {
+ return (False);
+ }
+
+ hinybble = PTR_DIFF(p1, hexchars);
+ lonybble = PTR_DIFF(p2, hexchars);
+
+ hours[i / 2] = (hinybble << 4) | lonybble;
+ }
+ return (True);
+}
+
int algorithmic_rid_base(void)
{
static int rid_offset = 0;
Converts NT user RID to a UNIX uid.
********************************************************************/
-uid_t fallback_pdb_user_rid_to_uid(uint32 user_rid)
+uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
{
int rid_offset = algorithmic_rid_base();
return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
converts UNIX uid to an NT User RID.
********************************************************************/
-uint32 fallback_pdb_uid_to_user_rid(uid_t uid)
+uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
{
int rid_offset = algorithmic_rid_base();
return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
Decides if a RID is a user or group RID.
********************************************************************/
-BOOL fallback_pdb_rid_is_user(uint32 rid)
+BOOL algorithmic_pdb_rid_is_user(uint32 rid)
{
- /* lkcl i understand that NT attaches an enumeration to a RID
- * such that it can be identified as either a user, group etc
- * type. there are 5 such categories, and they are documented.
- */
- /* However, they are not in the RID, just somthing you can query
- seperatly. Sorry luke :-) */
-
- if(pdb_rid_is_well_known(rid)) {
- /*
- * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
- * and DOMAIN_USER_RID_GUEST.
- */
- if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
- return True;
- } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
- return True;
- }
- return False;
+ if(pdb_rid_is_well_known(rid)) {
+ /*
+ * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
+ * and DOMAIN_USER_RID_GUEST.
+ */
+ if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
+ return True;
+ } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
+ return True;
+ }
+ return False;
}
/*******************************************************************
Convert a rid into a name. Used in the lookup SID rpc.
********************************************************************/
-BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use)
+BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use)
{
uint32 rid;
SAM_ACCOUNT *sam_account = NULL;
GROUP_MAP map;
+ BOOL ret;
+
+ if (sid_equal(get_global_sam_sid(), sid)) {
+ *psid_name_use = SID_NAME_DOMAIN;
+ fstrcpy(name, "");
+ DEBUG(5,("local_lookup_sid: SID is our own domain-sid: %s.\n",
+ sid_string_static(sid)));
+ return True;
+ }
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)){
DEBUG(0,("local_lookup_sid: sid_peek_check_rid return False! SID: %s\n",
return True;
}
- /*
- * Don't try to convert the rid to a name if
- * running in appliance mode
- */
-
- if (lp_hide_local_users())
- return False;
-
if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
return False;
}
/* see if the passdb can help us with the name of the user */
+ /* BEING ROOT BLLOCK */
become_root();
if (pdb_getsampwsid(sam_account, sid)) {
- unbecome_root();
+ unbecome_root(); /* -----> EXIT BECOME_ROOT() */
fstrcpy(name, pdb_get_username(sam_account));
*psid_name_use = SID_NAME_USER;
return True;
}
- unbecome_root();
pdb_free_sam(&sam_account);
-
- if (pdb_getgrsid(&map, *sid)) {
+
+ ret = pdb_getgrsid(&map, *sid);
+ unbecome_root();
+ /* END BECOME_ROOT BLOCK */
+
+ if ( ret ) {
if (map.gid!=(gid_t)-1) {
DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid));
} else {
return True;
}
- if (fallback_pdb_rid_is_user(rid)) {
+ if (algorithmic_pdb_rid_is_user(rid)) {
uid_t uid;
struct passwd *pw = NULL;
DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid));
- uid = fallback_pdb_user_rid_to_uid(rid);
+ uid = algorithmic_pdb_user_rid_to_uid(rid);
pw = sys_getpwuid( uid );
DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid,
DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name,
(unsigned int)rid ));
- /* assume fallback groups aer domain global groups */
+ /* assume algorithmic groups are domain global groups */
*psid_name_use = SID_NAME_DOM_GRP;
BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use)
{
- extern DOM_SID global_sid_World_Domain;
DOM_SID local_sid;
+ DOM_SID sid;
fstring user;
SAM_ACCOUNT *sam_account = NULL;
struct group *grp;
GROUP_MAP map;
-
+
*psid_name_use = SID_NAME_UNKNOWN;
/*
sid_copy(&local_sid, get_global_sam_sid());
- /*
- * Special case for MACHINE\Everyone. Map to the world_sid.
- */
-
- if(strequal(user, "Everyone")) {
- sid_copy( psid, &global_sid_World_Domain);
- sid_append_rid(psid, 0);
- *psid_name_use = SID_NAME_ALIAS;
+ if (map_name_to_wellknown_sid(&sid, psid_name_use, user)){
+ fstring sid_str;
+ sid_copy( psid, &sid);
+ sid_to_string(sid_str, &sid);
+ DEBUG(10,("lookup_name: name %s = SID %s, type = %u\n", user, sid_str,
+ (unsigned int)*psid_name_use ));
return True;
}
- /*
- * Don't lookup local unix users if running in appliance mode
- */
- if (lp_hide_local_users())
- return False;
-
(void)map_username(user);
if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
return False;
}
+ /* BEGIN ROOT BLOCK */
+
become_root();
if (pdb_getsampwnam(sam_account, user)) {
unbecome_root();
pdb_free_sam(&sam_account);
return True;
}
- unbecome_root();
pdb_free_sam(&sam_account);
} else {
/* it's not a mapped group */
grp = getgrnam(user);
- if(!grp)
+ if(!grp) {
+ unbecome_root(); /* ---> exit form block */
return False;
+ }
/*
*check if it's mapped, if it is reply it doesn't exist
*/
if (pdb_getgrgid(&map, grp->gr_gid)){
+ unbecome_root(); /* ---> exit form block */
return False;
}
sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
*psid_name_use = SID_NAME_ALIAS;
}
+ unbecome_root();
+ /* END ROOT BLOCK */
sid_copy( psid, &local_sid);
if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
/* Might not exist in /etc/passwd. Use rid algorithm here */
if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) {
- slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
+ slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name);
return False;
}
} else {
return True;
}
+/****************************************************************************
+ Convert a uid to SID - algorithmic.
+****************************************************************************/
+
+DOM_SID *algorithmic_uid_to_sid(DOM_SID *psid, uid_t uid)
+{
+ if ( !lp_enable_rid_algorithm() )
+ return NULL;
+
+ DEBUG(8,("algorithmic_uid_to_sid: falling back to RID algorithm\n"));
+ sid_copy( psid, get_global_sam_sid() );
+ sid_append_rid( psid, algorithmic_pdb_uid_to_user_rid(uid) );
+ DEBUG(10,("algorithmic_uid_to_sid: uid (%d) -> SID %s.\n",
+ (unsigned int)uid, sid_string_static(psid) ));
+
+ return psid;
+}
+
/****************************************************************************
Convert a uid to SID - locally.
****************************************************************************/
unix_pw = sys_getpwuid( uid );
if ( !unix_pw ) {
- DEBUG(4,("local_uid_to_sid: host has know idea of uid %lu\n", (unsigned long)uid));
- return NULL;
+ DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid));
+ return algorithmic_uid_to_sid( psid, uid);
}
if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
else {
DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n",
unix_pw->pw_name, (unsigned long)uid));
-
- if ( !lp_enable_rid_algorithm() )
- return NULL;
- DEBUG(8,("local_uid_to_sid: falling back to RID algorithm\n"));
-
- sid_copy( psid, get_global_sam_sid() );
- sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) );
+ return algorithmic_uid_to_sid( psid, uid);
}
-
DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n",
(unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
return True;
}
+/****************************************************************************
+ Convert a gid to SID - algorithmic.
+****************************************************************************/
+
+DOM_SID *algorithmic_gid_to_sid(DOM_SID *psid, uid_t gid)
+{
+ if ( !lp_enable_rid_algorithm() )
+ return NULL;
+
+ DEBUG(8,("algorithmic_gid_to_sid: falling back to RID algorithm\n"));
+ sid_copy( psid, get_global_sam_sid() );
+ sid_append_rid( psid, pdb_gid_to_group_rid(gid) );
+ DEBUG(10,("algorithmic_gid_to_sid: gid (%d) -> SID %s.\n",
+ (unsigned int)gid, sid_string_static(psid) ));
+
+ return psid;
+}
+
/****************************************************************************
Convert a gid to SID - locally.
****************************************************************************/
if ( !ret ) {
- /* fallback to rid mapping if enabled */
+ /* algorithmic to rid mapping if enabled */
if ( lp_enable_rid_algorithm() ) {
- sid_copy(psid, get_global_sam_sid());
- sid_append_rid(psid, pdb_gid_to_group_rid(gid));
DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n",
(unsigned int)gid, sid_string_static(psid)));
- return psid;
+ return algorithmic_gid_to_sid(psid, gid);
}
else
return NULL;
{
uint32 rid;
GROUP_MAP group;
+ BOOL ret;
*name_type = SID_NAME_UNKNOWN;
/* we don't need to disable winbindd since the gid is stored in
the GROUP_MAP object */
+
+ become_root();
+ ret = pdb_getgrsid(&group, *psid);
+ unbecome_root();
+
+ if ( !ret ) {
- if ( !pdb_getgrsid(&group, *psid) ) {
-
- /* fallback to rid mapping if enabled */
+ /* Fallback to algorithmic rid mapping if enabled */
if ( lp_enable_rid_algorithm() ) {
}
if (!sid_peek_rid(psid, &rid)) {
- DEBUG(10,("local_sid_to_uid: invalid SID!\n"));
+ DEBUG(10,("local_sid_to_gid: invalid SID!\n"));
return False;
}
DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n"));
- if (fallback_pdb_rid_is_user(rid)) {
+ if (algorithmic_pdb_rid_is_user(rid)) {
DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid)));
return False;
} else {
}
*pgid = group.gid;
+ *name_type = group.sid_name_use;
DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
(unsigned int)*pgid));
Marshall/unmarshall SAM_ACCOUNT structs.
*********************************************************************/
-#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBdd"
+#define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
/**********************************************************************
Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
*********************************************************************/
BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+{
+ return(init_sam_from_buffer_v2(sampass, buf, buflen));
+}
+
+/**********************************************************************
+ Intialize a BYTE buffer from a SAM_ACCOUNT struct
+ *********************************************************************/
+
+uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+{
+ return(init_buffer_from_sam_v2(buf, sampass, size_only));
+}
+
+
+BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
{
/* times are stored as 32bit integer
fullname_len, homedir_len, logon_script_len,
profile_path_len, acct_desc_len, workstations_len;
- uint32 user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6;
+ uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
uint8 *hours;
- static uint8 *lm_pw_ptr, *nt_pw_ptr;
+ uint8 *lm_pw_ptr, *nt_pw_ptr;
uint32 len = 0;
uint32 lm_pw_len, nt_pw_len, hourslen;
BOOL ret = True;
- uid_t uid = -1;
- gid_t gid = -1;
- struct passwd *pw = NULL;
if(sampass == NULL || buf == NULL) {
- DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n"));
+ DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
return False;
}
-
+
+/* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
/* unpack the buffer into variables */
- len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING,
- &logon_time,
- &logoff_time,
- &kickoff_time,
- &pass_last_set_time,
- &pass_can_change_time,
- &pass_must_change_time,
- &username_len, &username,
- &domain_len, &domain,
- &nt_username_len, &nt_username,
- &fullname_len, &fullname,
- &homedir_len, &homedir,
- &dir_drive_len, &dir_drive,
- &logon_script_len, &logon_script,
- &profile_path_len, &profile_path,
- &acct_desc_len, &acct_desc,
- &workstations_len, &workstations,
- &unknown_str_len, &unknown_str,
- &munged_dial_len, &munged_dial,
- &user_rid,
- &group_rid,
- &lm_pw_len, &lm_pw_ptr,
- &nt_pw_len, &nt_pw_ptr,
- &acct_ctrl,
- &unknown_3,
- &logon_divs,
- &hours_len,
- &hourslen, &hours,
- &unknown_5,
- &unknown_6);
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ &acct_ctrl, /* w */
+ &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
- if (len == -1) {
+ if (len == (uint32) -1) {
ret = False;
goto done;
}
pdb_set_nt_username(sampass, nt_username, PDB_SET);
pdb_set_fullname(sampass, fullname, PDB_SET);
-
- if ( (pw=Get_Pwnam(username)) != NULL ) {
- uid = pw->pw_uid;
- gid = pw->pw_gid;
- }
-
if (homedir) {
pdb_set_homedir(sampass, homedir, PDB_SET);
}
else {
pdb_set_homedir(sampass,
- talloc_sub_specified(sampass->mem_ctx,
- lp_logon_home(),
- username, domain,
- uid, gid),
- PDB_DEFAULT);
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ PDB_DEFAULT);
}
if (dir_drive)
pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
else {
pdb_set_dir_drive(sampass,
- talloc_sub_specified(sampass->mem_ctx,
- lp_logon_drive(),
- username, domain,
- uid, gid),
- PDB_DEFAULT);
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
+ PDB_DEFAULT);
}
if (logon_script)
pdb_set_logon_script(sampass, logon_script, PDB_SET);
else {
pdb_set_logon_script(sampass,
- talloc_sub_specified(sampass->mem_ctx,
- lp_logon_script(),
- username, domain,
- uid, gid),
- PDB_DEFAULT);
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ PDB_DEFAULT);
}
if (profile_path) {
pdb_set_profile_path(sampass, profile_path, PDB_SET);
} else {
pdb_set_profile_path(sampass,
- talloc_sub_specified(sampass->mem_ctx,
- lp_logon_path(),
- username, domain,
- uid, gid),
- PDB_DEFAULT);
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
+ PDB_DEFAULT);
}
pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
}
}
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
- pdb_set_unknown_3(sampass, unknown_3, PDB_SET);
pdb_set_hours_len(sampass, hours_len, PDB_SET);
- pdb_set_unknown_5(sampass, unknown_5, PDB_SET);
+ pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+ pdb_set_logon_count(sampass, logon_count, PDB_SET);
pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
SAFE_FREE(workstations);
SAFE_FREE(munged_dial);
SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
SAFE_FREE(hours);
return ret;
}
-/**********************************************************************
- Intialize a BYTE buffer from a SAM_ACCOUNT struct
- *********************************************************************/
+BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+{
-uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ bad_password_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username;
+ char *domain;
+ char *nt_username;
+ char *dir_drive;
+ char *unknown_str;
+ char *munged_dial;
+ char *fullname;
+ char *homedir;
+ char *logon_script;
+ char *profile_path;
+ char *acct_desc;
+ char *workstations;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours;
+ uint8 *lm_pw_ptr, *nt_pw_ptr;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, hourslen;
+ BOOL ret = True;
+
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
+ return False;
+ }
+
+/* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ /* Change from V0 is addition of bad_password_time field. */
+ &bad_password_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ &acct_ctrl, /* w */
+ &remove_me, /* d */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
+
+ if (len == (uint32) -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+
+ /* Change from V0 is addition of bad_password_time field. */
+ pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ pdb_set_homedir(sampass, homedir, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else {
+ pdb_set_dir_drive(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
+ PDB_DEFAULT);
+ }
+
+ if (logon_script)
+ pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ else {
+ pdb_set_logon_script(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ } else {
+ pdb_set_profile_path(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+
+ pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
+ pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
+ pdb_set_hours_len(sampass, hours_len, PDB_SET);
+ pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+ pdb_set_logon_count(sampass, logon_count, PDB_SET);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+
+BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+{
+
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ bad_password_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username;
+ char *domain;
+ char *nt_username;
+ char *dir_drive;
+ char *unknown_str;
+ char *munged_dial;
+ char *fullname;
+ char *homedir;
+ char *logon_script;
+ char *profile_path;
+ char *acct_desc;
+ char *workstations;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours;
+ uint8 *lm_pw_ptr, *nt_pw_ptr, *nt_pw_hist_ptr;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
+ uint32 pwHistLen = 0;
+ BOOL ret = True;
+
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
+ return False;
+ }
+
+/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ &bad_password_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ /* Change from V1 is addition of password history field. */
+ &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
+ &acct_ctrl, /* w */
+ /* Also "remove_me" field was removed. */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
+
+ if (len == (uint32) -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+ pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ pdb_set_homedir(sampass, homedir, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else {
+ pdb_set_dir_drive(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
+ PDB_DEFAULT);
+ }
+
+ if (logon_script)
+ pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ else {
+ pdb_set_logon_script(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ } else {
+ pdb_set_profile_path(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ /* Change from V1 is addition of password history field. */
+ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ if (pwHistLen) {
+ char *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
+ if (!pw_hist) {
+ ret = False;
+ goto done;
+ }
+ memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
+ if (nt_pw_hist_ptr && nt_pw_hist_len) {
+ int i;
+ SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
+ nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
+ for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
+ memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
+ &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
+ PW_HISTORY_ENTRY_LEN);
+ }
+ }
+ if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
+ SAFE_FREE(pw_hist);
+ ret = False;
+ goto done;
+ }
+ SAFE_FREE(pw_hist);
+ } else {
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+ }
+
+ pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
+ pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
+ pdb_set_hours_len(sampass, hours_len, PDB_SET);
+ pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+ pdb_set_logon_count(sampass, logon_count, PDB_SET);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
+ SAFE_FREE(nt_pw_hist_ptr);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
{
size_t len, buflen;
uint32 logon_time,
logoff_time,
kickoff_time,
+ bad_password_time,
pass_last_set_time,
pass_can_change_time,
pass_must_change_time;
const uint8 *lm_pw;
const uint8 *nt_pw;
+ const uint8 *nt_pw_hist;
uint32 lm_pw_len = 16;
uint32 nt_pw_len = 16;
+ uint32 nt_pw_hist_len;
+ uint32 pwHistLen = 0;
/* do we have a valid SAM_ACCOUNT pointer? */
if (sampass == NULL) {
logon_time = (uint32)pdb_get_logon_time(sampass);
logoff_time = (uint32)pdb_get_logoff_time(sampass);
kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
+ bad_password_time = (uint32)pdb_get_bad_password_time(sampass);
pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
group_rid = pdb_get_group_rid(sampass);
username = pdb_get_username(sampass);
- if (username)
+ if (username) {
username_len = strlen(username) +1;
- else
+ } else {
username_len = 0;
+ }
domain = pdb_get_domain(sampass);
- if (domain)
+ if (domain) {
domain_len = strlen(domain) +1;
- else
+ } else {
domain_len = 0;
+ }
nt_username = pdb_get_nt_username(sampass);
- if (nt_username)
+ if (nt_username) {
nt_username_len = strlen(nt_username) +1;
- else
+ } else {
nt_username_len = 0;
+ }
fullname = pdb_get_fullname(sampass);
- if (fullname)
+ if (fullname) {
fullname_len = strlen(fullname) +1;
- else
+ } else {
fullname_len = 0;
+ }
/*
* Only updates fields which have been set (not defaults from smb.conf)
*/
- if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE))
+ if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
dir_drive = pdb_get_dir_drive(sampass);
- else
+ } else {
dir_drive = NULL;
- if (dir_drive)
+ }
+ if (dir_drive) {
dir_drive_len = strlen(dir_drive) +1;
- else
+ } else {
dir_drive_len = 0;
+ }
- if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME))
+ if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
homedir = pdb_get_homedir(sampass);
- else
+ } else {
homedir = NULL;
- if (homedir)
+ }
+ if (homedir) {
homedir_len = strlen(homedir) +1;
- else
+ } else {
homedir_len = 0;
+ }
- if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT))
+ if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
logon_script = pdb_get_logon_script(sampass);
- else
+ } else {
logon_script = NULL;
- if (logon_script)
+ }
+ if (logon_script) {
logon_script_len = strlen(logon_script) +1;
- else
+ } else {
logon_script_len = 0;
+ }
- if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE))
+ if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
profile_path = pdb_get_profile_path(sampass);
- else
+ } else {
profile_path = NULL;
- if (profile_path)
+ }
+ if (profile_path) {
profile_path_len = strlen(profile_path) +1;
- else
+ } else {
profile_path_len = 0;
+ }
lm_pw = pdb_get_lanman_passwd(sampass);
- if (!lm_pw)
+ if (!lm_pw) {
lm_pw_len = 0;
+ }
nt_pw = pdb_get_nt_passwd(sampass);
- if (!nt_pw)
+ if (!nt_pw) {
nt_pw_len = 0;
-
+ }
+
+ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len);
+ if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
+ nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
+ } else {
+ nt_pw_hist_len = 0;
+ }
+
acct_desc = pdb_get_acct_desc(sampass);
- if (acct_desc)
+ if (acct_desc) {
acct_desc_len = strlen(acct_desc) +1;
- else
+ } else {
acct_desc_len = 0;
+ }
workstations = pdb_get_workstations(sampass);
- if (workstations)
+ if (workstations) {
workstations_len = strlen(workstations) +1;
- else
+ } else {
workstations_len = 0;
+ }
unknown_str = NULL;
unknown_str_len = 0;
munged_dial = pdb_get_munged_dial(sampass);
- if (munged_dial)
+ if (munged_dial) {
munged_dial_len = strlen(munged_dial) +1;
- else
+ } else {
munged_dial_len = 0;
-
+ }
+
+/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
+
/* one time to get the size needed */
- len = tdb_pack(NULL, 0, TDB_FORMAT_STRING,
- logon_time,
- logoff_time,
- kickoff_time,
- pass_last_set_time,
- pass_can_change_time,
- pass_must_change_time,
- username_len, username,
- domain_len, domain,
- nt_username_len, nt_username,
- fullname_len, fullname,
- homedir_len, homedir,
- dir_drive_len, dir_drive,
- logon_script_len, logon_script,
- profile_path_len, profile_path,
- acct_desc_len, acct_desc,
- workstations_len, workstations,
- unknown_str_len, unknown_str,
- munged_dial_len, munged_dial,
- user_rid,
- group_rid,
- lm_pw_len, lm_pw,
- nt_pw_len, nt_pw,
- pdb_get_acct_ctrl(sampass),
- pdb_get_unknown_3(sampass),
- pdb_get_logon_divs(sampass),
- pdb_get_hours_len(sampass),
- MAX_HOURS_LEN, pdb_get_hours(sampass),
- pdb_get_unknown_5(sampass),
- pdb_get_unknown_6(sampass));
-
-
- if (size_only)
+ len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V2,
+ logon_time, /* d */
+ logoff_time, /* d */
+ kickoff_time, /* d */
+ bad_password_time, /* d */
+ pass_last_set_time, /* d */
+ pass_can_change_time, /* d */
+ pass_must_change_time, /* d */
+ username_len, username, /* B */
+ domain_len, domain, /* B */
+ nt_username_len, nt_username, /* B */
+ fullname_len, fullname, /* B */
+ homedir_len, homedir, /* B */
+ dir_drive_len, dir_drive, /* B */
+ logon_script_len, logon_script, /* B */
+ profile_path_len, profile_path, /* B */
+ acct_desc_len, acct_desc, /* B */
+ workstations_len, workstations, /* B */
+ unknown_str_len, unknown_str, /* B */
+ munged_dial_len, munged_dial, /* B */
+ user_rid, /* d */
+ group_rid, /* d */
+ lm_pw_len, lm_pw, /* B */
+ nt_pw_len, nt_pw, /* B */
+ nt_pw_hist_len, nt_pw_hist, /* B */
+ pdb_get_acct_ctrl(sampass), /* w */
+ pdb_get_logon_divs(sampass), /* w */
+ pdb_get_hours_len(sampass), /* d */
+ MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
+ pdb_get_bad_password_count(sampass), /* w */
+ pdb_get_logon_count(sampass), /* w */
+ pdb_get_unknown_6(sampass)); /* d */
+
+ if (size_only) {
return buflen;
+ }
/* malloc the space needed */
- if ( (*buf=(uint8*)malloc(len)) == NULL) {
- DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n"));
+ if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
+ DEBUG(0,("init_buffer_from_sam_v2: Unable to malloc() memory for buffer!\n"));
return (-1);
}
/* now for the real call to tdb_pack() */
- buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING,
- logon_time,
- logoff_time,
- kickoff_time,
- pass_last_set_time,
- pass_can_change_time,
- pass_must_change_time,
- username_len, username,
- domain_len, domain,
- nt_username_len, nt_username,
- fullname_len, fullname,
- homedir_len, homedir,
- dir_drive_len, dir_drive,
- logon_script_len, logon_script,
- profile_path_len, profile_path,
- acct_desc_len, acct_desc,
- workstations_len, workstations,
- unknown_str_len, unknown_str,
- munged_dial_len, munged_dial,
- user_rid,
- group_rid,
- lm_pw_len, lm_pw,
- nt_pw_len, nt_pw,
- pdb_get_acct_ctrl(sampass),
- pdb_get_unknown_3(sampass),
- pdb_get_logon_divs(sampass),
- pdb_get_hours_len(sampass),
- MAX_HOURS_LEN, pdb_get_hours(sampass),
- pdb_get_unknown_5(sampass),
- pdb_get_unknown_6(sampass));
-
+ buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V2,
+ logon_time, /* d */
+ logoff_time, /* d */
+ kickoff_time, /* d */
+ bad_password_time, /* d */
+ pass_last_set_time, /* d */
+ pass_can_change_time, /* d */
+ pass_must_change_time, /* d */
+ username_len, username, /* B */
+ domain_len, domain, /* B */
+ nt_username_len, nt_username, /* B */
+ fullname_len, fullname, /* B */
+ homedir_len, homedir, /* B */
+ dir_drive_len, dir_drive, /* B */
+ logon_script_len, logon_script, /* B */
+ profile_path_len, profile_path, /* B */
+ acct_desc_len, acct_desc, /* B */
+ workstations_len, workstations, /* B */
+ unknown_str_len, unknown_str, /* B */
+ munged_dial_len, munged_dial, /* B */
+ user_rid, /* d */
+ group_rid, /* d */
+ lm_pw_len, lm_pw, /* B */
+ nt_pw_len, nt_pw, /* B */
+ nt_pw_hist_len, nt_pw_hist, /* B */
+ pdb_get_acct_ctrl(sampass), /* w */
+ pdb_get_logon_divs(sampass), /* w */
+ pdb_get_hours_len(sampass), /* d */
+ MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
+ pdb_get_bad_password_count(sampass), /* w */
+ pdb_get_logon_count(sampass), /* w */
+ pdb_get_unknown_6(sampass)); /* d */
/* check to make sure we got it correct */
if (buflen != len) {
- DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
+ DEBUG(0, ("init_buffer_from_sam_v2: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
(unsigned long)buflen, (unsigned long)len));
/* error */
SAFE_FREE (*buf);
return (buflen);
}
+BOOL pdb_copy_sam_account(const SAM_ACCOUNT *src, SAM_ACCOUNT **dst)
+{
+ BOOL result;
+ uint8 *buf;
+ int len;
+
+ if ((*dst == NULL) && (!NT_STATUS_IS_OK(pdb_init_sam(dst))))
+ return False;
+
+ len = init_buffer_from_sam_v2(&buf, src, False);
+
+ if (len == -1)
+ return False;
+
+ result = init_sam_from_buffer_v2(*dst, buf, len);
+ (*dst)->methods = src->methods;
+
+ free(buf);
+
+ return result;
+}
/**********************************************************************
**********************************************************************/
return False;
}
- *low = fallback_pdb_uid_to_user_rid(id_low);
- if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) {
+ *low = algorithmic_pdb_uid_to_user_rid(id_low);
+ if (algorithmic_pdb_user_rid_to_uid((uint32)-1) < id_high) {
*high = (uint32)-1;
} else {
- *high = fallback_pdb_uid_to_user_rid(id_high);
+ *high = algorithmic_pdb_uid_to_user_rid(id_high);
}
return True;
}
+/*********************************************************************
+ Update the bad password count checking the AP_RESET_COUNT_TIME
+*********************************************************************/
+
+BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated)
+{
+ time_t LastBadPassword;
+ uint16 BadPasswordCount;
+ uint32 resettime;
+
+ if (!sampass) return False;
+
+ BadPasswordCount = pdb_get_bad_password_count(sampass);
+ if (!BadPasswordCount) {
+ DEBUG(9, ("No bad password attempts.\n"));
+ return True;
+ }
+
+ if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) {
+ DEBUG(0, ("pdb_update_bad_password_count: account_policy_get failed.\n"));
+ return False;
+ }
+
+ /* First, check if there is a reset time to compare */
+ if ((resettime == (uint32) -1) || (resettime == 0)) {
+ DEBUG(9, ("No reset time, can't reset bad pw count\n"));
+ return True;
+ }
+
+ LastBadPassword = pdb_get_bad_password_time(sampass);
+ DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
+ (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
+ if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){
+ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
+ pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
+ if (updated) {
+ *updated = True;
+ }
+ }
+
+ return True;
+}
+/*********************************************************************
+ Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
+*********************************************************************/
+
+BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated)
+{
+ uint32 duration;
+ time_t LastBadPassword;
+
+ if (!sampass) return False;
+
+ if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
+ DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
+ pdb_get_username(sampass)));
+ return True;
+ }
+
+ if (!account_policy_get(AP_LOCK_ACCOUNT_DURATION, &duration)) {
+ DEBUG(0, ("pdb_update_autolock_flag: account_policy_get failed.\n"));
+ return False;
+ }
+
+ /* First, check if there is a duration to compare */
+ if ((duration == (uint32) -1) || (duration == 0)) {
+ DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
+ return True;
+ }
+
+ LastBadPassword = pdb_get_bad_password_time(sampass);
+ DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
+ pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
+
+ if (LastBadPassword == (time_t)0) {
+ DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \
+bad password time. Leaving locked out.\n",
+ pdb_get_username(sampass) ));
+ return True;
+ }
+
+ if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) {
+ pdb_set_acct_ctrl(sampass,
+ pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
+ PDB_CHANGED);
+ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
+ pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
+ if (updated) {
+ *updated = True;
+ }
+ }
+
+ return True;
+}
+
+/*********************************************************************
+ Increment the bad_password_count
+*********************************************************************/
+
+BOOL pdb_increment_bad_password_count(SAM_ACCOUNT *sampass)
+{
+ uint32 account_policy_lockout;
+ BOOL autolock_updated = False, badpw_updated = False;
+
+ if (!sampass)
+ return False;
+
+ /* Retrieve the account lockout policy */
+ if (!account_policy_get(AP_BAD_ATTEMPT_LOCKOUT,
+ &account_policy_lockout)) {
+ DEBUG(0, ("pdb_increment_bad_password_count: account_policy_get failed.\n"));
+ return False;
+ }
+
+ /* If there is no policy, we don't need to continue checking */
+ if (!account_policy_lockout) {
+ DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
+ return True;
+ }
+
+ /* Check if the autolock needs to be cleared */
+ if (!pdb_update_autolock_flag(sampass, &autolock_updated))
+ return False;
+
+ /* Check if the badpw count needs to be reset */
+ if (!pdb_update_bad_password_count(sampass, &badpw_updated))
+ return False;
+
+ /*
+ Ok, now we can assume that any resetting that needs to be
+ done has been done, and just get on with incrementing
+ and autolocking if necessary
+ */
+
+ pdb_set_bad_password_count(sampass,
+ pdb_get_bad_password_count(sampass)+1,
+ PDB_CHANGED);
+ pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
+
+
+ if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
+ return True;
+
+ if (!pdb_set_acct_ctrl(sampass,
+ pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
+ PDB_CHANGED)) {
+ DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
+ return False;
+ }
+
+ return True;
+}