Merge pull request #3381 from krytarowski/netbsd-support-20
[mono.git] / mcs / class / corlib / System.Security.AccessControl / CommonSecurityDescriptor.cs
1 //
2 // System.Security.AccessControl.CommonSecurityDescriptor implementation
3 //
4 // Author:
5 //      Dick Porter  <dick@ximian.com>
6 //      James Bellinger  <jfb@zer7.com>
7 //
8 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
9 // Copyright (C) 2012 James Bellinger
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Security.Principal;
33
34 namespace System.Security.AccessControl
35 {
36         public sealed class CommonSecurityDescriptor : GenericSecurityDescriptor
37         {
38                 bool is_container;
39                 bool is_ds;
40                 ControlFlags flags;
41                 SecurityIdentifier owner;
42                 SecurityIdentifier group;
43                 SystemAcl system_acl;
44                 DiscretionaryAcl discretionary_acl;
45                 
46                 public CommonSecurityDescriptor (bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor)
47                 {
48                         Init (isContainer, isDS, rawSecurityDescriptor);
49                 }
50                 
51                 public CommonSecurityDescriptor (bool isContainer, bool isDS, string sddlForm)
52                 {
53                         Init (isContainer, isDS, new RawSecurityDescriptor (sddlForm));
54                 }
55                 
56                 public CommonSecurityDescriptor (bool isContainer, bool isDS, byte[] binaryForm, int offset)
57                 {
58                         Init (isContainer, isDS, new RawSecurityDescriptor (binaryForm, offset));
59                 }
60                 
61                 public CommonSecurityDescriptor (bool isContainer, bool isDS,
62                                                  ControlFlags flags,
63                                                  SecurityIdentifier owner,
64                                                  SecurityIdentifier group,
65                                                  SystemAcl systemAcl,
66                                                  DiscretionaryAcl discretionaryAcl)
67                 {
68                         Init (isContainer, isDS, flags, owner, group, systemAcl, discretionaryAcl);
69                 }
70                 
71                 void Init (bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor)
72                 {
73                         if (null == rawSecurityDescriptor)
74                                 throw new ArgumentNullException ("rawSecurityDescriptor");
75                                 
76                         SystemAcl sacl = null;
77                         if (null != rawSecurityDescriptor.SystemAcl)
78                                 sacl = new SystemAcl (isContainer, isDS, rawSecurityDescriptor.SystemAcl);
79                                 
80                         DiscretionaryAcl dacl = null;
81                         if (null != rawSecurityDescriptor.DiscretionaryAcl)
82                                 dacl = new DiscretionaryAcl (isContainer, isDS, rawSecurityDescriptor.DiscretionaryAcl);
83                                 
84                         Init (isContainer, isDS,
85                               rawSecurityDescriptor.ControlFlags,
86                               rawSecurityDescriptor.Owner,
87                               rawSecurityDescriptor.Group,
88                               sacl, dacl);
89                 }
90                 
91                 void Init (bool isContainer, bool isDS,
92                            ControlFlags flags,
93                            SecurityIdentifier owner,
94                            SecurityIdentifier group,
95                            SystemAcl systemAcl,
96                            DiscretionaryAcl discretionaryAcl)
97                 {
98                         this.flags = flags & ~ControlFlags.SystemAclPresent;
99                         this.is_container = isContainer;
100                         this.is_ds = isDS;
101                         
102                         Owner = owner;
103                         Group = group;
104                         SystemAcl = systemAcl;
105                         DiscretionaryAcl = discretionaryAcl;
106                 }
107                 
108                 public override ControlFlags ControlFlags {
109                         get {
110                                 ControlFlags realFlags = flags;
111                                 
112                                 realFlags |= ControlFlags.DiscretionaryAclPresent;
113                                 realFlags |= ControlFlags.SelfRelative;
114                                 if (SystemAcl != null)
115                                         realFlags |= ControlFlags.SystemAclPresent;
116                                         
117                                 return realFlags;
118                         }
119                 }
120                 
121                 public DiscretionaryAcl DiscretionaryAcl {
122                         get { return discretionary_acl; }
123                         set {
124                                 if (value == null) {
125                                         value = new DiscretionaryAcl (IsContainer, IsDS, 1);
126                                         value.AddAccess (AccessControlType.Allow, new SecurityIdentifier ("WD"), -1,
127                                                         IsContainer ? InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
128                                                                     : InheritanceFlags.None, PropagationFlags.None);
129                                         value.IsAefa = true;
130                                 }
131                                 
132                                 CheckAclConsistency (value);
133                                 discretionary_acl = value;
134                         }
135                 }
136                 
137                 internal override GenericAcl InternalDacl {
138                         get { return DiscretionaryAcl; }
139                 }
140                 
141                 public override SecurityIdentifier Group {
142                         get { return  group; }
143                         set { group = value; }
144                 }
145
146                 public bool IsContainer {
147                         get { return is_container; }
148                 }
149                 
150                 public bool IsDiscretionaryAclCanonical {
151                         get { return DiscretionaryAcl.IsCanonical; }
152                 }
153                 
154                 public bool IsDS {
155                         get { return is_ds; }
156                 }
157                 
158                 public bool IsSystemAclCanonical {
159                         get { return SystemAcl == null || SystemAcl.IsCanonical; }
160                 }
161                 
162                 public override SecurityIdentifier Owner {
163                         get { return  owner; }
164                         set { owner = value; }
165                 }
166                 
167                 public SystemAcl SystemAcl {
168                         get { return system_acl;  }
169                         set {
170                                 if (value != null)
171                                         CheckAclConsistency (value);
172                                         
173                                 system_acl = value;
174                         }
175                 }
176                 
177                 internal override GenericAcl InternalSacl {
178                         get { return SystemAcl; }
179                 }
180
181                 public void PurgeAccessControl (SecurityIdentifier sid)
182                 {
183                         DiscretionaryAcl.Purge (sid);
184                 }
185                 
186                 public void PurgeAudit (SecurityIdentifier sid)
187                 {
188                         if (SystemAcl != null)
189                                 SystemAcl.Purge (sid);
190                 }
191                 
192                 public void SetDiscretionaryAclProtection (bool isProtected,
193                                                            bool preserveInheritance)
194                 {
195                         DiscretionaryAcl.IsAefa = false;
196                         
197                         if (!isProtected) {
198                                 flags &= ~ControlFlags.DiscretionaryAclProtected;
199                                 return;
200                         }
201                         
202                         flags |= ControlFlags.DiscretionaryAclProtected;
203                         if (!preserveInheritance)
204                                 DiscretionaryAcl.RemoveInheritedAces ();
205                 }
206                 
207                 public void SetSystemAclProtection (bool isProtected,
208                                                     bool preserveInheritance)
209                 {
210                         if (!isProtected) {
211                                 flags &= ~ControlFlags.SystemAclProtected;
212                                 return;
213                         }
214                         
215                         flags |= ControlFlags.SystemAclProtected;
216                         if (!preserveInheritance && SystemAcl != null)
217                                 SystemAcl.RemoveInheritedAces ();
218                 }
219
220                 public void AddDiscretionaryAcl (byte revision, int trusted)
221                 {
222                         DiscretionaryAcl = new DiscretionaryAcl (IsContainer, IsDS, revision, trusted);
223                         flags |= ControlFlags.DiscretionaryAclPresent;
224                 }
225
226                 public void AddSystemAcl(byte revision, int trusted)
227                 {
228                         SystemAcl = new SystemAcl (IsContainer, IsDS, revision, trusted);
229                         flags |= ControlFlags.SystemAclPresent;
230                 }
231
232                 void CheckAclConsistency (CommonAcl acl)
233                 {
234                         if (IsContainer != acl.IsContainer)
235                                 throw new ArgumentException ("IsContainer must match between descriptor and ACL.");
236                         
237                         if (IsDS != acl.IsDS)
238                                 throw new ArgumentException ("IsDS must match between descriptor and ACL.");
239                 }
240
241                 internal override bool DaclIsUnmodifiedAefa {
242                         get { return DiscretionaryAcl.IsAefa; }
243                 }
244         }
245 }
246