When UID is not UID…
So today, I had to juggle with client side certificate authentication. No big deal, one would think. This is 2006, not 1996 and client side certificates are well established. Little did I know. Little did I know…
Our request was, that the certificate contains a number of fields and got signed by our own, in-house CA. This is not a big thing, TinyCA did the job really nicely. Loading the user certs into the browser is no big deal either.
So I set up my Apache webserver (which is 2.0.54 included with Fedora 4):
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/server.crt
SSLCertificateKeyFile /etc/pki/tls/private/server.key
SSLCertificateChainFile /etc/pki/tls/certs/CA.crt
SSLCACertificateFile /etc/pki/tls/certs/CA.crt
[...]
<Limit...>
SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/
and %{SSL_CLIENT_I_DN_O} eq "CA Authority" )
SSLVerifyDepth 1
SSLVerifyClient require
</Limit...>
Hey, it works. Really nice, too. However, now comes the twist. My certificates look like this:
[Wed May 17 13:15:13 2006] [debug] ssl_engine_kernel.c(1166): Certificate Verification: depth: 0, subject: /C=DE/ST=Bayern/L=Nuernberg/O=Company/OU=Company Users/CN=Henning Schmiedehausen/emailAddress=henning@company/UID=henning,
issuer: /C=DE/ST=Bayern/L=Nuremberg/O=CA Authority/OU=Administration/CN=CA/emailAddress=admin@company
Now I wanted to use the certificates to set the user name. With Apache, this is easy:
SSLUserName SSL_CLIENT_S_DN_UID
But it does not work! The httpd doesn’t fill out this variable. However, the %{SSL_CLIENT_S_DN} field does contain an oid for userId. But mod_ssl ignores it. What the…?
This is, what my certificate contains:
426:d=3 hl=2 l= 23 cons: SET 428:d=4 hl=2 l= 21 cons: SEQUENCE 430:d=5 hl=2 l= 10 prim: OBJECT :userId 442:d=5 hl=2 l= 7 prim: PRINTABLESTRING :henning 451:d=2 hl=4 l= 546 cons: SEQUENCE
This is, what Apache httpd 2.0.x expects from the certificate (in modules/ssl/ssl_engine_vars.c, ~ line 380)
/* This has been removed in OpenSSL 0.9.8-dev. */
#ifdef NID_uniqueIdentifier
{ "UID", NID_uniqueIdentifier },
#endif
And OpenSSL 0.9.7f (also Fedora Core 4) tells you
openssl/objects.h: #define SN_uniqueIdentifier "UID" #define LN_uniqueIdentifier "uniqueIdentifier" #define NID_uniqueIdentifier 102 #define OBJ_uniqueIdentifier OBJ_X509,45L openssl/obj_mac.h: #define SN_userId "UID" #define LN_userId "userId" #define NID_userId 458 #define OBJ_userId OBJ_pilotAttributeType,1L
So I messed up. Not a big problem. UID means “uniqueIdentifier” and is not the same as “userName”. Should be corrected easily?!?
Enter Fedora Core 5 and Apache 2.2…
modules/ssl/ssl_engine_vars.c:
#ifdef NID_x500UniqueIdentifier /* new name as of Openssl 0.9.7 */
{ "UID", NID_x500UniqueIdentifier },
#else /* old name, OpenSSL < 0.9.7 */
{ "UID", NID_uniqueIdentifier },
#endif
openssl/objects.h:
#define SN_uniqueIdentifier "UID"
#define LN_uniqueIdentifier "uniqueIdentifier"
#define NID_uniqueIdentifier 102
#define OBJ_uniqueIdentifier OBJ_X509,45L
openssl/obj_mac.h:
#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
#define NID_x500UniqueIdentifier 503
#define OBJ_x500UniqueIdentifier OBJ_X509,45L
#define SN_userId "UID"
#define LN_userId "userId"
#define NID_userId 458
#define OBJ_userId OBJ_pilotAttributeType,1L
So, NID_uniqueIdentifier is different from NID_x500UniqueIdentifier. Which in turn seems to contain a bit string (according to the uniqueIdentifier definition (the 45L in the OBJ_… definition is the same as the 45 oid subtype on that page). And Apache 2.2 uses a different NID_ value, depending whether it is compiled using openssl 0.9.7 or openssl 0.9.8.
And, most of the times, people (and CAs!) will not fill out the uniqueIdentifier field. They will use the userId field (which by the way is documented here. And they will wonder, why their SSL_CLIENT_S_DN_UID fields are never filled out, even though there is an UID in the DN of the certificate.
Is that a bug? You decide. apache client side certificates fedora openssl