#1169 closed defect (wontfix)
HTTPAuth doesn't validate against AccountManager htpasswd file
Reported by: | Owned by: | Noah Kantrowitz | |
---|---|---|---|
Priority: | normal | Component: | HttpAuthPlugin |
Severity: | normal | Keywords: | |
Cc: | Trac Release: | 0.10 |
Description (last modified by )
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 18 years ago by
comment:2 Changed 18 years ago by
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 18 years ago by
get_header('Authorization') always seems to return None... has api changed?
comment:4 Changed 18 years ago by
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 18 years ago by
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 18 years ago by
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 17 years ago by
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 17 years ago by
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: 10 Changed 17 years ago by
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 Changed 17 years ago by
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 17 years ago by
Resolution: | → wontfix |
---|---|
Status: | new → closed |
This an Apache issue clearly. I can't do anything about it.
comment:12 Changed 17 years ago by
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:
comment:13 Changed 16 years ago by
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 15 years ago by
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 14 years ago by
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 12 years ago by
Adding the following Apache configuration directive worked for me
FcgidPassHeader AUTHORIZATION
my mistake: /xmlrpc & /login/xmlrpc targets work. They both result in a login dialog. But, again, username & password aren't accepted.