< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Security.ProtectionLevelHelper
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/SecurityUtils.cs
Line coverage
26%
Covered lines: 5
Uncovered lines: 14
Coverable lines: 19
Total lines: 1696
Line coverage: 26.3%
Branch coverage
25%
Covered branches: 6
Total branches: 24
Branch coverage: 25%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
IsDefined(...)0%440%
Validate(...)0%220%
IsStronger(...)50%66100%
IsStrongerOrEqual(...)50%44100%
Max(...)50%22100%
GetOrdinal(...)0%660%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/SecurityUtils.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Collections.ObjectModel;
 7using System.ComponentModel;
 8using System.Diagnostics;
 9using System.DirectoryServices.ActiveDirectory;
 10using System.Globalization;
 11using System.Net;
 12using System.Net.Security;
 13using System.Runtime.InteropServices;
 14using System.Security.Authentication.ExtendedProtection;
 15using System.Security.Cryptography;
 16using System.Security.Cryptography.X509Certificates;
 17using System.Security.Principal;
 18using System.Text;
 19using System.Threading;
 20using System.Threading.Tasks;
 21using System.Xml;
 22using CoreWCF.Channels;
 23using CoreWCF.Dispatcher;
 24using CoreWCF.IdentityModel;
 25using CoreWCF.IdentityModel.Claims;
 26using CoreWCF.IdentityModel.Policy;
 27using CoreWCF.IdentityModel.Selectors;
 28using CoreWCF.IdentityModel.Tokens;
 29using CoreWCF.Runtime;
 30using CoreWCF.Security.Tokens;
 31
 32namespace CoreWCF.Security
 33{
 34    internal static class ProtectionLevelHelper
 35    {
 36        internal static bool IsDefined(ProtectionLevel value)
 37        {
 038            return (value == ProtectionLevel.None
 039                || value == ProtectionLevel.Sign
 040                || value == ProtectionLevel.EncryptAndSign);
 41        }
 42
 43        internal static void Validate(ProtectionLevel value)
 44        {
 045            if (!IsDefined(value))
 46            {
 047                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException(nameof(value)
 048                    typeof(ProtectionLevel)));
 49            }
 050        }
 51
 52        internal static bool IsStronger(ProtectionLevel v1, ProtectionLevel v2)
 53        {
 24254            return ((v1 == ProtectionLevel.EncryptAndSign && v2 != ProtectionLevel.EncryptAndSign)
 24255                    || (v1 == ProtectionLevel.Sign && v2 == ProtectionLevel.None));
 56        }
 57
 58        internal static bool IsStrongerOrEqual(ProtectionLevel v1, ProtectionLevel v2)
 59        {
 960            return (v1 == ProtectionLevel.EncryptAndSign
 961                    || (v1 == ProtectionLevel.Sign && v2 != ProtectionLevel.EncryptAndSign));
 62        }
 63
 64        internal static ProtectionLevel Max(ProtectionLevel v1, ProtectionLevel v2)
 65        {
 24266            return IsStronger(v1, v2) ? v1 : v2;
 67        }
 68
 69        internal static int GetOrdinal(Nullable<ProtectionLevel> p)
 70        {
 071            if (p.HasValue)
 72            {
 073                switch ((ProtectionLevel)p)
 74                {
 75                    default:
 076                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException(nameo
 77                    case ProtectionLevel.None:
 078                        return 2;
 79                    case ProtectionLevel.Sign:
 080                        return 3;
 81                    case ProtectionLevel.EncryptAndSign:
 082                        return 4;
 83                }
 84            }
 85            else
 86            {
 087                return 1;
 88            }
 89        }
 90    }
 91
 92    internal class ServiceModelDictionaryManager
 93    {
 94        private static DictionaryManager s_dictionaryManager;
 95
 96        public static DictionaryManager Instance
 97        {
 98            get
 99            {
 100                if (s_dictionaryManager == null)
 101                {
 102                    s_dictionaryManager = new DictionaryManager((ServiceModelDictionary)BinaryMessageEncoderFactory.XmlD
 103                }
 104
 105                return s_dictionaryManager;
 106            }
 107        }
 108    }
 109
 110    internal class SecurityUtils
 111    {
 112        public const string Principal = "Principal";
 113        public const string Identities = "Identities";
 114        public const string AuthTypeCertMap = "SSL/PCT";
 115        private static SecurityIdentifier s_administratorsSid;
 116        internal static byte[] ReadContentAsBase64(XmlDictionaryReader reader, long maxBufferSize)
 117        {
 118            throw new PlatformNotSupportedException();
 119        }
 120
 121        private static bool s_computedDomain;
 122
 123        internal static byte[] EncryptKey(SecurityToken wrappingToken, string wrappingAlgorithm, byte[] keyToWrap)
 124        {
 125            throw new PlatformNotSupportedException();
 126        }
 127
 128        private static string s_currentDomain;
 129        private static IIdentity s_anonymousIdentity;
 130        private static X509SecurityTokenAuthenticator s_nonValidatingX509Authenticator;
 131        private static byte[] s_combinedHashLabel;
 132
 133        internal static byte[] CombinedHashLabel
 134        {
 135            get
 136            {
 137                if (s_combinedHashLabel == null)
 138                    s_combinedHashLabel = Encoding.UTF8.GetBytes(TrustApr2004Strings.CombinedHashLabel);
 139                return s_combinedHashLabel;
 140            }
 141        }
 142
 143        internal static IIdentity AnonymousIdentity
 144        {
 145            get
 146            {
 147                if (s_anonymousIdentity == null)
 148                {
 149                    s_anonymousIdentity = CreateIdentity(string.Empty);
 150                }
 151                return s_anonymousIdentity;
 152            }
 153        }
 154
 155        internal static X509SecurityTokenAuthenticator NonValidatingX509Authenticator
 156        {
 157            get
 158            {
 159                if (s_nonValidatingX509Authenticator == null)
 160                {
 161                    s_nonValidatingX509Authenticator = new X509SecurityTokenAuthenticator(X509CertificateValidator.None)
 162                }
 163                return s_nonValidatingX509Authenticator;
 164            }
 165        }
 166
 167        public static DateTime MinUtcDateTime => new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKi
 168
 169        public static DateTime MaxUtcDateTime =>
 170                // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
 171                new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc);
 172
 173        public static SecurityIdentifier AdministratorsSid
 174        {
 175            get
 176            {
 177                if (s_administratorsSid == null)
 178                {
 179                    s_administratorsSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
 180                }
 181
 182                return s_administratorsSid;
 183            }
 184        }
 185
 186
 187
 188        internal static ReadOnlyCollection<SecurityKey> CreateSymmetricSecurityKeys(byte[] key)
 189        {
 190            List<SecurityKey> temp = new List<SecurityKey>(1)
 191            {
 192                new InMemorySymmetricSecurityKey(key)
 193            };
 194            return temp.AsReadOnly();
 195        }
 196
 197        internal static SecurityKeyIdentifier CreateSecurityKeyIdentifier(Microsoft.IdentityModel.Xml.KeyInfo keyInfo)
 198        {
 199            if(keyInfo!=null && keyInfo.RSAKeyValue !=null)
 200            {
 201                throw new NotSupportedException("RSA key not supported.");
 202            }
 203
 204            foreach (var objdata in keyInfo.X509Data)
 205            {
 206                foreach (string certificateStr in objdata.Certificates)
 207                {
 208                    byte[] data = Convert.FromBase64String(certificateStr);
 209                    return new SecurityKeyIdentifier(new X509RawDataKeyIdentifierClause(data, false));;
 210                }
 211            }
 212
 213            return null;
 214        }
 215
 216        internal static IIdentity CreateIdentity(string name)
 217        {
 218            return new GenericIdentity(name);
 219        }
 220
 221        internal static EndpointIdentity CreateWindowsIdentity()
 222        {
 223            return CreateWindowsIdentity(false);
 224        }
 225
 226        internal static string GetSpnFromIdentity(EndpointIdentity identity, EndpointAddress target)
 227        {
 228            bool foundSpn = false;
 229            string spn = null;
 230            if (identity != null)
 231            {
 232                if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
 233                {
 234                    spn = (string)identity.IdentityClaim.Resource;
 235                    foundSpn = true;
 236                }
 237                else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
 238                {
 239                    spn = (string)identity.IdentityClaim.Resource;
 240                    foundSpn = true;
 241                }
 242                else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
 243                {
 244                    spn = string.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resourc
 245                    foundSpn = true;
 246                }
 247            }
 248            if (!foundSpn)
 249            {
 250                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.Format(SR.Cann
 251            }
 252            return spn;
 253        }
 254
 255        private static bool IsSystemAccount(WindowsIdentity self)
 256        {
 257            SecurityIdentifier sid = self.User;
 258            if (sid == null)
 259            {
 260                return false;
 261            }
 262            // S-1-5-82 is the prefix for the sid that represents the identity that IIS 7.5 Apppool thread runs under.
 263            return (sid.IsWellKnown(WellKnownSidType.LocalSystemSid)
 264                    || sid.IsWellKnown(WellKnownSidType.NetworkServiceSid)
 265                    || sid.IsWellKnown(WellKnownSidType.LocalServiceSid)
 266                    || self.User.Value.StartsWith("S-1-5-82", StringComparison.OrdinalIgnoreCase));
 267        }
 268
 269        internal static EndpointIdentity CreateWindowsIdentity(bool spnOnly)
 270        {
 271            // This is used by SspiNegotiationTokenAuthenticator to calculate the
 272            // DefaultServiceBinding value. On Linux, we cannot use the current Windows Identity,
 273            // so we will return an Spn based on the machine name. It's quite a bit of work to
 274            // get Windows authentication to work on Linux, so if a developer has gone to that
 275            // kind of effort to use Windows authentication on Linux, they can provide an
 276            // explicit value to SspiNegotiationTokenAuthenticator.DefaultServiceBinding and
 277            // this code won't be needed.
 278            EndpointIdentity identity = null;
 279            using (WindowsIdentity self = WindowsIdentity.GetCurrent())
 280            {
 281                bool isSystemAccount = IsSystemAccount(self);
 282                if (spnOnly || isSystemAccount || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
 283                {
 284                    // If we're running on a non-Windows platform, we can't use the current Windows identity.
 285                    // If we're running on Windows and the current identity is a system account, we also can't use it.
 286                    // In both cases, we create an SPN identity based on the machine name.
 287                    identity = new SpnEndpointIdentity(string.Format(CultureInfo.InvariantCulture, "host/{0}", DnsCache.
 288                }
 289                else
 290                {
 291                    // Fallback to using the current WindowsIdentity Name, which will be in the form DOMAIN\username.
 292                    identity = new UpnEndpointIdentity(self.Name);
 293                }
 294            }
 295
 296            return identity;
 297        }
 298
 299        internal static int GetMaxNegotiationBufferSize(BindingContext bindingContext)
 300        {
 301            TransportBindingElement transport = bindingContext.RemainingBindingElements.Find<TransportBindingElement>();
 302            Fx.Assert(transport != null, "TransportBindingElement is null!");
 303            int maxNegoMessageSize;
 304            //TODO move below binding elements to Primitives
 305            //if (transport is ConnectionOrientedTransportBindingElement)
 306            //{
 307            //    maxNegoMessageSize = ((ConnectionOrientedTransportBindingElement)transport).MaxBufferSize;
 308            //}
 309            //else if (transport is HttpTransportBindingElement)
 310            //{
 311            //    maxNegoMessageSize = ((HttpTransportBindingElement)transport).MaxBufferSize;
 312            //}
 313            //else
 314            //{
 315                maxNegoMessageSize = TransportDefaults.MaxBufferSize;
 316           // }
 317            return maxNegoMessageSize;
 318        }
 319
 320        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid)
 321        {
 322            return CloneWindowsIdentityIfNecessary(wid, null);
 323        }
 324
 325        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authType)
 326        {
 327            if (wid != null)
 328            {
 329                IntPtr token = UnsafeGetWindowsIdentityToken(wid);
 330                if (token != IntPtr.Zero)
 331                {
 332                    return UnsafeCreateWindowsIdentityFromToken(token, authType);
 333                }
 334            }
 335            return wid;
 336        }
 337
 338        private static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid)
 339        {
 340            return wid.Token;
 341        }
 342
 343        private static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authType)
 344        {
 345            if (authType != null)
 346            {
 347                return new WindowsIdentity(token, authType);
 348            }
 349            else
 350            {
 351                return new WindowsIdentity(token);
 352            }
 353        }
 354
 355        internal static Claim GetPrimaryIdentityClaim(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
 356        {
 357            return GetPrimaryIdentityClaim(AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies)
 358        }
 359
 360        internal static Claim GetPrimaryIdentityClaim(AuthorizationContext authContext)
 361        {
 362            if (authContext != null)
 363            {
 364                for (int i = 0; i < authContext.ClaimSets.Count; ++i)
 365                {
 366                    ClaimSet claimSet = authContext.ClaimSets[i];
 367                    foreach (Claim claim in claimSet.FindClaims(null, Rights.Identity))
 368                    {
 369                        return claim;
 370                    }
 371                }
 372            }
 373            return null;
 374        }
 375
 376        internal static string GetPrimaryDomain()
 377        {
 378            using (WindowsIdentity wid = WindowsIdentity.GetCurrent())
 379            {
 380                return GetPrimaryDomain(IsSystemAccount(wid));
 381            }
 382        }
 383
 384        internal static string GetPrimaryDomain(bool isSystemAccount)
 385        {
 386            if (s_computedDomain == false)
 387            {
 388                try
 389                {
 390                    if (isSystemAccount)
 391                    {
 392                        s_currentDomain = Domain.GetComputerDomain().Name;
 393                    }
 394                    else
 395                    {
 396                        s_currentDomain = Domain.GetCurrentDomain().Name;
 397                    }
 398                }
 399                catch (Exception e)
 400                {
 401                    if (Fx.IsFatal(e))
 402                    {
 403                        throw;
 404                    }
 405                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
 406                }
 407                finally
 408                {
 409                    s_computedDomain = true;
 410                }
 411            }
 412            return s_currentDomain;
 413        }
 414
 415        internal static void EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate)
 416        {
 417            if (certificate == null)
 418            {
 419                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(certificate));
 420            }
 421            bool canDoKeyExchange = false;
 422            Exception innerException = null;
 423            if (certificate.HasPrivateKey)
 424            {
 425                try
 426                {
 427                    canDoKeyExchange = CanKeyDoKeyExchange(certificate);
 428                }
 429                // exceptions can be due to ACLs on the key etc
 430                catch (System.Security.SecurityException e)
 431                {
 432                    innerException = e;
 433                }
 434                catch (CryptographicException e)
 435                {
 436                    innerException = e;
 437                }
 438            }
 439            if (!canDoKeyExchange)
 440            {
 441                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.SslCertMayN
 442            }
 443        }
 444
 445        public static WrappedKeySecurityToken CreateTokenFromEncryptedKeyClause(EncryptedKeyIdentifierClause keyClause, 
 446        {
 447            SecurityKeyIdentifier wrappingTokenReference = keyClause.EncryptingKeyIdentifier;
 448            byte[] wrappedKey = keyClause.GetEncryptedKey();
 449            SecurityKey unwrappingSecurityKey = unwrappingToken.SecurityKeys[0];
 450            string wrappingAlgorithm = keyClause.EncryptionMethod;
 451            byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
 452            //TODO, check value for XmlDictionaryString Symmetric or else
 453            return new WrappedKeySecurityToken(SecurityUtils.GenerateId(), unwrappedKey, wrappingAlgorithm,
 454               XmlDictionaryString.Empty, unwrappingToken, wrappingTokenReference, wrappedKey, unwrappingSecurityKey
 455                    );
 456        }
 457
 458        private static bool CanKeyDoKeyExchange(X509Certificate2 certificate)
 459        {
 460            X509KeyUsageExtension keyUsageExtension = null;
 461            for (int i = 0; i < certificate.Extensions.Count; i++)
 462            {
 463                keyUsageExtension = certificate.Extensions[i] as X509KeyUsageExtension;
 464                if (keyUsageExtension != null)
 465                {
 466                    break;
 467                }
 468            }
 469
 470            // No KeyUsage extension means most usages are permitted including key exchange.
 471            // See RFC 5280 section 4.2.1.3 (Key Usage) for details. If the extension is non-critical
 472            // then it's non-enforcing and meant as an aid in choosing the best certificate when
 473            // there are multiple certificates to choose from.
 474            if (keyUsageExtension == null || !keyUsageExtension.Critical)
 475            {
 476                return true;
 477            }
 478
 479            // One of KeyAgreement, KeyEncipherment or DigitalSignature need to be allowed depending on the cipher
 480            // being used. See RFC 5246 section 7.4.6 for more details.
 481            // Additionally, according to msdn docs for PFXImportCertStore, the key specification is set to AT_KEYEXCHAN
 482            // when the data encipherment usage is set.
 483            bool canDoKeyExchange = (keyUsageExtension.KeyUsages &
 484                (X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.KeyEncipherment |
 485                    X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.DataEncipherment)) != X509KeyUsageFlags.None;
 486            return canDoKeyExchange;
 487        }
 488
 489        internal static byte[] DecryptKey(SecurityToken unwrappingToken, string encryptionMethod, byte[] wrappedKey, out
 490        {
 491            unwrappingSecurityKey = null;
 492            if (unwrappingToken.SecurityKeys != null)
 493            {
 494                for (int i = 0; i < unwrappingToken.SecurityKeys.Count; ++i)
 495                {
 496                    if (unwrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod))
 497                    {
 498                        unwrappingSecurityKey = unwrappingToken.SecurityKeys[i];
 499                        break;
 500                    }
 501                }
 502            }
 503            if (unwrappingSecurityKey == null)
 504            {
 505                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(SR.Ca
 506            }
 507            return unwrappingSecurityKey.DecryptKey(encryptionMethod, wrappedKey);
 508        }
 509
 510        internal static MessageFault CreateSecurityContextNotFoundFault(SecurityStandardsManager standardsManager, strin
 511        {
 512            SecureConversationDriver scDriver = standardsManager.SecureConversationDriver;
 513            FaultCode subCode = new FaultCode(scDriver.BadContextTokenFaultCode.Value, scDriver.Namespace.Value);
 514            FaultReason reason;
 515            if (action != null)
 516            {
 517                reason = new FaultReason(SR.Format(SR.BadContextTokenOrActionFaultReason, action), CultureInfo.CurrentCu
 518            }
 519            else
 520            {
 521                reason = new FaultReason(SR.Format(SR.BadContextTokenFaultReason), CultureInfo.CurrentCulture);
 522            }
 523            FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
 524            return MessageFault.CreateFault(senderCode, reason);
 525        }
 526
 527        internal static MessageFault CreateSecurityMessageFault(Exception e, SecurityStandardsManager standardsManager)
 528        {
 529            bool isSecurityError = false;
 530            bool isTokenValidationError = false;
 531            bool isGenericTokenError = false;
 532            FaultException faultException = null;
 533            while (e != null)
 534            {
 535                if (e is SecurityTokenValidationException)
 536                {
 537                    if (e is SecurityContextTokenValidationException)
 538                    {
 539                        return CreateSecurityContextNotFoundFault(SecurityStandardsManager.DefaultInstance, null);
 540                    }
 541                    isSecurityError = true;
 542                    isTokenValidationError = true;
 543                    break;
 544                }
 545                else if (e is SecurityTokenException)
 546                {
 547                    isSecurityError = true;
 548                    isGenericTokenError = true;
 549                    break;
 550                }
 551                else if (e is MessageSecurityException ms)
 552                {
 553                    if (ms.Fault != null)
 554                    {
 555                        return ms.Fault;
 556                    }
 557                    isSecurityError = true;
 558                }
 559                else if (e is FaultException fe)
 560                {
 561                    faultException = fe;
 562                    break;
 563                }
 564                e = e.InnerException;
 565            }
 566            if (!isSecurityError && faultException == null)
 567            {
 568                return null;
 569            }
 570            FaultCode subCode;
 571            FaultReason reason;
 572            SecurityVersion wss = standardsManager.SecurityVersion;
 573            if (isTokenValidationError)
 574            {
 575                subCode = new FaultCode(wss.FailedAuthenticationFaultCode.Value, wss.HeaderNamespace.Value);
 576                reason = new FaultReason(SR.Format(SR.FailedAuthenticationFaultReason), CultureInfo.CurrentCulture);
 577            }
 578            else if (isGenericTokenError)
 579            {
 580                subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value);
 581                reason = new FaultReason(SR.Format(SR.InvalidSecurityTokenFaultReason), CultureInfo.CurrentCulture);
 582            }
 583            else if (faultException != null)
 584            {
 585                // Only support Code and Reason.  No detail or action customization.
 586                return MessageFault.CreateFault(faultException.Code, faultException.Reason);
 587            }
 588            else
 589            {
 590                subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value);
 591                reason = new FaultReason(SR.Format(SR.InvalidSecurityFaultReason), CultureInfo.CurrentCulture);
 592            }
 593            FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
 594            return MessageFault.CreateFault(senderCode, reason);
 595        }
 596
 597        internal static string GenerateId() => SecurityUniqueId.Create().Value;
 598
 599        internal static byte[] GenerateDerivedKey(SecurityToken tokenToDerive, string derivationAlgorithm, byte[] label,
 600        {
 601            SymmetricSecurityKey symmetricSecurityKey = GetSecurityKey<SymmetricSecurityKey>(tokenToDerive);
 602            if (symmetricSecurityKey == null || !symmetricSecurityKey.IsSupportedAlgorithm(derivationAlgorithm))
 603            {
 604                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(SR.Ca
 605            }
 606            return symmetricSecurityKey.GenerateDerivedKey(derivationAlgorithm, label, nonce, keySize, offset);
 607        }
 608
 609        public static bool TryCreateKeyFromIntrinsicKeyClause(SecurityKeyIdentifierClause keyIdentifierClause, SecurityT
 610        {
 611            key = null;
 612            if (keyIdentifierClause.CanCreateKey)
 613            {
 614                key = keyIdentifierClause.CreateKey();
 615                return true;
 616            }
 617            if (keyIdentifierClause is EncryptedKeyIdentifierClause keyClause)
 618            {
 619                for (int i = 0; i < keyClause.EncryptingKeyIdentifier.Count; i++)
 620                {
 621                    if (resolver.TryResolveSecurityKey(keyClause.EncryptingKeyIdentifier[i], out SecurityKey unwrappingS
 622                    {
 623                        byte[] wrappedKey = keyClause.GetEncryptedKey();
 624                        string wrappingAlgorithm = keyClause.EncryptionMethod;
 625                        byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
 626                        key = new InMemorySymmetricSecurityKey(unwrappedKey, false);
 627                        return true;
 628                    }
 629                }
 630            }
 631            return false;
 632        }
 633
 634        internal static bool HasSymmetricSecurityKey(SecurityToken sourceEncryptionToken)
 635        {
 636            return GetSecurityKey<SymmetricSecurityKey>(sourceEncryptionToken) != null;
 637        }
 638
 639        internal static byte[] CloneBuffer(byte[] buffer)
 640        {
 641            byte[] copy = Fx.AllocateByteArray(buffer.Length);
 642            Buffer.BlockCopy(buffer, 0, copy, 0, buffer.Length);
 643            return copy;
 644        }
 645
 646        internal static byte[] CloneBuffer(byte[] buffer, int offset, int len)
 647        {
 648            DiagnosticUtility.DebugAssert(offset >= 0, "Negative offset passed to CloneBuffer.");
 649            DiagnosticUtility.DebugAssert(len >= 0, "Negative len passed to CloneBuffer.");
 650            DiagnosticUtility.DebugAssert(buffer.Length - offset >= len, "Invalid parameters to CloneBuffer.");
 651
 652            byte[] copy = Fx.AllocateByteArray(len);
 653            Buffer.BlockCopy(buffer, offset, copy, 0, len);
 654            return copy;
 655        }
 656
 657        internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token)
 658        {
 659            if (token.SecurityKeys == null)
 660            {
 661                return false;
 662            }
 663            for (int i = 0; i < token.SecurityKeys.Count; ++i)
 664            {
 665                if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm))
 666                {
 667                    return true;
 668                }
 669            }
 670            return false;
 671        }
 672        internal static T GetSecurityKey<T>(SecurityToken token) where T : SecurityKey
 673        {
 674            T result = null;
 675            if (token.SecurityKeys != null)
 676            {
 677                for (int i = 0; i < token.SecurityKeys.Count; ++i)
 678                {
 679                    T temp = (token.SecurityKeys[i] as T);
 680                    if (temp != null)
 681                    {
 682                        if (result != null)
 683                        {
 684                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.
 685                        }
 686                        else
 687                        {
 688                            result = temp;
 689                        }
 690                    }
 691                }
 692            }
 693            return result;
 694        }
 695
 696        internal static bool TryCreateX509CertificateFromRawData(byte[] rawData, out X509Certificate2 certificate)
 697        {
 698            certificate = (rawData == null || rawData.Length == 0) ? null : new X509Certificate2(rawData);
 699            return certificate != null && certificate.Handle != IntPtr.Zero;
 700        }
 701
 702        internal static string GetKeyDerivationAlgorithm(SecureConversationVersion version)
 703        {
 704            string derivationAlgorithm;
 705            if (version == SecureConversationVersion.WSSecureConversationFeb2005)
 706            {
 707                derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivation;
 708            }
 709            else if (version == SecureConversationVersion.WSSecureConversation13)
 710            {
 711                derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivationDec2005;
 712            }
 713            else
 714            {
 715                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
 716            }
 717
 718            return derivationAlgorithm;
 719        }
 720
 721        internal static IIdentity CreateIdentity(string name, string authenticationType)
 722        {
 723            return new GenericIdentity(name, authenticationType);
 724        }
 725
 726        internal static ReadOnlyCollection<IAuthorizationPolicy> CloneAuthorizationPoliciesIfNecessary(ReadOnlyCollectio
 727        {
 728            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
 729            {
 730                bool clone = false;
 731                for (int i = 0; i < authorizationPolicies.Count; ++i)
 732                {
 733                    if (authorizationPolicies[i] is UnconditionalPolicy policy && policy.IsDisposable)
 734                    {
 735                        clone = true;
 736                        break;
 737                    }
 738                }
 739                if (clone)
 740                {
 741                    List<IAuthorizationPolicy> ret = new List<IAuthorizationPolicy>(authorizationPolicies.Count);
 742                    for (int i = 0; i < authorizationPolicies.Count; ++i)
 743                    {
 744                        if (authorizationPolicies[i] is UnconditionalPolicy policy)
 745                        {
 746                            ret.Add(policy.Clone());
 747                        }
 748                        else
 749                        {
 750                            ret.Add(authorizationPolicies[i]);
 751                        }
 752                    }
 753                    return ret.AsReadOnly();
 754                }
 755            }
 756            return authorizationPolicies;
 757        }
 758
 759        public static void DisposeAuthorizationPoliciesIfNecessary(ReadOnlyCollection<IAuthorizationPolicy> authorizatio
 760        {
 761            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
 762            {
 763                for (int i = 0; i < authorizationPolicies.Count; ++i)
 764                {
 765                    DisposeIfNecessary(authorizationPolicies[i] as UnconditionalPolicy);
 766                }
 767            }
 768        }
 769
 770        public static void DisposeIfNecessary(IDisposable obj)
 771        {
 772            if (obj != null)
 773            {
 774                obj.Dispose();
 775            }
 776        }
 777
 778        public static ChannelBinding GetChannelBindingFromMessage(Message message)
 779        {
 780            if (message == null)
 781            {
 782                return null;
 783            }
 784
 785            ChannelBindingMessageProperty.TryGet(message, out ChannelBindingMessageProperty channelBindingMessagePropert
 786            ChannelBinding channelBinding = null;
 787
 788            if (channelBindingMessageProperty != null)
 789            {
 790                channelBinding = channelBindingMessageProperty.ChannelBinding;
 791            }
 792
 793            return channelBinding;
 794        }
 795
 796        internal static NetworkCredential GetNetworkCredentialsCopy(NetworkCredential networkCredential)
 797        {
 798            NetworkCredential result;
 799            if (networkCredential != null && !NetworkCredentialHelper.IsDefault(networkCredential))
 800            {
 801                result = new NetworkCredential(NetworkCredentialHelper.UnsafeGetUsername(networkCredential), NetworkCred
 802            }
 803            else
 804            {
 805                result = networkCredential;
 806            }
 807            return result;
 808        }
 809
 810        private static class NetworkCredentialHelper
 811        {
 812            internal static bool IsNullOrEmpty(NetworkCredential credential)
 813            {
 814                return credential == null ||
 815                        (
 816                            string.IsNullOrEmpty(UnsafeGetUsername(credential)) &&
 817                            string.IsNullOrEmpty(UnsafeGetDomain(credential)) &&
 818                            string.IsNullOrEmpty(UnsafeGetPassword(credential))
 819                        );
 820            }
 821
 822            internal static bool IsDefault(NetworkCredential credential)
 823            {
 824                return UnsafeGetDefaultNetworkCredentials().Equals(credential);
 825            }
 826
 827            internal static string UnsafeGetUsername(NetworkCredential credential)
 828            {
 829                return credential.UserName;
 830            }
 831
 832            internal static string UnsafeGetPassword(NetworkCredential credential)
 833            {
 834                return credential.Password;
 835            }
 836
 837            internal static string UnsafeGetDomain(NetworkCredential credential)
 838            {
 839                return credential.Domain;
 840            }
 841
 842            private static NetworkCredential UnsafeGetDefaultNetworkCredentials()
 843            {
 844                return CredentialCache.DefaultNetworkCredentials;
 845            }
 846        }
 847
 848        internal static X509Certificate2 GetCertificateFromStore(StoreName storeName, StoreLocation storeLocation,
 849            X509FindType findType, object findValue, EndpointAddress target)
 850        {
 851            X509Certificate2 certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, ta
 852            if (certificate == null)
 853            {
 854                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.Can
 855            }
 856
 857            return certificate;
 858        }
 859
 860        private static X509Certificate2 GetCertificateFromStoreCore(StoreName storeName, StoreLocation storeLocation,
 861            X509FindType findType, object findValue, EndpointAddress target, bool throwIfMultipleOrNoMatch)
 862        {
 863            if (findValue == null)
 864            {
 865                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(findValue));
 866            }
 867            X509Store store = new X509Store(storeName, storeLocation);
 868            X509Certificate2Collection certs = null;
 869            try
 870            {
 871                store.Open(OpenFlags.ReadOnly);
 872                certs = store.Certificates.Find(findType, findValue, false);
 873                if (certs.Count == 1)
 874                {
 875                    return new X509Certificate2(certs[0]);
 876                }
 877                if (throwIfMultipleOrNoMatch)
 878                {
 879                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateCertificateLoadException(
 880                        storeName, storeLocation, findType, findValue, target, certs.Count));
 881                }
 882                else
 883                {
 884                    return null;
 885                }
 886            }
 887            finally
 888            {
 889                ResetAllCertificates(certs);
 890                store.Close();
 891            }
 892        }
 893
 894        private static Exception CreateCertificateLoadException(StoreName storeName, StoreLocation storeLocation,
 895            X509FindType findType, object findValue, EndpointAddress target, int certCount)
 896        {
 897            if (certCount == 0)
 898            {
 899                if (target == null)
 900                {
 901                    return new InvalidOperationException(SR.Format(SR.CannotFindCert, storeName, storeLocation, findType
 902                }
 903                else
 904                {
 905                    return new InvalidOperationException(SR.Format(SR.CannotFindCertForTarget, storeName, storeLocation,
 906                }
 907            }
 908            else
 909            {
 910                if (target == null)
 911                {
 912                    return new InvalidOperationException(SR.Format(SR.FoundMultipleCerts, storeName, storeLocation, find
 913                }
 914                else
 915                {
 916                    return new InvalidOperationException(SR.Format(SR.FoundMultipleCertsForTarget, storeName, storeLocat
 917                }
 918            }
 919        }
 920
 921        internal static UniqueId GenerateUniqueId()
 922        {
 923            return new UniqueId();
 924        }
 925
 926        // This is the workaround, Since store.Certificates returns a full collection
 927        // of certs in store.  These are holding native resources.
 928        internal static void ResetAllCertificates(X509Certificate2Collection certificates)
 929        {
 930            if (certificates != null)
 931            {
 932                for (int i = 0; i < certificates.Count; ++i)
 933                {
 934                    ResetCertificate(certificates[i]);
 935                }
 936            }
 937        }
 938
 939        internal static void ErasePasswordInUsernameTokenIfPresent(SecurityMessageProperty bootstrapMessageProperty)
 940        {
 941            throw new NotImplementedException();
 942        }
 943
 944        internal static void ResetCertificate(X509Certificate2 certificate)
 945        {
 946            certificate.Reset();
 947        }
 948
 949        internal static Task OpenTokenAuthenticatorIfRequiredAsync(SecurityTokenAuthenticator tokenAuthenticator, Cancel
 950        {
 951            return OpenCommunicationObjectAsync(tokenAuthenticator as ICommunicationObject, token);
 952        }
 953
 954        internal static Task OpenTokenProviderIfRequiredAsync(SecurityTokenProvider tokenProvider, CancellationToken tok
 955        {
 956            return OpenCommunicationObjectAsync(tokenProvider as ICommunicationObject, token);
 957        }
 958
 959        internal static Task CloseTokenProviderIfRequiredAsync(SecurityTokenProvider tokenProvider, CancellationToken to
 960        {
 961            return CloseCommunicationObjectAsync(tokenProvider, false, token);
 962        }
 963
 964        internal static void AbortTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator)
 965        {
 966            CloseCommunicationObjectAsync(tokenAuthenticator, true, CancellationToken.None).GetAwaiter().GetResult();
 967        }
 968
 969        internal static void AbortTokenProviderIfRequired(SecurityTokenProvider tokenProvider)
 970        {
 971            CloseCommunicationObjectAsync(tokenProvider, true, CancellationToken.None).GetAwaiter().GetResult();
 972        }
 973
 974
 975        internal static Task CloseTokenAuthenticatorIfRequiredAsync(SecurityTokenAuthenticator tokenAuthenticator, Cance
 976        {
 977            return CloseTokenAuthenticatorIfRequiredAsync(tokenAuthenticator, false, token);
 978        }
 979
 980        internal static Task CloseTokenAuthenticatorIfRequiredAsync(SecurityTokenAuthenticator tokenAuthenticator, bool 
 981        {
 982            return CloseCommunicationObjectAsync(tokenAuthenticator, aborted, token);
 983        }
 984
 985        private static Task OpenCommunicationObjectAsync(ICommunicationObject obj, CancellationToken token)
 986        {
 987            if (obj != null)
 988            {
 989                return obj.OpenAsync(token);
 990            }
 991
 992            return Task.CompletedTask;
 993        }
 994
 995        private static Task CloseCommunicationObjectAsync(object obj, bool aborted, CancellationToken token)
 996        {
 997            if (obj != null)
 998            {
 999                if (obj is ICommunicationObject co)
 1000                {
 1001                    if (aborted)
 1002                    {
 1003                        try
 1004                        {
 1005                            co.Abort();
 1006                        }
 1007                        catch (CommunicationException e)
 1008                        {
 1009                            DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 1010                        }
 1011                    }
 1012                    else
 1013                    {
 1014                        return co.CloseAsync(token);
 1015                    }
 1016                }
 1017                else if (obj is IDisposable disposable)
 1018                {
 1019                    disposable.Dispose();
 1020                }
 1021            }
 1022
 1023            return Task.CompletedTask;
 1024        }
 1025
 1026        public static void ValidateAnonymityConstraint(WindowsIdentity identity, bool allowUnauthenticatedCallers)
 1027        {
 1028            if (!allowUnauthenticatedCallers && identity.User.IsWellKnown(WellKnownSidType.AnonymousSid))
 1029            {
 1030                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(
 1031                    new SecurityTokenValidationException(SR.AnonymousLogonsAreNotAllowed));
 1032            }
 1033        }
 1034
 1035        /*internal static ReadOnlyCollection<IAuthorizationPolicy> CreatePrincipalNameAuthorizationPolicies(string princ
 1036        {
 1037            if (principalName == null)
 1038            {
 1039                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(principalName));
 1040            }
 1041
 1042            Claim identityClaim;
 1043            Claim primaryPrincipal;
 1044            if (principalName.Contains("@") || principalName.Contains(@"\"))
 1045            {
 1046                identityClaim = new Claim(ClaimTypes.Upn, principalName, Rights.Identity);
 1047                primaryPrincipal = Claim.CreateUpnClaim(principalName);
 1048            }
 1049            else
 1050            {
 1051                identityClaim = new Claim(ClaimTypes.Spn, principalName, Rights.Identity);
 1052                primaryPrincipal = Claim.CreateSpnClaim(principalName);
 1053            }
 1054
 1055            List<Claim> claims = new List<Claim>(2)
 1056            {
 1057                identityClaim,
 1058                primaryPrincipal
 1059            };
 1060
 1061
 1062            List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1)
 1063            {
 1064                new UnconditionalPolicy(CreateIdentity(principalName), new DefaultClaimSet(ClaimSet.Anonymous, claims))
 1065            };
 1066            return policies.AsReadOnly();
 1067        }*/
 1068
 1069        public static SecurityBindingElement GetIssuerSecurityBindingElement(ServiceModelSecurityTokenRequirement requir
 1070        {
 1071            SecurityBindingElement bindingElement = requirement.SecureConversationSecurityBindingElement;
 1072            if (bindingElement != null)
 1073            {
 1074                return bindingElement;
 1075            }
 1076
 1077            Binding binding = requirement.IssuerBinding;
 1078            if (binding == null)
 1079            {
 1080                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.Format(SR.IssuerBindingNotPresentInToken
 1081            }
 1082            BindingElementCollection bindingElements = binding.CreateBindingElements();
 1083            return bindingElements.Find<SecurityBindingElement>();
 1084        }
 1085
 1086        internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, 
 1087        {
 1088            SecurityTokenSerializer tokenSerializer = tokenManager.CreateSecurityTokenSerializer(securityVersion.Securit
 1089            return new SecurityStandardsManager(securityVersion, tokenSerializer);
 1090        }
 1091
 1092        internal static SecurityStandardsManager CreateSecurityStandardsManager(SecurityTokenRequirement requirement, Se
 1093        {
 1094            MessageSecurityTokenVersion securityVersion = (MessageSecurityTokenVersion)requirement.GetProperty<MessageSe
 1095            if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebrua
 1096            {
 1097                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConv
 1098            }
 1099            else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationF
 1100            {
 1101                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConv
 1102            }
 1103            else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationF
 1104            {
 1105                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConv
 1106            }
 1107            else if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrust13WSSecureConversation13BasicSecu
 1108            {
 1109                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13
 1110            }
 1111            else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13)
 1112            {
 1113                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13
 1114            }
 1115            else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13BasicSecu
 1116            {
 1117                return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13
 1118            }
 1119            else
 1120            {
 1121                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
 1122            }
 1123        }
 1124
 1125        internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion messageSecurityVe
 1126        {
 1127            if (messageSecurityVersion == null)
 1128            {
 1129                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(messageSecuri
 1130            }
 1131            if (securityTokenSerializer == null)
 1132            {
 1133                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(securityTokenSerializer));
 1134            }
 1135            return new SecurityStandardsManager(messageSecurityVersion, securityTokenSerializer);
 1136        }
 1137
 1138        internal static void MatchRstWithEndpointFilter(Message request, IMessageFilterTable<EndpointAddress> endpointFi
 1139        {
 1140            if (endpointFilterTable == null)
 1141            {
 1142                return;
 1143            }
 1144            Collection<EndpointAddress> result = new Collection<EndpointAddress>();
 1145            if (!endpointFilterTable.GetMatchingValues(request, result))
 1146            {
 1147                throw new SecurityNegotiationException(SR.Format(SR.RequestSecurityTokenDoesNotMatchEndpointFilters, lis
 1148            }
 1149        }
 1150
 1151        internal static bool IsEqual(byte[] a, byte[] b)
 1152        {
 1153            if (a == null || b == null || a.Length != b.Length)
 1154            {
 1155                return false;
 1156            }
 1157
 1158            for (int i = 0; i < a.Length; i++)
 1159            {
 1160                if (a[i] != b[i])
 1161                {
 1162                    return false;
 1163                }
 1164            }
 1165            return true;
 1166        }
 1167
 1168        internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClock
 1169        {
 1170            DateTime curEffectiveTime = (effectiveTime < DateTime.MinValue.Add(maxClockSkew)) ? effectiveTime : effectiv
 1171            DateTime curExpirationTime = (expirationTime > DateTime.MaxValue.Subtract(maxClockSkew)) ? expirationTime : 
 1172            DateTime curTime = DateTime.UtcNow;
 1173
 1174            return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime());
 1175        }
 1176
 1177        // match the RST with the endpoint filters in case there is at least 1 asymmetric signature in the message
 1178        internal static bool ShouldMatchRstWithEndpointFilter(SecurityBindingElement sbe)
 1179        {
 1180            foreach (SecurityTokenParameters parameters in new SecurityTokenParametersEnumerable(sbe, true))
 1181            {
 1182                if (parameters.HasAsymmetricKey)
 1183                {
 1184                    return true;
 1185                }
 1186            }
 1187            return false;
 1188        }
 1189
 1190        internal static string GetIdentityNamesFromPolicies(ReadOnlyCollection<IAuthorizationPolicy> authorizationPolici
 1191        {
 1192            return GetIdentityNamesFromContext(AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolic
 1193        }
 1194
 1195        internal static string GetIdentityNamesFromContext(AuthorizationContext authContext)
 1196        {
 1197            if (authContext == null)
 1198                return string.Empty;
 1199
 1200            StringBuilder str = new StringBuilder(256);
 1201            for (int i = 0; i < authContext.ClaimSets.Count; ++i)
 1202            {
 1203                ClaimSet claimSet = authContext.ClaimSets[i];
 1204
 1205                // Windows
 1206                if (claimSet is WindowsClaimSet windows)
 1207                {
 1208                    if (str.Length > 0)
 1209                        str.Append(", ");
 1210
 1211                    AppendIdentityName(str, windows.WindowsIdentity);
 1212                }
 1213                else
 1214                {
 1215                    // X509
 1216                    if (claimSet is X509CertificateClaimSet x509)
 1217                    {
 1218                        if (str.Length > 0)
 1219                            str.Append(", ");
 1220
 1221                        AppendCertificateIdentityName(str, x509.X509Certificate);
 1222                    }
 1223                }
 1224            }
 1225
 1226            if (str.Length <= 0)
 1227            {
 1228                List<IIdentity> identities = null;
 1229                if (authContext.Properties.TryGetValue(SecurityUtils.Identities, out object obj))
 1230                {
 1231                    identities = obj as List<IIdentity>;
 1232                }
 1233                if (identities != null)
 1234                {
 1235                    for (int i = 0; i < identities.Count; ++i)
 1236                    {
 1237                        IIdentity identity = identities[i];
 1238                        if (identity != null)
 1239                        {
 1240                            if (str.Length > 0)
 1241                                str.Append(", ");
 1242
 1243                            AppendIdentityName(str, identity);
 1244                        }
 1245                    }
 1246                }
 1247            }
 1248            return str.Length <= 0 ? string.Empty : str.ToString();
 1249        }
 1250
 1251        internal static void AppendIdentityName(StringBuilder str, IIdentity identity)
 1252        {
 1253            string name = null;
 1254            try
 1255            {
 1256                name = identity.Name;
 1257            }
 1258            catch (Exception e)
 1259            {
 1260                if (Fx.IsFatal(e))
 1261                {
 1262                    throw;
 1263                }
 1264                // suppress exception, this is just info.
 1265            }
 1266
 1267            str.Append(string.IsNullOrEmpty(name) ? "<null>" : name);
 1268
 1269            if (identity is WindowsIdentity windows)
 1270            {
 1271                if (windows.User != null)
 1272                {
 1273                    str.Append("; ");
 1274                    str.Append(windows.User.ToString());
 1275                }
 1276            }
 1277            else
 1278            {
 1279                if (identity is WindowsSidIdentity sid)
 1280                {
 1281                    str.Append("; ");
 1282                    str.Append(sid.SecurityIdentifier.ToString());
 1283                }
 1284            }
 1285        }
 1286
 1287        internal static void AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate)
 1288        {
 1289            string value = certificate.SubjectName.Name;
 1290            if (string.IsNullOrEmpty(value))
 1291            {
 1292                value = certificate.GetNameInfo(X509NameType.DnsName, false);
 1293                if (string.IsNullOrEmpty(value))
 1294                {
 1295                    value = certificate.GetNameInfo(X509NameType.SimpleName, false);
 1296                    if (string.IsNullOrEmpty(value))
 1297                    {
 1298                        value = certificate.GetNameInfo(X509NameType.EmailName, false);
 1299                        if (string.IsNullOrEmpty(value))
 1300                        {
 1301                            value = certificate.GetNameInfo(X509NameType.UpnName, false);
 1302                        }
 1303                    }
 1304                }
 1305            }
 1306            // Same format as X509Identity
 1307            str.Append(string.IsNullOrEmpty(value) ? "<x509>" : value);
 1308            str.Append("; ");
 1309            str.Append(certificate.Thumbprint);
 1310        }
 1311
 1312        internal static string GetCertificateId(X509Certificate2 certificate)
 1313        {
 1314            string certificateId = certificate.SubjectName.Name;
 1315            if (string.IsNullOrEmpty(certificateId))
 1316            {
 1317                certificateId = certificate.Thumbprint;
 1318            }
 1319
 1320            return certificateId;
 1321        }
 1322
 1323        internal static bool MatchesBuffer(byte[] src, byte[] dst)
 1324        {
 1325            return MatchesBuffer(src, 0, dst, 0);
 1326        }
 1327
 1328        internal static bool MatchesBuffer(byte[] src, int srcOffset, byte[] dst, int dstOffset)
 1329        {
 1330            DiagnosticUtility.DebugAssert(dstOffset >= 0, "Negative dstOffset passed to MatchesBuffer.");
 1331            DiagnosticUtility.DebugAssert(srcOffset >= 0, "Negative srcOffset passed to MatchesBuffer.");
 1332
 1333            // defensive programming
 1334            if ((dstOffset < 0) || (srcOffset < 0))
 1335            {
 1336                return false;
 1337            }
 1338
 1339            if (src == null || srcOffset >= src.Length)
 1340            {
 1341                return false;
 1342            }
 1343
 1344            if (dst == null || dstOffset >= dst.Length)
 1345            {
 1346                return false;
 1347            }
 1348
 1349            if ((src.Length - srcOffset) != (dst.Length - dstOffset))
 1350            {
 1351                return false;
 1352            }
 1353
 1354            for (int i = srcOffset, j = dstOffset; i < src.Length; i++, j++)
 1355            {
 1356                if (src[i] != dst[j])
 1357                {
 1358                    return false;
 1359                }
 1360            }
 1361            return true;
 1362        }
 1363
 1364        internal static string ClaimSetToString(ClaimSet claimSet)
 1365        {
 1366            StringBuilder sb = new StringBuilder();
 1367            sb.AppendLine("ClaimSet [");
 1368            for (int i = 0; i < claimSet.Count; i++)
 1369            {
 1370                Claim claim = claimSet[i];
 1371                if (claim != null)
 1372                {
 1373                    sb.Append("  ");
 1374                    sb.AppendLine(claim.ToString());
 1375                }
 1376            }
 1377            string prefix = "] by ";
 1378            ClaimSet issuer = claimSet;
 1379            do
 1380            {
 1381                issuer = issuer.Issuer;
 1382                sb.AppendFormat("{0}{1}", prefix, issuer == claimSet ? "Self" : (issuer.Count <= 0 ? "Unknown" : issuer[
 1383                prefix = " -> ";
 1384            } while (issuer.Issuer != issuer);
 1385            return sb.ToString();
 1386        }
 1387
 1388        internal static ReadOnlyCollection<IAuthorizationPolicy> CreateAuthorizationPolicies(ClaimSet claimSet)
 1389        {
 1390            return CreateAuthorizationPolicies(claimSet, MaxUtcDateTime);
 1391        }
 1392
 1393        internal static ReadOnlyCollection<IAuthorizationPolicy> CreateAuthorizationPolicies(ClaimSet claimSet, DateTime
 1394        {
 1395            List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1)
 1396            {
 1397                new UnconditionalPolicy(claimSet, expirationTime)
 1398            };
 1399            return policies.AsReadOnly();
 1400        }
 1401
 1402        internal static IIdentity CloneIdentityIfNecessary(IIdentity identity)
 1403        {
 1404            if (identity != null)
 1405            {
 1406                if (identity is WindowsIdentity wid)
 1407                {
 1408                    return CloneWindowsIdentityIfNecessary(wid);
 1409                }
 1410            }
 1411            return identity;
 1412        }
 1413
 1414        internal static ClaimSet CloneClaimSetIfNecessary(ClaimSet claimSet)
 1415        {
 1416            if (claimSet != null)
 1417            {
 1418                if (claimSet is WindowsClaimSet wic)
 1419                {
 1420                    return wic.Clone();
 1421                }
 1422            }
 1423            return claimSet;
 1424        }
 1425
 1426        internal static ReadOnlyCollection<ClaimSet> CloneClaimSetsIfNecessary(ReadOnlyCollection<ClaimSet> claimSets)
 1427        {
 1428            if (claimSets != null)
 1429            {
 1430                bool clone = false;
 1431                for (int i = 0; i < claimSets.Count; ++i)
 1432                {
 1433                    if (claimSets[i] is WindowsClaimSet)
 1434                    {
 1435                        clone = true;
 1436                        break;
 1437                    }
 1438                }
 1439                if (clone)
 1440                {
 1441                    List<ClaimSet> ret = new List<ClaimSet>(claimSets.Count);
 1442                    for (int i = 0; i < claimSets.Count; ++i)
 1443                    {
 1444                        ret.Add(CloneClaimSetIfNecessary(claimSets[i]));
 1445                    }
 1446                    return ret.AsReadOnly();
 1447                }
 1448            }
 1449            return claimSets;
 1450        }
 1451
 1452        internal static void DisposeClaimSetIfNecessary(ClaimSet claimSet)
 1453        {
 1454            if (claimSet != null)
 1455            {
 1456                DisposeIfNecessary(claimSet as WindowsClaimSet);
 1457            }
 1458        }
 1459
 1460        internal static void DisposeClaimSetsIfNecessary(ReadOnlyCollection<ClaimSet> claimSets)
 1461        {
 1462            if (claimSets != null)
 1463            {
 1464                for (int i = 0; i < claimSets.Count; ++i)
 1465                {
 1466                    DisposeIfNecessary(claimSets[i] as WindowsClaimSet);
 1467                }
 1468            }
 1469        }
 1470
 1471        private class SimpleAuthorizationContext : AuthorizationContext
 1472        {
 1473            private SecurityUniqueId _id;
 1474            private readonly UnconditionalPolicy _policy;
 1475            private readonly IDictionary<string, object> _properties;
 1476
 1477            public SimpleAuthorizationContext(IList<IAuthorizationPolicy> authorizationPolicies)
 1478            {
 1479                _policy = (UnconditionalPolicy)authorizationPolicies[0];
 1480                Dictionary<string, object> properties = new Dictionary<string, object>();
 1481                if (_policy.PrimaryIdentity != null && _policy.PrimaryIdentity != AnonymousIdentity)
 1482                {
 1483                    List<IIdentity> identities = new List<IIdentity>
 1484                    {
 1485                        _policy.PrimaryIdentity
 1486                    };
 1487                    properties.Add(Identities, identities);
 1488                }
 1489                // Might need to port ReadOnlyDictionary?
 1490                _properties = properties;
 1491            }
 1492
 1493            public override string Id
 1494            {
 1495                get
 1496                {
 1497                    if (_id == null)
 1498                    {
 1499                        _id = SecurityUniqueId.Create();
 1500                    }
 1501
 1502                    return _id.Value;
 1503                }
 1504            }
 1505            public override ReadOnlyCollection<ClaimSet> ClaimSets { get { return _policy.Issuances; } }
 1506            public override DateTime ExpirationTime { get { return _policy.ExpirationTime; } }
 1507            public override IDictionary<string, object> Properties { get { return _properties; } }
 1508        }
 1509        internal static AuthorizationContext CreateDefaultAuthorizationContext(IList<IAuthorizationPolicy> authorization
 1510        {
 1511            AuthorizationContext authorizationContext;
 1512            // This is faster than Policy evaluation.
 1513            if (authorizationPolicies != null && authorizationPolicies.Count == 1 && authorizationPolicies[0] is Uncondi
 1514            {
 1515                authorizationContext = new SimpleAuthorizationContext(authorizationPolicies);
 1516            }
 1517            // degenerate case
 1518            else if (authorizationPolicies == null || authorizationPolicies.Count <= 0)
 1519            {
 1520                return DefaultAuthorizationContext.Empty;
 1521            }
 1522            else
 1523            {
 1524                // there are some policies, run them until they are all done
 1525                DefaultEvaluationContext evaluationContext = new DefaultEvaluationContext();
 1526                object[] policyState = new object[authorizationPolicies.Count];
 1527                object done = new object();
 1528
 1529                int oldContextCount;
 1530                do
 1531                {
 1532                    oldContextCount = evaluationContext.Generation;
 1533
 1534                    for (int i = 0; i < authorizationPolicies.Count; i++)
 1535                    {
 1536                        if (policyState[i] == done)
 1537                        {
 1538                            continue;
 1539                        }
 1540
 1541                        IAuthorizationPolicy policy = authorizationPolicies[i];
 1542                        if (policy == null)
 1543                        {
 1544                            policyState[i] = done;
 1545                            continue;
 1546                        }
 1547
 1548                        if (policy.Evaluate(evaluationContext, ref policyState[i]))
 1549                        {
 1550                            policyState[i] = done;
 1551
 1552                            /* if (DiagnosticUtility.ShouldTraceVerbose)
 1553                             {
 1554                                 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.AuthorizationPolicyEvaluated,
 1555                                     SR.GetString(SR.AuthorizationPolicyEvaluated, policy.Id));
 1556                             }*/
 1557                        }
 1558                    }
 1559                } while (oldContextCount < evaluationContext.Generation);
 1560
 1561                authorizationContext = new DefaultAuthorizationContext(evaluationContext);
 1562            }
 1563
 1564            /*  if (DiagnosticUtility.ShouldTraceInformation)
 1565              {
 1566                  TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AuthorizationContextCreated,
 1567                      SR.GetString(SR.AuthorizationContextCreated, authorizationContext.Id));
 1568              }*/
 1569
 1570            return authorizationContext;
 1571        }
 1572        public static bool IsRequestSecurityContextIssuance(string actionString)
 1573        {
 1574            if (string.CompareOrdinal(actionString, XD.SecureConversationFeb2005Dictionary
 1575                .RequestSecurityContextIssuance.Value) == 0 ||
 1576                string.CompareOrdinal(actionString, XD.SecureConversationApr2004Dictionary
 1577                .RequestSecurityContextIssuance.Value) == 0)
 1578            {
 1579                return true;
 1580            }
 1581
 1582            return false;
 1583        }
 1584    }
 1585
 1586    internal static class EmptyReadOnlyCollection<T>
 1587    {
 1588        public static ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new List<T>());
 1589    }
 1590
 1591    internal class Sha1CryptoProviderFactory : Microsoft.IdentityModel.Tokens.CryptoProviderFactory
 1592    {
 1593        public Sha1CryptoProviderFactory() : base(new Microsoft.IdentityModel.Tokens.InMemoryCryptoProviderCache(new Mic
 1594        {
 1595        }
 1596
 1597        public Sha1CryptoProviderFactory(Microsoft.IdentityModel.Tokens.ICryptoProvider cryptoProvider)
 1598        {
 1599            CustomCryptoProvider = cryptoProvider;
 1600        }
 1601
 1602        public override Microsoft.IdentityModel.Tokens.SignatureProvider CreateForSigning(Microsoft.IdentityModel.Tokens
 1603        {
 1604            if (algorithm == "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
 1605                return null;
 1606            else
 1607                return base.CreateForSigning(key, algorithm);
 1608        }
 1609
 1610        public override Microsoft.IdentityModel.Tokens.SignatureProvider CreateForVerifying(Microsoft.IdentityModel.Toke
 1611        {
 1612            if (algorithm == "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
 1613            {
 1614                return new RSASha1SignatureProvider(key, algorithm);
 1615            }
 1616            else
 1617                return base.CreateForVerifying(key, algorithm);
 1618        }
 1619
 1620        public override HashAlgorithm CreateHashAlgorithm(string algorithm)
 1621        {
 1622            if (algorithm == "http://www.w3.org/2000/09/xmldsig#sha1")
 1623                return SHA1.Create();
 1624
 1625            return base.CreateHashAlgorithm(algorithm);
 1626        }
 1627
 1628        public override bool IsSupportedAlgorithm(string algorithm)
 1629        {
 1630
 1631            if (algorithm == "http://www.w3.org/2000/09/xmldsig#sha1")
 1632                return true;
 1633            else if (algorithm == "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
 1634                return true;
 1635            else
 1636                return base.IsSupportedAlgorithm(algorithm);
 1637        }
 1638
 1639        public override bool IsSupportedAlgorithm(string algorithm, Microsoft.IdentityModel.Tokens.SecurityKey key)
 1640        {
 1641            if (algorithm == "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
 1642                return true;
 1643            else if (algorithm == "http://www.w3.org/2000/09/xmldsig#sha1")
 1644                return true;
 1645            else
 1646                return base.IsSupportedAlgorithm(algorithm, key);
 1647        }
 1648
 1649        public override void ReleaseHashAlgorithm(HashAlgorithm hashAlgorithm)
 1650        {
 1651            hashAlgorithm.Dispose();
 1652        }
 1653
 1654        public override void ReleaseSignatureProvider(Microsoft.IdentityModel.Tokens.SignatureProvider signatureProvider
 1655        {
 1656            if (CustomCryptoProvider != null)
 1657                CustomCryptoProvider.Release(signatureProvider);
 1658            else
 1659                signatureProvider.Dispose();
 1660        }
 1661    }
 1662
 1663    internal class RSASha1SignatureProvider : Microsoft.IdentityModel.Tokens.SignatureProvider
 1664    {
 1665        private Microsoft.IdentityModel.Tokens.X509SecurityKey _key;
 1666
 1667        public RSASha1SignatureProvider(Microsoft.IdentityModel.Tokens.SecurityKey key, string algorithm) : base(key, al
 1668        {
 1669            _key = key as Microsoft.IdentityModel.Tokens.X509SecurityKey;
 1670        }
 1671
 1672        public override byte[] Sign(byte[] input)
 1673        {
 1674            throw new NotImplementedException();
 1675        }
 1676
 1677        public override bool Verify(byte[] input, byte[] signature)
 1678        {
 1679            RSA rsa = _key.PublicKey as RSA;
 1680            if (rsa == null)
 1681                return false;
 1682
 1683            // TODO: dispose of the hash, use pool
 1684            SHA1 sha1 = SHA1.Create();
 1685            byte[] hash = sha1.ComputeHash(input);
 1686            if (rsa.VerifyHash(hash, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
 1687                return true;
 1688
 1689            return false;
 1690        }
 1691
 1692        protected override void Dispose(bool disposing)
 1693        {
 1694        }
 1695    }
 1696}