From 680e4c398c79867f8a7ad40e9c2cd9c401922edd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Dec 2008 11:07:53 -0800 Subject: [PATCH] Fix bug #1254 - write list not working under share-level security (mtab.c, fix build). Jeremy. --- source/client/mtab.c | 1 + source/smbd/share_access.c | 4 ++-- source/smbd/uid.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/source/client/mtab.c b/source/client/mtab.c index 93fbd11359b..70789bcb9d8 100644 --- a/source/client/mtab.c +++ b/source/client/mtab.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c index adb9d169642..c9716941818 100644 --- a/source/smbd/share_access.c +++ b/source/smbd/share_access.c @@ -192,7 +192,7 @@ BOOL token_contains_name_in_list(const char *username, * The other use is the netgroup check when using @group or &group. */ -BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) +BOOL user_ok_token(const char *username, const struct nt_user_token *token, int snum) { if (lp_invalid_users(snum) != NULL) { if (token_contains_name_in_list(username, lp_servicename(snum), @@ -249,7 +249,7 @@ BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) */ BOOL is_share_read_only_for_token(const char *username, - struct nt_user_token *token, int snum) + const struct nt_user_token *token, int snum) { BOOL result = lp_readonly(snum); diff --git a/source/smbd/uid.c b/source/smbd/uid.c index c6d4e3329c8..07a42fa7fee 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -142,6 +142,48 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return(True); } +/******************************************************************* + Check if a username is OK in share level security. +********************************************************************/ + +static bool check_user_ok_sharelevel_security(connection_struct *conn, + const char *unix_name, + int snum) +{ + NT_USER_TOKEN *token = conn->nt_user_token; + + if (!user_ok_token(unix_name, token, snum)) { + return false; + } + + conn->read_only = is_share_read_only_for_token(unix_name, + token, + snum); + + if (!conn->read_only && + !share_access_check(token, lp_servicename(snum), + FILE_WRITE_DATA)) { + /* smb.conf allows r/w, but the security descriptor denies + * write. Fall back to looking at readonly. */ + conn->read_only = true; + DEBUG(5,("falling back to read-only access-evaluation due to " + "security descriptor\n")); + } + + if (!share_access_check(token, lp_servicename(snum), + conn->read_only ? + FILE_READ_DATA : FILE_WRITE_DATA)) { + return false; + } + + conn->admin_user = token_contains_name_in_list( + unix_name, NULL, token, + lp_admin_users(SNUM(conn))); + + return true; +} + + /**************************************************************************** Become the user of a connection number without changing the security context stack, but modify the current_user entries. @@ -149,6 +191,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) BOOL change_to_user(connection_struct *conn, uint16 vuid) { + enum security_types sec = (enum security_types)lp_security(); user_struct *vuser = get_valid_user_struct(vuid); int snum; gid_t gid; @@ -171,7 +214,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) * SMB's - this hurts performance - Badly. */ - if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && + if((sec == SEC_SHARE) && (current_user.conn == conn) && (current_user.ut.uid == conn->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); @@ -192,6 +235,13 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum))); return False; + } else if ((sec == SEC_SHARE) && !check_user_ok_sharelevel_security(conn, + conn->user, snum)) { + DEBUG(2,("change_to_user: unix user %s " + "not permitted access to share %s.\n", + conn->user, + lp_servicename(snum))); + return false; } if (conn->force_user) /* security = share sets this too */ { -- 2.11.4.GIT