Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / corlib / System.Security.AccessControl / ObjectAce.cs
1 //
2 // System.Security.AccessControl.ObjectAce implementation
3 //
4 // Authors:
5 //      Dick Porter  <dick@ximian.com>
6 //      Atsushi Enomoto  <atsushi@ximian.com>
7 //      Kenneth Bell
8 //      James Bellinger  <jfb@zer7.com>
9 //
10 // Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
11 // Copyright (C) 2012      James Bellinger
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.Security.Principal;
34 using System.Globalization;
35
36 namespace System.Security.AccessControl
37 {
38         public sealed class ObjectAce : QualifiedAce
39         {
40                 private Guid object_ace_type;
41                 private Guid inherited_object_type;
42                 private ObjectAceFlags object_ace_flags;
43
44                 public ObjectAce (AceFlags aceFlags, AceQualifier qualifier,
45                                   int accessMask, SecurityIdentifier sid,
46                                   ObjectAceFlags flags, Guid type,
47                                   Guid inheritedType, bool isCallback,
48                                   byte[] opaque)
49                         : base (ConvertType(qualifier, isCallback), aceFlags, opaque)
50                 {
51                         AccessMask = accessMask;
52                         SecurityIdentifier = sid;
53                         ObjectAceFlags = flags;
54                         ObjectAceType = type;
55                         InheritedObjectAceType = inheritedType;
56                 }
57
58                 internal ObjectAce (AceType type, AceFlags flags, int accessMask,
59                                     SecurityIdentifier sid, ObjectAceFlags objFlags,
60                                     Guid objType, Guid inheritedType, byte[] opaque)
61                         : base(type, flags, opaque)
62                 {
63                         AccessMask = accessMask;
64                         SecurityIdentifier = sid;
65                         ObjectAceFlags = objFlags;
66                         ObjectAceType = objType;
67                         InheritedObjectAceType = inheritedType;
68                 }
69                 
70                 internal ObjectAce(byte[] binaryForm, int offset)
71                         : base(binaryForm, offset)
72                 {
73                         int len = ReadUShort(binaryForm, offset + 2);
74                         int lenMinimum = 12 + SecurityIdentifier.MinBinaryLength;
75                         
76                         if (offset > binaryForm.Length - len)
77                                 throw new ArgumentException("Invalid ACE - truncated", "binaryForm");
78                         if (len < lenMinimum)
79                                 throw new ArgumentException("Invalid ACE", "binaryForm");
80                         
81                         AccessMask = ReadInt(binaryForm, offset + 4);
82                         ObjectAceFlags = (ObjectAceFlags)ReadInt(binaryForm, offset + 8);
83                         
84                         if (ObjectAceTypePresent) lenMinimum += 16;
85                         if (InheritedObjectAceTypePresent) lenMinimum += 16;
86                         if (len < lenMinimum)
87                                 throw new ArgumentException("Invalid ACE", "binaryForm");
88
89                         int pos = 12;
90                         if (ObjectAceTypePresent) {
91                                 ObjectAceType = ReadGuid(binaryForm, offset + pos); pos += 16;
92                         }
93                         if (InheritedObjectAceTypePresent) {
94                                 InheritedObjectAceType = ReadGuid(binaryForm, offset + pos); pos += 16;
95                         }
96                         
97                         SecurityIdentifier = new SecurityIdentifier(binaryForm, offset + pos);
98                         pos += SecurityIdentifier.BinaryLength;
99                         
100                         int opaqueLen = len - pos;
101                         if (opaqueLen > 0) {
102                                 byte[] opaque = new byte[opaqueLen];
103                                 Array.Copy(binaryForm, offset + pos, opaque, 0, opaqueLen);
104                                 SetOpaque (opaque);
105                         }
106                 }
107
108                 public override int BinaryLength
109                 {
110                         get {
111                                 int length = 12 + SecurityIdentifier.BinaryLength + OpaqueLength;
112                                 if (ObjectAceTypePresent) length += 16;
113                                 if (InheritedObjectAceTypePresent) length += 16;
114                                 return length;
115                         }
116                 }
117
118                 public Guid InheritedObjectAceType {
119                         get { return inherited_object_type; }
120                         set { inherited_object_type = value; }
121                 }
122                 
123                 bool InheritedObjectAceTypePresent {
124                         get { return 0 != (ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent); }
125                 }
126                 
127                 public ObjectAceFlags ObjectAceFlags {
128                         get { return object_ace_flags; }
129                         set { object_ace_flags = value; }
130                 }
131                 
132                 public Guid ObjectAceType {
133                         get { return object_ace_type; }
134                         set { object_ace_type = value; }
135                 }
136
137                 bool ObjectAceTypePresent {
138                         get { return 0 != (ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent); }
139                 }
140                 
141                 public override void GetBinaryForm (byte[] binaryForm, int offset)
142                 {
143                         int len = BinaryLength;
144                         binaryForm[offset++] = (byte)this.AceType;
145                         binaryForm[offset++] = (byte)this.AceFlags;
146                         WriteUShort ((ushort)len, binaryForm, offset); offset += 2;
147                         WriteInt (AccessMask, binaryForm, offset); offset += 4;
148                         WriteInt ((int)ObjectAceFlags, binaryForm, offset); offset += 4;
149                         
150                         if (0 != (ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent)) {
151                                 WriteGuid (ObjectAceType, binaryForm, offset); offset += 16;
152                         }
153                         if (0 != (ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent)) {
154                                 WriteGuid (InheritedObjectAceType, binaryForm, offset); offset += 16;
155                         }
156                         
157                         SecurityIdentifier.GetBinaryForm (binaryForm, offset);
158                         offset += SecurityIdentifier.BinaryLength;
159                         
160                         byte[] opaque = GetOpaque ();
161                         if (opaque != null) {
162                                 Array.Copy (opaque, 0, binaryForm, offset, opaque.Length);
163                                 offset += opaque.Length;
164                         }
165                 }
166                 
167                 public static int MaxOpaqueLength (bool isCallback)
168                 {
169                         // Varies by platform?
170                         return 65423;
171                 }
172                 
173                 internal override string GetSddlForm()
174                 {
175                         if (OpaqueLength != 0)
176                                 throw new NotImplementedException (
177                                         "Unable to convert conditional ACEs to SDDL");
178                         
179                         string objType = "";
180                         if ((ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent) != 0)
181                                 objType = object_ace_type.ToString("D");
182                         
183                         string inhObjType = "";
184                         if ((ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent) != 0)
185                                 inhObjType = inherited_object_type.ToString("D");
186                         
187                         return string.Format (CultureInfo.InvariantCulture,
188                                               "({0};{1};{2};{3};{4};{5})",
189                                               GetSddlAceType (AceType),
190                                               GetSddlAceFlags (AceFlags),
191                                               GetSddlAccessRights (AccessMask),
192                                               objType,
193                                               inhObjType,
194                                               SecurityIdentifier.GetSddlForm ());
195                 }
196                 
197                 private static AceType ConvertType(AceQualifier qualifier, bool isCallback)
198                 {
199                         switch(qualifier)
200                         {
201                         case AceQualifier.AccessAllowed:
202                                 if (isCallback)
203                                         return AceType.AccessAllowedCallbackObject;
204                                 else
205                                         return AceType.AccessAllowedObject;
206                                 
207                         case AceQualifier.AccessDenied:
208                                 if (isCallback)
209                                         return AceType.AccessDeniedCallbackObject;
210                                 else
211                                         return AceType.AccessDeniedObject;
212                                 
213                         case AceQualifier.SystemAlarm:
214                                 if (isCallback)
215                                         return AceType.SystemAlarmCallbackObject;
216                                 else
217                                         return AceType.SystemAlarmObject;
218                                 
219                         case AceQualifier.SystemAudit:
220                                 if (isCallback)
221                                         return AceType.SystemAuditCallbackObject;
222                                 else
223                                         return AceType.SystemAuditObject;
224                                 
225                         default:
226                                 throw new ArgumentException("Unrecognized ACE qualifier: " + qualifier, "qualifier");
227                         }
228                 }
229                 
230                 private void WriteGuid (Guid val, byte[] buffer,
231                                         int offset)
232                 {
233                         byte[] guidData = val.ToByteArray();
234                         Array.Copy(guidData, 0, buffer, offset, 16);
235                 }
236                 
237                 private Guid ReadGuid(byte[] buffer, int offset)
238                 {
239                         byte[] temp = new byte[16];
240                         Array.Copy(buffer, offset, temp, 0, 16);
241                         return new Guid(temp);
242                 }
243         }
244 }
245