1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Security
6 {
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;
17     using System.Net;
18     using System.Net.Security;
19     using System.Runtime;
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;
33     using System.Text;
34     using System.Threading;
35     using System.Xml;
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;
42 
43     static class StoreLocationHelper
44     {
IsDefined(StoreLocation value)45         internal static bool IsDefined(StoreLocation value)
46         {
47             return (value == StoreLocation.CurrentUser
48                 || value == StoreLocation.LocalMachine);
49         }
50     }
51 
52     static class ProtectionLevelHelper
53     {
IsDefined(ProtectionLevel value)54         internal static bool IsDefined(ProtectionLevel value)
55         {
56             return (value == ProtectionLevel.None
57                 || value == ProtectionLevel.Sign
58                 || value == ProtectionLevel.EncryptAndSign);
59         }
60 
Validate(ProtectionLevel value)61         internal static void Validate(ProtectionLevel value)
62         {
63             if (!IsDefined(value))
64             {
65                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
66                     typeof(ProtectionLevel)));
67             }
68         }
69 
IsStronger(ProtectionLevel v1, ProtectionLevel v2)70         internal static bool IsStronger(ProtectionLevel v1, ProtectionLevel v2)
71         {
72             return ((v1 == ProtectionLevel.EncryptAndSign && v2 != ProtectionLevel.EncryptAndSign)
73                     || (v1 == ProtectionLevel.Sign && v2 == ProtectionLevel.None));
74         }
75 
IsStrongerOrEqual(ProtectionLevel v1, ProtectionLevel v2)76         internal static bool IsStrongerOrEqual(ProtectionLevel v1, ProtectionLevel v2)
77         {
78             return (v1 == ProtectionLevel.EncryptAndSign
79                     || (v1 == ProtectionLevel.Sign && v2 != ProtectionLevel.EncryptAndSign));
80         }
81 
Max(ProtectionLevel v1, ProtectionLevel v2)82         internal static ProtectionLevel Max(ProtectionLevel v1, ProtectionLevel v2)
83         {
84             return IsStronger(v1, v2) ? v1 : v2;
85         }
86 
GetOrdinal(Nullable<ProtectionLevel> p)87         internal static int GetOrdinal(Nullable<ProtectionLevel> p)
88         {
89             if (p.HasValue)
90             {
91                 switch ((ProtectionLevel)p)
92                 {
93                     default:
94                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("p", (int)p,
95                         typeof(ProtectionLevel)));
96                     case ProtectionLevel.None:
97                         return 2;
98                     case ProtectionLevel.Sign:
99                         return 3;
100                     case ProtectionLevel.EncryptAndSign:
101                         return 4;
102                 }
103             }
104             else
105                 return 1;
106         }
107     }
108 
109     static class SslProtocolsHelper
110     {
IsDefined(SslProtocols value)111         internal static bool IsDefined(SslProtocols value)
112         {
113             SslProtocols allValues = SslProtocols.None;
114             foreach (var protocol in Enum.GetValues(typeof(SslProtocols)))
115             {
116                 allValues |= (SslProtocols)protocol;
117             }
118             return (value & allValues) == value;
119         }
120 
Validate(SslProtocols value)121         internal static void Validate(SslProtocols value)
122         {
123             if (!IsDefined(value))
124             {
125                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
126                     typeof(SslProtocols)));
127             }
128         }
129     }
130 
131     static class TokenImpersonationLevelHelper
132     {
IsDefined(TokenImpersonationLevel value)133         internal static bool IsDefined(TokenImpersonationLevel value)
134         {
135             return (value == TokenImpersonationLevel.None
136                 || value == TokenImpersonationLevel.Anonymous
137                 || value == TokenImpersonationLevel.Identification
138                 || value == TokenImpersonationLevel.Impersonation
139                 || value == TokenImpersonationLevel.Delegation);
140         }
141 
Validate(TokenImpersonationLevel value)142         internal static void Validate(TokenImpersonationLevel value)
143         {
144             if (!IsDefined(value))
145             {
146                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
147                     typeof(TokenImpersonationLevel)));
148             }
149         }
150 
151         static TokenImpersonationLevel[] TokenImpersonationLevelOrder = new TokenImpersonationLevel[]
152             {
153                 TokenImpersonationLevel.None,
154                 TokenImpersonationLevel.Anonymous,
155                 TokenImpersonationLevel.Identification,
156                 TokenImpersonationLevel.Impersonation,
157                 TokenImpersonationLevel.Delegation
158             };
159 
ToString(TokenImpersonationLevel impersonationLevel)160         internal static string ToString(TokenImpersonationLevel impersonationLevel)
161         {
162             if (impersonationLevel == TokenImpersonationLevel.Identification)
163             {
164                 return "identification";
165             }
166             else if (impersonationLevel == TokenImpersonationLevel.None)
167             {
168                 return "none";
169             }
170             else if (impersonationLevel == TokenImpersonationLevel.Anonymous)
171             {
172                 return "anonymous";
173             }
174             else if (impersonationLevel == TokenImpersonationLevel.Impersonation)
175             {
176                 return "impersonation";
177             }
178             else if (impersonationLevel == TokenImpersonationLevel.Delegation)
179             {
180                 return "delegation";
181             }
182 
183             Fx.Assert("unknown token impersonation level");
184             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("impersonationLevel", (int)impersonationLevel,
185             typeof(TokenImpersonationLevel)));
186         }
187 
IsGreaterOrEqual(TokenImpersonationLevel x, TokenImpersonationLevel y)188         internal static bool IsGreaterOrEqual(TokenImpersonationLevel x, TokenImpersonationLevel y)
189         {
190             TokenImpersonationLevelHelper.Validate(x);
191             TokenImpersonationLevelHelper.Validate(y);
192 
193             if (x == y)
194                 return true;
195 
196             int px = 0;
197             int py = 0;
198             for (int i = 0; i < TokenImpersonationLevelOrder.Length; i++)
199             {
200                 if (x == TokenImpersonationLevelOrder[i])
201                     px = i;
202                 if (y == TokenImpersonationLevelOrder[i])
203                     py = i;
204             }
205 
206             return (px > py);
207         }
208 
Compare(TokenImpersonationLevel x, TokenImpersonationLevel y)209         internal static int Compare(TokenImpersonationLevel x, TokenImpersonationLevel y)
210         {
211             int result = 0;
212 
213             if (x != y)
214             {
215                 switch (x)
216                 {
217                     case TokenImpersonationLevel.Identification:
218                         result = -1;
219                         break;
220                     case TokenImpersonationLevel.Impersonation:
221                         switch (y)
222                         {
223                             case TokenImpersonationLevel.Identification:
224                                 result = 1;
225                                 break;
226                             case TokenImpersonationLevel.Delegation:
227                                 result = -1;
228                                 break;
229                             default:
230                                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("y", (int)y,
231                                     typeof(TokenImpersonationLevel)));
232 
233                         }
234                         break;
235                     case TokenImpersonationLevel.Delegation:
236                         result = 1;
237                         break;
238                     default:
239                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("x", (int)x,
240                             typeof(TokenImpersonationLevel)));
241 
242                 }
243             }
244 
245             return result;
246         }
247     }
248 
249     internal class ServiceModelDictionaryManager
250     {
251         static DictionaryManager dictionaryManager;
252 
253         public static DictionaryManager Instance
254         {
255             get
256             {
257                 if (dictionaryManager == null)
258                     dictionaryManager = new DictionaryManager(BinaryMessageEncoderFactory.XmlDictionary);
259 
260                 return dictionaryManager;
261             }
262         }
263     }
264 
265     static class SecurityUtils
266     {
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;
286 
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
294 
GetChannelBindingFromMessage(Message message)295         public static ChannelBinding GetChannelBindingFromMessage(Message message)
296         {
297             if (message == null)
298             {
299                 return null;
300             }
301 
302             ChannelBindingMessageProperty channelBindingMessageProperty = null;
303             ChannelBindingMessageProperty.TryGet(message, out channelBindingMessageProperty);
304             ChannelBinding channelBinding = null;
305 
306             if (channelBindingMessageProperty != null)
307             {
308                 channelBinding = channelBindingMessageProperty.ChannelBinding;
309             }
310 
311             return channelBinding;
312         }
313 
IsOsGreaterThanXP()314         internal static bool IsOsGreaterThanXP()
315         {
316             return ((Environment.OSVersion.Version.Major >= SecurityUtils.XPMajorNumber && Environment.OSVersion.Version.Minor > SecurityUtils.XPMinorNumber) ||
317                     Environment.OSVersion.Version.Major > SecurityUtils.XPMajorNumber);
318         }
319 
IsOSGreaterThanOrEqualToWin7()320         internal static bool IsOSGreaterThanOrEqualToWin7()
321         {
322             Version windows7Version = new Version(6, 1, 0, 0);
323             return (Environment.OSVersion.Version.Major >= windows7Version.Major && Environment.OSVersion.Version.Minor >= windows7Version.Minor);
324         }
325 
IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew)326         internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew)
327         {
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;
331 
332             return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime());
333         }
334 
335         internal static X509SecurityTokenAuthenticator NonValidatingX509Authenticator
336         {
337             get
338             {
339                 if (nonValidatingX509Authenticator == null)
340                 {
341                     nonValidatingX509Authenticator = new X509SecurityTokenAuthenticator(X509CertificateValidator.None);
342                 }
343                 return nonValidatingX509Authenticator;
344             }
345         }
346 
347         public static SecurityIdentifier AdministratorsSid
348         {
349             get
350             {
351                 if (administratorsSid == null)
352                     administratorsSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
353                 return administratorsSid;
354             }
355         }
356 
357         internal static IIdentity AnonymousIdentity
358         {
359             get
360             {
361                 if (anonymousIdentity == null)
362                 {
363                     anonymousIdentity = SecurityUtils.CreateIdentity(String.Empty);
364                 }
365                 return anonymousIdentity;
366             }
367         }
368 
369         public static DateTime MaxUtcDateTime
370         {
371             get
372             {
373                 // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
374                 return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc);
375             }
376         }
377 
378         public static DateTime MinUtcDateTime
379         {
380             get
381             {
382                 // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
383                 return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc);
384             }
385         }
386 
CreateIdentity(string name, string authenticationType)387         internal static IIdentity CreateIdentity(string name, string authenticationType)
388         {
389             return new GenericIdentity(name, authenticationType);
390         }
391 
CreateIdentity(string name)392         internal static IIdentity CreateIdentity(string name)
393         {
394             return new GenericIdentity(name);
395         }
396 
CreateWindowsIdentity()397         internal static EndpointIdentity CreateWindowsIdentity()
398         {
399             return CreateWindowsIdentity(false);
400         }
401 
CreateWindowsIdentity(NetworkCredential serverCredential)402         internal static EndpointIdentity CreateWindowsIdentity(NetworkCredential serverCredential)
403         {
404             if (serverCredential != null && !NetworkCredentialHelper.IsDefault(serverCredential))
405             {
406                 string upn;
407                 if (serverCredential.Domain != null && serverCredential.Domain.Length > 0)
408                 {
409                     upn = serverCredential.UserName + "@" + serverCredential.Domain;
410                 }
411                 else
412                 {
413                     upn = serverCredential.UserName;
414                 }
415                 return EndpointIdentity.CreateUpnIdentity(upn);
416             }
417             else
418             {
419                 return SecurityUtils.CreateWindowsIdentity();
420             }
421         }
422 
IsSystemAccount(WindowsIdentity self)423         static bool IsSystemAccount(WindowsIdentity self)
424         {
425             SecurityIdentifier sid = self.User;
426             if (sid == null)
427             {
428                 return false;
429             }
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));
435         }
436 
CreateWindowsIdentity(bool spnOnly)437         internal static EndpointIdentity CreateWindowsIdentity(bool spnOnly)
438         {
439             EndpointIdentity identity = null;
440             using (WindowsIdentity self = WindowsIdentity.GetCurrent())
441             {
442                 bool isSystemAccount = IsSystemAccount(self);
443                 if (spnOnly || isSystemAccount)
444                 {
445                     identity = EndpointIdentity.CreateSpnIdentity(String.Format(CultureInfo.InvariantCulture, "host/{0}", DnsCache.MachineName));
446                 }
447                 else
448                 {
449                     // Save windowsIdentity for delay lookup
450                     identity = new UpnEndpointIdentity(CloneWindowsIdentityIfNecessary(self));
451                 }
452             }
453 
454             return identity;
455         }
456 
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]
CloneWindowsIdentityIfNecessary(WindowsIdentity wid)460         internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid)
461         {
462             return SecurityUtils.CloneWindowsIdentityIfNecessary(wid, null);
463         }
464 
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]
CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authType)468         internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authType)
469         {
470             if (wid != null)
471             {
472                 IntPtr token = UnsafeGetWindowsIdentityToken(wid);
473                 if (token != IntPtr.Zero)
474                 {
475                     return UnsafeCreateWindowsIdentityFromToken(token, authType);
476                 }
477             }
478             return wid;
479         }
480 
481         [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")]
482         [SecurityCritical]
483         [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
UnsafeGetWindowsIdentityToken(WindowsIdentity wid)484         static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid)
485         {
486             return wid.Token;
487         }
488 
489         [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the SecurityIdentifier of the current user as a string, caller must protect return value.")]
490         [SecurityCritical]
491         [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
UnsafeGetCurrentUserSidAsString()492         static string UnsafeGetCurrentUserSidAsString()
493         {
494             using (WindowsIdentity self = WindowsIdentity.GetCurrent())
495             {
496                 return self.User.Value;
497             }
498         }
499 
500         [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")]
501         [SecurityCritical]
502         [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)]
UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authType)503         static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authType)
504         {
505             if (authType != null)
506                 return new WindowsIdentity(token, authType);
507             else
508                 return new WindowsIdentity(token);
509         }
510 
AllowsImpersonation(WindowsIdentity windowsIdentity, TokenImpersonationLevel impersonationLevel)511         internal static bool AllowsImpersonation(WindowsIdentity windowsIdentity, TokenImpersonationLevel impersonationLevel)
512         {
513             if (windowsIdentity == null)
514                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("windowsIdentity");
515 
516             TokenImpersonationLevelHelper.Validate(impersonationLevel);
517 
518             if (impersonationLevel == TokenImpersonationLevel.Identification)
519                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("impersonationLevel"));
520 
521             bool result = true;
522 
523             switch (windowsIdentity.ImpersonationLevel)
524             {
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)
531                         result = false;
532                     break;
533                 case TokenImpersonationLevel.Delegation:
534                     break;
535                 default:
536                     result = false;
537                     break;
538             }
539 
540             return result;
541         }
542 
543         internal static byte[] CombinedHashLabel
544         {
545             get
546             {
547                 if (combinedHashLabel == null)
548                     combinedHashLabel = Encoding.UTF8.GetBytes(TrustApr2004Strings.CombinedHashLabel);
549                 return combinedHashLabel;
550             }
551         }
552 
553         internal static T GetSecurityKey<T>(SecurityToken token)
554             where T : SecurityKey
555         {
556             T result = null;
557             if (token.SecurityKeys != null)
558             {
559                 for (int i = 0; i < token.SecurityKeys.Count; ++i)
560                 {
561                     T temp = (token.SecurityKeys[i] as T);
562                     if (temp != null)
563                     {
564                         if (result != null)
565                         {
566                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.MultipleMatchingCryptosFound, typeof(T).ToString())));
567                         }
568                         else
569                         {
570                             result = temp;
571                         }
572                     }
573                 }
574             }
575             return result;
576         }
577 
HasSymmetricSecurityKey(SecurityToken token)578         internal static bool HasSymmetricSecurityKey(SecurityToken token)
579         {
580             return GetSecurityKey<SymmetricSecurityKey>(token) != null;
581         }
582 
EnsureExpectedSymmetricMatch(SecurityToken t1, SecurityToken t2, Message message)583         internal static void EnsureExpectedSymmetricMatch(SecurityToken t1, SecurityToken t2, Message message)
584         {
585             // nulls are not mismatches
586             if (t1 == null || t2 == null || ReferenceEquals(t1, t2))
587             {
588                 return;
589             }
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()))
594             {
595                 throw System.ServiceModel.Diagnostics.TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenNotExpectedInSecurityHeader, t2)), message);
596             }
597         }
598 
GetSymmetricAlgorithm(string algorithm, SecurityToken token)599         internal static SymmetricAlgorithm GetSymmetricAlgorithm(string algorithm, SecurityToken token)
600         {
601             SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(token);
602             if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm))
603             {
604                 return securityKey.GetSymmetricAlgorithm(algorithm);
605             }
606             else
607             {
608                 return null;
609             }
610         }
611 
GetKeyedHashAlgorithm(string algorithm, SecurityToken token)612         internal static KeyedHashAlgorithm GetKeyedHashAlgorithm(string algorithm, SecurityToken token)
613         {
614             SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(token);
615             if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm))
616             {
617                 return securityKey.GetKeyedHashAlgorithm(algorithm);
618             }
619             else
620             {
621                 return null;
622             }
623         }
624 
CreateSymmetricSecurityKeys(byte[] key)625         internal static ReadOnlyCollection<SecurityKey> CreateSymmetricSecurityKeys(byte[] key)
626         {
627             List<SecurityKey> temp = new List<SecurityKey>(1);
628             temp.Add(new InMemorySymmetricSecurityKey(key));
629             return temp.AsReadOnly();
630         }
631 
DecryptKey(SecurityToken unwrappingToken, string encryptionMethod, byte[] wrappedKey, out SecurityKey unwrappingSecurityKey)632         internal static byte[] DecryptKey(SecurityToken unwrappingToken, string encryptionMethod, byte[] wrappedKey, out SecurityKey unwrappingSecurityKey)
633         {
634             unwrappingSecurityKey = null;
635             if (unwrappingToken.SecurityKeys != null)
636             {
637                 for (int i = 0; i < unwrappingToken.SecurityKeys.Count; ++i)
638                 {
639                     if (unwrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod))
640                     {
641                         unwrappingSecurityKey = unwrappingToken.SecurityKeys[i];
642                         break;
643                     }
644                 }
645             }
646             if (unwrappingSecurityKey == null)
647             {
648                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod)));
649             }
650             return unwrappingSecurityKey.DecryptKey(encryptionMethod, wrappedKey);
651         }
652 
EncryptKey(SecurityToken wrappingToken, string encryptionMethod, byte[] keyToWrap)653         internal static byte[] EncryptKey(SecurityToken wrappingToken, string encryptionMethod, byte[] keyToWrap)
654         {
655             SecurityKey wrappingSecurityKey = null;
656             if (wrappingToken.SecurityKeys != null)
657             {
658                 for (int i = 0; i < wrappingToken.SecurityKeys.Count; ++i)
659                 {
660                     if (wrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod))
661                     {
662                         wrappingSecurityKey = wrappingToken.SecurityKeys[i];
663                         break;
664                     }
665                 }
666             }
667             if (wrappingSecurityKey == null)
668             {
669                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod));
670             }
671             return wrappingSecurityKey.EncryptKey(encryptionMethod, keyToWrap);
672         }
673 
ReadContentAsBase64(XmlDictionaryReader reader, long maxBufferSize)674         internal static byte[] ReadContentAsBase64(XmlDictionaryReader reader, long maxBufferSize)
675         {
676             if (reader == null)
677                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
678 
679             // Code cloned from System.Xml.XmlDictionaryReder.
680             byte[][] buffers = new byte[32][];
681             byte[] buffer;
682             // Its best to read in buffers that are a multiple of 3 so we don't break base64 boundaries when converting text
683             int count = 384;
684             int bufferCount = 0;
685             int totalRead = 0;
686             while (true)
687             {
688                 buffer = new byte[count];
689                 buffers[bufferCount++] = buffer;
690                 int read = 0;
691                 while (read < buffer.Length)
692                 {
693                     int actual = reader.ReadContentAsBase64(buffer, read, buffer.Length - read);
694                     if (actual == 0)
695                         break;
696                     read += actual;
697                 }
698                 if (totalRead > maxBufferSize - read)
699                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(SR.GetString(SR.BufferQuotaExceededReadingBase64, maxBufferSize)));
700                 totalRead += read;
701                 if (read < buffer.Length)
702                     break;
703                 count = count * 2;
704             }
705             buffer = new byte[totalRead];
706             int offset = 0;
707             for (int i = 0; i < bufferCount - 1; i++)
708             {
709                 Buffer.BlockCopy(buffers[i], 0, buffer, offset, buffers[i].Length);
710                 offset += buffers[i].Length;
711             }
712             Buffer.BlockCopy(buffers[bufferCount - 1], 0, buffer, offset, totalRead - offset);
713             return buffer;
714         }
715 
GenerateDerivedKey(SecurityToken tokenToDerive, string derivationAlgorithm, byte[] label, byte[] nonce, int keySize, int offset)716         internal static byte[] GenerateDerivedKey(SecurityToken tokenToDerive, string derivationAlgorithm, byte[] label, byte[] nonce,
717             int keySize, int offset)
718         {
719             SymmetricSecurityKey symmetricSecurityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(tokenToDerive);
720             if (symmetricSecurityKey == null || !symmetricSecurityKey.IsSupportedAlgorithm(derivationAlgorithm))
721             {
722                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, derivationAlgorithm)));
723             }
724             return symmetricSecurityKey.GenerateDerivedKey(derivationAlgorithm, label, nonce, keySize, offset);
725         }
726 
GetSpnFromIdentity(EndpointIdentity identity, EndpointAddress target)727         internal static string GetSpnFromIdentity(EndpointIdentity identity, EndpointAddress target)
728         {
729             bool foundSpn = false;
730             string spn = null;
731             if (identity != null)
732             {
733                 if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
734                 {
735                     spn = (string)identity.IdentityClaim.Resource;
736                     foundSpn = true;
737                 }
738                 else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
739                 {
740                     spn = (string)identity.IdentityClaim.Resource;
741                     foundSpn = true;
742                 }
743                 else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
744                 {
745                     spn = String.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource);
746                     foundSpn = true;
747                 }
748             }
749             if (!foundSpn)
750             {
751                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.CannotDetermineSPNBasedOnAddress, target)));
752             }
753             return spn;
754         }
755 
GetSpnFromTarget(EndpointAddress target)756         internal static string GetSpnFromTarget(EndpointAddress target)
757         {
758             if (target == null)
759             {
760                 throw Fx.AssertAndThrow("target should not be null - expecting an EndpointAddress");
761             }
762 
763             return string.Format(CultureInfo.InvariantCulture, "host/{0}", target.Uri.DnsSafeHost);
764         }
765 
IsSupportedAlgorithm(string algorithm, SecurityToken token)766         internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token)
767         {
768             if (token.SecurityKeys == null)
769             {
770                 return false;
771             }
772             for (int i = 0; i < token.SecurityKeys.Count; ++i)
773             {
774                 if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm))
775                 {
776                     return true;
777                 }
778             }
779             return false;
780         }
781 
GetPrimaryIdentityClaim(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)782         internal static Claim GetPrimaryIdentityClaim(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
783         {
784             return GetPrimaryIdentityClaim(AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies));
785         }
786 
GetPrimaryIdentityClaim(AuthorizationContext authContext)787         internal static Claim GetPrimaryIdentityClaim(AuthorizationContext authContext)
788         {
789             if (authContext != null)
790             {
791                 for (int i = 0; i < authContext.ClaimSets.Count; ++i)
792                 {
793                     ClaimSet claimSet = authContext.ClaimSets[i];
794                     foreach (Claim claim in claimSet.FindClaims(null, Rights.Identity))
795                     {
796                         return claim;
797                     }
798                 }
799             }
800             return null;
801         }
802 
GetServiceAddressAndViaHash(EndpointAddress sr)803         internal static int GetServiceAddressAndViaHash(EndpointAddress sr)
804         {
805             if (sr == null)
806             {
807                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sr");
808             }
809             return sr.GetHashCode();
810         }
811 
GenerateId()812         internal static string GenerateId()
813         {
814             return SecurityUniqueId.Create().Value;
815         }
816 
GenerateIdWithPrefix(string prefix)817         internal static string GenerateIdWithPrefix(string prefix)
818         {
819             return SecurityUniqueId.Create(prefix).Value;
820         }
821 
GenerateUniqueId()822         internal static UniqueId GenerateUniqueId()
823         {
824             return new UniqueId();
825         }
826 
GetPrimaryDomain()827         internal static string GetPrimaryDomain()
828         {
829             using (WindowsIdentity wid = WindowsIdentity.GetCurrent())
830             {
831                 return GetPrimaryDomain(IsSystemAccount(wid));
832             }
833         }
834 
GetPrimaryDomain(bool isSystemAccount)835         internal static string GetPrimaryDomain(bool isSystemAccount)
836         {
837             if (computedDomain == false)
838             {
839                 try
840                 {
841                     if (isSystemAccount)
842                     {
843                         currentDomain = Domain.GetComputerDomain().Name;
844                     }
845                     else
846                     {
847                         currentDomain = Domain.GetCurrentDomain().Name;
848                     }
849                 }
850 #pragma warning suppress 56500 // covered by FxCOP
851                 catch (Exception e)
852                 {
853                     if (Fx.IsFatal(e))
854                     {
855                         throw;
856                     }
857                     DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
858                 }
859                 finally
860                 {
861                     computedDomain = true;
862                 }
863             }
864             return currentDomain;
865         }
866 
EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate)867         internal static void EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate)
868         {
869             if (certificate == null)
870             {
871                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
872             }
873             bool canDoKeyExchange = false;
874             Exception innerException = null;
875             if (certificate.HasPrivateKey)
876             {
877                 try
878                 {
879                     canDoKeyExchange = CanKeyDoKeyExchange(certificate);
880                 }
881                 // exceptions can be due to ACLs on the key etc
882                 catch (System.Security.SecurityException e)
883                 {
884                     innerException = e;
885                 }
886                 catch (CryptographicException e)
887                 {
888                     innerException = e;
889                 }
890             }
891             if (!canDoKeyExchange)
892             {
893                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SslCertMayNotDoKeyExchange, certificate.SubjectName.Name), innerException));
894             }
895         }
896 
897         [Fx.Tag.SecurityNote(Critical = "Calls critical method GetKeyContainerInfo.",
898             Safe = "Info is not leaked.")]
899         [SecuritySafeCritical]
CanKeyDoKeyExchange(X509Certificate2 certificate)900         static bool CanKeyDoKeyExchange(X509Certificate2 certificate)
901         {
902             bool canDoKeyExchange = false;
903 
904             if (!LocalAppContextSwitches.DisableCngCertificates)
905             {
906                 X509KeyUsageExtension keyUsageExtension = null;
907                 for (int i = 0; i < certificate.Extensions.Count; i++)
908                 {
909                     keyUsageExtension = certificate.Extensions[i] as X509KeyUsageExtension;
910                     if (keyUsageExtension != null)
911                     {
912                         break;
913                     }
914                 }
915 
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)
921                 {
922                     return true;
923                 }
924 
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;
932             }
933 
934             if (!canDoKeyExchange)
935             {
936                 CspKeyContainerInfo info = GetKeyContainerInfo(certificate);
937                 canDoKeyExchange = info != null && info.KeyNumber == KeyNumber.Exchange;
938             }
939 
940             return canDoKeyExchange;
941         }
942 
943         [Fx.Tag.SecurityNote(Critical = "Elevates to call properties: X509Certificate2.PrivateKey and CspKeyContainerInfo. Caller must protect the return value.")]
944         [SecurityCritical]
945         [KeyContainerPermission(SecurityAction.Assert, Flags = KeyContainerPermissionFlags.Open)]
GetKeyContainerInfo(X509Certificate2 certificate)946         static CspKeyContainerInfo GetKeyContainerInfo(X509Certificate2 certificate)
947         {
948             RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider;
949             if (rsa != null)
950             {
951                 return rsa.CspKeyContainerInfo;
952             }
953 
954             return null;
955         }
956 
GetCertificateId(X509Certificate2 certificate)957         internal static string GetCertificateId(X509Certificate2 certificate)
958         {
959             StringBuilder str = new StringBuilder(256);
960             AppendCertificateIdentityName(str, certificate);
961             return str.ToString();
962         }
963 
CreatePrincipalNameAuthorizationPolicies(string principalName)964         internal static ReadOnlyCollection<IAuthorizationPolicy> CreatePrincipalNameAuthorizationPolicies(string principalName)
965         {
966             if (principalName == null)
967                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("principalName");
968 
969             Claim identityClaim;
970             Claim primaryPrincipal;
971             if (principalName.Contains("@") || principalName.Contains(@"\"))
972             {
973                 identityClaim = new Claim(ClaimTypes.Upn, principalName, Rights.Identity);
974                 primaryPrincipal = Claim.CreateUpnClaim(principalName);
975             }
976             else
977             {
978                 identityClaim = new Claim(ClaimTypes.Spn, principalName, Rights.Identity);
979                 primaryPrincipal = Claim.CreateSpnClaim(principalName);
980             }
981 
982             List<Claim> claims = new List<Claim>(2);
983             claims.Add(identityClaim);
984             claims.Add(primaryPrincipal);
985 
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();
989         }
990 
GetIdentityNamesFromPolicies(IList<IAuthorizationPolicy> authPolicies)991         internal static string GetIdentityNamesFromPolicies(IList<IAuthorizationPolicy> authPolicies)
992         {
993             return GetIdentityNamesFromContext(AuthorizationContext.CreateDefaultAuthorizationContext(authPolicies));
994         }
995 
GetIdentityNamesFromContext(AuthorizationContext authContext)996         internal static string GetIdentityNamesFromContext(AuthorizationContext authContext)
997         {
998             if (authContext == null)
999                 return String.Empty;
1000 
1001             StringBuilder str = new StringBuilder(256);
1002             for (int i = 0; i < authContext.ClaimSets.Count; ++i)
1003             {
1004                 ClaimSet claimSet = authContext.ClaimSets[i];
1005 
1006                 // Windows
1007                 WindowsClaimSet windows = claimSet as WindowsClaimSet;
1008                 if (windows != null)
1009                 {
1010                     if (str.Length > 0)
1011                         str.Append(", ");
1012 
1013                     AppendIdentityName(str, windows.WindowsIdentity);
1014                 }
1015                 else
1016                 {
1017                     // X509
1018                     X509CertificateClaimSet x509 = claimSet as X509CertificateClaimSet;
1019                     if (x509 != null)
1020                     {
1021                         if (str.Length > 0)
1022                             str.Append(", ");
1023 
1024                         AppendCertificateIdentityName(str, x509.X509Certificate);
1025                     }
1026                 }
1027             }
1028 
1029             if (str.Length <= 0)
1030             {
1031                 List<IIdentity> identities = null;
1032                 object obj;
1033                 if (authContext.Properties.TryGetValue(SecurityUtils.Identities, out obj))
1034                 {
1035                     identities = obj as List<IIdentity>;
1036                 }
1037                 if (identities != null)
1038                 {
1039                     for (int i = 0; i < identities.Count; ++i)
1040                     {
1041                         IIdentity identity = identities[i];
1042                         if (identity != null)
1043                         {
1044                             if (str.Length > 0)
1045                                 str.Append(", ");
1046 
1047                             AppendIdentityName(str, identity);
1048                         }
1049                     }
1050                 }
1051             }
1052             return str.Length <= 0 ? String.Empty : str.ToString();
1053         }
1054 
AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate)1055         internal static void AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate)
1056         {
1057             string value = certificate.SubjectName.Name;
1058             if (String.IsNullOrEmpty(value))
1059             {
1060                 value = certificate.GetNameInfo(X509NameType.DnsName, false);
1061                 if (String.IsNullOrEmpty(value))
1062                 {
1063                     value = certificate.GetNameInfo(X509NameType.SimpleName, false);
1064                     if (String.IsNullOrEmpty(value))
1065                     {
1066                         value = certificate.GetNameInfo(X509NameType.EmailName, false);
1067                         if (String.IsNullOrEmpty(value))
1068                         {
1069                             value = certificate.GetNameInfo(X509NameType.UpnName, false);
1070                         }
1071                     }
1072                 }
1073             }
1074             // Same format as X509Identity
1075             str.Append(String.IsNullOrEmpty(value) ? "<x509>" : value);
1076             str.Append("; ");
1077             str.Append(certificate.Thumbprint);
1078         }
1079 
AppendIdentityName(StringBuilder str, IIdentity identity)1080         internal static void AppendIdentityName(StringBuilder str, IIdentity identity)
1081         {
1082             string name = null;
1083             try
1084             {
1085                 name = identity.Name;
1086             }
1087 #pragma warning suppress 56500
1088             catch (Exception e)
1089             {
1090                 if (Fx.IsFatal(e))
1091                 {
1092                     throw;
1093                 }
1094                 // suppress exception, this is just info.
1095             }
1096 
1097             str.Append(String.IsNullOrEmpty(name) ? "<null>" : name);
1098 
1099             WindowsIdentity windows = identity as WindowsIdentity;
1100             if (windows != null)
1101             {
1102                 if (windows.User != null)
1103                 {
1104                     str.Append("; ");
1105                     str.Append(windows.User.ToString());
1106                 }
1107             }
1108             else
1109             {
1110                 WindowsSidIdentity sid = identity as WindowsSidIdentity;
1111                 if (sid != null)
1112                 {
1113                     str.Append("; ");
1114                     str.Append(sid.SecurityIdentifier.ToString());
1115                 }
1116             }
1117         }
1118 
1119         [Fx.Tag.SecurityNote(Critical = "Calls critical methods UnsafeGetDomain, UnsafeGetUserName, UnsafeGetPassword and UnsafeGetCurrentUserSidAsString.")]
1120         [SecurityCritical]
AppendWindowsAuthenticationInfo(string inputString, NetworkCredential credential, AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel)1121         internal static string AppendWindowsAuthenticationInfo(string inputString, NetworkCredential credential,
1122             AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel)
1123         {
1124             const string delimiter = "\0"; // nonprintable characters are invalid for SSPI Domain/UserName/Password
1125 
1126             if (IsDefaultNetworkCredential(credential))
1127             {
1128                 string sid = UnsafeGetCurrentUserSidAsString();
1129                 return string.Concat(inputString, delimiter,
1130                     sid, delimiter,
1131                     AuthenticationLevelHelper.ToString(authenticationLevel), delimiter,
1132                     TokenImpersonationLevelHelper.ToString(impersonationLevel));
1133             }
1134             else
1135             {
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));
1142             }
1143         }
1144 
GetIdentityName(IIdentity identity)1145         internal static string GetIdentityName(IIdentity identity)
1146         {
1147             StringBuilder str = new StringBuilder(256);
1148             AppendIdentityName(str, identity);
1149             return str.ToString();
1150         }
1151 
1152         /// <SecurityNote>
1153         /// Critical - Calls an UnsafeNativeMethod and a Critical method (GetFipsAlgorithmPolicyKeyFromRegistry)
1154         /// Safe - processes the return and just returns a bool, which is safe
1155         /// </SecurityNote>
1156         internal static bool IsChannelBindingDisabled
1157         {
1158             [SecuritySafeCritical]
1159             get
1160             {
1161                 return ((GetSuppressChannelBindingValue() & 0x1) != 0);
1162             }
1163         }
1164 
1165         const string suppressChannelBindingRegistryKey = @"System\CurrentControlSet\Control\Lsa";
1166 
1167         /// <SecurityNote>
1168         /// Critical - Asserts to get a value from the registry
1169         /// </SecurityNote>
1170         [SecurityCritical]
1171         [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + suppressChannelBindingRegistryKey)]
GetSuppressChannelBindingValue()1172         internal static int GetSuppressChannelBindingValue()
1173         {
1174             int channelBindingPolicyKeyValue = 0;
1175 
1176             try
1177             {
1178                 using (RegistryKey channelBindingPolicyKey = Registry.LocalMachine.OpenSubKey(suppressChannelBindingRegistryKey, false))
1179                 {
1180                     if (channelBindingPolicyKey != null)
1181                     {
1182                         object data = channelBindingPolicyKey.GetValue("SuppressChannelBindingInfo");
1183                         if (data != null)
1184                             channelBindingPolicyKeyValue = (int)data;
1185                     }
1186                 }
1187             }
1188 #pragma warning suppress 56500
1189             catch (Exception e)
1190             {
1191                 if (Fx.IsFatal(e))
1192                     throw;
1193             }
1194 
1195             return channelBindingPolicyKeyValue;
1196         }
1197 
IsSecurityBindingSuitableForChannelBinding(TransportSecurityBindingElement securityBindingElement)1198         internal static bool IsSecurityBindingSuitableForChannelBinding(TransportSecurityBindingElement securityBindingElement)
1199         {
1200             if (securityBindingElement == null)
1201             {
1202                 return false;
1203             }
1204 
1205             // channel binding of OperationSupportingTokenParameters, OptionalEndpointSupportingTokenParameters, or OptionalOperationSupportingTokenParameters
1206             // is not supported in Win7
1207             if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Endorsing))
1208             {
1209                 return true;
1210             }
1211 
1212             if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Signed))
1213             {
1214                 return true;
1215             }
1216 
1217             if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted))
1218             {
1219                 return true;
1220             }
1221 
1222             if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEndorsing))
1223             {
1224                 return true;
1225             }
1226 
1227             return false;
1228         }
1229 
AreSecurityTokenParametersSuitableForChannelBinding(Collection<SecurityTokenParameters> tokenParameters)1230         internal static bool AreSecurityTokenParametersSuitableForChannelBinding(Collection<SecurityTokenParameters> tokenParameters)
1231         {
1232             if (tokenParameters == null)
1233             {
1234                 return false;
1235             }
1236 
1237             foreach (SecurityTokenParameters stp in tokenParameters)
1238             {
1239                 if (stp is SspiSecurityTokenParameters || stp is KerberosSecurityTokenParameters)
1240                 {
1241                     return true;
1242                 }
1243 
1244                 SecureConversationSecurityTokenParameters scstp = stp as SecureConversationSecurityTokenParameters;
1245                 if (scstp != null)
1246                 {
1247                     return IsSecurityBindingSuitableForChannelBinding(scstp.BootstrapSecurityBindingElement as TransportSecurityBindingElement);
1248                 }
1249             }
1250 
1251             return false;
1252         }
1253 
ThrowIfNegotiationFault(Message message, EndpointAddress target)1254         internal static void ThrowIfNegotiationFault(Message message, EndpointAddress target)
1255         {
1256             if (message.IsFault)
1257             {
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)
1261                 {
1262                     FaultCode subCode = fault.Code.SubCode;
1263                     if (subCode.Name == DotNetSecurityStrings.SecurityServerTooBusyFault && subCode.Namespace == DotNetSecurityStrings.Namespace)
1264                     {
1265                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ServerTooBusyException(SR.GetString(SR.SecurityServerTooBusy, target), faultException));
1266                     }
1267                     else if (subCode.Name == AddressingStrings.EndpointUnavailable && subCode.Namespace == message.Version.Addressing.Namespace)
1268                     {
1269                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR.GetString(SR.SecurityEndpointNotFound, target), faultException));
1270                     }
1271                 }
1272                 throw TraceUtility.ThrowHelperError(faultException, message);
1273             }
1274         }
1275 
IsSecurityFault(MessageFault fault, SecurityStandardsManager standardsManager)1276         internal static bool IsSecurityFault(MessageFault fault, SecurityStandardsManager standardsManager)
1277         {
1278             if (fault.Code.IsSenderFault)
1279             {
1280                 FaultCode subCode = fault.Code.SubCode;
1281                 if (subCode != null)
1282                 {
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);
1287                 }
1288             }
1289             return false;
1290         }
1291 
CreateSecurityFaultException(Message unverifiedMessage)1292         internal static Exception CreateSecurityFaultException(Message unverifiedMessage)
1293         {
1294             MessageFault fault = MessageFault.CreateFault(unverifiedMessage, TransportDefaults.MaxSecurityFaultSize);
1295             return CreateSecurityFaultException(fault);
1296         }
1297 
CreateSecurityFaultException(MessageFault fault)1298         internal static Exception CreateSecurityFaultException(MessageFault fault)
1299         {
1300             FaultException faultException = FaultException.CreateFault(fault, typeof(string), typeof(object));
1301             return new MessageSecurityException(SR.GetString(SR.UnsecuredMessageFaultReceived), faultException);
1302         }
1303 
CreateSecurityContextNotFoundFault(SecurityStandardsManager standardsManager, string action)1304         internal static MessageFault CreateSecurityContextNotFoundFault(SecurityStandardsManager standardsManager, string action)
1305         {
1306             SecureConversationDriver scDriver = standardsManager.SecureConversationDriver;
1307             FaultCode subCode = new FaultCode(scDriver.BadContextTokenFaultCode.Value, scDriver.Namespace.Value);
1308             FaultReason reason;
1309             if (action != null)
1310             {
1311                 reason = new FaultReason(SR.GetString(SR.BadContextTokenOrActionFaultReason, action), CultureInfo.CurrentCulture);
1312             }
1313             else
1314             {
1315                 reason = new FaultReason(SR.GetString(SR.BadContextTokenFaultReason), CultureInfo.CurrentCulture);
1316             }
1317             FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
1318             return MessageFault.CreateFault(senderCode, reason);
1319         }
1320 
CreateSecurityMessageFault(Exception e, SecurityStandardsManager standardsManager)1321         internal static MessageFault CreateSecurityMessageFault(Exception e, SecurityStandardsManager standardsManager)
1322         {
1323             bool isSecurityError = false;
1324             bool isTokenValidationError = false;
1325             bool isGenericTokenError = false;
1326             FaultException faultException = null;
1327             while (e != null)
1328             {
1329                 if (e is SecurityTokenValidationException)
1330                 {
1331                     if (e is SecurityContextTokenValidationException)
1332                     {
1333                         return CreateSecurityContextNotFoundFault(SecurityStandardsManager.DefaultInstance, null);
1334                     }
1335                     isSecurityError = true;
1336                     isTokenValidationError = true;
1337                     break;
1338                 }
1339                 else if (e is SecurityTokenException)
1340                 {
1341                     isSecurityError = true;
1342                     isGenericTokenError = true;
1343                     break;
1344                 }
1345                 else if (e is MessageSecurityException)
1346                 {
1347                     MessageSecurityException ms = (MessageSecurityException)e;
1348                     if (ms.Fault != null)
1349                     {
1350                         return ms.Fault;
1351                     }
1352                     isSecurityError = true;
1353                 }
1354                 else if (e is FaultException)
1355                 {
1356                     faultException = (FaultException)e;
1357                     break;
1358                 }
1359                 e = e.InnerException;
1360             }
1361             if (!isSecurityError && faultException == null)
1362             {
1363                 return null;
1364             }
1365             FaultCode subCode;
1366             FaultReason reason;
1367             SecurityVersion wss = standardsManager.SecurityVersion;
1368             if (isTokenValidationError)
1369             {
1370                 subCode = new FaultCode(wss.FailedAuthenticationFaultCode.Value, wss.HeaderNamespace.Value);
1371                 reason = new FaultReason(SR.GetString(SR.FailedAuthenticationFaultReason), CultureInfo.CurrentCulture);
1372             }
1373             else if (isGenericTokenError)
1374             {
1375                 subCode = new FaultCode(wss.InvalidSecurityTokenFaultCode.Value, wss.HeaderNamespace.Value);
1376                 reason = new FaultReason(SR.GetString(SR.InvalidSecurityTokenFaultReason), CultureInfo.CurrentCulture);
1377             }
1378             else if (faultException != null)
1379             {
1380                 // Only support Code and Reason.  No detail or action customization.
1381                 return MessageFault.CreateFault(faultException.Code, faultException.Reason);
1382             }
1383             else
1384             {
1385                 subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value);
1386                 reason = new FaultReason(SR.GetString(SR.InvalidSecurityFaultReason), CultureInfo.CurrentCulture);
1387             }
1388             FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
1389             return MessageFault.CreateFault(senderCode, reason);
1390         }
1391 
IsCompositeDuplexBinding(BindingContext context)1392         internal static bool IsCompositeDuplexBinding(BindingContext context)
1393         {
1394             return ((context.Binding.Elements.Find<CompositeDuplexBindingElement>() != null)
1395                     || (context.Binding.Elements.Find<InternalDuplexBindingElement>() != null));
1396         }
1397 
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.
ErasePasswordInUsernameTokenIfPresent(SecurityMessageProperty messageProperty)1401         internal static void ErasePasswordInUsernameTokenIfPresent(SecurityMessageProperty messageProperty)
1402         {
1403             if (messageProperty == null)
1404             {
1405                 // Nothing to fix.
1406                 return;
1407             }
1408 
1409             if (messageProperty.TransportToken != null)
1410             {
1411                 UserNameSecurityToken token = messageProperty.TransportToken.SecurityToken as UserNameSecurityToken;
1412                 if ((token != null) && !messageProperty.TransportToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1413                 {
1414                     messageProperty.TransportToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.TransportToken.SecurityTokenPolicies);
1415                 }
1416             }
1417 
1418             if (messageProperty.ProtectionToken != null)
1419             {
1420                 UserNameSecurityToken token = messageProperty.ProtectionToken.SecurityToken as UserNameSecurityToken;
1421                 if ((token != null) && !messageProperty.ProtectionToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1422                 {
1423                     messageProperty.ProtectionToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.ProtectionToken.SecurityTokenPolicies);
1424                 }
1425             }
1426 
1427             if (messageProperty.HasIncomingSupportingTokens)
1428             {
1429                 for (int i = 0; i < messageProperty.IncomingSupportingTokens.Count; ++i)
1430                 {
1431                     SupportingTokenSpecification supportingTokenSpecification = messageProperty.IncomingSupportingTokens[i];
1432                     UserNameSecurityToken token = supportingTokenSpecification.SecurityToken as UserNameSecurityToken;
1433                     if ((token != null) && !supportingTokenSpecification.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken)))
1434                     {
1435                         messageProperty.IncomingSupportingTokens[i] = new SupportingTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), supportingTokenSpecification.SecurityTokenPolicies, supportingTokenSpecification.SecurityTokenAttachmentMode, supportingTokenSpecification.SecurityTokenParameters);
1436                     }
1437                 }
1438             }
1439         }
1440 
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]
FixNetworkCredential(ref NetworkCredential credential)1445         internal static void FixNetworkCredential(ref NetworkCredential credential)
1446         {
1447             if (credential == null)
1448             {
1449                 return;
1450             }
1451             string username = NetworkCredentialHelper.UnsafeGetUsername(credential);
1452             string domain = NetworkCredentialHelper.UnsafeGetDomain(credential);
1453             if (!string.IsNullOrEmpty(username) && string.IsNullOrEmpty(domain))
1454             {
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)
1459                 {
1460                     if (!string.IsNullOrEmpty(partsWithSlashDelimiter[0]) && !string.IsNullOrEmpty(partsWithSlashDelimiter[1]))
1461                     {
1462                         credential = new NetworkCredential(partsWithSlashDelimiter[1], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithSlashDelimiter[0]);
1463                     }
1464                 }
1465                 else if (partsWithSlashDelimiter.Length == 1 && partsWithAtDelimiter.Length == 2)
1466                 {
1467                     if (!string.IsNullOrEmpty(partsWithAtDelimiter[0]) && !string.IsNullOrEmpty(partsWithAtDelimiter[1]))
1468                     {
1469                         credential = new NetworkCredential(partsWithAtDelimiter[0], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithAtDelimiter[1]);
1470                     }
1471                 }
1472             }
1473         }
1474 
1475         // WORKAROUND, Microsoft, VSWhidbey 561276: The first NetworkCredential must be created in a lock.
PrepareNetworkCredential()1476         internal static void PrepareNetworkCredential()
1477         {
1478             if (dummyNetworkCredential == null)
1479             {
1480                 PrepareNetworkCredentialWorker();
1481             }
1482         }
1483 
1484         // Since this takes a lock, it probably won't be inlined, but the typical case will be.
PrepareNetworkCredentialWorker()1485         static void PrepareNetworkCredentialWorker()
1486         {
1487             lock (dummyNetworkCredentialLock)
1488             {
1489                 dummyNetworkCredential = new NetworkCredential("dummy", "dummy");
1490             }
1491         }
1492 
1493         // This is the workaround, Since store.Certificates returns a full collection
1494         // of certs in store.  These are holding native resources.
ResetAllCertificates(X509Certificate2Collection certificates)1495         internal static void ResetAllCertificates(X509Certificate2Collection certificates)
1496         {
1497             if (certificates != null)
1498             {
1499                 for (int i = 0; i < certificates.Count; ++i)
1500                 {
1501                     ResetCertificate(certificates[i]);
1502                 }
1503             }
1504         }
1505 
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]
ResetCertificate(X509Certificate2 certificate)1509         internal static void ResetCertificate(X509Certificate2 certificate)
1510         {
1511             certificate.Reset();
1512         }
1513 
IsDefaultNetworkCredential(NetworkCredential credential)1514         internal static bool IsDefaultNetworkCredential(NetworkCredential credential)
1515         {
1516             return NetworkCredentialHelper.IsDefault(credential);
1517         }
1518 
OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)1519         internal static void OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
1520         {
1521             OpenCommunicationObject(tokenProvider as ICommunicationObject, timeout);
1522         }
1523 
BeginOpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout, AsyncCallback callback, object state)1524         internal static IAsyncResult BeginOpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout,
1525             AsyncCallback callback, object state)
1526         {
1527             return new OpenCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state);
1528         }
1529 
EndOpenTokenProviderIfRequired(IAsyncResult result)1530         internal static void EndOpenTokenProviderIfRequired(IAsyncResult result)
1531         {
1532             OpenCommunicationObjectAsyncResult.End(result);
1533         }
1534 
BeginCloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout, AsyncCallback callback, object state)1535         internal static IAsyncResult BeginCloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout,
1536             AsyncCallback callback, object state)
1537         {
1538             return new CloseCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state);
1539         }
1540 
EndCloseTokenProviderIfRequired(IAsyncResult result)1541         internal static void EndCloseTokenProviderIfRequired(IAsyncResult result)
1542         {
1543             CloseCommunicationObjectAsyncResult.End(result);
1544         }
1545 
CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)1546         internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
1547         {
1548             CloseCommunicationObject(tokenProvider, false, timeout);
1549         }
1550 
CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, bool aborted, TimeSpan timeout)1551         internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, bool aborted, TimeSpan timeout)
1552         {
1553             CloseCommunicationObject(tokenProvider, aborted, timeout);
1554         }
1555 
AbortTokenProviderIfRequired(SecurityTokenProvider tokenProvider)1556         internal static void AbortTokenProviderIfRequired(SecurityTokenProvider tokenProvider)
1557         {
1558             CloseCommunicationObject(tokenProvider, true, TimeSpan.Zero);
1559         }
1560 
OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)1561         internal static void OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)
1562         {
1563             OpenCommunicationObject(tokenAuthenticator as ICommunicationObject, timeout);
1564         }
1565 
CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)1566         internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout)
1567         {
1568             CloseTokenAuthenticatorIfRequired(tokenAuthenticator, false, timeout);
1569         }
1570 
CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, bool aborted, TimeSpan timeout)1571         internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, bool aborted, TimeSpan timeout)
1572         {
1573             CloseCommunicationObject(tokenAuthenticator, aborted, timeout);
1574         }
1575 
BeginOpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout, AsyncCallback callback, object state)1576         internal static IAsyncResult BeginOpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout,
1577             AsyncCallback callback, object state)
1578         {
1579             return new OpenCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state);
1580         }
1581 
EndOpenTokenAuthenticatorIfRequired(IAsyncResult result)1582         internal static void EndOpenTokenAuthenticatorIfRequired(IAsyncResult result)
1583         {
1584             OpenCommunicationObjectAsyncResult.End(result);
1585         }
1586 
BeginCloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout, AsyncCallback callback, object state)1587         internal static IAsyncResult BeginCloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout,
1588             AsyncCallback callback, object state)
1589         {
1590             return new CloseCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state);
1591         }
1592 
EndCloseTokenAuthenticatorIfRequired(IAsyncResult result)1593         internal static void EndCloseTokenAuthenticatorIfRequired(IAsyncResult result)
1594         {
1595             CloseCommunicationObjectAsyncResult.End(result);
1596         }
1597 
AbortTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator)1598         internal static void AbortTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator)
1599         {
1600             CloseCommunicationObject(tokenAuthenticator, true, TimeSpan.Zero);
1601         }
1602 
OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout)1603         static void OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout)
1604         {
1605             if (obj != null)
1606                 obj.Open(timeout);
1607         }
1608 
CloseCommunicationObject(Object obj, bool aborted, TimeSpan timeout)1609         static void CloseCommunicationObject(Object obj, bool aborted, TimeSpan timeout)
1610         {
1611             if (obj != null)
1612             {
1613                 ICommunicationObject co = obj as ICommunicationObject;
1614                 if (co != null)
1615                 {
1616                     if (aborted)
1617                     {
1618                         try
1619                         {
1620                             co.Abort();
1621                         }
1622                         catch (CommunicationException e)
1623                         {
1624                             DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
1625                         }
1626                     }
1627                     else
1628                     {
1629                         co.Close(timeout);
1630                     }
1631                 }
1632                 else if (obj is IDisposable)
1633                 {
1634                     ((IDisposable)obj).Dispose();
1635                 }
1636             }
1637         }
1638 
1639         class OpenCommunicationObjectAsyncResult : AsyncResult
1640         {
1641             ICommunicationObject communicationObject;
1642             static AsyncCallback onOpen;
1643 
OpenCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)1644             public OpenCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)
1645                 : base(callback, state)
1646             {
1647                 this.communicationObject = obj as ICommunicationObject;
1648 
1649                 bool completeSelf = false;
1650                 if (this.communicationObject == null)
1651                 {
1652                     completeSelf = true;
1653                 }
1654                 else
1655                 {
1656                     if (onOpen == null)
1657                     {
1658                         onOpen = Fx.ThunkCallback(new AsyncCallback(OnOpen));
1659                     }
1660 
1661                     IAsyncResult result = this.communicationObject.BeginOpen(timeout, onOpen, this);
1662                     if (result.CompletedSynchronously)
1663                     {
1664                         this.communicationObject.EndOpen(result);
1665                         completeSelf = true;
1666                     }
1667                 }
1668 
1669                 if (completeSelf)
1670                 {
1671                     base.Complete(true);
1672                 }
1673             }
1674 
End(IAsyncResult result)1675             public static void End(IAsyncResult result)
1676             {
1677                 AsyncResult.End<OpenCommunicationObjectAsyncResult>(result);
1678             }
1679 
OnOpen(IAsyncResult result)1680             static void OnOpen(IAsyncResult result)
1681             {
1682                 if (result.CompletedSynchronously)
1683                 {
1684                     return;
1685                 }
1686 
1687                 OpenCommunicationObjectAsyncResult thisPtr =
1688                     (OpenCommunicationObjectAsyncResult)result.AsyncState;
1689 
1690                 Exception completionException = null;
1691                 try
1692                 {
1693                     thisPtr.communicationObject.EndOpen(result);
1694                 }
1695 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1696                 catch (Exception e)
1697                 {
1698                     if (Fx.IsFatal(e))
1699                     {
1700                         throw;
1701                     }
1702 
1703                     completionException = e;
1704                 }
1705                 thisPtr.Complete(false, completionException);
1706             }
1707         }
1708 
1709         class CloseCommunicationObjectAsyncResult : AsyncResult
1710         {
1711             ICommunicationObject communicationObject;
1712             static AsyncCallback onClose;
1713 
CloseCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)1714             public CloseCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state)
1715                 : base(callback, state)
1716             {
1717                 this.communicationObject = obj as ICommunicationObject;
1718 
1719                 bool completeSelf = false;
1720                 if (this.communicationObject == null)
1721                 {
1722                     IDisposable disposable = obj as IDisposable;
1723                     if (disposable != null)
1724                     {
1725                         disposable.Dispose();
1726                     }
1727                     completeSelf = true;
1728                 }
1729                 else
1730                 {
1731                     if (onClose == null)
1732                     {
1733                         onClose = Fx.ThunkCallback(new AsyncCallback(OnClose));
1734                     }
1735 
1736                     IAsyncResult result = this.communicationObject.BeginClose(timeout, onClose, this);
1737                     if (result.CompletedSynchronously)
1738                     {
1739                         this.communicationObject.EndClose(result);
1740                         completeSelf = true;
1741                     }
1742                 }
1743 
1744                 if (completeSelf)
1745                 {
1746                     base.Complete(true);
1747                 }
1748             }
1749 
End(IAsyncResult result)1750             public static void End(IAsyncResult result)
1751             {
1752                 AsyncResult.End<CloseCommunicationObjectAsyncResult>(result);
1753             }
1754 
OnClose(IAsyncResult result)1755             static void OnClose(IAsyncResult result)
1756             {
1757                 if (result.CompletedSynchronously)
1758                 {
1759                     return;
1760                 }
1761 
1762                 CloseCommunicationObjectAsyncResult thisPtr =
1763                     (CloseCommunicationObjectAsyncResult)result.AsyncState;
1764 
1765                 Exception completionException = null;
1766                 try
1767                 {
1768                     thisPtr.communicationObject.EndClose(result);
1769                 }
1770 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1771                 catch (Exception e)
1772                 {
1773                     if (Fx.IsFatal(e))
1774                     {
1775                         throw;
1776                     }
1777 
1778                     completionException = e;
1779                 }
1780                 thisPtr.Complete(false, completionException);
1781             }
1782         }
1783 
MatchRstWithEndpointFilter(Message rst, IMessageFilterTable<EndpointAddress> endpointFilterTable, Uri listenUri)1784         internal static void MatchRstWithEndpointFilter(Message rst, IMessageFilterTable<EndpointAddress> endpointFilterTable, Uri listenUri)
1785         {
1786             if (endpointFilterTable == null)
1787             {
1788                 return;
1789             }
1790             Collection<EndpointAddress> result = new Collection<EndpointAddress>();
1791             if (!endpointFilterTable.GetMatchingValues(rst, result))
1792             {
1793                 throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.RequestSecurityTokenDoesNotMatchEndpointFilters, listenUri)), rst);
1794             }
1795         }
1796 
1797         // match the RST with the endpoint filters in case there is at least 1 asymmetric signature in the message
ShouldMatchRstWithEndpointFilter(SecurityBindingElement sbe)1798         internal static bool ShouldMatchRstWithEndpointFilter(SecurityBindingElement sbe)
1799         {
1800             foreach (SecurityTokenParameters parameters in new SecurityTokenParametersEnumerable(sbe, true))
1801             {
1802                 if (parameters.HasAsymmetricKey)
1803                 {
1804                     return true;
1805                 }
1806             }
1807             return false;
1808         }
1809 
CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenManager tokenManager)1810         internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenManager tokenManager)
1811         {
1812             SecurityTokenSerializer tokenSerializer = tokenManager.CreateSecurityTokenSerializer(securityVersion.SecurityTokenVersion);
1813             return new SecurityStandardsManager(securityVersion, tokenSerializer);
1814         }
1815 
CreateSecurityStandardsManager(SecurityTokenRequirement requirement, SecurityTokenManager tokenManager)1816         internal static SecurityStandardsManager CreateSecurityStandardsManager(SecurityTokenRequirement requirement, SecurityTokenManager tokenManager)
1817         {
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);
1831             else
1832                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
1833         }
1834 
CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenSerializer securityTokenSerializer)1835         internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenSerializer securityTokenSerializer)
1836         {
1837             if (securityVersion == null)
1838             {
1839                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("securityVersion"));
1840             }
1841             if (securityTokenSerializer == null)
1842             {
1843                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenSerializer");
1844             }
1845             return new SecurityStandardsManager(securityVersion, securityTokenSerializer);
1846         }
1847 
TryCreateIdentity(ClaimSet claimSet, string claimType, out EndpointIdentity identity)1848         static bool TryCreateIdentity(ClaimSet claimSet, string claimType, out EndpointIdentity identity)
1849         {
1850             identity = null;
1851             foreach (Claim claim in claimSet.FindClaims(claimType, null))
1852             {
1853                 identity = EndpointIdentity.CreateIdentity(claim);
1854                 return true;
1855             }
1856             return false;
1857         }
1858 
GetServiceCertificateIdentity(X509Certificate2 certificate)1859         internal static EndpointIdentity GetServiceCertificateIdentity(X509Certificate2 certificate)
1860         {
1861             using (X509CertificateClaimSet claimSet = new X509CertificateClaimSet(certificate))
1862             {
1863                 EndpointIdentity identity;
1864                 if (!TryCreateIdentity(claimSet, ClaimTypes.Dns, out identity))
1865                 {
1866                     TryCreateIdentity(claimSet, ClaimTypes.Rsa, out identity);
1867                 }
1868                 return identity;
1869             }
1870         }
1871 
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]
GetNetworkCredentialsCopy(NetworkCredential networkCredential)1875         internal static NetworkCredential GetNetworkCredentialsCopy(NetworkCredential networkCredential)
1876         {
1877             NetworkCredential result;
1878             if (networkCredential != null && !NetworkCredentialHelper.IsDefault(networkCredential))
1879             {
1880                 result = new NetworkCredential(NetworkCredentialHelper.UnsafeGetUsername(networkCredential), NetworkCredentialHelper.UnsafeGetPassword(networkCredential), NetworkCredentialHelper.UnsafeGetDomain(networkCredential));
1881             }
1882             else
1883             {
1884                 result = networkCredential;
1885             }
1886             return result;
1887         }
1888 
GetNetworkCredentialOrDefault(NetworkCredential credential)1889         internal static NetworkCredential GetNetworkCredentialOrDefault(NetworkCredential credential)
1890         {
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))
1894             {
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;
1899             }
1900             else
1901             {
1902                 return credential;
1903             }
1904         }
1905 
CanReadPrivateKey(X509Certificate2 certificate)1906         public static bool CanReadPrivateKey(X509Certificate2 certificate)
1907         {
1908             if (!certificate.HasPrivateKey)
1909                 return false;
1910 
1911             try
1912             {
1913                 // CNG key, CNG permissions tests
1914                 using (RSA rsa = CngLightup.GetRSAPrivateKey(certificate))
1915                 {
1916                     if (rsa != null)
1917                     {
1918                         return true;
1919                     }
1920                 }
1921 
1922                 using (DSA dsa = CngLightup.GetDSAPrivateKey(certificate))
1923                 {
1924                     if (dsa != null)
1925                     {
1926                         return true;
1927                     }
1928                 }
1929 
1930                 using (ECDsa ecdsa = CngLightup.GetECDsaPrivateKey(certificate))
1931                 {
1932                     if (ecdsa != null)
1933                     {
1934                         return true;
1935                     }
1936                 }
1937 
1938                 // CAPI key, CAPI permissions test
1939                 if (certificate.PrivateKey != null)
1940                 {
1941                     return true;
1942                 }
1943 
1944                 return false;
1945             }
1946             catch (CryptographicException)
1947             {
1948                 return false;
1949             }
1950         }
1951 
1952         static class NetworkCredentialHelper
1953         {
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]
IsNullOrEmpty(NetworkCredential credential)1957             static internal bool IsNullOrEmpty(NetworkCredential credential)
1958             {
1959                 return credential == null ||
1960                         (
1961                             String.IsNullOrEmpty(UnsafeGetUsername(credential)) &&
1962                             String.IsNullOrEmpty(UnsafeGetDomain(credential)) &&
1963                             String.IsNullOrEmpty(UnsafeGetPassword(credential))
1964                         );
1965             }
1966 
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]
IsDefault(NetworkCredential credential)1970             static internal bool IsDefault(NetworkCredential credential)
1971             {
1972                 return UnsafeGetDefaultNetworkCredentials().Equals(credential);
1973             }
1974 
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.")]
1978             [SecurityCritical]
1979             [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")]
UnsafeGetUsername(NetworkCredential credential)1980             static internal string UnsafeGetUsername(NetworkCredential credential)
1981             {
1982                 return credential.UserName;
1983             }
1984 
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.")]
1988             [SecurityCritical]
1989             [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
UnsafeGetPassword(NetworkCredential credential)1990             static internal string UnsafeGetPassword(NetworkCredential credential)
1991             {
1992                 return credential.Password;
1993             }
1994 
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.")]
1998             [SecurityCritical]
1999             [EnvironmentPermission(SecurityAction.Assert, Read = "USERDOMAIN")]
UnsafeGetDomain(NetworkCredential credential)2000             static internal string UnsafeGetDomain(NetworkCredential credential)
2001             {
2002                 return credential.Domain;
2003             }
2004 
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.")]
2008             [SecurityCritical]
2009             [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")]
UnsafeGetDefaultNetworkCredentials()2010             static NetworkCredential UnsafeGetDefaultNetworkCredentials()
2011             {
2012                 return CredentialCache.DefaultNetworkCredentials;
2013             }
2014         }
2015 
GetCredentialsHandle(string package, NetworkCredential credential, bool isServer, params string[] additionalPackages)2016         internal static SafeFreeCredentials GetCredentialsHandle(string package, NetworkCredential credential, bool isServer, params string[] additionalPackages)
2017         {
2018             SafeFreeCredentials credentialsHandle;
2019             CredentialUse credentialUse = isServer ? CredentialUse.Inbound : CredentialUse.Outbound;
2020             if (credential == null || NetworkCredentialHelper.IsDefault(credential))
2021             {
2022                 AuthIdentityEx authIdentity = new AuthIdentityEx(null, null, null, additionalPackages);
2023                 credentialsHandle = SspiWrapper.AcquireCredentialsHandle(package, credentialUse, ref authIdentity);
2024             }
2025             else
2026             {
2027                 SecurityUtils.FixNetworkCredential(ref credential);
2028 
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);
2033             }
2034             return credentialsHandle;
2035         }
2036 
GetCredentialsHandle(Binding binding, KeyedByTypeCollection<IEndpointBehavior> behaviors)2037         internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, KeyedByTypeCollection<IEndpointBehavior> behaviors)
2038         {
2039             ClientCredentials clientCredentials = (behaviors == null) ? null : behaviors.Find<ClientCredentials>();
2040             return GetCredentialsHandle(binding, clientCredentials);
2041         }
2042 
GetCredentialsHandle(Binding binding, ClientCredentials clientCredentials)2043         internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, ClientCredentials clientCredentials)
2044         {
2045             SecurityBindingElement sbe = (binding == null) ? null : binding.CreateBindingElements().Find<SecurityBindingElement>();
2046             return GetCredentialsHandle(sbe, clientCredentials);
2047         }
2048 
GetCredentialsHandle(SecurityBindingElement sbe, BindingContext context)2049         internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, BindingContext context)
2050         {
2051             ClientCredentials clientCredentials = (context == null) ? null : context.BindingParameters.Find<ClientCredentials>();
2052             return GetCredentialsHandle(sbe, clientCredentials);
2053         }
2054 
GetCredentialsHandle(SecurityBindingElement sbe, ClientCredentials clientCredentials)2055         internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, ClientCredentials clientCredentials)
2056         {
2057             if (sbe == null)
2058             {
2059                 return null;
2060             }
2061 
2062             bool isSspi = false;
2063             bool isKerberos = false;
2064             foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
2065             {
2066                 if (stp is SecureConversationSecurityTokenParameters)
2067                 {
2068                     SafeFreeCredentials result = GetCredentialsHandle(((SecureConversationSecurityTokenParameters)stp).BootstrapSecurityBindingElement, clientCredentials);
2069                     if (result != null)
2070                     {
2071                         return result;
2072                     }
2073                     continue;
2074                 }
2075                 else if (stp is IssuedSecurityTokenParameters)
2076                 {
2077                     SafeFreeCredentials result = GetCredentialsHandle(((IssuedSecurityTokenParameters)stp).IssuerBinding, clientCredentials);
2078                     if (result != null)
2079                     {
2080                         return result;
2081                     }
2082                     continue;
2083                 }
2084                 else if (stp is SspiSecurityTokenParameters)
2085                 {
2086                     isSspi = true;
2087                     break;
2088                 }
2089                 else if (stp is KerberosSecurityTokenParameters)
2090                 {
2091                     isKerberos = true;
2092                     break;
2093                 }
2094             }
2095             if (!isSspi && !isKerberos)
2096             {
2097                 return null;
2098             }
2099 
2100             NetworkCredential credential = null;
2101             if (clientCredentials != null)
2102             {
2103                 credential = SecurityUtils.GetNetworkCredentialOrDefault(clientCredentials.Windows.ClientCredential);
2104             }
2105 
2106             if (isKerberos)
2107             {
2108                 return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false);
2109             }
2110             // if OS is less that Vista cannot use !NTLM, Windows SE 142400
2111 
2112 // To disable AllowNtlm warning.
2113 #pragma warning disable 618
2114 
2115             else if (clientCredentials != null && !clientCredentials.Windows.AllowNtlm)
2116             {
2117                 if (SecurityUtils.IsOsGreaterThanXP())
2118                 {
2119                     return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false, "!NTLM");
2120                 }
2121                 else
2122                 {
2123                     return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false);
2124                 }
2125             }
2126 
2127 #pragma warning restore 618
2128 
2129             return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false);
2130         }
2131 
CloneBuffer(byte[] buffer)2132         internal static byte[] CloneBuffer(byte[] buffer)
2133         {
2134             byte[] copy = DiagnosticUtility.Utility.AllocateByteArray(buffer.Length);
2135             Buffer.BlockCopy(buffer, 0, copy, 0, buffer.Length);
2136             return copy;
2137         }
2138 
GetCertificateFromStore(StoreName storeName, StoreLocation storeLocation, X509FindType findType, object findValue, EndpointAddress target)2139         internal static X509Certificate2 GetCertificateFromStore(StoreName storeName, StoreLocation storeLocation,
2140             X509FindType findType, object findValue, EndpointAddress target)
2141         {
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)));
2145 
2146             return certificate;
2147         }
2148 
TryGetCertificateFromStore(StoreName storeName, StoreLocation storeLocation, X509FindType findType, object findValue, EndpointAddress target, out X509Certificate2 certificate)2149         internal static bool TryGetCertificateFromStore(StoreName storeName, StoreLocation storeLocation,
2150             X509FindType findType, object findValue, EndpointAddress target, out X509Certificate2 certificate)
2151         {
2152             certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, target, false);
2153             return (certificate != null);
2154         }
2155 
GetCertificateFromStoreCore(StoreName storeName, StoreLocation storeLocation, X509FindType findType, object findValue, EndpointAddress target, bool throwIfMultipleOrNoMatch)2156         static X509Certificate2 GetCertificateFromStoreCore(StoreName storeName, StoreLocation storeLocation,
2157             X509FindType findType, object findValue, EndpointAddress target, bool throwIfMultipleOrNoMatch)
2158         {
2159             if (findValue == null)
2160             {
2161                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("findValue");
2162             }
2163             X509CertificateStore store = new X509CertificateStore(storeName, storeLocation);
2164             X509Certificate2Collection certs = null;
2165             try
2166             {
2167                 store.Open(OpenFlags.ReadOnly);
2168                 certs = store.Find(findType, findValue, false);
2169                 if (certs.Count == 1)
2170                 {
2171                     return new X509Certificate2(certs[0]);
2172                 }
2173                 if (throwIfMultipleOrNoMatch)
2174                 {
2175                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateCertificateLoadException(
2176                         storeName, storeLocation, findType, findValue, target, certs.Count));
2177                 }
2178                 else
2179                 {
2180                     return null;
2181                 }
2182             }
2183             finally
2184             {
2185                 SecurityUtils.ResetAllCertificates(certs);
2186                 store.Close();
2187             }
2188         }
2189 
CreateCertificateLoadException(StoreName storeName, StoreLocation storeLocation, X509FindType findType, object findValue, EndpointAddress target, int certCount)2190         static Exception CreateCertificateLoadException(StoreName storeName, StoreLocation storeLocation,
2191             X509FindType findType, object findValue, EndpointAddress target, int certCount)
2192         {
2193             if (certCount == 0)
2194             {
2195                 if (target == null)
2196                 {
2197                     return new InvalidOperationException(SR.GetString(SR.CannotFindCert, storeName, storeLocation, findType, findValue));
2198                 }
2199                 else
2200                 {
2201                     return new InvalidOperationException(SR.GetString(SR.CannotFindCertForTarget, storeName, storeLocation, findType, findValue, target));
2202                 }
2203             }
2204             else
2205             {
2206                 if (target == null)
2207                 {
2208                     return new InvalidOperationException(SR.GetString(SR.FoundMultipleCerts, storeName, storeLocation, findType, findValue));
2209                 }
2210                 else
2211                 {
2212                     return new InvalidOperationException(SR.GetString(SR.FoundMultipleCertsForTarget, storeName, storeLocation, findType, findValue, target));
2213                 }
2214             }
2215         }
2216 
GetIssuerSecurityBindingElement(ServiceModelSecurityTokenRequirement requirement)2217         public static SecurityBindingElement GetIssuerSecurityBindingElement(ServiceModelSecurityTokenRequirement requirement)
2218         {
2219             SecurityBindingElement bindingElement = requirement.SecureConversationSecurityBindingElement;
2220             if (bindingElement != null)
2221             {
2222                 return bindingElement;
2223             }
2224 
2225             Binding binding = requirement.IssuerBinding;
2226             if (binding == null)
2227             {
2228                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.IssuerBindingNotPresentInTokenRequirement, requirement));
2229             }
2230             BindingElementCollection bindingElements = binding.CreateBindingElements();
2231             return bindingElements.Find<SecurityBindingElement>();
2232         }
2233 
GetMaxNegotiationBufferSize(BindingContext bindingContext)2234         public static int GetMaxNegotiationBufferSize(BindingContext bindingContext)
2235         {
2236             TransportBindingElement transport = bindingContext.RemainingBindingElements.Find<TransportBindingElement>();
2237             Fx.Assert(transport != null, "TransportBindingElement is null!");
2238             int maxNegoMessageSize;
2239             if (transport is ConnectionOrientedTransportBindingElement)
2240             {
2241                 maxNegoMessageSize = ((ConnectionOrientedTransportBindingElement)transport).MaxBufferSize;
2242             }
2243             else if (transport is HttpTransportBindingElement)
2244             {
2245                 maxNegoMessageSize = ((HttpTransportBindingElement)transport).MaxBufferSize;
2246             }
2247             else
2248             {
2249                 maxNegoMessageSize = TransportDefaults.MaxBufferSize;
2250             }
2251             return maxNegoMessageSize;
2252         }
2253 
TryCreateKeyFromIntrinsicKeyClause(SecurityKeyIdentifierClause keyIdentifierClause, SecurityTokenResolver resolver, out SecurityKey key)2254         public static bool TryCreateKeyFromIntrinsicKeyClause(SecurityKeyIdentifierClause keyIdentifierClause, SecurityTokenResolver resolver, out SecurityKey key)
2255         {
2256             key = null;
2257             if (keyIdentifierClause.CanCreateKey)
2258             {
2259                 key = keyIdentifierClause.CreateKey();
2260                 return true;
2261             }
2262             if (keyIdentifierClause is EncryptedKeyIdentifierClause)
2263             {
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++)
2268                 {
2269                     SecurityKey unwrappingSecurityKey = null;
2270                     if (resolver.TryResolveSecurityKey(keyClause.EncryptingKeyIdentifier[i], out unwrappingSecurityKey))
2271                     {
2272                         byte[] wrappedKey = keyClause.GetEncryptedKey();
2273                         string wrappingAlgorithm = keyClause.EncryptionMethod;
2274                         byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
2275                         key = new InMemorySymmetricSecurityKey(unwrappedKey, false);
2276                         return true;
2277                     }
2278                 }
2279             }
2280             return false;
2281         }
2282 
CreateTokenFromEncryptedKeyClause(EncryptedKeyIdentifierClause keyClause, SecurityToken unwrappingToken)2283         public static WrappedKeySecurityToken CreateTokenFromEncryptedKeyClause(EncryptedKeyIdentifierClause keyClause, SecurityToken unwrappingToken)
2284         {
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
2292                     );
2293         }
2294 
ValidateAnonymityConstraint(WindowsIdentity identity, bool allowUnauthenticatedCallers)2295         public static void ValidateAnonymityConstraint(WindowsIdentity identity, bool allowUnauthenticatedCallers)
2296         {
2297             if (!allowUnauthenticatedCallers && identity.User.IsWellKnown(WellKnownSidType.AnonymousSid))
2298             {
2299                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(
2300                     new SecurityTokenValidationException(SR.GetString(SR.AnonymousLogonsAreNotAllowed)));
2301             }
2302         }
2303 
ComputeSslCipherStrengthRequirementFlag()2304         static bool ComputeSslCipherStrengthRequirementFlag()
2305         {
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))
2309             {
2310                 return false;
2311             }
2312             // version <= Win2K3
2313             if (Environment.OSVersion.Version.Major == XPMajorNumber && Environment.OSVersion.Version.Minor == XPMinorNumber)
2314             {
2315                 if ((Environment.OSVersion.ServicePack == string.Empty) || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase) || String.Equals(Environment.OSVersion.ServicePack, ServicePack2, StringComparison.OrdinalIgnoreCase))
2316                 {
2317                     return true;
2318                 }
2319                 else
2320                 {
2321                     // the OS is XP SP3 or higher
2322                     return false;
2323                 }
2324             }
2325             else if (Environment.OSVersion.Version.Major == WindowsServerMajorNumber && Environment.OSVersion.Version.Minor == WindowsServerMinorNumber)
2326             {
2327                 if (Environment.OSVersion.ServicePack == string.Empty || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase))
2328                 {
2329                     return true;
2330                 }
2331                 else
2332                 {
2333                     // the OS is Win2K3 SP2 or higher
2334                     return false;
2335                 }
2336             }
2337             else
2338             {
2339                 // this is <= XP. We should never get here but if we do validate SSL strength
2340                 return true;
2341             }
2342         }
2343 
ShouldValidateSslCipherStrength()2344         public static bool ShouldValidateSslCipherStrength()
2345         {
2346             if (!isSslValidationRequirementDetermined)
2347             {
2348                 shouldValidateSslCipherStrength = ComputeSslCipherStrengthRequirementFlag();
2349                 Thread.MemoryBarrier();
2350                 isSslValidationRequirementDetermined = true;
2351             }
2352             return shouldValidateSslCipherStrength;
2353         }
2354 
ValidateSslCipherStrength(int keySizeInBits)2355         public static void ValidateSslCipherStrength(int keySizeInBits)
2356         {
2357             if (ShouldValidateSslCipherStrength() && keySizeInBits < MinimumSslCipherStrength)
2358             {
2359                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.SslCipherKeyTooSmall, keySizeInBits, MinimumSslCipherStrength)));
2360             }
2361         }
2362 
TryCreateX509CertificateFromRawData(byte[] rawData, out X509Certificate2 certificate)2363         public static bool TryCreateX509CertificateFromRawData(byte[] rawData, out X509Certificate2 certificate)
2364         {
2365             certificate = (rawData == null || rawData.Length == 0) ? null : new X509Certificate2(rawData);
2366             return certificate != null && certificate.Handle != IntPtr.Zero;
2367         }
2368 
GetKeyDerivationAlgorithm(SecureConversationVersion version)2369         internal static string GetKeyDerivationAlgorithm(SecureConversationVersion version)
2370         {
2371             string derivationAlgorithm = null;
2372             if (version == SecureConversationVersion.WSSecureConversationFeb2005)
2373             {
2374                 derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivation;
2375             }
2376             else if (version == SecureConversationVersion.WSSecureConversation13)
2377             {
2378                 derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivationDec2005;
2379             }
2380             else
2381             {
2382                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
2383             }
2384 
2385             return derivationAlgorithm;
2386         }
2387 
2388     }
2389 
2390     struct SecurityUniqueId
2391     {
2392         static long nextId = 0;
2393         static string commonPrefix = "uuid-" + Guid.NewGuid().ToString() + "-";
2394 
2395         long id;
2396         string prefix;
2397         string val;
2398 
SecurityUniqueIdSystem.ServiceModel.Security.SecurityUniqueId2399         SecurityUniqueId(string prefix, long id)
2400         {
2401             this.id = id;
2402             this.prefix = prefix;
2403             this.val = null;
2404         }
2405 
CreateSystem.ServiceModel.Security.SecurityUniqueId2406         public static SecurityUniqueId Create()
2407         {
2408             return SecurityUniqueId.Create(commonPrefix);
2409         }
2410 
CreateSystem.ServiceModel.Security.SecurityUniqueId2411         public static SecurityUniqueId Create(string prefix)
2412         {
2413             return new SecurityUniqueId(prefix, Interlocked.Increment(ref nextId));
2414         }
2415 
2416         public string Value
2417         {
2418             get
2419             {
2420                 if (this.val == null)
2421                     this.val = this.prefix + this.id.ToString(CultureInfo.InvariantCulture);
2422 
2423                 return this.val;
2424             }
2425         }
2426     }
2427 
2428     static class EmptyReadOnlyCollection<T>
2429     {
2430         public static ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new List<T>());
2431     }
2432 
2433     class OperationWithTimeoutAsyncResult : TraceAsyncResult
2434     {
2435         static readonly Action<object> scheduledCallback = new Action<object>(OnScheduled);
2436         TimeoutHelper timeoutHelper;
2437         OperationWithTimeoutCallback operationWithTimeout;
2438 
OperationWithTimeoutAsyncResult(OperationWithTimeoutCallback operationWithTimeout, TimeSpan timeout, AsyncCallback callback, object state)2439         public OperationWithTimeoutAsyncResult(OperationWithTimeoutCallback operationWithTimeout, TimeSpan timeout, AsyncCallback callback, object state)
2440             : base(callback, state)
2441         {
2442             this.operationWithTimeout = operationWithTimeout;
2443             this.timeoutHelper = new TimeoutHelper(timeout);
2444             ActionItem.Schedule(scheduledCallback, this);
2445         }
2446 
OnScheduled(object state)2447         static void OnScheduled(object state)
2448         {
2449             OperationWithTimeoutAsyncResult thisResult = (OperationWithTimeoutAsyncResult)state;
2450             Exception completionException = null;
2451             try
2452             {
2453                 using (thisResult.CallbackActivity == null ? null : ServiceModelActivity.BoundOperation(thisResult.CallbackActivity))
2454                 {
2455                     thisResult.operationWithTimeout(thisResult.timeoutHelper.RemainingTime());
2456                 }
2457             }
2458 #pragma warning suppress 56500 // covered by FxCOP
2459             catch (Exception e)
2460             {
2461                 if (Fx.IsFatal(e))
2462                 {
2463                     throw;
2464                 }
2465 
2466                 completionException = e;
2467             }
2468             thisResult.Complete(false, completionException);
2469         }
2470 
End(IAsyncResult result)2471         public static void End(IAsyncResult result)
2472         {
2473             AsyncResult.End<OperationWithTimeoutAsyncResult>(result);
2474         }
2475     }
2476 }
2477