diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smb.h | 29 | ||||
-rw-r--r-- | source3/smbd/conn.c | 10 | ||||
-rw-r--r-- | source3/smbd/service.c | 84 | ||||
-rw-r--r-- | source3/smbd/uid.c | 88 |
4 files changed, 105 insertions, 106 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 24cdde30d1..37a2833d97 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -421,7 +421,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); @@ -434,19 +435,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 */ @@ -466,8 +475,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; |