mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
7.1 KiB
264 lines
7.1 KiB
using System;
|
|
using System.Security.Principal;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Security2
|
|
{
|
|
public class IdentityReference2
|
|
{
|
|
protected static Regex sidValidation = new Regex("(S-1-)[0-9-]+", RegexOptions.IgnoreCase);
|
|
protected SecurityIdentifier sid;
|
|
protected NTAccount ntAccount;
|
|
protected string lastError;
|
|
|
|
#region Properties
|
|
|
|
public string Sid
|
|
{
|
|
get { return sid.Value; }
|
|
}
|
|
|
|
public string AccountName
|
|
{
|
|
get
|
|
{
|
|
return ntAccount != null ? ntAccount.Value : string.Empty;
|
|
}
|
|
}
|
|
|
|
public string LastError
|
|
{
|
|
get { return lastError; }
|
|
}
|
|
|
|
#endregion Properties
|
|
|
|
#region Constructors
|
|
|
|
public IdentityReference2(IdentityReference ir)
|
|
{
|
|
ntAccount = ir as NTAccount;
|
|
if (ntAccount != null)
|
|
{
|
|
//throws an IdentityNotMapped Exception if the account cannot be translated
|
|
sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
|
|
}
|
|
else
|
|
{
|
|
sid = ir as SecurityIdentifier;
|
|
if (sid != null)
|
|
{
|
|
try
|
|
{
|
|
ntAccount = (NTAccount)sid.Translate(typeof(NTAccount));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
lastError = ex.Message;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public IdentityReference2(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
throw new ArgumentException("The value cannot be empty");
|
|
|
|
var sidMatch = sidValidation.Match(value);
|
|
|
|
if (!string.IsNullOrEmpty(sidMatch.Value))
|
|
{
|
|
//creating a SecurityIdentifier should always work if the string is in the right format
|
|
try
|
|
{
|
|
sid = new SecurityIdentifier(sidMatch.Value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidCastException("Could not create an IdentityReference2 with the given SID", ex);
|
|
}
|
|
|
|
//this is only going to work if the SID can be resolved
|
|
try
|
|
{
|
|
ntAccount = (NTAccount)sid.Translate(typeof(NTAccount));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
lastError = ex.Message;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
//creating an NTAccount always works, the OS does not verify the name
|
|
ntAccount = new NTAccount(value);
|
|
//verification si done by translating the name into a SecurityIdentifier (SID)
|
|
sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
|
|
}
|
|
catch (IdentityNotMappedException ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Constructors
|
|
|
|
#region Conversion
|
|
|
|
//NTAccount
|
|
public static explicit operator NTAccount(IdentityReference2 ir2)
|
|
{
|
|
return ir2.ntAccount;
|
|
}
|
|
|
|
public static explicit operator IdentityReference2(NTAccount ntAccount)
|
|
{
|
|
return new IdentityReference2(ntAccount);
|
|
}
|
|
|
|
//SecurityIdentifier
|
|
public static explicit operator SecurityIdentifier(IdentityReference2 ir2)
|
|
{
|
|
return ir2.sid;
|
|
}
|
|
|
|
public static explicit operator IdentityReference2(SecurityIdentifier sid)
|
|
{
|
|
return new IdentityReference2(sid);
|
|
}
|
|
|
|
//IdentityReference
|
|
public static implicit operator IdentityReference(IdentityReference2 ir2)
|
|
{
|
|
return ir2.sid;
|
|
}
|
|
|
|
public static implicit operator IdentityReference2(IdentityReference ir)
|
|
{
|
|
return new IdentityReference2(ir);
|
|
}
|
|
|
|
//string
|
|
public static implicit operator IdentityReference2(string value)
|
|
{
|
|
return new IdentityReference2(value);
|
|
}
|
|
|
|
public static implicit operator string(IdentityReference2 ir2)
|
|
{
|
|
return ir2.ToString();
|
|
}
|
|
|
|
#endregion Conversion
|
|
|
|
#region comparison
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
//Instance cannot be null
|
|
if (ReferenceEquals(obj, null))
|
|
return false;
|
|
|
|
//Instances are equal
|
|
if (ReferenceEquals(this, obj))
|
|
return true;
|
|
|
|
SecurityIdentifier sid = obj as SecurityIdentifier;
|
|
if (sid != null)
|
|
{
|
|
return this.sid == sid;
|
|
}
|
|
|
|
var ntAccount = obj as NTAccount;
|
|
if (ntAccount != null)
|
|
{
|
|
return this.ntAccount == ntAccount;
|
|
}
|
|
|
|
IdentityReference2 ir2 = obj as IdentityReference2;
|
|
if (ir2 != null)
|
|
{
|
|
return this.sid == ir2.sid;
|
|
}
|
|
|
|
string value = obj as string;
|
|
if (value != null)
|
|
{
|
|
if (this.sid.Value == value)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (this.ntAccount != null)
|
|
{
|
|
if (this.ntAccount.Value.ToLower() == value.ToLower())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return sid.GetHashCode();
|
|
}
|
|
|
|
public static bool operator ==(IdentityReference2 ir1, IdentityReference2 ir2)
|
|
{
|
|
//Instances are equal
|
|
if (ReferenceEquals(ir1, ir2))
|
|
return true;
|
|
|
|
//Instance cannot be null
|
|
if (ReferenceEquals(ir1, null) | ReferenceEquals(ir2, null))
|
|
return false;
|
|
|
|
return ir1.Equals(ir2);
|
|
}
|
|
|
|
public static bool operator !=(IdentityReference2 ir1, IdentityReference2 ir2)
|
|
{
|
|
//Instances are equal
|
|
if (ReferenceEquals(ir1, ir2))
|
|
return false;
|
|
|
|
//Instance cannot be null
|
|
if (ReferenceEquals(ir1, null) | ReferenceEquals(ir2, null))
|
|
return true;
|
|
|
|
return !ir1.Equals(ir2);
|
|
}
|
|
|
|
#endregion comparison
|
|
|
|
#region Methods
|
|
|
|
public byte[] GetBinaryForm()
|
|
{
|
|
byte[] rawSid = new byte[sid.BinaryLength];
|
|
sid.GetBinaryForm(rawSid, 0);
|
|
return rawSid;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if (ntAccount == null)
|
|
{
|
|
return sid.ToString();
|
|
}
|
|
else
|
|
{
|
|
return ntAccount.ToString();
|
|
}
|
|
}
|
|
|
|
#endregion Methods
|
|
}
|
|
}
|