Modify

Opened 7 years ago

Closed 7 years ago

Last modified 20 months ago

#1169 closed defect (wontfix)

HTTPAuth doesn't validate against AccountManager htpasswd file

Reported by: jlevy@… Owned by: coderanger
Priority: normal Component: HttpAuthPlugin
Severity: normal Keywords:
Cc: Trac Release: 0.10

Description (last modified by stp)

HTTPAuth dialog comes up, but username & passwords are rejected. Doesn't look like the Accountmanager plugin's password file is being consulted, as per your page's declaration that AccountManagerplugin is used to check passwords.

Using in conjunction w/XMLRPC plugin so we can use Mylar w/Eclipse & Trac.

Standard form-based login still works. Pop-up dialog appears for /xmlrpc & /xmlrpc/login targets, but username & password doesn't work.

  • Does crypt scheme in passwd file make two-bits of a difference? [using md5]
  • What's with the "Control Panel" name in the login dialog?
  • Is it a misconfiguration on my part?

I'm using trac 10.3, on Debian.
I'm using Py-24

Thanks for taking a look.

Attachments (0)

Change History (16)

comment:1 Changed 7 years ago by jlevy@…

my mistake: /xmlrpc & /login/xmlrpc targets work. They both result in a login dialog. But, again, username & password aren't accepted.

comment:2 Changed 7 years ago by jlevy@…

More details yet...

Snooping source, I see log entries... so I check my log:
2007-02-02 22:20:37,117 Trac[init] INFO: HTTPAuthFilter: No/bad authentication data given, returing 403

comment:3 Changed 7 years ago by jlevy@…

get_header('Authorization') always seems to return None... has api changed?

comment:4 Changed 7 years ago by beau@…

I see this too with a similar setup; 0.10.3, Python 2.4, FreeBSD.

/xmlrpc and /login/xmlrpc targets work but reject all users and passwords.

I also noticed that get_header('Authorization') is returning none.

I added a debug line to print out req._inheaders:

2007-03-29 17:54:36,852 Trac[filter] DEBUG: HTTPAuthFilter: req._inheaders = 
[('cookie', 'trac_form_token=f8938fa4194db5ac822c5260; 
trac_auth=27841af7dce3a81d8a685e62b3f467a0'), ('keep-alive', '300'), 
('accept-charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'), ('user-agent', 'Mozilla/5.0 
(Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3'), 
('connection', 'keep-alive'), ('host', 'www.redacted.com'), ('cache-control', 
'max-age=0, max-age=0'), ('accept', 
'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'), 
('accept-language', 'en-us,en;q=0.5'), ('accept-encoding', 'gzip,deflate')]

I then double-checked that I was sending the authorization header using 'Live HTTP Headers' for Firefox.

It seems that something (The AccountManager plugin?) is stripping this header.

comment:5 Changed 7 years ago by beau@…

Thought maybe I was crazy so I tcpdumped this from the server; the Authorization header is definitely received by Apache. Somewhere along the line it must be stripped out but I'm having a devil of a time trying to find where.

comment:6 Changed 7 years ago by chechu

I had the same problem. In my case the problem was that the header "Authorization" doesn't arrive to the cgi (or fcgi). I could get it in the .htaccess file, and I could set rules with this header in this file, but in the trac.cgi I could not see it.

I have my hosting with Dreamhost, maybe it's a server configuration problem.

My solution

First step

I set the next rules in the .htaccess file:

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{HTTP:Authorization} ^Basic.*
        RewriteRule ^(.*)$ index.cgi/$1?INTERNAL_AUTH=%{HTTP:Authorization} [L]
</IfModule>

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.cgi/$1 [L]
</IfModule>

The second one is the normal rule for Trac. The first one is an special adaption of the second one: when the header "Athorization" is present in a request (and starts with "Basic") I rewrite the url to pass an argument to the cgi. I pass as argument the value of the header Athorization. So, the next step is to get this argument in the cgi.

Second step

In the file trac.cgi (or trac.fcgi) I added the next code in the beginning:

import os, sys
from cgi import escape

valor = os.environ["QUERY_STRING"]
if valor:
    clave, valor = valor.split('=', 1)
    if clave == "INTERNAL_AUTH":
        os.environ["HTTP_AUTHORIZATION"] = valor

QUERY_STRING is an environmen variable with all the variables passed in the URL. We split this value to get the value of INTERNAL_AUTH variable, and only if this variable exists we set and environment variable: HTTP_AUTHORIZATION. This variable will be used then by the HttpAuthPlugin.

comment:7 Changed 7 years ago by yuji.od

That solution overwrite query strings.I changed following.

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{HTTP:Authorization} ^Basic.*
        RewriteRule ^(.*)$ index.cgi/$1?INTERNAL_AUTH=%{HTTP:Authorization}&%{QUERY_STRING} [L]
</IfModule>

comment:8 Changed 7 years ago by progrium@…

If you're using mod_wsgi, auth info is stripped before passing to the app. Turn WSGIPassAuthorization On for it to work. See http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives

comment:9 follow-up: Changed 7 years ago by caleb.lyness

I had a lot of trouble with the solution as stated above, eventually I came up with a slightly modified version which suited my environment. Here are the relavent sections of the apache (2.2) config (one still needs to modify the trac.fcgi as above):

<IfModule alias_module>
    AliasMatch ^/trac/[^/]+/chrome/common/(.*) "/usr/local/share/trac/htdocs/$1"
    AliasMatch ^/trac/([^/]+)/chrome/site/(.*) "/usr/local/www/trac/$1/htdocs/$2"
    ScriptAlias /trac /usr/local/www/apache22/cgi-bin/trac.fcgi
</IfModule>

<Location /trac>
   SetEnv TRAC_ENV_PARENT_DIR "/usr/local/www/trac"
   RewriteEngine on
   RewriteCond %{HTTP:Authorization} ^Basic.*
   RewriteCond %{QUERY_STRING} !INTERNAL_AUTH=.*
   RewriteRule ^.*trac\.fcgi/(.*xmlrpc)$ $1?INTERNAL_AUTH=%{HTTP:Authorization}&%{QUERY_STRING} [L]
</Location>

I also came across the following we should have worked but did not:

# http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html
<IfModule mod_fastcgi.c>
   AddHandler fastcgi-script .fcgi
   FastCgiConfig  -pass-header Authorization
</IfModule>

LoadModule fastcgi_module libexec/apache22/mod_fastcgi.so

comment:10 in reply to: ↑ 9 Changed 7 years ago by anonymous

Replying to caleb.lyness:

I had a lot of trouble with the solution as stated above, eventually I came up with a slightly modified version which suited my environment. Here are the relavent sections of the apache (2.2) config (one still needs to modify the trac.fcgi as above):

Holy formatting, Batman! Next time please hit preview.

comment:11 Changed 7 years ago by coderanger

  • Resolution set to wontfix
  • Status changed from new to closed

This an Apache issue clearly. I can't do anything about it.

comment:12 Changed 7 years ago by stp

  • Description modified (diff)

Please note that Mylyn should support form-based authentication via the AccountManagerPlugin in the latest releases. Please file a bug against Mylyn if it does not work for you:

http://www.eclipse.org/mylyn/bugs/

comment:13 Changed 6 years ago by anonymous

When you use the apache cgi you run in this problem, since the CGI specification told that the apache does not send the "authentication" header to python. I moved from cgi to mod_python and all works fine. When you start trac with its own http server (tracd) also all works fine.

comment:14 Changed 5 years ago by lee.calabrese@…

I know this is old but I was having lots of troubles with this and couldn't get the above to work. On shared hosting, I didn't have access to the Apache configuration, so I had to use this hack. What I ended up doing was the following:

I changed my .htaccess file with the following RewriteRule (which will then give you the request environment variable "REQUEST_HTTP_AUTHORIZATION":

RewriteRule ^(.*)$ index.fcgi/$1 [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

Note I had a couple of these RewriteRules in there because I was prettying the URL (removing the index.fcgi from the address and accessing it that way). Your mileage may vary but the idea is the same, use E= to pass through an environment variable. The trick that took me so long is it got prepended with "REQUEST_" automatically...

Then I modified the HttpAuthPlugin filter.py _check_password function to look at this variable as a fallback in case the headers weren't passed along properly. The full function became:

    def _check_password(self, req):
        header = req.get_header('Authorization')
        token = None
        if header:
            token = header.split()[1]
        if not token:
            # try the environment variables
            try:
                val = req.environ['REDIRECT_HTTP_AUTHORIZATION']
                if val:
                    token = val.split()[1]
            except KeyError:
                pass

        if token:
            user, passwd = b64decode(token).split(':', 1)
            if AccountManager(self.env).check_password(user, passwd):
                return user

Hope this helps someone else as it was a really tough one to deal with.

comment:15 Changed 4 years ago by anonymous

Here is my filter.py _check_password method :

def _check_password(self, req):
        val = req.environ['QUERY_STRING']
        token = None
        if val:
            token = val.split()[1]
        if token:
            user, passwd = b64decode(token).split(':', 1)
            if AccountManager(self.env).check_password(user, passwd):
                return user

And here is my apache configuration

<IfModule alias_module>
    AliasMatch /trac/[/]+/chrome/common/(.*) "/home/trac/htdocs/$1"
    AliasMatch /trac/([/]+)/chrome/site/(.*) "/home/trac/$1/htdocs/$2"
    ScriptAlias /trac /home/trac/cgi-bin/trac.fcgi/
</IfModule>

<Location /trac>
    SetEnv TRAC_ENV_PARENT_DIR "/home/trac/Prisme"
    RewriteEngine on
    RewriteCond %{HTTP:Authorization} Basic.*
    RewriteCond %{QUERY_STRING} !INTERNAL_AUTH=.*
    RewriteRule .*trac\.fcgi/(.*xmlrpc)$ $1?INTERNAL_AUTH=%{HTTP:Authorization}&%{QUERY_STRING} [L]
</Location>

<IfModule mod_fastcgi.c>
    AddHandler fastcgi-script .fcgi
    FastCgiConfig -pass-header Authorization
</IfModule>

comment:16 Changed 20 months ago by anonymous

Adding the following Apache configuration directive worked for me

FcgidPassHeader AUTHORIZATION

Add Comment

Modify Ticket

Action
as closed .
as The resolution will be set. Next status will be 'closed'.
to The owner will be changed from coderanger. Next status will be 'closed'.
The resolution will be deleted. Next status will be 'reopened'.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.