[SCM] Samba Shared Repository - branch v4-0-test updated

Karolin Seeger kseeger at samba.org
Mon Jan 14 12:45:04 MST 2013


The branch, v4-0-test has been updated
       via  15652ef selftest: show that Samba honours "write list" and valid users
       via  eeab8bb Fixup the change_to_user_by_session() case as called from become_user_by_session()
       via  456d4eb Move create_share_access_mask() from smbd/service.c to smbd/uid.c
       via  2c16104 Fix bug #9518 - conn->share_access appears not be be reset between users.
       via  a6a7041 Factor code out of check_user_ok() into a call to check_user_share_access().
       via  57aa765 Initialize stack variables. Prelude to factoring out calls to check_user_share_access().
       via  c1292fa Add check_user_share_access()
       via  c03fd9c Correctly setup the conn->share_access based on the current user token.
       via  bb7cdda Add parallel cache for share_access entries, one per connection struct.
       via  4fa8368 Change API for create_share_access_mask() - remove conn struct.
       via  ced2c1d Change API for create_share_access_mask() to pass in the token.
       via  3016cff Fix API for create_share_access_mask().
       via  76b214f Remove static from create_share_access_mask().
       via  ff2e3e2 Remove unneeded variable "const struct auth_session_info *session_info"
       via  c261e70 Remove dead code now vuser can no longer be NULL.
       via  7fe1f1f Remove the second set of {} braces, no longer needed. (cherry picked from commit ed0a34d163f777b2a0d4a2b358b7fb1b170d7686)
       via  b6c5860 Remove one set of enclosing {} braces, no longer needed.
       via  8dcf29e Move the definition of struct vuid_cache_entry *ent outside blocks.
       via  9b1cc0b Start to tidy-up check_user_ok().
      from  46d52b3 s3:smb2_negprot: set the 'remote_proto' value (bug #9499)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit 15652efca8644c03a48e258473fe5b58168df333
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Dec 20 23:05:55 2012 +1100

    selftest: show that Samba honours "write list" and valid users
    
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    The last 19 patches address bug #9518 - conn->share_access appears not be be
    reset between users.
    
    Autobuild-User(v4-0-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-0-test): Mon Jan 14 20:44:40 CET 2013 on sn-devel-104

commit eeab8bb5021fd5296e776a52747bc36514fcaf2a
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 11 11:14:48 2013 -0800

    Fixup the change_to_user_by_session() case as called from become_user_by_session()
    
    Use inside source3/printing/nt_printing.c:get_correct_cversion().
    
    Allow check_user_ok() to be called with vuid==UID_FIELD_INVALID.
    All this should do is throw away one entry in the vuid cache.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 456d4eb823011938ccda3261b2af8f7c02cc58ed
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 11 11:12:15 2013 -0800

    Move create_share_access_mask() from smbd/service.c to smbd/uid.c
    
    Make it static. Only called from uid.c now.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 2c161048c4daa88341e890ae9aaa92d7275433d5
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 15:15:59 2013 -0800

    Fix bug #9518 - conn->share_access appears not be be reset between users.
    
    Ensure make_connection_snum() uses the same logic as check_user_ok()
    to decide if a user can access a share.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit a6a70415a70bfcdd4c1189fd8fb157d4b923d868
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 15:13:53 2013 -0800

    Factor code out of check_user_ok() into a call to check_user_share_access().
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 57aa7658d7475c311942668a72b6cb1d60f002f8
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 11:05:03 2013 -0800

    Initialize stack variables. Prelude to factoring out calls to check_user_share_access().
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit c1292fa4b0f8f0297d8831e24eed7a7414645060
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 11 11:01:25 2013 -0800

    Add check_user_share_access()
    
    This factors out the share security and read_only flag
    setting code so this can be called from both make_connection_snum()
    as well as check_user_ok(). Gives a consistent share security
    check function.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit c03fd9c96b1d0b1a8f491daaf192293a666fd9d4
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 15:06:35 2013 -0800

    Correctly setup the conn->share_access based on the current user token.
    
    Also use this to set conn->read_only. Cache the share_access
    so we only evaluate this once per new user access on this share.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit bb7cdda75333f9ea49601f81047e6a1b94d890c2
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 11 10:47:56 2013 -0800

    Add parallel cache for share_access entries, one per connection struct.
    
    Needed as we cannot change the VFS ABI for 4.0.x, but need to add the
    equivalent of 'uint32_t share_access' to the struct vuid_cache referenced
    in connection_struct.
    
    Exports 2 accessor functions - lifetime managed by talloc on the conn
    struct list.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 4fa8368981d6275a9863f3129ac1b80d6f3b277c
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 15:04:26 2013 -0800

    Change API for create_share_access_mask() - remove conn struct.
    
    Eventually this will be indepentent of conn, just pass in the
    readonly flag.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit ced2c1db806d9281bac566385d326b6642756f49
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 4 12:01:17 2013 -0800

    Change API for create_share_access_mask() to pass in the token.
    
    Don't automatically use the one from conn->session_info->security_token.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 3016cff3f4ccdcbc74ba13b1e93bbcb813c4f19c
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Dec 21 09:45:03 2012 -0800

    Fix API for create_share_access_mask().
    
    Return the uint32_t share_access rather than directly
    changing the conn struct.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 33167c070c085b30569317666a3fca079d970321)

