public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { if (reference == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(reference)); } identity = reference.Identity; if (identity == null) { identity = TryCreateDnsIdentity(reference); } if (identity == null) { SecurityTraceRecordHelper.TraceIdentityDeterminationFailure(reference, typeof(DefaultIdentityVerifier)); return(false); } else { SecurityTraceRecordHelper.TraceIdentityDeterminationSuccess(reference, identity, typeof(DefaultIdentityVerifier)); return(true); } }
protected virtual void OnVerifyIncomingMessageFailure(Message message, Exception exception) { SecurityTraceRecordHelper.TraceVerifyIncomingMessageFailure(this, message); if ((PerformanceCounters.PerformanceCountersEnabled && (null != this.factory.ListenUri)) && (((exception.GetType() == typeof(MessageSecurityException)) || exception.GetType().IsSubclassOf(typeof(MessageSecurityException))) || ((exception.GetType() == typeof(SecurityTokenException)) || exception.GetType().IsSubclassOf(typeof(SecurityTokenException))))) { PerformanceCounters.AuthenticationFailed(message, this.factory.ListenUri); } if (AuditLevel.Failure == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Failure)) { try { string identityNamesFromContext; SecurityMessageProperty security = message.Properties.Security; if ((security != null) && (security.ServiceSecurityContext != null)) { identityNamesFromContext = System.ServiceModel.Security.SecurityUtils.GetIdentityNamesFromContext(security.ServiceSecurityContext.AuthorizationContext); } else { identityNamesFromContext = System.ServiceModel.Security.SecurityUtils.AnonymousIdentity.Name; } SecurityAuditHelper.WriteMessageAuthenticationFailureEvent(this.factory.AuditLogLocation, this.factory.SuppressAuditFailure, message, message.Headers.To, message.Headers.Action, identityNamesFromContext, exception); } catch (Exception exception2) { if (Fx.IsFatal(exception2)) { throw; } DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Error); } } }
public SessionOperationAsyncResult(SecuritySessionSecurityTokenProvider requestor, SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.requestor = requestor; this.operation = operation; this.target = target; this.via = via; this.currentToken = currentToken; this.timeoutHelper = new TimeoutHelper(timeout); SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken); bool flag = false; try { flag = this.StartOperation(); } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } this.OnOperationFailure(exception); throw; } if (flag) { this.OnOperationComplete(); base.Complete(true); } }
protected override ArrayList OnQuotaReached(Hashtable cacheTable) { if (!this.replaceOldestEntries) { SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, 0); return(base.OnQuotaReached(cacheTable)); } else { List <SecurityContextSecurityToken> tokens = new List <SecurityContextSecurityToken>(cacheTable.Count); foreach (IExpirableItem value in cacheTable.Values) { SecurityContextSecurityToken token = (SecurityContextSecurityToken)ExtractItem(value); tokens.Add(token); } tokens.Sort(sctEffectiveTimeComparer); int pruningAmount = (int)(((double)this.Capacity) * pruningFactor); pruningAmount = pruningAmount <= 0 ? this.Capacity : pruningAmount; ArrayList keys = new ArrayList(pruningAmount); for (int i = 0; i < pruningAmount; ++i) { keys.Add(GetHashKey(tokens[i].ContextId, tokens[i].KeyGeneration)); OnRemove(tokens[i]); } SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, pruningAmount); return(keys); } }
protected override ArrayList OnQuotaReached(Hashtable cacheTable) { if (!this.replaceOldestEntries) { SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(base.Capacity, 0); return(base.OnQuotaReached(cacheTable)); } List <SecurityContextSecurityToken> list = new List <SecurityContextSecurityToken>(cacheTable.Count); foreach (TimeBoundedCache.IExpirableItem item in cacheTable.Values) { SecurityContextSecurityToken token = (SecurityContextSecurityToken)base.ExtractItem(item); list.Add(token); } list.Sort(sctEffectiveTimeComparer); int capacity = (int)(base.Capacity * pruningFactor); capacity = (capacity <= 0) ? base.Capacity : capacity; ArrayList list2 = new ArrayList(capacity); for (int i = 0; i < capacity; i++) { list2.Add(this.GetHashKey(list[i].ContextId, list[i].KeyGeneration)); this.OnRemove(list[i]); } SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(base.Capacity, capacity); return(list2); }
protected SecurityToken EndNegotiation(IAsyncResult result) { SecurityToken serviceToken = SecurityNegotiationAsyncResult <T> .End(result); SecurityTraceRecordHelper.TraceEndSecurityNegotiation <T>((IssuanceTokenProviderBase <T>) this, serviceToken, this.targetAddress); return(serviceToken); }
public SessionOperationAsyncResult(SecuritySessionSecurityTokenProvider requestor, SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.requestor = requestor; this.operation = operation; this.target = target; this.via = via; this.currentToken = currentToken; this.timeoutHelper = new TimeoutHelper(timeout); SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken); bool completeSelf = false; try { completeSelf = this.StartOperation(); } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { if (Fx.IsFatal(e)) { throw; } this.OnOperationFailure(e); throw; } if (completeSelf) { this.OnOperationComplete(); Complete(true); } }
internal SecurityIdentifier GetUpnSid() { if (!this.hasUpnSidBeenComputed) { lock (this.thisLock) { string resource = (string)base.IdentityClaim.Resource; if (!this.hasUpnSidBeenComputed) { try { NTAccount account = new NTAccount(resource); this.upnSid = account.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier; } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } if (exception is NullReferenceException) { throw; } SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(resource, exception); } finally { this.hasUpnSidBeenComputed = true; } } } } return(this.upnSid); }
protected SecurityToken EndNegotiation(IAsyncResult result) { SecurityToken token = SecurityNegotiationAsyncResult.End(result); SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, token, this.targetAddress); return(token); }
public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { if (identity == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity"); } if (authContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authContext"); } for (int i = 0; i < authContext.ClaimSets.Count; i++) { ClaimSet claimSet = authContext.ClaimSets[i]; if (claimSet.ContainsClaim(identity.IdentityClaim)) { SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, identity.IdentityClaim, base.GetType()); return(true); } string expectedSpn = null; if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) { expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", new object[] { (string)identity.IdentityClaim.Resource }); Claim claim = this.CheckDnsEquivalence(claimSet, expectedSpn); if (claim != null) { SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, claim, base.GetType()); return(true); } } SecurityIdentifier identitySid = null; if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType)) { identitySid = this.GetSecurityIdentifier(identity.IdentityClaim); } else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType)) { identitySid = ((UpnEndpointIdentity)identity).GetUpnSid(); } else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType)) { identitySid = ((SpnEndpointIdentity)identity).GetSpnSid(); } else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) { identitySid = new SpnEndpointIdentity(expectedSpn).GetSpnSid(); } if (identitySid != null) { Claim claim2 = this.CheckSidEquivalence(identitySid, claimSet); if (claim2 != null) { SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, claim2, base.GetType()); return(true); } } } SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, base.GetType()); return(false); }
protected virtual void OnIncomingMessageVerified(Message verifiedMessage) { SecurityTraceRecordHelper.TraceIncomingMessageVerified(this, verifiedMessage); if (AuditLevel.Success == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Success)) { SecurityAuditHelper.WriteMessageAuthenticationSuccessEvent(this.factory.AuditLogLocation, this.factory.SuppressAuditFailure, verifiedMessage, verifiedMessage.Headers.To, verifiedMessage.Headers.Action, System.ServiceModel.Security.SecurityUtils.GetIdentityNamesFromContext(verifiedMessage.Properties.Security.ServiceSecurityContext.AuthorizationContext)); } }
void OnOperationFailure(SecuritySessionOperation operation, EndpointAddress target, SecurityToken currentToken, Exception e, IChannel channel) { SecurityTraceRecordHelper.TraceSecuritySessionOperationFailure(operation, target, currentToken, e); if (channel != null) { channel.Abort(); } }
// negotiation failure methods Message HandleNegotiationException(Message request, Exception e) { SecurityTraceRecordHelper.TraceServiceSecurityNegotiationFailure <T>( EventTraceActivityHelper.TryExtractActivity(request), this, e); return(CreateFault(request, e)); }
private GenericXmlSecurityToken DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout) { GenericXmlSecurityToken token2; if (target == null) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("target"); } if ((operation == SecuritySessionOperation.Renew) && (currentToken == null)) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("currentToken"); } IRequestChannel channel = null; try { object obj2; GenericXmlSecurityToken token; SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken); channel = this.CreateChannel(operation, target, via); TimeoutHelper helper = new TimeoutHelper(timeout); channel.Open(helper.RemainingTime()); using (Message message = this.CreateRequest(operation, target, currentToken, out obj2)) { TraceUtility.ProcessOutgoingMessage(message); using (Message message2 = channel.Request(message, helper.RemainingTime())) { if (message2 == null) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(System.ServiceModel.SR.GetString("FailToRecieveReplyFromNegotiation"))); } TraceUtility.ProcessIncomingMessage(message2); ThrowIfFault(message2, this.targetAddress); token = this.ProcessReply(message2, operation, obj2); this.ValidateKeySize(token); } } channel.Close(helper.RemainingTime()); this.OnOperationSuccess(operation, target, token, currentToken); token2 = token; } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } if (exception is TimeoutException) { exception = new TimeoutException(System.ServiceModel.SR.GetString("ClientSecuritySessionRequestTimeout", new object[] { timeout }), exception); } this.OnOperationFailure(operation, target, currentToken, exception, channel); throw; } return(token2); }
protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state) { base.CommunicationObject.ThrowIfClosedOrNotOpen(); lock (this.ThisLock) { SecurityToken currentServiceToken = this.GetCurrentServiceToken(); if (currentServiceToken != null) { SecurityTraceRecordHelper.TraceUsingCachedServiceToken <T>((IssuanceTokenProviderBase <T>) this, currentServiceToken, this.targetAddress); return(new CompletedAsyncResult <SecurityToken>(currentServiceToken, callback, state)); } return(this.BeginNegotiation(timeout, callback, state)); } }
protected override ReadOnlyCollection <IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation) { WindowsSspiNegotiation windowsNegotiation = (WindowsSspiNegotiation)sspiNegotiation; if (!windowsNegotiation.IsValidContext) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(System.ServiceModel.SR.GetString("InvalidSspiNegotiation"))); } if (this.AuthenticateServer && !windowsNegotiation.IsMutualAuthFlag) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(System.ServiceModel.SR.GetString("CannotAuthenticateServer"))); } SecurityTraceRecordHelper.TraceClientSpnego(windowsNegotiation); return(System.ServiceModel.Security.SecurityUtils.CreatePrincipalNameAuthorizationPolicies(windowsNegotiation.ServicePrincipalName)); }
protected override SecurityToken GetTokenCore(TimeSpan timeout) { SecurityToken currentServiceToken; base.CommunicationObject.ThrowIfClosedOrNotOpen(); lock (this.ThisLock) { currentServiceToken = this.GetCurrentServiceToken(); if (currentServiceToken != null) { SecurityTraceRecordHelper.TraceUsingCachedServiceToken <T>((IssuanceTokenProviderBase <T>) this, currentServiceToken, this.targetAddress); } } if (currentServiceToken == null) { currentServiceToken = this.DoNegotiation(timeout); } return(currentServiceToken); }
private void EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, string errorString) { EndpointIdentity identity; if (authorizationContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext"); } if (!this.TryGetIdentity(serviceReference, out identity)) { SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authorizationContext, base.GetType()); throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(System.ServiceModel.SR.GetString(errorString, new object[] { identity, serviceReference }))); } if (!this.CheckAccess(identity, authorizationContext)) { Exception exception = this.CreateIdentityCheckException(identity, authorizationContext, errorString, serviceReference); throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(exception); } }
protected override SecurityToken GetTokenCore(TimeSpan timeout) { this.CommunicationObject.ThrowIfClosedOrNotOpen(); SecurityToken result; lock (ThisLock) { result = GetCurrentServiceToken(); if (result != null) { SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, result, this.targetAddress); } } if (result == null) { result = DoNegotiation(timeout); } return(result); }
protected virtual void OnVerifyIncomingMessageFailure(Message message, Exception exception) { SecurityTraceRecordHelper.TraceVerifyIncomingMessageFailure(this, message); if (PerformanceCounters.PerformanceCountersEnabled && null != this.factory.ListenUri) //service side { if ((exception.GetType() == typeof(MessageSecurityException) || exception.GetType().IsSubclassOf(typeof(MessageSecurityException))) || (exception.GetType() == typeof(SecurityTokenException) || exception.GetType().IsSubclassOf(typeof(SecurityTokenException)))) { PerformanceCounters.AuthenticationFailed(message, this.factory.ListenUri); } } if (AuditLevel.Failure == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Failure)) { try { SecurityMessageProperty security = message.Properties.Security; string primaryIdentity; if (security != null && security.ServiceSecurityContext != null) { primaryIdentity = SecurityUtils.GetIdentityNamesFromContext(security.ServiceSecurityContext.AuthorizationContext); } else { primaryIdentity = SecurityUtils.AnonymousIdentity.Name; } SecurityAuditHelper.WriteMessageAuthenticationFailureEvent(this.factory.AuditLogLocation, this.factory.SuppressAuditFailure, message, message.Headers.To, message.Headers.Action, primaryIdentity, exception); } #pragma warning suppress 56500 catch (Exception auditException) { if (Fx.IsFatal(auditException)) { throw; } DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error); } } }
protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state) { this.CommunicationObject.ThrowIfClosedOrNotOpen(); IAsyncResult asyncResult; lock (ThisLock) { SecurityToken token = GetCurrentServiceToken(); if (token != null) { SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, token, this.targetAddress); asyncResult = new CompletedAsyncResult <SecurityToken>(token, callback, state); } else { asyncResult = BeginNegotiation(timeout, callback, state); } } return(asyncResult); }
internal SecurityIdentifier GetUpnSid() { Fx.Assert(ClaimTypes.Upn.Equals(this.IdentityClaim.ClaimType), ""); if (!hasUpnSidBeenComputed) { lock (thisLock) { string upn = (string)this.IdentityClaim.Resource; if (!hasUpnSidBeenComputed) { try { NTAccount userAccount = new NTAccount(upn); this.upnSid = userAccount.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier; } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { // Always immediately rethrow fatal exceptions. if (Fx.IsFatal(e)) { throw; } if (e is NullReferenceException) { throw; } SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(upn, e); } finally { hasUpnSidBeenComputed = true; } } } } return(this.upnSid); }
private void EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, String errorString) { if (authorizationContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext"); } EndpointIdentity identity; if (!TryGetIdentity(serviceReference, out identity)) { SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authorizationContext, this.GetType()); throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(string.Format(errorString, identity, serviceReference))); } else { if (!CheckAccess(identity, authorizationContext)) { // CheckAccess performs a Trace on failure, no need to do it twice Exception e = CreateIdentityCheckException(identity, authorizationContext, errorString, serviceReference); throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(e); } } }
protected override ReadOnlyCollection <IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation) { WindowsSspiNegotiation windowsNegotiation = (WindowsSspiNegotiation)sspiNegotiation; if (!windowsNegotiation.IsValidContext) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(System.ServiceModel.SR.GetString("InvalidSspiNegotiation"))); } SecurityTraceRecordHelper.TraceServiceSpnego(windowsNegotiation); if (base.IsClientAnonymous) { return(System.ServiceModel.Security.EmptyReadOnlyCollection <IAuthorizationPolicy> .Instance); } using (System.IdentityModel.SafeCloseHandle handle = windowsNegotiation.GetContextToken()) { WindowsIdentity identity = new WindowsIdentity(handle.DangerousGetHandle(), windowsNegotiation.ProtocolName); System.ServiceModel.Security.SecurityUtils.ValidateAnonymityConstraint(identity, this.AllowUnauthenticatedCallers); List <IAuthorizationPolicy> list = new List <IAuthorizationPolicy>(1); WindowsClaimSet issuance = new WindowsClaimSet(identity, windowsNegotiation.ProtocolName, this.extractGroupsForWindowsAccounts, false); list.Add(new UnconditionalPolicy(issuance, TimeoutHelper.Add(DateTime.UtcNow, base.ServiceTokenLifetime))); return(list.AsReadOnly()); } }
internal SecurityIdentifier GetSpnSid() { Fx.Assert(ClaimTypes.Spn.Equals(this.IdentityClaim.ClaimType) || ClaimTypes.Dns.Equals(this.IdentityClaim.ClaimType), ""); if (!hasSpnSidBeenComputed) { lock (thisLock) { if (!hasSpnSidBeenComputed) { string spn = null; try { if (ClaimTypes.Dns.Equals(this.IdentityClaim.ClaimType)) { spn = "host/" + (string)this.IdentityClaim.Resource; } else { spn = (string)this.IdentityClaim.Resource; } // canonicalize SPN for use in LDAP filter following RFC 1960: if (spn != null) { spn = spn.Replace("*", @"\*").Replace("(", @"\(").Replace(")", @"\)"); } DirectoryEntry de = GetDirectoryEntry(); using (DirectorySearcher searcher = new DirectorySearcher(de)) { searcher.CacheResults = true; searcher.ClientTimeout = SpnLookupTime; searcher.Filter = "(&(objectCategory=Computer)(objectClass=computer)(servicePrincipalName=" + spn + "))"; searcher.PropertiesToLoad.Add("objectSid"); SearchResult result = searcher.FindOne(); if (result != null) { byte[] sidBinaryForm = (byte[])result.Properties["objectSid"][0]; this.spnSid = new SecurityIdentifier(sidBinaryForm, 0); } else { SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, null); } } } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { // Always immediately rethrow fatal exceptions. if (Fx.IsFatal(e)) { throw; } if (e is NullReferenceException || e is SEHException) { throw; } SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, e); } finally { hasSpnSidBeenComputed = true; } } } } return(this.spnSid); }
public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { //EventTraceActivity eventTraceActivity = null; if (identity == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(identity)); } if (authContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(authContext)); } //if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled) //{ // eventTraceActivity = EventTraceActivityHelper.TryExtractActivity((OperationContext.Current != null) ? OperationContext.Current.IncomingMessage : null); //} for (int i = 0; i < authContext.ClaimSets.Count; ++i) { ClaimSet claimSet = authContext.ClaimSets[i]; if (claimSet.ContainsClaim(identity.IdentityClaim)) { //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, identity.IdentityClaim, this.GetType()); return(true); } // try Claim equivalence string expectedSpn = null; if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) { expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource); Claim claim = CheckDnsEquivalence(claimSet, expectedSpn); if (claim != null) { //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType()); return(true); } } // Allow a Sid claim to support UPN, and SPN identities SecurityIdentifier identitySid = null; if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType)) { identitySid = GetSecurityIdentifier(identity.IdentityClaim); } else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType)) { identitySid = ((UpnEndpointIdentity)identity).GetUpnSid(); } else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType)) { identitySid = ((SpnEndpointIdentity)identity).GetSpnSid(); } else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) { identitySid = new SpnEndpointIdentity(expectedSpn).GetSpnSid(); } if (identitySid != null) { Claim claim = CheckSidEquivalence(identitySid, claimSet); if (claim != null) { //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType()); return(true); } } } SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, GetType()); //if (TD.SecurityIdentityVerificationFailureIsEnabled()) //{ // TD.SecurityIdentityVerificationFailure(eventTraceActivity); //} return(false); }
public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { EventTraceActivity eventTraceActivity = null; if (identity == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity"); } if (authContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authContext"); } if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled) { eventTraceActivity = EventTraceActivityHelper.TryExtractActivity((OperationContext.Current != null) ? OperationContext.Current.IncomingMessage : null); } for (int i = 0; i < authContext.ClaimSets.Count; ++i) { ClaimSet claimSet = authContext.ClaimSets[i]; if (claimSet.ContainsClaim(identity.IdentityClaim)) { SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, identity.IdentityClaim, this.GetType()); return(true); } // try Claim equivalence string expectedSpn = null; if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) { expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource); Claim claim = CheckDnsEquivalence(claimSet, expectedSpn); if (claim != null) { SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType()); return(true); } } // Allow a Sid claim to support UPN, and SPN identities // SID claims not available yet //SecurityIdentifier identitySid = null; //if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType)) //{ // throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Sid"); //} //else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType)) //{ // throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Upn"); //} //else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType)) //{ // throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Spn"); //} //else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) //{ // throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Dns"); //} //if (identitySid != null) //{ // Claim claim = CheckSidEquivalence(identitySid, claimSet); // if (claim != null) // { // SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType()); // return true; // } //} } SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, this.GetType()); if (WcfEventSource.Instance.SecurityIdentityVerificationFailureIsEnabled()) { WcfEventSource.Instance.SecurityIdentityVerificationFailure(eventTraceActivity); } return(false); }
protected override async Task <Stream> OnInitiateUpgradeAsync(Stream stream, OutWrapper <SecurityMessageProperty> remoteSecurityWrapper) { if (WcfEventSource.Instance.SslOnInitiateUpgradeIsEnabled()) { WcfEventSource.Instance.SslOnInitiateUpgrade(); } // There is currently no way to convert a .Net X509Certificate2 to a UWP Certificate. The client certificate // needs to be provided by looking it up in the certificate store. E.g. // // factory.Credentials.ClientCertificate.SetCertificate( // StoreLocation.CurrentUser, // StoreName.My, // X509FindType.FindByThumbprint, // clientCertThumb); // // The certificate is retrieved using .Net api's and UWP api's. An artifical X509Extension is used to attach the // UWP certificate to the .Net X509Certificate2. This is then retrieved at the point of usage to use with UWP // networking api's. Certificate clientCertificate = null; if (_clientToken != null) { foreach (var extension in _clientToken.Certificate.Extensions) { var attachmentExtension = extension as X509CertificateInitiatorClientCredential.X509UwpCertificateAttachmentExtension; if (attachmentExtension != null && attachmentExtension.AttachedCertificate != null) { clientCertificate = attachmentExtension.AttachedCertificate; break; } } Contract.Assert(clientCertificate != null, "Missing UWP Certificate as an attachment to X509Certificate2"); } try { // Fetch the underlying raw transport object. For UWP, this will be a StreamSocket var connectionStream = stream as ConnectionStream; Contract.Assert(connectionStream != null, "stream is either null or not a ConnectionStream"); var rtStreamSocket = connectionStream.Connection.GetCoreTransport() as StreamSocket; Contract.Assert(rtStreamSocket != null, "Core transport is either null or not a StreamSocket"); rtStreamSocket.Control.ClientCertificate = clientCertificate; // On CoreClr, we use SslStream which calls a callback with any problems with the server certificate, which // returns whether to accept the certificate or not. With SocketStream in UWP, any custom validation needs to // happen after the connection has successfully negotiated. Some certificate errors need to be set to be ignored // to allow the connection to be established so we can retrieve the server certificate and choose whether to // accept the server certificate or not. rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired); rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName); rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain); rtStreamSocket.Control.IgnorableServerCertificateErrors.Add( ChainValidationResult.RevocationInformationMissing); rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure); // SocketStream doesn't take a bitwise field of accepted protocols, but instead accepts a value specifying the highest // protocol that can be negotiated. A check is made for each of the protocols in order to see if they've been requested // by the binding and set the protection level to the UWP equivalent. This will have the effect of protectionLevel being // set to the most secure protocol that was specified by client code. After the connection is established, if a protocol // was negotiated which the binding didn't request, the connection needs to be aborted. This could happen for example if // the requested SslProtocols was SslProtocols.Tls11 | SslProtocols.Tls12 and the server only supported SSL3 | Tls10. In // this case, SocketProtectionLevel would be set to SocketProtectionLevel.Tls12, which would mean Tls10, Tls11 and Tls12 // are all acceptable protocols to negotiate. As the server is offering SSL3 | Tls10, the connection would be successfully // negotiated using Tls10 which isn't allowed according to the binding configuration. SocketProtectionLevel protectionLevel = SocketProtectionLevel.PlainSocket; if ((_parent.SslProtocols & SslProtocols.Tls) != SslProtocols.None) { protectionLevel = SocketProtectionLevel.Tls10; } if ((_parent.SslProtocols & SslProtocols.Tls11) != SslProtocols.None) { protectionLevel = SocketProtectionLevel.Tls11; } if ((_parent.SslProtocols & SslProtocols.Tls12) != SslProtocols.None) { protectionLevel = SocketProtectionLevel.Tls12; } // With SslStream, the hostname provided in the server certificate is provided to the client and verified in the callback. // With UWP StreamSocket, the hostname needs to be provided to the call to UpgradeToSslAsync. The code to fetch the identity // lives in the callback for CoreClr but needs to be pulled into this method for UWP. EndpointAddress remoteAddress = RemoteAddress; if (remoteAddress.Identity == null && remoteAddress.Uri != Via) { remoteAddress = new EndpointAddress(Via); } EndpointIdentity identity; if (!_parent.IdentityVerifier.TryGetIdentity(remoteAddress, out identity)) { SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity: identity, authContext: null, identityVerifier: GetType()); throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning( new MessageSecurityException(SR.Format(SR.IdentityCheckFailedForOutgoingMessage, identity, remoteAddress))); } Contract.Assert(identity.IdentityClaim.ClaimType == ClaimTypes.Dns); string dnsHostName = identity.IdentityClaim.Resource as string; // This is the actual call to negotiate an SSL connection await rtStreamSocket.UpgradeToSslAsync(protectionLevel, new HostName(dnsHostName)).AsTask(); // Verify that we didn't negotiate a protocol lower than the binding configuration specified. No need to check Tls12 // as it will only be negotiated if Tls12 was actually specified. var negotiatedProtectionLevel = rtStreamSocket.Information.ProtectionLevel; if ((negotiatedProtectionLevel == SocketProtectionLevel.Tls11 && (_parent.SslProtocols & SslProtocols.Tls11) == SslProtocols.None) || (negotiatedProtectionLevel == SocketProtectionLevel.Tls10 && (_parent.SslProtocols & SslProtocols.Tls) == SslProtocols.None)) { // Need to dispose StreamSocket as normally SslStream wouldn't end up in a usable state in this situation. As // post-upgrade validation is required in UWP, the connection needs to be Dispose'd to ensure it isn't used. rtStreamSocket.Dispose(); throw new SecurityNegotiationException(SR.Format(SR.SSLProtocolNegotiationFailed, _parent.SslProtocols, negotiatedProtectionLevel)); } X509Certificate2 serverCertificate = null; X509Certificate2[] chainCertificates = null; X509Chain chain = null; try { // Convert the UWP Certificate object to a .Net X509Certificate2. byte[] serverCertificateBlob = rtStreamSocket.Information.ServerCertificate.GetCertificateBlob().ToArray(); serverCertificate = new X509Certificate2(serverCertificateBlob); // The chain building and validation logic is done by SslStream in CoreClr. This section of code is based // on the SslStream implementation to try to maintain behavior parity. chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; var serverIntermediateCertificates = rtStreamSocket.Information.ServerIntermediateCertificates; chainCertificates = new X509Certificate2[serverIntermediateCertificates.Count]; for (int i = 0; i < chainCertificates.Length; i++) { chainCertificates[i] = new X509Certificate2(serverIntermediateCertificates[i].GetCertificateBlob().ToArray()); } chain.ChainPolicy.ExtraStore.AddRange(chainCertificates); chain.Build(serverCertificate); SslPolicyErrors policyErrors = SslPolicyErrors.None; foreach (var serverCertificateError in rtStreamSocket.Information.ServerCertificateErrors) { if (serverCertificateError == ChainValidationResult.InvalidName) { policyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch; continue; } if (serverCertificateError == ChainValidationResult.IncompleteChain) { policyErrors |= SslPolicyErrors.RemoteCertificateChainErrors; } } X509ChainStatus[] chainStatusArray = chain.ChainStatus; if (chainStatusArray != null && chainStatusArray.Length != 0) { policyErrors |= SslPolicyErrors.RemoteCertificateChainErrors; } if (!ValidateRemoteCertificate(this, serverCertificate, chain, policyErrors)) { // Need to dispose StreamSocket as normally SslStream wouldn't end up in a usable state in this situation. As // post-upgrade validation is required in UWP, the connection needs to be Dispose'd to ensure it isn't used. rtStreamSocket.Dispose(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityNegotiationException(SR.ssl_io_cert_validation)); } } finally { serverCertificate?.Dispose(); chain?.Dispose(); if (chainCertificates != null) { foreach (var chainCert in chainCertificates) { chainCert?.Dispose(); } } } } catch (SecurityTokenValidationException tokenValidationException) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityNegotiationException(tokenValidationException.Message, tokenValidationException)); } catch (IOException ioException) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException( SR.Format(SR.NegotiationFailedIO, ioException.Message), ioException)); } catch (Exception exception) { // In NET Native the WinRT API's can throw the base Exception // class with an HRESULT indicating the issue. However, custom // validation code can also throw Exception, and to be compatible // with the CoreCLR version, we must allow those exceptions to // propagate without wrapping them. We use the simple heuristic // that if an HRESULT has been set to other than the default, // the exception should be wrapped in SecurityNegotiationException. if (exception.HResult == __HResults.COR_E_EXCEPTION) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException( exception.Message, exception)); } remoteSecurityWrapper.Value = _serverSecurity; return(stream); }
void Initialize(TokenImpersonationLevel tokenImpersonationLevel, NetworkCredential networkCredential, SafeFreeCredentials credentialsHandle, ChannelBinding channelBinding) { bool ownCredentialsHandle = false; SafeDeleteContext securityContext = null; try { if (credentialsHandle == null) { if (networkCredential == null || networkCredential == CredentialCache.DefaultNetworkCredentials) { credentialsHandle = SspiWrapper.AcquireDefaultCredential("Kerberos", CredentialUse.Outbound); } else { AuthIdentityEx authIdentity = new AuthIdentityEx(networkCredential.UserName, networkCredential.Password, networkCredential.Domain); credentialsHandle = SspiWrapper.AcquireCredentialsHandle("Kerberos", CredentialUse.Outbound, ref authIdentity); } ownCredentialsHandle = true; } SspiContextFlags fContextReq = SspiContextFlags.AllocateMemory | SspiContextFlags.Confidentiality | SspiContextFlags.ReplayDetect | SspiContextFlags.SequenceDetect; // we only accept Identity or Impersonation (Impersonation is default). if (tokenImpersonationLevel == TokenImpersonationLevel.Identification) { fContextReq |= SspiContextFlags.InitIdentify; } SspiContextFlags contextFlags = SspiContextFlags.Zero; SecurityBuffer inSecurityBuffer = null; if (channelBinding != null) { inSecurityBuffer = new SecurityBuffer(channelBinding); } SecurityBuffer outSecurityBuffer = new SecurityBuffer(0, BufferType.Token); int statusCode = SspiWrapper.InitializeSecurityContext( credentialsHandle, ref securityContext, this.servicePrincipalName, fContextReq, Endianness.Native, inSecurityBuffer, outSecurityBuffer, ref contextFlags); if (DiagnosticUtility.ShouldTraceInformation) { SecurityTraceRecordHelper.TraceChannelBindingInformation(null, false, channelBinding); } if (statusCode != (int)SecurityStatus.OK) { if (statusCode == (int)SecurityStatus.ContinueNeeded) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.KerberosMultilegsNotSupported), new Win32Exception(statusCode))); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.FailInitializeSecurityContext), new Win32Exception(statusCode))); } } #if REMOVEGSS // // ... and strip GSS-framing from it // int offset = 0; int len = outSecurityBuffer.token.Length; DEREncoding.VerifyTokenHeader(outSecurityBuffer.token, ref offset, ref len); this.apreq = SecurityUtils.CloneBuffer(outSecurityBuffer.token, offset, len); #else this.apreq = outSecurityBuffer.token; #endif // Expiration LifeSpan lifeSpan = (LifeSpan)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.Lifespan); this.effectiveTime = lifeSpan.EffectiveTimeUtc; this.expirationTime = lifeSpan.ExpiryTimeUtc; // SessionKey SecuritySessionKeyClass sessionKey = (SecuritySessionKeyClass)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.SessionKey); this.symmetricSecurityKey = new InMemorySymmetricSecurityKey(sessionKey.SessionKey); } finally { if (securityContext != null) { securityContext.Close(); } if (ownCredentialsHandle && credentialsHandle != null) { credentialsHandle.Close(); } } }
Message ProcessRequestCore(Message request) { if (request == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("request"); } Uri to = null; RequestSecurityToken rst = null; RequestSecurityTokenResponse rstr = null; string context = null; bool disposeRequest = false; bool isNegotiationFailure = true; T negotiationState = null; try { // validate the message size if needed if (this.maxMessageSize < int.MaxValue) { string action = request.Headers.Action; try { using (MessageBuffer buffer = request.CreateBufferedCopy(this.maxMessageSize)) { request = buffer.CreateMessage(); disposeRequest = true; } } catch (QuotaExceededException e) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.SecurityNegotiationMessageTooLarge, action, this.maxMessageSize), e)); } } try { to = request.Headers.To; ParseMessageBody(request, out context, out rst, out rstr); // check if there is existing state if (context != null) { negotiationState = this.stateCache.GetState(context); } else { negotiationState = null; } bool disposeState = false; BodyWriter replyBody; try { if (rst != null) { if (negotiationState != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.NegotiationStateAlreadyPresent, context))); } replyBody = this.ProcessRequestSecurityToken(request, rst, out negotiationState); lock (negotiationState.ThisLock) { if (negotiationState.IsNegotiationCompleted) { // if session-sct add it to cache and add a redirect header if (!negotiationState.ServiceToken.IsCookieMode) { this.IssuedTokenCache.AddContext(negotiationState.ServiceToken); } this.OnTokenIssued(negotiationState.ServiceToken); SecurityTraceRecordHelper.TraceServiceSecurityNegotiationCompleted(request, this, negotiationState.ServiceToken); disposeState = true; } else { this.stateCache.AddState(context, negotiationState); disposeState = false; } AddNegotiationChannelForIdleTracking(); } } else { if (negotiationState == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.CannotFindNegotiationState, context))); } lock (negotiationState.ThisLock) { replyBody = this.ProcessRequestSecurityTokenResponse(negotiationState, request, rstr); if (negotiationState.IsNegotiationCompleted) { // if session-sct add it to cache and add a redirect header if (!negotiationState.ServiceToken.IsCookieMode) { this.IssuedTokenCache.AddContext(negotiationState.ServiceToken); } this.OnTokenIssued(negotiationState.ServiceToken); SecurityTraceRecordHelper.TraceServiceSecurityNegotiationCompleted(request, this, negotiationState.ServiceToken); disposeState = true; } else { disposeState = false; } } } if (negotiationState.IsNegotiationCompleted && null != this.ListenUri) { if (AuditLevel.Success == (this.messageAuthenticationAuditLevel & AuditLevel.Success)) { string primaryIdentity = negotiationState.GetRemoteIdentityName(); SecurityAuditHelper.WriteSecurityNegotiationSuccessEvent(this.auditLogLocation, this.suppressAuditFailure, request, request.Headers.To, request.Headers.Action, primaryIdentity, this.GetType().Name); } } isNegotiationFailure = false; } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } if (PerformanceCounters.PerformanceCountersEnabled && null != this.ListenUri) { PerformanceCounters.AuthenticationFailed(request, this.ListenUri); } if (AuditLevel.Failure == (this.messageAuthenticationAuditLevel & AuditLevel.Failure)) { try { string primaryIdentity = (negotiationState != null) ? negotiationState.GetRemoteIdentityName() : String.Empty; SecurityAuditHelper.WriteSecurityNegotiationFailureEvent(this.auditLogLocation, this.suppressAuditFailure, request, request.Headers.To, request.Headers.Action, primaryIdentity, this.GetType().Name, exception); } #pragma warning suppress 56500 catch (Exception auditException) { if (Fx.IsFatal(auditException)) { throw; } DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error); } } disposeState = true; throw; } finally { if (disposeState) { if (negotiationState != null) { if (context != null) { stateCache.RemoveState(context); } negotiationState.Dispose(); } } } return(CreateReply(request, (replyBody is RequestSecurityTokenResponseCollection) ? RequestSecurityTokenResponseFinalAction : RequestSecurityTokenResponseAction, replyBody)); } finally { if (disposeRequest) { request.Close(); } } } finally { if (isNegotiationFailure) { AddNegotiationChannelForIdleTracking(); } else if (negotiationState != null && negotiationState.IsNegotiationCompleted) { RemoveNegotiationChannelFromIdleTracking(); } } }