AcquireCredentialsHandle() a échoué avec l’erreur 0X8009030D

Récemment, il m’est arrivé une bonne prise de tête avec cette erreur lorsque j’appelais un web service: AcquireCredentialsHandle() a échoué avec l’erreur 0X8009030D (ou en anglais : AcquireCredentialsHandle() failed with error 0X8009030D).

Le contexte

Nous devions pour l’un de nos client utiliser un web service d’un partenaire. Ce web service nécessite l’utilisation de créditentials mais aussi d’un certificat X509. L’installation du certificat n’a pas posé de problème. Pourtant, l’erreur générale « La demande a été abandonnée : Impossible de créer un canal sécurisé SSL/TLS. » est vite apparue.

Pour avoir un petit plus d’informations sur cette erreur, j’active les logs en ajoutant dans le fichier web.config ce code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<system.diagnostics> 
<trace autoflush="true"/>
    <sources>
        <source name="System.Net" maxdatasize="1024"> 
<listeners>
                <add name="TraceFile"/>
            </listeners>
        </source>
        <source name="System.Net.Sockets" maxdatasize="1024">
<listeners>
                <add name="TraceFile"/>
            </listeners>
        </source>
    </sources>
    <sharedListeners>
        <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/>
    </sharedListeners>
    <switches>
        <add name="System.Net" value="Verbose" />
        <add name="System.Net.Sockets" value="Verbose" />
    </switches>
</system.diagnostics>

Ce code va nous générer un fichier trace.log, contenant comme son nom l’indique la trace suite à l’exécution de notre code posant problème. C’est ainsi que nous avons découvert l’exception « AcquireCredentialsHandle() a échoué avec l’erreur 0X8009030D. »

Rapidement, nous trouvons que c’est dû à un problème de permissions : IIS n’a pas le droit d’accéder au certificat. Pour régler le problème, l’outil winhttpcertcfg (télécharger) résout parfaitement ce problème. Je lance donc la commande suivante :

1
winhttpcertcfg -i certificat.pki -c LOCAL_MACHINE\My -a NetworkService -p password

Bien que le retour de winhttpcertcfg m’informe d’un état succesfull, je n’arrive toujours pas à contacter mon web service. Il suffit simplement si vous utilisez un pool d’application de donner les droits à ce pool d’application qui fait tourner votre site et non à l’utilisateur qui fait tourner IIS.

Vous pouvez maintenant récupérer le certificat avec le code suivant:

1
2
3
4
5
6
string certPath = @"c:\\certificate.cer";
 
WebService ws = new WebService();
ws.ClientCertificates.Add(X509Certificate.CreateFromCertFile(certPath));
ws.Credentials = new NetworkCredential("XXX", "XXX");
string resp = ws.aMethod();

Chose plus étrange encore, chez moi, ce code nous retournait bien le bon certificat dans la collection de certificats :

1
2
3
4
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindBySerialNumber, 
"serial number", true);

Le certificat était bien ajouté au web service, et pourtant, l’erreur était toujours présente. L’utilisation du certificat à partir du fichier .cer lui ne pose aucun problème. Pendant mes recherches, j’ai remarqué que chez d’autres personnes ayant exactement la même erreur, c’est l’inverse qui peut se produire : le .cer ne fonctionne pas mais une recherche en magasin oui.

Un remerciement à l’auteur de ce post qui m’a bien aidé pour résoudre cette erreur.