Client side <serviceCertificate> and <identity> elements - wcf

MSDN for <serviceCertificate>says this
This configuration element specifies the settings used by
the client
to validate the certificate presented by the service using SSL
authentication.
MSDN for <identity> says this
In the handshake process between the client and service, the Windows
Communication Foundation (WCF) infrastructure will ensure that the
identity of the expected service matches the values of this element,
and thus can be authenticated.
As I understand, both these elements are used to authenticate service to the client.
Question: Could someone please elaborate and let me know the difference?
Thanks!

These are quite different.
As its name implies, the <identity> element is used by the client to identify a service, answering the question "Who are you?" It contains many child elements that can be used for this purpose - as there are many ways of identifying a service: certificate, SPN, UPN, etc.
<serviceCertificate> specifies an actual X.509 certificate used to authenticate a client or service, helping to answer the question "How can I be sure you are who you say you are?"

Related

WCF: Cannot find the X.509 certificate

Error when browsing Outlook.svc from IIS.
Cannot find the X.509 certificate using the following search criteria: StoreName 'My', StoreLocation 'LocalMachine', FindType 'FindBySubjectName', FindValue ''
Because your WCF service uses a certificate to secure communication, it is usually based on the transport layer or the message layer to encrypt and sign messages.
This makes it necessary to configure a certificate for the service when hosting the WCF service in IIS.
Certificates are usually stored in the certificate Store of windows computers and are divided into current users and local machines.
You can access it using the following shell commands.
Current User Store: Certmgr.msc
Local Machine Store: Certlm.msc
https://learn.microsoft.com/en-us/windows-hardware/drivers/install/local-machine-and-current-user-certificate-stores
The error details mainly indicate that there isn’t a specific certificate that meets the search condition in the Local Machine certificate store.
To solve the problem, we could specify another certificate or change the security mode of the WCF service.
Feel free to let me know if there is anything I can help with.

WCF client and service authentication via certificates

I just don’t seem to get my head around this. I need to enable via code or config, a way where in the client can authenticate the service and also service can authenticate the client.
What does
<Identity> play a role in this?
Can i specify the client credential here?
And what needs to be filled here
<serviceCertificate>
</serviceCertificate>
<windowsAuthentication>
</windowsAuthentication>
I need to understand the way the certificate are exchanged and various ways of doing so.

WCF Security: what is the way to go with many servers and server identity being unimportant?

