1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.ServiceModel.Security
7 using System.Collections.Generic;
8 using System.Collections.ObjectModel;
9 using System.ComponentModel;
10 using System.Diagnostics;
11 using System.DirectoryServices.ActiveDirectory;
12 using System.Globalization;
13 using System.IdentityModel.Claims;
14 using System.IdentityModel.Policy;
15 using System.IdentityModel.Selectors;
16 using System.IdentityModel.Tokens;
18 using System.Net.Security;
20 using System.Security;
21 using System.Security.Authentication;
22 using System.Security.Authentication.ExtendedProtection;
23 using System.Security.Cryptography;
24 using System.Security.Cryptography.X509Certificates;
25 using System.Security.Permissions;
26 using System.Security.Principal;
27 using System.ServiceModel;
28 using System.ServiceModel.Channels;
29 using System.ServiceModel.Description;
30 using System.ServiceModel.Diagnostics;
31 using System.ServiceModel.Dispatcher;
32 using System.ServiceModel.Security.Tokens;
34 using System.Threading;
36 using Microsoft.Win32;
37 using AuthIdentityEx = System.IdentityModel.AuthIdentityEx;
38 using CredentialUse = System.IdentityModel.CredentialUse;
39 using DictionaryManager = System.IdentityModel.DictionaryManager;
40 using SafeFreeCredentials = System.IdentityModel.SafeFreeCredentials;
41 using SspiWrapper = System.IdentityModel.SspiWrapper;
43 static class StoreLocationHelper
45 internal static bool IsDefined(StoreLocation value)
47 return (value == StoreLocation.CurrentUser
48 || value == StoreLocation.LocalMachine);
52 static class ProtectionLevelHelper
54 internal static bool IsDefined(ProtectionLevel value)
56 return (value == ProtectionLevel.None
57 || value == ProtectionLevel.Sign
58 || value == ProtectionLevel.EncryptAndSign);
61 internal static void Validate(ProtectionLevel value)
63 if (!IsDefined(value))
65 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
66 typeof(ProtectionLevel)));
70 internal static bool IsStronger(ProtectionLevel v1, ProtectionLevel v2)
72 return ((v1 == ProtectionLevel.EncryptAndSign && v2 != ProtectionLevel.EncryptAndSign)
73 || (v1 == ProtectionLevel.Sign && v2 == ProtectionLevel.None));
76 internal static bool IsStrongerOrEqual(ProtectionLevel v1, ProtectionLevel v2)
78 return (v1 == ProtectionLevel.EncryptAndSign
79 || (v1 == ProtectionLevel.Sign && v2 != ProtectionLevel.EncryptAndSign));
82 internal static ProtectionLevel Max(ProtectionLevel v1, ProtectionLevel v2)
84 return IsStronger(v1, v2) ? v1 : v2;
87 internal static int GetOrdinal(Nullable<ProtectionLevel> p)
91 switch ((ProtectionLevel)p)
94 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("p", (int)p,
95 typeof(ProtectionLevel)));
96 case ProtectionLevel.None:
98 case ProtectionLevel.Sign:
100 case ProtectionLevel.EncryptAndSign:
109 static class SslProtocolsHelper
111 internal static bool IsDefined(SslProtocols value)
113 SslProtocols allValues = SslProtocols.None;
114 foreach (var protocol in Enum.GetValues(typeof(SslProtocols)))
116 allValues |= (SslProtocols)protocol;
118 return (value & allValues) == value;
121 internal static void Validate(SslProtocols value)
123 if (!IsDefined(value))
125 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
126 typeof(SslProtocols)));
131 static class TokenImpersonationLevelHelper
133 internal static bool IsDefined(TokenImpersonationLevel value)
135 return (value == TokenImpersonationLevel.None
136 || value == TokenImpersonationLevel.Anonymous
137 || value == TokenImpersonationLevel.Identification
138 || value == TokenImpersonationLevel.Impersonation
139 || value == TokenImpersonationLevel.Delegation);
142 internal static void Validate(TokenImpersonationLevel value)
144 if (!IsDefined(value))
146 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
147 typeof(TokenImpersonationLevel)));
151 static TokenImpersonationLevel[] TokenImpersonationLevelOrder = new TokenImpersonationLevel[]
153 TokenImpersonationLevel.None,
154 TokenImpersonationLevel.Anonymous,
155 TokenImpersonationLevel.Identification,
156 TokenImpersonationLevel.Impersonation,
157 TokenImpersonationLevel.Delegation
160 internal static string ToString(TokenImpersonationLevel impersonationLevel)
162 if (impersonationLevel == TokenImpersonationLevel.Identification)
164 return "identification";
166 else if (impersonationLevel == TokenImpersonationLevel.None)
170 else if (impersonationLevel == TokenImpersonationLevel.Anonymous)
174 else if (impersonationLevel == TokenImpersonationLevel.Impersonation)
176 return "impersonation";
178 else if (impersonationLevel == TokenImpersonationLevel.Delegation)
183 Fx.Assert("unknown token impersonation level");
184 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("impersonationLevel", (int)impersonationLevel,
185 typeof(TokenImpersonationLevel)));
188 internal static bool IsGreaterOrEqual(TokenImpersonationLevel x, TokenImpersonationLevel y)
190 TokenImpersonationLevelHelper.Validate(x);
191 TokenImpersonationLevelHelper.Validate(y);
198 for (int i = 0; i < TokenImpersonationLevelOrder.Length; i++)
200 if (x == TokenImpersonationLevelOrder[i])
202 if (y == TokenImpersonationLevelOrder[i])
209 internal static int Compare(TokenImpersonationLevel x, TokenImpersonationLevel y)
217 case TokenImpersonationLevel.Identification:
220 case TokenImpersonationLevel.Impersonation:
223 case TokenImpersonationLevel.Identification:
226 case TokenImpersonationLevel.Delegation:
230 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("y", (int)y,
231 typeof(TokenImpersonationLevel)));
235 case TokenImpersonationLevel.Delegation:
239 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("x", (int)x,
240 typeof(TokenImpersonationLevel)));
249 internal class ServiceModelDictionaryManager
251 static DictionaryManager dictionaryManager;
253 public static DictionaryManager Instance
257 if (dictionaryManager == null)
258 dictionaryManager = new DictionaryManager(BinaryMessageEncoderFactory.XmlDictionary);
260 return dictionaryManager;
265 static class SecurityUtils
267 public const string Principal = "Principal";
268 public const string Identities = "Identities";
269 static bool computedDomain;
270 static string currentDomain;
271 static byte[] combinedHashLabel;
272 static IIdentity anonymousIdentity;
273 static NetworkCredential dummyNetworkCredential;
274 static object dummyNetworkCredentialLock = new object();
275 static X509SecurityTokenAuthenticator nonValidatingX509Authenticator;
276 static SecurityIdentifier administratorsSid;
277 const int WindowsServerMajorNumber = 5;
278 const int WindowsServerMinorNumber = 2;
279 const int XPMajorNumber = 5;
280 const int XPMinorNumber = 1;
281 const string ServicePack1 = "Service Pack 1";
282 const string ServicePack2 = "Service Pack 2";
283 volatile static bool shouldValidateSslCipherStrength;
284 volatile static bool isSslValidationRequirementDetermined = false;
285 static readonly int MinimumSslCipherStrength = 128;
287 // these are kept in sync with IIS70
288 public const string AuthTypeNTLM = "NTLM";
289 public const string AuthTypeNegotiate = "Negotiate";
290 public const string AuthTypeKerberos = "Kerberos";
291 public const string AuthTypeAnonymous = "";
292 public const string AuthTypeCertMap = "SSL/PCT"; // mapped from a cert
293 public const string AuthTypeBasic = "Basic"; //LogonUser
295 public static ChannelBinding GetChannelBindingFromMessage(Message message)
302 ChannelBindingMessageProperty channelBindingMessageProperty = null;
303 ChannelBindingMessageProperty.TryGet(message, out channelBindingMessageProperty);
304 ChannelBinding channelBinding = null;
306 if (channelBindingMessageProperty != null)
308 channelBinding = channelBindingMessageProperty.ChannelBinding;
311 return channelBinding;
314 internal static bool IsOsGreaterThanXP()
316 return ((Environment.OSVersion.Version.Major >= SecurityUtils.XPMajorNumber && Environment.OSVersion.Version.Minor > SecurityUtils.XPMinorNumber) ||
317 Environment.OSVersion.Version.Major > SecurityUtils.XPMajorNumber);
320 internal static bool IsOSGreaterThanOrEqualToWin7()
322 Version windows7Version = new Version(6, 1, 0, 0);
323 return (Environment.OSVersion.Version.Major >= windows7Version.Major && Environment.OSVersion.Version.Minor >= windows7Version.Minor);
326 internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew)
328 DateTime curEffectiveTime = (effectiveTime < DateTime.MinValue.Add(maxClockSkew)) ? effectiveTime : effectiveTime.Subtract(maxClockSkew);
329 DateTime curExpirationTime = (expirationTime > DateTime.MaxValue.Subtract(maxClockSkew)) ? expirationTime : expirationTime.Add(maxClockSkew);
330 DateTime curTime = DateTime.UtcNow;
332 return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime());
335 internal static X509SecurityTokenAuthenticator NonValidatingX509Authenticator
339 if (nonValidatingX509Authenticator == null)
341 nonValidatingX509Authenticator = new X509SecurityTokenAuthenticator(X509CertificateValidator.None);
343 return nonValidatingX509Authenticator;
347 public static SecurityIdentifier AdministratorsSid
351 if (administratorsSid == null)
352 administratorsSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
353 return administratorsSid;
357 internal static IIdentity AnonymousIdentity
361 if (anonymousIdentity == null)
363 anonymousIdentity = SecurityUtils.CreateIdentity(String.Empty);
365 return anonymousIdentity;
369 public static DateTime MaxUtcDateTime
373 // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
374 return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc);
378 public static DateTime MinUtcDateTime
382 // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
383 return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc);
387 internal static IIdentity CreateIdentity(string name, string authenticationType)
389 return new GenericIdentity(name, authenticationType);
392 internal static IIdentity CreateIdentity(string name)
394 return new GenericIdentity(name);
397 internal static EndpointIdentity CreateWindowsIdentity()
399 return CreateWindowsIdentity(false);
402 internal static EndpointIdentity CreateWindowsIdentity(NetworkCredential serverCredential)
404 if (serverCredential != null && !NetworkCredentialHelper.IsDefault(serverCredential))
407 if (serverCredential.Domain != null && serverCredential.Domain.Length > 0)
409 upn = serverCredential.UserName + "@" + serverCredential.Domain;
413 upn = serverCredential.UserName;
415 return EndpointIdentity.CreateUpnIdentity(upn);
419 return SecurityUtils.CreateWindowsIdentity();
423 static bool IsSystemAccount(WindowsIdentity self)
425 SecurityIdentifier sid = self.User;
430 // S-1-5-82 is the prefix for the sid that represents the identity that IIS 7.5 Apppool thread runs under.
431 return (sid.IsWellKnown(WellKnownSidType.LocalSystemSid)
432 || sid.IsWellKnown(WellKnownSidType.NetworkServiceSid)
433 || sid.IsWellKnown(WellKnownSidType.LocalServiceSid)
434 || self.User.Value.StartsWith("S-1-5-82", StringComparison.OrdinalIgnoreCase));
437 internal static EndpointIdentity CreateWindowsIdentity(bool spnOnly)
439 EndpointIdentity identity = null;
440 using (WindowsIdentity self = WindowsIdentity.GetCurrent())
442 bool isSystemAccount = IsSystemAccount(self);
443 if (spnOnly || isSystemAccount)
445 identity = EndpointIdentity.CreateSpnIdentity(String.Format(CultureInfo.InvariantCulture, "host/{0}", DnsCache.MachineName));
449 // Save windowsIdentity for delay lookup
450 identity = new UpnEndpointIdentity(CloneWindowsIdentityIfNecessary(self));
457 [Fx.Tag.SecurityNote(Critical = "Calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken.",
458 Safe = "'Clone' operation is considered safe despite using WindowsIdentity IntPtr token. Must not let IntPtr token leak in or out.")]
459 [SecuritySafeCritical]
460 internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid)
462 return SecurityUtils.CloneWindowsIdentityIfNecessary(wid, null);
465 [Fx.Tag.SecurityNote(Critical = "Calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken.",
466 Safe = "'Clone' operation is considered safe despite using WindowsIdentity IntPtr token. Must not let IntPtr token leak in or out.")]
467 [SecuritySafeCritical]
468 internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authType)
472 IntPtr token = UnsafeGetWindowsIdentityToken(wid);
473 if (token != IntPtr.Zero)
475 return UnsafeCreateWindowsIdentityFromToken(token, authType);
481 [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")]
483 [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
484 static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid)
489 [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the SecurityIdentifier of the current user as a string, caller must protect return value.")]
491 [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
492 static string UnsafeGetCurrentUserSidAsString()
494 using (WindowsIdentity self = WindowsIdentity.GetCurrent())
496 return self.User.Value;
500 [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")]
502 [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)]
503 static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authType)
505 if (authType != null)
506 return new WindowsIdentity(token, authType);
508 return new WindowsIdentity(token);
511 internal static bool AllowsImpersonation(WindowsIdentity windowsIdentity, TokenImpersonationLevel impersonationLevel)
513 if (windowsIdentity == null)
514 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("windowsIdentity");
516 TokenImpersonationLevelHelper.Validate(impersonationLevel);
518 if (impersonationLevel == TokenImpersonationLevel.Identification)
519 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("impersonationLevel"));
523 switch (windowsIdentity.ImpersonationLevel)
525 case TokenImpersonationLevel.None:
526 case TokenImpersonationLevel.Anonymous:
527 case TokenImpersonationLevel.Identification:
528 result = false; break;
529 case TokenImpersonationLevel.Impersonation:
530 if (impersonationLevel == TokenImpersonationLevel.Delegation)
533 case TokenImpersonationLevel.Delegation:
543 internal static byte[] CombinedHashLabel
547 if (combinedHashLabel == null)
548 combinedHashLabel = Encoding.UTF8.GetBytes(TrustApr2004Strings.CombinedHashLabel);
549 return combinedHashLabel;
553 internal static T GetSecurityKey<T>(SecurityToken token)
554 where T : SecurityKey
557 if (token.SecurityKeys != null)
559 for (int i = 0; i < token.SecurityKeys.Count; ++i)
561 T temp = (token.SecurityKeys[i] as T);
566 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.MultipleMatchingCryptosFound, typeof(T).ToString())));
578 internal static bool HasSymmetricSecurityKey(SecurityToken token)
580 return GetSecurityKey<SymmetricSecurityKey>(token) != null;
583 internal static void EnsureExpectedSymmetricMatch(SecurityToken t1, SecurityToken t2, Message message)
585 // nulls are not mismatches
586 if (t1 == null || t2 == null || ReferenceEquals(t1, t2))
590 // check for interop flexibility
591 SymmetricSecurityKey c1 = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(t1);
592 SymmetricSecurityKey c2 = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(t2);
593 if (c1 == null || c2 == null || !CryptoHelper.IsEqual(c1.GetSymmetricKey(), c2.GetSymmetricKey()))
595 throw System.ServiceModel.Diagnostics.TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenNotExpectedInSecurityHeader, t2)), message);
599 internal static SymmetricAlgorithm GetSymmetricAlgorithm(string algorithm, SecurityToken token)
601 SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(token);
602 if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm))
604 return securityKey.GetSymmetricAlgorithm(algorithm);
612 internal static KeyedHashAlgorithm GetKeyedHashAlgorithm(string algorithm, SecurityToken token)
614 SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(token);
615 if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm))
617 return securityKey.GetKeyedHashAlgorithm(algorithm);
625 internal static ReadOnlyCollection<SecurityKey> CreateSymmetricSecurityKeys(byte[] key)
627 List<SecurityKey> temp = new List<SecurityKey>(1);
628 temp.Add(new InMemorySymmetricSecurityKey(key));
629 return temp.AsReadOnly();
632 internal static byte[] DecryptKey(SecurityToken unwrappingToken, string encryptionMethod, byte[] wrappedKey, out SecurityKey unwrappingSecurityKey)
634 unwrappingSecurityKey = null;
635 if (unwrappingToken.SecurityKeys != null)
637 for (int i = 0; i < unwrappingToken.SecurityKeys.Count; ++i)
639 if (unwrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod))
641 unwrappingSecurityKey = unwrappingToken.SecurityKeys[i];
646 if (unwrappingSecurityKey == null)
648 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod)));
650 return unwrappingSecurityKey.DecryptKey(encryptionMethod, wrappedKey);
653 internal static byte[] EncryptKey(SecurityToken wrappingToken, string encryptionMethod, byte[] keyToWrap)
655 SecurityKey wrappingSecurityKey = null;
656 if (wrappingToken.SecurityKeys != null)
658 for (int i = 0; i < wrappingToken.SecurityKeys.Count; ++i)
660 if (wrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod))
662 wrappingSecurityKey = wrappingToken.SecurityKeys[i];
667 if (wrappingSecurityKey == null)
669 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod));
671 return wrappingSecurityKey.EncryptKey(encryptionMethod, keyToWrap);
674 internal static byte[] ReadContentAsBase64(XmlDictionaryReader reader, long maxBufferSize)
677 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
679 // Code cloned from System.Xml.XmlDictionaryReder.
680 byte[][] buffers = new byte[32][];
682 // Its best to read in buffers that are a multiple of 3 so we don't break base64 boundaries when converting text
688 buffer = new byte[count];
689 buffers[bufferCount++] = buffer;
691 while (read < buffer.Length)
693 int actual = reader.ReadContentAsBase64(buffer, read, buffer.Length - read);
698 if (totalRead > maxBufferSize - read)
699 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(SR.GetString(SR.BufferQuotaExceededReadingBase64, maxBufferSize)));
701 if (read < buffer.Length)
705 buffer = new byte[totalRead];
707 for (int i = 0; i < bufferCount - 1; i++)
709 Buffer.BlockCopy(buffers[i], 0, buffer, offset, buffers[i].Length);
710 offset += buffers[i].Length;
712 Buffer.BlockCopy(buffers[bufferCount - 1], 0, buffer, offset, totalRead - offset);
716 internal static byte[] GenerateDerivedKey(SecurityToken tokenToDerive, string derivationAlgorithm, byte[] label, byte[] nonce,
717 int keySize, int offset)
719 SymmetricSecurityKey symmetricSecurityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(tokenToDerive);
720 if (symmetricSecurityKey == null || !symmetricSecurityKey.IsSupportedAlgorithm(derivationAlgorithm))
722 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, derivationAlgorithm)));
724 return symmetricSecurityKey.GenerateDerivedKey(derivationAlgorithm, label, nonce, keySize, offset);
727 internal static string GetSpnFromIdentity(EndpointIdentity identity, EndpointAddress target)
729 bool foundSpn = false;
731 if (identity != null)
733 if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
735 spn = (string)identity.IdentityClaim.Resource;
738 else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
740 spn = (string)identity.IdentityClaim.Resource;
743 else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
745 spn = String.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource);
751 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.CannotDetermineSPNBasedOnAddress, target)));
756 internal static string GetSpnFromTarget(EndpointAddress target)
760 throw Fx.AssertAndThrow("target should not be null - expecting an EndpointAddress");
763 return string.Format(CultureInfo.InvariantCulture, "host/{0}", target.Uri.DnsSafeHost);
766 internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token)
768 if (token.SecurityKeys == null)
772 for (int i = 0; i < token.SecurityKeys.Count; ++i)
774 if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm))
782 internal static Claim GetPrimaryIdentityClaim(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
784 return GetPrimaryIdentityClaim(AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies));
787 internal static Claim GetPrimaryIdentityClaim(AuthorizationContext authContext)
789 if (authContext != null)
791 for (int i = 0; i < authContext.ClaimSets.Count; ++i)
793 ClaimSet claimSet = authContext.ClaimSets[i];
794 foreach (Claim claim in claimSet.FindClaims(null, Rights.Identity))
803 internal static int GetServiceAddressAndViaHash(EndpointAddress sr)
807 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sr");
809 return sr.GetHashCode();
812 internal static string GenerateId()
814 return SecurityUniqueId.Create().Value;
817 internal static string GenerateIdWithPrefix(string prefix)
819 return SecurityUniqueId.Create(prefix).Value;
822 internal static UniqueId GenerateUniqueId()
824 return new UniqueId();
827 internal static string GetPrimaryDomain()
829 using (WindowsIdentity wid = WindowsIdentity.GetCurrent())
831 return GetPrimaryDomain(IsSystemAccount(wid));
835 internal static string GetPrimaryDomain(bool isSystemAccount)
837 if (computedDomain == false)
843 currentDomain = Domain.GetComputerDomain().Name;
847 currentDomain = Domain.GetCurrentDomain().Name;
850 #pragma warning suppress 56500 // covered by FxCOP
857 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
861 computedDomain = true;
864 return currentDomain;
867 internal static void EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate)
869 if (certificate == null)
871 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
873 bool canDoKeyExchange = false;
874 Exception innerException = null;
875 if (certificate.HasPrivateKey)
879 canDoKeyExchange = CanKeyDoKeyExchange(certificate);
881 // exceptions can be due to ACLs on the key etc
882 catch (System.Security.SecurityException e)
886 catch (CryptographicException e)
891 if (!canDoKeyExchange)
893 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SslCertMayNotDoKeyExchange, certificate.SubjectName.Name), innerException));
897 [Fx.Tag.SecurityNote(Critical = "Calls critical method GetKeyContainerInfo.",
898 Safe = "Info is not leaked.")]
899 [SecuritySafeCritical]
900 static bool CanKeyDoKeyExchange(X509Certificate2 certificate)
902 bool canDoKeyExchange = false;
904 if (!LocalAppContextSwitches.DisableCngCertificates)
906 X509KeyUsageExtension keyUsageExtension = null;
907 for (int i = 0; i < certificate.Extensions.Count; i++)
909 keyUsageExtension = certificate.Extensions[i] as X509KeyUsageExtension;
910 if (keyUsageExtension != null)
916 // No KeyUsage extension means most usages are permitted including key exchange.
917 // See RFC 5280 section 4.2.1.3 (Key Usage) for details. If the extension is non-critical
918 // then it's non-enforcing and meant as an aid in choosing the best certificate when
919 // there are multiple certificates to choose from.
920 if (keyUsageExtension == null || !keyUsageExtension.Critical)
925 // One of KeyAgreement, KeyEncipherment or DigitalSignature need to be allowed depending on the cipher
926 // being used. See RFC 5246 section 7.4.6 for more details.
927 // Additionally, according to msdn docs for PFXImportCertStore, the key specification is set to AT_KEYEXCHANGE
928 // when the data encipherment usage is set.
929 canDoKeyExchange = (keyUsageExtension.KeyUsages &
930 (X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.KeyEncipherment |
931 X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.DataEncipherment)) != X509KeyUsageFlags.None;
934 if (!canDoKeyExchange)
936 CspKeyContainerInfo info = GetKeyContainerInfo(certificate);
937 canDoKeyExchange = info != null && info.KeyNumber == KeyNumber.Exchange;
940 return canDoKeyExchange;
943 [Fx.Tag.SecurityNote(Critical = "Elevates to call properties: X509Certificate2.PrivateKey and CspKeyContainerInfo. Caller must protect the return value.")]
945 [KeyContainerPermission(SecurityAction.Assert, Flags = KeyContainerPermissionFlags.Open)]
946 static CspKeyContainerInfo GetKeyContainerInfo(X509Certificate2 certificate)
948 RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider;
951 return rsa.CspKeyContainerInfo;
957 internal static string GetCertificateId(X509Certificate2 certificate)
959 StringBuilder str = new StringBuilder(256);
960 AppendCertificateIdentityName(str, certificate);
961 return str.ToString();
964 internal static ReadOnlyCollection<IAuthorizationPolicy> CreatePrincipalNameAuthorizationPolicies(string principalName)
966 if (principalName == null)
967 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("principalName");
970 Claim primaryPrincipal;
971 if (principalName.Contains("@") || principalName.Contains(@"\"))
973 identityClaim = new Claim(ClaimTypes.Upn, principalName, Rights.Identity);
974 primaryPrincipal = Claim.CreateUpnClaim(principalName);
978 identityClaim = new Claim(ClaimTypes.Spn, principalName, Rights.Identity);
979 primaryPrincipal = Claim.CreateSpnClaim(principalName);
982 List<Claim> claims = new List<Claim>(2);
983 claims.Add(identityClaim);
984 claims.Add(primaryPrincipal);
986 List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1);
987 policies.Add(new UnconditionalPolicy(SecurityUtils.CreateIdentity(principalName), new DefaultClaimSet(ClaimSet.Anonymous, claims)));
988 return policies.AsReadOnly();
991 internal static string GetIdentityNamesFromPolicies(IList<IAuthorizationPolicy> authPolicies)
993 return GetIdentityNamesFromContext(AuthorizationContext.CreateDefaultAuthorizationContext(authPolicies));
996 internal static string GetIdentityNamesFromContext(AuthorizationContext authContext)
998 if (authContext == null)
1001 StringBuilder str = new StringBuilder(256);
1002 for (int i = 0; i < authContext.ClaimSets.Count; ++i)
1004 ClaimSet claimSet = authContext.ClaimSets[i];
1007 WindowsClaimSet windows = claimSet as WindowsClaimSet;
1008 if (windows != null)
1013 AppendIdentityName(str, windows.WindowsIdentity);
1018 X509CertificateClaimSet x509 = claimSet as X509CertificateClaimSet;
1024 AppendCertificateIdentityName(str, x509.X509Certificate);
1029 if (str.Length <= 0)
1031 List<IIdentity> identities = null;
1033 if (authContext.Properties.TryGetValue(SecurityUtils.Identities, out obj))
1035 identities = obj as List<IIdentity>;
1037 if (identities != null)
1039 for (int i = 0; i < identities.Count; ++i)
1041 IIdentity identity = identities[i];
1042 if (identity != null)
1047 AppendIdentityName(str, identity);
1052 return str.Length <= 0 ? String.Empty : str.ToString();
1055 internal static void AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate)
1057 string value = certificate.SubjectName.Name;
1058 if (String.IsNullOrEmpty(value))
1060 value = certificate.GetNameInfo(X509NameType.DnsName, false);
1061 if (String.IsNullOrEmpty(value))
1063 value = certificate.GetNameInfo(X509NameType.SimpleName, false);
1064 if (String.IsNullOrEmpty(value))
1066 value = certificate.GetNameInfo(X509NameType.EmailName, false);
1067 if (String.IsNullOrEmpty(value))
1069 value = certificate.GetNameInfo(X509NameType.UpnName, false);
1074 // Same format as X509Identity
1075 str.Append(String.IsNullOrEmpty(value) ? "<x509>" : value);
1077 str.Append(certificate.Thumbprint);
1080 internal static void AppendIdentityName(StringBuilder str, IIdentity identity)
1085 name = identity.Name;
1087 #pragma warning suppress 56500
1094 // suppress exception, this is just info.
1097 str.Append(String.IsNullOrEmpty(name) ? "<null>" : name);
1099 WindowsIdentity windows = identity as WindowsIdentity;
1100 if (windows != null)
1102 if (windows.User != null)
1105 str.Append(windows.User.ToString());
1110 WindowsSidIdentity sid = identity as WindowsSidIdentity;
1114 str.Append(sid.SecurityIdentifier.ToString());
1119 [Fx.Tag.SecurityNote(Critical = "Calls critical methods UnsafeGetDomain, UnsafeGetUserName, UnsafeGetPassword and UnsafeGetCurrentUserSidAsString.")]
1121 internal static string AppendWindowsAuthenticationInfo(string inputString, NetworkCredential credential,
1122 AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel)
1124 const string delimiter = "\0"; // nonprintable characters are invalid for SSPI Domain/UserName/Password
1126 if (IsDefaultNetworkCredential(credential))
1128 string sid = UnsafeGetCurrentUserSidAsString();
1129 return string.Concat(inputString, delimiter,
1131 AuthenticationLevelHelper.ToString(authenticationLevel), delimiter,
1132 TokenImpersonationLevelHelper.ToString(impersonationLevel));
1136 return string.Concat(inputString, delimiter,
1137 NetworkCredentialHelper.UnsafeGetDomain(credential), delimiter,
1138 NetworkCredentialHelper.UnsafeGetUsername(credential), delimiter,
1139 NetworkCredentialHelper.UnsafeGetPassword(credential), delimiter,
1140 AuthenticationLevelHelper.ToString(authenticationLevel), delimiter,
1141 TokenImpersonationLevelHelper.ToString(impersonationLevel));
1145 internal static string GetIdentityName(IIdentity identity)
1147 StringBuilder str = new StringBuilder(256);
1148 AppendIdentityName(str, identity);
1149 return str.ToString();
1153 /// Critical - Calls an UnsafeNativeMethod and a Critical method (GetFipsAlgorithmPolicyKeyFromRegistry)
1154 /// Safe - processes the return and just returns a bool, which is safe
1156 internal static bool IsChannelBindingDisabled
1158 [SecuritySafeCritical]
1161 return ((GetSuppressChannelBindingValue() & 0x1) != 0);
1165 const string suppressChannelBindingRegistryKey = @"System\CurrentControlSet\Control\Lsa";
1168 /// Critical - Asserts to get a value from the registry
1171 [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + suppressChannelBindingRegistryKey)]
1172 internal static int GetSuppressChannelBindingValue()
1174 int channelBindingPolicyKeyValue = 0;
1178 using (RegistryKey channelBindingPolicyKey = Registry.LocalMachine.OpenSubKey(suppressChannelBindingRegistryKey, false))
1180 if (channelBindingPolicyKey != null)
1182 object data = channelBindingPolicyKey.GetValue("SuppressChannelBindingInfo");
1184 channelBindingPolicyKeyValue = (int)data;
1188 #pragma warning suppress 56500
1195 return channelBindingPolicyKeyValue;
1198 internal static bool IsSecurityBindingSuitableForChannelBinding(TransportSecurityBindingElement securityBindingElement)
1200 if (securityBindingElement == null)
1205 // channel binding of OperationSupportingTokenParameters, OptionalEndpointSupportingTokenParameters, or OptionalOperationSupportingTokenParameters
1206 // is not supported in Win7
1207 if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Endorsing))
1212 if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Signed))
1217 if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted))
1222 if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEndorsing))
1230 internal static bool AreSecurityTokenParametersSuitableForChannelBinding(Collection<SecurityTokenParameters> tokenParameters)
1232 if (tokenParameters == null)
1237 foreach (SecurityTokenParameters stp in tokenParameters)
1239 if (stp is SspiSecurityTokenParameters || stp is KerberosSecurityTokenParameters)
1244 SecureConversationSecurityTokenParameters scstp = stp as SecureConversationSecurityTokenParameters;
1247 return IsSecurityBindingSuitableForChannelBinding(scstp.BootstrapSecurityBindingElement as TransportSecurityBindingElement);
1254 internal static void ThrowIfNegotiationFault(Message message, EndpointAddress target)
1256 if (message.IsFault)
1258 MessageFault fault = MessageFault.CreateFault(message, TransportDefaults.MaxSecurityFaultSize);
1259 Exception faultException = new FaultException(fault, message.Headers.Action);
1260 if (fault.Code != null && fault.Code.IsReceiverFault && fault.Code.SubCode != null)
1262 FaultCode subCode = fault.Code.SubCode;
1263 if (subCode.Name == DotNetSecurityStrings.SecurityServerTooBusyFault && subCode.Namespace == DotNetSecurityStrings.Namespace)
1265 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ServerTooBusyException(SR.GetString(SR.SecurityServerTooBusy, target), faultException));
1267 else if (subCode.Name == AddressingStrings.EndpointUnavailable && subCode.Namespace == message.Version.Addressing.Namespace)
1269 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR.GetString(SR.SecurityEndpointNotFound, target), faultException));
1272 throw TraceUtility.ThrowHelperError(faultException, message);
1276 internal static bool IsSecurityFault(MessageFault fault, SecurityStandardsManager standardsManager)
1278 if (fault.Code.IsSenderFault)
1280 FaultCode subCode = fault.Code.SubCode;
1281 if (subCode != null)
1283 return (subCode.Namespace == standardsManager.SecurityVersion.HeaderNamespace.Value
1284 || subCode.Namespace == standardsManager.SecureConversationDriver.Namespace.Value
1285 || subCode.Namespace == standardsManager.TrustDriver.Namespace.Value
1286 || subCode.Namespace == DotNetSecurityStrings.Namespace);
1292 internal static Exception CreateSecurityFaultException(Message unverifiedMessage)
1294 MessageFault fault = MessageFault.CreateFault(unverifiedMessage, TransportDefaults.MaxSecurityFaultSize);
1295 return CreateSecurityFaultException(fault);
1298 internal static Exception CreateSecurityFaultException(MessageFault fault)
1300 FaultException faultException = FaultException.CreateFault(fault, typeof(string), typeof(object));
1301 return new MessageSecurityException(SR.GetString(SR.UnsecuredMessageFaultReceived), faultException);
1304 internal static MessageFault CreateSecurityContextNotFoundFault(SecurityStandardsManager standardsManager, string action)
1306 SecureConversationDriver scDriver = standardsManager.SecureConversationDriver;
1307 FaultCode subCode = new FaultCode(scDriver.BadContextTokenFaultCode.Value, scDriver.Namespace.Value);
1311 reason = new FaultReason(SR.GetString(SR.BadContextTokenOrActionFaultReason, action), CultureInfo.CurrentCulture);
1315 reason = new FaultReason(SR.GetString(SR.BadContextTokenFaultReason), CultureInfo.CurrentCulture);
1317 FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
1318 return MessageFault.CreateFault(senderCode, reason);
1321 internal static MessageFault CreateSecurityMessageFault(Exception e, SecurityStandardsManager standardsManager)
1323 bool isSecurityError = false;
1324 bool isTokenValidationError = false;
1325 bool isGenericTokenError = false;
1326 FaultException faultException = null;
1329 if (e is SecurityTokenValidationException)
1331 if (e is SecurityContextTokenValidationException)
1333 return CreateSecurityContextNotFoundFault(SecurityStandardsManager.DefaultInstance, null);
1335 isSecurityError = true;
1336 isTokenValidationError = true;
1339 else if (e is SecurityTokenException)
1341 isSecurityError = true;
1342 isGenericTokenError = true;
1345 else if (e is MessageSecurityException)
1347 MessageSecurityException ms = (MessageSecurityException)e;
1348 if (ms.Fault != null)
1352 isSecurityError = true;
1354 else if (e is FaultException)
1356 faultException = (FaultException)e;
1359 e = e.InnerException;
1361 if (!isSecurityError && faultException == null)
1367 SecurityVersion wss = standardsManager.SecurityVersion;
1368 if (isTokenValidationError)
1370 subCode = new FaultCode(wss.FailedAuthenticationFaultCode.Value, wss.HeaderNamespace.Value);
1371 reason = new FaultReason(SR.GetString(SR.FailedAuthenticationFaultReason), CultureInfo.CurrentCulture);
1373 else if (isGenericTokenError)
1375 subCode = new FaultCode(wss.InvalidSecurityTokenFaultCode.Value, wss.HeaderNamespace.Value);
1376 reason = new FaultReason(SR.GetString(SR.InvalidSecurityTokenFaultReason), CultureInfo.CurrentCulture);
1378 else if (faultException != null)
1380 // Only support Code and Reason. No detail or action customization.
1381 return MessageFault.CreateFault(faultException.Code, faultException.Reason);
1385 subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value);
1386 reason = new FaultReason(SR.GetString(SR.InvalidSecurityFaultReason), CultureInfo.CurrentCulture);
1388 FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
1389 return MessageFault.CreateFault(senderCode, reason);
1392 internal static bool IsCompositeDuplexBinding(BindingContext context)
1394 return ((context.Binding.Elements.Find<CompositeDuplexBindingElement>() != null)
1395 || (context.Binding.Elements.Find<InternalDuplexBindingElement>() != null));
1398 // The method checks TransportToken, ProtectionToken and all SupportingTokens to find a
1399 // UserNameSecurityToken. If found, it sets the password of the UserNameSecurityToken to null.
1400 // Custom UserNameSecurityToken are skipped.
1401 internal static void ErasePasswordInUsernameTokenIfPresent(SecurityMessageProperty messageProperty)
1403 if (messageProperty == null)
1409 if (messageProperty.TransportToken != null)
1411 UserNameSecurityToken token = messageProperty.TransportToken.SecurityToken as UserNameSecurityToken;
1412 if ((token != null) && !messageProperty.TransportToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1414 messageProperty.TransportToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.TransportToken.SecurityTokenPolicies);
1418 if (messageProperty.ProtectionToken != null)
1420 UserNameSecurityToken token = messageProperty.ProtectionToken.SecurityToken as UserNameSecurityToken;
1421 if ((token != null) && !messageProperty.ProtectionToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1423 messageProperty.ProtectionToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.ProtectionToken.SecurityTokenPolicies);
1427 if (messageProperty.HasIncomingSupportingTokens)
1429 for (int i = 0; i < messageProperty.IncomingSupportingTokens.Count; ++i)
1431 SupportingTokenSpecification supportingTokenSpecification = messageProperty.IncomingSupportingTokens[i];
1432 UserNameSecurityToken token = supportingTokenSpecification.SecurityToken as UserNameSecurityToken;
1433 if ((token != null) && !supportingTokenSpecification.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1435 messageProperty.IncomingSupportingTokens[i] = new SupportingTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), supportingTokenSpecification.SecurityTokenPolicies, supportingTokenSpecification.SecurityTokenAttachmentMode, supportingTokenSpecification.SecurityTokenParameters);
1441 // work-around to Windows SE Bug 141614
1442 [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetPassword to access the credential password without a Demand.",
1443 Safe = "Only uses the password to construct a cloned NetworkCredential instance, does not leak password value.")]
1444 [SecuritySafeCritical]
1445 internal static void FixNetworkCredential(ref NetworkCredential credential)
1447 if (credential == null)
1451 string username = NetworkCredentialHelper.UnsafeGetUsername(credential);
1452 string domain = NetworkCredentialHelper.UnsafeGetDomain(credential);
1453 if (!string.IsNullOrEmpty(username) && string.IsNullOrEmpty(domain))
1455 // do the splitting only if there is exactly 1 \ or exactly 1 @
1456 string[] partsWithSlashDelimiter = username.Split('\\');
1457 string[] partsWithAtDelimiter = username.Split('@');
1458 if (partsWithSlashDelimiter.Length == 2 && partsWithAtDelimiter.Length == 1)
1460 if (!string.IsNullOrEmpty(partsWithSlashDelimiter[0]) && !string.IsNullOrEmpty(partsWithSlashDelimiter[1]))
1462 credential = new NetworkCredential(partsWithSlashDelimiter[1], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithSlashDelimiter[0]);
1465 else if (partsWithSlashDelimiter.Length == 1 && partsWithAtDelimiter.Length == 2)
1467 if (!string.IsNullOrEmpty(partsWithAtDelimiter[0]) && !string.IsNullOrEmpty(partsWithAtDelimiter[1]))
1469 credential = new NetworkCredential(partsWithAtDelimiter[0], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithAtDelimiter[1]);
1475 // WORKAROUND, Microsoft, VSWhidbey 561276: The first NetworkCredential must be created in a lock.
1476 internal static void PrepareNetworkCredential()
1478 if (dummyNetworkCredential == null)
1480 PrepareNetworkCredentialWorker();
1484 // Since this takes a lock, it probably won't be inlined, but the typical case will be.
1485 static void PrepareNetworkCredentialWorker()
1487 lock (dummyNetworkCredentialLock)
1489 dummyNetworkCredential = new NetworkCredential("dummy", "dummy");
1493 // This is the workaround, Since store.Certificates returns a full collection
1494 // of certs in store. These are holding native resources.
1495 internal static void ResetAllCertificates(X509Certificate2Collection certificates)
1497 if (certificates != null)
1499 for (int i = 0; i < certificates.Count; ++i)
1501 ResetCertificate(certificates[i]);
1506 [Fx.Tag.SecurityNote(Critical = "Calls critical method X509Certificate2.Reset.",
1507 Safe = "Per review from CLR security team, this method does nothing unsafe.")]
1508 [SecuritySafeCritical]
1509 internal static void ResetCertificate(X509Certificate2 certificate)
1511 certificate.Reset();
1514 internal static bool IsDefaultNetworkCredential(NetworkCredential credential)
1516 return NetworkCredentialHelper.IsDefault(credential);
1519 internal static void OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
1521 OpenCommunicationObject(tokenProvider as ICommunicationObject, timeout);
1524 internal static IAsyncResult BeginOpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout,
1525 AsyncCallback callback, object state)
1527 return new OpenCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state);
1530 internal static void EndOpenTokenProviderIfRequired(IAsyncResult result)
1532 OpenCommunicationObjectAsyncResult.End(result);
1535 internal static IAsyncResult BeginCloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout,
1536 AsyncCallback callback, object state)
1538 return new CloseCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state);
1541 internal static void EndCloseTokenProviderIfRequired(IAsyncResult result)
1543 CloseCommunicationObjectAsyncResult.End(result);
1546 internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
1548 CloseCommunicationObject(tokenProvider, false, timeout);
1551 internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, bool aborted, TimeSpan timeout)
1553 CloseCommunicationObject(tokenProvider, aborted, timeout);
1556 internal static void AbortTokenProviderIfRequired(SecurityTokenProvider tokenProvider)
1558 CloseCommunicationObject(tokenProvider, true, TimeSpan.Zero);
1561 internal static void OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)
1563 OpenCommunicationObject(tokenAuthenticator as ICommunicationObject, timeout);
1566 internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)
1568 CloseTokenAuthenticatorIfRequired(tokenAuthenticator, false, timeout);
1571 internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, bool aborted, TimeSpan timeout)
1573 CloseCommunicationObject(tokenAuthenticator, aborted, timeout);
1576 internal static IAsyncResult BeginOpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout,
1577 AsyncCallback callback, object state)
1579 return new OpenCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state);
1582 internal static void EndOpenTokenAuthenticatorIfRequired(IAsyncResult result)
1584 OpenCommunicationObjectAsyncResult.End(result);
1587 internal static IAsyncResult BeginCloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout,
1588 AsyncCallback callback, object state)
1590 return new CloseCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state);
1593 internal static void EndCloseTokenAuthenticatorIfRequired(IAsyncResult result)
1595 CloseCommunicationObjectAsyncResult.End(result);
1598 internal static void AbortTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator)
1600 CloseCommunicationObject(tokenAuthenticator, true, TimeSpan.Zero);
1603 static void OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout)
1609 static void CloseCommunicationObject(Object obj, bool aborted, TimeSpan timeout)
1613 ICommunicationObject co = obj as ICommunicationObject;
1622 catch (CommunicationException e)
1624 DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
1632 else if (obj is IDisposable)
1634 ((IDisposable)obj).Dispose();
1639 class OpenCommunicationObjectAsyncResult : AsyncResult
1641 ICommunicationObject communicationObject;
1642 static AsyncCallback onOpen;
1644 public OpenCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)
1645 : base(callback, state)
1647 this.communicationObject = obj as ICommunicationObject;
1649 bool completeSelf = false;
1650 if (this.communicationObject == null)
1652 completeSelf = true;
1658 onOpen = Fx.ThunkCallback(new AsyncCallback(OnOpen));
1661 IAsyncResult result = this.communicationObject.BeginOpen(timeout, onOpen, this);
1662 if (result.CompletedSynchronously)
1664 this.communicationObject.EndOpen(result);
1665 completeSelf = true;
1671 base.Complete(true);
1675 public static void End(IAsyncResult result)
1677 AsyncResult.End<OpenCommunicationObjectAsyncResult>(result);
1680 static void OnOpen(IAsyncResult result)
1682 if (result.CompletedSynchronously)
1687 OpenCommunicationObjectAsyncResult thisPtr =
1688 (OpenCommunicationObjectAsyncResult)result.AsyncState;
1690 Exception completionException = null;
1693 thisPtr.communicationObject.EndOpen(result);
1695 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1703 completionException = e;
1705 thisPtr.Complete(false, completionException);
1709 class CloseCommunicationObjectAsyncResult : AsyncResult
1711 ICommunicationObject communicationObject;
1712 static AsyncCallback onClose;
1714 public CloseCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)
1715 : base(callback, state)
1717 this.communicationObject = obj as ICommunicationObject;
1719 bool completeSelf = false;
1720 if (this.communicationObject == null)
1722 IDisposable disposable = obj as IDisposable;
1723 if (disposable != null)
1725 disposable.Dispose();
1727 completeSelf = true;
1731 if (onClose == null)
1733 onClose = Fx.ThunkCallback(new AsyncCallback(OnClose));
1736 IAsyncResult result = this.communicationObject.BeginClose(timeout, onClose, this);
1737 if (result.CompletedSynchronously)
1739 this.communicationObject.EndClose(result);
1740 completeSelf = true;
1746 base.Complete(true);
1750 public static void End(IAsyncResult result)
1752 AsyncResult.End<CloseCommunicationObjectAsyncResult>(result);
1755 static void OnClose(IAsyncResult result)
1757 if (result.CompletedSynchronously)
1762 CloseCommunicationObjectAsyncResult thisPtr =
1763 (CloseCommunicationObjectAsyncResult)result.AsyncState;
1765 Exception completionException = null;
1768 thisPtr.communicationObject.EndClose(result);
1770 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1778 completionException = e;
1780 thisPtr.Complete(false, completionException);
1784 internal static void MatchRstWithEndpointFilter(Message rst, IMessageFilterTable<EndpointAddress> endpointFilterTable, Uri listenUri)
1786 if (endpointFilterTable == null)
1790 Collection<EndpointAddress> result = new Collection<EndpointAddress>();
1791 if (!endpointFilterTable.GetMatchingValues(rst, result))
1793 throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.RequestSecurityTokenDoesNotMatchEndpointFilters, listenUri)), rst);
1797 // match the RST with the endpoint filters in case there is at least 1 asymmetric signature in the message
1798 internal static bool ShouldMatchRstWithEndpointFilter(SecurityBindingElement sbe)
1800 foreach (SecurityTokenParameters parameters in new SecurityTokenParametersEnumerable(sbe, true))
1802 if (parameters.HasAsymmetricKey)
1810 internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenManager tokenManager)
1812 SecurityTokenSerializer tokenSerializer = tokenManager.CreateSecurityTokenSerializer(securityVersion.SecurityTokenVersion);
1813 return new SecurityStandardsManager(securityVersion, tokenSerializer);
1816 internal static SecurityStandardsManager CreateSecurityStandardsManager(SecurityTokenRequirement requirement, SecurityTokenManager tokenManager)
1818 MessageSecurityTokenVersion securityVersion = (MessageSecurityTokenVersion)requirement.GetProperty<MessageSecurityTokenVersion>(ServiceModelSecurityTokenRequirement.MessageSecurityVersionProperty);
1819 if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005BasicSecurityProfile10)
1820 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, tokenManager);
1821 else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005)
1822 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11, tokenManager);
1823 else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005BasicSecurityProfile10)
1824 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, tokenManager);
1825 else if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrust13WSSecureConversation13BasicSecurityProfile10)
1826 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10, tokenManager);
1827 else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13)
1828 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12, tokenManager);
1829 else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13BasicSecurityProfile10)
1830 return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10, tokenManager);
1832 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
1835 internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenSerializer securityTokenSerializer)
1837 if (securityVersion == null)
1839 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("securityVersion"));
1841 if (securityTokenSerializer == null)
1843 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenSerializer");
1845 return new SecurityStandardsManager(securityVersion, securityTokenSerializer);
1848 static bool TryCreateIdentity(ClaimSet claimSet, string claimType, out EndpointIdentity identity)
1851 foreach (Claim claim in claimSet.FindClaims(claimType, null))
1853 identity = EndpointIdentity.CreateIdentity(claim);
1859 internal static EndpointIdentity GetServiceCertificateIdentity(X509Certificate2 certificate)
1861 using (X509CertificateClaimSet claimSet = new X509CertificateClaimSet(certificate))
1863 EndpointIdentity identity;
1864 if (!TryCreateIdentity(claimSet, ClaimTypes.Dns, out identity))
1866 TryCreateIdentity(claimSet, ClaimTypes.Rsa, out identity);
1872 [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetPassword to access the credential password without a Demand.",
1873 Safe = "Only uses the password to construct a new NetworkCredential which will then protect access, password does not leak from this method.")]
1874 [SecuritySafeCritical]
1875 internal static NetworkCredential GetNetworkCredentialsCopy(NetworkCredential networkCredential)
1877 NetworkCredential result;
1878 if (networkCredential != null && !NetworkCredentialHelper.IsDefault(networkCredential))
1880 result = new NetworkCredential(NetworkCredentialHelper.UnsafeGetUsername(networkCredential), NetworkCredentialHelper.UnsafeGetPassword(networkCredential), NetworkCredentialHelper.UnsafeGetDomain(networkCredential));
1884 result = networkCredential;
1889 internal static NetworkCredential GetNetworkCredentialOrDefault(NetworkCredential credential)
1891 // because of VSW 564452, we dont use CredentialCache.DefaultNetworkCredentials in our OM. Instead we
1892 // use an empty NetworkCredential to denote the default credentials
1893 if (NetworkCredentialHelper.IsNullOrEmpty(credential))
1895 // FYI: this will fail with SecurityException in PT due to Demand for EnvironmentPermission.
1896 // Typically a PT app should not have access to DefaultNetworkCredentials. If there is a valid reason,
1897 // see UnsafeGetDefaultNetworkCredentials.
1898 return CredentialCache.DefaultNetworkCredentials;
1906 public static bool CanReadPrivateKey(X509Certificate2 certificate)
1908 if (!certificate.HasPrivateKey)
1913 // CNG key, CNG permissions tests
1914 using (RSA rsa = CngLightup.GetRSAPrivateKey(certificate))
1922 using (DSA dsa = CngLightup.GetDSAPrivateKey(certificate))
1930 using (ECDsa ecdsa = CngLightup.GetECDsaPrivateKey(certificate))
1938 // CAPI key, CAPI permissions test
1939 if (certificate.PrivateKey != null)
1946 catch (CryptographicException)
1952 static class NetworkCredentialHelper
1954 [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical methods UnsafeGetUsername, UnsafeGetPassword, and UnsafeGetDomain to access the credential details without a Demand.",
1955 Safe = "Only uses the protected values to test for null/empty. Does not leak.")]
1956 [SecuritySafeCritical]
1957 static internal bool IsNullOrEmpty(NetworkCredential credential)
1959 return credential == null ||
1961 String.IsNullOrEmpty(UnsafeGetUsername(credential)) &&
1962 String.IsNullOrEmpty(UnsafeGetDomain(credential)) &&
1963 String.IsNullOrEmpty(UnsafeGetPassword(credential))
1967 [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetDefaultNetworkCredentials to access the default network credentials without a Demand.",
1968 Safe = "Only uses the default credentials to test for equality and uses the system credential's .Equals, not the caller's.")]
1969 [SecuritySafeCritical]
1970 static internal bool IsDefault(NetworkCredential credential)
1972 return UnsafeGetDefaultNetworkCredentials().Equals(credential);
1975 [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password."
1976 + "This is used for example to test for empty/null or to construct a cloned NetworkCredential."
1977 + "Callers absolutely must not leak the return value.")]
1979 [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")]
1980 static internal string UnsafeGetUsername(NetworkCredential credential)
1982 return credential.UserName;
1985 [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password."
1986 + "This is used for example to test for empty/null or to construct a cloned NetworkCredential."
1987 + "Callers absolutely must not leak the return value.")]
1989 [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
1990 static internal string UnsafeGetPassword(NetworkCredential credential)
1992 return credential.Password;
1995 [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password."
1996 + "This is used for example to test for empty/null or to construct a cloned NetworkCredential."
1997 + "Callers absolutely must not leak the return value.")]
1999 [EnvironmentPermission(SecurityAction.Assert, Read = "USERDOMAIN")]
2000 static internal string UnsafeGetDomain(NetworkCredential credential)
2002 return credential.Domain;
2005 [Fx.Tag.SecurityNote(Critical = "Asserts EnvironmentPermission(Read='USERNAME') in order to get the DefaultNetworkCredentials in PT."
2006 + "This is used for example to test for instance equality with a specific NetworkCredential."
2007 + "Callers absolutely must not leak the return value.")]
2009 [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")]
2010 static NetworkCredential UnsafeGetDefaultNetworkCredentials()
2012 return CredentialCache.DefaultNetworkCredentials;
2016 internal static SafeFreeCredentials GetCredentialsHandle(string package, NetworkCredential credential, bool isServer, params string[] additionalPackages)
2018 SafeFreeCredentials credentialsHandle;
2019 CredentialUse credentialUse = isServer ? CredentialUse.Inbound : CredentialUse.Outbound;
2020 if (credential == null || NetworkCredentialHelper.IsDefault(credential))
2022 AuthIdentityEx authIdentity = new AuthIdentityEx(null, null, null, additionalPackages);
2023 credentialsHandle = SspiWrapper.AcquireCredentialsHandle(package, credentialUse, ref authIdentity);
2027 SecurityUtils.FixNetworkCredential(ref credential);
2029 // we're not using DefaultCredentials, we need a
2030 // AuthIdentity struct to contain credentials
2031 AuthIdentityEx authIdentity = new AuthIdentityEx(credential.UserName, credential.Password, credential.Domain);
2032 credentialsHandle = SspiWrapper.AcquireCredentialsHandle(package, credentialUse, ref authIdentity);
2034 return credentialsHandle;
2037 internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, KeyedByTypeCollection<IEndpointBehavior> behaviors)
2039 ClientCredentials clientCredentials = (behaviors == null) ? null : behaviors.Find<ClientCredentials>();
2040 return GetCredentialsHandle(binding, clientCredentials);
2043 internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, ClientCredentials clientCredentials)
2045 SecurityBindingElement sbe = (binding == null) ? null : binding.CreateBindingElements().Find<SecurityBindingElement>();
2046 return GetCredentialsHandle(sbe, clientCredentials);
2049 internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, BindingContext context)
2051 ClientCredentials clientCredentials = (context == null) ? null : context.BindingParameters.Find<ClientCredentials>();
2052 return GetCredentialsHandle(sbe, clientCredentials);
2055 internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, ClientCredentials clientCredentials)
2062 bool isSspi = false;
2063 bool isKerberos = false;
2064 foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
2066 if (stp is SecureConversationSecurityTokenParameters)
2068 SafeFreeCredentials result = GetCredentialsHandle(((SecureConversationSecurityTokenParameters)stp).BootstrapSecurityBindingElement, clientCredentials);
2075 else if (stp is IssuedSecurityTokenParameters)
2077 SafeFreeCredentials result = GetCredentialsHandle(((IssuedSecurityTokenParameters)stp).IssuerBinding, clientCredentials);
2084 else if (stp is SspiSecurityTokenParameters)
2089 else if (stp is KerberosSecurityTokenParameters)
2095 if (!isSspi && !isKerberos)
2100 NetworkCredential credential = null;
2101 if (clientCredentials != null)
2103 credential = SecurityUtils.GetNetworkCredentialOrDefault(clientCredentials.Windows.ClientCredential);
2108 return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false);
2110 // if OS is less that Vista cannot use !NTLM, Windows SE 142400
2112 // To disable AllowNtlm warning.
2113 #pragma warning disable 618
2115 else if (clientCredentials != null && !clientCredentials.Windows.AllowNtlm)
2117 if (SecurityUtils.IsOsGreaterThanXP())
2119 return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false, "!NTLM");
2123 return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false);
2127 #pragma warning restore 618
2129 return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false);
2132 internal static byte[] CloneBuffer(byte[] buffer)
2134 byte[] copy = DiagnosticUtility.Utility.AllocateByteArray(buffer.Length);
2135 Buffer.BlockCopy(buffer, 0, copy, 0, buffer.Length);
2139 internal static X509Certificate2 GetCertificateFromStore(StoreName storeName, StoreLocation storeLocation,
2140 X509FindType findType, object findValue, EndpointAddress target)
2142 X509Certificate2 certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, target, true);
2143 if (certificate == null)
2144 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotFindCert, storeName, storeLocation, findType, findValue)));
2149 internal static bool TryGetCertificateFromStore(StoreName storeName, StoreLocation storeLocation,
2150 X509FindType findType, object findValue, EndpointAddress target, out X509Certificate2 certificate)
2152 certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, target, false);
2153 return (certificate != null);
2156 static X509Certificate2 GetCertificateFromStoreCore(StoreName storeName, StoreLocation storeLocation,
2157 X509FindType findType, object findValue, EndpointAddress target, bool throwIfMultipleOrNoMatch)
2159 if (findValue == null)
2161 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("findValue");
2163 X509CertificateStore store = new X509CertificateStore(storeName, storeLocation);
2164 X509Certificate2Collection certs = null;
2167 store.Open(OpenFlags.ReadOnly);
2168 certs = store.Find(findType, findValue, false);
2169 if (certs.Count == 1)
2171 return new X509Certificate2(certs[0]);
2173 if (throwIfMultipleOrNoMatch)
2175 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateCertificateLoadException(
2176 storeName, storeLocation, findType, findValue, target, certs.Count));
2185 SecurityUtils.ResetAllCertificates(certs);
2190 static Exception CreateCertificateLoadException(StoreName storeName, StoreLocation storeLocation,
2191 X509FindType findType, object findValue, EndpointAddress target, int certCount)
2197 return new InvalidOperationException(SR.GetString(SR.CannotFindCert, storeName, storeLocation, findType, findValue));
2201 return new InvalidOperationException(SR.GetString(SR.CannotFindCertForTarget, storeName, storeLocation, findType, findValue, target));
2208 return new InvalidOperationException(SR.GetString(SR.FoundMultipleCerts, storeName, storeLocation, findType, findValue));
2212 return new InvalidOperationException(SR.GetString(SR.FoundMultipleCertsForTarget, storeName, storeLocation, findType, findValue, target));
2217 public static SecurityBindingElement GetIssuerSecurityBindingElement(ServiceModelSecurityTokenRequirement requirement)
2219 SecurityBindingElement bindingElement = requirement.SecureConversationSecurityBindingElement;
2220 if (bindingElement != null)
2222 return bindingElement;
2225 Binding binding = requirement.IssuerBinding;
2226 if (binding == null)
2228 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.IssuerBindingNotPresentInTokenRequirement, requirement));
2230 BindingElementCollection bindingElements = binding.CreateBindingElements();
2231 return bindingElements.Find<SecurityBindingElement>();
2234 public static int GetMaxNegotiationBufferSize(BindingContext bindingContext)
2236 TransportBindingElement transport = bindingContext.RemainingBindingElements.Find<TransportBindingElement>();
2237 Fx.Assert(transport != null, "TransportBindingElement is null!");
2238 int maxNegoMessageSize;
2239 if (transport is ConnectionOrientedTransportBindingElement)
2241 maxNegoMessageSize = ((ConnectionOrientedTransportBindingElement)transport).MaxBufferSize;
2243 else if (transport is HttpTransportBindingElement)
2245 maxNegoMessageSize = ((HttpTransportBindingElement)transport).MaxBufferSize;
2249 maxNegoMessageSize = TransportDefaults.MaxBufferSize;
2251 return maxNegoMessageSize;
2254 public static bool TryCreateKeyFromIntrinsicKeyClause(SecurityKeyIdentifierClause keyIdentifierClause, SecurityTokenResolver resolver, out SecurityKey key)
2257 if (keyIdentifierClause.CanCreateKey)
2259 key = keyIdentifierClause.CreateKey();
2262 if (keyIdentifierClause is EncryptedKeyIdentifierClause)
2264 EncryptedKeyIdentifierClause keyClause = (EncryptedKeyIdentifierClause)keyIdentifierClause;
2265 // PreSharp Bug: Parameter 'keyClause' to this public method must be validated: A null-dereference can occur here.
2266 #pragma warning suppress 56506 // keyClause will not be null due to the if condition above.
2267 for (int i = 0; i < keyClause.EncryptingKeyIdentifier.Count; i++)
2269 SecurityKey unwrappingSecurityKey = null;
2270 if (resolver.TryResolveSecurityKey(keyClause.EncryptingKeyIdentifier[i], out unwrappingSecurityKey))
2272 byte[] wrappedKey = keyClause.GetEncryptedKey();
2273 string wrappingAlgorithm = keyClause.EncryptionMethod;
2274 byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
2275 key = new InMemorySymmetricSecurityKey(unwrappedKey, false);
2283 public static WrappedKeySecurityToken CreateTokenFromEncryptedKeyClause(EncryptedKeyIdentifierClause keyClause, SecurityToken unwrappingToken)
2285 SecurityKeyIdentifier wrappingTokenReference = keyClause.EncryptingKeyIdentifier;
2286 byte[] wrappedKey = keyClause.GetEncryptedKey();
2287 SecurityKey unwrappingSecurityKey = unwrappingToken.SecurityKeys[0];
2288 string wrappingAlgorithm = keyClause.EncryptionMethod;
2289 byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
2290 return new WrappedKeySecurityToken(SecurityUtils.GenerateId(), unwrappedKey, wrappingAlgorithm,
2291 unwrappingToken, wrappingTokenReference, wrappedKey, unwrappingSecurityKey
2295 public static void ValidateAnonymityConstraint(WindowsIdentity identity, bool allowUnauthenticatedCallers)
2297 if (!allowUnauthenticatedCallers && identity.User.IsWellKnown(WellKnownSidType.AnonymousSid))
2299 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(
2300 new SecurityTokenValidationException(SR.GetString(SR.AnonymousLogonsAreNotAllowed)));
2304 static bool ComputeSslCipherStrengthRequirementFlag()
2306 // validate only for XP versions < XP SP3 and windows server versions < Win2K3 SP2
2307 if ((Environment.OSVersion.Version.Major > WindowsServerMajorNumber)
2308 || (Environment.OSVersion.Version.Major == WindowsServerMajorNumber && Environment.OSVersion.Version.Minor > WindowsServerMinorNumber))
2312 // version <= Win2K3
2313 if (Environment.OSVersion.Version.Major == XPMajorNumber && Environment.OSVersion.Version.Minor == XPMinorNumber)
2315 if ((Environment.OSVersion.ServicePack == string.Empty) || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase) || String.Equals(Environment.OSVersion.ServicePack, ServicePack2, StringComparison.OrdinalIgnoreCase))
2321 // the OS is XP SP3 or higher
2325 else if (Environment.OSVersion.Version.Major == WindowsServerMajorNumber && Environment.OSVersion.Version.Minor == WindowsServerMinorNumber)
2327 if (Environment.OSVersion.ServicePack == string.Empty || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase))
2333 // the OS is Win2K3 SP2 or higher
2339 // this is <= XP. We should never get here but if we do validate SSL strength
2344 public static bool ShouldValidateSslCipherStrength()
2346 if (!isSslValidationRequirementDetermined)
2348 shouldValidateSslCipherStrength = ComputeSslCipherStrengthRequirementFlag();
2349 Thread.MemoryBarrier();
2350 isSslValidationRequirementDetermined = true;
2352 return shouldValidateSslCipherStrength;
2355 public static void ValidateSslCipherStrength(int keySizeInBits)
2357 if (ShouldValidateSslCipherStrength() && keySizeInBits < MinimumSslCipherStrength)
2359 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.SslCipherKeyTooSmall, keySizeInBits, MinimumSslCipherStrength)));
2363 public static bool TryCreateX509CertificateFromRawData(byte[] rawData, out X509Certificate2 certificate)
2365 certificate = (rawData == null || rawData.Length == 0) ? null : new X509Certificate2(rawData);
2366 return certificate != null && certificate.Handle != IntPtr.Zero;
2369 internal static string GetKeyDerivationAlgorithm(SecureConversationVersion version)
2371 string derivationAlgorithm = null;
2372 if (version == SecureConversationVersion.WSSecureConversationFeb2005)
2374 derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivation;
2376 else if (version == SecureConversationVersion.WSSecureConversation13)
2378 derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivationDec2005;
2382 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
2385 return derivationAlgorithm;
2390 struct SecurityUniqueId
2392 static long nextId = 0;
2393 static string commonPrefix = "uuid-" + Guid.NewGuid().ToString() + "-";
2399 SecurityUniqueId(string prefix, long id)
2402 this.prefix = prefix;
2406 public static SecurityUniqueId Create()
2408 return SecurityUniqueId.Create(commonPrefix);
2411 public static SecurityUniqueId Create(string prefix)
2413 return new SecurityUniqueId(prefix, Interlocked.Increment(ref nextId));
2420 if (this.val == null)
2421 this.val = this.prefix + this.id.ToString(CultureInfo.InvariantCulture);
2428 static class EmptyReadOnlyCollection<T>
2430 public static ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new List<T>());
2433 class OperationWithTimeoutAsyncResult : TraceAsyncResult
2435 static readonly Action<object> scheduledCallback = new Action<object>(OnScheduled);
2436 TimeoutHelper timeoutHelper;
2437 OperationWithTimeoutCallback operationWithTimeout;
2439 public OperationWithTimeoutAsyncResult(OperationWithTimeoutCallback operationWithTimeout, TimeSpan timeout, AsyncCallback callback, object state)
2440 : base(callback, state)
2442 this.operationWithTimeout = operationWithTimeout;
2443 this.timeoutHelper = new TimeoutHelper(timeout);
2444 ActionItem.Schedule(scheduledCallback, this);
2447 static void OnScheduled(object state)
2449 OperationWithTimeoutAsyncResult thisResult = (OperationWithTimeoutAsyncResult)state;
2450 Exception completionException = null;
2453 using (thisResult.CallbackActivity == null ? null : ServiceModelActivity.BoundOperation(thisResult.CallbackActivity))
2455 thisResult.operationWithTimeout(thisResult.timeoutHelper.RemainingTime());
2458 #pragma warning suppress 56500 // covered by FxCOP
2466 completionException = e;
2468 thisResult.Complete(false, completionException);
2471 public static void End(IAsyncResult result)
2473 AsyncResult.End<OperationWithTimeoutAsyncResult>(result);