1 # Unix SMB/CIFS implementation.
2 # Copyright © Catalyst IT 2023
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 """Fine-grained control over conditional ACE contents.
19 This deliberately allows you to do broken things that SDDL doesn't.
21 - token sequences that make no real sense
22 - sequences that make sense which SDDL can't encode
23 - strings that aren't proper utf-16
27 from samba
.tests
import DynamicTestCase
, TestCase
28 from samba
.tests
import conditional_ace_assembler
as caa
29 from samba
.tests
.token_factory
import token
as Token
30 from samba
.dcerpc
import security
31 from samba
.ndr
import ndr_pack
32 from samba
import NTSTATUSError
33 from samba
.ntstatus
import NT_STATUS_ACCESS_DENIED
34 from samba
.colour
import colourdiff
37 class ConditionalAceBytesBase(TestCase
):
41 cls
.domain_sid
= security
.dom_sid("S-1-2-3")
42 cls
.token
= Token(sids
=['WD', 'AA'],
43 device_claims
={"colour": ["orange", "blue"]})
46 def setUpDynamicTestCases(cls
):
47 for i
, row
in enumerate(cls
.data
):
48 assembly
, sddl
, access_desired
, name
= row
51 name
= f
'{i+1:03}-{name}'
53 name
= f
"{name[:125]}+{len(name) - 125}-more-characters"
55 cls
.generate_dynamic_test('test_assembly',
56 name
, assembly
, sddl
, access_desired
)
58 def _test_assembly_with_args(self
, assembly
, sddl_ref
, access_desired
):
59 sd_bytes
= caa
.assemble(*assembly
)
61 raise ValueError("for this test we need reference SDDL")
63 sddl_ref_full
= f
'D:(XA;;;;;WD;{sddl_ref})'
64 sd_ref
= security
.descriptor
.from_sddl(sddl_ref_full
, self
.domain_sid
)
65 sd_ref_bytes
= ndr_pack(sd_ref
)
66 header
, artx
, conditions
= sd_ref_bytes
.partition(b
'artx')
67 ref_bytes
= artx
+ conditions
68 print(colourdiff(sd_bytes
, ref_bytes
))
70 self
.assertEqual(sd_bytes
, ref_bytes
)
72 if access_desired
is not None:
74 granted
= security
.access_check(sd
, self
.token
, access_desired
)
75 except NTSTATUSError
as e
:
76 if e
.args
[0] != NT_STATUS_ACCESS_DENIED
:
79 self
.fail(f
"{assembly}: access was denied")
80 self
.assertEqual(granted
, access_desired
)
84 self
.fail(f
"{assembly}: unexpected access")
87 class ConditionalAceAssemblySDDL(ConditionalAceBytesBase
):
90 ((caa
.LocalAttr("x"), 41, caa
.EQUAL
,
91 caa
.LocalAttr("x"), caa
.DeviceAttr("x"), caa
.GREATER_THAN
,
93 "((x == 41) && (x > @device.x))",