Feature #1288

SSL Client Certificate validation.

Added by nmaier over 7 years ago. Updated over 2 years ago.

Status:FixedStart date:
Priority:NormalDue date:
Assignee:-% Done:

100%

Category:core
Target version:1.4.25
Missing in 1.5.x:No

Description

I took the opportunity to port #921 to trunk, enhance it and the port it back to 1.4.x branch ;)

Lighttpd should support SSL Client Certificate validating. There are a lot of good use-cases for this.

And most importantly Apache mod_ssl supports it :p

lighty-clientvalidation-trunk.path - patch for current trunk (6.94 KB) nmaier, 2007-08-06 00:45

lighty-clientvalidation-trunk.patch Magnifier - fixing segfault, wrong patch location (see further comments) (6.54 KB) nmaier, 2007-08-13 20:06

lighty-clientvalidation-1.4.x.patch Magnifier - fixing segfault, wrong patch location (see further comments) (6.71 KB) nmaier, 2007-08-13 20:06

lighty-clientcert.tar.gz - fixing segfault, wrong patch location (see further comments) (13.6 KB) nmaier, 2007-08-13 20:08

lighty-clientvalidation-1.4.x.2.patch Magnifier - fixed environment variable duplication when using mod_rewrite (6.64 KB) presbrey, 2007-08-24 02:35

lighty-clientvalidation-serialenv.patch Magnifier - Patch to set serial number of the client certificate into environment -- laurent.corbes (1.37 KB) Anonymous, 2008-05-21 15:18

lighty-clientvalidation-1.4.20.patch Magnifier (6.91 KB) akrus, 2008-12-03 06:47

lighty-clientvalidation-1.4.21.patch Magnifier (8.74 KB) akrus, 2009-03-05 08:51

lighty-clientvalidation-1.4.22.patch Magnifier - patch for 1.4.22 (please read comment below) (8.74 KB) bjuchli, 2009-03-16 18:02

lighttpd-clientverify2-1.4.22.patch Magnifier - patch for 1.4.22 with SSL_CLIENT_VERIFY variable (7.53 KB) oleg.smirnov, 2009-03-25 15:20

lighty-sslcert-r2585.patch Magnifier - patch to r2585 (trunk) (6.9 KB) presbrey, 2009-07-14 14:48

lighttpd-1.4.28-clientvalidation-serialenv.patch Magnifier (1.11 KB) cicik, 2010-10-23 13:54


Related issues

Duplicated by Feature #921: Client SSL Authentication Module Fixed

Associated revisions

Revision 2654
Added by stbuehler about 5 years ago

Add SSL Client Certificate verification (#1288)

Revision 2655
Added by stbuehler about 5 years ago

Add SSL Client Certificate verification (#1288)

Revision 2688
Added by stbuehler about 5 years ago

export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey)

Revision 2689
Added by stbuehler about 5 years ago

export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey)

History

#1 Updated by nmaier over 7 years ago

Lighttpd Client Certificate Validation README

A patchset to add support for validation client side ssl certificates to lighty.

Contents

  • lighty-clientvalidation-1.4.x.patch - against branches/lighttpd-1.4.x@1882
  • lighty-clientvalidation-trunk.patch - against trunk@1878
  • test/ca.crt - CA Cert used when conducting the testing
  • test/server.prem - Server Certificate (pemfile) during testing
  • test/client.p12 - Client Certificate during testing; password=test
  • test/lighttpd14.conf - test conf for the 1.4.x branch
  • test/lighttpd.conf - test conf for the trunk

New configuration

  • bool ssl.verifyclient.activate - Activate the functionality; default=disable
  • bool ssl.verifyclient.enforce - Only let clients with a cert in; default=enable
  • short ssl.verifyclient.depth - Depth of validation that OpenSSL should perform; default=9
  • string ssl.verifyclient.username - Use this Certificate entry as a username which will be passed to (most) handlers

Idea

My goal was to add validation of client certs to lighttpd.
I tried to keep somewhat compatible with apache2.

