The branch, v3-2-test has been updated via 82ec832f7edffe2fcfd1bb067e092c159bed2973 (commit) via 34db58061bf0ec1d495579ac40bc6315b76f5b6c (commit) via b848f96d747fb41c074dd073f24f186539257d71 (commit) from e7b0d1c984a37600a234c1f4c95b06e9b5898f30 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-2-test - Log ----------------------------------------------------------------- commit 82ec832f7edffe2fcfd1bb067e092c159bed2973 Author: Jeremy Allison <[EMAIL PROTECTED]> Date: Tue Oct 21 17:06:53 2008 -0700 Cope with MAXIMUM_ALLOWED_ACCESS requests when opening handles. Jeremy. commit 34db58061bf0ec1d495579ac40bc6315b76f5b6c Merge: b848f96d747fb41c074dd073f24f186539257d71 e7b0d1c984a37600a234c1f4c95b06e9b5898f30 Author: Jeremy Allison <[EMAIL PROTECTED]> Date: Tue Oct 21 12:20:00 2008 -0700 Merge branch 'v3-2-test' of ssh://[EMAIL PROTECTED]/data/git/samba into v3-2-test commit b848f96d747fb41c074dd073f24f186539257d71 Author: Jeremy Allison <[EMAIL PROTECTED]> Date: Mon Oct 20 16:53:05 2008 -0700 Remove the requirement for ldap call made as root. Add in security checks for all SAMR calls. Jeremy. ----------------------------------------------------------------------- Summary of changes: source/lib/smbldap.c | 7 -- source/lib/util_sid.c | 11 +++ source/rpc_server/srv_samr_nt.c | 131 ++++++++++++++++++++++++++++++++++++--- source/utils/net_rpc.c | 11 --- 4 files changed, 133 insertions(+), 27 deletions(-) Changeset truncated at 500 lines: diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index bcde53c..315b1e3 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -1023,13 +1023,6 @@ static int smbldap_open(struct smbldap_state *ldap_state) int rc, opt_rc; bool reopen = False; SMB_ASSERT(ldap_state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, ("smbldap_open: cannot access LDAP when not root\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) { diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c index 53614ed..f656bb1 100644 --- a/source/lib/util_sid.c +++ b/source/lib/util_sid.c @@ -664,6 +664,17 @@ bool is_null_sid(const DOM_SID *sid) return sid_equal(sid, &null_sid); } +bool is_sid_in_token(const NT_USER_TOKEN *token, const DOM_SID *sid) +{ + int i; + + for (i=0; i<token->num_sids; i++) { + if (sid_compare(sid, &token->user_sids[i]) == 0) + return true; + } + return false; +} + NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx, const struct netr_SamInfo3 *info3, DOM_SID **user_sids, diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index c59a46c..a085aa7 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Marc Jacobsen 1999, - * Copyright (C) Jeremy Allison 2001-2005, + * Copyright (C) Jeremy Allison 2001-2008, * Copyright (C) Jean François Micouleau 1998-2001, * Copyright (C) Jim McDonough <[EMAIL PROTECTED]> 2002, * Copyright (C) Gerald (Jerry) Carter 2003-2004, @@ -249,6 +249,48 @@ static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_requir } /******************************************************************* + Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. +********************************************************************/ + +static void map_max_allowed_access(const NT_USER_TOKEN *token, + uint32_t *pacc_requested) +{ + if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) { + return; + } + *pacc_requested &= ~MAXIMUM_ALLOWED_ACCESS; + + /* At least try for generic read. */ + *pacc_requested = GENERIC_READ_ACCESS; + + /* root gets anything. */ + if (geteuid() == sec_initial_uid()) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + + /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ + + if (is_sid_in_token(token, &global_sid_Builtin_Administrators) || + is_sid_in_token(token, &global_sid_Builtin_Account_Operators)) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + + /* Full access for DOMAIN\Domain Admins. */ + if ( IS_DC ) { + DOM_SID domadmin_sid; + sid_copy( &domadmin_sid, get_global_sam_sid() ); + sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); + if (is_sid_in_token(token, &domadmin_sid)) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + } + /* TODO ! Check privileges. */ +} + +/******************************************************************* Fetch or create a dispinfo struct. ********************************************************************/ @@ -586,6 +628,7 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, return status; /*check if access can be granted as requested by client. */ + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 ); se_map_generic( &des_access, &dom_generic_mapping ); @@ -826,6 +869,13 @@ NTSTATUS _samr_QuerySecurity(pipes_struct *p, DEBUG(10,("_samr_QuerySecurity: querying security on SID: %s\n", sid_string_dbg(&pol_sid))); + status = access_check_samr_function(acc_granted, + STD_RIGHT_READ_CONTROL_ACCESS, + "_samr_QuerySecurity"); + if (NT_STATUS_IS_OK(status)) { + return status; + } + /* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */ /* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */ @@ -1154,6 +1204,9 @@ NTSTATUS _samr_EnumDomainAliases(pipes_struct *p, if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; + DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", + sid_string_dbg(&info->sid))); + status = access_check_samr_function(info->acc_granted, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, "_samr_EnumDomainAliases"); @@ -1161,9 +1214,6 @@ NTSTATUS _samr_EnumDomainAliases(pipes_struct *p, return status; } - DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", - sid_string_dbg(&info->sid))); - samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); if (!samr_array) { return NT_STATUS_NO_MEMORY; @@ -1430,6 +1480,13 @@ NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p, if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr_QueryDisplayInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* * calculate how many entries we will return. * based on @@ -2063,6 +2120,13 @@ NTSTATUS _samr_LookupRids(pipes_struct *p, if (!get_lsa_policy_samr_sid(p, r->in.domain_handle, &pol_sid, &acc_granted, NULL)) return NT_STATUS_INVALID_HANDLE; + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr__LookupRids"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (num_rids > 1000) { DEBUG(0, ("Got asked for %d rids (more than 1000) -- according " "to samba4 idl this is not possible\n", num_rids)); @@ -2158,6 +2222,8 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, /* check if access can be granted as requested by client. */ + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); @@ -2633,6 +2699,13 @@ NTSTATUS _samr_QueryUserInfo(pipes_struct *p, if (!find_policy_by_hnd(p, r->in.user_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, + "_samr_QueryUserInfo"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + domain_sid = info->sid; sid_split_rid(&domain_sid, &rid); @@ -2881,6 +2954,13 @@ static NTSTATUS samr_QueryDomainInfo_internal(const char *fn_name, return NT_STATUS_INVALID_HANDLE; } + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_SAM_OPEN_DOMAIN, + "_samr_QueryDomainInfo_internal" ); + + if ( !NT_STATUS_IS_OK(status) ) + return status; + switch (level) { case 0x01: @@ -3221,6 +3301,8 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p, sid_compose(&sid, get_global_sam_sid(), *r->out.rid); + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); @@ -3282,10 +3364,7 @@ NTSTATUS _samr_Connect(pipes_struct *p, was observed from a win98 client trying to enumerate users (when configured user level access control on shares) --jerry */ - if (des_access == MAXIMUM_ALLOWED_ACCESS) { - /* Map to max possible knowing we're filtered below. */ - des_access = GENERIC_ALL_ACCESS; - } + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); se_map_generic( &des_access, &sam_generic_mapping ); info->acc_granted = des_access & (SA_RIGHT_SAM_ENUM_DOMAINS|SA_RIGHT_SAM_OPEN_DOMAIN); @@ -3321,6 +3400,8 @@ NTSTATUS _samr_Connect2(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); @@ -3370,6 +3451,8 @@ NTSTATUS _samr_Connect4(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); @@ -3419,6 +3502,8 @@ NTSTATUS _samr_Connect5(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); @@ -3586,6 +3671,8 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p, /*check if access can be granted as requested by client. */ + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &ali_generic_mapping, NULL, 0); se_map_generic(&des_access,&ali_generic_mapping); @@ -5478,6 +5565,8 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, return status; /*check if access can be granted as requested by client. */ + map_max_allowed_access(p->pipe_user.nt_user_token, &des_access); + make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &grp_generic_mapping, NULL, 0); se_map_generic(&des_access,&grp_generic_mapping); @@ -5604,16 +5693,32 @@ NTSTATUS _samr_QueryDomainInfo2(pipes_struct *p, NTSTATUS _samr_SetDomainInfo(pipes_struct *p, struct samr_SetDomainInfo *r) { + struct samr_info *info = NULL; time_t u_expire, u_min_age; time_t u_logout; time_t u_lock_duration, u_reset_time; + NTSTATUS result; DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, r->in.domain_handle, NULL)) + if (!find_policy_by_hnd(p, r->in.domain_handle, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; + /* We do have different access bits for info + * levels here, but we're really just looking for + * GENERIC_RIGHTS_DOMAIN_WRITE access. Unfortunately + * this maps to different specific bits. So + * assume if we have SA_RIGHT_DOMAIN_SET_INFO_1 + * set we are ok. */ + + result = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_SET_INFO_1, + "_samr_SetDomainInfo"); + + if (!NT_STATUS_IS_OK(result)) + return result; + DEBUG(5,("_samr_SetDomainInfo: level: %d\n", r->in.level)); switch (r->in.level) { @@ -5671,6 +5776,7 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, int i; uint32_t num_account = 0; struct samr_displayentry *entries = NULL; + NTSTATUS status; DEBUG(5,("_samr_GetDisplayEnumerationIndex: %d\n", __LINE__)); @@ -5679,6 +5785,13 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(pipes_struct *p, return NT_STATUS_INVALID_HANDLE; } + status = access_check_samr_function(info->acc_granted, + SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, + "_samr_GetDisplayEnumerationIndex"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if ((r->in.level < 1) || (r->in.level > 3)) { DEBUG(0,("_samr_GetDisplayEnumerationIndex: " "Unknown info level (%u)\n", diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index a5c2de0..ef1ebd3 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -4187,17 +4187,6 @@ static void free_user_token(NT_USER_TOKEN *token) SAFE_FREE(token->user_sids); } -static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid) -{ - int i; - - for (i=0; i<token->num_sids; i++) { - if (sid_compare(sid, &token->user_sids[i]) == 0) - return True; - } - return False; -} - static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid) { if (is_sid_in_token(token, sid)) -- Samba Shared Repository