2000-06-08 12:41:28 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2008-10-31 20:51:45 +03:00
Copyright ( C ) Andrew Tridgell 2004
Copyright ( C ) Gerald Carter 2005
Copyright ( C ) Volker Lendecke 2007
Copyright ( C ) Jeremy Allison 2008
2000-06-08 12:41:28 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-06-08 12:41:28 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-06-08 12:41:28 +04:00
*/
# include "includes.h"
2010-10-12 08:27:50 +04:00
# include "libcli/security/security.h"
2000-06-08 12:41:28 +04:00
2001-01-04 22:27:08 +03:00
/* Map generic access rights to object specific rights. This technique is
used to give meaning to assigning read , write , execute and all access to
objects . Each type of object has its own mapping of generic to object
specific access rights . */
2007-10-06 01:41:17 +04:00
void se_map_generic ( uint32 * access_mask , const struct generic_mapping * mapping )
2001-01-04 22:27:08 +03:00
{
uint32 old_mask = * access_mask ;
if ( * access_mask & GENERIC_READ_ACCESS ) {
* access_mask & = ~ GENERIC_READ_ACCESS ;
* access_mask | = mapping - > generic_read ;
}
if ( * access_mask & GENERIC_WRITE_ACCESS ) {
* access_mask & = ~ GENERIC_WRITE_ACCESS ;
* access_mask | = mapping - > generic_write ;
}
if ( * access_mask & GENERIC_EXECUTE_ACCESS ) {
* access_mask & = ~ GENERIC_EXECUTE_ACCESS ;
* access_mask | = mapping - > generic_execute ;
}
if ( * access_mask & GENERIC_ALL_ACCESS ) {
* access_mask & = ~ GENERIC_ALL_ACCESS ;
* access_mask | = mapping - > generic_all ;
}
if ( old_mask ! = * access_mask ) {
DEBUG ( 10 , ( " se_map_generic(): mapped mask 0x%08x to 0x%08x \n " ,
old_mask , * access_mask ) ) ;
}
}
2008-10-09 05:06:58 +04:00
/* Map generic access rights to object specific rights for all the ACE's
* in a security_acl .
*/
void security_acl_map_generic ( struct security_acl * sa ,
const struct generic_mapping * mapping )
{
unsigned int i ;
if ( ! sa ) {
return ;
}
for ( i = 0 ; i < sa - > num_aces ; i + + ) {
se_map_generic ( & sa - > aces [ i ] . access_mask , mapping ) ;
}
}
2002-03-15 11:14:10 +03:00
/* Map standard access rights to object specific rights. This technique is
used to give meaning to assigning read , write , execute and all access to
objects . Each type of object has its own mapping of standard to object
specific access rights . */
2010-06-30 12:39:43 +04:00
void se_map_standard ( uint32 * access_mask , const struct standard_mapping * mapping )
2002-03-15 11:14:10 +03:00
{
uint32 old_mask = * access_mask ;
2008-10-31 20:51:45 +03:00
if ( * access_mask & SEC_STD_READ_CONTROL ) {
* access_mask & = ~ SEC_STD_READ_CONTROL ;
2002-03-15 11:14:10 +03:00
* access_mask | = mapping - > std_read ;
}
2008-10-31 20:51:45 +03:00
if ( * access_mask & ( SEC_STD_DELETE | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER | SEC_STD_SYNCHRONIZE ) ) {
* access_mask & = ~ ( SEC_STD_DELETE | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER | SEC_STD_SYNCHRONIZE ) ;
2002-03-15 11:14:10 +03:00
* access_mask | = mapping - > std_all ;
}
if ( old_mask ! = * access_mask ) {
DEBUG ( 10 , ( " se_map_standard(): mapped mask 0x%08x to 0x%08x \n " ,
old_mask , * access_mask ) ) ;
}
}
2008-10-31 20:51:45 +03:00
/*
perform a SEC_FLAG_MAXIMUM_ALLOWED access check
*/
static uint32_t access_check_max_allowed ( const struct security_descriptor * sd ,
2010-08-26 16:08:22 +04:00
const struct security_token * token )
2000-06-08 12:41:28 +04:00
{
2008-10-31 20:51:45 +03:00
uint32_t denied = 0 , granted = 0 ;
unsigned i ;
2008-11-01 04:04:53 +03:00
2010-09-17 07:08:59 +04:00
if ( security_token_has_sid ( token , sd - > owner_sid ) ) {
2008-10-31 20:51:45 +03:00
granted | = SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE ;
2010-08-30 07:04:27 +04:00
} else if ( security_token_has_privilege ( token , SEC_PRIV_RESTORE ) ) {
2008-10-31 20:51:45 +03:00
granted | = SEC_STD_DELETE ;
}
if ( sd - > dacl = = NULL ) {
return granted & ~ denied ;
}
2008-11-01 04:04:53 +03:00
2008-10-31 20:51:45 +03:00
for ( i = 0 ; i < sd - > dacl - > num_aces ; i + + ) {
struct security_ace * ace = & sd - > dacl - > aces [ i ] ;
2000-06-08 12:41:28 +04:00
2008-10-31 20:51:45 +03:00
if ( ace - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) {
continue ;
}
2000-06-08 12:41:28 +04:00
2010-09-17 07:08:59 +04:00
if ( ! security_token_has_sid ( token , & ace - > trustee ) ) {
2008-10-31 20:51:45 +03:00
continue ;
}
2001-09-26 04:05:03 +04:00
2008-10-31 20:51:45 +03:00
switch ( ace - > type ) {
case SEC_ACE_TYPE_ACCESS_ALLOWED :
granted | = ace - > access_mask ;
break ;
case SEC_ACE_TYPE_ACCESS_DENIED :
case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT :
denied | = ace - > access_mask ;
break ;
default : /* Other ACE types not handled/supported */
break ;
}
}
2000-06-08 12:41:28 +04:00
2008-10-31 20:51:45 +03:00
return granted & ~ denied ;
}
2000-08-09 22:40:48 +04:00
2008-10-31 20:51:45 +03:00
/*
2009-02-03 04:10:27 +03:00
The main entry point for access checking . If returning ACCESS_DENIED
this function returns the denied bits in the uint32_t pointed
to by the access_granted pointer .
2008-10-31 20:51:45 +03:00
*/
NTSTATUS se_access_check ( const struct security_descriptor * sd ,
2010-08-26 16:08:22 +04:00
const struct security_token * token ,
2008-10-31 20:51:45 +03:00
uint32_t access_desired ,
uint32_t * access_granted )
{
int i ;
uint32_t bits_remaining ;
2000-06-08 12:41:28 +04:00
2008-10-31 20:51:45 +03:00
* access_granted = access_desired ;
bits_remaining = access_desired ;
2000-08-08 23:34:34 +04:00
2008-10-31 20:51:45 +03:00
/* handle the maximum allowed flag */
if ( access_desired & SEC_FLAG_MAXIMUM_ALLOWED ) {
2008-11-04 09:42:53 +03:00
uint32_t orig_access_desired = access_desired ;
2008-10-31 20:51:45 +03:00
access_desired | = access_check_max_allowed ( sd , token ) ;
access_desired & = ~ SEC_FLAG_MAXIMUM_ALLOWED ;
* access_granted = access_desired ;
bits_remaining = access_desired & ~ SEC_STD_DELETE ;
2008-11-04 09:42:53 +03:00
DEBUG ( 10 , ( " se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x \n " ,
orig_access_desired ,
* access_granted ,
bits_remaining ) ) ;
2000-06-08 12:41:28 +04:00
}
2008-10-31 20:51:45 +03:00
if ( access_desired & SEC_FLAG_SYSTEM_SECURITY ) {
2010-09-18 04:29:02 +04:00
if ( security_token_has_privilege ( token , SEC_PRIV_SECURITY ) ) {
2008-10-31 20:51:45 +03:00
bits_remaining & = ~ SEC_FLAG_SYSTEM_SECURITY ;
} else {
return NT_STATUS_PRIVILEGE_NOT_HELD ;
2002-09-25 19:19:00 +04:00
}
2001-01-04 22:27:08 +03:00
}
2008-10-31 20:51:45 +03:00
/* a NULL dacl allows access */
if ( ( sd - > type & SEC_DESC_DACL_PRESENT ) & & sd - > dacl = = NULL ) {
* access_granted = access_desired ;
return NT_STATUS_OK ;
2000-06-08 12:41:28 +04:00
}
2008-10-31 20:51:45 +03:00
/* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
if ( ( bits_remaining & ( SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE ) ) & &
2010-09-17 07:08:59 +04:00
security_token_has_sid ( token , sd - > owner_sid ) ) {
2008-10-31 20:51:45 +03:00
bits_remaining & = ~ ( SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE ) ;
}
if ( ( bits_remaining & SEC_STD_DELETE ) & &
2010-08-30 07:04:27 +04:00
( security_token_has_privilege ( token , SEC_PRIV_RESTORE ) ) ) {
2008-10-31 20:51:45 +03:00
bits_remaining & = ~ SEC_STD_DELETE ;
}
2010-09-18 04:29:02 +04:00
if ( ( bits_remaining & SEC_RIGHTS_PRIV_RESTORE ) & &
security_token_has_privilege ( token , SEC_PRIV_RESTORE ) ) {
bits_remaining & = ~ ( SEC_RIGHTS_PRIV_RESTORE ) ;
}
if ( ( bits_remaining & SEC_RIGHTS_PRIV_BACKUP ) & &
security_token_has_privilege ( token , SEC_PRIV_BACKUP ) ) {
bits_remaining & = ~ ( SEC_RIGHTS_PRIV_BACKUP ) ;
}
2000-07-06 10:57:22 +04:00
2008-10-31 20:51:45 +03:00
if ( sd - > dacl = = NULL ) {
goto done ;
2000-08-02 06:11:55 +04:00
}
2000-07-06 10:57:22 +04:00
2008-10-31 20:51:45 +03:00
/* check each ace in turn. */
for ( i = 0 ; bits_remaining & & i < sd - > dacl - > num_aces ; i + + ) {
struct security_ace * ace = & sd - > dacl - > aces [ i ] ;
if ( ace - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) {
continue ;
2000-08-04 23:56:58 +04:00
}
2000-07-06 10:57:22 +04:00
2010-09-17 07:08:59 +04:00
if ( ! security_token_has_sid ( token , & ace - > trustee ) ) {
2008-10-31 20:51:45 +03:00
continue ;
}
2000-07-06 10:57:22 +04:00
2008-10-31 20:51:45 +03:00
switch ( ace - > type ) {
case SEC_ACE_TYPE_ACCESS_ALLOWED :
bits_remaining & = ~ ace - > access_mask ;
break ;
case SEC_ACE_TYPE_ACCESS_DENIED :
case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT :
if ( bits_remaining & ace - > access_mask ) {
return NT_STATUS_ACCESS_DENIED ;
}
break ;
default : /* Other ACE types not handled/supported */
break ;
}
}
done :
if ( bits_remaining ! = 0 ) {
2009-02-03 04:10:27 +03:00
* access_granted = bits_remaining ;
2008-10-31 20:51:45 +03:00
return NT_STATUS_ACCESS_DENIED ;
2000-06-08 12:41:28 +04:00
}
2001-01-19 19:56:58 +03:00
2008-10-31 20:51:45 +03:00
return NT_STATUS_OK ;
}