static void Main(string[] args) { var cert = X509Util.CreateSelfSignedCertificate(Environment.MachineName); //Register a namespace reservation for everyone in localhost in port 9010 HttpServerApi.ModifyNamespaceReservation(new Uri("https://localhost:9010"), "everyone", HttpServerApiConfigurationAction.AddOrUpdate); //Register the SSL certificate for any address (0.0.0.0) in the port 9010. HttpServerApi.ModifySslCertificateToAddressBinding("0.0.0.0", 9010, cert.GetCertHash(), System.Security.Cryptography.X509Certificates.StoreName.My, HttpServerApiConfigurationAction.AddOrUpdate); }
/// <summary> /// Validates the given certificate. /// </summary> /// <param name="certificate">X.509 Certificate to validate.</param> /// <exception cref="ArgumentNullException">The input parameter 'certificate' is null.</exception> /// <exception cref="SecurityTokenValidationException">X.509 Certificate validation failed.</exception> public override void Validate(X509Certificate2 certificate) { if (certificate == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate"); } X509CertificateChain chain = new X509CertificateChain(this.useMachineContext, (uint)this.chainPolicyOID); if (this.chainPolicy != null) { chain.ChainPolicy = this.chainPolicy; } if (!chain.Build(certificate)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenValidationException( SR.GetString( SR.ID4070, X509Util.GetCertificateId(certificate), GetChainStatusInformation(chain.ChainStatus)))); } }
/// <summary> /// Creates a <see cref="WindowsIdentity"/> associated with a given X509 certificate. /// </summary> /// <param name="x509Certificate">The certificate to use to map to the associated <see cref="WindowsIdentity"/></param> /// <returns></returns> public static WindowsIdentity CertificateLogon(X509Certificate2 x509Certificate) { // for Vista, LsaLogon supporting mapping cert to NTToken if (Environment.OSVersion.Version.Major >= CryptoHelper.WindowsVistaMajorNumber) { return(X509SecurityTokenHandler.KerberosCertificateLogon(x509Certificate)); } else { // Downlevel, S4U over PrincipalName SubjectAltNames string upn = x509Certificate.GetNameInfo(X509NameType.UpnName, false); if (string.IsNullOrEmpty(upn)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4067, X509Util.GetCertificateId(x509Certificate)))); } return(new WindowsIdentity(upn)); } }
/// <summary> /// Load custom configuration from Xml /// </summary> /// <param name="customConfigElements">XmlElement to custom configuration.</param> /// <exception cref="ArgumentNullException">The param 'customConfigElements' is null.</exception> /// <exception cref="InvalidOperationException">Custom configuration specified was invalid.</exception> public override void LoadCustomConfiguration(XmlNodeList customConfigElements) { if (customConfigElements == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("customConfigElements"); } List <XmlElement> configNodes = XmlUtil.GetXmlElements(customConfigElements); bool foundValidConfig = false; bool foundCustomX509Validator = false; X509RevocationMode revocationMode = defaultRevocationMode; X509CertificateValidationMode certificateValidationMode = defaultValidationMode; StoreLocation trustedStoreLocation = defaultStoreLocation; string customValidator = null; foreach (XmlElement customConfigElement in configNodes) { if (!StringComparer.Ordinal.Equals(customConfigElement.LocalName, ConfigurationStrings.X509SecurityTokenHandlerRequirement)) { continue; } if (foundValidConfig) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7026, ConfigurationStrings.X509SecurityTokenHandlerRequirement)); } foreach (XmlAttribute attribute in customConfigElement.Attributes) { if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.MapToWindows)) { mapToWindows = XmlConvert.ToBoolean(attribute.Value.ToLowerInvariant()); } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.X509CertificateValidator)) { customValidator = attribute.Value.ToString(); } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.X509CertificateRevocationMode)) { foundCustomX509Validator = true; string revocationModeString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeNoCheck)) { revocationMode = X509RevocationMode.NoCheck; } else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOffline)) { revocationMode = X509RevocationMode.Offline; } else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOnline)) { revocationMode = X509RevocationMode.Online; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, customConfigElement.LocalName))); } } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.X509CertificateValidationMode)) { foundCustomX509Validator = true; string validationModeString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeChainTrust)) { certificateValidationMode = X509CertificateValidationMode.ChainTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerOrChainTrust)) { certificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerTrust)) { certificateValidationMode = X509CertificateValidationMode.PeerTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeNone)) { certificateValidationMode = X509CertificateValidationMode.None; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeCustom)) { certificateValidationMode = X509CertificateValidationMode.Custom; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, customConfigElement.LocalName))); } } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.X509TrustedStoreLocation)) { foundCustomX509Validator = true; string trustedStoreLocationString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationCurrentUser)) { trustedStoreLocation = StoreLocation.CurrentUser; } else if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationLocalMachine)) { trustedStoreLocation = StoreLocation.LocalMachine; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, customConfigElement.LocalName))); } } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7004, attribute.LocalName, customConfigElement.LocalName))); } } foundValidConfig = true; } if (certificateValidationMode == X509CertificateValidationMode.Custom) { if (String.IsNullOrEmpty(customValidator)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7028)); } Type customValidatorType = Type.GetType(customValidator, true); if (customValidatorType == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.ID7007, customValidatorType)); } certificateValidator = CustomTypeElement.Resolve <X509CertificateValidator>(new CustomTypeElement(customValidatorType)); } else if (foundCustomX509Validator) { certificateValidator = X509Util.CreateCertificateValidator(certificateValidationMode, revocationMode, trustedStoreLocation); } }
/// <summary> /// Validates an <see cref="X509SecurityToken"/>. /// </summary> /// <param name="token">The <see cref="X509SecurityToken"/> to validate.</param> /// <returns>A <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns> /// <exception cref="ArgumentNullException">The parameter 'token' is null.</exception> /// <exception cref="ArgumentException">The token is not assignable from <see cref="X509SecurityToken"/>.</exception> /// <exception cref="InvalidOperationException">Configuration <see cref="SecurityTokenHandlerConfiguration"/>is null.</exception> /// <exception cref="SecurityTokenValidationException">The current <see cref="X509CertificateValidator"/> was unable to validate the certificate in the Token.</exception> /// <exception cref="InvalidOperationException">Configuration.IssuerNameRegistry is null.</exception> /// <exception cref="SecurityTokenException">Configuration.IssuerNameRegistry return null when resolving the issuer of the certificate in the Token.</exception> public override ReadOnlyCollection <ClaimsIdentity> ValidateToken(SecurityToken token) { if (token == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token"); } X509SecurityToken x509Token = token as X509SecurityToken; if (x509Token == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(X509SecurityToken))); } if (this.Configuration == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274)); } try { // Validate the token. try { this.CertificateValidator.Validate(x509Token.Certificate); } catch (SecurityTokenValidationException e) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4257, X509Util.GetCertificateId(x509Token.Certificate)), e)); } if (this.Configuration.IssuerNameRegistry == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4277)); } string issuer = X509Util.GetCertificateIssuerName(x509Token.Certificate, this.Configuration.IssuerNameRegistry); if (String.IsNullOrEmpty(issuer)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4175))); } ClaimsIdentity identity = null; if (!mapToWindows) { identity = new ClaimsIdentity(AuthenticationTypes.X509); // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical. identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509)); } else { WindowsIdentity windowsIdentity; X509WindowsSecurityToken x509WindowsSecurityToken = token as X509WindowsSecurityToken; // if this is the case, then the user has already been mapped to a windows account, just return the identity after adding a couple of claims. if (x509WindowsSecurityToken != null && x509WindowsSecurityToken.WindowsIdentity != null) { // X509WindowsSecurityToken is disposable, make a copy. windowsIdentity = new WindowsIdentity(x509WindowsSecurityToken.WindowsIdentity.Token, x509WindowsSecurityToken.AuthenticationType); } else { // Ensure NT_AUTH chain policy for certificate account mapping if (this.x509NTAuthChainTrustValidator == null) { lock (this.lockObject) { if (this.x509NTAuthChainTrustValidator == null) { this.x509NTAuthChainTrustValidator = new X509NTAuthChainTrustValidator(); } } } this.x509NTAuthChainTrustValidator.Validate(x509Token.Certificate); windowsIdentity = ClaimsHelper.CertificateLogon(x509Token.Certificate); } // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical. windowsIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509)); identity = windowsIdentity; } if (this.Configuration.SaveBootstrapContext) { identity.BootstrapContext = new BootstrapContext(token, this); } identity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.UtcNow, DateTimeFormats.Generated), ClaimValueTypes.DateTime)); identity.AddClaims(X509Util.GetClaimsFromCertificate(x509Token.Certificate, issuer)); this.TraceTokenValidationSuccess(token); List <ClaimsIdentity> identities = new List <ClaimsIdentity>(1); identities.Add(identity); return(identities.AsReadOnly()); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } this.TraceTokenValidationFailure(token, e.Message); throw e; } }
/// <summary> /// Creates an instance of <see cref="SamlSecurityTokenRequirement"/> /// <param name="element">The XmlElement from which the instance is to be loaded.</param> /// </summary> public SamlSecurityTokenRequirement(XmlElement element) { if (element == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); } if (element.LocalName != ConfigurationStrings.SamlSecurityTokenRequirement) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7000, ConfigurationStrings.SamlSecurityTokenRequirement, element.LocalName)); } bool foundCustomX509Validator = false; X509RevocationMode revocationMode = DefaultRevocationMode; X509CertificateValidationMode certificateValidationMode = DefaultValidationMode; StoreLocation trustedStoreLocation = DefaultStoreLocation; string customValidator = null; foreach (XmlAttribute attribute in element.Attributes) { if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.MapToWindows)) { bool outMapToWindows = false; if (!bool.TryParse(attribute.Value, out outMapToWindows)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7022, attribute.Value)); } this.MapToWindows = outMapToWindows; } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateValidator)) { customValidator = attribute.Value.ToString(); } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateRevocationMode)) { foundCustomX509Validator = true; string revocationModeString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeNoCheck)) { revocationMode = X509RevocationMode.NoCheck; } else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOffline)) { revocationMode = X509RevocationMode.Offline; } else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOnline)) { revocationMode = X509RevocationMode.Online; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName))); } } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateValidationMode)) { foundCustomX509Validator = true; string validationModeString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeChainTrust)) { certificateValidationMode = X509CertificateValidationMode.ChainTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerOrChainTrust)) { certificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerTrust)) { certificateValidationMode = X509CertificateValidationMode.PeerTrust; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeNone)) { certificateValidationMode = X509CertificateValidationMode.None; } else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeCustom)) { certificateValidationMode = X509CertificateValidationMode.Custom; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName))); } } else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateTrustedStoreLocation)) { foundCustomX509Validator = true; string trustedStoreLocationString = attribute.Value.ToString(); if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationCurrentUser)) { trustedStoreLocation = StoreLocation.CurrentUser; } else if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationLocalMachine)) { trustedStoreLocation = StoreLocation.LocalMachine; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName))); } } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7004, attribute.LocalName, element.LocalName))); } } List <XmlElement> configElements = XmlUtil.GetXmlElements(element.ChildNodes); foreach (XmlElement childElement in configElements) { if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.NameClaimType)) { if (childElement.Attributes.Count != 1 || !StringComparer.Ordinal.Equals(childElement.Attributes[0].LocalName, ConfigurationStrings.Value)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7001, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", element.LocalName, childElement.LocalName), ConfigurationStrings.Value)); } this.NameClaimType = childElement.Attributes[0].Value; } else if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.RoleClaimType)) { if (childElement.Attributes.Count != 1 || !StringComparer.Ordinal.Equals(childElement.Attributes[0].LocalName, ConfigurationStrings.Value)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7001, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", element.LocalName, childElement.LocalName), ConfigurationStrings.Value)); } this.RoleClaimType = childElement.Attributes[0].Value; } else { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7002, childElement.LocalName, ConfigurationStrings.SamlSecurityTokenRequirement)); } } if (certificateValidationMode == X509CertificateValidationMode.Custom) { if (string.IsNullOrEmpty(customValidator)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7028)); } Type customValidatorType = Type.GetType(customValidator, true); if (customValidatorType == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.ID7007, customValidatorType)); } _certificateValidator = CustomTypeElement.Resolve <X509CertificateValidator>(new CustomTypeElement(customValidatorType)); } else if (foundCustomX509Validator) { _certificateValidator = X509Util.CreateCertificateValidator(certificateValidationMode, revocationMode, trustedStoreLocation); } }
/// <summary> /// Updates properties in the <see cref="SecurityTokenHandlerConfiguration"/> objects for the /// <see cref="SecurityTokenHandlerCollection"/> objects contained in /// <see cref="IdentityConfiguration.SecurityTokenHandlerCollectionManager"/> to be consistent with the property /// values on this <see cref="IdentityConfiguration"/> instance. /// </summary> /// <remarks> /// This method should be invoked prior to using these token handlers /// for token processing. /// </remarks> /// <exception cref="InvalidOperationException">If this method is invoked more than once.</exception> public virtual void Initialize() { if (this.IsInitialized) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7009)); } SecurityTokenHandlerCollection defaultCollection = this.SecurityTokenHandlers; if (!object.ReferenceEquals(_serviceHandlerConfiguration, defaultCollection.Configuration)) { // // If someone has created their own new STHConfig and set it as default, leave that config alone. // TraceUtility.TraceString(TraceEventType.Information, SR.GetString(SR.ID4283)); this.IsInitialized = true; return; } // Update the ServiceTokenResolver of the default TokenHandlerCollection's configuration, if serviceCertificate is set. if (this.ServiceCertificate != null) { SecurityTokenResolver serviceCertificateResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(new ReadOnlyCollection <SecurityToken>( new SecurityToken[] { new X509SecurityToken(this.ServiceCertificate) }), false); SecurityTokenResolver tokenResolver = this.SecurityTokenHandlers.Configuration.ServiceTokenResolver; if ((tokenResolver != null) && (tokenResolver != EmptySecurityTokenResolver.Instance)) { this.SecurityTokenHandlers.Configuration.ServiceTokenResolver = new AggregateTokenResolver(new SecurityTokenResolver[] { serviceCertificateResolver, tokenResolver }); } else { this.SecurityTokenHandlers.Configuration.ServiceTokenResolver = serviceCertificateResolver; } } SecurityTokenResolver configuredIssuerTokenResolver = this.IssuerTokenResolver; if (this.IssuerTokenResolver == SecurityTokenHandlerConfiguration.DefaultIssuerTokenResolver) { // // Add the known certificates from WCF's ServiceCredentials in front of // the default issuer token resolver. // if (this.KnownIssuerCertificates != null) { int count = this.KnownIssuerCertificates.Count; if (count > 0) { SecurityToken[] tokens = new SecurityToken[count]; for (int i = 0; i < count; i++) { tokens[i] = new X509SecurityToken(this.KnownIssuerCertificates[i]); } SecurityTokenResolver knownCertificateTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(new ReadOnlyCollection <SecurityToken>(tokens), false); this.IssuerTokenResolver = new AggregateTokenResolver(new SecurityTokenResolver[] { knownCertificateTokenResolver, configuredIssuerTokenResolver }); } } } if (this.CertificateValidationMode != X509CertificateValidationMode.Custom) { defaultCollection.Configuration.CertificateValidator = X509Util.CreateCertificateValidator(defaultCollection.Configuration.CertificateValidationMode, defaultCollection.Configuration.RevocationMode, defaultCollection.Configuration.TrustedStoreLocation); } else if (object.ReferenceEquals(defaultCollection.Configuration.CertificateValidator, SecurityTokenHandlerConfiguration.DefaultCertificateValidator)) { // // If the mode is custom but the validator or still default, something has gone wrong. // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4280))); } this.IsInitialized = true; }