commit 76b214f24748a59bbc69f75c0259a81157febd5c
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Dec 21 09:35:31 2012 -0800

    Remove static from create_share_access_mask().
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 48187220ff47efe70616361fcef1a794aef765b4)

commit ff2e3e2453f326fc70f32f0c4271249ff351621a
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:55:09 2012 -0800

    Remove unneeded variable "const struct auth_session_info *session_info"
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 5a3cda176f5eecd65b289c74132b0126357c5ef0)

commit c261e70da1abeb5c3a4310e33d1b6ed01b31748d
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:54:07 2012 -0800

    Remove dead code now vuser can no longer be NULL.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit d35ba04e25eb3c396f791ea80c0ebb74543d4005)

commit 7fe1f1fe23810760a541e990c9a1883edbe64619
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:53:11 2012 -0800

    Remove the second set of {} braces, no longer needed. (cherry picked from commit ed0a34d163f777b2a0d4a2b358b7fb1b170d7686)

commit b6c5860c7ce827aea0e56eb8b977b307666550ba
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:52:27 2012 -0800

    Remove one set of enclosing {} braces, no longer needed.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit d64ea67c78a5b09559971ff6953cd67feb2b1ec2)

commit 8dcf29ea538837ff89c5f584457209e665cd1da9
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:51:55 2012 -0800

    Move the definition of struct vuid_cache_entry *ent outside blocks.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 092c9517acf5a4b11577ef7b5f1d645e5e463f6d)

commit 9b1cc0b67f358c8126fbd1d579d7bbde3dec6cf5
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 20 11:50:25 2012 -0800

    Start to tidy-up check_user_ok().
    
    Now we have removed "security=share" we cannot be
    called with vuid == UID_FIELD_INVALID.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit f0450e0d80c2ff56c4834b2f1271a7f84132ca5b)

-----------------------------------------------------------------------

Summary of changes:
 selftest/target/Samba3.pm                          |    7 +
 .../script/tests/test_smbclient_machine_auth.sh    |    4 +
 source3/script/tests/test_smbclient_s3.sh          |    8 +-
 source3/selftest/tests.py                          |    5 +
 source3/smbd/conn.c                                |   85 ++++++++-
 source3/smbd/proto.h                               |    9 +
 source3/smbd/service.c                             |   64 +-----
 source3/smbd/uid.c                                 |  225 ++++++++++++++------
 8 files changed, 282 insertions(+), 125 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 2037a2e..6c63413 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -956,6 +956,13 @@ sub provision($$$$$$)
 [ro-tmp]
 	path = $ro_shrdir
 	guest ok = yes
