a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
318 lines
9.2 KiB
C#
318 lines
9.2 KiB
C#
//
|
|
// System.Data.Common.DbDataPermission.cs
|
|
//
|
|
// Authors:
|
|
// Rodrigo Moya (rodrigo@ximian.com)
|
|
// Tim Coleman (tim@timcoleman.com)
|
|
// Sebastien Pouliot <sebastien@ximian.com>
|
|
//
|
|
// (C) Ximian, Inc
|
|
// Copyright (C) Tim Coleman, 2002-2003
|
|
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System.Collections;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
|
|
namespace System.Data.Common {
|
|
|
|
[Serializable]
|
|
public abstract class DBDataPermission : CodeAccessPermission, IUnrestrictedPermission {
|
|
|
|
#region Fields
|
|
|
|
private const int version = 1;
|
|
|
|
private bool allowBlankPassword;
|
|
private PermissionState state;
|
|
private Hashtable _connections;
|
|
|
|
#endregion // Fields
|
|
|
|
#region Constructors
|
|
|
|
#if NET_2_0
|
|
[Obsolete ("use DBDataPermission (PermissionState.None)", true)]
|
|
#endif
|
|
protected DBDataPermission ()
|
|
: this (PermissionState.None)
|
|
{
|
|
}
|
|
|
|
protected DBDataPermission (DBDataPermission permission)
|
|
{
|
|
if (permission == null)
|
|
throw new ArgumentNullException ("permission");
|
|
|
|
state = permission.state;
|
|
if (state != PermissionState.Unrestricted) {
|
|
allowBlankPassword = permission.allowBlankPassword;
|
|
_connections = (Hashtable) permission._connections.Clone ();
|
|
}
|
|
}
|
|
|
|
protected DBDataPermission (DBDataPermissionAttribute permissionAttribute)
|
|
{
|
|
if (permissionAttribute == null)
|
|
throw new ArgumentNullException ("permissionAttribute");
|
|
|
|
_connections = new Hashtable ();
|
|
if (permissionAttribute.Unrestricted) {
|
|
state = PermissionState.Unrestricted;
|
|
}
|
|
else {
|
|
state = PermissionState.None;
|
|
allowBlankPassword = permissionAttribute.AllowBlankPassword;
|
|
if (permissionAttribute.ConnectionString.Length > 0) {
|
|
Add (permissionAttribute.ConnectionString, permissionAttribute.KeyRestrictions,
|
|
permissionAttribute.KeyRestrictionBehavior);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected DBDataPermission (PermissionState state)
|
|
{
|
|
this.state = PermissionHelper.CheckPermissionState (state, true);
|
|
_connections = new Hashtable ();
|
|
}
|
|
|
|
#if NET_2_0
|
|
[Obsolete ("use DBDataPermission (PermissionState.None)", true)]
|
|
protected
|
|
#else
|
|
public
|
|
#endif
|
|
DBDataPermission (PermissionState state, bool allowBlankPassword)
|
|
: this (state)
|
|
{
|
|
this.allowBlankPassword = allowBlankPassword;
|
|
}
|
|
|
|
#endregion // Constructors
|
|
|
|
#region Properties
|
|
|
|
public bool AllowBlankPassword {
|
|
get { return allowBlankPassword; }
|
|
set { allowBlankPassword = value; }
|
|
}
|
|
|
|
#endregion // Properties
|
|
|
|
#region Methods
|
|
|
|
public virtual void Add (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
|
|
{
|
|
state = PermissionState.None;
|
|
_connections [connectionString] = new object [2] { restrictions, behavior };
|
|
}
|
|
|
|
protected void Clear ()
|
|
{
|
|
_connections.Clear ();
|
|
}
|
|
|
|
public override IPermission Copy ()
|
|
{
|
|
DBDataPermission dbdp = CreateInstance ();
|
|
dbdp.allowBlankPassword = this.allowBlankPassword;
|
|
dbdp._connections = (Hashtable) this._connections.Clone ();
|
|
return dbdp;
|
|
}
|
|
|
|
protected virtual DBDataPermission CreateInstance ()
|
|
{
|
|
return (DBDataPermission) Activator.CreateInstance (this.GetType (), new object [1] { PermissionState.None });
|
|
}
|
|
|
|
public override void FromXml (SecurityElement securityElement)
|
|
{
|
|
PermissionHelper.CheckSecurityElement (securityElement, "securityElement", version, version);
|
|
// Note: we do not (yet) care about the return value
|
|
// as we only accept version 1 (min/max values)
|
|
|
|
state = (PermissionHelper.IsUnrestricted (securityElement) ?
|
|
PermissionState.Unrestricted : PermissionState.None);
|
|
|
|
allowBlankPassword = false;
|
|
string blank = securityElement.Attribute ("AllowBlankPassword");
|
|
if (blank != null) {
|
|
#if NET_2_0
|
|
// avoid possible exceptions with Fx 2.0
|
|
if (!Boolean.TryParse (blank, out allowBlankPassword))
|
|
allowBlankPassword = false;
|
|
#else
|
|
try {
|
|
allowBlankPassword = Boolean.Parse (blank);
|
|
}
|
|
catch {
|
|
allowBlankPassword = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (securityElement.Children != null) {
|
|
foreach (SecurityElement child in securityElement.Children) {
|
|
string connect = child.Attribute ("ConnectionString");
|
|
string restricts = child.Attribute ("KeyRestrictions");
|
|
KeyRestrictionBehavior behavior = (KeyRestrictionBehavior) Enum.Parse (
|
|
typeof (KeyRestrictionBehavior), child.Attribute ("KeyRestrictionBehavior"));
|
|
|
|
if ((connect != null) && (connect.Length > 0))
|
|
Add (connect, restricts, behavior);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override IPermission Intersect (IPermission target)
|
|
{
|
|
// FIXME: restrictions not completely implemented - nor documented
|
|
DBDataPermission dbdp = Cast (target);
|
|
if (dbdp == null)
|
|
return null;
|
|
if (IsUnrestricted ()) {
|
|
if (dbdp.IsUnrestricted ()) {
|
|
DBDataPermission u = CreateInstance ();
|
|
u.state = PermissionState.Unrestricted;
|
|
return u;
|
|
}
|
|
return dbdp.Copy ();
|
|
}
|
|
if (dbdp.IsUnrestricted ())
|
|
return Copy ();
|
|
if (IsEmpty () || dbdp.IsEmpty ())
|
|
return null;
|
|
|
|
DBDataPermission p = CreateInstance ();
|
|
p.allowBlankPassword = (allowBlankPassword && dbdp.allowBlankPassword);
|
|
foreach (DictionaryEntry de in _connections) {
|
|
object o = dbdp._connections [de.Key];
|
|
if (o != null)
|
|
p._connections.Add (de.Key, de.Value);
|
|
}
|
|
return (p._connections.Count > 0) ? p : null;
|
|
}
|
|
|
|
public override bool IsSubsetOf (IPermission target)
|
|
{
|
|
// FIXME: restrictions not completely implemented - nor documented
|
|
DBDataPermission dbdp = Cast (target);
|
|
if (dbdp == null)
|
|
return IsEmpty ();
|
|
if (dbdp.IsUnrestricted ())
|
|
return true;
|
|
if (IsUnrestricted ())
|
|
return dbdp.IsUnrestricted ();
|
|
|
|
if (allowBlankPassword && !dbdp.allowBlankPassword)
|
|
return false;
|
|
if (_connections.Count > dbdp._connections.Count)
|
|
return false;
|
|
|
|
foreach (DictionaryEntry de in _connections) {
|
|
object o = dbdp._connections [de.Key];
|
|
if (o == null)
|
|
return false;
|
|
// FIXME: this is a subset of what is required
|
|
// it seems that we must process both the connect string
|
|
// and the restrictions - but this has other effects :-/
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool IsUnrestricted ()
|
|
{
|
|
return (state == PermissionState.Unrestricted);
|
|
}
|
|
|
|
public override SecurityElement ToXml ()
|
|
{
|
|
SecurityElement se = PermissionHelper.Element (this.GetType (), version);
|
|
if (IsUnrestricted ()) {
|
|
se.AddAttribute ("Unrestricted", "true");
|
|
}
|
|
else {
|
|
// attribute is present for both True and False
|
|
se.AddAttribute ("AllowBlankPassword", allowBlankPassword.ToString ());
|
|
foreach (DictionaryEntry de in _connections) {
|
|
SecurityElement child = new SecurityElement ("add");
|
|
child.AddAttribute ("ConnectionString", (string) de.Key);
|
|
object[] restrictionsInfo = (object[]) de.Value;
|
|
child.AddAttribute ("KeyRestrictions", (string) restrictionsInfo [0]);
|
|
KeyRestrictionBehavior krb = (KeyRestrictionBehavior) restrictionsInfo [1];
|
|
child.AddAttribute ("KeyRestrictionBehavior", krb.ToString ());
|
|
se.AddChild (child);
|
|
}
|
|
}
|
|
return se;
|
|
}
|
|
|
|
public override IPermission Union (IPermission target)
|
|
{
|
|
// FIXME: restrictions not completely implemented - nor documented
|
|
DBDataPermission dbdp = Cast (target);
|
|
if (dbdp == null)
|
|
return Copy ();
|
|
if (IsEmpty () && dbdp.IsEmpty ())
|
|
return Copy ();
|
|
|
|
DBDataPermission p = CreateInstance ();
|
|
if (IsUnrestricted () || dbdp.IsUnrestricted ()) {
|
|
p.state = PermissionState.Unrestricted;
|
|
}
|
|
else {
|
|
p.allowBlankPassword = (allowBlankPassword || dbdp.allowBlankPassword);
|
|
p._connections = new Hashtable (_connections.Count + dbdp._connections.Count);
|
|
foreach (DictionaryEntry de in _connections)
|
|
p._connections.Add (de.Key, de.Value);
|
|
// don't duplicate
|
|
foreach (DictionaryEntry de in dbdp._connections)
|
|
p._connections [de.Key] = de.Value;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
// helpers
|
|
|
|
private bool IsEmpty ()
|
|
{
|
|
return ((state != PermissionState.Unrestricted) && (_connections.Count == 0));
|
|
}
|
|
|
|
private DBDataPermission Cast (IPermission target)
|
|
{
|
|
if (target == null)
|
|
return null;
|
|
|
|
DBDataPermission dbdp = (target as DBDataPermission);
|
|
if (dbdp == null) {
|
|
PermissionHelper.ThrowInvalidPermission (target, this.GetType ());
|
|
}
|
|
|
|
return dbdp;
|
|
}
|
|
|
|
#endregion // Methods
|
|
}
|
|
}
|