Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I have Apache set up to require a client certificate. Unfortunately, REMOTE_USER comes across has a nasty, long string from the certificate. This is problematic for applications like Trac that use that for the user name. I've been able to get Apache to map the certificate to a more legible user name using:

RewriteMap certmap txt:/var/www/certmap.txt
RewriteRule .* - [E=REMOTE_USER:${certmap:%{SSL:SSL_CLIENT_S_DN_CN}}]

This works just fine except for the first request. The first request has REMOTE_USER as an empty string but the next action (i.e. click a link) results in the value being set. In Trac, the effect is the user is not initially logged in but are after they do anything.

Is there some way to have REMOTE_USER set initially? Or if that's not possible, could a redirect or two take care of "clicking on a link"?

Edit

Unsurprisingly, IE has to throw a wrench into things. This method just flat out doesn't work in IE (8): the client SSL variables are not available at any point when trying to use the RewriteRule.

share|improve this question
    
I'd have expected the rewriteRule you've provided to work every time. Maybe use rewrite to direct the user to a simple landing page which drops a session cookie in the absence of an existing session cookie? –  symcbean Jun 29 '11 at 15:30

2 Answers 2

up vote 1 down vote accepted

I found a solution that doesn't use mod_rewrite or Apache at all for that matter. Unfortunately, it only works with WSGI scripts. While this doesn't solve a potential problem in the future, it does solve the immediate need. The main application that needs this is Trac, which this works just fine for.

I'm using this WSGI script for Trac:

def application(environ, start_response):
    common_name = environ['SSL_CLIENT_S_DN_CN']
    user_mapped = False
    file = open('/var/www/cert-map.txt')
    for line in file:
        if not line or line.startswith('#'):
            continue
        parts = line.split()
        if len(parts) < 2:
            continue
        if common_name == parts[0]:
            environ['REMOTE_USER'] = parts[1]
            user_mapped = True
            break
    file.close()
    if not user_mapped:
        environ['REMOTE_USER'] = common_name
    return trac.web.main.dispatch_request(environ, start_response)

Essentially, it's setting the value of REMOTE_USER before Trac does its thing.

share|improve this answer

Does http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslusername not do the job?

share|improve this answer
    
I had tried that but I'm using FakeBasicAuth which the documentation states SSLUserName has no effect when FakeBasicAuth is used. –  Matthew Jacobs Jul 5 '11 at 11:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.