+[write-list-tmp]
+	path = $shrdir
+        read only = yes
+	write list = $unix_name
+[valid-users-tmp]
+	path = $shrdir
+	valid users = $unix_name
 [msdfs-share]
 	path = $msdfs_shrdir
 	msdfs root = yes
diff --git a/source3/script/tests/test_smbclient_machine_auth.sh b/source3/script/tests/test_smbclient_machine_auth.sh
index f67256d..a890d48 100755
--- a/source3/script/tests/test_smbclient_machine_auth.sh
+++ b/source3/script/tests/test_smbclient_machine_auth.sh
@@ -19,3 +19,7 @@ incdir=`dirname $0`/../../../testprogs/blackbox
 . $incdir/subunit.sh
 
 testit "smbclient //$SERVER/tmp" $SMBCLIENT //$SERVER/tmp --machine-pass -I $SERVER_IP -p 139 -c quit $ADDARGS
+
+# Testing these here helps because we know the machine account isn't already this user/group
+testit "smbclient //$SERVER/forceuser" $SMBCLIENT //$SERVER/tmp --machine-pass -I $SERVER_IP -p 139 -c quit $ADDARGS
+testit "smbclient //$SERVER/forcegroup" $SMBCLIENT //$SERVER/tmp --machine-pass -I $SERVER_IP -p 139 -c quit $ADDARGS
diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
index 3341c62..aa2ba77 100755
--- a/source3/script/tests/test_smbclient_s3.sh
+++ b/source3/script/tests/test_smbclient_s3.sh
@@ -211,7 +211,7 @@ mkdir a_test_dir
 quit
 EOF
 
-    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U% //$SERVER/ro-tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
+    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U% //$SERVER/$1" -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
     eval echo "$cmd"
     out=`eval $cmd`
     ret=$?
@@ -529,7 +529,11 @@ testit "creating a good symlink and deleting it by path" \
    failed=`expr $failed + 1`
 
 testit "writing into a read-only directory fails" \
-   test_read_only_dir || \
+   test_read_only_dir ro-tmp || \
+   failed=`expr $failed + 1`
+
+testit "writing into a read-only share fails" \
+   test_read_only_dir valid-users-tmp || \
    failed=`expr $failed + 1`
 
 testit "Reading a owner-only file fails" \
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 9b0527c..57c80f2 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -330,6 +330,11 @@ for t in tests:
     elif t == "smb2.durable-open" or t == "smb2.durable-v2-open":
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/durable -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER_IP/durable -U$USERNAME%$PASSWORD')
+    elif t == "base.rw1":
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/valid-users-tmp -U$USERNAME%$PASSWORD')
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/write-list-tmp -U$USERNAME%$PASSWORD')
+        plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     else:
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index bc5a03b..e6f81a9 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -24,6 +24,84 @@
 #include "smbd/globals.h"
 #include "lib/util/bitmap.h"
 
+/*******************************************************************
+ Static cache for storing per-user share access value. This really
+ belongs inside the vuid_cache.array struct but we can't change the
+ VFS ABI for 4.0.x. This is fixed in 4.1.x. JRA.
+********************************************************************/
+
+struct connection_share_access_list {
+	struct connection_share_access_list *next, *prev;
+	connection_struct *conn;
+	uint32_t vuid_cache_share_access_array[VUID_CACHE_SIZE];
+};
+
+static struct connection_share_access_list *conn_share_access_list;
+
+/*******************************************************************
+ Destructor function for per-user share access value.
+********************************************************************/
+
+static int free_csal_entry(struct connection_share_access_list *csal)
+{
+	DLIST_REMOVE(conn_share_access_list, csal);
+	return 0;
+}
+
+/*******************************************************************
+ Utility function to find a per-user share access value struct.
+********************************************************************/
+
+static struct connection_share_access_list *find_csal_entry(connection_struct *conn)
+{
+	struct connection_share_access_list *csal;
+
+	for (csal = conn_share_access_list; csal; csal = csal->next) {
+		if (csal->conn == conn) {
+			DLIST_PROMOTE(conn_share_access_list, csal);
+			return csal;
+		}
+	}
+	return NULL;
+}
+
+/*******************************************************************
+ Accessor functions for per-user share access value.
+ These are the only two functions exposed externally.
+********************************************************************/
+
+uint32_t get_connection_share_access_list_entry(connection_struct *conn,
+						unsigned int i)
+{
+	struct connection_share_access_list *csal =
+			find_csal_entry(conn);
+
+	if (csal == NULL) {
+		/*
+		 * This is a faked up connection struct
+		 * for internal purposes.
+		 * Return full access.
+		 */
+		return SEC_RIGHTS_FILE_ALL;
+	}
+
+	return csal->vuid_cache_share_access_array[i];
+}
+
+void set_connection_share_access_list_entry(connection_struct *conn,
+						unsigned int i,
+						uint32_t val)
+{
+	struct connection_share_access_list *csal =
+			find_csal_entry(conn);
+
+	if (csal == NULL) {
+		return;
+	}
+
+	csal->vuid_cache_share_access_array[i] = val;
+}
+
 /****************************************************************************
  Return the number of open connections.
 ****************************************************************************/
