| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //------------------------------------------------------------------------------
- // <copyright file="NameValuePermission.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">Microsoft</owner>
- // <owner current="true" primary="false">Microsoft</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.Common {
- using System.Collections;
- using System.Data.Common;
- using System.Diagnostics;
- using System.Globalization;
- using System.Security;
- using System.Security.Permissions;
- using System.Text;
- [Serializable] // MDAC 83147
- sealed internal class NameValuePermission : IComparable {
- // reused as both key and value nodes
- // key nodes link to value nodes
- // value nodes link to key nodes
- private string _value;
- // value node with (null != _restrictions) are allowed to match connection strings
- private DBConnectionString _entry;
- private NameValuePermission[] _tree; // with branches
- static internal readonly NameValuePermission Default = null;// = new NameValuePermission(String.Empty, new string[] { "File Name" }, KeyRestrictionBehavior.AllowOnly);
- internal NameValuePermission() { // root node
- }
- private NameValuePermission(string keyword) {
- _value = keyword;
- }
- private NameValuePermission(string value, DBConnectionString entry) {
- _value = value;
- _entry = entry;
- }
- private NameValuePermission(NameValuePermission permit) { // deep-copy
- _value = permit._value;
- _entry = permit._entry;
- _tree = permit._tree;
- if (null != _tree) {
- NameValuePermission[] tree = (_tree.Clone() as NameValuePermission[]);
- for(int i = 0; i < tree.Length; ++i) {
- if (null != tree[i]) { // WebData 98488
- tree[i] = tree[i].CopyNameValue(); // deep copy
- }
- }
- _tree = tree;
- }
- }
- int IComparable.CompareTo(object a) {
- return StringComparer.Ordinal.Compare(_value, ((NameValuePermission)a)._value);
- }
- static internal void AddEntry(NameValuePermission kvtree, ArrayList entries, DBConnectionString entry) {
- Debug.Assert(null != entry, "null DBConnectionString");
- if (null != entry.KeyChain) {
- for(NameValuePair keychain = entry.KeyChain; null != keychain; keychain = keychain.Next) {
- NameValuePermission kv;
- kv = kvtree.CheckKeyForValue(keychain.Name);
- if (null == kv) {
- kv = new NameValuePermission(keychain.Name);
- kvtree.Add(kv); // add directly into live tree
- }
- kvtree = kv;
- kv = kvtree.CheckKeyForValue(keychain.Value);
- if (null == kv) {
- DBConnectionString insertValue = ((null != keychain.Next) ? null : entry);
- kv = new NameValuePermission(keychain.Value, insertValue);
- kvtree.Add(kv); // add directly into live tree
- if (null != insertValue) {
- entries.Add(insertValue);
- }
- }
- else if (null == keychain.Next) { // shorter chain potential
- if (null != kv._entry) {
- Debug.Assert(entries.Contains(kv._entry), "entries doesn't contain entry");
- entries.Remove(kv._entry);
- kv._entry = kv._entry.Intersect(entry); // union new restrictions into existing tree
- }
- else {
- kv._entry = entry;
- }
- entries.Add(kv._entry);
- }
- kvtree = kv;
- }
- }
- else { // global restrictions, MDAC 84443
- DBConnectionString kentry = kvtree._entry;
- if (null != kentry) {
- Debug.Assert(entries.Contains(kentry), "entries doesn't contain entry");
- entries.Remove(kentry);
- kvtree._entry = kentry.Intersect(entry);
- }
- else {
- kvtree._entry = entry;
- }
- entries.Add(kvtree._entry);
- }
- }
- internal void Intersect(ArrayList entries, NameValuePermission target) {
- if (null == target) {
- _tree = null;
- _entry = null;
- }
- else {
- if (null != _entry) {
- entries.Remove(_entry);
- _entry = _entry.Intersect(target._entry);
- entries.Add(_entry);
- }
- else if (null != target._entry) {
- _entry = target._entry.Intersect(null);
- entries.Add(_entry);
- }
- if (null != _tree) {
- int count = _tree.Length;
- for(int i = 0; i < _tree.Length; ++i) {
- NameValuePermission kvtree = target.CheckKeyForValue(_tree[i]._value);
- if (null != kvtree) { // does target tree contain our value
- _tree[i].Intersect(entries, kvtree);
- }
- else {
- _tree[i] = null;
- --count;
- }
- }
- if (0 == count) {
- _tree = null;
- }
- else if (count < _tree.Length) {
- NameValuePermission[] kvtree = new NameValuePermission[count];
- for (int i = 0, j = 0; i < _tree.Length; ++i) {
- if(null != _tree[i]) {
- kvtree[j++] = _tree[i];
- }
- }
- _tree = kvtree;
- }
- }
- }
- }
- private void Add(NameValuePermission permit) {
- NameValuePermission[] tree = _tree;
- int length = ((null != tree) ? tree.Length : 0);
- NameValuePermission[] newtree = new NameValuePermission[1+length];
- for(int i = 0; i < newtree.Length-1; ++i) {
- newtree[i] = tree[i];
- }
- newtree[length] = permit;
- Array.Sort(newtree);
- _tree = newtree;
- }
- internal bool CheckValueForKeyPermit(DBConnectionString parsetable) {
- if (null == parsetable) {
- return false;
- }
- bool hasMatch = false;
- NameValuePermission[] keytree = _tree; // _tree won't mutate but Add will replace it
- if (null != keytree) {
- hasMatch = parsetable.IsEmpty; // MDAC 86773
- if (!hasMatch) {
- // which key do we follow the key-value chain on
- for (int i = 0; i < keytree.Length; ++i) {
- NameValuePermission permitKey = keytree[i];
- if (null != permitKey) {
- string keyword = permitKey._value;
- #if DEBUG
- Debug.Assert(null == permitKey._entry, "key member has no restrictions");
- #endif
- if (parsetable.ContainsKey(keyword)) {
- string valueInQuestion = (string)parsetable[keyword];
- // keyword is restricted to certain values
- NameValuePermission permitValue = permitKey.CheckKeyForValue(valueInQuestion);
- if (null != permitValue) {
- //value does match - continue the chain down that branch
- if (permitValue.CheckValueForKeyPermit(parsetable)) {
- hasMatch = true;
- // adding a break statement is tempting, but wrong
- // user can safetly extend their restrictions for current rule to include missing keyword
- // i.e. Add("provider=sqloledb;integrated security=sspi", "data provider=", KeyRestrictionBehavior.AllowOnly);
- // i.e. Add("data provider=msdatashape;provider=sqloledb;integrated security=sspi", "", KeyRestrictionBehavior.AllowOnly);
- }
- else { // failed branch checking
- return false;
- }
- }
- else { // value doesn't match to expected values - fail here
- return false;
- }
- }
- }
- // else try next keyword
- }
- }
- // partial chain match, either leaf-node by shorter chain or fail mid-chain if (null == _restrictions)
- }
- DBConnectionString entry = _entry;
- if (null != entry) {
- // also checking !hasMatch is tempting, but wrong
- // user can safetly extend their restrictions for current rule to include missing keyword
- // i.e. Add("provider=sqloledb;integrated security=sspi", "data provider=", KeyRestrictionBehavior.AllowOnly);
- // i.e. Add("provider=sqloledb;", "integrated security=;", KeyRestrictionBehavior.AllowOnly);
- hasMatch = entry.IsSupersetOf(parsetable);
- }
- return hasMatch; // mid-chain failure
- }
- private NameValuePermission CheckKeyForValue(string keyInQuestion) {
- NameValuePermission[] valuetree = _tree; // _tree won't mutate but Add will replace it
- if (null != valuetree) {
- for (int i = 0; i < valuetree.Length; ++i) {
- NameValuePermission permitValue = valuetree[i];
- if (String.Equals(keyInQuestion, permitValue._value, StringComparison.OrdinalIgnoreCase)) {
- return permitValue;
- }
- }
- }
- return null;
- }
- internal NameValuePermission CopyNameValue() {
- return new NameValuePermission(this);
- }
- }
- }
|