Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / DBDataPermission.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DBDataPermission.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
8
9 namespace System.Data.Common {
10
11     using System.Collections;
12     using System.Data.Common;
13     using System.Diagnostics;
14     using System.Globalization;
15     using System.Runtime.Serialization;
16     using System.Security;
17     using System.Security.Permissions;
18     using System.Text;
19
20     [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, ControlEvidence=true, ControlPolicy=true)]
21     [Serializable]
22     public abstract class DBDataPermission :  CodeAccessPermission, IUnrestrictedPermission {
23
24         private bool _isUnrestricted;// = false;
25         private bool _allowBlankPassword;// = false;
26         private NameValuePermission _keyvaluetree = NameValuePermission.Default;
27         private /*DBConnectionString[]*/ArrayList _keyvalues; // = null;
28
29         [ Obsolete("DBDataPermission() has been deprecated.  Use the DBDataPermission(PermissionState.None) constructor.  http://go.microsoft.com/fwlink/?linkid=14202", true) ] // V1.2.3300, MDAC 86034
30         protected DBDataPermission() : this(PermissionState.None) { // V1.0.3300
31         }
32
33         protected DBDataPermission(PermissionState state) { // V1.0.3300
34             if (state == PermissionState.Unrestricted) {
35                 _isUnrestricted = true;
36             }
37             else if (state == PermissionState.None) {
38                 _isUnrestricted = false;
39             }
40             else {
41                 throw ADP.InvalidPermissionState(state);
42             }
43         }
44
45         [ Obsolete("DBDataPermission(PermissionState state,Boolean allowBlankPassword) has been deprecated.  Use the DBDataPermission(PermissionState.None) constructor.  http://go.microsoft.com/fwlink/?linkid=14202", true) ] // V1.2.3300, MDAC 86034
46         protected DBDataPermission(PermissionState state, bool allowBlankPassword) : this(state) { // V1.0.3300,  MDAC 84281
47             AllowBlankPassword = allowBlankPassword;
48         }
49
50         protected DBDataPermission(DBDataPermission permission) { // V1.0.5000,  for Copy
51             if (null == permission) {
52                 throw ADP.ArgumentNull("permissionAttribute");
53             }
54             CopyFrom(permission);
55         }
56
57         protected DBDataPermission(DBDataPermissionAttribute permissionAttribute) { // V1.0.5000, for CreatePermission
58             if (null == permissionAttribute) {
59                 throw ADP.ArgumentNull("permissionAttribute");
60             }
61             _isUnrestricted = permissionAttribute.Unrestricted;
62             if (!_isUnrestricted) {
63                 _allowBlankPassword = permissionAttribute.AllowBlankPassword;
64                 if (permissionAttribute.ShouldSerializeConnectionString() || permissionAttribute.ShouldSerializeKeyRestrictions()) { // MDAC 86773
65                     Add(permissionAttribute.ConnectionString, permissionAttribute.KeyRestrictions, permissionAttribute.KeyRestrictionBehavior);
66                 }
67             }
68         }
69
70         // how connectionString security is used
71         // parsetable (all string) is shared with connection
72         internal DBDataPermission(DbConnectionOptions connectionOptions) { // v2.0
73             if (null != connectionOptions) {
74                 _allowBlankPassword = connectionOptions.HasBlankPassword; // MDAC 84563
75                 AddPermissionEntry(new DBConnectionString(connectionOptions));
76             }
77         }
78
79         public bool AllowBlankPassword { // V1.0.3300
80             get {
81                 return _allowBlankPassword;
82             }
83             set { // MDAC 61263
84                 // for behavioral backward compatability with V1.1
85                 // set_AllowBlankPassword does not _isUnrestricted=false
86                 _allowBlankPassword = value;
87             }
88         }
89
90         public virtual void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior) { // V1.0.5000
91             DBConnectionString constr = new DBConnectionString(connectionString, restrictions, behavior, null, false);
92             AddPermissionEntry(constr);
93         }
94
95         internal void AddPermissionEntry(DBConnectionString entry) {
96             if (null == _keyvaluetree) {
97                 _keyvaluetree = new NameValuePermission();
98             }
99             if (null == _keyvalues) {
100                 _keyvalues = new ArrayList();
101             }
102             NameValuePermission.AddEntry(_keyvaluetree, _keyvalues, entry);
103             _isUnrestricted = false; // MDAC 84639
104         }
105
106         protected void Clear() { // V1.2.3300, MDAC 83105
107             _keyvaluetree = null;
108             _keyvalues = null;
109         }
110
111         // IPermission interface methods
112         // [ObsoleteAttribute("override Copy instead of using default implementation")] // not inherited
113         override public IPermission Copy() {
114             DBDataPermission copy = CreateInstance();
115             copy.CopyFrom(this);
116             return copy;
117         }
118
119         private void CopyFrom(DBDataPermission permission) {
120             _isUnrestricted = permission.IsUnrestricted();
121             if (!_isUnrestricted) {
122                 _allowBlankPassword = permission.AllowBlankPassword;
123
124                 if (null != permission._keyvalues) {
125                     _keyvalues = (ArrayList) permission._keyvalues.Clone();
126
127                     if (null != permission._keyvaluetree) {
128                         _keyvaluetree = permission._keyvaluetree.CopyNameValue();
129                     }
130                 }
131             }
132         }
133
134         // [ Obsolete("use DBDataPermission(DBDataPermission) ctor") ]
135         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] // V1.0.5000, MDAC 82936
136         virtual protected DBDataPermission CreateInstance() {
137             // derived class should override with a different implementation avoiding reflection to allow semi-trusted scenarios
138             return (Activator.CreateInstance(GetType(), System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Instance, null, null, CultureInfo.InvariantCulture, null) as DBDataPermission);
139         }
140
141         override public IPermission Intersect(IPermission target) { // used during Deny actions
142             if (null == target) {
143                 return null;
144             }
145             if (target.GetType() != this.GetType()) {
146                 throw ADP.PermissionTypeMismatch();
147             }
148             if (this.IsUnrestricted()) { // MDAC 84803, NDPWhidbey 29121
149                 return target.Copy();
150             }
151
152             DBDataPermission operand = (DBDataPermission) target;
153             if (operand.IsUnrestricted()) { // NDPWhidbey 29121
154                 return this.Copy();
155             }
156
157             DBDataPermission newPermission = (DBDataPermission) operand.Copy();
158             newPermission._allowBlankPassword &= AllowBlankPassword;
159
160             if ((null != _keyvalues) && (null != newPermission._keyvalues)) {
161                 newPermission._keyvalues.Clear();
162
163                 newPermission._keyvaluetree.Intersect(newPermission._keyvalues, _keyvaluetree);
164             }
165             else {
166                 // either target.Add or this.Add have not been called
167                 // return a non-null object so IsSubset calls will fail
168                 newPermission._keyvalues = null;
169                 newPermission._keyvaluetree = null;
170             }
171
172             if (newPermission.IsEmpty()) { // no intersection, MDAC 86773
173                 newPermission = null;
174             }
175             return newPermission;
176         }
177
178         private bool IsEmpty() { // MDAC 84804
179             ArrayList keyvalues = _keyvalues;
180             bool flag = (!IsUnrestricted() && !AllowBlankPassword && ((null == keyvalues) || (0 == keyvalues.Count)));
181             return flag;
182         }
183
184         override public bool IsSubsetOf(IPermission target) {
185             if (null == target) {
186                 return IsEmpty();
187             }
188             if (target.GetType() != this.GetType()) {
189                 throw ADP.PermissionTypeMismatch();
190             }
191
192             DBDataPermission superset = (target as DBDataPermission);
193
194             bool subset = superset.IsUnrestricted();
195             if (!subset) {
196                 if (!IsUnrestricted() &&
197                     (!AllowBlankPassword || superset.AllowBlankPassword) &&
198                     ((null == _keyvalues) || (null != superset._keyvaluetree))) {
199
200                     subset = true;
201                     if (null != _keyvalues) {
202                         foreach(DBConnectionString kventry in _keyvalues) {
203                             if(!superset._keyvaluetree.CheckValueForKeyPermit(kventry)) {
204                                 subset = false;
205                                 break;
206                             }
207                         }
208                     }
209                 }
210             }
211             return subset;
212         }
213
214         // IUnrestrictedPermission interface methods
215         public bool IsUnrestricted() {
216             return _isUnrestricted;
217         }
218
219         override public IPermission Union(IPermission target) {
220             if (null == target) {
221                 return this.Copy();
222             }
223             if (target.GetType() != this.GetType()) {
224                 throw ADP.PermissionTypeMismatch();
225             }
226             if (IsUnrestricted()) { // MDAC 84803
227                 return this.Copy();
228             }
229
230             DBDataPermission newPermission = (DBDataPermission) target.Copy();
231             if (!newPermission.IsUnrestricted()) {
232                 newPermission._allowBlankPassword |= AllowBlankPassword;
233
234                 if (null != _keyvalues) {
235                     foreach(DBConnectionString entry in _keyvalues) {
236                         newPermission.AddPermissionEntry(entry);
237                     }
238                 }
239             }
240             return (newPermission.IsEmpty() ? null : newPermission);
241         }
242
243         private string DecodeXmlValue(string value) {
244             if ((null != value) && (0 < value.Length)) {
245                 value = value.Replace("&quot;", "\"");
246                 value = value.Replace("&apos;", "\'");
247                 value = value.Replace("&lt;",   "<");
248                 value = value.Replace("&gt;",   ">");
249                 value = value.Replace("&amp;",  "&");
250             }
251             return value;
252         }
253
254         private string EncodeXmlValue(string value) {
255             if ((null != value) && (0 < value.Length)) {
256                 value = value.Replace('\0', ' '); // assumption that '\0' will only be at end of string
257                 value = value.Trim();
258                 value = value.Replace("&",  "&amp;");
259                 value = value.Replace(">",  "&gt;");
260                 value = value.Replace("<",  "&lt;");
261                 value = value.Replace("\'", "&apos;");
262                 value = value.Replace("\"", "&quot;");
263             }
264             return value;
265         }
266
267         // <IPermission class="...Permission" version="1" AllowBlankPassword=false>
268         //     <add ConnectionString="provider=x;data source=y;" KeyRestrictions="address=;server=" KeyRestrictionBehavior=PreventUsage/>
269         // </IPermission>
270         override public void FromXml(SecurityElement securityElement) {
271             // code derived from CodeAccessPermission.ValidateElement
272             if (null == securityElement) {
273                 throw ADP.ArgumentNull("securityElement");
274             }
275             string tag = securityElement.Tag;
276             if (!tag.Equals(XmlStr._Permission) && !tag.Equals(XmlStr._IPermission)) {
277                 throw ADP.NotAPermissionElement();
278             }
279             String version = securityElement.Attribute(XmlStr._Version);
280             if ((null != version) && !version.Equals(XmlStr._VersionNumber)) {
281                 throw ADP.InvalidXMLBadVersion();
282             }
283
284             string unrestrictedValue = securityElement.Attribute(XmlStr._Unrestricted);
285             _isUnrestricted = (null != unrestrictedValue) && Boolean.Parse(unrestrictedValue);
286
287             Clear(); // MDAC 83105
288             if (!_isUnrestricted) {
289                 string allowNull = securityElement.Attribute(XmlStr._AllowBlankPassword);
290                 _allowBlankPassword = (null != allowNull) && Boolean.Parse(allowNull);
291
292                 ArrayList children = securityElement.Children;
293                 if (null != children) {
294                     foreach(SecurityElement keyElement in children) {
295                         tag = keyElement.Tag;
296                         if ((XmlStr._add == tag) || ((null != tag) && (XmlStr._add == tag.ToLower(CultureInfo.InvariantCulture)))) {
297                             string constr = keyElement.Attribute(XmlStr._ConnectionString);
298                             string restrt = keyElement.Attribute(XmlStr._KeyRestrictions);
299                             string behavr = keyElement.Attribute(XmlStr._KeyRestrictionBehavior);
300
301                             KeyRestrictionBehavior behavior = KeyRestrictionBehavior.AllowOnly;
302                             if (null != behavr) {
303                                 behavior = (KeyRestrictionBehavior) Enum.Parse(typeof(KeyRestrictionBehavior), behavr, true);
304                             }
305                             constr = DecodeXmlValue(constr);
306                             restrt = DecodeXmlValue(restrt);
307                             Add(constr, restrt, behavior);
308                         }
309                     }
310                 }
311             }
312             else {
313                 _allowBlankPassword = false;
314             }
315         }
316
317         // <IPermission class="...Permission" version="1" AllowBlankPassword=false>
318         //     <add ConnectionString="provider=x;data source=y;"/>
319         //     <add ConnectionString="provider=x;data source=y;" KeyRestrictions="user id=;password=;" KeyRestrictionBehavior=AllowOnly/>
320         //     <add ConnectionString="provider=x;data source=y;" KeyRestrictions="address=;server=" KeyRestrictionBehavior=PreventUsage/>
321         // </IPermission>
322         override public SecurityElement ToXml() {
323             Type type = this.GetType();
324             SecurityElement root = new SecurityElement(XmlStr._IPermission);
325             root.AddAttribute(XmlStr._class, type.AssemblyQualifiedName.Replace('\"', '\''));
326             root.AddAttribute(XmlStr._Version, XmlStr._VersionNumber);
327
328             if (IsUnrestricted()) {
329                 root.AddAttribute(XmlStr._Unrestricted, XmlStr._true);
330             }
331             else {
332                 root.AddAttribute(XmlStr._AllowBlankPassword, _allowBlankPassword.ToString(CultureInfo.InvariantCulture));
333
334                 if (null != _keyvalues) {
335                     foreach(DBConnectionString value in _keyvalues) {
336                         SecurityElement valueElement = new SecurityElement(XmlStr._add);
337                         string tmp;
338
339                         tmp = value.ConnectionString; // WebData 97375
340                         tmp = EncodeXmlValue(tmp);
341                         if (!ADP.IsEmpty(tmp)) {
342                             valueElement.AddAttribute(XmlStr._ConnectionString, tmp);
343                         }
344                         tmp = value.Restrictions;
345                         tmp = EncodeXmlValue(tmp);
346                         if (null == tmp) { tmp = ADP.StrEmpty; }
347                         valueElement.AddAttribute(XmlStr._KeyRestrictions, tmp);
348
349                         tmp = value.Behavior.ToString();
350                         valueElement.AddAttribute(XmlStr._KeyRestrictionBehavior, tmp);
351
352                         root.AddChild(valueElement);
353                     }
354                 }
355             }
356             return root;
357         }
358
359         private static class XmlStr {
360             internal const string _class = "class";
361             internal const string _IPermission = "IPermission";
362             internal const string _Permission = "Permission";
363             internal const string _Unrestricted = "Unrestricted";
364             internal const string _AllowBlankPassword = "AllowBlankPassword";
365             internal const string _true = "true";
366             internal const string _Version = "version";
367             internal const string _VersionNumber = "1";
368
369             internal const string _add = "add";
370
371             internal const string _ConnectionString = "ConnectionString";
372             internal const string _KeyRestrictions = "KeyRestrictions";
373             internal const string _KeyRestrictionBehavior = "KeyRestrictionBehavior";
374         }
375     }
376 }