2010-11-03 8 views
12

J'essaie d'accéder à un service Web SOAP hébergé publiquement (pas à WCF) via https, et je reçois une erreur que je n'ai jamais vue auparavant. Tout d'abord, voici les faits:Comment forcer le client WCF à envoyer un certificat client?

  • Ce service nécessite des certificats clients. J'ai un certificat qui est signé par la même autorité de certification que le certificat du serveur.
  • Je sais que l'URL est disponible, comme je peux le faire dans Internet Explorer. IE affiche la fenêtre "Choisir un certificat", et si je la sélectionne (et ignore l'erreur de certificat serveur-nom-d'hôte-ne-concordance-pas), elle continue et me donne une erreur HTTP 500.
  • Si j'ouvre le site dans Chrome, après avoir choisi le CERT et ignoré l'erreur, je reçois un message d'erreur normal à propos de WSA Action = null.
  • Si j'ouvre le site dans FireFox, après avoir ignoré l'erreur, j'obtiens une page sur la façon dont le serveur n'a pas pu valider mon certificat. Il ne m'a jamais demandé d'en choisir un, alors c'est tout à fait logique.

Maintenant, l'exception:

Error occurred while executing test 12302: System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'ihexds.nist.gov:9085'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. 
    at System.Net.HttpWebRequest.GetResponse() 
    at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) 

J'ai retracé l'interaction avec Wireshark, mais parce que je ne suis pas un expert dans le protocole TLS, je pourrais être des indices manquant quant à ce qui se passe . Ici, cependant, est ce que je vois:

  1. C -> S client Bonjour
    • Contient des choses comme un nombre aléatoire, date/heure, suites cypher pris en charge, etc
  2. S - > C serveur Bonjour, certificat, demande de certificat, serveur Bonjour Fait
    • Contient le certificat du serveur, et une demande de certificat client
  3. C -> Certificat S, Key Exchange client, changement Cipher Spec, Encrypted Handshake message
    • VOICI LE INTÉRESSANT PARTIE - La première partie de ce paquet est la poignée de main de certificat, où je suppose que le certificat client serait être, mais il n'y a aucun certificat présent (longueur des certificats: 0).
  4. S -> C Alert (Niveau: Fatal, Description: Bad certificat)
    • Eh bien, oui, il n'y avait pas de certificat envoyé.

Ma liaison est mis en place comme suit:

<binding name="https_binding"> 
    <textMessageEncoding /> 
    <httpsTransport useDefaultWebProxy="false" /> 
</binding> 

Mon comportement est défini comme suit:

<behavior name="clientcred"> 
    <clientCredentials> 
     <clientCertificate findValue="69b6fbbc615a20dc272a79caa201fe3f505664c3" storeLocation="CurrentUser" storeName="My" x509FindType="FindByThumbprint" /> 
     <serviceCertificate> 
      <authentication certificateValidationMode="None" revocationMode="NoCheck" /> 
     </serviceCertificate> 
    </clientCredentials> 
    <messageInspector /> 
</behavior> 

Mon critère d'évaluation est configuré pour utiliser à la fois la liaison et le comportement. Pourquoi WCF refuse-t-il d'envoyer le certificat lorsqu'il crée la connexion https?

Répondre

9

J'ai résolu le problème, mais je ne comprends pas pourquoi ce changement de configuration l'a corrigé. J'ai changé cette ligne:

<httpsTransport useDefaultWebProxy="false" /> 

à ceci:

<httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" /> 

et comme par magie il a commencé à travailler. J'avais compris que le "bouton" requireClientCertificate était pour le côté serveur, donc je ne l'avais pas essayé pendant mes querelles. Apparemment j'avais tort.

+0

Je déteste tellement la WCF. Cette solution a fonctionné pour moi, merci tas - mais tout est si fastidieux. Tue moi maintenant. – robnick

-1

Il peut s'agir d'un problème lors de la négociation du protocole de sécurité à utiliser.Plus précisément, je pense que le serveur pourrait ne pas aimer WCF essayant d'utiliser TLS 1.0.

Pour voir si tel est le cas, essayez d'ajouter ce qui suit avant d'appeler le service

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3 

Cela pourrait être ajouté dans le code client ou en le plaçant dans un IEndpointBehavior

+0

J'ai essayé ceci, et cela n'a pas changé les résultats. Je sais que le serveur prend en charge TLS 1.0 (et seulement un chiffrement spécifique, en fait, mais que le chiffrement est dans la liste envoyée au serveur dans la poignée de main). – Mark

+0

Non si l'échange est arrivé aussi loin qu'un message ChangeCipherSpec. Cela signifie que tout ce qui concerne le protocole a été convenu. – EJP

2

Il aurait dû être une CertificateRequest du serveur, nommant les types de certificat et les autorités de certification acceptables. Si votre certificat ne correspond pas à ceux-ci, il ne sera pas envoyé.

+0

Il y avait une demande de certificat (voir # 2), et il contenait en effet une liste d'autorités de certification et de types de certificats. J'ai en effet un certificat approprié, et c'est celui spécifié dans le comportement. – Mark

+0

Si tout cela est vrai, il y aurait eu un message de certificat du client après le CertificateRequest du serveur. La conclusion inévitable est que certaines d'entre elles ne sont pas vraies. Vous devez vérifier tout cela: spécifiquement, que le certificat (a) est disponible pour l'application et (b) conforme à toutes les contraintes exprimées dans CertificateRequest. – EJP

+0

C'est véridiquement vrai ... J'ai la capture WireShark ici. J'ai fini par résoudre le problème, mais je ne comprends pas vraiment pourquoi ce que j'ai changé l'a corrigé. Je l'afficherai dans une réponse séparée. – Mark

Questions connexes