[mod_python] PythonAuthzHandler not working

Jim Gallacher jpg at jgassociates.ca
Sun Apr 23 22:23:16 EDT 2006


Problem solved, discussion below. Thanks for your help Graham. The 
mod_python project is *very* lucky to have you on board.

Graham Dumpleton wrote:
> 
> On 23/04/2006, at 11:43 AM, Graham Dumpleton wrote:
> 
>>
>> On 23/04/2006, at 8:19 AM, Graham Dumpleton wrote:
>>
>>>
>>> On 23/04/2006, at 5:22 AM, Jim Gallacher wrote:
>>>
>>>> Graham Dumpleton wrote:
>>>>> Add to config:
>>>>>   AuthAuthoritative Off
>>>>
>>>> That doesn't really make sense to me. Nothing like this is mentioned 
>>>> for other auth modules like mod_auth_ldap.
>>>
>>> I couldn't even find it documented. It is mentioned in source code 
>>> for 2.0.
>>> Turns of inbuilt auth.
>>
>> BTW, if you are using Apache 2.2, you might actually need both:
>>
>>   AuthzDefaultAuthoritative Off
>>   AuthzUserAuthoritative Off
>>
>> I didn't check before if it had changed form 2.0 to 2.2.
>>
>> I'll do some tests and get back to you on what is required for 2.2 if 
>> that
>> is what you are using.
> 
> Done testing, and on Apache 2.2, you don't need either of the above.
> 
> Here is a summary of what I found. Note that I am using mod_python 3.3
> from trunk. First off, am using the handlers:
> 
>     from mod_python import apache
> 
>     def authenhandler(req):
>         apache.log_error("authenhandler")
>         req.phases = ["authenhandler"]
>         req.user = "grumpy"
>         req.ap_auth_type = req.auth_type()
>         return apache.OK
> 
>     def authzhandler(req):
>         apache.log_error("authzhandler")
>         req.phases.append("authzhandler")
>         return apache.OK
> 
>     def handler(req):
>         apache.log_error("handler")
>         req.phases.append("handler")
>         req.content_type = "text/plain"
>         req.write(req.ap_auth_type+"\n")
>         req.write(req.user+"\n")
>         req.write(str(req.phases)+"\n")
>         return apache.OK
> 
> For Apache 2.0, the configuration that works is:
> 
>     SetHandler mod_python
> 
>     PythonAuthenHandler authz_1
>     PythonAuthzHandler authz_1
>     PythonHandler authz_1
>     PythonDebug On
> 
>     AuthType authztest
>     Require group grumpy
>     #AuthAuthoritative Off
> 
> The result in the browser is:
> 
>     authztest
>     grumpy
>     ['authenhandler', 'authzhandler', 'handler']
> 
> Note that I am not using AuthAuthoritative in the end here.
> 
> Now, if I instead use either:
> 
>     Require user grumpy
> 
> or:
> 
>     Require valid-user
> 
> even if set in conjunction with:
> 
>     Require group grumpy
> 
> the result is:
> 
>     authztest
>     grumpy
>     ['authenhandler', 'handler']
> 
> Thus, no authzhandler run. This is because builtin mod_authz is getting 
> run before
> my authzhandler and the user condition is being satisfied and so my 
> handler never
> gets to run.
> 
> If you want to have something like 'valid-user' or 'user', you need to 
> call it something
> else. For example, thus:
> 
>     Require authztest::valid-user
> 
> If I do that alone though, I get authorization required response and 
> error log says:
> 
>     [Sun Apr 23 13:21:58 2006] [error] [client ::1] access to 
> /testing/authz-1/ failed, reason: unknown require 
> directive:"authztest::valid-user"
> 
> To get past that, that is where in Apache 2.0 I need to set 
> AuthAuthoritative.
> 
>     SetHandler mod_python
> 
>     PythonAuthenHandler authz_1
>     PythonAuthzHandler authz_1
>     PythonHandler authz_1
>     PythonDebug On
> 
>     AuthType authztest
>     Require authztest::valid-user
>     AuthAuthoritative Off
> 
> Thus I again get:
> 
>     authztest
>     grumpy
>     ['authenhandler', 'authzhandler', 'handler']
> 
> In Apache 2.2, things are slightly different. Using:
> 
>     SetHandler mod_python
> 
>     PythonAuthenHandler authz_1
>     PythonAuthzHandler authz_1
>     PythonHandler authz_1
>     PythonDebug On
> 
>     AuthType authztest
>     Require group grumpy
> 
> still works okay. Using:
> 
>     Require user grumpy
> 
> or:
> 
>     Require valid-user
> 
> still results in:
> 
>     authztest
>     grumpy
>     ['authenhandler', 'handler']
> 
> In Apache 2.2, if I use:
> 
>     SetHandler mod_python
> 
>     PythonAuthenHandler authz_1
>     PythonAuthzHandler authz_1
>     PythonHandler authz_1
>     PythonDebug On
> 
>     AuthType authztest
>     Require authztest::valid-user
> 
> I get:
> 
>     authztest
>     grumpy
>     ['authenhandler', 'authzhandler', 'handler']
> 
> So, no need to have any equivalent to AuthAuthoritative in Apache 2.2.
> 
> In summary, situation seems to be that if you want to perform 
> authorization based
> on group member ship, okay to still use:
> 
>     Require group grumpy

