diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Common/Microsoft/Data/Common/NameValuePermission.cs b/src/Microsoft.Data.SqlClient/netfx/src/Common/Microsoft/Data/Common/NameValuePermission.cs
deleted file mode 100644
index a7ad9be288..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Common/Microsoft/Data/Common/NameValuePermission.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Data.Common
-{
-
- using System;
- using System.Collections;
- using System.Diagnostics;
-
- [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 (_restrictions != null) 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 (_tree != null)
- {
- NameValuePermission[] tree = (_tree.Clone() as NameValuePermission[]);
- for (int i = 0; i < tree.Length; ++i)
- {
- if (tree[i] != null)
- { // 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(entry != null, "null DBConnectionString");
-
- if (entry.KeyChain != null)
- {
- for (NameValuePair keychain = entry.KeyChain; keychain != null; keychain = keychain.Next)
- {
- NameValuePermission kv;
-
- kv = kvtree.CheckKeyForValue(keychain.Name);
- if (kv == null)
- {
- kv = new NameValuePermission(keychain.Name);
- kvtree.Add(kv); // add directly into live tree
- }
- kvtree = kv;
-
- kv = kvtree.CheckKeyForValue(keychain.Value);
- if (kv == null)
- {
- DBConnectionString insertValue = keychain.Next != null ? null : entry;
- kv = new NameValuePermission(keychain.Value, insertValue);
- kvtree.Add(kv); // add directly into live tree
- if (insertValue != null)
- {
- entries.Add(insertValue);
- }
- }
- else if (keychain.Next == null)
- { // shorter chain potential
- if (kv._entry != null)
- {
- 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 (kentry != null)
- {
- 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 (target == null)
- {
- _tree = null;
- _entry = null;
- }
- else
- {
- if (_entry != null)
- {
- entries.Remove(_entry);
- _entry = _entry.Intersect(target._entry);
- entries.Add(_entry);
- }
- else if (target._entry != null)
- {
- _entry = target._entry.Intersect(null);
- entries.Add(_entry);
- }
-
- if (_tree != null)
- {
- int count = _tree.Length;
- for (int i = 0; i < _tree.Length; ++i)
- {
- NameValuePermission kvtree = target.CheckKeyForValue(_tree[i]._value);
- if (kvtree != null)
- { // 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 (_tree[i] != null)
- {
- kvtree[j++] = _tree[i];
- }
- }
- _tree = kvtree;
- }
- }
- }
- }
-
- private void Add(NameValuePermission permit)
- {
- NameValuePermission[] tree = _tree;
- int length = tree != null ? 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 (parsetable == null)
- {
- return false;
- }
- bool hasMatch = false;
- NameValuePermission[] keytree = _tree; // _tree won't mutate but Add will replace it
- if (keytree != null)
- {
- 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 (permitKey != null)
- {
- string keyword = permitKey._value;
-#if DEBUG
- Debug.Assert(permitKey._entry == null, "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 (permitValue != null)
- {
- //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 safely 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 ( _restrictions == null)
- }
-
- DBConnectionString entry = _entry;
- if (entry != null)
- {
- // also checking !hasMatch is tempting, but wrong
- // user can safely 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 (valuetree != null)
- {
- 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);
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 7408ce42ac..01d96660b7 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -651,6 +651,12 @@
Microsoft\Data\SqlClient\SqlClientMetaDataCollectionNames.cs
+
+ Microsoft\Data\SqlClient\SqlClientPermission.netfx.cs
+
+
+ Microsoft\Data\SqlClient\SqlClientPermissionAttribute.netfx.cs
+
Microsoft\Data\SqlClient\SqlClientSymmetricKey.cs
@@ -890,7 +896,6 @@
-
@@ -905,7 +910,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlClientPermission.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlClientPermission.cs
deleted file mode 100644
index 69cc432e3e..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlClientPermission.cs
+++ /dev/null
@@ -1,432 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections;
-using System.Data;
-using System.Data.Common;
-using System.Globalization;
-using System.Reflection;
-using System.Security;
-using System.Security.Permissions;
-using Microsoft.Data.Common;
-using DBDataPermission = System.Data.Common.DBDataPermission;
-
-namespace Microsoft.Data.SqlClient
-{
- ///
- [Serializable]
- public sealed class SqlClientPermission : System.Data.Common.DBDataPermission
- {
-
- ///
- [Obsolete("SqlClientPermission() has been deprecated. Use the SqlClientPermission(PermissionState.None) constructor. http://go.microsoft.com/fwlink/?linkid=14202", true)] // MDAC 86034
- public SqlClientPermission() : this(PermissionState.None)
- {
- }
-
- ///
- public SqlClientPermission(PermissionState state) : base(state)
- {
- }
-
- ///
- [Obsolete("SqlClientPermission(PermissionState state, Boolean allowBlankPassword) has been deprecated. Use the SqlClientPermission(PermissionState.None) constructor. http://go.microsoft.com/fwlink/?linkid=14202", true)] // MDAC 86034
- public SqlClientPermission(PermissionState state, bool allowBlankPassword) : this(state)
- {
- AllowBlankPassword = allowBlankPassword;
- }
-
- private SqlClientPermission(SqlClientPermission permission) : base(permission)
- { // for Copy
- // Explicitly copyFrom to clone the key value pairs
- CopyFrom(permission);
- }
-
- internal SqlClientPermission(SqlClientPermissionAttribute permissionAttribute) : base(permissionAttribute)
- { // for CreatePermission
- }
-
- internal SqlClientPermission(SqlConnectionString constr) : base(PermissionState.None)
- { // for Open
- if (constr != null)
- {
- AllowBlankPassword = constr.HasBlankPassword; // MDAC 84563
- AddPermissionEntry(new DBConnectionString(constr));
- }
- if (constr == null || constr.IsEmpty)
- {
- base.Add("", "", KeyRestrictionBehavior.AllowOnly);
- }
- }
-
- ///
- public override void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior)
- {
- DBConnectionString constr = new DBConnectionString(connectionString, restrictions, behavior, SqlConnectionString.GetParseSynonyms(), false);
- AddPermissionEntry(constr);
- }
-
- ///
- override public IPermission Copy()
- {
- return new SqlClientPermission(this);
- }
-
- // Modifications
-
- private NameValuePermission _keyvaluetree = NameValuePermission.Default;
- private /*DBConnectionString[]*/ArrayList _keyvalues; // = null;
-
- internal void AddPermissionEntry(DBConnectionString entry)
- {
- if (_keyvaluetree == null)
- {
- _keyvaluetree = new NameValuePermission();
- }
- if (_keyvalues == null)
- {
- _keyvalues = new ArrayList();
- }
- NameValuePermission.AddEntry(_keyvaluetree, _keyvalues, entry);
- _IsUnrestricted = false; // MDAC 84639
- }
-
- private bool _IsUnrestricted
- {
- set
- {
- // Use Reflection to access the base class _isUnrestricted. There is no other way to alter this externally.
- FieldInfo fieldInfo = GetType().BaseType.GetField("_isUnrestricted", BindingFlags.Instance
- | BindingFlags.NonPublic);
- fieldInfo.SetValue(this, value);
- }
-
- get
- {
- return base.IsUnrestricted();
- }
- }
-
- // Modified CopyFrom to make sure that we copy the Name Value Pair
- private void CopyFrom(SqlClientPermission permission)
- {
- if (!_IsUnrestricted)
- {
- if (permission._keyvalues != null)
- {
- _keyvalues = (ArrayList)permission._keyvalues.Clone();
-
- if (permission._keyvaluetree != null)
- {
- _keyvaluetree = permission._keyvaluetree.CopyNameValue();
- }
- }
- }
- }
-
- ///
- override public IPermission Intersect(IPermission target)
- { // used during Deny actions
- if (target == null)
- {
- return null;
- }
- if (target.GetType() != this.GetType())
- {
- throw ADP.PermissionTypeMismatch();
- }
- if (this.IsUnrestricted())
- { // MDAC 84803, NDPWhidbey 29121
- return target.Copy();
- }
-
- DBDataPermission operand = (DBDataPermission)target;
- if (operand.IsUnrestricted())
- { // NDPWhidbey 29121
- return this.Copy();
- }
-
- SqlClientPermission newPermission = (SqlClientPermission)operand.Copy();
- newPermission.AllowBlankPassword &= AllowBlankPassword;
-
- if (_keyvalues != null && newPermission._keyvalues != null)
- {
- newPermission._keyvalues.Clear();
-
- newPermission._keyvaluetree.Intersect(newPermission._keyvalues, _keyvaluetree);
- }
- else
- {
- // either target.Add or this.Add have not been called
- // return a non-null object so IsSubset calls will fail
- newPermission._keyvalues = null;
- newPermission._keyvaluetree = null;
- }
-
- if (newPermission.IsEmpty())
- { // no intersection, MDAC 86773
- newPermission = null;
- }
- return newPermission;
- }
-
- private bool IsEmpty()
- { // MDAC 84804
- ArrayList keyvalues = _keyvalues;
- bool flag = !IsUnrestricted() && !AllowBlankPassword && (keyvalues == null || (0 == keyvalues.Count));
- return flag;
- }
-
- ///
- override public bool IsSubsetOf(IPermission target)
- {
- if (null == target)
- {
- return IsEmpty();
- }
- if (target.GetType() != this.GetType())
- {
- throw ADP.PermissionTypeMismatch();
- }
-
- SqlClientPermission superset = (target as SqlClientPermission);
-
- bool subset = superset.IsUnrestricted();
- if (!subset)
- {
- if (!IsUnrestricted() &&
- (!AllowBlankPassword || superset.AllowBlankPassword) &&
- (_keyvalues == null || superset._keyvaluetree != null))
- {
-
- subset = true;
- if (_keyvalues != null)
- {
- foreach (DBConnectionString kventry in _keyvalues)
- {
- if (!superset._keyvaluetree.CheckValueForKeyPermit(kventry))
- {
- subset = false;
- break;
- }
- }
- }
- }
- }
- return subset;
- }
-
- ///
- override public IPermission Union(IPermission target)
- {
- if (target == null)
- {
- return this.Copy();
- }
- if (target.GetType() != this.GetType())
- {
- throw ADP.PermissionTypeMismatch();
- }
- if (IsUnrestricted())
- { // MDAC 84803
- return this.Copy();
- }
-
- SqlClientPermission newPermission = (SqlClientPermission)target.Copy();
- if (!newPermission.IsUnrestricted())
- {
- newPermission.AllowBlankPassword |= AllowBlankPassword;
-
- if (_keyvalues != null)
- {
- foreach (DBConnectionString entry in _keyvalues)
- {
- newPermission.AddPermissionEntry(entry);
- }
- }
- }
- return (newPermission.IsEmpty() ? null : newPermission);
- }
-
- private string DecodeXmlValue(string value)
- {
- if (value != null && (0 < value.Length))
- {
- value = value.Replace(""", "\"");
- value = value.Replace("'", "\'");
- value = value.Replace("<", "<");
- value = value.Replace(">", ">");
- value = value.Replace("&", "&");
- }
- return value;
- }
-
- private string EncodeXmlValue(string value)
- {
- if (value != null && (0 < value.Length))
- {
- value = value.Replace('\0', ' '); // assumption that '\0' will only be at end of string
- value = value.Trim();
- value = value.Replace("&", "&");
- value = value.Replace(">", ">");
- value = value.Replace("<", "<");
- value = value.Replace("\'", "'");
- value = value.Replace("\"", """);
- }
- return value;
- }
-
- //
- //
- //
- ///
- override public void FromXml(SecurityElement securityElement)
- {
- // code derived from CodeAccessPermission.ValidateElement
- if (securityElement == null)
- {
- throw ADP.ArgumentNull("securityElement");
- }
- string tag = securityElement.Tag;
- if (!tag.Equals(XmlStr._Permission) && !tag.Equals(XmlStr._IPermission))
- {
- throw ADP.NotAPermissionElement();
- }
- String version = securityElement.Attribute(XmlStr._Version);
- if (version != null && !version.Equals(XmlStr._VersionNumber))
- {
- throw ADP.InvalidXMLBadVersion();
- }
-
- string unrestrictedValue = securityElement.Attribute(XmlStr._Unrestricted);
- _IsUnrestricted = unrestrictedValue != null && Boolean.Parse(unrestrictedValue);
-
- Clear(); // MDAC 83105
- if (!_IsUnrestricted)
- {
- string allowNull = securityElement.Attribute(XmlStr._AllowBlankPassword);
- AllowBlankPassword = allowNull != null && Boolean.Parse(allowNull);
-
- ArrayList children = securityElement.Children;
- if (children != null)
- {
- foreach (SecurityElement keyElement in children)
- {
- tag = keyElement.Tag;
- if (XmlStr._add == tag || (tag != null && XmlStr._add == tag.ToLower(CultureInfo.InvariantCulture)))
- {
- string constr = keyElement.Attribute(XmlStr._ConnectionString);
- string restrt = keyElement.Attribute(XmlStr._KeyRestrictions);
- string behavr = keyElement.Attribute(XmlStr._KeyRestrictionBehavior);
-
- KeyRestrictionBehavior behavior = KeyRestrictionBehavior.AllowOnly;
- if (behavr != null)
- {
- behavior = (KeyRestrictionBehavior)Enum.Parse(typeof(KeyRestrictionBehavior), behavr, true);
- }
- constr = DecodeXmlValue(constr);
- restrt = DecodeXmlValue(restrt);
- Add(constr, restrt, behavior);
- }
- }
- }
- }
- else
- {
- AllowBlankPassword = false;
- }
- }
-
- //
- //
- //
- //
- //
- ///
- override public SecurityElement ToXml()
- {
- Type type = this.GetType();
- SecurityElement root = new SecurityElement(XmlStr._IPermission);
- root.AddAttribute(XmlStr._class, type.AssemblyQualifiedName.Replace('\"', '\''));
- root.AddAttribute(XmlStr._Version, XmlStr._VersionNumber);
-
- if (IsUnrestricted())
- {
- root.AddAttribute(XmlStr._Unrestricted, XmlStr._true);
- }
- else
- {
- root.AddAttribute(XmlStr._AllowBlankPassword, AllowBlankPassword.ToString(CultureInfo.InvariantCulture));
-
- if (_keyvalues != null)
- {
- foreach (DBConnectionString value in _keyvalues)
- {
- SecurityElement valueElement = new SecurityElement(XmlStr._add);
- string tmp;
-
- tmp = value.ConnectionString; // WebData 97375
- tmp = EncodeXmlValue(tmp);
- if (!string.IsNullOrEmpty(tmp))
- {
- valueElement.AddAttribute(XmlStr._ConnectionString, tmp);
- }
- tmp = value.Restrictions;
- tmp = EncodeXmlValue(tmp);
- if (tmp == null)
- {
- tmp = "";
- }
- valueElement.AddAttribute(XmlStr._KeyRestrictions, tmp);
-
- tmp = value.Behavior.ToString();
- valueElement.AddAttribute(XmlStr._KeyRestrictionBehavior, tmp);
-
- root.AddChild(valueElement);
- }
- }
- }
- return root;
- }
-
- private static class XmlStr
- {
- internal const string _class = "class";
- internal const string _IPermission = "IPermission";
- internal const string _Permission = "Permission";
- internal const string _Unrestricted = "Unrestricted";
- internal const string _AllowBlankPassword = "AllowBlankPassword";
- internal const string _true = "true";
- internal const string _Version = "version";
- internal const string _VersionNumber = "1";
-
- internal const string _add = "add";
-
- internal const string _ConnectionString = "ConnectionString";
- internal const string _KeyRestrictions = "KeyRestrictions";
- internal const string _KeyRestrictionBehavior = "KeyRestrictionBehavior";
- }
-
-
- }
-
- ///
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
- [Serializable]
- public sealed class SqlClientPermissionAttribute : DBDataPermissionAttribute
- {
-
- ///
- public SqlClientPermissionAttribute(SecurityAction action) : base(action)
- {
- }
-
- ///
- override public IPermission CreatePermission()
- {
- return new SqlClientPermission(this);
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermission.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermission.netfx.cs
new file mode 100644
index 0000000000..2b0d7ef50e
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermission.netfx.cs
@@ -0,0 +1,701 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if NETFRAMEWORK
+
+using System;
+using System.Collections;
+using System.Data;
+using System.Diagnostics;
+using System.Globalization;
+using System.Net;
+using System.Reflection;
+using System.Security;
+using System.Security.Permissions;
+using Microsoft.Data.Common;
+using DBDataPermission = System.Data.Common.DBDataPermission;
+
+namespace Microsoft.Data.SqlClient
+{
+ ///
+ [Serializable]
+ public sealed class SqlClientPermission : DBDataPermission
+ {
+ #region Member Variables
+
+ // @TODO: Replace ArrayList with a typed list.
+ private NameValuePermission _keyvaluetree = NameValuePermission.Default;
+ private ArrayList _keyvalues;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ [Obsolete("SqlClientPermission() has been deprecated. Use the SqlClientPermission(PermissionState.None) constructor. http://go.microsoft.com/fwlink/?linkid=14202", true)] // MDAC 86034
+ public SqlClientPermission() : this(PermissionState.None)
+ {
+ }
+
+ ///
+ public SqlClientPermission(PermissionState state) : base(state)
+ {
+ }
+
+ ///
+ [Obsolete("SqlClientPermission(PermissionState state, Boolean allowBlankPassword) has been deprecated. Use the SqlClientPermission(PermissionState.None) constructor. http://go.microsoft.com/fwlink/?linkid=14202", true)] // MDAC 86034
+ public SqlClientPermission(PermissionState state, bool allowBlankPassword) : this(state)
+ {
+ AllowBlankPassword = allowBlankPassword;
+ }
+
+ internal SqlClientPermission(SqlClientPermissionAttribute permissionAttribute) : base(permissionAttribute)
+ {
+ // Used by SqlClientPermissionAttribute.CreatePermission
+ }
+
+ internal SqlClientPermission(SqlConnectionString constr) : base(PermissionState.None)
+ {
+ // Used by SqlConnectionString.CreatePermissionSet
+
+ if (constr != null)
+ {
+ AllowBlankPassword = constr.HasBlankPassword; // MDAC 84563
+ AddPermissionEntry(new DBConnectionString(constr));
+ }
+
+ if (constr == null || constr.IsEmpty)
+ {
+ base.Add("", "", KeyRestrictionBehavior.AllowOnly);
+ }
+ }
+
+ private SqlClientPermission(SqlClientPermission permission) : base(permission)
+ {
+ // for Copy
+ // Explicitly copyFrom to clone the key value pairs
+ CopyFrom(permission);
+ }
+
+ #endregion
+
+ #region Properties
+
+ private bool _IsUnrestricted
+ {
+ get
+ {
+ return base.IsUnrestricted();
+ }
+
+ set
+ {
+ // Use Reflection to access the base class _isUnrestricted. There is no other way to alter this externally.
+ FieldInfo fieldInfo = GetType().BaseType.GetField(
+ "_isUnrestricted",
+ BindingFlags.Instance | BindingFlags.NonPublic);
+ fieldInfo.SetValue(this, value);
+ }
+ }
+
+ #endregion
+
+ #region Public/Internal Methods
+
+ ///
+ public override void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior)
+ {
+ DBConnectionString constr = new DBConnectionString(connectionString, restrictions, behavior, SqlConnectionString.GetParseSynonyms(), false);
+ AddPermissionEntry(constr);
+ }
+
+ ///
+ public override IPermission Copy()
+ {
+ return new SqlClientPermission(this);
+ }
+
+ ///
+ public override void FromXml(SecurityElement securityElement)
+ {
+ // Reads an XML tree like:
+ //
+ //
+ //
+
+ // code derived from CodeAccessPermission.ValidateElement
+ if (securityElement == null)
+ {
+ throw ADP.ArgumentNull("securityElement");
+ }
+
+ string tag = securityElement.Tag;
+ if (!tag.Equals(XmlStr._Permission) && !tag.Equals(XmlStr._IPermission))
+ {
+ throw ADP.NotAPermissionElement();
+ }
+
+ string version = securityElement.Attribute(XmlStr._Version);
+ if (version != null && !version.Equals(XmlStr._VersionNumber))
+ {
+ throw ADP.InvalidXMLBadVersion();
+ }
+
+ string unrestrictedValue = securityElement.Attribute(XmlStr._Unrestricted);
+ _IsUnrestricted = unrestrictedValue != null && bool.Parse(unrestrictedValue);
+
+ Clear(); // MDAC 83105
+ if (!_IsUnrestricted)
+ {
+ string allowNull = securityElement.Attribute(XmlStr._AllowBlankPassword);
+ AllowBlankPassword = allowNull != null && bool.Parse(allowNull);
+
+ ArrayList children = securityElement.Children;
+ if (children != null)
+ {
+ foreach (SecurityElement keyElement in children)
+ {
+ tag = keyElement.Tag;
+ if (XmlStr._add == tag || (tag != null && XmlStr._add == tag.ToLower(CultureInfo.InvariantCulture)))
+ {
+ string constr = keyElement.Attribute(XmlStr._ConnectionString);
+ string restrt = keyElement.Attribute(XmlStr._KeyRestrictions);
+ string behavr = keyElement.Attribute(XmlStr._KeyRestrictionBehavior);
+
+ KeyRestrictionBehavior behavior = KeyRestrictionBehavior.AllowOnly;
+ if (behavr != null)
+ {
+ behavior = (KeyRestrictionBehavior)Enum.Parse(typeof(KeyRestrictionBehavior), behavr, true);
+ }
+
+ constr = WebUtility.HtmlDecode(constr);
+ restrt = WebUtility.HtmlDecode(restrt);
+ Add(constr, restrt, behavior);
+ }
+ }
+ }
+ }
+ else
+ {
+ AllowBlankPassword = false;
+ }
+ }
+
+ ///
+ public override IPermission Intersect(IPermission target)
+ {
+ // used during Deny actions
+ if (target == null)
+ {
+ return null;
+ }
+ if (target.GetType() != this.GetType())
+ {
+ throw ADP.PermissionTypeMismatch();
+ }
+ if (this.IsUnrestricted())
+ { // MDAC 84803, NDPWhidbey 29121
+ return target.Copy();
+ }
+
+ DBDataPermission operand = (DBDataPermission)target;
+ if (operand.IsUnrestricted())
+ { // NDPWhidbey 29121
+ return this.Copy();
+ }
+
+ SqlClientPermission newPermission = (SqlClientPermission)operand.Copy();
+ newPermission.AllowBlankPassword &= AllowBlankPassword;
+
+ if (_keyvalues != null && newPermission._keyvalues != null)
+ {
+ newPermission._keyvalues.Clear();
+
+ newPermission._keyvaluetree.Intersect(newPermission._keyvalues, _keyvaluetree);
+ }
+ else
+ {
+ // either target.Add or this.Add have not been called
+ // return a non-null object so IsSubset calls will fail
+ newPermission._keyvalues = null;
+ newPermission._keyvaluetree = null;
+ }
+
+ if (newPermission.IsEmpty())
+ { // no intersection, MDAC 86773
+ newPermission = null;
+ }
+ return newPermission;
+ }
+
+ ///
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (null == target)
+ {
+ return IsEmpty();
+ }
+ if (target.GetType() != this.GetType())
+ {
+ throw ADP.PermissionTypeMismatch();
+ }
+
+ SqlClientPermission superset = (target as SqlClientPermission);
+
+ bool subset = superset.IsUnrestricted();
+ if (!subset)
+ {
+ if (!IsUnrestricted() &&
+ (!AllowBlankPassword || superset.AllowBlankPassword) &&
+ (_keyvalues == null || superset._keyvaluetree != null))
+ {
+
+ subset = true;
+ if (_keyvalues != null)
+ {
+ foreach (DBConnectionString kventry in _keyvalues)
+ {
+ if (!superset._keyvaluetree.CheckValueForKeyPermit(kventry))
+ {
+ subset = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return subset;
+ }
+
+ ///
+ public override SecurityElement ToXml()
+ {
+ // Generates an XML tree like:
+ //
+ //
+ //
+ //
+ //
+
+ Type type = GetType();
+ SecurityElement root = new SecurityElement(XmlStr._IPermission);
+ root.AddAttribute(XmlStr._class, type.AssemblyQualifiedName.Replace('\"', '\''));
+ root.AddAttribute(XmlStr._Version, XmlStr._VersionNumber);
+
+ if (IsUnrestricted())
+ {
+ root.AddAttribute(XmlStr._Unrestricted, XmlStr._true);
+ }
+ else
+ {
+ root.AddAttribute(XmlStr._AllowBlankPassword, AllowBlankPassword.ToString(CultureInfo.InvariantCulture));
+
+ if (_keyvalues != null)
+ {
+ foreach (DBConnectionString value in _keyvalues)
+ {
+ SecurityElement valueElement = new SecurityElement(XmlStr._add);
+ string tmp;
+
+ tmp = SecurityElement.Escape(value.ConnectionString);
+ if (!string.IsNullOrEmpty(tmp))
+ {
+ valueElement.AddAttribute(XmlStr._ConnectionString, tmp);
+ }
+
+ tmp = SecurityElement.Escape(value.Restrictions) ?? "";
+ valueElement.AddAttribute(XmlStr._KeyRestrictions, tmp);
+
+ tmp = value.Behavior.ToString();
+ valueElement.AddAttribute(XmlStr._KeyRestrictionBehavior, tmp);
+
+ root.AddChild(valueElement);
+ }
+ }
+ }
+ return root;
+ }
+
+ ///
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ return Copy();
+ }
+
+ if (target.GetType() != GetType())
+ {
+ throw ADP.PermissionTypeMismatch();
+ }
+
+ if (IsUnrestricted())
+ {
+ return Copy();
+ }
+
+ SqlClientPermission newPermission = (SqlClientPermission)target.Copy();
+ if (!newPermission.IsUnrestricted())
+ {
+ newPermission.AllowBlankPassword |= AllowBlankPassword;
+
+ if (_keyvalues != null)
+ {
+ foreach (DBConnectionString entry in _keyvalues)
+ {
+ newPermission.AddPermissionEntry(entry);
+ }
+ }
+ }
+
+ return newPermission.IsEmpty() ? null : newPermission;
+ }
+
+ internal void AddPermissionEntry(DBConnectionString entry)
+ {
+ if (_keyvaluetree == null)
+ {
+ _keyvaluetree = new NameValuePermission();
+ }
+
+ if (_keyvalues == null)
+ {
+ _keyvalues = new ArrayList();
+ }
+
+ NameValuePermission.AddEntry(_keyvaluetree, _keyvalues, entry);
+ _IsUnrestricted = false;
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ // Modified CopyFrom to make sure that we copy the Name Value Pair
+ private void CopyFrom(SqlClientPermission permission)
+ {
+ if (!_IsUnrestricted)
+ {
+ if (permission._keyvalues != null)
+ {
+ _keyvalues = (ArrayList)permission._keyvalues.Clone();
+
+ if (permission._keyvaluetree != null)
+ {
+ _keyvaluetree = permission._keyvaluetree.CopyNameValue();
+ }
+ }
+ }
+ }
+
+ private bool IsEmpty()
+ {
+ ArrayList keyvalues = _keyvalues;
+ bool flag = !IsUnrestricted() && !AllowBlankPassword && (keyvalues == null || (0 == keyvalues.Count));
+ return flag;
+ }
+
+ #endregion
+
+ [Serializable]
+ private sealed class NameValuePermission : IComparable
+ {
+ // Reused as both key and value nodes:
+ // Key nodes link to value nodes.
+ // Value nodes link to key nodes.
+ private readonly string _value;
+
+ // value node with (_restrictions != null) are allowed to match connection strings
+ private DBConnectionString _entry;
+
+ private NameValuePermission[] _tree; // with branches
+
+ internal static readonly NameValuePermission Default = null;
+
+ internal NameValuePermission()
+ { // root node
+ }
+
+ private NameValuePermission(NameValuePermission permit)
+ {
+ // deep-copy
+ _value = permit._value;
+ _entry = permit._entry;
+ _tree = permit._tree;
+ if (_tree != null)
+ {
+ NameValuePermission[] tree = _tree.Clone() as NameValuePermission[];
+ for (int i = 0; i < tree.Length; ++i)
+ {
+ if (tree[i] != null)
+ { // WebData 98488
+ tree[i] = tree[i].CopyNameValue(); // deep copy
+ }
+ }
+ _tree = tree;
+ }
+ }
+
+ private NameValuePermission(string keyword)
+ {
+ _value = keyword;
+ }
+
+ private NameValuePermission(string value, DBConnectionString entry)
+ {
+ _value = value;
+ _entry = entry;
+ }
+
+ int IComparable.CompareTo(object other) =>
+ string.CompareOrdinal(_value, ((NameValuePermission)other)._value);
+
+ internal static void AddEntry(NameValuePermission kvtree, ArrayList entries, DBConnectionString entry)
+ {
+ Debug.Assert(entry != null, "null DBConnectionString");
+
+ if (entry.KeyChain != null)
+ {
+ for (NameValuePair keychain = entry.KeyChain; keychain != null; keychain = keychain.Next)
+ {
+ NameValuePermission kv = kvtree.CheckKeyForValue(keychain.Name);
+ if (kv == null)
+ {
+ kv = new NameValuePermission(keychain.Name);
+ kvtree.Add(kv); // add directly into live tree
+ }
+
+ kvtree = kv;
+
+ kv = kvtree.CheckKeyForValue(keychain.Value);
+ if (kv == null)
+ {
+ DBConnectionString insertValue = keychain.Next != null ? null : entry;
+ kv = new NameValuePermission(keychain.Value, insertValue);
+ kvtree.Add(kv); // add directly into live tree
+ if (insertValue != null)
+ {
+ entries.Add(insertValue);
+ }
+ }
+ else if (keychain.Next == null)
+ {
+ // shorter chain potential
+ if (kv._entry != null)
+ {
+ 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
+ DBConnectionString kentry = kvtree._entry;
+ if (kentry != null)
+ {
+ 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 bool CheckValueForKeyPermit(DBConnectionString parsetable)
+ {
+ if (parsetable == null)
+ {
+ return false;
+ }
+
+ bool hasMatch = false;
+ NameValuePermission[] keytree = _tree; // _tree won't mutate but Add will replace it
+ if (keytree != null)
+ {
+ hasMatch = parsetable.IsEmpty; // MDAC 86773
+ if (!hasMatch)
+ {
+ // which key do we follow the key-value chain on
+ foreach (var permitKey in keytree)
+ {
+ if (permitKey != null)
+ {
+ string keyword = permitKey._value;
+
+ Debug.Assert(permitKey._entry == null, "key member has no restrictions");
+ if (parsetable.ContainsKey(keyword))
+ {
+ string valueInQuestion = (string)parsetable[keyword];
+
+ // keyword is restricted to certain values
+ NameValuePermission permitValue = permitKey.CheckKeyForValue(valueInQuestion);
+ if (permitValue != null)
+ {
+ //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 safely 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;
+ }
+ }
+ }
+ }
+ }
+ // partial chain match, either leaf-node by shorter chain or fail mid-chain if ( _restrictions == null)
+ }
+
+ DBConnectionString entry = _entry;
+ if (entry != null)
+ {
+ // also checking !hasMatch is tempting, but wrong
+ // user can safely 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);
+ }
+
+ // mid-chain failure
+ return hasMatch;
+ }
+
+ internal NameValuePermission CopyNameValue()
+ {
+ return new NameValuePermission(this);
+ }
+
+ internal void Intersect(ArrayList entries, NameValuePermission target)
+ {
+ if (target == null)
+ {
+ _tree = null;
+ _entry = null;
+ }
+ else
+ {
+ if (_entry != null)
+ {
+ entries.Remove(_entry);
+ _entry = _entry.Intersect(target._entry);
+ entries.Add(_entry);
+ }
+ else if (target._entry != null)
+ {
+ _entry = target._entry.Intersect(null);
+ entries.Add(_entry);
+ }
+
+ if (_tree != null)
+ {
+ int count = _tree.Length;
+ for (int i = 0; i < _tree.Length; ++i)
+ {
+ NameValuePermission kvtree = target.CheckKeyForValue(_tree[i]._value);
+ if (kvtree != null)
+ { // 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 (_tree[i] != null)
+ {
+ kvtree[j++] = _tree[i];
+ }
+ }
+ _tree = kvtree;
+ }
+ }
+ }
+ }
+
+ private void Add(NameValuePermission permit)
+ {
+ NameValuePermission[] tree = _tree;
+ int length = tree != null ? 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;
+ }
+
+ private NameValuePermission CheckKeyForValue(string keyInQuestion)
+ {
+ NameValuePermission[] valuetree = _tree; // _tree won't mutate but Add will replace it
+ if (valuetree != null)
+ {
+ foreach (var permitValue in valuetree)
+ {
+ if (string.Equals(keyInQuestion, permitValue._value, StringComparison.OrdinalIgnoreCase))
+ {
+ return permitValue;
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ private static class XmlStr
+ {
+ internal const string _class = "class";
+ internal const string _IPermission = "IPermission";
+ internal const string _Permission = "Permission";
+ internal const string _Unrestricted = "Unrestricted";
+ internal const string _AllowBlankPassword = "AllowBlankPassword";
+ internal const string _true = "true";
+ internal const string _Version = "version";
+ internal const string _VersionNumber = "1";
+
+ internal const string _add = "add";
+
+ internal const string _ConnectionString = "ConnectionString";
+ internal const string _KeyRestrictions = "KeyRestrictions";
+ internal const string _KeyRestrictionBehavior = "KeyRestrictionBehavior";
+ }
+ }
+}
+
+#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermissionAttribute.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermissionAttribute.netfx.cs
new file mode 100644
index 0000000000..d26def255e
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientPermissionAttribute.netfx.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if NETFRAMEWORK
+
+using System;
+using System.Data.Common;
+using System.Security;
+using System.Security.Permissions;
+
+namespace Microsoft.Data.SqlClient
+{
+ ///
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
+ [Serializable]
+ public sealed class SqlClientPermissionAttribute : DBDataPermissionAttribute
+ {
+ ///
+ public SqlClientPermissionAttribute(SecurityAction action) : base(action)
+ {
+ }
+
+ ///
+ public override IPermission CreatePermission()
+ {
+ return new SqlClientPermission(this);
+ }
+ }
+}
+
+#endif