|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// <OWNER>Microsoft</OWNER>
//
//
// KeyContainerPermission.cs
//
namespace System.Security.Permissions {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Security.Util;
using System.Globalization;
using System.Diagnostics.Contracts;
#if !FEATURE_PAL
[Serializable]
[Flags]
[System.Runtime.InteropServices.ComVisible(true)]
public enum KeyContainerPermissionFlags {
NoFlags = 0x0000,
Create = 0x0001,
Open = 0x0002,
Delete = 0x0004,
Import = 0x0010,
Export = 0x0020,
Sign = 0x0100,
Decrypt = 0x0200,
ViewAcl = 0x1000,
ChangeAcl = 0x2000,
AllFlags = 0x3337
}
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class KeyContainerPermissionAccessEntry {
private string m_keyStore;
private string m_providerName;
private int m_providerType;
private string m_keyContainerName;
private int m_keySpec;
private KeyContainerPermissionFlags m_flags;
internal KeyContainerPermissionAccessEntry(KeyContainerPermissionAccessEntry accessEntry) :
this (accessEntry.KeyStore, accessEntry.ProviderName, accessEntry.ProviderType, accessEntry.KeyContainerName,
accessEntry.KeySpec, accessEntry.Flags) {
}
public KeyContainerPermissionAccessEntry(string keyContainerName, KeyContainerPermissionFlags flags) :
this (null, null, -1, keyContainerName, -1, flags) {
}
public KeyContainerPermissionAccessEntry(CspParameters parameters, KeyContainerPermissionFlags flags) :
this((parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? "Machine" : "User",
parameters.ProviderName,
parameters.ProviderType,
parameters.KeyContainerName,
parameters.KeyNumber,
flags) {
}
public KeyContainerPermissionAccessEntry(string keyStore, string providerName, int providerType,
string keyContainerName, int keySpec, KeyContainerPermissionFlags flags) {
m_providerName = (providerName == null ? "*" : providerName);
m_providerType = providerType;
m_keyContainerName = (keyContainerName == null ? "*" : keyContainerName);
m_keySpec = keySpec;
KeyStore = keyStore;
Flags = flags;
}
public string KeyStore {
get {
return m_keyStore;
}
set {
// Unrestricted entries are invalid; they should not be allowed.
if (IsUnrestrictedEntry(value, this.ProviderName, this.ProviderType, this.KeyContainerName, this.KeySpec))
throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
if (value == null) {
m_keyStore = "*";
} else {
if (value != "User" && value != "Machine" && value != "*")
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKeyStore", value), "value");
m_keyStore = value;
}
}
}
public string ProviderName {
get {
return m_providerName;
}
set {
// Unrestricted entries are invalid; they should not be allowed.
if (IsUnrestrictedEntry(this.KeyStore, value, this.ProviderType, this.KeyContainerName, this.KeySpec))
throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
if (value == null)
m_providerName = "*";
else
m_providerName = value;
}
}
public int ProviderType {
get {
return m_providerType;
}
set {
// Unrestricted entries are invalid; they should not be allowed.
if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, value, this.KeyContainerName, this.KeySpec))
throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
m_providerType = value;
}
}
public string KeyContainerName {
get {
return m_keyContainerName;
}
set {
// Unrestricted entries are invalid; they should not be allowed.
if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, value, this.KeySpec))
throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
if (value == null)
m_keyContainerName = "*";
else
m_keyContainerName = value;
}
}
public int KeySpec {
get {
return m_keySpec;
}
set {
// Unrestricted entries are invalid; they should not be allowed.
if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, this.KeyContainerName, value))
throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
m_keySpec = value;
}
}
public KeyContainerPermissionFlags Flags {
get {
return m_flags;
}
set {
KeyContainerPermission.VerifyFlags(value);
m_flags = value;
}
}
public override bool Equals (Object o) {
KeyContainerPermissionAccessEntry accessEntry = o as KeyContainerPermissionAccessEntry;
if (accessEntry == null)
return false;
if (accessEntry.m_keyStore != m_keyStore) return false;
if (accessEntry.m_providerName != m_providerName) return false;
if (accessEntry.m_providerType != m_providerType) return false;
if (accessEntry.m_keyContainerName != m_keyContainerName) return false;
if (accessEntry.m_keySpec != m_keySpec) return false;
return true;
}
public override int GetHashCode () {
int hash = 0;
hash |= (this.m_keyStore.GetHashCode() & 0x000000FF) << 24;
hash |= (this.m_providerName.GetHashCode() & 0x000000FF) << 16;
hash |= (this.m_providerType & 0x0000000F) << 12;
hash |= (this.m_keyContainerName.GetHashCode() & 0x000000FF) << 4;
hash |= (this.m_keySpec & 0x0000000F);
return hash;
}
internal bool IsSubsetOf (KeyContainerPermissionAccessEntry target) {
if (target.m_keyStore != "*" && this.m_keyStore != target.m_keyStore)
return false;
if (target.m_providerName != "*" && this.m_providerName != target.m_providerName)
return false;
if (target.m_providerType != -1 && this.m_providerType != target.m_providerType)
return false;
if (target.m_keyContainerName != "*" && this.m_keyContainerName != target.m_keyContainerName)
return false;
if (target.m_keySpec != -1 && this.m_keySpec != target.m_keySpec)
return false;
return true;
}
internal static bool IsUnrestrictedEntry (string keyStore, string providerName, int providerType,
string keyContainerName, int keySpec) {
if (keyStore != "*" && keyStore != null) return false;
if (providerName != "*" && providerName != null) return false;
if (providerType != -1) return false;
if (keyContainerName != "*" && keyContainerName != null) return false;
if (keySpec != -1) return false;
return true;
}
}
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class KeyContainerPermissionAccessEntryCollection : ICollection {
private ArrayList m_list;
private KeyContainerPermissionFlags m_globalFlags;
private KeyContainerPermissionAccessEntryCollection () {}
internal KeyContainerPermissionAccessEntryCollection (KeyContainerPermissionFlags globalFlags) {
m_list = new ArrayList();
m_globalFlags = globalFlags;
}
public KeyContainerPermissionAccessEntry this[int index] {
get {
if (index < 0)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
if (index >= Count)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
return (KeyContainerPermissionAccessEntry)m_list[index];
}
}
public int Count {
get {
return m_list.Count;
}
}
public int Add (KeyContainerPermissionAccessEntry accessEntry) {
if (accessEntry == null)
throw new ArgumentNullException("accessEntry");
Contract.EndContractBlock();
int index = m_list.IndexOf(accessEntry);
if (index == -1) {
if (accessEntry.Flags != m_globalFlags) {
return m_list.Add(accessEntry);
}
else
return -1;
} else {
// We pick up the intersection of the 2 flags. This is the secure choice
// so we are opting for it.
((KeyContainerPermissionAccessEntry)m_list[index]).Flags &= accessEntry.Flags;
return index;
}
}
public void Clear () {
m_list.Clear();
}
public int IndexOf (KeyContainerPermissionAccessEntry accessEntry) {
return m_list.IndexOf(accessEntry);
}
public void Remove (KeyContainerPermissionAccessEntry accessEntry) {
if (accessEntry == null)
throw new ArgumentNullException("accessEntry");
Contract.EndContractBlock();
m_list.Remove(accessEntry);
}
public KeyContainerPermissionAccessEntryEnumerator GetEnumerator () {
return new KeyContainerPermissionAccessEntryEnumerator(this);
}
/// <internalonly/>
IEnumerator IEnumerable.GetEnumerator () {
return new KeyContainerPermissionAccessEntryEnumerator(this);
}
/// <internalonly/>
void ICollection.CopyTo (Array array, int index) {
if (array == null)
throw new ArgumentNullException("array");
if (array.Rank != 1)
throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
if (index < 0 || index >= array.Length)
throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
if (index + this.Count > array.Length)
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
Contract.EndContractBlock();
for (int i=0; i < this.Count; i++) {
array.SetValue(this[i], index);
index++;
}
}
public void CopyTo (KeyContainerPermissionAccessEntry[] array, int index) {
((ICollection)this).CopyTo(array, index);
}
public bool IsSynchronized {
get {
return false;
}
}
public Object SyncRoot {
get {
return this;
}
}
}
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class KeyContainerPermissionAccessEntryEnumerator : IEnumerator {
private KeyContainerPermissionAccessEntryCollection m_entries;
private int m_current;
private KeyContainerPermissionAccessEntryEnumerator () {}
internal KeyContainerPermissionAccessEntryEnumerator (KeyContainerPermissionAccessEntryCollection entries) {
m_entries = entries;
m_current = -1;
}
public KeyContainerPermissionAccessEntry Current {
get {
return m_entries[m_current];
}
}
/// <internalonly/>
Object IEnumerator.Current {
get {
return (Object) m_entries[m_current];
}
}
public bool MoveNext() {
if (m_current == ((int) m_entries.Count - 1))
return false;
m_current++;
return true;
}
public void Reset() {
m_current = -1;
}
}
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class KeyContainerPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
private KeyContainerPermissionFlags m_flags;
private KeyContainerPermissionAccessEntryCollection m_accessEntries;
public KeyContainerPermission (PermissionState state) {
if (state == PermissionState.Unrestricted)
m_flags = KeyContainerPermissionFlags.AllFlags;
else if (state == PermissionState.None)
m_flags = KeyContainerPermissionFlags.NoFlags;
else
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
}
public KeyContainerPermission (KeyContainerPermissionFlags flags) {
VerifyFlags(flags);
m_flags = flags;
m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
}
public KeyContainerPermission (KeyContainerPermissionFlags flags, KeyContainerPermissionAccessEntry[] accessList) {
if (accessList == null)
throw new ArgumentNullException("accessList");
Contract.EndContractBlock();
VerifyFlags(flags);
m_flags = flags;
m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
for (int index = 0; index < accessList.Length; index++) {
m_accessEntries.Add(accessList[index]);
}
}
public KeyContainerPermissionFlags Flags {
get {
return m_flags;
}
}
public KeyContainerPermissionAccessEntryCollection AccessEntries {
get {
return m_accessEntries;
}
}
public bool IsUnrestricted () {
if (m_flags != KeyContainerPermissionFlags.AllFlags)
return false;
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
if ((accessEntry.Flags & KeyContainerPermissionFlags.AllFlags) != KeyContainerPermissionFlags.AllFlags)
return false;
}
return true;
}
private bool IsEmpty () {
if (this.Flags == KeyContainerPermissionFlags.NoFlags) {
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
if (accessEntry.Flags != KeyContainerPermissionFlags.NoFlags)
return false;
}
return true;
}
return false;
}
//
// IPermission implementation
//
public override bool IsSubsetOf (IPermission target) {
if (target == null)
return IsEmpty();
if (!VerifyType(target))
throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
KeyContainerPermission operand = (KeyContainerPermission) target;
// since there are containers that are neither in the access list of the source, nor in the
// access list of the target, the source flags must be a subset of the target flags.
if ((this.m_flags & operand.m_flags) != this.m_flags)
return false;
// Any entry in the source should have "applicable" flags in the destination that actually
// are less restrictive than the flags in the source.
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
KeyContainerPermissionFlags targetFlags = GetApplicableFlags(accessEntry, operand);
if ((accessEntry.Flags & targetFlags) != accessEntry.Flags)
return false;
}
// Any entry in the target should have "applicable" flags in the source that actually
// are more restrictive than the flags in the target.
foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
KeyContainerPermissionFlags sourceFlags = GetApplicableFlags(accessEntry, this);
if ((sourceFlags & accessEntry.Flags) != sourceFlags)
return false;
}
return true;
}
public override IPermission Intersect (IPermission target) {
if (target == null)
return null;
if (!VerifyType(target))
throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
KeyContainerPermission operand = (KeyContainerPermission) target;
if (this.IsEmpty() || operand.IsEmpty())
return null;
KeyContainerPermissionFlags flags_intersect = operand.m_flags & this.m_flags;
KeyContainerPermission cp = new KeyContainerPermission(flags_intersect);
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
cp.AddAccessEntryAndIntersect(accessEntry, operand);
}
foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
cp.AddAccessEntryAndIntersect(accessEntry, this);
}
return cp.IsEmpty() ? null : cp;
}
public override IPermission Union (IPermission target) {
if (target == null)
return this.Copy();
if (!VerifyType(target))
throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
KeyContainerPermission operand = (KeyContainerPermission) target;
if (this.IsUnrestricted() || operand.IsUnrestricted())
return new KeyContainerPermission(PermissionState.Unrestricted);
KeyContainerPermissionFlags flags_union = (KeyContainerPermissionFlags) (m_flags | operand.m_flags);
KeyContainerPermission cp = new KeyContainerPermission(flags_union);
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
cp.AddAccessEntryAndUnion(accessEntry, operand);
}
foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
cp.AddAccessEntryAndUnion(accessEntry, this);
}
return cp.IsEmpty() ? null : cp;
}
public override IPermission Copy () {
if (this.IsEmpty())
return null;
KeyContainerPermission cp = new KeyContainerPermission((KeyContainerPermissionFlags)m_flags);
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
cp.AccessEntries.Add(accessEntry);
}
return cp;
}
#if FEATURE_CAS_POLICY
public override SecurityElement ToXml () {
SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.KeyContainerPermission");
if (!IsUnrestricted()) {
securityElement.AddAttribute("Flags", m_flags.ToString());
if (AccessEntries.Count > 0) {
SecurityElement al = new SecurityElement("AccessList");
foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
SecurityElement entryElem = new SecurityElement("AccessEntry");
entryElem.AddAttribute("KeyStore", accessEntry.KeyStore);
entryElem.AddAttribute("ProviderName", accessEntry.ProviderName);
entryElem.AddAttribute("ProviderType", accessEntry.ProviderType.ToString(null, null));
entryElem.AddAttribute("KeyContainerName", accessEntry.KeyContainerName);
entryElem.AddAttribute("KeySpec", accessEntry.KeySpec.ToString(null, null));
entryElem.AddAttribute("Flags", accessEntry.Flags.ToString());
al.AddChild(entryElem);
}
securityElement.AddChild(al);
}
} else
securityElement.AddAttribute("Unrestricted", "true");
return securityElement;
}
public override void FromXml (SecurityElement securityElement) {
CodeAccessPermission.ValidateElement(securityElement, this);
if (XMLUtil.IsUnrestricted(securityElement)) {
m_flags = KeyContainerPermissionFlags.AllFlags;
m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
return;
}
m_flags = KeyContainerPermissionFlags.NoFlags;
string strFlags = securityElement.Attribute("Flags");
if (strFlags != null) {
KeyContainerPermissionFlags flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strFlags);
VerifyFlags(flags);
m_flags = flags;
}
m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
IEnumerator enumerator = securityElement.Children.GetEnumerator();
while (enumerator.MoveNext()) {
SecurityElement current = (SecurityElement) enumerator.Current;
if (current != null) {
if (String.Equals(current.Tag, "AccessList"))
AddAccessEntries(current);
}
}
}
}
#endif // FEATURE_CAS_POLICY
/// <internalonly/>
int IBuiltInPermission.GetTokenIndex () {
return KeyContainerPermission.GetTokenIndex();
}
//
// private methods
//
private void AddAccessEntries(SecurityElement securityElement) {
if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
IEnumerator elemEnumerator = securityElement.Children.GetEnumerator();
while (elemEnumerator.MoveNext()) {
SecurityElement current = (SecurityElement) elemEnumerator.Current;
if (current != null) {
if (String.Equals(current.Tag, "AccessEntry")) {
int iMax = current.m_lAttributes.Count;
Contract.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
string keyStore = null;
string providerName = null;
int providerType = -1;
string keyContainerName = null;
int keySpec = -1;
KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
for (int i = 0; i < iMax; i += 2) {
String strAttrName = (String) current.m_lAttributes[i];
String strAttrValue = (String) current.m_lAttributes[i+1];
if (String.Equals(strAttrName, "KeyStore"))
keyStore = strAttrValue;
if (String.Equals(strAttrName, "ProviderName"))
providerName = strAttrValue;
else if (String.Equals(strAttrName, "ProviderType"))
providerType = Convert.ToInt32(strAttrValue, null);
else if (String.Equals(strAttrName, "KeyContainerName"))
keyContainerName = strAttrValue;
else if (String.Equals(strAttrName, "KeySpec"))
keySpec = Convert.ToInt32(strAttrValue, null);
else if (String.Equals(strAttrName, "Flags")) {
flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strAttrValue);
}
}
KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(keyStore, providerName, providerType, keyContainerName, keySpec, flags);
AccessEntries.Add(accessEntry);
}
}
}
}
}
private void AddAccessEntryAndUnion (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
newAccessEntry.Flags |= GetApplicableFlags(accessEntry, target);
AccessEntries.Add(newAccessEntry);
}
private void AddAccessEntryAndIntersect (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
newAccessEntry.Flags &= GetApplicableFlags(accessEntry, target);
AccessEntries.Add(newAccessEntry);
}
//
// private/internal static methods.
//
internal static void VerifyFlags (KeyContainerPermissionFlags flags) {
if ((flags & ~KeyContainerPermissionFlags.AllFlags) != 0)
throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flags));
Contract.EndContractBlock();
}
private static KeyContainerPermissionFlags GetApplicableFlags (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
bool applyDefaultFlags = true;
// If the entry exists in the target, return the flag of the target entry.
int index = target.AccessEntries.IndexOf(accessEntry);
if (index != -1) {
flags = ((KeyContainerPermissionAccessEntry)target.AccessEntries[index]).Flags;
return flags;
}
// Intersect the flags in all the target entries that apply to the current access entry,
foreach (KeyContainerPermissionAccessEntry targetAccessEntry in target.AccessEntries) {
if (accessEntry.IsSubsetOf(targetAccessEntry)) {
if (applyDefaultFlags == false) {
flags &= targetAccessEntry.Flags;
} else {
flags = targetAccessEntry.Flags;
applyDefaultFlags = false;
}
}
}
// If no target entry applies to the current entry, the default global flag applies.
if (applyDefaultFlags)
flags = target.Flags;
return flags;
}
private static int GetTokenIndex() {
return BuiltInPermissionIndex.KeyContainerPermissionIndex;
}
}
#endif // !FEATURE_PAL
}
|