Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / PeerSecurityHelpers.cs / 1 / PeerSecurityHelpers.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Net; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.ServiceModel.Diagnostics; using System.Security.Principal; using System.Xml; using System.Security; using System.IdentityModel.Claims; using System.IdentityModel.Policy; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.ServiceModel.Security; using System.ServiceModel.Security.Tokens; using System.Text; using System.Threading; class PeerSecurityHelpers { public static byte[] ComputeHash(X509Certificate2 cert, string pwd) { RSACryptoServiceProvider keyProv = cert.PublicKey.Key as RSACryptoServiceProvider; DiagnosticUtility.DebugAssert(keyProv != null, "Remote Peer's credentials are invalid!"); byte[] key = keyProv.ExportCspBlob(false); return ComputeHash(key, pwd); } public static byte[] ComputeHash(Claim claim, string pwd) { RSACryptoServiceProvider provider = claim.Resource as RSACryptoServiceProvider; if(provider == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claim"); using(provider) { byte[] keyBlob = provider.ExportCspBlob(false); if(keyBlob == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key"); return ComputeHash(keyBlob,pwd); } } public static byte[] ComputeHash(byte[] message, string pwd) { byte[] returnValue = null; RuntimeHelpers.PrepareConstrainedRegions(); byte[] pwdBytes = null; byte[] pwdHash = null; byte[] tempBuffer = null; try { pwdBytes = UnicodeEncoding.Unicode.GetBytes(pwd.Trim()); using(HMACSHA256 algo = new HMACSHA256(pwdBytes)) { using(SHA256Managed sha = new SHA256Managed()) { pwdHash = sha.ComputeHash(pwdBytes); tempBuffer = DiagnosticUtility.Utility.AllocateByteArray(checked(message.Length + pwdHash.Length)); Array.Copy(pwdHash, tempBuffer, pwdHash.Length); Array.Copy(message, 0, tempBuffer, pwdHash.Length, message.Length); returnValue = algo.ComputeHash(tempBuffer); } } } finally { ArrayClear(pwdBytes); ArrayClear(pwdHash); ArrayClear(tempBuffer); } return returnValue; } static void ArrayClear(byte[] buffer) { if(buffer != null) Array.Clear(buffer,0,buffer.Length); } public static bool Authenticate(Claim claim, string password, byte[] authenticator) { bool returnValue = false; if(authenticator == null) return false; byte[] hash = null; RuntimeHelpers.PrepareConstrainedRegions(); try { hash = ComputeHash(claim,password); if (hash.Length == authenticator.Length) { for (int i = 0; i < hash.Length; i++) { if (hash[i] != authenticator[i]) { returnValue = false; break; } } returnValue = true; } } finally { ArrayClear(hash); } return returnValue; } public static bool AuthenticateRequest(Claim claim, string password, Message message) { PeerHashToken request = PeerRequestSecurityToken.CreateHashTokenFrom(message); return request.Validate(claim, password); } public static bool AuthenticateResponse(Claim claim, string password, Message message) { PeerHashToken request = PeerRequestSecurityTokenResponse.CreateHashTokenFrom(message); return request.Validate(claim, password); } } internal class PeerIdentityClaim { const string resourceValue = "peer"; const string resourceRight = "peer"; public const string PeerClaimType = PeerStrings.Namespace+"/peer"; static internal Claim Claim() { return new Claim(PeerClaimType,resourceValue,resourceRight); } static internal bool IsMatch(EndpointIdentity identity) { return identity.IdentityClaim.ClaimType == PeerClaimType; } } class PeerDoNothingSecurityProtocol : SecurityProtocol { public PeerDoNothingSecurityProtocol(SecurityProtocolFactory factory):base(factory, null, null){} public override void SecureOutgoingMessage(ref Message message, TimeSpan timeout) { } public override void VerifyIncomingMessage(ref Message request, TimeSpan timeout) { try { int i = request.Headers.FindHeader(SecurityJan2004Strings.Security, SecurityJan2004Strings.Namespace); if (i >= 0) { request.Headers.AddUnderstood(i); } } catch (MessageHeaderException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } catch(XmlException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } catch (SerializationException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } public override void OnAbort() { } public override void OnClose(TimeSpan timeout) { } public override void OnOpen(TimeSpan timeout) { } } class PeerDoNothingSecurityProtocolFactory : SecurityProtocolFactory { protected override SecurityProtocol OnCreateSecurityProtocol(EndpointAddress target, Uri via, object listenerSecurityState, TimeSpan timeout) { return new PeerDoNothingSecurityProtocol(this); } public override void OnAbort() { } public override void OnOpen(TimeSpan timeout) { } public override void OnClose(TimeSpan timeout) { } } class PeerIdentityVerifier : IdentityVerifier { public PeerIdentityVerifier():base(){} public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { return true; } public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { if (reference == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reference"); identity = reference.Identity; if(identity == null) { identity = new PeerEndpointIdentity(); } return true; } } class PeerEndpointIdentity : EndpointIdentity { public PeerEndpointIdentity() : base() { base.Initialize(PeerIdentityClaim.Claim()); } } class PeerX509TokenProvider : X509SecurityTokenProvider { X509CertificateValidator validator; public PeerX509TokenProvider(X509CertificateValidator validator, X509Certificate2 credential) : base(credential) { this.validator = validator; } protected override SecurityToken GetTokenCore(TimeSpan timeout) { X509SecurityToken token = (X509SecurityToken) base.GetTokenCore(timeout); if (validator != null) { validator.Validate(token.Certificate); } return token; } } class PeerCertificateClientCredentials : SecurityCredentialsManager { X509Certificate2 selfCertificate; X509CertificateValidator certificateValidator; public PeerCertificateClientCredentials(X509Certificate2 selfCertificate, X509CertificateValidator validator) { this.selfCertificate = selfCertificate; this.certificateValidator = validator; } public override SecurityTokenManager CreateSecurityTokenManager() { return new PeerCertificateClientCredentialsSecurityTokenManager(this); } class PeerCertificateClientCredentialsSecurityTokenManager : SecurityTokenManager { PeerCertificateClientCredentials creds; public PeerCertificateClientCredentialsSecurityTokenManager(PeerCertificateClientCredentials creds) { this.creds = creds; } public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version) { MessageSecurityTokenVersion messageVersion = (MessageSecurityTokenVersion) version; return new WSSecurityTokenSerializer(messageVersion.SecurityVersion, messageVersion.TrustVersion, messageVersion.SecureConversationVersion, messageVersion.EmitBspRequiredAttributes, null, null, null); } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement requirement) { if (requirement == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requirement"); } if (requirement.TokenType == SecurityTokenTypes.X509Certificate && requirement.KeyUsage == SecurityKeyUsage.Signature) { return new PeerX509TokenProvider(this.creds.certificateValidator, this.creds.selfCertificate); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } } } } internal class PeerHashToken : SecurityToken { string id = SecurityUniqueId.Create().Value; Uri status; bool isValid; ReadOnlyCollectionkeys; internal const string TokenTypeString = PeerStrings.Namespace + "/peerhashtoken"; internal const string RequestTypeString = "http://schemas.xmlsoap.org/ws/2005/02/trust/Validate"; internal const string Action = "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Validate"; public const string PeerNamespace = PeerStrings.Namespace; public const string PeerTokenElementName = "PeerHashToken"; public const string PeerAuthenticatorElementName = "Authenticator"; public const string PeerPrefix = "peer"; static PeerHashToken invalid = new PeerHashToken(); byte[] authenticator; DateTime effectiveTime = DateTime.UtcNow; DateTime expirationTime = DateTime.UtcNow.AddHours(10); PeerHashToken() { CheckValidity(); } public PeerHashToken(byte[] authenticator) { this.authenticator = authenticator; CheckValidity(); } public PeerHashToken(X509Certificate2 certificate, string password) { this.authenticator = PeerSecurityHelpers.ComputeHash(certificate, password); CheckValidity(); } public PeerHashToken(Claim claim, string password) { this.authenticator = PeerSecurityHelpers.ComputeHash(claim, password); CheckValidity(); } public override string Id { get { return this.id; } } public override DateTime ValidFrom { get { return this.effectiveTime; } } public override DateTime ValidTo { get { return this.expirationTime; } } public static PeerHashToken Invalid { get { return invalid; } } public override ReadOnlyCollection SecurityKeys { get { if(null == this.keys) { this.keys = new ReadOnlyCollection (new List ()); } return this.keys; } } public Uri Status { get { return this.status; } } public bool IsValid { get { return this.isValid; } } public bool Validate(Claim claim, string password) { if (!(this.authenticator != null)) { DiagnosticUtility.DebugAssert("Incorrect initialization"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } bool result = PeerSecurityHelpers.Authenticate(claim, password, this.authenticator); return result; } void CheckValidity() { isValid = this.authenticator != null; status = new Uri(isValid? PeerRequestSecurityTokenResponse.ValidString : PeerRequestSecurityTokenResponse.InvalidString); } public void Write(XmlWriter writer) { writer.WriteStartElement(PeerPrefix,PeerTokenElementName, PeerNamespace); writer.WriteStartElement(PeerPrefix,PeerAuthenticatorElementName,PeerNamespace); writer.WriteString(Convert.ToBase64String(this.authenticator)); writer.WriteEndElement(); writer.WriteEndElement(); } internal static PeerHashToken CreateFrom(XmlElement child) { byte[] auth = null; foreach(XmlNode node in child.ChildNodes) { XmlElement element = (XmlElement)node; if(element == null || !PeerRequestSecurityToken.CompareWithNS(element.LocalName, element.NamespaceURI, PeerTokenElementName, PeerNamespace)) continue; if(element.ChildNodes.Count != 1) break; XmlElement authElement = element.ChildNodes[0] as XmlElement; if(authElement == null || !PeerRequestSecurityToken.CompareWithNS(authElement.LocalName, authElement.NamespaceURI, PeerAuthenticatorElementName, PeerNamespace)) break; try { auth = Convert.FromBase64String(XmlHelper.ReadTextElementAsTrimmedString(authElement)); break; } catch(ArgumentNullException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } catch(FormatException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } return new PeerHashToken(auth); } public override bool Equals(object token) { PeerHashToken that = token as PeerHashToken; if (that == null) return false; if (Object.ReferenceEquals(that, this)) return true; if(this.authenticator != null && that.authenticator != null && this.authenticator.Length == that.authenticator.Length) { for(int i=0;i { IPeerNeighbor host; PeerSecurityManager securityManager; PeerAuthState state; EventArgs originalArgs; EventHandler onSucceeded; IOThreadTimer timer = null; object thisLock = new object(); static TimeSpan Timeout = new TimeSpan(0,2,0); string meshId; enum PeerAuthState { Created, Authenticated, Failed } public PeerChannelAuthenticatorExtension(PeerSecurityManager securityManager, EventHandler onSucceeded, EventArgs args, string meshId) { this.securityManager = securityManager; this.state = PeerAuthState.Created; this.originalArgs = args; this.onSucceeded = onSucceeded; this.meshId = meshId; } object ThisLock { get { return this.thisLock; } } public void Attach(IPeerNeighbor host) { if (!(this.securityManager.AuthenticationMode == PeerAuthenticationMode.Password)) { DiagnosticUtility.DebugAssert("Invalid AuthenticationMode!"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if (!(host != null)) { DiagnosticUtility.DebugAssert("unrecognized host!"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } this.host = host; this.timer = new IOThreadTimer(OnTimeout, null, true); this.timer.Set(Timeout); } static public void OnNeighborClosed(IPeerNeighbor neighbor) { DiagnosticUtility.DebugAssert(neighbor != null, "Neighbor must have a value"); PeerChannelAuthenticatorExtension ext = neighbor.Extensions.Find (); if(ext != null) neighbor.Extensions.Remove(ext); } public void Detach(IPeerNeighbor host) { DiagnosticUtility.DebugAssert(host != null, "unrecognized host!"); if(host.State < PeerNeighborState.Authenticated) { OnFailed(host); } this.host = null; this.timer.Cancel(); } void OnTimeout(object state) { IPeerNeighbor neighbor = host; if(neighbor == null) return; if(neighbor.State < PeerNeighborState.Authenticated) { OnFailed(neighbor); } } public void InitiateHandShake() { IPeerNeighbor neighbor = host; Message reply = null; DiagnosticUtility.DebugAssert(host != null, "Cannot initiate security handshake without a host!"); //send the RST message. using(OperationContextScope scope = new OperationContextScope(new OperationContext((ServiceHostBase)null))) { PeerHashToken token = this.securityManager.GetSelfToken(); Message request = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, TrustFeb2005Strings.RequestSecurityToken,new PeerRequestSecurityToken(token)); bool fatal = false; try { reply = neighbor.RequestSecurityToken(request); if (!(reply != null)) { DiagnosticUtility.DebugAssert("SecurityHandshake return empty message!"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } ProcessRstr(neighbor, reply, PeerSecurityManager.FindClaim(ServiceSecurityContext.Current)); } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { fatal = true; throw; } DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); this.state = PeerAuthState.Failed; if (DiagnosticUtility.ShouldTraceError) { ServiceSecurityContext context = ServiceSecurityContext.Current; ClaimSet claimSet = null; if(context != null && context.AuthorizationContext != null && context.AuthorizationContext.ClaimSets != null && context.AuthorizationContext.ClaimSets.Count > 0) claimSet = context.AuthorizationContext.ClaimSets[0]; PeerAuthenticationFailureTraceRecord record = new PeerAuthenticationFailureTraceRecord( meshId, neighbor.ListenAddress.EndpointAddress.ToString(), claimSet, e); TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.PeerNodeAuthenticationFailure, record, this, null); } neighbor.Abort(PeerCloseReason.AuthenticationFailure, PeerCloseInitiator.LocalNode); } finally { if(!fatal) request.Close(); } } } public Message ProcessRst(Message message, Claim claim) { IPeerNeighbor neighbor = host; PeerRequestSecurityTokenResponse response = null; Message reply = null; lock(ThisLock) { if(this.state != PeerAuthState.Created || neighbor == null || neighbor.IsInitiator || neighbor.State != PeerNeighborState.Opened) { OnFailed(neighbor); return null; } } try { PeerHashToken receivedToken = PeerRequestSecurityToken.CreateHashTokenFrom(message); PeerHashToken expectedToken = securityManager.GetExpectedTokenForClaim(claim); if(!expectedToken.Equals(receivedToken)) { OnFailed(neighbor); } else { this.state = PeerAuthState.Authenticated; PeerHashToken selfToken = securityManager.GetSelfToken(); response = new PeerRequestSecurityTokenResponse(selfToken); reply = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, TrustFeb2005Strings.RequestSecurityTokenResponse, response); OnAuthenticated(); } } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); OnFailed(neighbor); } return reply; } public void ProcessRstr(IPeerNeighbor neighbor, Message message, Claim claim) { PeerHashToken receivedToken = PeerRequestSecurityTokenResponse.CreateHashTokenFrom(message); if(!receivedToken.IsValid) { OnFailed(neighbor); } else { PeerHashToken expectedToken = securityManager.GetExpectedTokenForClaim(claim); if(!expectedToken.Equals(receivedToken)) OnFailed(neighbor); else OnAuthenticated(); } } public void OnAuthenticated() { IPeerNeighbor neighbor = null; lock(ThisLock) { this.timer.Cancel(); neighbor = this.host; this.state = PeerAuthState.Authenticated; } if(neighbor == null) return; neighbor.TrySetState(PeerNeighborState.Authenticated); onSucceeded(neighbor,originalArgs); } void OnFailed(IPeerNeighbor neighbor) { lock(ThisLock) { this.state = PeerAuthState.Failed; this.timer.Cancel(); this.host = null; } if (DiagnosticUtility.ShouldTraceError) { PeerAuthenticationFailureTraceRecord record = null; String remoteUri = ""; PeerNodeAddress remoteAddress = neighbor.ListenAddress; if(remoteAddress != null) { remoteUri = remoteAddress.EndpointAddress.ToString(); } OperationContext opContext = OperationContext.Current; if(opContext != null) { remoteUri = opContext.IncomingMessageProperties.Via.ToString(); ServiceSecurityContext secContext = opContext.ServiceSecurityContext; if (secContext != null) { record = new PeerAuthenticationFailureTraceRecord( meshId, remoteUri, secContext.AuthorizationContext.ClaimSets[0],null); if (DiagnosticUtility.ShouldTraceError) { TraceUtility.TraceEvent( TraceEventType.Error, TraceCode.PeerNodeAuthenticationFailure, record, this, null); } } } else { record = new PeerAuthenticationFailureTraceRecord(meshId, remoteUri); if (DiagnosticUtility.ShouldTraceError) { TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.PeerNodeAuthenticationTimeout, record, this, null); } } } neighbor.Abort(PeerCloseReason.AuthenticationFailure, PeerCloseInitiator.LocalNode); } } } namespace System.ServiceModel.Channels { internal enum PeerAuthenticationMode { None = 0, Password = 1, MutualCertificate = 2 } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- mediaeventshelper.cs
- Graph.cs
- ISAPIRuntime.cs
- MarkupExtensionParser.cs
- safex509handles.cs
- AutoGeneratedFieldProperties.cs
- CodeNamespace.cs
- HtmlLink.cs
- HandledMouseEvent.cs
- ResXBuildProvider.cs
- ViewCellRelation.cs
- ListMarkerSourceInfo.cs
- Typeface.cs
- SortedList.cs
- DurableErrorHandler.cs
- ResourceBinder.cs
- EdmToObjectNamespaceMap.cs
- SemanticAnalyzer.cs
- HwndMouseInputProvider.cs
- NonBatchDirectoryCompiler.cs
- ServiceReference.cs
- XmlRawWriter.cs
- ReadWriteObjectLock.cs
- XmlValueConverter.cs
- TypeListConverter.cs
- CornerRadiusConverter.cs
- InternalBase.cs
- FixedSOMElement.cs
- ToolStripGrip.cs
- CustomError.cs
- UserNamePasswordClientCredential.cs
- CreationContext.cs
- NativeCppClassAttribute.cs
- SettingsBase.cs
- CodeDomConfigurationHandler.cs
- CreationContext.cs
- AlternateViewCollection.cs
- SingleSelectRootGridEntry.cs
- AssemblyInfo.cs
- DefaultTraceListener.cs
- Paragraph.cs
- DbProviderFactories.cs
- DummyDataSource.cs
- PatternMatcher.cs
- SqlTypeSystemProvider.cs
- WindowsPen.cs
- XmlSchemaCompilationSettings.cs
- ToolboxItemCollection.cs
- DeviceContext2.cs
- DBConcurrencyException.cs
- MULTI_QI.cs
- IISMapPath.cs
- TraceRecord.cs
- DataGridViewColumnCollection.cs
- Int16Animation.cs
- WindowsUserNameSecurityTokenAuthenticator.cs
- LineSegment.cs
- XamlStyleSerializer.cs
- TextRunCache.cs
- PromptBuilder.cs
- ComboBox.cs
- HttpCacheVary.cs
- CodeTypeDelegate.cs
- SymmetricAlgorithm.cs
- DataRowCollection.cs
- LogExtentCollection.cs
- ColumnClickEvent.cs
- ValidationSummary.cs
- MediaContext.cs
- DrawItemEvent.cs
- HttpClientCertificate.cs
- DbConnectionPoolGroupProviderInfo.cs
- URLAttribute.cs
- EventLogPermission.cs
- CompressStream.cs
- StrongNameKeyPair.cs
- ControlBuilderAttribute.cs
- TableStyle.cs
- CompilationRelaxations.cs
- ComponentResourceKey.cs
- EnumType.cs
- EntityKeyElement.cs
- ControlPropertyNameConverter.cs
- RSACryptoServiceProvider.cs
- Label.cs
- MetadataStore.cs
- StaticSiteMapProvider.cs
- FilterQuery.cs
- Merger.cs
- GradientStop.cs
- PkcsMisc.cs
- ParagraphResult.cs
- ListViewItemEventArgs.cs
- Nullable.cs
- XmlElementAttribute.cs
- HybridDictionary.cs
- LineProperties.cs
- SeekStoryboard.cs
- XmlDictionaryReader.cs
- PermissionRequestEvidence.cs