You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Rainer Jung <ra...@kippdata.de> on 2009/12/16 14:57:16 UTC

How to combine IP and user based AAA without Satisfy?

Hi,

during a test migration from 2.2 to 2.4 I noticed, that the new AAA does 
not allow to combine ip based AAA with user based.

The goal: allow access if either client ip address satisfies conditions 
or user authenticates via basic auth.

Until 2.2 one could use "Satisfy Any". The resulting config first 
checked the ip, and only prompted via basic auth, if the ip was not allowed.

In 2.4, *without* using the deprecated "Satisfy" via mod_access_compat, 
you will always be prompted by basic auth, because the ip addresses are 
only used during authz which comes after authn.

Is there any solution known to this? Should there be one? Would it make 
sense to not deprecate "Satisfy" because of this?

Regards,

Rainer


Re: How to combine IP and user based AAA without Satisfy?

Posted by Rainer Jung <ra...@kippdata.de>.
On 18.12.2009 00:36, Christian Seiler wrote:
> Hi,
>
> Since I'm also interested in AAA in future Apache versions, I decided to
> have a look at this.
>
>> In 2.4, *without* using the deprecated "Satisfy" via mod_access_compat,
>> you will always be prompted by basic auth, because the ip addresses are
>> only used during authz which comes after authn.
>
> This issue is found in ap_process_request_internal: If ap_satisfies(r)
> is not SATISFY_ANY (which it will only be with mod_access_compat since
> ap_satisfies else simply returns SATISFY_NOSPEC in 2.3+), it actually
> requires that an AuthN module (Basic, Digest, Form) actually
> authenticates a user.
>
> The current Apache implementation has is 3 different hooks that are run
> in that place:
>
>   1. access_checker
>        * Allow from / Deny from
>             (older versions, mod_access_compat)
>        * Some mod_ssl logic
>        * mod_lua (it actually provides access to every hook so there
>          isn't any real functionality behind it that the user doesn't
>          add him/herself)
>   2. check_user_id:   AuthN (mod_auth_basic _dist, _form)
>   3. auth_checker:    AuthZ (mod_authz_core ->  mod_authz_*)
>
> Previous logic (mod_access_compat, Apache up to 2.2) was:
>
>   * Satisfy All:
>         Check all 3 in the order access_checker, check_user_id,
>         auth_checker. If any fails, bail out.
>
>   * Satisfy Any:
>         Check access_checker. If that's ok, continue. If that fails,
>         run check_user_id and auth_checker and any of those fails, bail
>         out.

I agree with your analysis. Sorry that you had to do it again, I wanted 
to keep my inital post short.

> To me, all this seems to be violation of the separation between
> authorization and authentication and basically a leftover from before
> the AuthZ rewrite. What should happen (in my eyes) is the following:
>
>   1. Authentication phase: If it is possible to authenticate the user,
>      set r->user to the username. If not (no authentication data passed
>      with the request, user does not exist or even password wrong) the
>      r->user field is simply left with NULL. The authentication modules
>      by themselves do not send 401 or 403 headers if they fail.

Interesting idea.

>   2. Authorization phase: Only here it is determined whether the user
>      has to be authenticated (require valid-user for instance) or if
>      the user has to match any other criterion, such as source IP or
>      anything else. At that point, it would be nice to be able to somehow
>      detect if the condition that failed relied on a user (in that case
>      401 should be sent) or not (in that case it should be 403). Perhaps
>      a return code for authz modules.
>
> Also, access_checker seems to be a bit superfluous to me - since that's
> actually part of the AuthZ phase and was only added as an extra hook in
> the past in order to be able to have checks that don't actually require
> a user.

In trunk it is only used by mod_access_compat and mod_ssl. The mod_ssl 
use of the hook is non-trivial though.

Regards,

Rainer

Re: How to combine IP and user based AAA without Satisfy?

Posted by Christian Seiler <ch...@gmx.net>.
Hi,

Since I'm also interested in AAA in future Apache versions, I decided to
have a look at this.

> In 2.4, *without* using the deprecated "Satisfy" via mod_access_compat,
> you will always be prompted by basic auth, because the ip addresses are
> only used during authz which comes after authn.

This issue is found in ap_process_request_internal: If ap_satisfies(r)
is not SATISFY_ANY (which it will only be with mod_access_compat since
ap_satisfies else simply returns SATISFY_NOSPEC in 2.3+), it actually
requires that an AuthN module (Basic, Digest, Form) actually
authenticates a user.

The current Apache implementation has is 3 different hooks that are run
in that place:

 1. access_checker
      * Allow from / Deny from
           (older versions, mod_access_compat)
      * Some mod_ssl logic
      * mod_lua (it actually provides access to every hook so there
        isn't any real functionality behind it that the user doesn't
        add him/herself)
 2. check_user_id:   AuthN (mod_auth_basic _dist, _form)
 3. auth_checker:    AuthZ (mod_authz_core -> mod_authz_*)

Previous logic (mod_access_compat, Apache up to 2.2) was:

 * Satisfy All:
       Check all 3 in the order access_checker, check_user_id,
       auth_checker. If any fails, bail out.

 * Satisfy Any:
       Check access_checker. If that's ok, continue. If that fails,
       run check_user_id and auth_checker and any of those fails, bail
       out.

To me, all this seems to be violation of the separation between
authorization and authentication and basically a leftover from before
the AuthZ rewrite. What should happen (in my eyes) is the following:

 1. Authentication phase: If it is possible to authenticate the user,
    set r->user to the username. If not (no authentication data passed
    with the request, user does not exist or even password wrong) the
    r->user field is simply left with NULL. The authentication modules
    by themselves do not send 401 or 403 headers if they fail.

 2. Authorization phase: Only here it is determined whether the user
    has to be authenticated (require valid-user for instance) or if
    the user has to match any other criterion, such as source IP or
    anything else. At that point, it would be nice to be able to somehow
    detect if the condition that failed relied on a user (in that case
    401 should be sent) or not (in that case it should be 403). Perhaps
    a return code for authz modules.

Also, access_checker seems to be a bit superfluous to me - since that's
actually part of the AuthZ phase and was only added as an extra hook in
the past in order to be able to have checks that don't actually require
a user.

Just my 2c.

Regards,
Christian