245 lines
7.0 KiB
C#
245 lines
7.0 KiB
C#
|
//
|
||
|
// System.Security.AccessControl.RawAcl implementation
|
||
|
//
|
||
|
// Authors:
|
||
|
// Dick Porter <dick@ximian.com>
|
||
|
// Atsushi Enomoto <atsushi@ximian.com>
|
||
|
// Kenneth Bell
|
||
|
//
|
||
|
// Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||
|
// a copy of this software and associated documentation files (the
|
||
|
// "Software"), to deal in the Software without restriction, including
|
||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||
|
// the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be
|
||
|
// included in all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
//
|
||
|
|
||
|
using System.Collections.Generic;
|
||
|
using System.Text;
|
||
|
|
||
|
namespace System.Security.AccessControl {
|
||
|
public sealed class RawAcl : GenericAcl
|
||
|
{
|
||
|
private byte revision;
|
||
|
private List<GenericAce> list;
|
||
|
|
||
|
public RawAcl (byte revision, int capacity)
|
||
|
{
|
||
|
this.revision = revision;
|
||
|
list = new List<GenericAce> (capacity);
|
||
|
}
|
||
|
|
||
|
public RawAcl (byte [] binaryForm, int offset)
|
||
|
{
|
||
|
if (binaryForm == null)
|
||
|
throw new ArgumentNullException("binaryForm");
|
||
|
|
||
|
if (offset < 0 || offset > binaryForm.Length - 8)
|
||
|
throw new ArgumentOutOfRangeException("offset", offset, "Offset out of range");
|
||
|
|
||
|
revision = binaryForm[offset];
|
||
|
if (revision != AclRevision && revision != AclRevisionDS)
|
||
|
throw new ArgumentException("Invalid ACL - unknown revision", "binaryForm");
|
||
|
|
||
|
int binaryLength = ReadUShort(binaryForm, offset + 2);
|
||
|
if (offset > binaryForm.Length - binaryLength)
|
||
|
throw new ArgumentException("Invalid ACL - truncated", "binaryForm");
|
||
|
|
||
|
int pos = offset + 8;
|
||
|
int numAces = ReadUShort(binaryForm, offset + 4);
|
||
|
list = new List<GenericAce>(numAces);
|
||
|
for (int i = 0; i < numAces; ++i) {
|
||
|
GenericAce newAce = GenericAce.CreateFromBinaryForm(binaryForm, pos);
|
||
|
list.Add(newAce);
|
||
|
pos += newAce.BinaryLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal RawAcl(byte revision, List<GenericAce> aces)
|
||
|
{
|
||
|
this.revision = revision;
|
||
|
this.list = aces;
|
||
|
}
|
||
|
|
||
|
public override int BinaryLength
|
||
|
{
|
||
|
get {
|
||
|
int len = 8;
|
||
|
foreach(var ace in list)
|
||
|
{
|
||
|
len += ace.BinaryLength;
|
||
|
}
|
||
|
return len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override int Count {
|
||
|
get { return list.Count; }
|
||
|
}
|
||
|
|
||
|
public override GenericAce this [int index]
|
||
|
{
|
||
|
get { return list [index]; }
|
||
|
set { list [index] = value; }
|
||
|
}
|
||
|
|
||
|
public override byte Revision {
|
||
|
get { return revision; }
|
||
|
}
|
||
|
|
||
|
public override void GetBinaryForm (byte[] binaryForm,
|
||
|
int offset)
|
||
|
{
|
||
|
if(binaryForm == null)
|
||
|
throw new ArgumentNullException("binaryForm");
|
||
|
|
||
|
if(offset < 0
|
||
|
|| offset > binaryForm.Length - BinaryLength)
|
||
|
throw new ArgumentException("Offset out of range", "offset");
|
||
|
|
||
|
binaryForm[offset] = Revision;
|
||
|
binaryForm[offset + 1] = 0;
|
||
|
WriteUShort((ushort)BinaryLength, binaryForm,
|
||
|
offset + 2);
|
||
|
WriteUShort((ushort)list.Count, binaryForm,
|
||
|
offset + 4);
|
||
|
WriteUShort(0, binaryForm, offset + 6);
|
||
|
|
||
|
int pos = offset + 8;
|
||
|
foreach(var ace in list)
|
||
|
{
|
||
|
ace.GetBinaryForm(binaryForm, pos);
|
||
|
pos += ace.BinaryLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void InsertAce (int index, GenericAce ace)
|
||
|
{
|
||
|
if (ace == null)
|
||
|
throw new ArgumentNullException ("ace");
|
||
|
list.Insert (index, ace);
|
||
|
}
|
||
|
|
||
|
public void RemoveAce (int index)
|
||
|
{
|
||
|
list.RemoveAt (index);
|
||
|
}
|
||
|
|
||
|
internal override string GetSddlForm(ControlFlags sdFlags,
|
||
|
bool isDacl)
|
||
|
{
|
||
|
StringBuilder result = new StringBuilder();
|
||
|
|
||
|
if(isDacl) {
|
||
|
if((sdFlags & ControlFlags.DiscretionaryAclProtected) != 0)
|
||
|
result.Append("P");
|
||
|
if((sdFlags & ControlFlags.DiscretionaryAclAutoInheritRequired) != 0)
|
||
|
result.Append("AR");
|
||
|
if((sdFlags & ControlFlags.DiscretionaryAclAutoInherited) != 0)
|
||
|
result.Append("AI");
|
||
|
} else {
|
||
|
if((sdFlags & ControlFlags.SystemAclProtected) != 0)
|
||
|
result.Append("P");
|
||
|
if((sdFlags & ControlFlags.SystemAclAutoInheritRequired) != 0)
|
||
|
result.Append("AR");
|
||
|
if((sdFlags & ControlFlags.SystemAclAutoInherited) != 0)
|
||
|
result.Append("AI");
|
||
|
}
|
||
|
|
||
|
foreach(var ace in list)
|
||
|
{
|
||
|
result.Append(ace.GetSddlForm());
|
||
|
}
|
||
|
|
||
|
return result.ToString();
|
||
|
}
|
||
|
|
||
|
internal static RawAcl ParseSddlForm(string sddlForm,
|
||
|
bool isDacl,
|
||
|
ref ControlFlags sdFlags,
|
||
|
ref int pos)
|
||
|
{
|
||
|
ParseFlags(sddlForm, isDacl, ref sdFlags, ref pos);
|
||
|
|
||
|
byte revision = GenericAcl.AclRevision;
|
||
|
List<GenericAce> aces = new List<GenericAce>();
|
||
|
while(pos < sddlForm.Length && sddlForm[pos] == '(') {
|
||
|
GenericAce ace = GenericAce.CreateFromSddlForm(
|
||
|
sddlForm, ref pos);
|
||
|
if ((ace as ObjectAce) != null)
|
||
|
revision = GenericAcl.AclRevisionDS;
|
||
|
aces.Add(ace);
|
||
|
}
|
||
|
|
||
|
|
||
|
return new RawAcl(revision, aces);
|
||
|
}
|
||
|
|
||
|
private static void ParseFlags(string sddlForm,
|
||
|
bool isDacl,
|
||
|
ref ControlFlags sdFlags,
|
||
|
ref int pos)
|
||
|
{
|
||
|
char ch = Char.ToUpperInvariant(sddlForm[pos]);
|
||
|
while(ch == 'P' || ch == 'A') {
|
||
|
if(ch == 'P') {
|
||
|
if (isDacl)
|
||
|
sdFlags |= ControlFlags.DiscretionaryAclProtected;
|
||
|
else
|
||
|
sdFlags |= ControlFlags.SystemAclProtected;
|
||
|
pos++;
|
||
|
} else if(sddlForm.Length > pos + 1) {
|
||
|
ch = Char.ToUpperInvariant(sddlForm[pos + 1]);
|
||
|
if(ch == 'R') {
|
||
|
if (isDacl)
|
||
|
sdFlags |= ControlFlags.DiscretionaryAclAutoInheritRequired;
|
||
|
else
|
||
|
sdFlags |= ControlFlags.SystemAclAutoInheritRequired;
|
||
|
pos += 2;
|
||
|
} else if (ch == 'I') {
|
||
|
if (isDacl)
|
||
|
sdFlags |= ControlFlags.DiscretionaryAclAutoInherited;
|
||
|
else
|
||
|
sdFlags |= ControlFlags.SystemAclAutoInherited;
|
||
|
pos += 2;
|
||
|
} else {
|
||
|
throw new ArgumentException("Invalid SDDL string.", "sddlForm");
|
||
|
}
|
||
|
} else {
|
||
|
throw new ArgumentException("Invalid SDDL string.", "sddlForm");
|
||
|
}
|
||
|
|
||
|
ch = Char.ToUpperInvariant(sddlForm[pos]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
private void WriteUShort (ushort val, byte[] buffer, int offset)
|
||
|
{
|
||
|
buffer[offset] = (byte)val;
|
||
|
buffer[offset + 1] = (byte)(val >> 8);
|
||
|
}
|
||
|
|
||
|
private ushort ReadUShort (byte[] buffer, int offset)
|
||
|
{
|
||
|
return (ushort)((((int)buffer[offset + 0]) << 0)
|
||
|
| (((int)buffer[offset + 1]) << 8));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|