Comment résoudre "Impossible d'établir une relation de confiance pour le canal sécurisé SSL / TLS avec autorité"

135

Je pensais vraiment avoir réglé ce problème, mais il n'était déguisé qu'avant.

J'ai un service WCF hébergé dans IIS 7 en utilisant HTTPS. Lorsque je navigue sur ce site dans Internet Explorer, cela fonctionne comme un charme, c'est parce que je l' ai ajouté le certificat au magasin d'autorité de certification racine local.

Je développe sur 1 machine, donc le client et le serveur sont la même machine. Le certificat est auto-signé directement à partir du composant logiciel enfichable de gestion IIS 7.

Je reçois continuellement cette erreur maintenant ...

Impossible d'établir une relation d'approbation pour le canal sécurisé SSL / TLS avec autorité.

... lorsqu'il est appelé depuis la console client.

Je me suis donné manuellement des autorisations et un service réseau sur le certificat, en utilisant findprivatekeyet en utilisant cacls.exe.

J'ai essayé de me connecter au service en utilisant SOAPUI, et cela fonctionne, donc cela doit être un problème dans mon application cliente, qui est un code basé sur ce qui fonctionnait avec http.

Où puis-je regarder ailleurs? Il semble que j'ai épuisé toutes les possibilités pour lesquelles je ne peux pas me connecter?

JL.
la source
Si vous contrôlez la création des certificats, n'oubliez pas "Autre nom du sujet". Comme vous pourriez mettre un joker dans "* .full.domainname.com". Voir digicert.com/subject-alternative-name.htm
granadaCoder

Réponses:

198

Pour contourner le problème, vous pouvez ajouter un gestionnaire aux ServicePointManager's ServerCertificateValidationCallbackcôté client:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

mais sachez que ce n'est pas une bonne pratique car elle ignore complètement le certificat du serveur et indique au gestionnaire du point de service que tout certificat convient, ce qui peut sérieusement compromettre la sécurité du client. Vous pouvez affiner cela et effectuer une vérification personnalisée (pour le nom du certificat, le hachage, etc.). au moins, vous pouvez contourner les problèmes lors du développement lors de l'utilisation de certificats de test.

Joachim Kerschbaumer
la source
9
Je pense que la plupart des configurations publiques utiliseront un certificat acheté, mais pendant le développement, utilisez le code ci-dessus dans des instructions #if conditionnelles. Les développeurs d'entreprise doivent généralement configurer un serveur CA interne >> technet.microsoft.com/en-us/library/cc875810.aspx
Luke Puplett
2
M'a aidé à comprendre comment faire fonctionner mon appel SSL WCF avec Fiddler2 pour le débogage.
Roger Willcocks
2
@karank Pensez à le mettre dans la méthode Application_Start du Global.asax (voir stackoverflow.com/a/12507094/1175419 ). Je recommanderais fortement d'utiliser une directive de compilation #if DEBUG ou quelque chose de similaire comme mentionné dans le commentaire de Luke.
Riche C
4
Impressionnant! vous pouvez utiliser l'expression lambda comme System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777
Une petite explication supplémentaire peut être trouvée ici: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder
40

Quand j'ai ce problème, c'est parce que client.config avait ses points de terminaison comme:

 https://myserver/myservice.svc 

mais le certificat attendait

 https://myserver.mydomain.com/myservice.svc

Changer les points de terminaison pour qu'ils correspondent au FQDN du serveur résout mon problème. Je sais que ce n'est pas la seule cause de ce problème.

Mike Cheel
la source
Je viens d'avoir à nouveau ce problème et cette fois, il fallait utiliser le mauvais certificat. Il semble que dans les deux cas, il s'agit de faire correspondre correctement les noms.
Mike Cheel
3
Ma configuration générée automatiquement avait <endpoint address = " localhost / myservice.svc " en changeant cela en <endpoint address = " mymachine.mydoman.com/myservice.svc " résolu ce problème .
knightscharge
C'était absolument mon problème et il m'a fallu deux jours pour trouver votre réponse. +1, je vous donnerais +1000 si je le pouvais.
AussieJoe
20

