summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2004-02-13 19:05:27 +0000
committerJeremy Allison <jra@samba.org>2004-02-13 19:05:27 +0000
commit8b9cdc96b4886e415eccf0a8aa57adff637570fe (patch)
tree0ca71358b84d12f4e406a3253a7f1927bf07f353
parent608c737cdf45ff2b6e61de97f6f19dde8fea21d2 (diff)
downloadsamba-8b9cdc96b4886e415eccf0a8aa57adff637570fe.tar.gz
samba-8b9cdc96b4886e415eccf0a8aa57adff637570fe.tar.bz2
samba-8b9cdc96b4886e415eccf0a8aa57adff637570fe.zip
Fixup the 'multiple-vuids' bugs.
Jeremy. (This used to be commit a7d4a6d1167f7657113148cdf68ea3c491b51b14)
-rw-r--r--source3/include/smb.h29
-rw-r--r--source3/smbd/conn.c10
-rw-r--r--source3/smbd/service.c84
-rw-r--r--source3/smbd/uid.c88
4 files changed, 105 insertions, 106 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 7ffbe8f720..342c010124 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -423,7 +423,8 @@ typedef struct files_struct
#include "sysquotas.h"
/* used to hold an arbitrary blob of data */
-typedef struct data_blob {
+typedef struct data_blob
+{
uint8 *data;
size_t length;
void (*free)(struct data_blob *data_blob);
@@ -436,19 +437,27 @@ typedef struct data_blob {
typedef struct
{
- time_t modify_time;
- time_t status_time;
+ time_t modify_time;
+ time_t status_time;
} dir_status_struct;
-struct vuid_cache {
- unsigned int entries;
- uint16 list[VUID_CACHE_SIZE];
+struct vuid_cache_entry
+{
+ uint16 vuid;
+ BOOL read_only;
+ BOOL admin_user;
+};
+
+struct vuid_cache
+{
+ unsigned int entries;
+ struct vuid_cache_entry array[VUID_CACHE_SIZE];
};
typedef struct
{
- char *name;
- BOOL is_wild;
+ char *name;
+ BOOL is_wild;
} name_compare_entry;
/* Include VFS stuff */
@@ -468,8 +477,8 @@ typedef struct connection_struct
void *dirptr;
BOOL printer;
BOOL ipc;
- BOOL read_only;
- BOOL admin_user;
+ BOOL read_only; /* Attributes for the current user of the share. */
+ BOOL admin_user; /* Attributes for the current user of the share. */
char *dirpath;
char *connectpath;
char *origpath;
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index 289b7d611d..9bac0acdb9 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -199,8 +199,9 @@ BOOL conn_idle_all(time_t t, int deadtime)
}
/****************************************************************************
-clear a vuid out of the validity cache, and as the 'owner' of a connection.
+ Clear a vuid out of the validity cache, and as the 'owner' of a connection.
****************************************************************************/
+
void conn_clear_vuid_cache(uint16 vuid)
{
connection_struct *conn;
@@ -212,8 +213,11 @@ void conn_clear_vuid_cache(uint16 vuid)
}
for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
- if (conn->vuid_cache.list[i] == vuid) {
- conn->vuid_cache.list[i] = UID_FIELD_INVALID;
+ if (conn->vuid_cache.array[i].vuid == vuid) {
+ struct vuid_cache_entry *ent = &conn->vuid_cache.array[i];
+ ent->vuid = UID_FIELD_INVALID;
+ ent->read_only = False;
+ ent->admin_user = False;
}
}
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index e5655bd9f4..78b610ae37 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -260,78 +260,6 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev)
}
/****************************************************************************
- readonly share?
-****************************************************************************/
-
-static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups)
-{
- char **list;
- const char *service = lp_servicename(conn->service);
- conn->read_only = lp_readonly(conn->service);
-
- if (!service)
- return;
-
- str_list_copy(&list, lp_readlist(conn->service));
- if (list) {
- if (!str_list_sub_basic(list, current_user_info.smb_name) ) {
- DEBUG(0, ("ERROR: read list substitution failed\n"));
- }
- if (!str_list_substitute(list, "%S", service)) {
- DEBUG(0, ("ERROR: read list service substitution failed\n"));
- }
- if (user_in_list(conn->user, (const char **)list, groups, n_groups))
- conn->read_only = True;
- str_list_free(&list);
- }
-
- str_list_copy(&list, lp_writelist(conn->service));
- if (list) {
- if (!str_list_sub_basic(list, current_user_info.smb_name) ) {
- DEBUG(0, ("ERROR: write list substitution failed\n"));
- }
- if (!str_list_substitute(list, "%S", service)) {
- DEBUG(0, ("ERROR: write list service substitution failed\n"));
- }
- if (user_in_list(conn->user, (const char **)list, groups, n_groups))
- conn->read_only = False;
- str_list_free(&list);
- }
-}
-
-/****************************************************************************
- admin user check
-****************************************************************************/
-
-static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups)
-{
- /* admin user check */
-
- /* JRA - original code denied admin user if the share was
- 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), groups, n_groups)
-#if 0
- && !conn->read_only
-#endif
- ) {
- conn->admin_user = True;
- conn->force_user = True; /* Admin users are effectivly 'forced' */
- DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user));
- } else {
- conn->admin_user = False;
- }
-
-#if 0 /* This done later, for now */
- /* admin users always run as uid=0 */
- if (conn->admin_user) {
- conn->uid = 0;
- }
-#endif
-}
-
-/****************************************************************************
Make a connection, given the snum to connect to, and the vuser of the
connecting user if appropriate.
****************************************************************************/
@@ -443,10 +371,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
string_set(&conn->dirpath,"");
string_set(&conn->user,user);
conn->nt_user_token = NULL;
-
- set_read_only(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
-
- set_admin_user(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
+
+ conn->read_only = lp_readonly(conn->service);
+ conn->admin_user = False;
/*
* If force user is true, then store the
@@ -478,11 +405,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
}
}
- /* admin users always run as uid=0 */
- if (conn->admin_user) {
- conn->uid = 0;
- }
-
#ifdef HAVE_GETGRNAM
/*
* If force group is true, then override
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index f3d9004dd9..3859298055 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -54,33 +54,97 @@ BOOL change_to_guest(void)
return True;
}
+/****************************************************************************
+ Readonly share for this user ?
+****************************************************************************/
+
+static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser)
+{
+ char **list;
+ const char *service = lp_servicename(conn->service);
+ BOOL read_only_ret = lp_readonly(conn->service);
+
+ if (!service)
+ return read_only_ret;
+
+ str_list_copy(&list, lp_readlist(conn->service));
+ if (list) {
+ if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
+ DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n"));
+ }
+ if (!str_list_substitute(list, "%S", service)) {
+ DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n"));
+ }
+ if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) {
+ read_only_ret = True;
+ }
+ str_list_free(&list);
+ }
+
+ str_list_copy(&list, lp_writelist(conn->service));
+ if (list) {
+ if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
+ DEBUG(0, ("is_share_read_only_for_user: ERROR: write list substitution failed\n"));
+ }
+ if (!str_list_substitute(list, "%S", service)) {
+ DEBUG(0, ("is_share_read_only_for_user: ERROR: write list service substitution failed\n"));
+ }
+ if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) {
+ read_only_ret = False;
+ }
+ str_list_free(&list);
+ }
+
+ DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user %s\n",
+ service, read_only_ret ? "read-only" : "read-write", vuser->user.unix_name ));
+
+ return read_only_ret;
+}
+
/*******************************************************************
Check if a username is OK.
********************************************************************/
static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
{
- unsigned i;
- for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++)
- if (conn->vuid_cache.list[i] == vuser->vuid)
+ unsigned int i;
+ struct vuid_cache_entry *ent = NULL;
+ BOOL readonly_share;
+
+ for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
+ if (conn->vuid_cache.array[i].vuid == vuser->vuid) {
+ ent = &conn->vuid_cache.array[i];
+ conn->read_only = ent->read_only;
+ conn->admin_user = ent->admin_user;
return(True);
-
- if ((conn->force_user || conn->force_group)
- && (conn->vuid != vuser->vuid)) {
- return False;
+ }
}
-
+
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)) {
+ readonly_share = is_share_read_only_for_user(conn, vuser);
+
+ if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) {
return False;
}
i = conn->vuid_cache.entries % VUID_CACHE_SIZE;
- conn->vuid_cache.list[i] = vuser->vuid;
+ if (conn->vuid_cache.entries < VUID_CACHE_SIZE)
+ conn->vuid_cache.entries++;
+
+ ent = &conn->vuid_cache.array[i];
+ ent->vuid = vuser->vuid;
+ ent->read_only = readonly_share;
+
+ if (user_in_list(vuser->user.unix_name ,lp_admin_users(conn->service), vuser->groups, vuser->n_groups)) {
+ ent->admin_user = True;
+ } else {
+ ent->admin_user = False;
+ }
- conn->vuid_cache.entries++;
+ conn->read_only = ent->read_only;
+ conn->admin_user = ent->admin_user;
return(True);
}
@@ -132,7 +196,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
current_user.ngroups = conn->ngroups;
token = conn->nt_user_token;
} else if ((vuser) && check_user_ok(conn, vuser, snum)) {
- uid = vuser->uid;
+ uid = conn->admin_user ? 0 : vuser->uid;
gid = vuser->gid;
current_user.ngroups = vuser->n_groups;
current_user.groups = vuser->groups;