So I've done some research and found out that, indeed, WCF prevents us from sending username/password in clear text. The basic argument is that "it is not secure, because it allows a hacker to intercept credentials". Hence, a secure channel is required, and for that, the server needs an X.509 certificate.
Ok, point taken. But here's a problem: said certificate needs to be trusted on the client. But why?
A trusted certificate is commonly used on Internet-open servers to enable clients to verify the server's identity (i.e. make sure they're not connecting to a bogus server). But what if server's identity is not important in a given context?
My product consists of two applications. Let's call them client and server1.
The basic scenario is this:
The user connects to a network that has one or more of those servers installed and opens the client application
The client uses WCF discovery to find any servers on the network
(or, optionally, the user can specify server's address manually)
The user chooses which server he wants to connect to, and then enters username/password for that server
The connection is established, the client does some calls to the server on behalf of the user
One can see how in this scenario, the user doesn't need to verify that the server is not bogus. Even if he wanted to, there is nothing to verify against. After all, the only thing we know about the server is that it supports our protocol, and that fact doesn't need verification.
In other words, I need communication confidentiality and client authentication, but not server authentication.
It would be bad enough to ask my customers to purchase a certificate from a trusted authority for every server, but it would be even worse not being able to explain why exactly they need it.
Given all the above mentioned points, I see three possibilities:
The WCF designers simply didn't think about this scenario. That is, WCF doesn't support it.
(at least natively; yes, I am aware of Yaron Naveh's creation).
I am missing some detail that implies that the certificate does have to be trusted after all.
There is a way (unknown to me) to use certificate just for encryption and not for server's authentication, and thus avoid making it a trusted one.
So the question is:
Which of these three options is the case? And if it's the third one, what is that way? (My fingers are crossed for number 3 :-)
.
.
1 It is important to note that the term "server" is not used in the "Internet" sense here. That is, the server is not a computer on the web, but rather a program that gets installed on some computer, not necessarily even connected to the Internet. And there going to be many of these, installed by different customers on their sites, most times without my direct knowledge.
To avoid certificate validation, add following in system.serviceModel/behaviors/endpointBehaviors/behavior/clientCredentials/serviceCertificate element:
<authentication certificateValidationMode="None" />
Each "server" doesn't have to have it's own unique identity. All "server" instances could use the same identity and you just configure the client to expect that identity no matter which "server" it's talking to. That way the client doesn't care as long as all "servers" use the same identity. Essentially this boils down to buying/generating a single certificate for the "server" identity and just making sure that all your "server" instances use this identity in their communication.
From a "server" configuration perspective you just make sure that keypair is installed and use the <serviceCertificate> configuration element to use it:
<behavior name="MyServiceBehavior">
<!-- ... -->
<serviceCertificate findValue="AcmeCorpServer" storeLocation="LocalMachine" storeName="My" X509FindType="FindBySubjectName" />
<!-- ... -->
</behavior>
And then on clients you just make sure you have the public key installed and configure the endpoint behavior:
<behavior name="MyEndpointBehavior">
<!-- ... -->
<clientCredentials>
<clientCertificate findValue="MyClient" storeLocation="CurrentUser" storeName="My" X509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="AcmeCorpServer" storeLocation="CurrentUser" storeName="TrustedPeople" X509FindType="FindBySubjectName" />
</serviceCertificate>
</clientCredentials>
<!-- ... -->
</behavior>
This is more of a coarse grained approach to security, but it seems like it would fit your particular needs. It's basically like saying "allow my client to talk to any service that might ever exist as long as we can validate the identity to be our identity".
Finally, if you can't/don't want to do this with configuration for some reason (i.e. you can't/don't want to put things into certificate stores) there's ways to do it programatically as well by loading the X.509 certificate manually and then assigning it to the client/server behavior at runtime.

WCF NetTcpBinding Security - how does it work?

I am encountering the following problems trying to work through the quagmire of settings in WCF...
I created a WCF client-server service using a NetTcp binding. I didn't make any changes to the security settings and when running on one machine it works very nicely. However, when I ran my client from another machine it complained that the server didn't like the security credentials that were sent.
I understand now that NetTCP is "secured" by default and that my client would have been passing the wrong security details - namely the Windows user name and password (or some form of domain authentication) to my server which as they are not running on the same domain it would not have liked.
However, what I don't understand is as follows:
I haven't specified any security in my binding - does the standard settings expect a Windows user name or password to be sent?
I don't have any certificate installed on my server - I understand that NetTCP bindings need some form of public private key to protect the credentials - yet this seemed to work when both client and server were on the same machine - how was the data getting encrypted? Or wants it as WCF knew it was on the same machine and encryption isn't needed?
I have had to set my security mode on my client and server to "none" now and they connect nicely. However is there a way to encrypt my data without a certificate?
Finally... what is the difference between Transport and Message security?
To check my understanding (excuse the scenario!) message security is like if I sent a letter from person A to person B and I encode my hand writing to ensure that if anyone intercepts it they cannot read it? Transport Security is if I decide to have my letter sent by armed transport so that no one can get at it along the way?
Is it possible to have any form of encryption in WCF without a certificate? My project is a private project and I don't want to purchase a certificate and the data isn't that sensitive anyway so it's just for my own knowledge.
The default client credential type for NetTcpBinding is Windows Authentication. For Windows Authentication to work both client and server must be in the same domain, or mutually trusting domains (which in your case you do not have).
If both client and server were on the same domain, WCF would handle the mechanics of Windows Authentication "behind the scenes". And when both client and server are on the same machine they are effectively within the same domain, so Windows can use its own mechanisms to handle the encryption and decryption. It will only do this within mutually trusting domains, though.
If you don't have mutually trusting client and server domains, then the client and server must have some other way to determine if they trust each other with their keys. That's where certificates come in. The client and the server have their own certificates (or the server can issue the client a certificate).
Transport security is like encrypting the outside of the envelope as well as the inside. The downside is if you have to pass the envelope to someone outside your own organization, they need a decryption key just to know where the envelope is supposed to go--now they can read the message in the envelope also. On the other hand, transport security is faster--it requires less security overhead data getting passed along with your envelope.
Message security encrypts your message, but the envelope can be read by the postal workers (the internet and its routers). Only the source and the destination have the keys to decrypt the message, but the intermediaries can properly route your message.
To summarize: to use encryption over the NetTcpBinding both client and server must be within a domain (or mutually trusting domains) or you must have a key exchanging certificate.
Edit: I was asked for some example code--here is a binding element in XAML. It would normally be placed within a netTcpBinding element.
<binding name="Secure" listenBacklog="4000" receiveTimeout="00:20:00" sendTimeout="00:20:01"
maxReceivedMessageSize="2147483647" maxConnections="200" portSharingEnabled="true">
<!-- ~2 GB -->
<readerQuotas maxStringContentLength="2147483647"/>
<!-- ~2 GB max string content length -->
<security mode="Message">
<transport clientCredentialType="None" protectionLevel="EncryptAndSign"/>
<message clientCredentialType="None"/>
</security>
</binding>
The important part is the security element. For transport security one would change the mode attribute to "Transport". More than likely the clientCredentialType would not be "None" but rather "Certificate", "Ntlm", or "Windows" depending on the context.

dns tag is web.config WCF

What is the significance of this tag in the WCF client config? What does it actually mean. I have seen people put the name of their certificates in this tag like
<dns value="CertificateName">
Can any WCF experts out there give me a detailed explanation...
I am assuming that the dns tag is the client -> endpoint -> indentity -> dns tag.
In that case the value is the name of the server that the client expects to be talking to.
http://msdn.microsoft.com/en-us/library/ms733130.aspx
If you want to use a certificate to identify the service you would use the certificate tag or the rsa tag.
The service is identifying itself by means of a certificate installed on the machine where your service is running.
The <dns> tag defines what the "subject name" (or identity) of that service certificate is going to be, so that the client can check to see whether the certificate presented by the service to "prove" its identity is really what it expected it to be.
There's a really good set of blog post here that talk about WCF security scenarios - one of them (part 4) is Internet scenario which mentions the service authenticating itself by means of a certificate as well.
Hope this helps a bit
Marc