}
/* this holds info on user ids that are already validated for this VC */
-static user_struct *validated_users = NULL;
-static int num_validated_users = 0;
+static user_struct *validated_users;
+static int next_vuid = VUID_OFFSET;
+static int num_validated_vuids;
/****************************************************************************
check if a uid has been validated, and return an pointer to the user_struct
****************************************************************************/
user_struct *get_valid_user_struct(uint16 vuid)
{
- if (vuid == UID_FIELD_INVALID)
- return NULL;
- vuid -= VUID_OFFSET;
- if ((vuid >= (uint16)num_validated_users) ||
- (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1))
- return NULL;
- return &validated_users[vuid];
+ user_struct *usp;
+ int count=0;
+
+ if (vuid == UID_FIELD_INVALID)
+ return NULL;
+
+ for (usp=validated_users;usp;usp=usp->next,count++) {
+ if (vuid == usp->vuid) {
+ if (count > 10)
+ DLIST_PROMOTE(validated_users, usp);
+ return usp;
+ }
+ }
+
+ return NULL;
}
/****************************************************************************
if (vuser == NULL)
return;
- vuser->uid = (uid_t)-1;
- vuser->gid = (gid_t)-1;
-
- /* same number of igroups as groups */
- vuser->n_groups = 0;
-
- if (vuser->groups)
- free((char *)vuser->groups);
-
- vuser->groups = NULL;
+ DLIST_REMOVE(validated_users, vuser);
+ safe_free(vuser->groups);
delete_nt_token(&vuser->nt_user_token);
+ safe_free(vuser);
+ num_validated_vuids--;
}
/****************************************************************************
}
-/****************************************************************************
- Initialize the groups a user belongs to.
-****************************************************************************/
-
-BOOL initialize_groups(char *user, uid_t uid, gid_t gid)
-{
- become_root();
- if (initgroups(user,gid) == -1) {
- DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) ));
- if (getuid() == 0) {
- if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) {
- DEBUG(0,("This is probably a problem with the account %s\n", user));
- }
- }
- unbecome_root();
- return False;
- }
- unbecome_root();
- return True;
-}
-
/****************************************************************************
Create the SID list for this user.
****************************************************************************/
-NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups)
+NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
{
+ extern DOM_SID global_sid_World;
+ extern DOM_SID global_sid_Network;
+ extern DOM_SID global_sid_Builtin_Guests;
+ extern DOM_SID global_sid_Authenticated_Users;
NT_USER_TOKEN *token;
DOM_SID *psids;
int i, psid_ndx = 0;
+ size_t num_sids = 0;
+ fstring sid_str;
if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL)
return NULL;
ZERO_STRUCTP(token);
- if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) {
+ /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */
+ num_sids = 5 + ngroups;
+
+ if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) {
free(token);
return NULL;
}
psids = token->user_sids;
- token->num_sids = 2;
+ /*
+ * Note - user SID *MUST* be first in token !
+ * se_access_check depends on this.
+ */
- uid_to_sid( &psids[0], uid);
- gid_to_sid( &psids[1], gid);
+ uid_to_sid( &psids[psid_ndx++], uid);
+
+ /*
+ * Primary group SID is second in token. Convention.
+ */
+
+ gid_to_sid( &psids[psid_ndx++], gid);
+
+ /* Now add the group SIDs. */
for (i = 0; i < ngroups; i++) {
if (groups[i] != gid) {
- gid_to_sid( &psids[psid_ndx+2], groups[i]);
- psid_ndx++;
- token->num_sids++;
+ gid_to_sid( &psids[psid_ndx++], groups[i]);
}
}
- for (i = 0; i < ngroups; i++)
- gid_to_sid( &psids[i+2], groups[i]);
+
+ /*
+ * Finally add the "standard" SIDs.
+ * The only difference between guest and "anonymous" (which we
+ * don't really support) is the addition of Authenticated_Users.
+ */
+
+ sid_copy( &psids[psid_ndx++], &global_sid_World);
+ sid_copy( &psids[psid_ndx++], &global_sid_Network);
+
+ if (is_guest)
+ sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests);
+ else
+ sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users);
+
+ token->num_sids = psid_ndx;
+
+ /* Dump list of sids in token */
+
+ for (i = 0; i < token->num_sids; i++) {
+ DEBUG(5, ("user token sid %s\n",
+ sid_to_string(sid_str, &token->user_sids[i])));
+ }
return token;
}
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
char *domain,BOOL guest)
{
- user_struct *vuser;
- struct passwd *pwfile; /* for getting real name from passwd file */
+ user_struct *vuser = NULL;
+ struct passwd *pwfile; /* for getting real name from passwd file */
- /* Ensure no vuid gets registered in share level security. */
- if(lp_security() == SEC_SHARE)
- return UID_FIELD_INVALID;
+ /* Ensure no vuid gets registered in share level security. */
+ if(lp_security() == SEC_SHARE)
+ return UID_FIELD_INVALID;
- validated_users = (user_struct *)Realloc(validated_users,
- sizeof(user_struct)*
- (num_validated_users+1));
-
- if (!validated_users) {
- DEBUG(0,("Failed to realloc users struct!\n"));
- num_validated_users = 0;
- return UID_FIELD_INVALID;
- }
+ /* Limit allowed vuids to 16bits - VUID_OFFSET. */
+ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET)
+ return UID_FIELD_INVALID;
- vuser = &validated_users[num_validated_users];
- num_validated_users++;
+ if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) {
+ DEBUG(0,("Failed to malloc users struct!\n"));
+ return UID_FIELD_INVALID;
+ }
- vuser->uid = uid;
- vuser->gid = gid;
- vuser->guest = guest;
- fstrcpy(vuser->user.unix_name,unix_name);
- fstrcpy(vuser->user.smb_name,requested_name);
- fstrcpy(vuser->user.domain,domain);
+ ZERO_STRUCTP(vuser);
- vuser->n_groups = 0;
- vuser->groups = NULL;
+ DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid,
+ unix_name, requested_name, domain, guest ));
- /* Find all the groups this uid is in and store them.
- Used by become_user() */
- initialise_groups(unix_name, uid, gid);
- initialize_groups(unix_name, uid, gid);
- get_current_groups( &vuser->n_groups, &vuser->groups);
+ /* Allocate a free vuid. Yes this is a linear search... :-) */
+ while( get_valid_user_struct(next_vuid) != NULL ) {
+ next_vuid++;
+ /* Check for vuid wrap. */
+ if (next_vuid == UID_FIELD_INVALID)
+ next_vuid = VUID_OFFSET;
+ }
- /* Create an NT_USER_TOKEN struct for this user. */
- vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups);
+ DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
- DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
+ vuser->vuid = next_vuid;
+ vuser->uid = uid;
+ vuser->gid = gid;
+ vuser->guest = guest;
+ fstrcpy(vuser->user.unix_name,unix_name);
+ fstrcpy(vuser->user.smb_name,requested_name);
+ fstrcpy(vuser->user.domain,domain);
- DEBUG(3, ("Clearing default real name\n"));
- fstrcpy(vuser->user.full_name, "<Full Name>");
- if (lp_unix_realname()) {
- if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
- DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
- fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
- }
- }
+ vuser->n_groups = 0;
+ vuser->groups = NULL;
+
+ /* Find all the groups this uid is in and store them.
+ Used by become_user() */
+ initialise_groups(unix_name, uid, gid);
+ get_current_groups( &vuser->n_groups, &vuser->groups);
+
+ /* Create an NT_USER_TOKEN struct for this user. */
+ vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups, guest);
+
+ next_vuid++;
+ num_validated_vuids++;
+
+ DLIST_ADD(validated_users, vuser);
- memset(&vuser->dc, '\0', sizeof(vuser->dc));
+ DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
- return (uint16)((num_validated_users - 1) + VUID_OFFSET);
+ DEBUG(3, ("Clearing default real name\n"));
+ fstrcpy(vuser->user.full_name, "<Full Name>");
+ if (lp_unix_realname()) {
+ if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
+ DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
+ fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
+ }
+ }
+
+ memset(&vuser->dc, '\0', sizeof(vuser->dc));
+
+ return vuser->vuid;
}
*****************************************************************************/
static BOOL update_smbpassword_file(char *user, char *password)
{
- struct smb_passwd *smbpw;
- BOOL ret;
+ SAM_ACCOUNT *sampass = NULL;
+ BOOL ret;
become_root();
- smbpw = getsmbpwnam(user);
+ sampass = pdb_getsampwnam(user);
unbecome_root();
- if(smbpw == NULL) {
- DEBUG(0,("getsmbpwnam returned NULL\n"));
+ if(sampass == NULL) {
+ DEBUG(0,("pdb_getsampwnam returned NULL\n"));
return False;
}
* Remove the account disabled flag - we are updating the
* users password from a login.
*/
- smbpw->acct_ctrl &= ~ACB_DISABLED;
+ pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED);
/* Here, the flag is one, because we want to ignore the
XXXXXXX'd out password */
- ret = change_oem_password( smbpw, password, True);
+ ret = change_oem_password( sampass, password, True);
if (ret == False) {
DEBUG(3,("change_oem_password returned False\n"));
}
return ret;
}
-
-
-
-
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
unsigned char p21[21];
unsigned char p24[24];
- if (part_passwd == NULL)
+ if (part_passwd == NULL)
+ {
DEBUG(10,("No password set - allowing access\n"));
- /* No password set - always true ! */
- if (part_passwd == NULL)
+
+ /* No password set - always true ! */
return 1;
+ }
memset(p21,'\0',21);
memcpy(p21,part_passwd,16);
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
-BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
+BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8],
uchar lm_pass[24], uchar nt_pass[24])
{
uchar challenge[8];
+ char* user_name;
+ BYTE *nt_pw, *lm_pw;
- if (!lm_pass || !smb_pass) return(False);
+ if (!lm_pass || !sampass)
+ return(False);
- DEBUG(4,("Checking SMB password for user %s\n",
- smb_pass->smb_name));
+ user_name = pdb_get_username(sampass);
+
+ DEBUG(4,("Checking SMB password for user %s\n",user_name));
- if(smb_pass->acct_ctrl & ACB_DISABLED) {
- DEBUG(1,("account for user %s was disabled.\n",
- smb_pass->smb_name));
+ if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
+ DEBUG(1,("account for user %s was disabled.\n", user_name));
return(False);
}
memcpy(challenge, chal, 8);
}
- if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) {
+ nt_pw = pdb_get_nt_passwd(sampass);
+
+ if ((Protocol >= PROTOCOL_NT1) && (nt_pw != NULL)) {
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
- if (smb_password_check((char *)nt_pass,
- (uchar *)smb_pass->smb_nt_passwd,
- challenge)) {
+ if (smb_password_check((char *)nt_pass, (uchar *)nt_pw, challenge))
+ {
DEBUG(4,("NT MD4 password check succeeded\n"));
return(True);
}
DEBUG(4,("NT MD4 password check failed\n"));
}
- /* Try against the lanman password. smb_pass->smb_passwd == NULL means
- no password, allow access. */
+ /* Try against the lanman password. pdb_get_lanman_passwd(sampass) == NULL
+ means no password, allow access. */
DEBUG(4,("Checking LM MD4 password\n"));
- if((smb_pass->smb_passwd == NULL) &&
- (smb_pass->acct_ctrl & ACB_PWNOTREQ)) {
- DEBUG(4,("no password required for user %s\n",
- smb_pass->smb_name));
+ lm_pw = pdb_get_lanman_passwd(sampass);
+
+ if((lm_pw == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ))
+ {
+ DEBUG(4,("no password required for user %s\n",user_name));
return True;
}
- if((smb_pass->smb_passwd != NULL) &&
- smb_password_check((char *)lm_pass,
- (uchar *)smb_pass->smb_passwd, challenge)) {
+ if((lm_pw != NULL) && smb_password_check((char *)lm_pass,(uchar *)lm_pw, challenge))
+ {
DEBUG(4,("LM MD4 password check succeeded\n"));
return(True);
}
return True if the password is correct, False otherwise
****************************************************************************/
-BOOL pass_check_smb(char *user, char *domain,
- uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
- struct passwd *pwd)
+BOOL pass_check_smb(char *user, char *domain, uchar *chal,
+ uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd)
{
struct passwd *pass;
- struct smb_passwd *smb_pass;
+ SAM_ACCOUNT *sampass;
if (!lm_pwd || !nt_pwd)
{
return(False);
}
+ /* FIXME! this code looks to be unnecessary now that the passdb
+ validates that the username exists and has a valid uid */
if (pwd != NULL && user == NULL)
{
pass = (struct passwd *) pwd;
}
else
{
+ /* I don't get this call here. I think it should be moved.
+ Need to check on it. --jerry */
pass = smb_getpwnam(user,True);
}
return(False);
}
- smb_pass = getsmbpwnam(user);
-
- if (smb_pass == NULL)
+ /* get the account information */
+ sampass = pdb_getsampwnam(user);
+ if (sampass == NULL)
{
- DEBUG(1,("Couldn't find user '%s' in smb_passwd file.\n", user));
+ DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user));
return(False);
}
/* Quit if the account was disabled. */
- if(smb_pass->acct_ctrl & ACB_DISABLED) {
+ if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
DEBUG(1,("Account for user '%s' was disabled.\n", user));
return(False);
}
- /* Ensure the uid's match */
+ /* Ensure the uid's match
+ FIXME! This also seems unnecessary --jerry */
+#if 0 /* GWC */
if (smb_pass->smb_userid != pass->pw_uid)
{
DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user));
return(False);
}
+#endif
- if (lm_pwd[0] == '\0' && (smb_pass->acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords())
+ if (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)
{
- DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name));
- return(True);
+ if (lp_null_passwords())
+ {
+ DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user));
+ return(True);
+ }
+ else
+ {
+ DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user));
+ return(False);
+ }
}
- if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd))
+ if (smb_password_ok(sampass, chal, lm_pwd, nt_pwd))
{
return(True);
}
else
DEBUG(0,("Invalid guest account %s??\n",guestname));
*guest = True;
- *force = True;
}
if (ok && !user_ok(user,snum))
int plus_allowed = 1;
char *file_host;
char *file_user;
- char **lines = file_lines_load(equiv_file, NULL);
+ char **lines = file_lines_load(equiv_file, NULL, False);
int i;
DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
We have been asked to dynamcially determine the IP addresses of
the PDC and BDC's for this DOMAIN, and query them in turn.
************************************************************************/
-static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd)
+static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd, time_t last_change_time)
{
struct in_addr *ip_list = NULL;
int count = 0;
int i;
BOOL connected_ok = False;
+ time_t time_now = time(NULL);
+ BOOL use_pdc_only = False;
+
+ /*
+ * If the time the machine password has changed
+ * was less than an hour ago then we need to contact
+ * the PDC only, as we cannot be sure domain replication
+ * has yet taken place. Bug found by Gerald (way to go
+ * Gerald !). JRA.
+ */
+
+ if (time_now - last_change_time < 3600)
+ use_pdc_only = True;
- if (!get_dc_list(lp_workgroup(), &ip_list, &count))
+ if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count))
return False;
/*
struct cli_state cli;
uint32 smb_uid_low;
BOOL connected_ok = False;
+ time_t last_change_time;
if(user_exists != NULL)
*user_exists = True; /* Only set false on a very specific error. */
/*
* Get the machine account password for our primary domain
*/
- if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL))
+ if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time))
{
- return False;
+ DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup()));
+ return False;
}
/*
while (!connected_ok &&
next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) {
if(strequal(remote_machine, "*")) {
- connected_ok = find_connect_pdc(&cli, trust_passwd);
+ connected_ok = find_connect_pdc(&cli, trust_passwd, last_change_time);
} else {
connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd);
}