// (c) 2006 Richard Grimes // www.grimes.demon.co.uk using System; using System.Security; using System.Reflection; using System.Security.Permissions; [assembly: AssemblyKeyFile("key.snk")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AllowPartiallyTrustedCallers] // This permission only gives access between defined times [Serializable] public sealed class ProtectedDataPermission : IPermission, IUnrestrictedPermission { int startTime; int endTime; bool unrestricted = false; public ProtectedDataPermission(PermissionState state) { if (state == PermissionState.Unrestricted) unrestricted = true; startTime = endTime = -1; // No times specified } public ProtectedDataPermission(int start, int end) { if (end < start) throw new ArgumentException("time period cannot cross midnight"); startTime = start; endTime = end; } public bool IsUnrestricted() { return unrestricted; } public IPermission Copy() { return new ProtectedDataPermission(startTime, endTime); } public IPermission Intersect(IPermission target) { if (target == null) return null; ProtectedDataPermission targetItem = target as ProtectedDataPermission; if (targetItem == null) throw new ArgumentException( "Argument must be of type ProtectedDataPermission."); // If one is unrestricted then the intersection is the other if (this.unrestricted) return targetItem.Copy(); if (targetItem.unrestricted) return this.Copy(); // Return an object which is the common time of the two int start, end; if (this.startTime > targetItem.startTime) start = this.startTime; else start = targetItem.startTime; if (this.endTime < targetItem.endTime) end = this.endTime; else end = targetItem.endTime; if (start < end) // The two periods do not overlap return new ProtectedDataPermission(start, end); return new ProtectedDataPermission(PermissionState.None); } public IPermission Union(IPermission other) { if (other == null) return this.Copy(); ProtectedDataPermission targetItem = other as ProtectedDataPermission; if (targetItem == null) throw new ArgumentException( "Argument must be of type ProtectedDataPermission."); // If either unrestricted then return unrestricted if (this.unrestricted || targetItem.unrestricted) { return new ProtectedDataPermission(PermissionState.Unrestricted); } // Return the time covered by both int start, end; if (this.startTime < targetItem.startTime) start = this.startTime; else start = targetItem.startTime; if (this.endTime > targetItem.endTime) end = this.endTime; else end = targetItem.endTime; // Make sure they intersect, the combined lengths of this and target must // be less than or equal to the range calculated if ((end - start) > ((this.endTime - this.startTime) + (targetItem.endTime - targetItem.startTime))) return new ProtectedDataPermission(PermissionState.None); return new ProtectedDataPermission(start, end); } public bool IsSubsetOf(IPermission target) { if (target == null) { return false; } ProtectedDataPermission targetItem = target as ProtectedDataPermission; if (targetItem == null) throw new ArgumentException( "Argument must be of type ProtectedDataPermission."); // If both are unrestricted, then they are a subset of each other if (this.unrestricted && targetItem.unrestricted) return true; // Test to see if they overlap if (this.endTime < targetItem.startTime) return false; // Now see if our times are within the times of the target return (this.startTime >= targetItem.startTime && this.endTime <= targetItem.endTime); } public void FromXml(SecurityElement elem) { string unrestricted = elem.Attribute("Unrestricted"); if (unrestricted != null) { this.unrestricted = (unrestricted == "true"); } string strStart = elem.Attribute("Start"); if (strStart != null) { startTime = Int32.Parse(strStart); } string strEnd = elem.Attribute("End"); if (strEnd != null) { endTime = Int32.Parse(strEnd); } } public SecurityElement ToXml() { SecurityElement e = new SecurityElement("IPermission"); e.AddAttribute("class", this.GetType().AssemblyQualifiedName); e.AddAttribute("version", "1"); if (this.unrestricted) { e.AddAttribute("Unrestricted", "true"); } else { e.AddAttribute("Start", startTime.ToString()); e.AddAttribute("End", endTime.ToString()); } return e; } public void Demand() { if (this.unrestricted) return; if (startTime == -1 && endTime == -1) throw new SecurityException("No access is allowed at any time"); int hours = DateTime.Now.Hour; if (hours < startTime || hours >= endTime) throw new SecurityException("Access not allowed at this time"); // Otherwise allow access } } [Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true, Inherited = false)] public sealed class ProtectedDataPermissionAttribute : CodeAccessSecurityAttribute { int startTime; int endTime; bool unrestricted = false; public ProtectedDataPermissionAttribute(SecurityAction action) : base(action) { startTime = -1; endTime = -1; } public new bool Unrestricted { get { return unrestricted; } set { unrestricted = value; } } public int StartTime { get { return startTime; } set { startTime = value; } } public int EndTime { get { return endTime; } set { endTime = value; } } public override IPermission CreatePermission() { if (Unrestricted) { return new ProtectedDataPermission(PermissionState.Unrestricted); } else { if (endTime < startTime || endTime == -1 || startTime == -1) return new ProtectedDataPermission(PermissionState.None); return new ProtectedDataPermission(startTime, endTime); } } }