Apache will set REMOTE_USER. This implementation does as well (.username) but additionally provides all SSL_CLIENT_DN_* entries.

Webapps/handlers may use this information for fine grained authentication/identity checking.

Allowing the client to not provide a certificate (see: .enforce/REMOTE_USER/SSL_CLIENT_DN_*) might provide webapps with the ability to allow also anonymous access. This is turned off by default to protect against "lazy people" ;)

The CA file it will use is configured through ssl.ca-file.

Testing

I carried out testing on two system:
  • Ubuntu Feisty / PHP5.2.1
  • Debian Sarge / PHP5.2.3-0.dotdeb.0

Browsers tested * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty) * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a7pre) Gecko/2007072118 Minefield/3.0a7pre * Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6 * Opera/9.22 (Windows NT 5.1; de) (Opera sucks for CS btw :p) * Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)

Tested was against a static index.html, a favicon and a phpinfo() script via php5-fcgi.

Known issues

  • It seems that CA certs using other than sha1 fail.
  • At the moment lighty screams about a lot of read errors. This will also happen without this patchset

Acknowledgements

Copyright/License

The authors disclaims copyright to the code thereby placing it into public domain.
Lighttpd Devs may simply take this and interoperate this into lighty without legal problems.
(I would be thankful for some credit however, and I guess Lars would too ;))

#2 Updated by presbrey over 7 years ago

Conditional configurations prevent SSL_ environment variables from being passed to CGI. A snippet from the failing case follows:


$SERVER["socket"] == "0.0.0.0:443" {
    ssl.engine                 = "enable" 
    ssl.verifyclient.activate  = "enable" 
    ssl.verifyclient.enforce   = "enable" 
    ssl.verifyclient.depth     = 2
    server.document-root       = "/srv/www/root-ssl/" 
}

#3 Updated by nmaier over 7 years ago

Replying to presbrey:

Conditional configurations prevent SSL_ environment variables from being passed to CGI. ...

I had the code that adds the envvars in the wrong place, i.e. before the config was merged. Hence only the global context was recognized. Should be fixed by now.

Furthermore I fixed an error causing segfaults when the ssl.engine and verifyclient are enabled but later the engine is conditionally disabled again.

(Hence the ssl stuff is random and openssl crashed).

#4 Updated by presbrey over 7 years ago

Replying to nmaier:

Getting close nmaier... here's the next bug. In a script resolved via url.rewrite-once (i.e: url.rewrite-once += ( "^/main/do/([[^\]]+)(\??.*)" => "/main/$1.php$2" )), environment variables' values are injected twice producing duplicated values:

_ENV[SSL_CLIENT_S_DN_C]    US, US
_ENV[SSL_CLIENT_S_DN_ST]    State, State
_ENV[SSL_CLIENT_S_DN_CN]    presbrey, presbrey
_ENV[SSL_CLIENT_S_DN_EMAILADDRESS]    presbrey@foo.bar, presbrey@foo.bar

...etc.

#5 Updated by presbrey over 7 years ago

Replying to nmaier:

Getting close nmaier... here's the next bug. In a script resolved via url.rewrite-once (i.e: url.rewrite-once += ( "^/main/do/([^\]+)(\??.*)" => "/main/$1.php$2" )), environment variables' values are injected twice producing duplicated values:

_ENV["SSL_CLIENT_S_DN_C"]    US, US
_ENV["SSL_CLIENT_S_DN_ST"]    State, State
_ENV["SSL_CLIENT_S_DN_CN"]    presbrey, presbrey
_ENV["SSL_CLIENT_S_DN_EMAILADDRESS"]    presbrey@foo.bar, presbrey@foo.bar

...etc.

(fixed trac comment formatting)

#6 Updated by presbrey over 7 years ago

Moving the call to https_add_ssl_entries below plugins_call_handle_uri_raw in response.c fixes the issue I reported (attached new patch above).

#7 Updated by Farcaller about 7 years ago

Any hope to see it released in 1.4.x?

