From 46cb3be0cf3f14bc2b95101189983b6d3afdacad Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Fri, 15 Jul 2016 16:21:21 -0700 Subject: [PATCH] s3: Prefer user accounts in read and write lists Currently, objects in the write list always override the same objects in the read list. This includes cases where you have an individual user account in the read list, and a group he belongs to in the write list. This seems unintuitive, as normally user account settings take precedence over group account settings. Change this behavior by keeping track of the object type, and giving preference to user account objects. Signed-off-by: Justin Maggard --- source3/smbd/proto.h | 3 ++- source3/smbd/share_access.c | 41 +++++++++++++++++++++++++++++++---------- source3/smbd/uid.c | 3 ++- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 81bdc87..1a7956f 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1076,7 +1076,8 @@ bool token_contains_name_in_list(const char *username, const char *domain, const char *sharename, const struct security_token *token, - const char **list); + const char **list, + uint32_t *type); bool user_ok_token(const char *username, const char *domain, const struct security_token *token, int snum); bool is_share_read_only_for_token(const char *username, diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index fa56063..75b8b87 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -72,7 +72,8 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, const char *domain, const char *sharename, const struct security_token *token, - const char *name) + const char *name, + uint32_t *sid_type) { const char *prefix; struct dom_sid sid; @@ -104,6 +105,9 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, DEBUG(5, ("lookup_name %s failed\n", name)); return False; } + if (sid_type) { + *sid_type = type; + } if (type != SID_NAME_USER) { DEBUG(5, ("%s is a %s, expected a user\n", name, sid_type_lookup(type))); @@ -120,6 +124,9 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, DEBUG(5, ("lookup_name %s failed\n", name)); return False; } + if (sid_type) { + *sid_type = type; + } if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && (type != SID_NAME_WKN_GRP)) { @@ -160,8 +167,11 @@ bool token_contains_name_in_list(const char *username, const char *domain, const char *sharename, const struct security_token *token, - const char **list) + const char **list, + uint32_t *type) { + bool found = False; + if (list == NULL) { return False; } @@ -170,14 +180,17 @@ bool token_contains_name_in_list(const char *username, bool ret; ret = token_contains_name(frame, username, domain, sharename, - token, *list); + token, *list, type); TALLOC_FREE(frame); if (ret) { - return true; + found = True; + if (type && *type == SID_NAME_USER) { + break; + } } list += 1; } - return False; + return found; } /* @@ -200,7 +213,7 @@ bool user_ok_token(const char *username, const char *domain, if (token_contains_name_in_list(username, domain, lp_servicename(talloc_tos(), snum), token, - lp_invalid_users(snum))) { + lp_invalid_users(snum), NULL)) { DEBUG(10, ("User %s in 'invalid users'\n", username)); return False; } @@ -210,7 +223,7 @@ bool user_ok_token(const char *username, const char *domain, if (!token_contains_name_in_list(username, domain, lp_servicename(talloc_tos(), snum), token, - lp_valid_users(snum))) { + lp_valid_users(snum), NULL)) { DEBUG(10, ("User %s not in 'valid users'\n", username)); return False; @@ -244,13 +257,18 @@ bool is_share_read_only_for_token(const char *username, { int snum = SNUM(conn); bool result = conn->read_only; + bool user_match = False; + uint32_t type; if (lp_read_list(snum) != NULL) { if (token_contains_name_in_list(username, domain, lp_servicename(talloc_tos(), snum), token, - lp_read_list(snum))) { + lp_read_list(snum), &type)) { result = True; + if (type == SID_NAME_USER) { + user_match = True; + } } } @@ -258,8 +276,11 @@ bool is_share_read_only_for_token(const char *username, if (token_contains_name_in_list(username, domain, lp_servicename(talloc_tos(), snum), token, - lp_write_list(snum))) { - result = False; + lp_write_list(snum), &type)) { + /* Prefer user accounts to groups */ + if (type == SID_NAME_USER || !user_match) { + result = False; + } } } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6eb5392..76a86d6 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -217,7 +217,8 @@ static bool check_user_ok(connection_struct *conn, 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)); + NULL, session_info->security_token, lp_admin_users(snum), + NULL); ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry]; -- 2.9.1