Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client Certificate Support #80

Open
dougman82 opened this issue Oct 30, 2014 · 16 comments
Open

Client Certificate Support #80

dougman82 opened this issue Oct 30, 2014 · 16 comments

Comments

@dougman82
Copy link

I am using the 1.0.9.1 release version of mod_auth_cas (dated 13 DEC 2010).

I have been able to successfully configure mod_auth_cas to trust the CAS server's SSL certificate using the CASCertificatePath directive. However, in the case where the CAS server requires a client certificate, mod_auth_cas is failing to validate the service ticket. I cannot find any configuration options to specify a certificate for the outbound connection.

After enabling "debug" logging on the Apache server and enabling the CASDebug option, I was able to find the following in Apache's "ssl_error_log":

[:debug] [pid 973] mod_auth_cas.c(539): [client 127.0.0.1:44847] CAS Service '[TargetURL]', referer: [CASLoginURL]?service=[TargetURL]
[ssl:info] [pid 974] [client 127.0.0.1:44853] AH01964: Connection to child 4 established (server [MyServer]:443)
[ssl:debug] [pid 974] ssl_engine_kernel.c(1913): [client 127.0.0.1:44853] AH02043: SSL virtual host for servername [MyServer] found
[ssl:info] [pid 974] [client 127.0.0.1:44853] AH02008: SSL library error 1 in handshake (server [MyServer]:443)
[ssl:info] [pid 974] SSL Library Error: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate -- No CAs known to server for verification?
[ssl:info] [pid 974] [client 127.0.0.1:44853] AH01998: Connection closed to child 4 with abortive shutdown (server [MyServer]:443)
[ssl:info] [pid 971] [client 127.0.0.1:44854] AH01964: Connection to child 1 established (server [MyServer]:443)
[ssl:info] [pid 971] [client 127.0.0.1:44854] AH02008: SSL library error 1 in handshake (server [MyServer]:443)
[ssl:info] [pid 971] SSL Library Error: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate -- No CAs known to server for verification?
[ssl:info] [pid 971] [client 127.0.0.1:44854] AH01998: Connection closed to child 1 with abortive shutdown (server [MyServer]:443)
[:debug] [pid 973] mod_auth_cas.c(1666): [client 127.0.0.1:44847] MOD_AUTH_CAS: curl_easy_perform() failed (NSS: client certificate not found (nickname not specified)), referer: [CASLoginURL]?service=[TargetURL]

I attempted to install the appropriate certificate into my NSS certificate db (CentOS 7: /etc/pki/nssdb), but that did not seem to help. I also attempted to set the Apache SSLProxyMachineCertificateFile directive, but that had no effect either.

My specific configuration is such that both Apache and CAS (Tomcat) run on the same server, with Apache proxying requests to CAS via AJP/mod_proxy. Therefore, in this specific instance, when mod_auth_cas attempts to validate the service ticket, it is sending a request back to the Apache web server, which then proxies it to CAS. This works great until I configure Apache to require a client certificate, at which point I see the above log output and receive a 401 error in the browser.

@ruckc
Copy link

ruckc commented Oct 31, 2014