@@ -60,19 +138,24 @@ bool conn_snum_used(struct smbd_server_connection *sconn,
 connection_struct *conn_new(struct smbd_server_connection *sconn)
 {
 	connection_struct *conn;
+	struct connection_share_access_list *csal;
 
 	if (!(conn=talloc_zero(NULL, connection_struct)) ||
 	    !(conn->params = talloc(conn, struct share_params)) ||
 	    !(conn->connectpath = talloc_strdup(conn, "")) ||
-	    !(conn->origpath = talloc_strdup(conn, ""))) {
+	    !(conn->origpath = talloc_strdup(conn, "")) ||
+	    !(csal = talloc_zero(conn, struct connection_share_access_list))) {
 		DEBUG(0,("TALLOC_ZERO() failed!\n"));
 		TALLOC_FREE(conn);
 		return NULL;
 	}
+	talloc_set_destructor(csal, free_csal_entry);
+
 	conn->sconn = sconn;
 	conn->force_group_gid = (gid_t)-1;
 
 	DLIST_ADD(sconn->connections, conn);
+	DLIST_ADD(conn_share_access_list, csal);
 	sconn->num_connections++;
 
 	return conn;
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index b48cf44..fae1407 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -145,6 +145,11 @@ bool recursive_rmdir(TALLOC_CTX *ctx,
 
 /* The following definitions come from smbd/conn.c  */
 
+uint32_t get_connection_share_access_list_entry(connection_struct *conn,
+						unsigned int i);
+void set_connection_share_access_list_entry(connection_struct *conn,
+						unsigned int i,
+						uint32_t val);
 int conn_num_open(struct smbd_server_connection *sconn);
 bool conn_snum_used(struct smbd_server_connection *sconn, int snum);
 connection_struct *conn_new(struct smbd_server_connection *sconn);
@@ -1079,6 +1084,10 @@ void reply_transs2(struct smb_request *req);
 /* The following definitions come from smbd/uid.c  */
 
 bool change_to_guest(void);
+NTSTATUS check_user_share_access(connection_struct *conn,
+				const struct auth_session_info *session_info,
+				uint32_t *p_share_access,
+				bool *p_readonly_share);
 bool change_to_user(connection_struct *conn, uint64_t vuid);
 bool change_to_root_user(void);
 bool smbd_change_to_root_user(void);
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 2214ac0..b3abdd8 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -512,40 +512,6 @@ NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
 }
 
 /****************************************************************************
-  Setup the share access mask for a connection.
-****************************************************************************/
-
-static void create_share_access_mask(connection_struct *conn, int snum)
-{
-	const struct security_token *token = conn->session_info->security_token;
-
-	share_access_check(token,
-			lp_servicename(talloc_tos(), snum),
-			MAXIMUM_ALLOWED_ACCESS,
-			&conn->share_access);
-
-	if (!CAN_WRITE(conn)) {
-		conn->share_access &=
-			~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
-			  SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
-			  SEC_DIR_DELETE_CHILD );
-	}
-
-	if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
-		conn->share_access |= SEC_FLAG_SYSTEM_SECURITY;
-	}
-	if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
-		conn->share_access |= (SEC_RIGHTS_PRIV_RESTORE);
-	}
-	if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
-		conn->share_access |= (SEC_RIGHTS_PRIV_BACKUP);
-	}
-	if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
-		conn->share_access |= (SEC_STD_WRITE_OWNER);
-	}
-}
-
-/****************************************************************************
   Make a connection, given the snum to connect to, and the vuser of the
   connecting user if appropriate.
 ****************************************************************************/