#8 Updated by Anonymous almost 7 years ago

Is there any chance to see support for Certificate Revocation Lists? This would be ideal in case certificates are compromised.

Great work on this patch, by the way, thanks!

-- berto

#9 Updated by hvdkamer over 6 years ago

I've backported this patch to the version shipped in Debian Etch. It works great. However in Apache the complete presented certificate can be exported in an environment variable. Is it possible to do the same in Lighttpd? See the Apache documentation:

http://www.apache-ssl.org/docs.html#SSLExportClientCertificates

With the complete certificate more rigoreus testing of the authentication would be possible. For example in this setup:

https://test.hetlab.tk/certlogin/

I accept certificates from CAcert, Ascertia, StartSSL and my own CA. I now use the e-mailaddress because that one is in the three free certificate providers tested with a mailprobe. In this case someone can use the same e-mailaddress in all certificate providers and still be mapped to the same account. Not a real problem, but with access to the certificate we could use the fingerprint in a tighter control. The above question could also be done in the application code. In this case checking the CRL is better be done in the server? Anyway, access to the complete certificate could be ice in more scenarios...

#10 Updated by lcorbes over 6 years ago

Hi all,

I don't know if it will be usefull to someone else but I add a patch to get the serial number of the client certificate in environment variables.

This allow us to check it for authentification thru a cgi script.

(The patch works on 1.4.19, will check for 1.5.x if needed).

#11 Updated by Anonymous over 6 years ago

Hi, is it possible to set ssl.verifyclient for a folder?
Something like:

$SERVER[[socket]] == "0.0.0.0:443" {
    ssl.engine                 = "enable" 
    $HTTP[[url]] =~ "^/login/" {
        ssl.verifyclient.activate  = "enable" 
        ssl.verifyclient.enforce   = "enable" 
        ssl.verifyclient.depth     = 2
    }
}

#12 Updated by Anonymous over 6 years ago

any news there? :(

#13 Updated by Anonymous over 6 years ago

What is the status of this issue?

Is there any version that supports this?

-- sinister

#14 Updated by stbuehler over 6 years ago

i plan to have a look at it after 1.4.20 got released.

#15 Updated by akrus about 6 years ago

  • % Done changed from 0 to 20

Something new here? :)

#16 Updated by akrus about 6 years ago

  • % Done changed from 20 to 0

Oops, sorry :x

#17 Updated by iuridiniz about 6 years ago

This issue is marked for 1.4.21, so will it be possible on 1.4.21? I'm currently doing this by using stunnel.

#18 Updated by stbuehler about 6 years ago

  • Patch available set to No

As long as the feature request is not "fixed" it obviously isn't included.

#19 Updated by akrus about 6 years ago

Installed lighttpd/1.4.20 with this patch yesterday, works fine, but anyway it would be great the patch is included in mainstream :)

#20 Updated by akrus about 6 years ago

Okay, someone to add CRL support? Would be great...

#21 Updated by akrus about 6 years ago

Uploaded patch for 1.4.20, minor changes, but previous one didn't work as expected :)

currently trying to make $HTTP["url"] support...

#22 Updated by kjikaqawej about 6 years ago

nmaier wrote:

Copyright/License

The authors disclaims copyright to the code thereby placing it into public domain.
Lighttpd Devs may simply take this and interoperate this into lighty without legal problems.
(I would be thankful for some credit however, and I guess Lars would too ;))

Maybe it's possible where you are, but in .ca and .us you can't put anything into the public domain, unless you're at NASA or some org. that has explicit laws allowing you to do so. Also, with your statement, you effectively put it under a permissive BSD-like licence. Nonetheless, it would be GPL (v2, dunno about v3) compatible. Note, I'm not a lawyer, and you should consult a lawyer for more information.

As for the work itself, thank you :).

#23 Updated by icy almost 6 years ago

  • Target version changed from 1.4.21 to 1.4.22

#24 Updated by akrus almost 6 years ago

why 1.4.22? lighttpd is missing this feature for sooooo long.

