SSL Client Authentication
Client certificates contain information that identifies the user, as well as information about the organization that issued the certificate. For example, a standard X.509 certificate contains at least the following:
Signature algorithm ID
Subject (user) name
Subject public key information
Signature on the fields just listed
|SSL client certificates are only supported in Windows CE .NET 4.1 and later.|
It is possible to require or allow a client to provide a certificate during SSL negotiations. Whether to require (or allow) a client certificate is set on a per-virtual-root basis. The Web Server will request the Web client to send a client certificate, if it has one, if either of the following flags are set as the P parameter of the requested virtual root. For more information, see Virtual Path Registry Settings.
The following code example shows how to set the flags to require or allow SSL client certificates.
HSE_URL_FLAGS_REQUIRE_CERT (0x00000040) Requires SSL client certificates. HSE_URL_FLAGS_NEGO_CERT (0x00000020) Allows SSL client certificates.
If the client does not provide a certificate to the Web Server and
HSE_URL_FLAGS_REQUIRE_CERT was set, the request will terminate and an error will be returned to the client. If the
HSE_URL_FLAGS_NEGO_CERT but not the
HSE_URL_FLAGS_REQUIRE_CERT was set, then the request will continue.
There are two primary ways to use client certificates on the server. One is to write an ISAPI extension that uses information in the client certificate to determine information such as what operations on the extension the user is allowed to perform. In this case, the ISAPI extension maps the user name and permissions allowed for itself. The other way is to use the Web Server to map client certificates before processing the request further.
If the following flag is set in the P value of the virtual root the Web Server will attempt to match the information in the certificate to a user name upon successfully receiving the SSL client certificate.
HSE_URL_FLAGS_MAP_CERT 0x00000080 // Map SSL cert to user account
With IIS, the
HSE_URL_FLAGS_MAP_CERT flag will map the certificate information to an NT user account. Since Windows Embedded CE does not have user accounts, this flag will instead map to a Web Server pseudo-user. This user is then checked against the UserList registry setting for the virtual root that is being accessed, as described in Web Server Access Rights. For information about UserList, see Virtual Path Registry Settings.
Client certificates are mapped to users based on the IssuerCN and/or the certificate's serial number. Web Server pseudo users are enumerated in the registry and specified under the Web site's SSL\Users key. The name of each registry key under the SSL\Users key specifies the pseudo user's name. The values IssuerCN and SerialNumber under each user name registry entry specify the IssuerCN and SerialNumber of the certificate that must be provided in order to map the user. IssuerCN is a REG_SZ. SerialNumber is a binary entry.
The following example shows how to setup a Web Server registry to require SSL client certificates for a restricted virtual root, create a list of users, and map the certificates to the user name. In this scenario, we want to limit access to the virtual root /Accounts to the users Alice, Bob, and Carol.
First we setup the Web Server to use SSL. The certificate name CE Server Certificate must already be installed in the Web Server's certificate store. This is the server certificate that the Web Server sends on all SSL negotiations, not to be confused with the client certificate. It is also assumed that the issuer of the client certificates will have already been setup as a trusted authority in the Windows Embedded CE trusted or privileged security store.
[HKEY_LOCAL_MACHINE\HTTPD\SSL] "IsEnabled"=dword:1 "CertificateSubject"= "CE Server Certificate"
Next we setup the virtual root /Accounts.
A=1 signifies that a user must be authenticated to gain access to resources under this virtual root.
P= HSE_URL_FLAGS_EXECUTE | HSE_URL_FLAGS_REQUIRE_CERT | HSE_URL_FLAGS_MAP_CERT | HSE_URL_FLAGS_SSL128. This allows the virtual root resources to be executed — that is, to run the ISAPI extension), requires the client to send SSL certificates, maps the certificate to a user account, and requires 128 bit encryption. The UserList specifies the users who will be allowed to access this page.
[HKEY_LOCAL_MACHINE\HTTPD\VROOTS\/Accounting/] ; ISAPI extension that we're placing restricitons on. @="\windows\accounting.dll" "A"=dword:1 "P"=dword: 0x000001C4 "UserList"="alice;bob;carol"
Now we list our three users and the SSL client certificates that will map to them. Alice and Bob were issued their certificate from CompanyIssuer, which is the certificate server for their company. Since we do not want to allow access to anyone that has a certificate issued from CompanyIssuer, we further restrict access based on the serial number of the certificate. In Carol's case, AccountingIssuer is more restrictive about to whom certificates will be issued in the first place. So as not to need to enter a different serial number for each user that has a certificate from AccountingIssuer, we do not include the serial number in this case.
[HKEY_LOCAL_MACHINE\HTTPD\SSL\USERS\Alice\MAP-1] "IssuerCN"="CompanyIssuer" "SerialNumber"=hex: 01,02,03,04,00,00,00,00,00,05 [HKEY_LOCAL_MACHINE\HTTPD\SSL\USERS\Bob\MAP-1] "IssuerCN"="CompanyIssuer" "SerialNumber"=hex: 01,02,03,04,00,00,00,00,00,06 [HKEY_LOCAL_MACHINE\HTTPD\SSL\USERS\Carol\MAP-1] "IssuerCN"="AccountingIssuer"
That is all that is needed for the registry.
When a request comes in over SSL to the virtual root /Accounting, the Web Server will request a client certificate and fail if one is not provided (due to
HSE_URL_FLAGS_REQUIRE_CERT being set.)
If the certificate is provided, the Web Server will run through each of the users and try to match the provided IssuerCN and SerialNumber.
Before accessing accounting.dll, the Web Server will verify that the user mapped by the client cert is specified is present in the UserList. If this is not the case, the Web Server will return an error, but will not try to perform Basic or NTLM authentication on this virtual root, even if Basic and/or NTLM are supported by the Web Server. If a client certificate is requested for a given virtual root, no other form of authentication will be supported other than mapping that client certificate to the user name as described above.
Before retrieving any information from the client certificate, the Web Server will first verify that the certificate is valid. To be valid the certificate must have a valid date, be issued from a trusted authority, among other requirements. The Web Server makes a call to CertGetCertificateChain to make this determination. If there is an error, CertGetCertificateChain will specify an error of the form CERT_TRUST_xxx (CERT_TRUST flags are defined in Wincrypt.h). If the value specified is anything other than CERT_TRUST_NO_ERROR, by default the Web Server will terminate the request and return an error to the client.
It is possible to override the Web Server's default rejection of invalid certificates. To enable this, in the base SSL registry key for the Web site set the registry value CertTrustOverride to be a DWORD of the CERT_TRUST_ error flags that you are willing to have the Web Server ignore. The Web Server will ignore these (and only these) error codes.
For instance, to have the default Web site accept a certificate authority that CertGetCertificateChain brings up errors on, set (
CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT) in CertTrustOverride, as follows.
[HKEY_LOCAL_MACHINE\COMM\HTTPD\SSL] CertTrustOverride=dword: 0x00010020
|It is highly recommended that CertTrustOverride not be modified from the default value, due to security concerns. This functionality is provided as a last ditch resort for scenarios where proper certificates cannot be issued.|
Due to the way the SSL protocol works, along with the security policy of the Web Server, there may be some difficulty posting extremely large amounts of data to the Web Server if SSL client certificates are being used in the same request.
The way the Web Server typically handles large POST requests (even when doing SSL with no client certificates) is to read the first PostReadSize size of bytes into a buffer and stop reading. It is the responsibility of the ISAPI extension to continue to receive more data at this point by making repeated calls to ReadClient. The Web Server does this to make sure that it never tries to allocate a buffer that is too large and to guard against malicious users sending enormous amounts of data to the device to exhausts its resources.
When a request comes into a virtual root using a client certificate, the Web Server is unaware that it will need a client certificate until after the initial SSL handshake because it will not know what virtual root is being requested until after the handshake is complete. When it sees it needs a client certificate, the Web Server will request one in the middle of the request. It is possible that the Web client will send its client certificate after it has sent greater than PostReadSize amount of bytes. If the Web Server has not received the SSL client cert before reading PostReadSize bytes, it will terminate the request.
To work around this, either increase the size of PostReadSize to be the maximum size of the buffer you are willing to accept. As an alternative, you can create a connection to the virtual root that requires client certificates that does not POST data and that does a keep-alive. On this connection the client certificate can be obtained by the Web Server without having to deal with this issue. On the next request (as long as keep-alives are used), there will be no need for the client to resend its certificate and the previous scenario will not be an issue.