Bug 63800

Summary: HTTP 403 instead of HTTP 401 in RequireAll
Product: Apache httpd-2 Reporter: goldendev
Component: mod_authz_coreAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: normal    
Priority: P2    
Version: 2.4.41   
Target Milestone: ---   
Hardware: Other   
OS: Linux   

Description goldendev 2019-10-03 02:35:50 UTC
I have a following block:

<RequireAll>
Require valid user
Require env SMTH
</RequireAll>

The environmental variable SMTH depends on the data from "Authentication" header - so the user's credentials must be present for it to be setted to the correct value.

In case if no authentication credentials provided, apache will check the first Require, will "fail" with AUTHZ_DENIED_NO_USER, but then will check the second condition which will fail and apache will "fail" RequireAll with AUTHZ_DENIED abd return HTTP 403 instead of HTTP 401 so the user would never have a chance to enter credentials.

I wonder why apache checks all conditions inside RequireAll if one of the failed already?

Moreover check out the comment here: https://github.com/apache/httpd/blob/trunk/modules/aaa/mod_authz_core.c#766

```c
/*
                 * Handling of AUTHZ_DENIED/AUTHZ_DENIED_NO_USER: Return
                 * AUTHZ_DENIED_NO_USER if providing a user may change the
                 * result, AUTHZ_DENIED otherwise.
                 */
```

So apache should return AUTHZ_DENIED_NO_USER, but it doesn't.
Comment 1 goldendev 2019-10-03 04:22:32 UTC
I bet it should have been (line 772):

```c
if (child_result == AUTHZ_DENIED || child_result == AUTHZ_DENIED_NO_USER) {
```

Instead of:

```c
if (child_result == AUTHZ_DENIED) {
```
Comment 2 Christophe JAILLET 2019-10-03 20:14:24 UTC
Hi, untested, but does:

<RequireAll>
   Require valid-user
   <RequireAny>
      Require not valid-user
      Require env SMTH
   </RequireAny>
</RequireAll>

would do what you are looking for ?
Comment 3 goldendev 2019-10-03 22:07:47 UTC
(In reply to Christophe JAILLET from comment #2)
> Hi, untested, but does:
> 
> <RequireAll>
>    Require valid-user
>    <RequireAny>
>       Require not valid-user
>       Require env SMTH
>    </RequireAny>
> </RequireAll>
> 
> would do what you are looking for ?

Unfortunately no.  I've got syntax error on httpd -t:

"Require directive has no effect in <RequireAny> directive."

It seems that "Require not" must always be enclosed in RequireAll.
Comment 4 goldendev 2019-10-04 01:57:41 UTC
*I meant:

"[Negative] Require directive has no effect in <RequireAny> directive."