#25 Updated by icy almost 6 years ago

True but we wanted to get 1.4.21 out very soon and in fact there is already a RC out (see blog).
We included the most important fixes and some stuff that was particularly easy to commit in that version.
I haven't looked through all these patches and it would need some testing too. Therefor it was set for .22 like all other patches that didn't make it into .21

I am sorry that this feature didn't make it into svn yet but there are limits on how much time we can invest so something is always falling behind :(

#26 Updated by icy almost 6 years ago

  • Patch available changed from No to Yes

#27 Updated by stbuehler almost 6 years ago

  • Target version changed from 1.4.22 to 1.4.23

#28 Updated by tdussa almost 6 years ago

So why has the target version been bounced again?

#29 Updated by jkb almost 6 years ago

any chance somebody can make a patch against 1.4.21? our site really needs this feature and would hate to switch to apache for this. thanks.

#30 Updated by akrus almost 6 years ago

Here we go~

#31 Updated by icy almost 6 years ago

tdussa wrote:

So why has the target version been bounced again?

Because 1.4.22 is an important bugfix release that needs to be pushed out as fast as possible. Mostly concerning FreeBSD users.

Sorry, again :(
And thanks to nmaier, presbrey and akrus for working on the patches! I will keep an eye on this one.

#32 Updated by jkb almost 6 years ago

solved my problem, deleting previous note. sorry about this..

#33 Updated by bjuchli almost 6 years ago

Hi everybody,
i've updated the patch to 1.4.22. I've never made a patch before... so here's what i did:
Compared the the files 1.4.21 files to the 1.4.21 files that are affected by the patch (1.4.21).
Since only only /src/server.c has changed i've adjusted line 209 of the patch from

@@ -275,6 +275,7 @@
to
@@ -278,6 +278,7 @@

since the altered code section has moved down 3 lines but has not changed itself.
I think i should work. At least it seems to work for me ;-)

#34 Updated by oleg.smirnov over 5 years ago

I checked patch for 1.4.22 -- it actually works, and wrote one more feauture: now it sets SSL_CLIENT_VERIFY env variable in the same way as mod_ssl does.

#35 Updated by icy over 5 years ago

  • Target version changed from 1.4.22 to 1.4.23

Please don't set target version to something already released. It's the version that is planed to include the change.

#36 Updated by jkb over 5 years ago

hi... is there a way to do client authentication based on URL string or Agent string?

#37 Updated by akrus over 5 years ago

jkb wrote:

hi... is there a way to do client authentication based on URL string or Agent string?

You may write a new patch that will support it :) currently there's no support for this kind of authorization, only 'enable' or 'disable'.

#38 Updated by hamar over 5 years ago

How can I authenticate users with certificates coming from multiple CAs? Is there a way to configure the CA certificate path, something equivalent to the SSLCACertificatePath directive in apache?

#39 Updated by nipil over 5 years ago

hamar wrote:

How can I authenticate users with certificates coming from multiple CAs? Is there a way to configure the CA certificate path, something equivalent to the SSLCACertificatePath directive in apache?

As far as i know, you can add the different CA certificates to the ca-file. Maybe you could ask hvdkamer (who posted above), he does this kind of multiple acceptance in his testbed located at https://test.hetlab.tk.

#40 Updated by stbuehler over 5 years ago

Okay... how to get this upstream: I want one clean patch for the latest released version (1.4.22 now). Porting it to trunk shouldn't be too difficult after that.

This means that the involved developers should be included in that patch (if they want to), and all used environment variables should be documented; and i think it would be nice to have some more "standard" (i.e. Apache) variables there.

I tried to find the time to do this myself... but as you see, nothing happend yet. So if you want to help getting this upstream, you know what to do :)

#41 Updated by stbuehler over 5 years ago

  • Target version changed from 1.4.23 to 1.4.24

#42 Updated by presbrey over 5 years ago