les deux premiers utilisent lambda, le troisième utilise du code normal ... j'espère que vous le trouverez utile

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            // trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

            // validate cert by calling a function
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

    // callback used to validate the certificate in an SSL conversation
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }
Sébastien Castaldi
la source
1
// Faire confiance à tous les certificats System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // Faire confiance à l'expéditeur System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild
1
N'importe quel pirate peut forger un certificat en passant tous les tests ci-dessus. Ceci n'est pas sûr.
Bjartur Thorlacius
19

Votre problème survient parce que vous utilisez une clé auto-signée. Le client ne fait pas confiance à cette clé et la clé elle-même ne fournit pas de chaîne à valider ni de liste de révocation de certificats.

Vous avez quelques options - vous pouvez

  1. désactiver la validation du certificat sur le client (mauvais coup, les attaques de l'homme au milieu abondent)

  2. utilisez makecert pour créer une autorité de certification racine et créer des certificats à partir de cela (ok, mais il n'y a toujours pas de CRL)

  3. créer une autorité de certification racine interne à l'aide de Windows Certificate Server ou d'une autre solution PKI, puis faire confiance à ce certificat racine (un peu difficile à gérer)

  4. acheter un certificat SSL auprès de l'une des autorités de certification de confiance (coûteux)

blowdart
la source
3
Concernant (4), StartSSL vous donnera en fait un certificat de classe 1 gratuit qui fonctionne dans tous les principaux navigateurs. Ils fonctionnent très bien pour moi pour ma demi-douzaine de sites à faible bande passante.
moodboom
Je pense que # 2 sur cette liste ... cette URL pourrait aider: blogs.technet.microsoft.com/jhoward/2005/02/02/… "Comment utiliser MakeCert pour l'autorité de certification racine de confiance et l'émission de certificats SSL"
granadaCoder
1
Remarque: StartCom n'est plus digne de confiance - et vient d'être supprimé de Chrome en.wikipedia.org/wiki/StartCom
Simon_Weaver
16

Une solution en une seule ligne. Ajoutez ceci n'importe où avant d'appeler le serveur côté client:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

Cela ne doit être utilisé qu'à des fins de test car le client ignorera les contrôles de sécurité SSL / TLS.

Gaspa79
la source
2
Une solution de contournement brillante pour les tests. Nous consommons un service dont le fournisseur a fait de la sécurité un enfer avec une chaîne alambiquée de certificats de sécurité et jusqu'à ce que nous puissions faire fonctionner correctement leurs certificats et leur chaînage bancals, cette solution de contournement est la seule chose qui nous permet de poursuivre le développement.
markaaronky
12

J'ai rencontré le même problème et j'ai pu le résoudre avec deux solutions: tout d'abord, j'ai utilisé le composant logiciel enfichable MMC "Certificats" pour le "Compte d'ordinateur" et j'ai fait glisser le certificat auto-signé dans le dossier "Autorités de certification racine de confiance" . Cela signifie que l'ordinateur local (celui qui a généré le certificat) fera désormais confiance à ce certificat. Deuxièmement, j'ai remarqué que le certificat avait été généré pour un nom d'ordinateur interne, mais que le service Web était accessible sous un autre nom. Cela a provoqué une incompatibilité lors de la validation du certificat. Nous avons généré le certificat pour computer.operations.local, mais avons accédé au service Web en utilisant https://computer.internaldomain.companydomain.com . Lorsque nous avons remplacé l'URL par celle utilisée pour générer le certificat, nous n'avons plus eu d'erreur.

Peut-être que le simple changement d'URL aurait fonctionné, mais en rendant le certificat fiable, vous évitez également l'écran rouge dans Internet Explorer où il vous indique qu'il ne fait pas confiance au certificat.

Jeroen-bart Engelen
la source
11

Si vous utilisez .net core, essayez ceci:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };
Grzegorz J
la source
1
Merci, ça marche. Mais cela n'a rien à voir avec .net core. C'est une recette universelle :)
Alexander
7

