Jul 24 2008
WCF, certificates, event logs and silly security exceptions
my friend was working on certificate based WCF transport messages. she prototyped a demo, and was testing it out. she kept on hitting the following exception:
Found multiple X.509 certificates using the following search criteria: StoreName ‘My’, StoreLocation ‘LocalMachine’, FindType ‘FindBySubjectName’, FindValue ”. Provide a more specific find value.
the error message could not have been more concise.. I had a look at the code, and there was nothing programmatic to verify. it was all WCF configuration driven [that I like so much J].
the configuration for binding was as follows:
<bindings>
<wsHttpBinding>
<binding name=“wsHttpEndpointBinding“>
<security mode=“Message“>
<message clientCredentialType=“Certificate“ />
</security>
</binding>
</wsHttpBinding>
</bindings>
the configuration for service credentials was as follows:
<serviceCredentials>
<clientCertificate>
<certificate storeLocation=“LocalMachine“ storeName=“My“
x509FindType=“FindBySubjectName“ />
<authentication revocationMode=“Online“ trustedStoreLocation=“CurrentUser“ />
</clientCertificate>
<serviceCertificate findValue=“rajanadar.com“ storeName=“My“
storeLocation=“LocalMachine“
x509FindType=“FindBySubjectName“ />
</serviceCredentials>
I thought, the search ‘rajanadar.com’ may be returning more than one certificate from the store. (may be due to root certificates etc.., I don’t know)
I checked my certificate store, and gave a specific (unique) Subject Name and tried different things.
no luck, still the same issue.
after a little observation, I read the error message a little more carefully.. (why didn’t I do this the first time?)
Found multiple X.509 certificates using the following search criteria: StoreName ‘My’, StoreLocation ‘LocalMachine’, FindType ‘FindBySubjectName’, FindValue ”. Provide a more specific find value.
it complained of a blank ‘FindValue’
then it struck me that we missed the FindValue for the client certificate, not the service certificate.
The corrected configuration was:
<serviceCredentials>
<clientCertificate>
<certificate storeLocation=“LocalMachine“ storeName=“My“
x509FindType=“FindBySubjectName“ findValue=“uniqueclient.rajanadar.com “ />
<authentication revocationMode=“Online“ trustedStoreLocation=“CurrentUser“ />
</clientCertificate>
<serviceCertificate findValue=“server.rajanadar.com“ storeName=“My“
storeLocation=“LocalMachine“ x509FindType=“FindBySubjectName“ />
</serviceCredentials>
that solved the issue. it was a simple silly mistake. (obviously only after it was caught)
the next error I encountered, sounded something like:
Unhandled Exception: System.Net.WebException: The underlying connection was closed: Could not establish secure channel for SSL/TLS.
Fortunately, my past sleight of hand on WSE and SSL certificates, quickly reminded me that, when dealing with Web Applications, I need to give sufficient access permissions to the aspnet user account, to the PFX files of the certificates.
I modified the access permissions of the PFX file in question, (yeah the \AppData\Microsoft\Crypto\RSA\MachineKeys path) and the application seemed to work without any more issues. silly things, nonetheless there’s a first time..
p.s. the aspnet user account permission issue reminds me of one more classic issue that I encountered most of the times..
[SecurityException: Requested registry access is not allowed.]
Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)
System.Diagnostics.EventLog.SourceExists(String source, String machineName) +79
System.Diagnostics.EventLog.SourceExists(String source)
this is again because, creating a new event log or event source, needs registry write permissions, typically not possessed by the aspnet account.
Solution: initially, I used to grant write permissions to the registry keys
(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\NewLog or HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\Source)
But then, this is not a good security approach. during the lifetime of the application, it just needs to write to the event logs and never create new ones. Hence I created the new registry keys (effectively new event logs/sources) using my Installers, and granted read permissions to the web application accounts. this sounded good.
there’s a solution to every problem; given enough time and sometimes, well, just time…