Woot, Woot, Woot! We have a solution! 10,000 Thank-yous and as much 
virtual beer as you can drink, Graham. It never occurred to me to *not* 
use "Require valid-user". Any discussion I've seen on 
PythonAuthenHandler indicated the valid-user was *required* to get the 
authenhandler to run.

> But you should not set AuthGroupFile, because if you do then the 
> builting authz handler
> will try and do the interpretation itself.
> 
> If you want equivalents to 'valid-user' or 'user' where your 
> authzhandler interprets them,
> you need to qualify them to avoid builtin authz module interpreting 
> them. Thus use something
> like:
> 
>     Require authztest::valid-user
>     Require authztest::user grumpy
> 
> and the check req.requires for pertinent tags and data.
> 
> Going back to your original configuration:
> 
>     <Directory /srv/projects/aos/html/aos-admin/>
>       DirectoryIndex index.py
> 
> Take note of DirectoryIndex problems recorded in:
> 
>     http://issues.apache.org/jira/browse/MODPYTHON-146
> 
> This would be an issue if you are trying to pass data in req through 
> from these handlers
> to content handler. Plus notes and subprocess_env values can get 
> duplicated.
> 
>       AllowOverride None
>       AddHandler mod_python .py
> 
>       AuthType PyCookie
>       AuthName "Restricted"
>       Require valid-user
> 
> If req.user is set, use of 'valid-user' would cause inbuilt authz 
> handler to return
> OK and so your authzhandler would not run. If though req.user hadn't been
> set by authenhandler, you probably get an error occur.

That is correct, but the error is generated in mod_python.c, 
irrespective of the existence of "Require valid-user". Looking at that 
code makes me think there is an unreported bug, which may also explain 
some of the confusion over the AuthAuthorative business. More on this below.

>       Require admin
> 
> The "admin" tag is not one known of by Apache. If you were using Apache 2.0
> you would most like be getting:
> 
>     [Sun Apr 23 13:41:06 2006] [error] [client ::1] access to 
> /testing/authz-1/ failed, reason: unknown require directive:"admin"

This is not a problem as long as Require [valid-user|user|group] is set. 
  An error will not be raised as long as one of those is set. Strings 
set with Require can be retrieved with req.requires().

> Thus, in Apache 2.0, you would need to have AuthAuthoritative set. In 
> Apache 2.2
> you wouldn't need to.
> 
>       PythonAccessHandler mprest.authtest
>       PythonAuthenHandler mprest.authtest
>       PythonAuthzHandler mprest.authtest
>       PythonHandler mprest.authtest
> 
>     </Directory>
> 
> Now, what was the final configuration you were trying to use and what 
> version of
> Apache were you using?

Just for the record here is the conf that worked for me with Apache 
2.0.55 and mp 3.3.0-dev (with both new and old module importers). One of 
the directories contains dynamic content, while the other is static 
content. Note the absence of Require valid-user. Require group is 
sufficient to get both PythonAuthenHandler and PythonAuthzHandler to fire.

<Directory /path/to/html/adminonly/>
   AddHandler mod_python .py
   AuthType PyCookie
   AuthName "Restricted - Administrators Only"
   Require group
   Require pygroup admin
   PythonAuthenHandler mprest.auth
   PythonAuthzHandler mprest.auth
   PythonHandler mprest.publisher
</Directory>

There is no PythonHandler in the next example, as the directory only 
contains static content, but I want to use the same authen/authz 
mechanism to protect this resource.

<Directory /path/to/html/membersonly/>
   AuthType PyCookie
   AuthName "Restricted - Members Only"
   Require group
   Require pygroup member admin
   PythonAuthenHandler mprest.auth
   PythonAuthzHandler mprest.auth
</Directory>

I'll make some notes to stick in the documentation so some other poor 
sob can avoid the trouble this caused me.

Ultimately however it seems to me there is a bug in mod_python.c related 
to the whole AuthAthoritative business. Consider the following code 
pulled from the python_handler function. (mod_python.c line 1412 
revision 396250):

    if (strcmp(phase, "PythonAuthenHandler") == 0) {
          ... snip ...

          if (result == HTTP_UNAUTHORIZED)
          {
               if   (! conf->authoritative)
                     result = DECLINED;


conf->authoritative is initialized to 1, but we don't have an Apache 
directive to set the value. I wonder if the assumption was that this was 
set by AuthAuthoritative, or if it there was an oversight in not adding 
a new directive? Either way it's a bug. Mod_python should not concern 
itself with AuthAuthoritative, as that is for use by mod_auth, so we 
really need our on directive.

As confirmation I modified python_handler to log conf->authoritative and 
indeed it's value is unaffected by the AuthAthoritative setting. In it's 
current state, PythonAuthenHander will *always* be authoritative.

Other mod_auth_* modules define their own  authoritative directives, for 
example: AuthDBMAuthoritative, AuthLDAPAuthoritative, 
AuthMySQLAuthoritative and Anonymous_Authoritative. Following the most 
common pattern I would suggest we add AuthPythonAuthoritative.

This issue may also be important to 
http://issues.apache.org/jira/browse/MODPYTHON-129

Jim


More information about the Mod_python mailing list