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