2 // System.Security.AccessControl.RawAcl implementation
5 // Dick Porter <dick@ximian.com>
6 // Atsushi Enomoto <atsushi@ximian.com>
9 // Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
31 using System.Collections.Generic;
34 namespace System.Security.AccessControl {
35 public sealed class RawAcl : GenericAcl
37 private byte revision;
38 private List<GenericAce> list;
40 public RawAcl (byte revision, int capacity)
42 this.revision = revision;
43 list = new List<GenericAce> (capacity);
46 public RawAcl (byte [] binaryForm, int offset)
48 if (binaryForm == null)
49 throw new ArgumentNullException("binaryForm");
51 if (offset < 0 || offset > binaryForm.Length - 8)
52 throw new ArgumentOutOfRangeException("offset", offset, "Offset out of range");
54 revision = binaryForm[offset];
55 if (revision != AclRevision && revision != AclRevisionDS)
56 throw new ArgumentException("Invalid ACL - unknown revision", "binaryForm");
58 int binaryLength = ReadUShort(binaryForm, offset + 2);
59 if (offset > binaryForm.Length - binaryLength)
60 throw new ArgumentException("Invalid ACL - truncated", "binaryForm");
63 int numAces = ReadUShort(binaryForm, offset + 4);
64 list = new List<GenericAce>(numAces);
65 for (int i = 0; i < numAces; ++i) {
66 GenericAce newAce = GenericAce.CreateFromBinaryForm(binaryForm, pos);
68 pos += newAce.BinaryLength;
72 internal RawAcl(byte revision, List<GenericAce> aces)
74 this.revision = revision;
78 public override int BinaryLength
82 foreach(var ace in list)
84 len += ace.BinaryLength;
90 public override int Count {
91 get { return list.Count; }
94 public override GenericAce this [int index]
96 get { return list [index]; }
97 set { list [index] = value; }
100 public override byte Revision {
101 get { return revision; }
104 public override void GetBinaryForm (byte[] binaryForm,
107 if(binaryForm == null)
108 throw new ArgumentNullException("binaryForm");
111 || offset > binaryForm.Length - BinaryLength)
112 throw new ArgumentException("Offset out of range", "offset");
114 binaryForm[offset] = Revision;
115 binaryForm[offset + 1] = 0;
116 WriteUShort((ushort)BinaryLength, binaryForm,
118 WriteUShort((ushort)list.Count, binaryForm,
120 WriteUShort(0, binaryForm, offset + 6);
122 int pos = offset + 8;
123 foreach(var ace in list)
125 ace.GetBinaryForm(binaryForm, pos);
126 pos += ace.BinaryLength;
130 public void InsertAce (int index, GenericAce ace)
133 throw new ArgumentNullException ("ace");
134 list.Insert (index, ace);
137 public void RemoveAce (int index)
139 list.RemoveAt (index);
142 internal override string GetSddlForm(ControlFlags sdFlags,
145 StringBuilder result = new StringBuilder();
148 if((sdFlags & ControlFlags.DiscretionaryAclProtected) != 0)
150 if((sdFlags & ControlFlags.DiscretionaryAclAutoInheritRequired) != 0)
152 if((sdFlags & ControlFlags.DiscretionaryAclAutoInherited) != 0)
155 if((sdFlags & ControlFlags.SystemAclProtected) != 0)
157 if((sdFlags & ControlFlags.SystemAclAutoInheritRequired) != 0)
159 if((sdFlags & ControlFlags.SystemAclAutoInherited) != 0)
163 foreach(var ace in list)
165 result.Append(ace.GetSddlForm());
168 return result.ToString();
171 internal static RawAcl ParseSddlForm(string sddlForm,
173 ref ControlFlags sdFlags,
176 ParseFlags(sddlForm, isDacl, ref sdFlags, ref pos);
178 byte revision = GenericAcl.AclRevision;
179 List<GenericAce> aces = new List<GenericAce>();
180 while(pos < sddlForm.Length && sddlForm[pos] == '(') {
181 GenericAce ace = GenericAce.CreateFromSddlForm(
183 if ((ace as ObjectAce) != null)
184 revision = GenericAcl.AclRevisionDS;
189 return new RawAcl(revision, aces);
192 private static void ParseFlags(string sddlForm,
194 ref ControlFlags sdFlags,
197 char ch = Char.ToUpperInvariant(sddlForm[pos]);
198 while(ch == 'P' || ch == 'A') {
201 sdFlags |= ControlFlags.DiscretionaryAclProtected;
203 sdFlags |= ControlFlags.SystemAclProtected;
205 } else if(sddlForm.Length > pos + 1) {
206 ch = Char.ToUpperInvariant(sddlForm[pos + 1]);
209 sdFlags |= ControlFlags.DiscretionaryAclAutoInheritRequired;
211 sdFlags |= ControlFlags.SystemAclAutoInheritRequired;
213 } else if (ch == 'I') {
215 sdFlags |= ControlFlags.DiscretionaryAclAutoInherited;
217 sdFlags |= ControlFlags.SystemAclAutoInherited;
220 throw new ArgumentException("Invalid SDDL string.", "sddlForm");
223 throw new ArgumentException("Invalid SDDL string.", "sddlForm");
226 ch = Char.ToUpperInvariant(sddlForm[pos]);
231 private void WriteUShort (ushort val, byte[] buffer, int offset)
233 buffer[offset] = (byte)val;
234 buffer[offset + 1] = (byte)(val >> 8);
237 private ushort ReadUShort (byte[] buffer, int offset)
239 return (ushort)((((int)buffer[offset + 0]) << 0)
240 | (((int)buffer[offset + 1]) << 8));