Merge pull request #3183 from marek-safar/bug41874
[mono.git] / mcs / class / corlib / System.Security.AccessControl / GenericSecurityDescriptor.cs
1 //
2 // System.Security.AccessControl.GenericSecurityDescriptor implementation
3 //
4 // Author:
5 //      Dick Porter  <dick@ximian.com>
6 //      Kenneth Bell
7 //
8 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Globalization;
31 using System.Security.Principal;
32 using System.Text;
33
34 namespace System.Security.AccessControl {
35         public abstract class GenericSecurityDescriptor {
36
37                 protected GenericSecurityDescriptor ()
38                 {
39                 }
40
41                 public int BinaryLength {
42                         get {
43                                 int len = 0x14;
44                                 if (Owner != null)
45                                         len += Owner.BinaryLength;
46                                 if (Group != null)
47                                         len += Group.BinaryLength;
48                                 if (DaclPresent && !DaclIsUnmodifiedAefa)
49                                         len += InternalDacl.BinaryLength;
50                                 if (SaclPresent)
51                                         len += InternalSacl.BinaryLength;
52                                 return len;
53                         }
54                 }
55
56                 public abstract ControlFlags ControlFlags { get; }
57
58                 public abstract SecurityIdentifier Group { get; set; }
59
60                 public abstract SecurityIdentifier Owner { get; set; }
61
62                 public static byte Revision {
63                         get { return 1; }
64                 }
65
66                 internal virtual GenericAcl InternalDacl {
67                         get { return null; }
68                 }
69
70                 internal virtual GenericAcl InternalSacl {
71                         get { return null; }
72                 }
73
74                 internal virtual byte InternalReservedField {
75                         get { return 0; }
76                 }
77
78                 public void GetBinaryForm (byte[] binaryForm, int offset)
79                 {
80                         if (null == binaryForm)
81                                 throw new ArgumentNullException ("binaryForm");
82
83                         int binaryLength = BinaryLength;
84                         if (offset < 0 || offset > binaryForm.Length - binaryLength)
85                                 throw new ArgumentOutOfRangeException ("offset");
86                         
87                         ControlFlags controlFlags = ControlFlags;
88                         if (DaclIsUnmodifiedAefa) { controlFlags &= ~ControlFlags.DiscretionaryAclPresent; }
89                         binaryForm[offset + 0x00] = Revision;
90                         binaryForm[offset + 0x01] = InternalReservedField;
91                         WriteUShort ((ushort)controlFlags, binaryForm,
92                                      offset + 0x02);
93                         
94                         // Skip 'offset' fields (will fill later)
95                         int pos = 0x14;
96                         
97                         if (Owner != null) {
98                                 WriteInt (pos, binaryForm, offset + 0x04);
99                                 Owner.GetBinaryForm (binaryForm, offset + pos);
100                                 pos += Owner.BinaryLength;
101                         } else {
102                                 WriteInt (0, binaryForm, offset + 0x04);
103                         }
104                         
105                         if (Group != null) {
106                                 WriteInt (pos, binaryForm, offset + 0x08);
107                                 Group.GetBinaryForm (binaryForm, offset + pos);
108                                 pos += Group.BinaryLength;
109                         } else {
110                                 WriteInt (0, binaryForm, offset + 0x08);
111                         }
112                         
113                         GenericAcl sysAcl = InternalSacl;
114                         if (SaclPresent) {
115                                 WriteInt (pos, binaryForm, offset + 0x0C);
116                                 sysAcl.GetBinaryForm (binaryForm, offset + pos);
117                                 pos += InternalSacl.BinaryLength;
118                         } else {
119                                 WriteInt (0, binaryForm, offset + 0x0C);
120                         }
121                         
122                         GenericAcl discAcl = InternalDacl;
123                         if (DaclPresent && !DaclIsUnmodifiedAefa) {
124                                 WriteInt (pos, binaryForm, offset + 0x10);
125                                 discAcl.GetBinaryForm (binaryForm, offset + pos);
126                                 pos += InternalDacl.BinaryLength;
127                         } else {
128                                 WriteInt (0, binaryForm, offset + 0x10);
129                         }
130                 }
131
132                 public string GetSddlForm (AccessControlSections includeSections)
133                 {
134                         StringBuilder result = new StringBuilder ();
135                         
136                         if ((includeSections & AccessControlSections.Owner) != 0
137                             && Owner != null) {
138                                 result.AppendFormat (
139                                         CultureInfo.InvariantCulture,
140                                         "O:{0}", Owner.GetSddlForm ());
141                         }
142                         
143                         if ((includeSections & AccessControlSections.Group) != 0
144                             && Group != null) {
145                                 result.AppendFormat (
146                                         CultureInfo.InvariantCulture,
147                                         "G:{0}", Group.GetSddlForm ());
148                         }
149                         
150                         if ((includeSections & AccessControlSections.Access) != 0
151                             && DaclPresent && !DaclIsUnmodifiedAefa) {
152                                 result.AppendFormat (
153                                         CultureInfo.InvariantCulture,
154                                         "D:{0}",
155                                         InternalDacl.GetSddlForm (ControlFlags,
156                                                                   true));
157                         }
158                         
159                         if ((includeSections & AccessControlSections.Audit) != 0
160                             && SaclPresent) {
161                                 result.AppendFormat (
162                                         CultureInfo.InvariantCulture,
163                                         "S:{0}",
164                                         InternalSacl.GetSddlForm (ControlFlags,
165                                                                   false));
166                         }
167                         
168                         return result.ToString ();
169                 }
170
171                 public static bool IsSddlConversionSupported ()
172                 {
173                         return true;
174                 }
175                 
176                 // See CommonSecurityDescriptor constructor regarding this persistence detail.
177                 internal virtual bool DaclIsUnmodifiedAefa {
178                         get { return false; }
179                 }
180                 
181                 bool DaclPresent {
182                         get {
183                                 return InternalDacl != null
184                                     && (ControlFlags & ControlFlags.DiscretionaryAclPresent) != 0;
185                         }
186                 }
187                 
188                 bool SaclPresent {
189                         get {
190                                 return InternalSacl != null
191                                     && (ControlFlags & ControlFlags.SystemAclPresent) != 0;
192                         }
193                 }
194                                 
195                 void WriteUShort (ushort val, byte[] buffer, int offset)
196                 {
197                         buffer[offset] = (byte)val;
198                         buffer[offset + 1] = (byte)(val >> 8);
199                 }
200
201                 void WriteInt (int val, byte[] buffer, int offset)
202                 {
203                         buffer[offset] = (byte)val;
204                         buffer[offset + 1] = (byte)(val >> 8);
205                         buffer[offset + 2] = (byte)(val >> 16);
206                         buffer[offset + 3] = (byte)(val >> 24);
207                 }
208                 
209         }
210 }
211