Fix bug #1254 - write list not working under share-level security
authorJeremy Allison <jra@samba.org>
Thu, 4 Dec 2008 19:20:57 +0000 (11:20 -0800)
committerJeremy Allison <jra@samba.org>
Thu, 4 Dec 2008 19:20:57 +0000 (11:20 -0800)
A somewhat more elegant fix than I could use for 3.2.x or 3.0.x.
Turns out the only part of check_user_ok() that needs to change
for share level security is the VUID cache pieces, so I can just
always use check_user_ok() for all lp_security() cases.
Jeremy

source3/auth/auth_util.c
source3/include/proto.h
source3/smbd/share_access.c
source3/smbd/uid.c

index 9220df01c001ea7b8a9e4e3f6c0448f4b7653214..d2a8591ae61e9e97dadc3877dd86b21997f0edad 100644 (file)
@@ -1294,7 +1294,7 @@ NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
 
 
 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
-                                                auth_serversupplied_info *src)
+                                                const auth_serversupplied_info *src)
 {
        auth_serversupplied_info *dst;
 
index 63fe4d47c54ee1a8012b08daf20de706f6998a05..89b443e9db965aac72e42cf83c215f8e54580b05 100644 (file)
@@ -123,7 +123,7 @@ NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
                                       bool is_guest,
                                       struct auth_serversupplied_info **presult);
 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
-                                                auth_serversupplied_info *src);
+                                                const auth_serversupplied_info *src);
 bool init_guest_info(void);
 bool server_info_set_session_key(struct auth_serversupplied_info *info,
                                 DATA_BLOB session_key);
@@ -8462,10 +8462,10 @@ bool token_contains_name_in_list(const char *username,
                                 const struct nt_user_token *token,
                                 const char **list);
 bool user_ok_token(const char *username, const char *domain,
-                  struct nt_user_token *token, int snum);
+                  const struct nt_user_token *token, int snum);
 bool is_share_read_only_for_token(const char *username,
                                  const char *domain,
-                                 struct nt_user_token *token,
+                                 const struct nt_user_token *token,
                                  connection_struct *conn);
 
 /* The following definitions come from smbd/srvstr.c  */
index 9dbacc2998366f3756188d54d67ffa8e93c71b2f..c72251b5a7761367b4f1cf8a726ca5741b2ca6cc 100644 (file)
@@ -192,7 +192,7 @@ bool token_contains_name_in_list(const char *username,
  */
 
 bool user_ok_token(const char *username, const char *domain,
-                  struct nt_user_token *token, int snum)
+                  const struct nt_user_token *token, int snum)
 {
        if (lp_invalid_users(snum) != NULL) {
                if (token_contains_name_in_list(username, domain,
@@ -252,7 +252,7 @@ bool user_ok_token(const char *username, const char *domain,
 
 bool is_share_read_only_for_token(const char *username,
                                  const char *domain,
-                                 struct nt_user_token *token,
+                                 const struct nt_user_token *token,
                                  connection_struct *conn)
 {
        int snum = SNUM(conn);
index ca7df264e2fb6f719fa77a57991cb8302b01fb13..5a4b8a52e791bb8a65a802bb765bba72b13c31fb 100644 (file)
@@ -61,22 +61,27 @@ bool change_to_guest(void)
  later code can then mess with.
 ********************************************************************/
 
-static bool check_user_ok(connection_struct *conn, uint16_t vuid,
-                         struct auth_serversupplied_info *server_info,
-                         int snum)
+static bool check_user_ok(connection_struct *conn,
+                       uint16_t vuid,
+                       const struct auth_serversupplied_info *server_info,
+                       int snum)
 {
+       bool valid_vuid = (vuid != UID_FIELD_INVALID);
        unsigned int i;
-       struct vuid_cache_entry *ent = NULL;
        bool readonly_share;
        bool admin_user;
 
-       for (i=0; i<VUID_CACHE_SIZE; i++) {
-               ent = &conn->vuid_cache.array[i];
-               if (ent->vuid == vuid) {
-                       conn->server_info = ent->server_info;
-                       conn->read_only = ent->read_only;
-                       conn->admin_user = ent->admin_user;
-                       return(True);
+       if (valid_vuid) {
+               struct vuid_cache_entry *ent;
+
+               for (i=0; i<VUID_CACHE_SIZE; i++) {
+                       ent = &conn->vuid_cache.array[i];
+                       if (ent->vuid == vuid) {
+                               conn->server_info = ent->server_info;
+                               conn->read_only = ent->read_only;
+                               conn->admin_user = ent->admin_user;
+                               return(True);
+                       }
                }
        }
 
@@ -112,33 +117,36 @@ static bool check_user_ok(connection_struct *conn, uint16_t vuid,
                pdb_get_domain(server_info->sam_account),
                NULL, server_info->ptok, lp_admin_users(snum));
 
-       ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry];
+       if (valid_vuid) {
+               struct vuid_cache_entry *ent =
+                       &conn->vuid_cache.array[conn->vuid_cache.next_entry];
 
-       conn->vuid_cache.next_entry =
-               (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
+               conn->vuid_cache.next_entry =
+                       (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
 
-       TALLOC_FREE(ent->server_info);
+               TALLOC_FREE(ent->server_info);
 
-       /*
-        * If force_user was set, all server_info's are based on the same
-        * username-based faked one.
-        */
+               /*
+                * If force_user was set, all server_info's are based on the same
+                * username-based faked one.
+                */
 
-       ent->server_info = copy_serverinfo(
-               conn, conn->force_user ? conn->server_info : server_info);
+               ent->server_info = copy_serverinfo(
+                       conn, conn->force_user ? conn->server_info : server_info);
 
-       if (ent->server_info == NULL) {
-               ent->vuid = UID_FIELD_INVALID;
-               return false;
-       }
+               if (ent->server_info == NULL) {
+                       ent->vuid = UID_FIELD_INVALID;
+                       return false;
+               }
 
-       ent->vuid = vuid;
-       ent->read_only = readonly_share;
-       ent->admin_user = admin_user;
+               ent->vuid = vuid;
+               ent->read_only = readonly_share;
+               ent->admin_user = admin_user;
+               conn->server_info = ent->server_info;
+       }
 
-       conn->read_only = ent->read_only;
-       conn->admin_user = ent->admin_user;
-       conn->server_info = ent->server_info;
+       conn->read_only = readonly_share;
+       conn->admin_user = admin_user;
 
        return(True);
 }
@@ -172,6 +180,7 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
 
 bool change_to_user(connection_struct *conn, uint16 vuid)
 {
+       const struct auth_serversupplied_info *server_info = NULL;
        user_struct *vuser = get_valid_user_struct(vuid);
        int snum;
        gid_t gid;
@@ -207,13 +216,15 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
 
        snum = SNUM(conn);
 
-       if ((vuser) && !check_user_ok(conn, vuid, vuser->server_info, snum)) {
+       server_info = vuser ? vuser->server_info : conn->server_info;
+
+       if (!check_user_ok(conn, vuid, server_info, snum)) {
                DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
                         "not permitted access to share %s.\n",
-                        vuser->server_info->sanitized_username,
-                        vuser->server_info->unix_name, vuid,
+                        server_info->sanitized_username,
+                        server_info->unix_name, vuid,
                         lp_servicename(snum)));
-               return False;
+               return false;
        }
 
        /*