Attached patch to latest trunk (r2585). Compatible with GSSAPI patch (#1899).

#43 Updated by nicolas314 over 5 years ago

Just my 2 cents on the topic: mod_ssl forwards a lot more variables than what the current patch seems to offer. A quick glance shows:
SSL_CIPHER, SSL_CIPHER_ALGKEYSIZE,
SSL_CIPHER_EXPORT, SSL_CIPHER_USEKEYSIZE,
SSL_CLIENT_CERT, SSL_CLIENT_VERIFY,
SSL_COMPRESS_METHOD, SSL_PROTOCOL,
SSL_SERVER_A_KEY, SSL_SERVER_A_SIG,
SSL_SERVER_CERT, SSL_SERVER_I_DN,
SSL_SERVER_I_DN_CN, SSL_SERVER_I_DN_O,
SSL_SERVER_M_SERIAL, SSL_SERVER_M_VERSION,
SSL_SERVER_S_DN, SSL_SERVER_S_DN_C,
SSL_SERVER_S_DN_CN, SSL_SERVER_S_DN_O,
SSL_SERVER_S_DN_OU, SSL_SERVER_V_END,
SSL_SERVER_V_START SSL_VERSION_INTERFACE
SSL_VERSION_LIBRARY

Most important for client certificate validation would be to pass the client certificate itself, which would allow web apps to dig out whatever values they need.
Many thanks for bringing this to lighttpd!

#44 Updated by stbuehler about 5 years ago

  • Assignee deleted (jan)
  • Priority changed from High to Normal
  • Target version changed from 1.4.24 to 1.4.x
  • Missing in 1.5.x set to No

I pushed the basic verification support now; but the environment vars are missing for now (I really think the vars should be documented in the code) - I agree with nicolas314: we should at least export the client cert, and the others should be included too.

#45 Updated by patrickdk about 5 years ago

nicolas314 wrote:

SSL_CIPHER, SSL_CIPHER_ALGKEYSIZE,
SSL_CIPHER_EXPORT, SSL_CIPHER_USEKEYSIZE,
SSL_COMPRESS_METHOD, SSL_PROTOCOL,
SSL_SERVER_A_KEY, SSL_SERVER_A_SIG,
SSL_SERVER_CERT, SSL_SERVER_I_DN,
SSL_SERVER_I_DN_CN, SSL_SERVER_I_DN_O,
SSL_SERVER_M_SERIAL, SSL_SERVER_M_VERSION,
SSL_SERVER_S_DN, SSL_SERVER_S_DN_C,
SSL_SERVER_S_DN_CN, SSL_SERVER_S_DN_O,
SSL_SERVER_S_DN_OU, SSL_SERVER_V_END,
SSL_SERVER_V_START SSL_VERSION_INTERFACE
SSL_VERSION_LIBRARY

Shouldn't all those be a seperate issue? those should be passed on any ssl session, and not a client thing
I agree the client_cert belongs on this ticket though.

#46 Updated by nicolas314 about 5 years ago

patrickdk wrote:

Shouldn't all those be a seperate issue?

You are right, sorry. Server-side and protocol-related SSL variables should always be present whenever SSL is used. Client-side variables: the client certificate is a minimum, splitting it into components would probably be very appreciated by application writers.

#47 Updated by ostehovel about 5 years ago

  • File diff.patch added

I just made a patch by combinding some other patches in this thread.
This patch was made from rev #2656 of the trunk

and if you find any mistakes, bad typing stuff like that please re-upload a corrected version please ;D

Oste Hovel

#48 Updated by icy about 5 years ago

  • File deleted (diff.patch)

#49 Updated by stbuehler about 5 years ago

  • Status changed from New to Fixed
  • % Done changed from 0 to 100

Applied in changeset r2688.

#50 Updated by stbuehler about 5 years ago

  • Target version changed from 1.4.x to 1.4.25

#51 Updated by cicik about 4 years ago

Here is a patch for lighttpd 1.4.28 that sets serial number of the client certificate into environment. Previous patch won't work with this version of lighttpd.

Also available in: Atom