From ab9a29eb638143a93f70bb7880ca24f73bbb2118 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 25 Mar 2011 14:12:59 +0100 Subject: s3-rpc_server: move access check functions out of samr server. Guenther --- source3/Makefile.in | 2 +- source3/include/proto.h | 10 --- source3/rpc_server/lsa/srv_lsa_nt.c | 1 + source3/rpc_server/samr/srv_samr_nt.c | 114 +------------------------- source3/rpc_server/srv_access_check.c | 146 ++++++++++++++++++++++++++++++++++ source3/rpc_server/srv_access_check.h | 10 +++ source3/rpc_server/wscript_build | 6 +- 7 files changed, 164 insertions(+), 125 deletions(-) create mode 100644 source3/rpc_server/srv_access_check.c create mode 100644 source3/rpc_server/srv_access_check.h diff --git a/source3/Makefile.in b/source3/Makefile.in index 6bdf64972d7..15279ee039e 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -714,7 +714,7 @@ NPA_TSTREAM_OBJ = ../libcli/named_pipe_auth/npa_tstream.o \ ../auth/auth_sam_reply.o librpc/gen_ndr/ndr_auth.o RPC_NCACN_NP = rpc_server/srv_pipe_register.o rpc_server/rpc_ncacn_np.o \ - rpc_server/rpc_handles.o + rpc_server/rpc_handles.o rpc_server/srv_access_check.o RPC_SERVICE = rpc_server/rpc_server.o diff --git a/source3/include/proto.h b/source3/include/proto.h index 54676e1d564..27989738d6f 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3001,16 +3001,6 @@ NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs, int *pfd, size_t *chosen_index, uint16_t *chosen_port); -/* The following definitions come from rpc_server/srv_samr_nt.c */ -NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, - enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, - uint32 rights_mask, - uint32 des_access, uint32 *acc_granted, - const char *debug ); -void map_max_allowed_access(const struct security_token *nt_token, - const struct security_unix_token *unix_token, - uint32_t *pacc_requested); - /* The following definitions come from lib/util_wellknown.c */ bool sid_check_is_wellknown_domain(const struct dom_sid *sid, const char **name); diff --git a/source3/rpc_server/lsa/srv_lsa_nt.c b/source3/rpc_server/lsa/srv_lsa_nt.c index ca05a1ae70f..63ff41c0499 100644 --- a/source3/rpc_server/lsa/srv_lsa_nt.c +++ b/source3/rpc_server/lsa/srv_lsa_nt.c @@ -45,6 +45,7 @@ #include "auth.h" #include "ntdomain.h" #include "lib/privileges.h" +#include "rpc_server/srv_access_check.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c index 2d8564d7864..2e4f883a582 100644 --- a/source3/rpc_server/samr/srv_samr_nt.c +++ b/source3/rpc_server/samr/srv_samr_nt.c @@ -44,6 +44,7 @@ #include "passdb.h" #include "auth.h" #include "ntdomain.h" +#include "rpc_server/srv_access_check.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -179,119 +180,6 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, struct security_descriptor return NT_STATUS_OK; } -/******************************************************************* - Checks if access to an object should be granted, and returns that - level of access for further checks. - - If the user has either of needed_priv_1 or needed_priv_2 then they - get the rights in rights_mask in addition to any calulated rights. - - This handles the unusual case where we need to allow two different - privileges to obtain exactly the same rights, which occours only in - SAMR. -********************************************************************/ - -NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, - enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, - uint32 rights_mask, - uint32 des_access, uint32 *acc_granted, - const char *debug ) -{ - NTSTATUS status = NT_STATUS_ACCESS_DENIED; - uint32 saved_mask = 0; - - /* check privileges; certain SAM access bits should be overridden - by privileges (mostly having to do with creating/modifying/deleting - users and groups) */ - - if ((needed_priv_1 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_1)) || - (needed_priv_2 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_2))) { - saved_mask = (des_access & rights_mask); - des_access &= ~saved_mask; - - DEBUG(4,("access_check_object: user rights access mask [0x%x]\n", - rights_mask)); - } - - - /* check the security descriptor first */ - - status = se_access_check(psd, token, des_access, acc_granted); - if (NT_STATUS_IS_OK(status)) { - goto done; - } - - /* give root a free pass */ - - if ( geteuid() == sec_initial_uid() ) { - - DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access)); - DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n")); - - *acc_granted = des_access; - - status = NT_STATUS_OK; - goto done; - } - - -done: - /* add in any bits saved during the privilege check (only - matters is status is ok) */ - - *acc_granted |= rights_mask; - - DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", - debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", - des_access, *acc_granted)); - - return status; -} - - -/******************************************************************* - Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. -********************************************************************/ - -void map_max_allowed_access(const struct security_token *nt_token, - const struct security_unix_token *unix_token, - uint32_t *pacc_requested) -{ - if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) { - return; - } - *pacc_requested &= ~MAXIMUM_ALLOWED_ACCESS; - - /* At least try for generic read|execute - Everyone gets that. */ - *pacc_requested = GENERIC_READ_ACCESS|GENERIC_EXECUTE_ACCESS; - - /* root gets anything. */ - if (unix_token->uid == sec_initial_uid()) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - - /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ - - if (security_token_has_sid(nt_token, &global_sid_Builtin_Administrators) || - security_token_has_sid(nt_token, &global_sid_Builtin_Account_Operators)) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - - /* Full access for DOMAIN\Domain Admins. */ - if ( IS_DC ) { - struct dom_sid domadmin_sid; - sid_compose(&domadmin_sid, get_global_sam_sid(), - DOMAIN_RID_ADMINS); - if (security_token_has_sid(nt_token, &domadmin_sid)) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - } - /* TODO ! Check privileges. */ -} - /******************************************************************* Fetch or create a dispinfo struct. ********************************************************************/ diff --git a/source3/rpc_server/srv_access_check.c b/source3/rpc_server/srv_access_check.c new file mode 100644 index 00000000000..12d90240b1d --- /dev/null +++ b/source3/rpc_server/srv_access_check.c @@ -0,0 +1,146 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997, + * Copyright (C) Marc Jacobsen 1999, + * Copyright (C) Jeremy Allison 2001-2008, + * Copyright (C) Jean François Micouleau 1998-2001, + * Copyright (C) Jim McDonough 2002, + * Copyright (C) Gerald (Jerry) Carter 2003-2004, + * Copyright (C) Simo Sorce 2003. + * Copyright (C) Volker Lendecke 2005. + * Copyright (C) Guenther Deschner 2008. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "rpc_server/srv_access_check.h" +#include "../libcli/security/security.h" +#include "passdb/machine_sid.h" + +/******************************************************************* + Checks if access to an object should be granted, and returns that + level of access for further checks. + + If the user has either of needed_priv_1 or needed_priv_2 then they + get the rights in rights_mask in addition to any calulated rights. + + This handles the unusual case where we need to allow two different + privileges to obtain exactly the same rights, which occours only in + SAMR. +********************************************************************/ + +NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, + enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, + uint32 rights_mask, + uint32 des_access, uint32 *acc_granted, + const char *debug ) +{ + NTSTATUS status = NT_STATUS_ACCESS_DENIED; + uint32 saved_mask = 0; + + /* check privileges; certain SAM access bits should be overridden + by privileges (mostly having to do with creating/modifying/deleting + users and groups) */ + + if ((needed_priv_1 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_1)) || + (needed_priv_2 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_2))) { + saved_mask = (des_access & rights_mask); + des_access &= ~saved_mask; + + DEBUG(4,("access_check_object: user rights access mask [0x%x]\n", + rights_mask)); + } + + + /* check the security descriptor first */ + + status = se_access_check(psd, token, des_access, acc_granted); + if (NT_STATUS_IS_OK(status)) { + goto done; + } + + /* give root a free pass */ + + if ( geteuid() == sec_initial_uid() ) { + + DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access)); + DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n")); + + *acc_granted = des_access; + + status = NT_STATUS_OK; + goto done; + } + + +done: + /* add in any bits saved during the privilege check (only + matters is status is ok) */ + + *acc_granted |= rights_mask; + + DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", + debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", + des_access, *acc_granted)); + + return status; +} + + +/******************************************************************* + Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. +********************************************************************/ + +void map_max_allowed_access(const struct security_token *nt_token, + const struct security_unix_token *unix_token, + uint32_t *pacc_requested) +{ + if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) { + return; + } + *pacc_requested &= ~MAXIMUM_ALLOWED_ACCESS; + + /* At least try for generic read|execute - Everyone gets that. */ + *pacc_requested = GENERIC_READ_ACCESS|GENERIC_EXECUTE_ACCESS; + + /* root gets anything. */ + if (unix_token->uid == sec_initial_uid()) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + + /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ + + if (security_token_has_sid(nt_token, &global_sid_Builtin_Administrators) || + security_token_has_sid(nt_token, &global_sid_Builtin_Account_Operators)) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + + /* Full access for DOMAIN\Domain Admins. */ + if ( IS_DC ) { + struct dom_sid domadmin_sid; + sid_compose(&domadmin_sid, get_global_sam_sid(), + DOMAIN_RID_ADMINS); + if (security_token_has_sid(nt_token, &domadmin_sid)) { + *pacc_requested |= GENERIC_ALL_ACCESS; + return; + } + } + /* TODO ! Check privileges. */ +} diff --git a/source3/rpc_server/srv_access_check.h b/source3/rpc_server/srv_access_check.h new file mode 100644 index 00000000000..27a09bd0074 --- /dev/null +++ b/source3/rpc_server/srv_access_check.h @@ -0,0 +1,10 @@ +/* The following definitions come from rpc_server/srv_access_check.c */ + +NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, + enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, + uint32 rights_mask, + uint32 des_access, uint32 *acc_granted, + const char *debug ); +void map_max_allowed_access(const struct security_token *nt_token, + const struct security_unix_token *unix_token, + uint32_t *pacc_requested); diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build index 8f7697a946b..346d770385e 100644 --- a/source3/rpc_server/wscript_build +++ b/source3/rpc_server/wscript_build @@ -44,13 +44,17 @@ bld.SAMBA3_SUBSYSTEM('RPC_SERVER_REGISTER', bld.SAMBA3_SUBSYSTEM('EPMD', source='epmd.c') +bld.SAMBA3_SUBSYSTEM('SRV_ACCESS_CHECK', + source='srv_access_check.c') + bld.SAMBA3_SUBSYSTEM('RPC_SAMR', source=RPC_SAMR_SRC, - deps='PLAINTEXT_AUTH', + deps='PLAINTEXT_AUTH SRV_ACCESS_CHECK', vars=locals()) bld.SAMBA3_SUBSYSTEM('RPC_LSARPC', source=RPC_LSARPC_SRC, + deps='SRV_ACCESS_CHECK', vars=locals()) bld.SAMBA3_SUBSYSTEM('RPC_WINREG', -- cgit