summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/auth/auth_ntlmssp.c2
-rw-r--r--source3/auth/auth_rhosts.c68
-rw-r--r--source3/auth/auth_util.c73
-rw-r--r--source3/include/smb.h2
-rw-r--r--source3/lib/username.c57
-rw-r--r--source3/rpc_server/srv_netlog_nt.c2
-rw-r--r--source3/rpc_server/srv_samr_nt.c20
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c6
-rw-r--r--source3/smbd/password.c59
-rw-r--r--source3/smbd/posix_acls.c2
-rw-r--r--source3/smbd/service.c22
-rw-r--r--source3/smbd/sesssetup.c60
-rw-r--r--source3/smbd/uid.c4
13 files changed, 224 insertions, 153 deletions
diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c
index 43542b2474..d32d248296 100644
--- a/source3/auth/auth_ntlmssp.c
+++ b/source3/auth/auth_ntlmssp.c
@@ -131,7 +131,7 @@ NTSTATUS auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
}
NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state,
- DATA_BLOB request, DATA_BLOB *reply)
+ const DATA_BLOB request, DATA_BLOB *reply)
{
return ntlmssp_server_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
}
diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c
index 4ed0e6bbc4..5451f7d930 100644
--- a/source3/auth/auth_rhosts.c
+++ b/source3/auth/auth_rhosts.c
@@ -129,23 +129,19 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e
return False;
}
-
/****************************************************************************
check for a possible hosts equiv or rhosts entry for the user
****************************************************************************/
-static BOOL check_hosts_equiv(struct passwd *pass)
+static BOOL check_hosts_equiv(SAM_ACCOUNT *account)
{
char *fname = NULL;
- if (!pass)
- return(False);
-
fname = lp_hosts_equiv();
/* note: don't allow hosts.equiv on root */
- if (fname && *fname && (pass->pw_uid != 0)) {
- if (check_user_equiv(pass->pw_name,client_name(),fname))
+ if (IS_SAM_UNIX_USER(account) && fname && *fname && (pdb_get_uid(account) != 0)) {
+ if (check_user_equiv(pdb_get_username(account),client_name(),fname))
return(True);
}
@@ -164,15 +160,18 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
- struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
-
- if (pass) {
- if (check_hosts_equiv(pass)) {
- nt_status = NT_STATUS_OK;
- make_server_info_pw(server_info, pass);
- }
+ SAM_ACCOUNT *account = NULL;
+ if (!NT_STATUS_IS_OK(nt_status =
+ auth_get_sam_account(user_info->internal_username.str,
+ &account))) {
+ return nt_status;
+ }
+
+ if (check_hosts_equiv(account)) {
+ nt_status = make_server_info_sam(server_info, account);
} else {
- nt_status = NT_STATUS_NO_SUCH_USER;
+ pdb_free_sam(&account);
+ nt_status = NT_STATUS_LOGON_FAILURE;
}
return nt_status;
@@ -186,6 +185,7 @@ NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* par
}
(*auth_method)->auth = check_hostsequiv_security;
+ (*auth_method)->name = "hostsequiv";
return NT_STATUS_OK;
}
@@ -201,24 +201,33 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
- struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
+ SAM_ACCOUNT *account = NULL;
pstring rhostsfile;
+ const char *home;
- if (pass) {
- char *home = pass->pw_dir;
- if (home) {
- slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
- become_root();
- if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) {
- nt_status = NT_STATUS_OK;
- make_server_info_pw(server_info, pass);
- }
- unbecome_root();
- }
- } else {
- nt_status = NT_STATUS_NO_SUCH_USER;
+ if (!NT_STATUS_IS_OK(nt_status =
+ auth_get_sam_account(user_info->internal_username.str,
+ &account))) {
+ return nt_status;
}
+ home = pdb_get_unix_homedir(account);
+
+ if (home) {
+ slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
+ become_root();
+ if (check_user_equiv(pdb_get_username(account),client_name(),rhostsfile)) {
+ nt_status = make_server_info_sam(server_info, account);
+ } else {
+ pdb_free_sam(&account);
+ nt_status = NT_STATUS_LOGON_FAILURE;
+ }
+ unbecome_root();
+ } else {
+ pdb_free_sam(&account);
+ nt_status = NT_STATUS_LOGON_FAILURE;
+ }
+
return nt_status;
}
@@ -230,5 +239,6 @@ NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param,
}
(*auth_method)->auth = check_rhosts_security;
+ (*auth_method)->name = "rhosts";
return NT_STATUS_OK;
}
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index bbe0c7cf43..7d85153bd0 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -78,6 +78,36 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli
}
/****************************************************************************
+ Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from
+ unix info.
+****************************************************************************/
+
+NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account)
+{
+ BOOL pdb_ret;
+ NTSTATUS nt_status;
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) {
+ return nt_status;
+ }
+
+ become_root();
+ pdb_ret = pdb_getsampwnam(*account, user);
+ unbecome_root();
+
+ if (!pdb_ret) {
+
+ struct passwd *pass = Get_Pwnam(user);
+ if (!pass)
+ return NT_STATUS_NO_SUCH_USER;
+
+ if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) {
+ return nt_status;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Create an auth_usersupplied_data structure
****************************************************************************/
@@ -641,34 +671,25 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups,
* of groups.
******************************************************************************/
-static NTSTATUS get_user_groups_from_local_sam(const DOM_SID *user_sid,
+static NTSTATUS get_user_groups_from_local_sam(SAM_ACCOUNT *sampass,
int *n_groups, DOM_SID **groups, gid_t **unix_groups)
{
uid_t uid;
- enum SID_NAME_USE snu;
- fstring str;
+ gid_t gid;
int n_unix_groups;
int i;
struct passwd *usr;
-
+
*n_groups = 0;
*groups = NULL;
-
- if (!sid_to_uid(user_sid, &uid, &snu)) {
- DEBUG(2, ("get_user_groups_from_local_sam: Failed to convert user SID %s to a uid!\n",
- sid_to_string(str, user_sid)));
- /* This might be a non-unix account */
- return NT_STATUS_OK;
- }
- /*
- * This is _essential_ to prevent occasional segfaults when
- * winbind can't find uid -> username mapping
- */
- if (!(usr = getpwuid_alloc(uid))) {
- DEBUG(0, ("Couldn't find passdb structure for UID = %d ! Aborting.\n", uid));
+ if (!IS_SAM_UNIX_USER(sampass)) {
+ DEBUG(1, ("user %s does not have a unix identity!\n", pdb_get_username(sampass)));
return NT_STATUS_NO_SUCH_USER;
- };
+ }
+
+ uid = pdb_get_uid(sampass);
+ gid = pdb_get_gid(sampass);
n_unix_groups = groups_max();
if ((*unix_groups = malloc( sizeof(gid_t) * n_unix_groups ) ) == NULL) {
@@ -677,7 +698,7 @@ static NTSTATUS get_user_groups_from_local_sam(const DOM_SID *user_sid,
return NT_STATUS_NO_MEMORY;
}
- if (sys_getgrouplist(usr->pw_name, usr->pw_gid, *unix_groups, &n_unix_groups) == -1) {
+ if (sys_getgrouplist(pdb_get_username(sampass), gid, *unix_groups, &n_unix_groups) == -1) {
gid_t *groups_tmp;
groups_tmp = Realloc(*unix_groups, sizeof(gid_t) * n_unix_groups);
if (!groups_tmp) {
@@ -687,7 +708,7 @@ static NTSTATUS get_user_groups_from_local_sam(const DOM_SID *user_sid,
}
*unix_groups = groups_tmp;
- if (sys_getgrouplist(usr->pw_name, usr->pw_gid, *unix_groups, &n_unix_groups) == -1) {
+ if (sys_getgrouplist(pdb_get_username(sampass), gid, *unix_groups, &n_unix_groups) == -1) {
DEBUG(0, ("get_user_groups_from_local_sam: failed to get the unix group list\n"));
SAFE_FREE(*unix_groups);
passwd_free(&usr);
@@ -695,9 +716,7 @@ static NTSTATUS get_user_groups_from_local_sam(const DOM_SID *user_sid,
}
}
- debug_unix_user_token(DBGC_CLASS, 5, usr->pw_uid, usr->pw_gid, n_unix_groups, *unix_groups);
-
- passwd_free(&usr);
+ debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
if (n_unix_groups > 0) {
*groups = malloc(sizeof(DOM_SID) * n_unix_groups);
@@ -763,7 +782,7 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
}
if (!NT_STATUS_IS_OK(nt_status
- = get_user_groups_from_local_sam(pdb_get_user_sid(sampass),
+ = get_user_groups_from_local_sam(sampass,
&n_groupSIDs, &groupSIDs, &unix_groups)))
{
DEBUG(4,("get_user_groups_from_local_sam failed\n"));
@@ -838,7 +857,9 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
nt_status = make_server_info_sam(server_info, sampass);
- (*server_info)->guest = True;
+ if (NT_STATUS_IS_OK(nt_status)) {
+ (*server_info)->guest = True;
+ }
return nt_status;
}
@@ -996,7 +1017,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
returned to the caller. */
if (!NT_STATUS_IS_OK(nt_status
- = get_user_groups_from_local_sam(&user_sid,
+ = get_user_groups_from_local_sam(sam_account,
&n_lgroupSIDs,
&lgroupSIDs,
&unix_groups)))
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 279b79eace..f96a19954a 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1642,6 +1642,8 @@ typedef struct user_struct
TDB key string */
int homes_snum;
+ struct auth_serversupplied_info *server_info;
+
} user_struct;
diff --git a/source3/lib/username.c b/source3/lib/username.c
index b1c9ca0f08..b8f33494ee 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -169,7 +169,7 @@ BOOL map_username(char *user)
return False;
}
- if (strchr_m(dosname,'*') || user_in_list(user, (const char **)dosuserlist)) {
+ if (strchr_m(dosname,'*') || user_in_list(user, (const char **)dosuserlist, NULL, 0)) {
DEBUG(3,("Mapped user %s to %s\n",user,unixname));
mapped_user = True;
fstrcpy(last_from,user);
@@ -328,11 +328,27 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL
int num_groups;
int i;
gid_t *groups = NULL;
- gid_t gid;
+ gid_t gid, gid_low, gid_high;
BOOL ret = False;
*winbind_answered = False;
+ if ((gid = nametogid(gname)) == (gid_t)-1) {
+ DEBUG(0,("user_in_winbind_group_list: nametogid for group %s failed.\n",
+ gname ));
+ goto err;
+ }
+
+ if (!lp_winbind_gid(&gid_low, &gid_high)) {
+ DEBUG(4, ("winbind gid range not configured, therefore %s cannot be a winbind group\n", gname));
+ goto err;
+ }
+
+ if (gid < gid_low || gid > gid_high) {
+ DEBUG(4, ("group %s is not a winbind group\n", gname));
+ goto err;
+ }
+
/*
* Get the gid's that this user belongs to.
*/
@@ -361,12 +377,6 @@ failed with error %s\n", strerror(errno) ));
* to a gid_t via either winbind or the local UNIX lookup and do the comparison.
*/
- if ((gid = nametogid(gname)) == (gid_t)-1) {
- DEBUG(0,("user_in_winbind_group_list: winbind_lookup_name for group %s failed.\n",
- gname ));
- goto err;
- }
-
for (i = 0; i < num_groups; i++) {
if (gid == groups[i]) {
ret = True;
@@ -389,7 +399,7 @@ failed with error %s\n", strerror(errno) ));
Check if a user is in a UNIX group.
****************************************************************************/
-static BOOL user_in_unix_group_list(const char *user,const char *gname)
+BOOL user_in_unix_group_list(const char *user,const char *gname)
{
struct passwd *pass = Get_Pwnam(user);
struct sys_userlist *user_list;
@@ -432,10 +442,27 @@ static BOOL user_in_unix_group_list(const char *user,const char *gname)
Check if a user is in a group list. Ask winbind first, then use UNIX.
****************************************************************************/
-BOOL user_in_group_list(const char *user, const char *gname)
+BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, size_t n_groups)
{
BOOL winbind_answered = False;
BOOL ret;
+ gid_t gid;
+ unsigned i;
+
+ gid = nametogid(gname);
+ if (gid == (gid_t)-1)
+ return False;
+
+ if (groups && n_groups > 0) {
+ for (i=0; i < n_groups; i++) {
+ if (groups[i] == gid) {
+ return True;
+ }
+ }
+ return False;
+ }
+
+ /* fallback if we don't yet have the group list */
ret = user_in_winbind_group_list(user, gname, &winbind_answered);
if (!winbind_answered)
@@ -451,7 +478,7 @@ BOOL user_in_group_list(const char *user, const char *gname)
and netgroup lists.
****************************************************************************/
-BOOL user_in_list(const char *user,const char **list)
+BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_groups)
{
if (!list || !*list)
return False;
@@ -480,7 +507,7 @@ BOOL user_in_list(const char *user,const char **list)
*/
if(user_in_netgroup_list(user, *list +1))
return True;
- if(user_in_group_list(user, *list +1))
+ if(user_in_group_list(user, *list +1, groups, n_groups))
return True;
} else if (**list == '+') {
@@ -488,7 +515,7 @@ BOOL user_in_list(const char *user,const char **list)
/*
* Search UNIX list followed by netgroup.
*/
- if(user_in_group_list(user, *list +2))
+ if(user_in_group_list(user, *list +2, groups, n_groups))
return True;
if(user_in_netgroup_list(user, *list +2))
return True;
@@ -499,7 +526,7 @@ BOOL user_in_list(const char *user,const char **list)
* Just search UNIX list.
*/
- if(user_in_group_list(user, *list +1))
+ if(user_in_group_list(user, *list +1, groups, n_groups))
return True;
}
@@ -511,7 +538,7 @@ BOOL user_in_list(const char *user,const char **list)
*/
if(user_in_netgroup_list(user, *list +2))
return True;
- if(user_in_group_list(user, *list +2))
+ if(user_in_group_list(user, *list +2, groups, n_groups))
return True;
} else {
/*
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index 8070cdd984..6182da53d9 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -668,7 +668,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
fstring group_sid_string;
uchar user_sess_key[16];
uchar netlogon_sess_key[16];
-
+
sampw = server_info->sam_account;
/* set up pointer indicating user/password failed to be found */
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 2896fd79e4..d766e9c19e 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -3427,7 +3427,7 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
fstrcpy(grp_name, grp->gr_name);
/* if the user is already in the group */
- if(user_in_group_list(pwd->pw_name, grp_name)) {
+ if(user_in_unix_group_list(pwd->pw_name, grp_name)) {
passwd_free(&pwd);
return NT_STATUS_MEMBER_IN_ALIAS;
}
@@ -3439,7 +3439,7 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
smb_add_user_group(grp_name, pwd->pw_name);
/* check if the user has been added then ... */
- if(!user_in_group_list(pwd->pw_name, grp_name)) {
+ if(!user_in_unix_group_list(pwd->pw_name, grp_name)) {
passwd_free(&pwd);
return NT_STATUS_MEMBER_NOT_IN_ALIAS; /* don't know what to reply else */
}
@@ -3485,7 +3485,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
if ((grp=getgrgid(map.gid)) == NULL)
return NT_STATUS_NO_SUCH_ALIAS;
- /* we need to copy the name otherwise it's overloaded in user_in_group_list */
+ /* we need to copy the name otherwise it's overloaded in user_in_unix_group_list */
fstrcpy(grp_name, grp->gr_name);
/* check if the user exists before trying to remove it from the group */
@@ -3497,7 +3497,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
}
/* if the user is not in the group */
- if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if(!user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_MEMBER_IN_ALIAS;
}
@@ -3505,7 +3505,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
/* check if the user has been removed then ... */
- if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if(user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_MEMBER_NOT_IN_ALIAS; /* don't know what to reply else */
}
@@ -3583,11 +3583,11 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
return NT_STATUS_NO_SUCH_GROUP;
}
- /* we need to copy the name otherwise it's overloaded in user_in_group_list */
+ /* we need to copy the name otherwise it's overloaded in user_in_unix_group_list */
fstrcpy(grp_name, grp->gr_name);
/* if the user is already in the group */
- if(user_in_group_list(pwd->pw_name, grp_name)) {
+ if(user_in_unix_group_list(pwd->pw_name, grp_name)) {
passwd_free(&pwd);
return NT_STATUS_MEMBER_IN_GROUP;
}
@@ -3601,7 +3601,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
smb_add_user_group(grp_name, pwd->pw_name);
/* check if the user has been added then ... */
- if(!user_in_group_list(pwd->pw_name, grp_name)) {
+ if(!user_in_unix_group_list(pwd->pw_name, grp_name)) {
passwd_free(&pwd);
return NT_STATUS_MEMBER_NOT_IN_GROUP; /* don't know what to reply else */
}
@@ -3662,7 +3662,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
}
/* if the user is not in the group */
- if (!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if (!user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_MEMBER_NOT_IN_GROUP;
}
@@ -3670,7 +3670,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
/* check if the user has been removed then ... */
- if (user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if (user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_ACCESS_DENIED; /* don't know what to reply else */
}
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 3605c1a24d..93566c2bb7 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -1606,7 +1606,7 @@ Can't find printer handle we created for printer %s\n", name ));
/* if the user is not root and not a printer admin, then fail */
if ( user.uid != 0
- && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
+ && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
{
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
@@ -1653,7 +1653,7 @@ Can't find printer handle we created for printer %s\n", name ));
/* check smb.conf parameters and the the sec_desc */
- if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
+ if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
DEBUG(3, ("access DENIED for printer open\n"));
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
@@ -8992,7 +8992,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
done:
if ( printer )
- free_a_printer(&printer, 2);
+ free_a_printer(&printer, 2);
return result;
}
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 4ce99e96bb..784c1525c8 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -62,11 +62,15 @@ void invalidate_vuid(uint16 vuid)
if (vuser == NULL)
return;
-
+
SAFE_FREE(vuser->homedir);
-
+ SAFE_FREE(vuser->unix_homedir);
+ SAFE_FREE(vuser->logon_script);
+
session_yield(vuser);
+ free_server_info(&vuser->server_info);
+
DLIST_REMOVE(validated_users, vuser);
/* clear the vuid from the 'cache' on each connection, and
@@ -93,11 +97,15 @@ void invalidate_all_vuids(void)
}
}
-/****************************************************************************
-register a uid/name pair as being valid and that a valid password
-has been given. vuid is biased by an offset. This allows us to
-tell random client vuid's (normally zero) from valid vuids.
-****************************************************************************/
+/**
+ * register that a valid login has been performed, establish 'session'.
+ * @param server_info The token returned from the authentication process.
+ * (now 'owned' by register_vuid)
+ *
+ * @return Newly allocated vuid, biased by an offset. (This allows us to
+ * tell random client vuid's (normally zero) from valid vuids.)
+ *
+ */
int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
{
@@ -136,6 +144,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
if (!IS_SAM_UNIX_USER(server_info->sam_account)) {
DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n"));
free(vuser);
+ free_server_info(&server_info);
return UID_FIELD_INVALID;
}
@@ -147,20 +156,24 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
free(vuser);
+ free_server_info(&server_info);
return UID_FIELD_INVALID;
}
}
vuser->guest = server_info->guest;
fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account));
- fstrcpy(vuser->user.smb_name, smb_name);
+
+ /* This is a potentially untrusted username */
+ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));
+
fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
{
/* Keep the homedir handy */
const char *homedir = pdb_get_homedir(server_info->sam_account);
- const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); /* should be optained by SMS */
+ const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
const char *logon_script = pdb_get_logon_script(server_info->sam_account);
if (homedir) {
vuser->homedir = smb_xstrdup(homedir);
@@ -188,10 +201,18 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
vuser->nt_user_token = dup_nt_token(server_info->ptok);
} else {
DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
- free(vuser);
+ free_server_info(&server_info);
+ SAFE_FREE(vuser->homedir);
+ SAFE_FREE(vuser->unix_homedir);
+ SAFE_FREE(vuser->logon_script);
+
+ SAFE_FREE(vuser);
return UID_FIELD_INVALID;
}
+ /* use this to keep tabs on all our info from the authentication */
+ vuser->server_info = server_info;
+
DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
next_vuid++;
@@ -246,7 +267,7 @@ void add_session_user(const char *user)
/****************************************************************************
check if a username is valid
****************************************************************************/
-BOOL user_ok(const char *user,int snum)
+BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
{
char **valid, **invalid;
BOOL ret;
@@ -257,7 +278,7 @@ BOOL user_ok(const char *user,int snum)
if (lp_invalid_users(snum)) {
str_list_copy(&invalid, lp_invalid_users(snum));
if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) {
- ret = !user_in_list(user, (const char **)invalid);
+ ret = !user_in_list(user, (const char **)invalid, groups, n_groups);
}
}
if (invalid)
@@ -266,7 +287,7 @@ BOOL user_ok(const char *user,int snum)
if (ret && lp_valid_users(snum)) {
str_list_copy(&valid, lp_valid_users(snum));
if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) {
- ret = user_in_list(user, (const char **)valid);
+ ret = user_in_list(user, (const char **)valid, groups, n_groups);
}
}
if (valid)
@@ -275,7 +296,7 @@ BOOL user_ok(const char *user,int snum)
if (ret && lp_onlyuser(snum)) {
char **user_list = str_list_make (lp_username(snum), NULL);
if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) {
- ret = user_in_list(user, (const char **)user_list);
+ ret = user_in_list(user, (const char **)user_list, groups, n_groups);
}
if (user_list) str_list_free (&user_list);
}
@@ -294,7 +315,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
setnetgrent(group);
while (getnetgrent(&host, &user, &domain)) {
if (user) {
- if (user_ok(user, snum) &&
+ if (user_ok(user, snum, NULL, 0) &&
password_ok(user,password)) {
endnetgrent();
return(user);
@@ -349,7 +370,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
while (*member) {
static fstring name;
fstrcpy(name,member);
- if (user_ok(name,snum) &&
+ if (user_ok(name,snum, NULL, 0) &&
password_ok(name,password)) {
endgrent();
return(&name[0]);
@@ -408,7 +429,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
auser = strtok(NULL,LIST_SEP)) {
fstring user2;
fstrcpy(user2,auser);
- if (!user_ok(user2,snum))
+ if (!user_ok(user2,snum, NULL, 0))
continue;
if (password_ok(user2,password)) {
@@ -443,7 +464,7 @@ and given password ok (%s)\n", user));
} else {
fstring user2;
fstrcpy(user2,auser);
- if (user_ok(user2,snum) && password_ok(user2,password)) {
+ if (user_ok(user2,snum, NULL, 0) && password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("authorise_login: ACCEPTED: user list username \
@@ -468,7 +489,7 @@ and given password ok (%s)\n", user));
*guest = True;
}
- if (ok && !user_ok(user,snum)) {
+ if (ok && !user_ok(user, snum, NULL, 0)) {
DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
ok = False;
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index ee8a4430e1..93a57925f1 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -573,7 +573,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
* not uids/gids.
*/
- return user_in_group_list(u_name, g_name );
+ return user_in_group_list(u_name, g_name, NULL, 0);
}
/****************************************************************************
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 2a41a6db1c..1c7e4017b0 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -258,7 +258,7 @@ static NTSTATUS share_sanity_checks(int snum, pstring dev)
/****************************************************************************
readonly share?
****************************************************************************/
-static void set_read_only(connection_struct *conn)
+static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups)
{
char **list;
char *service = lp_servicename(conn->service);
@@ -271,7 +271,7 @@ static void set_read_only(connection_struct *conn)
if (!str_list_substitute(list, "%S", service)) {
DEBUG(0, ("ERROR: read list substitution failed\n"));
}
- if (user_in_list(conn->user, (const char **)list))
+ if (user_in_list(conn->user, (const char **)list, groups, n_groups))
conn->read_only = True;
str_list_free(&list);
}
@@ -281,7 +281,7 @@ static void set_read_only(connection_struct *conn)
if (!str_list_substitute(list, "%S", service)) {
DEBUG(0, ("ERROR: write list substitution failed\n"));
}
- if (user_in_list(conn->user, (const char **)list))
+ if (user_in_list(conn->user, (const char **)list, groups, n_groups))
conn->read_only = False;
str_list_free(&list);
}
@@ -291,7 +291,7 @@ static void set_read_only(connection_struct *conn)
/****************************************************************************
admin user check
****************************************************************************/
-static void set_admin_user(connection_struct *conn)
+static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups)
{
/* admin user check */
@@ -299,7 +299,7 @@ static void set_admin_user(connection_struct *conn)
marked read_only. Changed as I don't think this is needed,
but old code left in case there is a problem here.
*/
- if (user_in_list(conn->user,lp_admin_users(conn->service))
+ if (user_in_list(conn->user,lp_admin_users(conn->service), groups, n_groups)
#if 0
&& !conn->read_only
#endif
@@ -364,14 +364,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
} else if (vuser) {
if (vuser->guest) {
if (!lp_guest_ok(snum)) {
- DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum)));
+ DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
conn_free(conn);
*status = NT_STATUS_ACCESS_DENIED;
return NULL;
}
} else {
- if (!user_ok(vuser->user.unix_name, snum)) {
- DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum)));
+ if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
+ DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
conn_free(conn);
*status = NT_STATUS_ACCESS_DENIED;
return NULL;
@@ -427,9 +427,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
string_set(&conn->user,user);
conn->nt_user_token = NULL;
- set_read_only(conn);
+ set_read_only(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
- set_admin_user(conn);
+ set_admin_user(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
/*
* If force user is true, then store the
@@ -499,7 +499,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
* Otherwise, the meaning of the '+' would be ignored.
*/
if (conn->force_user && user_must_be_member) {
- if (user_in_group_list( user, gname )) {
+ if (user_in_group_list( user, gname, NULL, 0)) {
conn->gid = gid;
DEBUG(3,("Forced group %s for member %s\n",gname,user));
}
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index bb7d17be56..eafe805aba 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -148,6 +148,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB auth_data;
auth_serversupplied_info *server_info = NULL;
ADS_STRUCT *ads;
+ BOOL foreign = False;
if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
@@ -168,6 +169,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
+ data_blob_free(&auth_data);
+
DEBUG(3,("Ticket name is [%s]\n", client));
p = strchr_m(client, '@');
@@ -183,12 +186,20 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (!lp_allow_trusted_domains()) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- /* this gives a fully qualified user name (ie. with full realm).
- that leads to very long usernames, but what else can we do? */
- asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
- } else {
- user = strdup(client);
+ foreign = True;
+ }
+
+ /* this gives a fully qualified user name (ie. with full realm).
+ that leads to very long usernames, but what else can we do? */
+ asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
+
+ pw = Get_Pwnam(user);
+ if (!pw && !foreign) {
+ pw = Get_Pwnam(client);
+ SAFE_FREE(user);
+ user = smb_xstrdup(client);
}
+
ads_destroy(&ads);
/* setup the string used by %U */
@@ -196,19 +207,6 @@ static int reply_spnego_kerberos(connection_struct *conn,
reload_services(True);
- /* the password is good - let them in */
- pw = Get_Pwnam(user);
- if (!pw && !strstr(user, lp_winbind_separator())) {
- char *user2;
- /* try it with a winbind domain prefix */
- asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
- pw = Get_Pwnam(user2);
- if (pw) {
- free(user);
- user = user2;
- }
- }
-
if (!pw) {
DEBUG(1,("Username %s is invalid on this system\n",user));
return ERROR_NT(NT_STATUS_NO_SUCH_USER);
@@ -219,10 +217,10 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(ret);
}
+ /* register_vuid keeps the server info */
sess_vuid = register_vuid(server_info, user);
free(user);
- free_server_info(&server_info);
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
@@ -263,8 +261,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
if (NT_STATUS_IS_OK(nt_status)) {
int sess_vuid;
- sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */);
-
+ /* register_vuid keeps the server info */
+ sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user);
+ (*auth_ntlmssp_state)->server_info = NULL;
+
if (sess_vuid == -1) {
nt_status = NT_STATUS_LOGON_FAILURE;
} else {
@@ -272,7 +272,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
- if ((*auth_ntlmssp_state)->server_info && (*auth_ntlmssp_state)->server_info->guest) {
+ if (server_info->guest) {
SSVAL(outbuf,smb_vwv2,1);
}
@@ -285,7 +285,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
data_blob_free(&response);
if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- auth_ntlmssp_end(&global_ntlmssp_state);
+ auth_ntlmssp_end(auth_ntlmssp_state);
}
return ret;
@@ -463,7 +463,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
extern BOOL global_encrypted_passwords_negotiated;
extern BOOL global_spnego_negotiated;
extern int Protocol;
- extern userdom_struct current_user_info;
extern int max_send;
auth_usersupplied_info *user_info = NULL;
@@ -584,13 +583,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
domain,native_os,native_lanman));
}
- /* don't allow for weird usernames or domains */
- alpha_strcpy(user, user, ". _-$", sizeof(user));
- alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
- if (strstr(user, "..") || strstr(domain,"..")) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
-
DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
if (*user) {
@@ -609,7 +601,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
fstrcpy(sub_user, lp_guestaccount());
}
- fstrcpy(current_user_info.smb_name,sub_user);
+ sub_set_smb_name(sub_user);
reload_services(True);
@@ -692,15 +684,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* register the name and uid as being validated, so further connections
to a uid can get through without a password, on the same VC */
+ /* register_vuid keeps the server info */
sess_vuid = register_vuid(server_info, sub_user);
-
- free_server_info(&server_info);
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
-
SSVAL(outbuf,smb_uid,sess_vuid);
SSVAL(inbuf,smb_uid,sess_vuid);
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 7c0d3805e7..6ac3528b1a 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -60,7 +60,7 @@ BOOL change_to_guest(void)
static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
{
- int i;
+ unsigned i;
for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++)
if (conn->vuid_cache.list[i] == vuser->vuid)
return(True);
@@ -70,7 +70,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
return False;
}
- if (!user_ok(vuser->user.unix_name,snum))
+ if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups))
return(False);
if (!share_access_check(conn, snum, vuser, conn->read_only ? FILE_READ_DATA : FILE_WRITE_DATA)) {