Veuillez suivre les étapes suivantes:

  1. Ouvrir le lien de service dans IE.

  2. Cliquez sur la mention d'erreur de certificat dans la barre d'adresse et cliquez sur Afficher les certificats.

  3. Chèque émis à: nom.

  4. Prenez le nom émis et remplacez la mention localhost dans le nom de l'adresse de base du point de terminaison du service et du client par un nom de domaine complet (FQDN).

Par exemple: https: // localhost : 203 / SampleService.svc To https: // INL-126166-.groupinfra.com : 203 / SampleService.svc

Rahul Rai
la source
Super, merci pour cette réponse! Résolu les problèmes sans apporter de modifications au code.
Vipin Dubey
6

En plus des réponses ci-dessus, vous pouvez rencontrer cette erreur si votre client exécute la mauvaise version de TLS, par exemple si le serveur exécute uniquement TLS 1.2.

Vous pouvez le réparer en utilisant:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
NMrt
la source
dans mon cas, la réponse acceptée ne m'a pas aidé, mais celui-ci a fait un tour
Sergey
C'est la seule réponse qui a corrigé l'erreur dans mon cas.
Tolga
5

J'ai eu le même problème. J'avais également ajouté des certificats CA dans le magasin local, mais je l'ai fait de la mauvaise manière.

En utilisant la console mmc (Démarrer -> Exécuter -> mmc ), vous devez ajouter composant logiciel enfichable Certificats en tant que compte de service (en choisissant le compte de service d'IIS) ou compte d'ordinateur (il ajoute pour chaque compte sur la machine)

Voici une image de ce dont je parle Ajouter un composant logiciel enfichable pour un compte de service ou le compte d'ordinateur

À partir de maintenant, vous pouvez ajouter des certificats d'autorités de certification (autorités de certification racines de confiance et autorités de certification intermédiaires ), et tout fonctionnera correctement

dar0x
la source
4

J'ai eu un problème similaire avec le certificat auto-signé. Je pourrais le résoudre en utilisant le nom du certificat identique au nom de domaine complet du serveur.

Idéalement, la partie SSL doit être gérée côté serveur. Le client n'est pas tenu d'installer un certificat pour SSL. En outre, certains des articles mentionnés sur le contournement du SSL du code client. Mais je suis totalement en désaccord avec cela.

Umesh Bhavsar
la source
3

Je viens de faire glisser le certificat dans le dossier "Autorités de certification racines de confiance" et voilà, tout a bien fonctionné.

Oh. Et j'ai d'abord ajouté ce qui suit à partir d'une invite de commande administrateur:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

Je ne suis pas sûr du nom dont vous avez besoin pour l'utilisateur (le mien est norvégien comme vous pouvez le voir!) user=NT-AUTHORITY/INTERACTIVE:?

Vous pouvez voir toutes les URL existantes en exécutant la commande: netsh http show urlacl

Haguna
la source
0

Cela s'est produit lors de la tentative de connexion au service WCF via. l'IP par exemplehttps://111.11.111.1:port/MyService.svc lors de l'utilisation d'un certificat lié à un nom, par exemple mysite.com.

Passer au https://mysite.com:port/MyService.svcrésolu.

lko
la source
0

Je viens de corriger un problème similaire.

J'ai réalisé que j'avais un pool d'applications qui s'exécutait sous un compte qui n'avait l'autorisation de lecture que sur le certificat utilisé.

L'application .NET pouvait récupérer correctement le certificat, mais cette exception n'était levée que lorsque GetRequestStream () était appelé.

Les autorisations de certificats peuvent être gérées via la console MMC

Alberto
la source
0

Si vous utilisez .net core, pendant le développement, vous pouvez contourner la validation de certificat à l'aide des directives du compilateur. Cette méthode validera uniquement le certificat pour la publication et non pour le débogage:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif
Panayiotis Hiripis
la source
-6

Ajoutez ceci à votre code client:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });
user662285
la source
4
Cette réponse n'est pas très bonne, car elle n'explique pas les risques associés au code.
daveD