@@ -647,28 +613,18 @@ static NTSTATUS make_connection_snum(struct smbd_server_connection *sconn,
 		TALLOC_FREE(s);
 	}
 
-	/*
-	 * New code to check if there's a share security descripter
-	 * added from NT server manager. This is done after the
-	 * smb.conf checks are done as we need a uid and token. JRA.
-	 *
-	 */
-
-	create_share_access_mask(conn, snum);
+        /*
+         * Set up the share security descripter
+         */
 
-	if ((conn->share_access & FILE_WRITE_DATA) == 0) {
-		if ((conn->share_access & FILE_READ_DATA) == 0) {
-			/* No access, read or write. */
-			DEBUG(0,("make_connection: connection to %s "
-				 "denied due to security "
-				 "descriptor.\n",
-				 lp_servicename(talloc_tos(), snum)));
-			status = NT_STATUS_ACCESS_DENIED;
-			goto err_root_exit;
-		} else {
-			conn->read_only = True;
-		}
+	status = check_user_share_access(conn,
+					conn->session_info,
+					&conn->share_access,
+					&conn->read_only);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto err_root_exit;
 	}
+
 	/* Initialise VFS function pointers */
 
 	if (!smbd_vfs_init(conn)) {
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 30c7154..852ae39 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -78,41 +78,61 @@ static void free_conn_session_info_if_unused(connection_struct *conn)
 	TALLOC_FREE(conn->session_info);
 }
 
-/*******************************************************************
- Check if a username is OK.
-
- This sets up conn->session_info with a copy related to this vuser that
- later code can then mess with.
-********************************************************************/
+/****************************************************************************
+  Setup the share access mask for a connection.
+****************************************************************************/
 
-static bool check_user_ok(connection_struct *conn,
-			uint64_t vuid,
-			const struct auth_session_info *session_info,
-			int snum)
+static uint32_t create_share_access_mask(int snum,
+				bool readonly_share,
+				const struct security_token *token)
 {
-	bool valid_vuid = (vuid != UID_FIELD_INVALID);
-	unsigned int i;
-	bool readonly_share;
-	bool admin_user;
-
-	if (valid_vuid) {
-		struct vuid_cache_entry *ent;
+	uint32_t share_access = 0;
+
+	share_access_check(token,
+			lp_servicename(talloc_tos(), snum),
+			MAXIMUM_ALLOWED_ACCESS,
+			&share_access);
+
+	if (readonly_share) {
+		share_access &=
+			~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
+			  SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
+			  SEC_DIR_DELETE_CHILD );
+	}
 
-		for (i=0; i<VUID_CACHE_SIZE; i++) {
-			ent = &conn->vuid_cache.array[i];
-			if (ent->vuid == vuid) {
-				free_conn_session_info_if_unused(conn);
-				conn->session_info = ent->session_info;
-				conn->read_only = ent->read_only;
-				return(True);
-			}
-		}
+	if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
+		share_access |= SEC_FLAG_SYSTEM_SECURITY;
+	}
+	if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
+		share_access |= (SEC_RIGHTS_PRIV_RESTORE);
 	}
+	if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
+		share_access |= (SEC_RIGHTS_PRIV_BACKUP);
+	}
+	if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
+		share_access |= (SEC_STD_WRITE_OWNER);
+	}
+
+	return share_access;
+}
+
+/*******************************************************************
+ Calculate access mask and if this user can access this share.
+********************************************************************/
+
+NTSTATUS check_user_share_access(connection_struct *conn,
+				const struct auth_session_info *session_info,
+				uint32_t *p_share_access,
+				bool *p_readonly_share)
+{
+	int snum = SNUM(conn);
+	uint32_t share_access = 0;
+	bool readonly_share = false;
 
 	if (!user_ok_token(session_info->unix_info->unix_name,
 			   session_info->info->domain_name,
 			   session_info->security_token, snum))
-		return(False);
+		return NT_STATUS_ACCESS_DENIED;
 
 	readonly_share = is_share_read_only_for_token(
 		session_info->unix_info->unix_name,
@@ -120,11 +140,24 @@ static bool check_user_ok(connection_struct *conn,
 		session_info->security_token,
 		conn);
 
+	share_access = create_share_access_mask(snum,
+					readonly_share,
+					session_info->security_token);
+
+	if ((share_access & FILE_WRITE_DATA) == 0) {
+		if ((share_access & FILE_READ_DATA) == 0) {
+			/* No access, read or write. */
+			DEBUG(0,("user %s connection to %s "
+				"denied due to share security "
+				"descriptor.\n",
+				session_info->unix_info->unix_name,
+				lp_servicename(talloc_tos(), snum)));
+			return NT_STATUS_ACCESS_DENIED;
+		}
+	}
+
 	if (!readonly_share &&
-	    !share_access_check(session_info->security_token,
-				lp_servicename(talloc_tos(), snum),
-				FILE_WRITE_DATA,
-				NULL)) {
+	    !(share_access & FILE_WRITE_DATA)) {
 		/* smb.conf allows r/w, but the security descriptor denies
 		 * write. Fall back to looking at readonly. */
 		readonly_share = True;
@@ -132,48 +165,114 @@ static bool check_user_ok(connection_struct *conn,
 			 "security descriptor\n"));
 	}
 
-	if (!share_access_check(session_info->security_token,
-				lp_servicename(talloc_tos(), snum),
-				readonly_share ?
-				FILE_READ_DATA : FILE_WRITE_DATA,
-				NULL)) {
-		return False;
+	*p_share_access = share_access;
+	*p_readonly_share = readonly_share;
+
+	return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Check if a username is OK.
+
+ This sets up conn->session_info with a copy related to this vuser that
+ later code can then mess with.
+********************************************************************/
+
+static bool check_user_ok(connection_struct *conn,
+			uint64_t vuid,
+			const struct auth_session_info *session_info,
+			int snum)
+{
+	unsigned int i;
+	bool readonly_share = false;
+	bool admin_user = false;
+	struct vuid_cache_entry *ent = NULL;
+	uint32_t share_access = 0;
+	unsigned int share_array_index;
+	NTSTATUS status;
+
+	for (i=0; i<VUID_CACHE_SIZE; i++) {
+		ent = &conn->vuid_cache.array[i];
+		if (ent->vuid == vuid) {
+			if (vuid == UID_FIELD_INVALID) {
+				/*
+				 * Slow path, we don't care
+				 * about the array traversal.
+				 */
+				continue;
+			}
+			free_conn_session_info_if_unused(conn);
+			conn->session_info = ent->session_info;
+			conn->read_only = ent->read_only;
+			conn->share_access = get_connection_share_access_list_entry(
+							conn,
+							i);
+			return(True);
+		}
+	}
+
+	status = check_user_share_access(conn,
+					session_info,
+					&share_access,
+					&readonly_share);
+	if (!NT_STATUS_IS_OK(status)) {
+		return false;
 	}
 
+
 	admin_user = token_contains_name_in_list(
 		session_info->unix_info->unix_name,
 		session_info->info->domain_name,
 		NULL, session_info->security_token, lp_admin_users(snum));
 
-	if (valid_vuid) {
-		struct vuid_cache_entry *ent =
-			&conn->vuid_cache.array[conn->vuid_cache.next_entry];
+	share_array_index = conn->vuid_cache.next_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;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list