| File: FrameworkFork\System.ServiceModel\System\IdentityModel\SecurityUtils.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// 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.Collections.Generic; using System.Collections.ObjectModel; using System.IdentityModel.Claims; using System.IdentityModel.Policy; using System.IdentityModel.Tokens; using System.Runtime; using System.Security; using System.Security.Cryptography.X509Certificates; using System.Security.Principal; using System.ServiceModel; using System.ServiceModel.Diagnostics; using System.Text; using Microsoft.Win32.SafeHandles; namespace System.IdentityModel { internal static class SecurityUtils { public const string Identities = "Identities"; private static IIdentity s_anonymousIdentity; // these should be kept in sync with IIS70 public const string AuthTypeNTLM = "NTLM"; public const string AuthTypeNegotiate = "Negotiate"; public const string AuthTypeKerberos = "Kerberos"; public const string AuthTypeAnonymous = ""; public const string AuthTypeCertMap = "SSL/PCT"; // mapped from a cert public const string AuthTypeBasic = "Basic"; //LogonUser internal static IIdentity AnonymousIdentity { get { if (s_anonymousIdentity == null) { s_anonymousIdentity = SecurityUtils.CreateIdentity(string.Empty); } return s_anonymousIdentity; } } public static DateTime MaxUtcDateTime { get { // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow. return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc); } } public static DateTime MinUtcDateTime { get { // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow. return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc); } } internal static IIdentity CreateIdentity(string name, string authenticationType) { return new GenericIdentity(name, authenticationType); } internal static IIdentity CreateIdentity(string name) { return new GenericIdentity(name); } internal static byte[] CloneBuffer(byte[] buffer) { return CloneBuffer(buffer, 0, buffer.Length); } internal static byte[] CloneBuffer(byte[] buffer, int offset, int len) { DiagnosticUtility.DebugAssert(offset >= 0, "Negative offset passed to CloneBuffer."); DiagnosticUtility.DebugAssert(len >= 0, "Negative len passed to CloneBuffer."); DiagnosticUtility.DebugAssert(buffer.Length - offset >= len, "Invalid parameters to CloneBuffer."); byte[] copy = Fx.AllocateByteArray(len); Buffer.BlockCopy(buffer, offset, copy, 0, len); return copy; } internal static bool MatchesBuffer(byte[] src, byte[] dst) { return MatchesBuffer(src, 0, dst, 0); } internal static bool MatchesBuffer(byte[] src, int srcOffset, byte[] dst, int dstOffset) { DiagnosticUtility.DebugAssert(dstOffset >= 0, "Negative dstOffset passed to MatchesBuffer."); DiagnosticUtility.DebugAssert(srcOffset >= 0, "Negative srcOffset passed to MatchesBuffer."); // defensive programming if ((dstOffset < 0) || (srcOffset < 0)) return false; if (src == null || srcOffset >= src.Length) return false; if (dst == null || dstOffset >= dst.Length) return false; if ((src.Length - srcOffset) != (dst.Length - dstOffset)) return false; for (int i = srcOffset, j = dstOffset; i < src.Length; i++, j++) { if (src[i] != dst[j]) return false; } return true; } internal static ReadOnlyCollection<IAuthorizationPolicy> CreateAuthorizationPolicies(ClaimSet claimSet) { return CreateAuthorizationPolicies(claimSet, SecurityUtils.MaxUtcDateTime); } internal static ReadOnlyCollection<IAuthorizationPolicy> CreateAuthorizationPolicies(ClaimSet claimSet, DateTime expirationTime) { List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1); policies.Add(new UnconditionalPolicy(claimSet, expirationTime)); return policies.AsReadOnly(); } internal static AuthorizationContext CreateDefaultAuthorizationContext(IList<IAuthorizationPolicy> authorizationPolicies) { AuthorizationContext _authorizationContext; // This is faster than Policy evaluation. if (authorizationPolicies != null && authorizationPolicies.Count == 1 && authorizationPolicies[0] is UnconditionalPolicy) { _authorizationContext = new SimpleAuthorizationContext(authorizationPolicies); } // degenerate case else if (authorizationPolicies == null || authorizationPolicies.Count <= 0) { return DefaultAuthorizationContext.Empty; } else { // there are some policies, run them until they are all done DefaultEvaluationContext evaluationContext = new DefaultEvaluationContext(); object[] policyState = new object[authorizationPolicies.Count]; object done = new object(); int oldContextCount; do { oldContextCount = evaluationContext.Generation; for (int i = 0; i < authorizationPolicies.Count; i++) { if (policyState[i] == done) continue; IAuthorizationPolicy policy = authorizationPolicies[i]; if (policy == null) { policyState[i] = done; continue; } if (policy.Evaluate(evaluationContext, ref policyState[i])) { policyState[i] = done; } } } while (oldContextCount < evaluationContext.Generation); _authorizationContext = new DefaultAuthorizationContext(evaluationContext); } return _authorizationContext; } internal static string ClaimSetToString(ClaimSet claimSet) { StringBuilder sb = new StringBuilder(); sb.AppendLine("ClaimSet ["); for (int i = 0; i < claimSet.Count; i++) { Claim claim = claimSet[i]; if (claim != null) { sb.Append(" "); sb.AppendLine(claim.ToString()); } } string prefix = "] by "; ClaimSet issuer = claimSet; do { issuer = issuer.Issuer; sb.AppendFormat("{0}{1}", prefix, issuer == claimSet ? "Self" : (issuer.Count <= 0 ? "Unknown" : issuer[0].ToString())); prefix = " -> "; } while (issuer.Issuer != issuer); return sb.ToString(); } internal static IIdentity CloneIdentityIfNecessary(IIdentity identity) { if (identity != null) { throw ExceptionHelper.PlatformNotSupported(); } return identity; } #if SUPPORTS_WINDOWSIDENTITY // NegotiateStream internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid) { return CloneWindowsIdentityIfNecessary(wid, wid.AuthenticationType); } internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authenticationType) { if (wid != null) { IntPtr token = wid.AccessToken.DangerousGetHandle(); if (token != null) { return UnsafeCreateWindowsIdentityFromToken(token, authenticationType); } } return wid; } static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid) { return wid.AccessToken.DangerousGetHandle(); } static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authenticationType) { if (authenticationType != null) { return new WindowsIdentity(token, authenticationType); } else { return new WindowsIdentity(token); } } #endif // SUPPORTS_WINDOWSIDENTITY internal static ClaimSet CloneClaimSetIfNecessary(ClaimSet claimSet) { if (claimSet != null) { throw ExceptionHelper.PlatformNotSupported(); } return claimSet; } internal static ReadOnlyCollection<ClaimSet> CloneClaimSetsIfNecessary(ReadOnlyCollection<ClaimSet> claimSets) { throw ExceptionHelper.PlatformNotSupported(); } internal static void DisposeClaimSetIfNecessary(ClaimSet claimSet) { throw ExceptionHelper.PlatformNotSupported(); } internal static void DisposeClaimSetsIfNecessary(ReadOnlyCollection<ClaimSet> claimSets) { throw ExceptionHelper.PlatformNotSupported(); } internal static ReadOnlyCollection<SecurityKey> CreateSymmetricSecurityKeys(byte[] key) { List<SecurityKey> temp = new List<SecurityKey>(1); temp.Add(new InMemorySymmetricSecurityKey(key)); return temp.AsReadOnly(); } internal static string GetCertificateId(X509Certificate2 certificate) { StringBuilder str = new StringBuilder(256); AppendCertificateIdentityName(str, certificate); return str.ToString(); } internal static void AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate) { string value = certificate.SubjectName.Name; if (String.IsNullOrEmpty(value)) { value = certificate.GetNameInfo(X509NameType.DnsName, false); if (String.IsNullOrEmpty(value)) { value = certificate.GetNameInfo(X509NameType.SimpleName, false); if (String.IsNullOrEmpty(value)) { value = certificate.GetNameInfo(X509NameType.EmailName, false); if (String.IsNullOrEmpty(value)) { value = certificate.GetNameInfo(X509NameType.UpnName, false); } } } } // Same format as X509Identity str.Append(String.IsNullOrEmpty(value) ? "<x509>" : value); str.Append("; "); str.Append(certificate.Thumbprint); } internal static ReadOnlyCollection<IAuthorizationPolicy> CloneAuthorizationPoliciesIfNecessary(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies) { if (authorizationPolicies != null && authorizationPolicies.Count > 0) { bool clone = false; for (int i = 0; i < authorizationPolicies.Count; ++i) { UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy; if (policy != null && policy.IsDisposable) { clone = true; break; } } if (clone) { List<IAuthorizationPolicy> ret = new List<IAuthorizationPolicy>(authorizationPolicies.Count); for (int i = 0; i < authorizationPolicies.Count; ++i) { UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy; if (policy != null) { ret.Add(policy.Clone()); } else { ret.Add(authorizationPolicies[i]); } } return new ReadOnlyCollection<IAuthorizationPolicy>(ret); } } return authorizationPolicies; } public static void DisposeAuthorizationPoliciesIfNecessary(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies) { if (authorizationPolicies != null && authorizationPolicies.Count > 0) { for (int i = 0; i < authorizationPolicies.Count; ++i) { DisposeIfNecessary(authorizationPolicies[i] as UnconditionalPolicy); } } } public static void DisposeIfNecessary(IDisposable obj) { if (obj != null) { obj.Dispose(); } } // This is the workaround, Since store.Certificates returns a full collection // of certs in store. These are holding native resources. internal static void ResetAllCertificates(X509Certificate2Collection certificates) { if (certificates != null) { for (int i = 0; i < certificates.Count; ++i) { ResetCertificate(certificates[i]); } } } internal static void ResetCertificate(X509Certificate2 certificate) { // Check that Dispose() and Reset() do the same thing certificate.Dispose(); } } internal static class EmptyReadOnlyCollection<T> { public static ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new List<T>()); } internal class SimpleAuthorizationContext : AuthorizationContext { private SecurityUniqueId _id; private UnconditionalPolicy _policy; private IDictionary<string, object> _properties; public SimpleAuthorizationContext(IList<IAuthorizationPolicy> authorizationPolicies) { _policy = (UnconditionalPolicy)authorizationPolicies[0]; Dictionary<string, object> properties = new Dictionary<string, object>(); if (_policy.PrimaryIdentity != null && _policy.PrimaryIdentity != SecurityUtils.AnonymousIdentity) { List<IIdentity> identities = new List<IIdentity>(); identities.Add(_policy.PrimaryIdentity); properties.Add(SecurityUtils.Identities, identities); } _properties = properties; } public override string Id { get { if (_id == null) _id = SecurityUniqueId.Create(); return _id.Value; } } public override ReadOnlyCollection<ClaimSet> ClaimSets { get { return _policy.Issuances; } } public override DateTime ExpirationTime { get { return _policy.ExpirationTime; } } public override IDictionary<string, object> Properties { get { return _properties; } } } }