From f0b1a1bc9b74372e2af2a48ce9b06802b2198eb4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 2008 16:51:37 -0700 Subject: Remove the requirement for ldap call made as root. Add in security checks for all SAMR calls. Jeremy. --- source3/lib/smbldap.c | 7 ----- source3/rpc_server/srv_samr_nt.c | 67 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index f5e152bb95..f2161dc946 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1025,13 +1025,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/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index e527631cc1..261d77ca65 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -825,6 +825,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 */ @@ -1153,6 +1160,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"); @@ -1160,9 +1170,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; @@ -1429,6 +1436,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 @@ -2062,6 +2076,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)); @@ -2632,6 +2653,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); @@ -2880,6 +2908,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: @@ -5605,16 +5640,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) { @@ -5672,6 +5723,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__)); @@ -5680,6 +5732,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", -- cgit