3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>[....]</OWNER>
10 // KeyContainerPermission.cs
13 namespace System.Security.Permissions {
15 using System.Collections;
16 using System.Collections.Generic;
17 using System.Security.Cryptography;
18 using System.Security.Util;
19 using System.Globalization;
20 using System.Diagnostics.Contracts;
26 [System.Runtime.InteropServices.ComVisible(true)]
27 public enum KeyContainerPermissionFlags {
47 [System.Runtime.InteropServices.ComVisible(true)]
48 public sealed class KeyContainerPermissionAccessEntry {
49 private string m_keyStore;
50 private string m_providerName;
51 private int m_providerType;
52 private string m_keyContainerName;
53 private int m_keySpec;
54 private KeyContainerPermissionFlags m_flags;
56 internal KeyContainerPermissionAccessEntry(KeyContainerPermissionAccessEntry accessEntry) :
57 this (accessEntry.KeyStore, accessEntry.ProviderName, accessEntry.ProviderType, accessEntry.KeyContainerName,
58 accessEntry.KeySpec, accessEntry.Flags) {
61 public KeyContainerPermissionAccessEntry(string keyContainerName, KeyContainerPermissionFlags flags) :
62 this (null, null, -1, keyContainerName, -1, flags) {
65 public KeyContainerPermissionAccessEntry(CspParameters parameters, KeyContainerPermissionFlags flags) :
66 this((parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? "Machine" : "User",
67 parameters.ProviderName,
68 parameters.ProviderType,
69 parameters.KeyContainerName,
74 public KeyContainerPermissionAccessEntry(string keyStore, string providerName, int providerType,
75 string keyContainerName, int keySpec, KeyContainerPermissionFlags flags) {
76 m_providerName = (providerName == null ? "*" : providerName);
77 m_providerType = providerType;
78 m_keyContainerName = (keyContainerName == null ? "*" : keyContainerName);
84 public string KeyStore {
89 // Unrestricted entries are invalid; they should not be allowed.
90 if (IsUnrestrictedEntry(value, this.ProviderName, this.ProviderType, this.KeyContainerName, this.KeySpec))
91 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
96 if (value != "User" && value != "Machine" && value != "*")
97 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKeyStore", value), "value");
103 public string ProviderName {
105 return m_providerName;
108 // Unrestricted entries are invalid; they should not be allowed.
109 if (IsUnrestrictedEntry(this.KeyStore, value, this.ProviderType, this.KeyContainerName, this.KeySpec))
110 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
113 m_providerName = "*";
115 m_providerName = value;
119 public int ProviderType {
121 return m_providerType;
124 // Unrestricted entries are invalid; they should not be allowed.
125 if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, value, this.KeyContainerName, this.KeySpec))
126 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
128 m_providerType = value;
132 public string KeyContainerName {
134 return m_keyContainerName;
137 // Unrestricted entries are invalid; they should not be allowed.
138 if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, value, this.KeySpec))
139 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
142 m_keyContainerName = "*";
144 m_keyContainerName = value;
153 // Unrestricted entries are invalid; they should not be allowed.
154 if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, this.KeyContainerName, value))
155 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
161 public KeyContainerPermissionFlags Flags {
166 KeyContainerPermission.VerifyFlags(value);
171 public override bool Equals (Object o) {
172 KeyContainerPermissionAccessEntry accessEntry = o as KeyContainerPermissionAccessEntry;
173 if (accessEntry == null)
176 if (accessEntry.m_keyStore != m_keyStore) return false;
177 if (accessEntry.m_providerName != m_providerName) return false;
178 if (accessEntry.m_providerType != m_providerType) return false;
179 if (accessEntry.m_keyContainerName != m_keyContainerName) return false;
180 if (accessEntry.m_keySpec != m_keySpec) return false;
185 public override int GetHashCode () {
188 hash |= (this.m_keyStore.GetHashCode() & 0x000000FF) << 24;
189 hash |= (this.m_providerName.GetHashCode() & 0x000000FF) << 16;
190 hash |= (this.m_providerType & 0x0000000F) << 12;
191 hash |= (this.m_keyContainerName.GetHashCode() & 0x000000FF) << 4;
192 hash |= (this.m_keySpec & 0x0000000F);
197 internal bool IsSubsetOf (KeyContainerPermissionAccessEntry target) {
198 if (target.m_keyStore != "*" && this.m_keyStore != target.m_keyStore)
200 if (target.m_providerName != "*" && this.m_providerName != target.m_providerName)
202 if (target.m_providerType != -1 && this.m_providerType != target.m_providerType)
204 if (target.m_keyContainerName != "*" && this.m_keyContainerName != target.m_keyContainerName)
206 if (target.m_keySpec != -1 && this.m_keySpec != target.m_keySpec)
212 internal static bool IsUnrestrictedEntry (string keyStore, string providerName, int providerType,
213 string keyContainerName, int keySpec) {
214 if (keyStore != "*" && keyStore != null) return false;
215 if (providerName != "*" && providerName != null) return false;
216 if (providerType != -1) return false;
217 if (keyContainerName != "*" && keyContainerName != null) return false;
218 if (keySpec != -1) return false;
225 [System.Runtime.InteropServices.ComVisible(true)]
226 public sealed class KeyContainerPermissionAccessEntryCollection : ICollection {
227 private ArrayList m_list;
228 private KeyContainerPermissionFlags m_globalFlags;
230 private KeyContainerPermissionAccessEntryCollection () {}
231 internal KeyContainerPermissionAccessEntryCollection (KeyContainerPermissionFlags globalFlags) {
232 m_list = new ArrayList();
233 m_globalFlags = globalFlags;
236 public KeyContainerPermissionAccessEntry this[int index] {
239 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
241 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
242 Contract.EndContractBlock();
244 return (KeyContainerPermissionAccessEntry)m_list[index];
254 public int Add (KeyContainerPermissionAccessEntry accessEntry) {
255 if (accessEntry == null)
256 throw new ArgumentNullException("accessEntry");
257 Contract.EndContractBlock();
259 int index = m_list.IndexOf(accessEntry);
261 if (accessEntry.Flags != m_globalFlags) {
262 return m_list.Add(accessEntry);
267 // We pick up the intersection of the 2 flags. This is the secure choice
268 // so we are opting for it.
269 ((KeyContainerPermissionAccessEntry)m_list[index]).Flags &= accessEntry.Flags;
274 public void Clear () {
278 public int IndexOf (KeyContainerPermissionAccessEntry accessEntry) {
279 return m_list.IndexOf(accessEntry);
282 public void Remove (KeyContainerPermissionAccessEntry accessEntry) {
283 if (accessEntry == null)
284 throw new ArgumentNullException("accessEntry");
285 Contract.EndContractBlock();
286 m_list.Remove(accessEntry);
289 public KeyContainerPermissionAccessEntryEnumerator GetEnumerator () {
290 return new KeyContainerPermissionAccessEntryEnumerator(this);
294 IEnumerator IEnumerable.GetEnumerator () {
295 return new KeyContainerPermissionAccessEntryEnumerator(this);
299 void ICollection.CopyTo (Array array, int index) {
301 throw new ArgumentNullException("array");
303 throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
304 if (index < 0 || index >= array.Length)
305 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
306 if (index + this.Count > array.Length)
307 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
308 Contract.EndContractBlock();
310 for (int i=0; i < this.Count; i++) {
311 array.SetValue(this[i], index);
316 public void CopyTo (KeyContainerPermissionAccessEntry[] array, int index) {
317 ((ICollection)this).CopyTo(array, index);
320 public bool IsSynchronized {
326 public Object SyncRoot {
334 [System.Runtime.InteropServices.ComVisible(true)]
335 public sealed class KeyContainerPermissionAccessEntryEnumerator : IEnumerator {
336 private KeyContainerPermissionAccessEntryCollection m_entries;
337 private int m_current;
339 private KeyContainerPermissionAccessEntryEnumerator () {}
340 internal KeyContainerPermissionAccessEntryEnumerator (KeyContainerPermissionAccessEntryCollection entries) {
345 public KeyContainerPermissionAccessEntry Current {
347 return m_entries[m_current];
352 Object IEnumerator.Current {
354 return (Object) m_entries[m_current];
358 public bool MoveNext() {
359 if (m_current == ((int) m_entries.Count - 1))
365 public void Reset() {
371 [System.Runtime.InteropServices.ComVisible(true)]
372 public sealed class KeyContainerPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
373 private KeyContainerPermissionFlags m_flags;
374 private KeyContainerPermissionAccessEntryCollection m_accessEntries;
376 public KeyContainerPermission (PermissionState state) {
377 if (state == PermissionState.Unrestricted)
378 m_flags = KeyContainerPermissionFlags.AllFlags;
379 else if (state == PermissionState.None)
380 m_flags = KeyContainerPermissionFlags.NoFlags;
382 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
383 m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
386 public KeyContainerPermission (KeyContainerPermissionFlags flags) {
389 m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
392 public KeyContainerPermission (KeyContainerPermissionFlags flags, KeyContainerPermissionAccessEntry[] accessList) {
393 if (accessList == null)
394 throw new ArgumentNullException("accessList");
395 Contract.EndContractBlock();
399 m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
400 for (int index = 0; index < accessList.Length; index++) {
401 m_accessEntries.Add(accessList[index]);
405 public KeyContainerPermissionFlags Flags {
411 public KeyContainerPermissionAccessEntryCollection AccessEntries {
413 return m_accessEntries;
417 public bool IsUnrestricted () {
418 if (m_flags != KeyContainerPermissionFlags.AllFlags)
421 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
422 if ((accessEntry.Flags & KeyContainerPermissionFlags.AllFlags) != KeyContainerPermissionFlags.AllFlags)
429 private bool IsEmpty () {
430 if (this.Flags == KeyContainerPermissionFlags.NoFlags) {
431 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
432 if (accessEntry.Flags != KeyContainerPermissionFlags.NoFlags)
441 // IPermission implementation
444 public override bool IsSubsetOf (IPermission target) {
448 if (!VerifyType(target))
449 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
451 KeyContainerPermission operand = (KeyContainerPermission) target;
453 // since there are containers that are neither in the access list of the source, nor in the
454 // access list of the target, the source flags must be a subset of the target flags.
455 if ((this.m_flags & operand.m_flags) != this.m_flags)
458 // Any entry in the source should have "applicable" flags in the destination that actually
459 // are less restrictive than the flags in the source.
461 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
462 KeyContainerPermissionFlags targetFlags = GetApplicableFlags(accessEntry, operand);
463 if ((accessEntry.Flags & targetFlags) != accessEntry.Flags)
467 // Any entry in the target should have "applicable" flags in the source that actually
468 // are more restrictive than the flags in the target.
470 foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
471 KeyContainerPermissionFlags sourceFlags = GetApplicableFlags(accessEntry, this);
472 if ((sourceFlags & accessEntry.Flags) != sourceFlags)
479 public override IPermission Intersect (IPermission target) {
483 if (!VerifyType(target))
484 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
486 KeyContainerPermission operand = (KeyContainerPermission) target;
487 if (this.IsEmpty() || operand.IsEmpty())
490 KeyContainerPermissionFlags flags_intersect = operand.m_flags & this.m_flags;
491 KeyContainerPermission cp = new KeyContainerPermission(flags_intersect);
492 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
493 cp.AddAccessEntryAndIntersect(accessEntry, operand);
495 foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
496 cp.AddAccessEntryAndIntersect(accessEntry, this);
498 return cp.IsEmpty() ? null : cp;
501 public override IPermission Union (IPermission target) {
505 if (!VerifyType(target))
506 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
508 KeyContainerPermission operand = (KeyContainerPermission) target;
509 if (this.IsUnrestricted() || operand.IsUnrestricted())
510 return new KeyContainerPermission(PermissionState.Unrestricted);
512 KeyContainerPermissionFlags flags_union = (KeyContainerPermissionFlags) (m_flags | operand.m_flags);
513 KeyContainerPermission cp = new KeyContainerPermission(flags_union);
514 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
515 cp.AddAccessEntryAndUnion(accessEntry, operand);
517 foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
518 cp.AddAccessEntryAndUnion(accessEntry, this);
520 return cp.IsEmpty() ? null : cp;
523 public override IPermission Copy () {
527 KeyContainerPermission cp = new KeyContainerPermission((KeyContainerPermissionFlags)m_flags);
528 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
529 cp.AccessEntries.Add(accessEntry);
534 #if FEATURE_CAS_POLICY
535 public override SecurityElement ToXml () {
536 SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.KeyContainerPermission");
537 if (!IsUnrestricted()) {
538 securityElement.AddAttribute("Flags", m_flags.ToString());
539 if (AccessEntries.Count > 0) {
540 SecurityElement al = new SecurityElement("AccessList");
541 foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
542 SecurityElement entryElem = new SecurityElement("AccessEntry");
543 entryElem.AddAttribute("KeyStore", accessEntry.KeyStore);
544 entryElem.AddAttribute("ProviderName", accessEntry.ProviderName);
545 entryElem.AddAttribute("ProviderType", accessEntry.ProviderType.ToString(null, null));
546 entryElem.AddAttribute("KeyContainerName", accessEntry.KeyContainerName);
547 entryElem.AddAttribute("KeySpec", accessEntry.KeySpec.ToString(null, null));
548 entryElem.AddAttribute("Flags", accessEntry.Flags.ToString());
549 al.AddChild(entryElem);
551 securityElement.AddChild(al);
554 securityElement.AddAttribute("Unrestricted", "true");
556 return securityElement;
559 public override void FromXml (SecurityElement securityElement) {
560 CodeAccessPermission.ValidateElement(securityElement, this);
561 if (XMLUtil.IsUnrestricted(securityElement)) {
562 m_flags = KeyContainerPermissionFlags.AllFlags;
563 m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
567 m_flags = KeyContainerPermissionFlags.NoFlags;
568 string strFlags = securityElement.Attribute("Flags");
569 if (strFlags != null) {
570 KeyContainerPermissionFlags flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strFlags);
574 m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
576 if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
577 IEnumerator enumerator = securityElement.Children.GetEnumerator();
578 while (enumerator.MoveNext()) {
579 SecurityElement current = (SecurityElement) enumerator.Current;
580 if (current != null) {
581 if (String.Equals(current.Tag, "AccessList"))
582 AddAccessEntries(current);
587 #endif // FEATURE_CAS_POLICY
590 int IBuiltInPermission.GetTokenIndex () {
591 return KeyContainerPermission.GetTokenIndex();
598 private void AddAccessEntries(SecurityElement securityElement) {
599 if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
600 IEnumerator elemEnumerator = securityElement.Children.GetEnumerator();
601 while (elemEnumerator.MoveNext()) {
602 SecurityElement current = (SecurityElement) elemEnumerator.Current;
603 if (current != null) {
604 if (String.Equals(current.Tag, "AccessEntry")) {
605 int iMax = current.m_lAttributes.Count;
606 Contract.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
607 string keyStore = null;
608 string providerName = null;
609 int providerType = -1;
610 string keyContainerName = null;
612 KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
613 for (int i = 0; i < iMax; i += 2) {
614 String strAttrName = (String) current.m_lAttributes[i];
615 String strAttrValue = (String) current.m_lAttributes[i+1];
616 if (String.Equals(strAttrName, "KeyStore"))
617 keyStore = strAttrValue;
618 if (String.Equals(strAttrName, "ProviderName"))
619 providerName = strAttrValue;
620 else if (String.Equals(strAttrName, "ProviderType"))
621 providerType = Convert.ToInt32(strAttrValue, null);
622 else if (String.Equals(strAttrName, "KeyContainerName"))
623 keyContainerName = strAttrValue;
624 else if (String.Equals(strAttrName, "KeySpec"))
625 keySpec = Convert.ToInt32(strAttrValue, null);
626 else if (String.Equals(strAttrName, "Flags")) {
627 flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strAttrValue);
630 KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(keyStore, providerName, providerType, keyContainerName, keySpec, flags);
631 AccessEntries.Add(accessEntry);
638 private void AddAccessEntryAndUnion (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
639 KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
640 newAccessEntry.Flags |= GetApplicableFlags(accessEntry, target);
641 AccessEntries.Add(newAccessEntry);
644 private void AddAccessEntryAndIntersect (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
645 KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
646 newAccessEntry.Flags &= GetApplicableFlags(accessEntry, target);
647 AccessEntries.Add(newAccessEntry);
651 // private/internal static methods.
654 internal static void VerifyFlags (KeyContainerPermissionFlags flags) {
655 if ((flags & ~KeyContainerPermissionFlags.AllFlags) != 0)
656 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flags));
657 Contract.EndContractBlock();
660 private static KeyContainerPermissionFlags GetApplicableFlags (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
661 KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
662 bool applyDefaultFlags = true;
664 // If the entry exists in the target, return the flag of the target entry.
665 int index = target.AccessEntries.IndexOf(accessEntry);
667 flags = ((KeyContainerPermissionAccessEntry)target.AccessEntries[index]).Flags;
671 // Intersect the flags in all the target entries that apply to the current access entry,
672 foreach (KeyContainerPermissionAccessEntry targetAccessEntry in target.AccessEntries) {
673 if (accessEntry.IsSubsetOf(targetAccessEntry)) {
674 if (applyDefaultFlags == false) {
675 flags &= targetAccessEntry.Flags;
677 flags = targetAccessEntry.Flags;
678 applyDefaultFlags = false;
683 // If no target entry applies to the current entry, the default global flag applies.
684 if (applyDefaultFlags)
685 flags = target.Flags;
690 private static int GetTokenIndex() {
691 return BuiltInPermissionIndex.KeyContainerPermissionIndex;
695 #endif // !FEATURE_PAL