2010-06-24 08:33:58 +04:00
#!/usr/bin/env python
2009-11-18 21:07:25 +03:00
# Unix SMB/CIFS implementation.
2010-01-08 13:06:47 +03:00
# Copyright (C) Matthieu Patou <mat@matws.net> 2009-2010
2009-11-18 21:07:25 +03: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
# 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 <http://www.gnu.org/licenses/>.
#
2010-11-28 16:09:30 +03:00
""" NT Acls. """
2010-01-08 13:06:47 +03:00
import os
import samba . xattr_native , samba . xattr_tdb
2009-11-18 21:07:25 +03:00
from samba . dcerpc import security , xattr
from samba . ndr import ndr_pack , ndr_unpack
2010-03-01 06:46:40 +03:00
2010-01-08 13:06:47 +03:00
class XattrBackendError ( Exception ) :
""" A generic xattr backend error. """
2010-04-09 01:18:17 +04:00
def checkset_backend ( lp , backend , eadbfile ) :
2010-11-26 04:10:55 +03:00
''' return the path to the eadb, or None '''
if backend is None :
return lp . get ( " posix:eadb " )
elif backend == " native " :
return None
elif backend == " tdb " :
if eadbfile is not None :
return eadbfile
2010-03-01 06:46:40 +03:00
else :
2010-11-26 04:10:55 +03:00
return os . path . abspath ( os . path . join ( lp . get ( " private dir " ) , " eadb.tdb " ) )
else :
raise XattrBackendError ( " Invalid xattr backend choice %s " % backend )
2010-04-09 01:18:17 +04:00
2010-01-08 13:06:47 +03:00
2010-03-01 06:46:40 +03:00
def getntacl ( lp , file , backend = None , eadbfile = None ) :
2010-11-26 04:10:55 +03:00
eadbname = checkset_backend ( lp , backend , eadbfile )
if eadbname is not None :
2010-03-01 06:46:40 +03:00
try :
2010-04-08 23:01:17 +04:00
attribute = samba . xattr_tdb . wrap_getxattr ( eadbname , file ,
xattr . XATTR_NTACL_NAME )
2010-11-29 06:15:57 +03:00
except Exception :
2010-04-08 23:01:17 +04:00
# FIXME: Don't catch all exceptions, just those related to opening
# xattrdb
2010-03-01 06:46:40 +03:00
print " Fail to open %s " % eadbname
2010-04-08 23:01:17 +04:00
attribute = samba . xattr_native . wrap_getxattr ( file ,
xattr . XATTR_NTACL_NAME )
2010-03-01 06:46:40 +03:00
else :
2010-04-08 23:01:17 +04:00
attribute = samba . xattr_native . wrap_getxattr ( file ,
xattr . XATTR_NTACL_NAME )
2010-06-11 01:12:53 +04:00
ntacl = ndr_unpack ( xattr . NTACL , attribute )
2010-03-01 06:46:40 +03:00
return ntacl
2010-01-08 13:06:47 +03:00
2010-06-11 01:12:53 +04:00
2010-03-01 07:04:23 +03:00
def setntacl ( lp , file , sddl , domsid , backend = None , eadbfile = None ) :
2010-11-26 04:10:55 +03:00
eadbname = checkset_backend ( lp , backend , eadbfile )
2010-04-09 01:18:17 +04:00
ntacl = xattr . NTACL ( )
2010-03-01 06:46:40 +03:00
ntacl . version = 1
2010-04-09 01:18:17 +04:00
sid = security . dom_sid ( domsid )
2010-03-01 06:46:40 +03:00
sd = security . descriptor . from_sddl ( sddl , sid )
ntacl . info = sd
2010-11-26 04:10:55 +03:00
if eadbname is not None :
2010-03-01 06:46:40 +03:00
try :
2010-04-08 23:01:17 +04:00
samba . xattr_tdb . wrap_setxattr ( eadbname ,
2010-06-11 01:12:53 +04:00
file , xattr . XATTR_NTACL_NAME , ndr_pack ( ntacl ) )
2010-11-29 06:15:57 +03:00
except Exception :
2010-04-08 23:01:17 +04:00
# FIXME: Don't catch all exceptions, just those related to opening
# xattrdb
2010-06-11 01:12:53 +04:00
print " Fail to open %s " % eadbname
samba . xattr_native . wrap_setxattr ( file , xattr . XATTR_NTACL_NAME ,
ndr_pack ( ntacl ) )
2010-03-01 06:46:40 +03:00
else :
2010-06-11 01:12:53 +04:00
samba . xattr_native . wrap_setxattr ( file , xattr . XATTR_NTACL_NAME ,
ndr_pack ( ntacl ) )
2009-11-18 21:07:25 +03:00
def ldapmask2filemask ( ldm ) :
2010-06-11 01:12:53 +04:00
""" Takes the access mask of a DS ACE and transform them in a File ACE mask.
"""
2010-03-01 06:46:40 +03:00
RIGHT_DS_CREATE_CHILD = 0x00000001
RIGHT_DS_DELETE_CHILD = 0x00000002
RIGHT_DS_LIST_CONTENTS = 0x00000004
ACTRL_DS_SELF = 0x00000008
RIGHT_DS_READ_PROPERTY = 0x00000010
RIGHT_DS_WRITE_PROPERTY = 0x00000020
RIGHT_DS_DELETE_TREE = 0x00000040
RIGHT_DS_LIST_OBJECT = 0x00000080
RIGHT_DS_CONTROL_ACCESS = 0x00000100
FILE_READ_DATA = 0x0001
FILE_LIST_DIRECTORY = 0x0001
FILE_WRITE_DATA = 0x0002
FILE_ADD_FILE = 0x0002
FILE_APPEND_DATA = 0x0004
FILE_ADD_SUBDIRECTORY = 0x0004
FILE_CREATE_PIPE_INSTANCE = 0x0004
FILE_READ_EA = 0x0008
FILE_WRITE_EA = 0x0010
FILE_EXECUTE = 0x0020
FILE_TRAVERSE = 0x0020
FILE_DELETE_CHILD = 0x0040
FILE_READ_ATTRIBUTES = 0x0080
FILE_WRITE_ATTRIBUTES = 0x0100
DELETE = 0x00010000
READ_CONTROL = 0x00020000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
SYNCHRONIZE = 0x00100000
STANDARD_RIGHTS_ALL = 0x001F0000
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
filemask = ldm & STANDARD_RIGHTS_ALL
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
if ( ldm & RIGHT_DS_READ_PROPERTY ) and ( ldm & RIGHT_DS_LIST_CONTENTS ) :
filemask = filemask | ( SYNCHRONIZE | FILE_LIST_DIRECTORY | \
FILE_READ_ATTRIBUTES | FILE_READ_EA | \
FILE_READ_DATA | FILE_EXECUTE )
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
if ldm & RIGHT_DS_WRITE_PROPERTY :
filemask = filemask | ( SYNCHRONIZE | FILE_WRITE_DATA | \
FILE_APPEND_DATA | FILE_WRITE_EA | \
FILE_WRITE_ATTRIBUTES | FILE_ADD_FILE | \
FILE_ADD_SUBDIRECTORY )
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
if ldm & RIGHT_DS_CREATE_CHILD :
filemask = filemask | ( FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE )
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
if ldm & RIGHT_DS_DELETE_CHILD :
filemask = filemask | FILE_DELETE_CHILD
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
return filemask
2009-11-18 21:07:25 +03:00
2010-04-09 01:18:17 +04:00
2010-03-01 06:46:40 +03:00
def dsacl2fsacl ( dssddl , domsid ) :
"""
This function takes an the SDDL representation of a DS
ACL and return the SDDL representation of this ACL adapted
for files . It ' s used for Policy object provision
"""
sid = security . dom_sid ( domsid )
2010-06-11 01:12:53 +04:00
ref = security . descriptor . from_sddl ( dssddl , sid )
2010-03-01 06:46:40 +03:00
fdescr = security . descriptor ( )
fdescr . owner_sid = ref . owner_sid
fdescr . group_sid = ref . group_sid
fdescr . type = ref . type
fdescr . revision = ref . revision
fdescr . sacl = ref . sacl
aces = ref . dacl . aces
2010-03-01 07:04:23 +03:00
for i in range ( 0 , len ( aces ) ) :
2010-03-01 06:46:40 +03:00
ace = aces [ i ]
2010-04-09 01:18:17 +04:00
if not ace . type & security . SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT and str ( ace . trustee ) != security . SID_BUILTIN_PREW2K :
# if fdescr.type & security.SEC_DESC_DACL_AUTO_INHERITED:
2010-03-01 06:46:40 +03:00
ace . flags = ace . flags | security . SEC_ACE_FLAG_OBJECT_INHERIT | security . SEC_ACE_FLAG_CONTAINER_INHERIT
if str ( ace . trustee ) == security . SID_CREATOR_OWNER :
# For Creator/Owner the IO flag is set as this ACE has only a sense for child objects
ace . flags = ace . flags | security . SEC_ACE_FLAG_INHERIT_ONLY
ace . access_mask = ldapmask2filemask ( ace . access_mask )
fdescr . dacl_add ( ace )
2009-11-18 21:07:25 +03:00
2010-03-01 06:46:40 +03:00
return fdescr . as_sddl ( sid )