2016-01-20 9 views
11

Sto lavorando allo sviluppo di un nuovo bind per un servizio Wcf ospitato in IIS, pensavo di avere tutto funzionante, ma risulta che il client funziona solo quando è attivo targetting .Net framework 4.5, se cambio per indirizzare 4.6 allora ottengo il seguente errore quando si tenta di aprire una connessione:WCF SslStreamSecurity Identity Check DNS non riuscito per il solo framework 4.6

System.ServiceModel.Security.MessageSecurityException occurred 
    HResult=-2146233087 
    Message=The Identity check failed for the outgoing message. The remote endpoint did not provide a domain name system (DNS) claim and therefore did not satisfied DNS identity 'xxx.domain.local'. This may be caused by lack of DNS or CN name in the remote endpoint X.509 certificate's distinguished name. 
    Source=System.ServiceModel 
    StackTrace: 
     at System.ServiceModel.Security.IdentityVerifier.EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, String errorString) 

Se non faccio altro che cambiare il framework di destinazione nel mio codice di prova di nuovo a 4.5, quindi funziona correttamente. Questo mi fa pensare che potrebbe essere un bug in .Net 4.6, so che ci sono stati Wcf ssl changes made in 4.6

Con eccezioni first-chance acceso vedo la seguente eccezione che viene generato internamente System.ServiceModel

System.ArgumentNullException occurred 
    HResult=-2147467261 
    Message=Value cannot be null. 
Parameter name: value 
    ParamName=value 
    Source=mscorlib 
    StackTrace: 
     at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult) 
    InnerException: 

    System.ServiceModel.dll!System.ServiceModel.Security.IssuanceTokenProviderBase<System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.FederatedTokenProviderState>.DoNegotiation(System.TimeSpan timeout) Unknown  System.ServiceModel.dll!System.ServiceModel.Security.IssuanceTokenProviderBase<System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.FederatedTokenProviderState>.GetTokenCore(System.TimeSpan timeout) Unknown 
    System.IdentityModel.dll!System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.GetTokenCore(System.TimeSpan timeout) Unknown 
    System.IdentityModel.dll!System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.TryGetSupportingTokens(System.ServiceModel.Security.SecurityProtocolFactory factory, System.ServiceModel.EndpointAddress target, System.Uri via, System.ServiceModel.Channels.Message message, System.TimeSpan timeout, bool isBlockingCall, out System.Collections.Generic.IList<System.ServiceModel.Security.SupportingTokenSpecification> supportingTokens) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Security.TransportSecurityProtocol.SecureOutgoingMessageAtInitiator(ref System.ServiceModel.Channels.Message message, string actor, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Security.TransportSecurityProtocol.SecureOutgoingMessage(ref System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.SecureOutgoingMessage(ref System.ServiceModel.Channels.Message message, System.TimeSpan timeout, System.ServiceModel.Security.SecurityProtocolCorrelationState correlationState) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Channels.SecurityChannelFactory<System.ServiceModel.Channels.IRequestChannel>.SecurityRequestChannel.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Channels.TransactionRequestChannelGeneric<System.ServiceModel.Channels.IRequestChannel>.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation) Unknown 
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message) Unknown 
    mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type) Unknown 

Il servizio wcf a cui è stato comunicato il targeting è il 4.6 e, per quanto posso dire, sto specificando l'identità dns, che esiste come CN = nel soggetto cert. Il binding è un'associazione personalizzata in modo che possa eseguire federated net.tcp, il client crea tutto nel codice e non uso la funzione Aggiungi riferimento al servizio in visual studio, il codice client che sta creando l'associazione:

var binding = new CustomBinding(new BindingElement[] { 
      new TransactionFlowBindingElement(), 
      security, 
      new SslStreamSecurityBindingElement(), 
      new BinaryMessageEncodingBindingElement() { 
       ReaderQuotas = { MaxDepth = maxReceivedSizeBytes, MaxStringContentLength = maxReceivedSizeBytes, MaxArrayLength = maxReceivedSizeBytes, MaxBytesPerRead = maxReceivedSizeBytes, MaxNameTableCharCount = maxReceivedSizeBytes }, 
      }, 
      new TcpTransportBindingElement { 
       TransferMode = TransferMode.StreamedResponse, 
       MaxReceivedMessageSize = maxReceivedSizeBytes, 
      }, 
     }) { 
    SendTimeout = sendTimeout, 
}; 

var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(new Uri(url), EndpointIdentity.CreateDnsIdentity("xxx.domain.local"), new AddressHeader[0])); 

Questo potrebbe essere un bug nel framework 4.6 che causa un comportamento diverso? I prossimi passi proverebbero solo a passare e ad eseguire il debug del codice framework per cercare di scoprire perché il 4.6 si comporta in modo diverso?

EDIT - ho creato un small sample project that demonstrates the error, i passaggi di Repro sono:

  • (Usando VS 2015) aprire la soluzione WcfSelfHostedServer
  • Aggiungere il CERT IdentityFail.pfx sul computer locale, archivio Personale utilizzando mmc
  • Eseguire il progetto WcfSelfHostedServer (probabilmente clic su Sì firewall consentono porta 30000)
  • Aprire la soluzione WcfClient
  • 012.351.
  • clic destro sul progetto> proprietà, notare che è destinati a 4.6.1
  • Eseguire il progetto, sarà generare l'eccezione sopra descritto
  • Ora passare al client di indirizzare 4.5.2, è in grado di funzionare senza errori

Update - ho trovato la seguente che appaiono correlati: https://support.microsoft.com/en-us/kb/3069494 https://msdn.microsoft.com/en-us/library/mt298998(v=vs.110).aspx

Ma specificando Tls12 sul server e sul client non ha risolto il problema e anche l'aggiunta del flag DontEnableSchUseStrongCrypto = true non ha influito sull'errore di controllo dell'identità DNS anche se si è verificato attorno all'errore Enum.Parse interno che was being thrown from this line

risposta

18

Avevo bisogno di guardare a Retargetting Changes in the .NET Framework 4.6.1, come logica di convalida del certificato modificata in quella versione. (change in behavior for X509CertificateClaimSet.FindClaims che causa il mio problema)

La correzione sta modificando la mia app.config per aggiungere:

<runtime> 
    <AppContextSwitchOverrides value="Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate=true" /> 
</runtime> 

si può vedere la changed code on referencesource, e naturalmente Makecert.exe non sembra supportare generating certificates with "Subject Alternative Name" fields

1

Brandon.

Sembra che se il flag è 'falso' E un certificato NON contiene voci SAN, non aggiungiamo la voce dns.

4

È possibile risolvere il problema aggiungendo una riga.

come questo.

 AppContext.SetSwitch("Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate",true); 
+1

Per qualche motivo questo ha funzionato e il cambiamento app.config no. – Jazaret

+1

Sto vivendo la stessa cosa. Ho impostato lo switch nella sezione 'runtime' di web.config, ma non viene applicato. Tuttavia, impostarlo nel codice funziona (e risolve il problema per me). Al momento non ho una soluzione a questo ... ho pensato di entrare. – erlingormar

1

L'installazione di .net 4.7 sul server ha risolto il problema per me.

Problemi correlati