You would need to remove the SSL Client cert requirement to the /cas/*Validate endpoints.

@dhawes
Copy link
Contributor

dhawes commented Nov 1, 2014

If you feel comfortable modifying source and just want to test to see if this works, look at mod_auth_cas.c and add the following lines in getResponseFromServer():

    curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
    curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/cert.pem");
    curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/key.pem");

You'll have to hardcode the paths and use a PEM cert/key.

Please note that I haven't even compiled this, but it may get you where you want to be. I can whip up a patch with config options in the near future.

@ruckc
Copy link

ruckc commented Nov 1, 2014

I believe you just want to exclude the validation endpoints from the SSL
Client Certificate validation. There is no reason to have SSL Client
Validation on them. Another alternative would be to only apply SSL Client
Certificate requirements on the login endpoints /cas/login and potentially
/cas/v1/tickets if you use the RESTful API.

On Fri Oct 31 2014 at 8:45:43 PM David Hawes [email protected]
wrote:

If you feel comfortable modifying source and just want to test to see if
this works, look at mod_auth_cas.c and add the following lines in
getResponseFromServer():

curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/cert.pem");
curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/key.pem");

You'll have to hardcode the paths and use a PEM cert/key.

Please note that I haven't even compiled this, but it may get you where
you want to be. I can whip up a patch with config options in the near
future.


Reply to this email directly or view it on GitHub
#80 (comment).

@smaresca
Copy link
Contributor

smaresca commented Nov 1, 2014

Or, instead, are you hoping to use client certs to prevent validation
attempts by unauthorized CAS clients?
On Oct 31, 2014 9:10 PM, "ruckc" [email protected] wrote:

I believe you just want to exclude the validation endpoints from the SSL
Client Certificate validation. There is no reason to have SSL Client
Validation on them. Another alternative would be to only apply SSL Client
Certificate requirements on the login endpoints /cas/login and potentially
/cas/v1/tickets if you use the RESTful API.

On Fri Oct 31 2014 at 8:45:43 PM David Hawes [email protected]
wrote:

If you feel comfortable modifying source and just want to test to see if
this works, look at mod_auth_cas.c and add the following lines in
getResponseFromServer():

curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/cert.pem");
curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/key.pem");

You'll have to hardcode the paths and use a PEM cert/key.

Please note that I haven't even compiled this, but it may get you where
you want to be. I can whip up a patch with config options in the near
future.


Reply to this email directly or view it on GitHub
#80 (comment).


Reply to this email directly or view it on GitHub
#80 (comment).

@dhawes
Copy link
Contributor

dhawes commented Nov 1, 2014

I don't know if that's what the original poster wants, but I consider it to
be a valid use case.

We use client certificates for purposes like this at the institution I work
at, so I guess you could say I'm sympathetic when client cert stuff doesn't
work (which is too often, unfortunately).

On Fri, Oct 31, 2014 at 9:33 PM, Steve Maresca [email protected]
wrote:

Or, instead, are you hoping to use client certs to prevent validation
attempts by unauthorized CAS clients?
On Oct 31, 2014 9:10 PM, "ruckc" [email protected] wrote:

I believe you just want to exclude the validation endpoints from the SSL
Client Certificate validation. There is no reason to have SSL Client
Validation on them. Another alternative would be to only apply SSL
Client
Certificate requirements on the login endpoints /cas/login and
potentially
/cas/v1/tickets if you use the RESTful API.

On Fri Oct 31 2014 at 8:45:43 PM David Hawes [email protected]
wrote:

If you feel comfortable modifying source and just want to test to see
if
this works, look at mod_auth_cas.c and add the following lines in
getResponseFromServer():

curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/cert.pem");
curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/key.pem");

You'll have to hardcode the paths and use a PEM cert/key.

Please note that I haven't even compiled this, but it may get you
where
you want to be. I can whip up a patch with config options in the near
future.


Reply to this email directly or view it on GitHub
#80 (comment).


Reply to this email directly or view it on GitHub
#80 (comment).


Reply to this email directly or view it on GitHub
#80 (comment).

@smaresca
Copy link
Contributor

smaresca commented Nov 1, 2014

Yep that's why I asked to be sure; it sounds like an entirely reasonable
use case to me.

Doug, definitely interested in your testing of David's proposal.

Steve
On Oct 31, 2014 10:06 PM, "David Hawes" [email protected] wrote:

I don't know if that's what the original poster wants, but I consider it
to
be a valid use case.

We use client certificates for purposes like this at the institution I
work
at, so I guess you could say I'm sympathetic when client cert stuff
doesn't
work (which is too often, unfortunately).

On Fri, Oct 31, 2014 at 9:33 PM, Steve Maresca [email protected]
wrote:

Or, instead, are you hoping to use client certs to prevent validation
attempts by unauthorized CAS clients?
On Oct 31, 2014 9:10 PM, "ruckc" [email protected] wrote:

I believe you just want to exclude the validation endpoints from the
SSL
Client Certificate validation. There is no reason to have SSL Client
Validation on them. Another alternative would be to only apply SSL
Client
Certificate requirements on the login endpoints /cas/login and
potentially
/cas/v1/tickets if you use the RESTful API.

On Fri Oct 31 2014 at 8:45:43 PM David Hawes [email protected]

wrote:

If you feel comfortable modifying source and just want to test to
see
if
this works, look at mod_auth_cas.c and add the following lines in
getResponseFromServer():

curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, "/path/to/cert.pem");
curl_easy_setopt(curl, CURLOPT_SSLKEY, "/path/to/key.pem");

You'll have to hardcode the paths and use a PEM cert/key.

Please note that I haven't even compiled this, but it may get you
where
you want to be. I can whip up a patch with config options in the
near
future.


Reply to this email directly or view it on GitHub
<
https://github.com/Jasig/mod_auth_cas/issues/80#issuecomment-61349766>.


Reply to this email directly or view it on GitHub
#80 (comment).


Reply to this email directly or view it on GitHub
#80 (comment).


Reply to this email directly or view it on GitHub
#80 (comment).

@dougman82
Copy link
Author

Yes, the reasoning is that due to security requirements at my institution, all web servers require client certificate authentication - even if only to verify that all clients connecting to them have "trusted" certificates.

I will go ahead and attempt David's proposal when I get back to the office on Monday.

Thanks,
Doug

@dougman82
Copy link
Author

Just an update. I went ahead and added the 3 lines of code that David suggested above, and it works perfectly!

@dougman82
Copy link
Author

So at this point, I have two questions:

  1. I can probably take a look at the code and figure out how to make this configurable. However, it's a very real possibility that I could end up breaking it instead. David, you mentioned that you could make a patch to add that in the "near future". What time frame would you be thinking of?

  2. As I stated in my original message, I am currently using the 1.0.9.1 release of the code. Is it recommended that I be using an up-to-date clone of the Master branch instead?

@dhawes
Copy link
Contributor

dhawes commented Nov 4, 2014

I'm glad that it works, thanks for testing that.

I should have time in the next couple of days to make a patch. Would you be willing to test it out for me?

As for (2), my personal testing has shown that master is ready for production use, but I don't know if that's the official recommendation.

@dougman82
Copy link
Author

That sounds excellent. I will definitely be willing to test it out whenever - just let me know.

My only hesitation with using the master is just traceability for my current project - that I can't point to a specific version and say that's what I used to configure the system. But that shouldn't matter too much as long as I keep the source I used to build the module with my system configuration files.

Thanks again,
Doug

@dhawes
Copy link
Contributor

dhawes commented Nov 4, 2014

A quick patch against master is available at:

https://github.com/dhawes/mod_auth_cas/commit/ae4b4f731dff9e6a683be579380f2926f73f4d1d.diff

The commit log has the config options:

dhawes@ae4b4f7

It should be easy enough to make a 1.0.9.1 patch if you really need it.

@dougman82
Copy link
Author

I apologize, as I have probably done something stupid. I went ahead and grabbed the master and built it. Then, when I installed it in Apache, the service will not start, stating that "ap_requires" is an undefined symbol.

A quick google search tells me that this is an incompatibility with Apache 2.4 (which I am using). Is there a different configuration I need to enable? Or should I stick with the 1.0.9.1 release for now (which didn't give me this issue)?

@dhawes
Copy link
Contributor

dhawes commented Nov 5, 2014

No, you've just come across another issue:

#49

Here's a patch for v1.0.9.1 if you want to try it. It compiles, but I have not tested it:

https://github.com/dhawes/mod_auth_cas/commit/0a7b4a99beab7eb0c02c23ff7d873e882f2e822a.diff

@dougman82
Copy link
Author

Excellent. Thank you for putting that together. As you, say, it does compile, and I was able to test it successfully for the case of "PEM" certificate files. However, for completeness, I converted my PEM files to DER format and gave that a go (updating the CASClientCert and CASClientKey paths as well as changing the CASClientCertType configuration to "DER"), and it doesn't seem to work.

Looking in my Apache logs, I see the following line:

MOD_AUTH_CAS: curl_easy_perform() failed (unable to load client cert: -8018 (SEC_ERROR_UNKNOWN_PKCS11_ERROR))

To convert my PEM files I used the following OpenSSL commands:

openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
openssl rsa -in key.pem -inform PEM -out key.der -outform DER

Assuming it's not an issue with my cert files, could this be a libcurl or NSS issue?

Fortunately for me, my use case is to always use PEM-encoded certificates, so my configuration is working great.

@dhawes
Copy link
Contributor

dhawes commented Nov 5, 2014

I'm glad it works for PEM certs.

I just tested with DER certs and they seem to load fine for me. I don't currently have a CAS server that requires client auth to test this, so they are not actually being used, but they are being loaded. I'm fairly sure my libcurl is compiled against OpenSSL, which is interesting because the cURL docs claim:

"DER" format key file currently does not work because of a bug in OpenSSL.

Needless to say, there is a fair amount of testing needed to make sure this works with all the SSL/TLS libraries that cURL can be built against.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants