1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 5 namespace System.IdentityModel.Policy 6 { 7 using System.Collections.Generic; 8 using System.Collections.ObjectModel; 9 using System.IdentityModel.Claims; 10 using System.Security.Principal; 11 12 interface IIdentityInfo 13 { 14 IIdentity Identity { get; } 15 } 16 17 class UnconditionalPolicy : IAuthorizationPolicy, IDisposable 18 { 19 SecurityUniqueId id; 20 ClaimSet issuer; 21 ClaimSet issuance; 22 ReadOnlyCollection<ClaimSet> issuances; 23 DateTime expirationTime; 24 IIdentity primaryIdentity; 25 bool disposable = false; 26 bool disposed = false; 27 UnconditionalPolicy(ClaimSet issuance)28 public UnconditionalPolicy(ClaimSet issuance) 29 : this(issuance, SecurityUtils.MaxUtcDateTime) 30 { 31 } 32 UnconditionalPolicy(ClaimSet issuance, DateTime expirationTime)33 public UnconditionalPolicy(ClaimSet issuance, DateTime expirationTime) 34 { 35 if (issuance == null) 36 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuance"); 37 38 Initialize(ClaimSet.System, issuance, null, expirationTime); 39 } 40 UnconditionalPolicy(ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime)41 public UnconditionalPolicy(ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime) 42 { 43 if (issuances == null) 44 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuances"); 45 46 Initialize(ClaimSet.System, null, issuances, expirationTime); 47 } 48 UnconditionalPolicy(IIdentity primaryIdentity, ClaimSet issuance)49 internal UnconditionalPolicy(IIdentity primaryIdentity, ClaimSet issuance) 50 : this(issuance) 51 { 52 this.primaryIdentity = primaryIdentity; 53 } 54 UnconditionalPolicy(IIdentity primaryIdentity, ClaimSet issuance, DateTime expirationTime)55 internal UnconditionalPolicy(IIdentity primaryIdentity, ClaimSet issuance, DateTime expirationTime) 56 : this(issuance, expirationTime) 57 { 58 this.primaryIdentity = primaryIdentity; 59 } 60 UnconditionalPolicy(IIdentity primaryIdentity, ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime)61 internal UnconditionalPolicy(IIdentity primaryIdentity, ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime) 62 : this(issuances, expirationTime) 63 { 64 this.primaryIdentity = primaryIdentity; 65 } 66 UnconditionalPolicy(UnconditionalPolicy from)67 UnconditionalPolicy(UnconditionalPolicy from) 68 { 69 this.disposable = from.disposable; 70 this.primaryIdentity = from.disposable ? SecurityUtils.CloneIdentityIfNecessary(from.primaryIdentity) : from.primaryIdentity; 71 if (from.issuance != null) 72 { 73 this.issuance = from.disposable ? SecurityUtils.CloneClaimSetIfNecessary(from.issuance) : from.issuance; 74 } 75 else 76 { 77 this.issuances = from.disposable ? SecurityUtils.CloneClaimSetsIfNecessary(from.issuances) : from.issuances; 78 } 79 this.issuer = from.issuer; 80 this.expirationTime = from.expirationTime; 81 } 82 Initialize(ClaimSet issuer, ClaimSet issuance, ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime)83 void Initialize(ClaimSet issuer, ClaimSet issuance, ReadOnlyCollection<ClaimSet> issuances, DateTime expirationTime) 84 { 85 this.issuer = issuer; 86 this.issuance = issuance; 87 this.issuances = issuances; 88 this.expirationTime = expirationTime; 89 if (issuance != null) 90 { 91 this.disposable = issuance is WindowsClaimSet; 92 } 93 else 94 { 95 for (int i = 0; i < issuances.Count; ++i) 96 { 97 if (issuances[i] is WindowsClaimSet) 98 { 99 this.disposable = true; 100 break; 101 } 102 } 103 } 104 } 105 106 public string Id 107 { 108 get 109 { 110 if (this.id == null) 111 this.id = SecurityUniqueId.Create(); 112 return this.id.Value; 113 } 114 } 115 116 public ClaimSet Issuer 117 { 118 get { return this.issuer; } 119 } 120 121 internal IIdentity PrimaryIdentity 122 { 123 get 124 { 125 ThrowIfDisposed(); 126 if (this.primaryIdentity == null) 127 { 128 IIdentity identity = null; 129 if (this.issuance != null) 130 { 131 if (this.issuance is IIdentityInfo) 132 { 133 identity = ((IIdentityInfo)this.issuance).Identity; 134 } 135 } 136 else 137 { 138 for (int i = 0; i < this.issuances.Count; ++i) 139 { 140 ClaimSet issuance = this.issuances[i]; 141 if (issuance is IIdentityInfo) 142 { 143 identity = ((IIdentityInfo)issuance).Identity; 144 // Preferably Non-Anonymous 145 if (identity != null && identity != SecurityUtils.AnonymousIdentity) 146 { 147 break; 148 } 149 } 150 } 151 } 152 this.primaryIdentity = identity ?? SecurityUtils.AnonymousIdentity; 153 } 154 return this.primaryIdentity; 155 } 156 } 157 158 internal ReadOnlyCollection<ClaimSet> Issuances 159 { 160 get 161 { 162 ThrowIfDisposed(); 163 if (this.issuances == null) 164 { 165 List<ClaimSet> issuances = new List<ClaimSet>(1); 166 issuances.Add(issuance); 167 this.issuances = issuances.AsReadOnly(); 168 } 169 return this.issuances; 170 } 171 } 172 173 public DateTime ExpirationTime 174 { 175 get { return this.expirationTime; } 176 } 177 178 internal bool IsDisposable 179 { 180 get { return this.disposable; } 181 } 182 Clone()183 internal UnconditionalPolicy Clone() 184 { 185 ThrowIfDisposed(); 186 return (this.disposable) ? new UnconditionalPolicy(this) : this; 187 } 188 Dispose()189 public virtual void Dispose() 190 { 191 if (this.disposable && !this.disposed) 192 { 193 this.disposed = true; 194 SecurityUtils.DisposeIfNecessary(this.primaryIdentity as WindowsIdentity); 195 SecurityUtils.DisposeClaimSetIfNecessary(this.issuance); 196 SecurityUtils.DisposeClaimSetsIfNecessary(this.issuances); 197 } 198 } 199 ThrowIfDisposed()200 void ThrowIfDisposed() 201 { 202 if (this.disposed) 203 { 204 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName)); 205 } 206 } 207 Evaluate(EvaluationContext evaluationContext, ref object state)208 public virtual bool Evaluate(EvaluationContext evaluationContext, ref object state) 209 { 210 ThrowIfDisposed(); 211 if (this.issuance != null) 212 { 213 evaluationContext.AddClaimSet(this, this.issuance); 214 } 215 else 216 { 217 for (int i = 0; i < this.issuances.Count; ++i) 218 { 219 if (this.issuances[i] != null) 220 { 221 evaluationContext.AddClaimSet(this, this.issuances[i]); 222 } 223 } 224 } 225 226 // Preferably Non-Anonymous 227 if (this.PrimaryIdentity != null && this.PrimaryIdentity != SecurityUtils.AnonymousIdentity) 228 { 229 IList<IIdentity> identities; 230 object obj; 231 if (!evaluationContext.Properties.TryGetValue(SecurityUtils.Identities, out obj)) 232 { 233 identities = new List<IIdentity>(1); 234 evaluationContext.Properties.Add(SecurityUtils.Identities, identities); 235 } 236 else 237 { 238 // null if other overrides the property with something else 239 identities = obj as IList<IIdentity>; 240 } 241 242 if (identities != null) 243 { 244 identities.Add(this.PrimaryIdentity); 245 } 246 } 247 248 evaluationContext.RecordExpirationTime(this.expirationTime); 249 return true; 250 } 251 } 252 } 253