Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Graham Leggett via dev
On 23 Nov 2023, at 13:28, Yann Ylavic  wrote:

>> Unfortunately the message is correct and we do just that via 
>> get_dn_for_nonldap_authn (line 1451). The DN you mention we look for
>> later in line 1480 via util_ldap_cache_getuserdn.
> 
> My guess was that if r->user is set we always want to use it for ldap
> requests/authn? Or maybe there should be another Require ldap-!search
> configured to achieve that (if wanted) since ldap-search is special..

We already have that, it’s ldap-filter.

In more detail, ldap-filter takes an LDAP filter, for example 
(objectclass=mailRecipient), and then it takes an r->user, for example 
f...@example.com, and then it combines them to create a new filter 
(&(uid=f...@example.com)(objectclass=mailRecipient)), and if exactly one (not 
zero, not two) objects exist, it is a match.

ldap-search ignores the r->user special case and broadens this to any 
expression you can image.

>>> On a side note, ldap-search requires that exactly one LDAP object matches, 
>>> we might want to support many matches, or a specific
>>> number of matches.
> 
> I still don't get where "Make sure that the filtered search returned a
> single dn" is enforced, is it because result != LDAP_SUCCESS
> otherwise, or dn == NULL if there are multiple objects/DNs?

It’s enforced here:

https://github.com/apache/httpd/blob/trunk/modules/ldap/util_ldap.c#L2118

For historic reasons, the function is called uldap_cache_getuserdn(), but what 
the function actually does is run a single LDAP query, and expect one and only 
one object in return.

ldap-search runs a single LDAP query, and expects one and only one object in 
return, it just isn’t a user.

Regards,
Graham
—



Re: svn commit: r1589993 - in /httpd/httpd/trunk: CHANGES docs/manual/expr.xml docs/manual/mod/mod_authnz_ldap.xml modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Christophe JAILLET

Le 18/11/2023 à 20:52, Yann Ylavic a écrit :

On Wed, Apr 30, 2014 at 1:02 AM Yann Ylavic  wrote:


On Tue, Apr 29, 2014 at 10:54 PM, Christophe JAILLET
 wrote:

Hi,

doc does not build because of  below:

CJ

Le 25/04/2014 13:14, minf...@apache.org a écrit :

+
+LocationMatch ^/dav/(?[^/]+)/


   ^ There



Hmm, won't LocationMatch itself be broken by the inner <>s ?


Wow, fortunately I didn't hold my breath on this one :)
Someone needs to answer to this former/younger/naive me though and
since I'm on this commit again: look Yann, this match is double-quoted
now so we should be fine!



In fact, at that time, another solution was provided in r1591113.

But what you propose above, should have worked as well, I guess. :).

CJ


Re: mod_dav_fs locking / Re: apr_dbm and concurrency

2023-11-23 Thread Emmanuel Dreyfus
On Thu, Nov 23, 2023 at 05:36:06PM +, Joe Orton wrote:
> 3) in the mean time I worked up a PR for mod_dav_fs which adds a global 
> mutex around the dbm lockdb use. This passes my stress tests for the 
> first time.

How concurent is the stress test? 

In the past, I have been badly hurt by a few WebDAV clients proactively 
exploring the filesystem using locksdiscovery. That compeltely killed the 
service. I introduced the DavLockDiscovery directive to work it around.

-- 
Emmanuel Dreyfus
m...@netbsd.org


mod_dav_fs locking / Re: apr_dbm and concurrency

2023-11-23 Thread Joe Orton
Adding dev@httpd to a dev@apr thread about apr_dbm locking being broken.

On Sun, Nov 12, 2023 at 07:43:13AM -0600, Greg Stein wrote:
> Or, apps can stick to an older APR. ... we don't have to carry this forward
> into future versions of APR (IMO).
> 
> To your point, it is probably a single page with code samples to show how
> to do K/V with sqlite, to replace the apr_dbm calls. That's gonna be way
> easier than locking code integrated into apr_dbm.

This seems reasonable to me for the mod_dav use case where the database 
is an implementation detail which users don't care about. For other use 
cases in httpd I'm not so sure, but saying "dbm is dead, sqlite is the 
way" is probably possible for all of them. It does mean someone writing 
a lot of new modules to replace mod_auth*dbm etc tho ;)

There are a few alternative approaches I looked at:

1) we could hack fcntl-based locks to work on Linux by using F_OFD_SETLK 
etc which a sane locking model rather than the weird/dumb F_SETLK which 
has the traditional/POSIX non-thread-safe model. Linux-specific, so...

2) try to shoehorn "proper" locking into apr_dbm is hard because there 
isn't a suitable locking primitive that can be used at this level. Maybe 
the only approach that might work would be filesystem-based locking 
based off open/O_EXCL but this is not exactly reliable.

3) in the mean time I worked up a PR for mod_dav_fs which adds a global 
mutex around the dbm lockdb use. This passes my stress tests for the 
first time. Kind of ugly but this seems like the least ugly option at 
this point other than the "start again with sqlite": 
https://github.com/apache/httpd/pull/395

Any comments/review/flames from either dev@ welcome.

Regards, Joe



Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Ruediger Pluem



On 11/23/23 5:05 PM, Yann Ylavic wrote:
> On Thu, Nov 23, 2023 at 4:46 PM Yann Ylavic  wrote:
>>
>> On Thu, Nov 23, 2023 at 4:17 PM Ruediger Pluem  wrote:
>>>
>>> On 11/23/23 3:53 PM, Yann Ylavic wrote:

>>> I am asking because I guess I am hit now by races in the byrequests LB
>>> with the worker->s->lbstatus.
>>> I probably want to look for a way to solve this in a more generic way
>>> for various shared worker fields.
>>
>> lbstatus is an int so the 32bit apr_atomic API could do I think.
> 
> I mean, if lbstatus becomes inconsistent because of the race then we

My current theory is that this is the case.

> can do something, but if it is e.g. that a worker switches from error
> state to non-error become some threads can connect while some others
> can't this is something we should address elsewhere (like a failure
> threshold).
> 
>> Maybe we need some ap_atomic_{int,long,size_t,..}_*() helpers for
>> system dependent widths. It preferably would be implemented in APR but
>> in the meantime we could have something in httpd already.
>> What we should avoid IMO is needing 64bit atomics on 32bit systems
>> (because we'd have to reimplement the mutexes etc), but apart from
>> that I think we can wrap anything using the existing apr atomics.
> 
> What we need for lbstatus is ap_atomic_int_or() and
> ap_atomic_int_and_not() it seems, both could be implemented with a
> cas32 loop.

What functionality are ap_atomic_int_or() / ap_atomic_int_and_not() are 
supposed to deliver?
I am having a hard time guessing it from the name :-).

Regards

Rüdiger



Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Yann Ylavic
On Thu, Nov 23, 2023 at 4:46 PM Yann Ylavic  wrote:
>
> On Thu, Nov 23, 2023 at 4:17 PM Ruediger Pluem  wrote:
> >
> > On 11/23/23 3:53 PM, Yann Ylavic wrote:
> > >
> > > As for the 64bit atomics vs APR version dance, it's because the former
> > > are not available before apr-1.7 and likely not reliable before 1.7.4
> > > (at least for some architectures where builtins are not available). In
> > > any case we need a fallback for apr < 1.7, but maybe to keep this
> > > simpler we should fall back to non-atomics (as before) in this case.
> > > It all looks over complicated for the feature, but I can't think of
> > > something simpler and still correct..
> >
> > Understood.
> >
> > I am asking because I guess I am hit now by races in the byrequests LB
> > with the worker->s->lbstatus.
> > I probably want to look for a way to solve this in a more generic way
> > for various shared worker fields.
>
> lbstatus is an int so the 32bit apr_atomic API could do I think.

I mean, if lbstatus becomes inconsistent because of the race then we
can do something, but if it is e.g. that a worker switches from error
state to non-error become some threads can connect while some others
can't this is something we should address elsewhere (like a failure
threshold).

> Maybe we need some ap_atomic_{int,long,size_t,..}_*() helpers for
> system dependent widths. It preferably would be implemented in APR but
> in the meantime we could have something in httpd already.
> What we should avoid IMO is needing 64bit atomics on 32bit systems
> (because we'd have to reimplement the mutexes etc), but apart from
> that I think we can wrap anything using the existing apr atomics.

What we need for lbstatus is ap_atomic_int_or() and
ap_atomic_int_and_not() it seems, both could be implemented with a
cas32 loop.

>
> Regards;
> Yann.


Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Yann Ylavic
On Thu, Nov 23, 2023 at 4:17 PM Ruediger Pluem  wrote:
>
> On 11/23/23 3:53 PM, Yann Ylavic wrote:
> >
> > As for the 64bit atomics vs APR version dance, it's because the former
> > are not available before apr-1.7 and likely not reliable before 1.7.4
> > (at least for some architectures where builtins are not available). In
> > any case we need a fallback for apr < 1.7, but maybe to keep this
> > simpler we should fall back to non-atomics (as before) in this case.
> > It all looks over complicated for the feature, but I can't think of
> > something simpler and still correct..
>
> Understood.
>
> I am asking because I guess I am hit now by races in the byrequests LB
> with the worker->s->lbstatus.
> I probably want to look for a way to solve this in a more generic way
> for various shared worker fields.

lbstatus is an int so the 32bit apr_atomic API could do I think.
Maybe we need some ap_atomic_{int,long,size_t,..}_*() helpers for
system dependent widths. It preferably would be implemented in APR but
in the meantime we could have something in httpd already.
What we should avoid IMO is needing 64bit atomics on 32bit systems
(because we'd have to reimplement the mutexes etc), but apart from
that I think we can wrap anything using the existing apr atomics.

Regards;
Yann.


Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Ruediger Pluem



On 11/23/23 3:53 PM, Yann Ylavic wrote:
> On Thu, Nov 23, 2023 at 12:11 PM Ruediger Pluem  wrote:
>>
>> On 9/11/23 3:50 PM, jfcl...@apache.org wrote:
>>> Author: jfclere
>>> Date: Mon Sep 11 13:50:21 2023
>>> New Revision: 1912245
>>>
>>> URL: http://svn.apache.org/viewvc?rev=1912245=rev
>>> Log:
>>> Arrange the bybusyness logic and prevent bad busy values
>>> this closes #383
> []
>>> --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
>>> +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Mon Sep 11 13:50:21 2023
>>> @@ -21,6 +21,7 @@
>>>  #include "apr_version.h"
>>>  #include "apr_strings.h"
>>>  #include "apr_hash.h"
>>> +#include "apr_atomic.h"
>>>  #include "http_core.h"
>>>  #include "proxy_util.h"
>>>  #include "ajp.h"
>>> @@ -4984,6 +4985,124 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tun
>>>  return APR_SUCCESS;
>>>  }
>>>
>>> +PROXY_DECLARE(apr_status_t) decrement_busy_count(void *worker_)
>>
>> Why can't we use the respective apr_atomic_sub/add/inc/dec* functions here
>> instead of the logic below?
> 
> This has been discussed in https://github.com/apache/httpd/pull/383,
> at least for why the "if atomic_dec() < 0 then atomic_inc()"
> proposed originally was racy.
> So the below implements dec_not_zero and inc_not_at_max to keep ->busy
> in the bounds, like the original non-atomic functions.
> I think the under/overflows could still happen without this because,
> even if we inc per request and dec on request pool cleanup, there is a
> balancer->lbmethod->reset() which may clear ->busy at any time (IIUC),
> not to talk about a child crash (though then ->busy may not be very
> reliable anyway, under/overflow or not..).

Thanks for the pointer. I missed this.

> 
> As for the 64bit atomics vs APR version dance, it's because the former
> are not available before apr-1.7 and likely not reliable before 1.7.4
> (at least for some architectures where builtins are not available). In
> any case we need a fallback for apr < 1.7, but maybe to keep this
> simpler we should fall back to non-atomics (as before) in this case.
> It all looks over complicated for the feature, but I can't think of
> something simpler and still correct..

Understood.

I am asking because I guess I am hit now by races in the byrequests LB
with the worker->s->lbstatus.
I probably want to look for a way to solve this in a more generic way
for various shared worker fields.

Regards

Rüdiger



Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Yann Ylavic
On Thu, Nov 23, 2023 at 12:11 PM Ruediger Pluem  wrote:
>
> On 9/11/23 3:50 PM, jfcl...@apache.org wrote:
> > Author: jfclere
> > Date: Mon Sep 11 13:50:21 2023
> > New Revision: 1912245
> >
> > URL: http://svn.apache.org/viewvc?rev=1912245=rev
> > Log:
> > Arrange the bybusyness logic and prevent bad busy values
> > this closes #383
[]
> > --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
> > +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Mon Sep 11 13:50:21 2023
> > @@ -21,6 +21,7 @@
> >  #include "apr_version.h"
> >  #include "apr_strings.h"
> >  #include "apr_hash.h"
> > +#include "apr_atomic.h"
> >  #include "http_core.h"
> >  #include "proxy_util.h"
> >  #include "ajp.h"
> > @@ -4984,6 +4985,124 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tun
> >  return APR_SUCCESS;
> >  }
> >
> > +PROXY_DECLARE(apr_status_t) decrement_busy_count(void *worker_)
>
> Why can't we use the respective apr_atomic_sub/add/inc/dec* functions here
> instead of the logic below?

This has been discussed in https://github.com/apache/httpd/pull/383,
at least for why the "if atomic_dec() < 0 then atomic_inc()"
proposed originally was racy.
So the below implements dec_not_zero and inc_not_at_max to keep ->busy
in the bounds, like the original non-atomic functions.
I think the under/overflows could still happen without this because,
even if we inc per request and dec on request pool cleanup, there is a
balancer->lbmethod->reset() which may clear ->busy at any time (IIUC),
not to talk about a child crash (though then ->busy may not be very
reliable anyway, under/overflow or not..).

As for the 64bit atomics vs APR version dance, it's because the former
are not available before apr-1.7 and likely not reliable before 1.7.4
(at least for some architectures where builtins are not available). In
any case we need a fallback for apr < 1.7, but maybe to keep this
simpler we should fall back to non-atomics (as before) in this case.
It all looks over complicated for the feature, but I can't think of
something simpler and still correct..

>
> > +{
> > +apr_size_t val;
> > +proxy_worker *worker = worker_;
> > +
> > +#if APR_SIZEOF_VOIDP == 4
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> > +val = apr_atomic_read32(>s->busy);
> > +while (val > 0) {
> > +apr_size_t old = val;
> > +val = apr_atomic_cas32(>s->busy, val - 1, old);
> > +if (val == old) {
> > +break;
> > +}
> > +}
> > +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 
> > 1.7.4 */
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> > +val = apr_atomic_read64(>s->busy);
> > +while (val > 0) {
> > +apr_size_t old = val;
> > +val = apr_atomic_cas64(>s->busy, val - 1, old);
> > +if (val == old) {
> > +break;
> > +}
> > +}
> > +#else /* Use atomics for (64bit) pointers */
> > +void *volatile *busy_p = (void *)>s->busy;
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> > +AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> > +val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> > +while (val > 0) {
> > +apr_size_t old = val;
> > +val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p,
> > +   (void *)(apr_uintptr_t)(val 
> > - 1),
> > +   (void *)(apr_uintptr_t)old);
> > +if (val == old) {
> > +break;
> > +}
> > +}
> > +#endif
> > +return APR_SUCCESS;
> > +}
> > +
> > +PROXY_DECLARE(void) increment_busy_count(proxy_worker *worker)
> > +{
> > +apr_size_t val;
> > +#if APR_SIZEOF_VOIDP == 4
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> > +val = apr_atomic_read32(>s->busy);
> > +while (val < APR_INT32_MAX) {
> > +apr_size_t old = val;
> > +val = apr_atomic_cas32(>s->busy, val + 1, old);
> > +if (val == old) {
> > +break;
> > +}
> > +}
> > +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 
> > 1.7.4 */
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> > +val = apr_atomic_read64(>s->busy);
> > +while (val < APR_INT64_MAX) {
> > +apr_size_t old = val;
> > +val = apr_atomic_cas64(>s->busy, val + 1, old);
> > +if (val == old) {
> > +break;
> > +}
> > +}
> > +#else /* Use atomics for (64bit) pointers */
> > +void *volatile *busy_p = (void *)>s->busy;
> > +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> > +AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> > +val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> > +while (val < APR_INT64_MAX) {
> > +apr_size_t old = val;
> > +val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p,
> > +   

Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Ruediger Pluem



On 11/23/23 2:28 PM, Yann Ylavic wrote:
> On Thu, Nov 23, 2023 at 1:33 PM Ruediger Pluem  wrote:
>>
>>
>>
>> On 11/23/23 12:52 PM, Graham Leggett via dev wrote:
>>> On 23 Nov 2023, at 11:25, Ruediger Pluem  wrote:
>>>
> -if (req->dn == NULL || !*req->dn) {
> -ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> -  "auth_ldap authorize: require ldap-filter: user's 
> DN "
> -  "has not been defined; failing authorization");
> -return AUTHZ_DENIED;
> +if (req->dn == NULL || !*req->dn) {
> +ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> +  "auth_ldap authorize: require ldap-search: 
> user's DN "
> +  "has not been defined; failing authorization");
> +return AUTHZ_DENIED;
> +}

 Why do we need to get the dn in case that r->user is not NULL and why is 
 it a reason to fail if we don't get a dn for this user?
>>>
>>> This message is misleading, the DN we care about is not the DN of the user, 
>>> but rather the DN of the object returned in the
>>> ldap-search, which may or may not bear a relation to the user.
>>
>> Unfortunately the message is correct and we do just that via 
>> get_dn_for_nonldap_authn (line 1451). The DN you mention we look for
>> later in line 1480 via util_ldap_cache_getuserdn.
> 
> My guess was that if r->user is set we always want to use it for ldap
> requests/authn? Or maybe there should be another Require ldap-!search
> configured to achieve that (if wanted) since ldap-search is special..

I think for ldap-search things depend on the configured filter expression. It 
may involve a previously authenticated user, in
which case it has similar approaches like ldap-filter or even require 
valid-user or it does not include that and may remind more
of a mod_authz_host with a dynamic IP list stored in LDAP. Or the certificate 
example Graham gave.

> 
>> BTW: I guess the following patch is missing as we don't store the dn / vals 
>> we get from util_ldap_cache_getuserdn but just
>> "forget" it once we leave the function.
>>
>>
>> Index: modules/aaa/mod_authnz_ldap.c
>> ===
>> --- modules/aaa/mod_authnz_ldap.c   (revision 1914069)
>> +++ modules/aaa/mod_authnz_ldap.c   (working copy)
>> @@ -1482,10 +1482,12 @@
>>
>>  /* Make sure that the filtered search returned a single dn */
>>  if (result == LDAP_SUCCESS && dn) {
>> +req->dn = dn;
>> +req->vals = vals;
>>  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02631)
>>"auth_ldap authorize: require ldap-search: "
>>"authorization successful");
>> -set_request_vars(r, LDAP_AUTHZ, req->vals);
>> +set_request_vars(r, LDAP_AUTHZ, vals);
>>  return AUTHZ_GRANTED;
>>  }
>>  else {
>>
>>
>>>
>>> For example the ldap-search might be doing a lookup on (sucks thumb) the 
>>> issuer of a certificate, which if it matches some LDAP
>>> object means it is allowed. The DN will not refer to the user, but 
>>> something else.
>>
>> I get that. Hence I wonder why we care of the dn fitting to r->user set 
>> before.
>>
>>>
>>> On a side note, ldap-search requires that exactly one LDAP object matches, 
>>> we might want to support many matches, or a specific
>>> number of matches.
> 
> I still don't get where "Make sure that the filtered search returned a
> single dn" is enforced, is it because result != LDAP_SUCCESS
> otherwise, or dn == NULL if there are multiple objects/DNs?

Have a look at line 2117 and following in modules/ldap/util_ldap.c. We call it 
in line 1480 of modules/aaa/mod_authnz_ldap.c via
util_ldap_cache_getuserdn. Result will be LDAP_NO_SUCH_OBJECT and dn will stay 
the same as before the call.

Regards

Rüdiger


Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Yann Ylavic
On Thu, Nov 23, 2023 at 1:33 PM Ruediger Pluem  wrote:
>
>
>
> On 11/23/23 12:52 PM, Graham Leggett via dev wrote:
> > On 23 Nov 2023, at 11:25, Ruediger Pluem  wrote:
> >
> >>> -if (req->dn == NULL || !*req->dn) {
> >>> -ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> >>> -  "auth_ldap authorize: require ldap-filter: user's 
> >>> DN "
> >>> -  "has not been defined; failing authorization");
> >>> -return AUTHZ_DENIED;
> >>> +if (req->dn == NULL || !*req->dn) {
> >>> +ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> >>> +  "auth_ldap authorize: require ldap-search: 
> >>> user's DN "
> >>> +  "has not been defined; failing authorization");
> >>> +return AUTHZ_DENIED;
> >>> +}
> >>
> >> Why do we need to get the dn in case that r->user is not NULL and why is 
> >> it a reason to fail if we don't get a dn for this user?
> >
> > This message is misleading, the DN we care about is not the DN of the user, 
> > but rather the DN of the object returned in the
> > ldap-search, which may or may not bear a relation to the user.
>
> Unfortunately the message is correct and we do just that via 
> get_dn_for_nonldap_authn (line 1451). The DN you mention we look for
> later in line 1480 via util_ldap_cache_getuserdn.

My guess was that if r->user is set we always want to use it for ldap
requests/authn? Or maybe there should be another Require ldap-!search
configured to achieve that (if wanted) since ldap-search is special..

> BTW: I guess the following patch is missing as we don't store the dn / vals 
> we get from util_ldap_cache_getuserdn but just
> "forget" it once we leave the function.
>
>
> Index: modules/aaa/mod_authnz_ldap.c
> ===
> --- modules/aaa/mod_authnz_ldap.c   (revision 1914069)
> +++ modules/aaa/mod_authnz_ldap.c   (working copy)
> @@ -1482,10 +1482,12 @@
>
>  /* Make sure that the filtered search returned a single dn */
>  if (result == LDAP_SUCCESS && dn) {
> +req->dn = dn;
> +req->vals = vals;
>  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02631)
>"auth_ldap authorize: require ldap-search: "
>"authorization successful");
> -set_request_vars(r, LDAP_AUTHZ, req->vals);
> +set_request_vars(r, LDAP_AUTHZ, vals);
>  return AUTHZ_GRANTED;
>  }
>  else {
>
>
> >
> > For example the ldap-search might be doing a lookup on (sucks thumb) the 
> > issuer of a certificate, which if it matches some LDAP
> > object means it is allowed. The DN will not refer to the user, but 
> > something else.
>
> I get that. Hence I wonder why we care of the dn fitting to r->user set 
> before.
>
> >
> > On a side note, ldap-search requires that exactly one LDAP object matches, 
> > we might want to support many matches, or a specific
> > number of matches.

I still don't get where "Make sure that the filtered search returned a
single dn" is enforced, is it because result != LDAP_SUCCESS
otherwise, or dn == NULL if there are multiple objects/DNs?


Regards;
Yann.


Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Ruediger Pluem



On 11/23/23 12:52 PM, Graham Leggett via dev wrote:
> On 23 Nov 2023, at 11:25, Ruediger Pluem  wrote:
> 
>>> -    if (req->dn == NULL || !*req->dn) {
>>> -    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
>>> -  "auth_ldap authorize: require ldap-filter: user's DN 
>>> "
>>> -  "has not been defined; failing authorization");
>>> -    return AUTHZ_DENIED;
>>> +    if (req->dn == NULL || !*req->dn) {
>>> +    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
>>> +  "auth_ldap authorize: require ldap-search: 
>>> user's DN "
>>> +  "has not been defined; failing authorization");
>>> +    return AUTHZ_DENIED;
>>> +    }
>>
>> Why do we need to get the dn in case that r->user is not NULL and why is it 
>> a reason to fail if we don't get a dn for this user?
> 
> This message is misleading, the DN we care about is not the DN of the user, 
> but rather the DN of the object returned in the
> ldap-search, which may or may not bear a relation to the user.

Unfortunately the message is correct and we do just that via 
get_dn_for_nonldap_authn (line 1451). The DN you mention we look for
later in line 1480 via util_ldap_cache_getuserdn.
BTW: I guess the following patch is missing as we don't store the dn / vals we 
get from util_ldap_cache_getuserdn but just
"forget" it once we leave the function.


Index: modules/aaa/mod_authnz_ldap.c
===
--- modules/aaa/mod_authnz_ldap.c   (revision 1914069)
+++ modules/aaa/mod_authnz_ldap.c   (working copy)
@@ -1482,10 +1482,12 @@

 /* Make sure that the filtered search returned a single dn */
 if (result == LDAP_SUCCESS && dn) {
+req->dn = dn;
+req->vals = vals;
 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02631)
   "auth_ldap authorize: require ldap-search: "
   "authorization successful");
-set_request_vars(r, LDAP_AUTHZ, req->vals);
+set_request_vars(r, LDAP_AUTHZ, vals);
 return AUTHZ_GRANTED;
 }
 else {


> 
> For example the ldap-search might be doing a lookup on (sucks thumb) the 
> issuer of a certificate, which if it matches some LDAP
> object means it is allowed. The DN will not refer to the user, but something 
> else.

I get that. Hence I wonder why we care of the dn fitting to r->user set before.

> 
> On a side note, ldap-search requires that exactly one LDAP object matches, we 
> might want to support many matches, or a specific
> number of matches.
> 

Regards

Rüdiger



Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Graham Leggett via dev
On 23 Nov 2023, at 11:25, Ruediger Pluem  wrote:

>> -if (req->dn == NULL || !*req->dn) {
>> -ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
>> -  "auth_ldap authorize: require ldap-filter: user's DN "
>> -  "has not been defined; failing authorization");
>> -return AUTHZ_DENIED;
>> +if (req->dn == NULL || !*req->dn) {
>> +ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
>> +  "auth_ldap authorize: require ldap-search: user's 
>> DN "
>> +  "has not been defined; failing authorization");
>> +return AUTHZ_DENIED;
>> +}
> 
> Why do we need to get the dn in case that r->user is not NULL and why is it a 
> reason to fail if we don't get a dn for this user?

This message is misleading, the DN we care about is not the DN of the user, but 
rather the DN of the object returned in the ldap-search, which may or may not 
bear a relation to the user.

For example the ldap-search might be doing a lookup on (sucks thumb) the issuer 
of a certificate, which if it matches some LDAP object means it is allowed. The 
DN will not refer to the user, but something else.

On a side note, ldap-search requires that exactly one LDAP object matches, we 
might want to support many matches, or a specific number of matches.

Regards,
Graham
—



Re: svn commit: r1914067 - in /httpd/httpd/trunk: changes-entries/ldap-optimise.txt modules/aaa/mod_authnz_ldap.c

2023-11-23 Thread Ruediger Pluem



On 11/23/23 11:22 AM, minf...@apache.org wrote:
> Author: minfrin
> Date: Thu Nov 23 10:22:58 2023
> New Revision: 1914067
> 
> URL: http://svn.apache.org/viewvc?rev=1914067=rev
> Log:
> Optimise handling LDAP authorization where LDAP was not used
> previously for LDAP authentication.
> 
> Added:
> httpd/httpd/trunk/changes-entries/ldap-optimise.txt
> Modified:
> httpd/httpd/trunk/modules/aaa/mod_authnz_ldap.c
> 

> Modified: httpd/httpd/trunk/modules/aaa/mod_authnz_ldap.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authnz_ldap.c?rev=1914067=1914066=1914067=diff
> ==
> --- httpd/httpd/trunk/modules/aaa/mod_authnz_ldap.c (original)

> @@ -1440,24 +1437,27 @@ static authz_status ldapsearch_check_aut
>   * the req structure needed for authorization needs to be created
>   * and populated with the userid and DN of the account in LDAP
>   */
> -
>  if (!req) {
> -authz_status rv = AUTHZ_DENIED;
>  req = build_request_config(r);
> -ldc = get_connection_for_authz(r, LDAP_SEARCH);
> -if (AUTHZ_GRANTED != (rv = get_dn_for_nonldap_authn(r, ldc))) {
> +}
> +ldc = get_connection_for_authz(r, LDAP_SEARCH);
> +if (!req->dn && r->user) {
> +authz_status rv;
> +if (!*r->user) {
> +ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10487)
> +  "ldap authorize: Userid is blank, AuthType=%s",
> +  r->ap_auth_type);
> +}
> +rv = get_dn_for_nonldap_authn(r, ldc);
> +if (rv != AUTHZ_GRANTED) {
>  return rv;
>  }
> -}
> -else {
> -ldc = get_connection_for_authz(r, LDAP_SEARCH);
> -}
> -
> -if (req->dn == NULL || !*req->dn) {
> -ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> -  "auth_ldap authorize: require ldap-filter: user's DN "
> -  "has not been defined; failing authorization");
> -return AUTHZ_DENIED;
> +if (req->dn == NULL || !*req->dn) {
> +ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02636)
> +  "auth_ldap authorize: require ldap-search: user's 
> DN "
> +  "has not been defined; failing authorization");
> +return AUTHZ_DENIED;
> +}

Why do we need to get the dn in case that r->user is not NULL and why is it a 
reason to fail if we don't get a dn for this user?

>  }
>  
>  require = ap_expr_str_exec(r, expr, );
> 
> 
> 


Regards

Rüdiger


Re: svn commit: r1912245 - in /httpd/httpd/trunk/modules/proxy: balancers/mod_lbmethod_bybusyness.c mod_proxy_balancer.c proxy_util.c proxy_util.h

2023-11-23 Thread Ruediger Pluem



On 9/11/23 3:50 PM, jfcl...@apache.org wrote:
> Author: jfclere
> Date: Mon Sep 11 13:50:21 2023
> New Revision: 1912245
> 
> URL: http://svn.apache.org/viewvc?rev=1912245=rev
> Log:
> Arrange the bybusyness logic and prevent bad busy values
> this closes #383
> 
> Modified:
> httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_bybusyness.c
> httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
> httpd/httpd/trunk/modules/proxy/proxy_util.c
> httpd/httpd/trunk/modules/proxy/proxy_util.h
> 

> Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c?rev=1912245=1912244=1912245=diff
> ==
> --- httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c (original)
> +++ httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c Mon Sep 11 13:50:21 
> 2023
> @@ -17,6 +17,7 @@
>  /* Load balancer module for Apache proxy */
>  
>  #include "mod_proxy.h"
> +#include "proxy_util.h"
>  #include "scoreboard.h"
>  #include "ap_mpm.h"
>  #include "apr_version.h"
> @@ -486,17 +487,6 @@ static void force_recovery(proxy_balance
>  }
>  }
>  
> -static apr_status_t decrement_busy_count(void *worker_)
> -{
> -proxy_worker *worker = worker_;
> -
> -if (worker->s->busy) {
> -worker->s->busy--;
> -}
> -
> -return APR_SUCCESS;
> -}
> -
>  static int proxy_balancer_pre_request(proxy_worker **worker,
>proxy_balancer **balancer,
>request_rec *r,
> @@ -635,7 +625,7 @@ static int proxy_balancer_pre_request(pr
>  *worker = runtime;
>  }
>  
> -(*worker)->s->busy++;
> +increment_busy_count(*worker);
>  apr_pool_cleanup_register(r->pool, *worker, decrement_busy_count,
>apr_pool_cleanup_null);
>  
> @@ -1575,7 +1565,7 @@ static void balancer_display_page(reques
>"\n", NULL);
>  ap_rprintf(r,
> "  %" APR_SIZE_T_FMT 
> "\n",
> -   worker->s->busy);
> +   getbusy_count(worker));
>  ap_rprintf(r, "  %d\n",
> worker->s->lbset);
>  /* End proxy_worker_stat */
> @@ -1748,7 +1738,7 @@ static void balancer_display_page(reques
>  ap_rvputs(r, ap_proxy_parse_wstatus(r->pool, worker), NULL);
>  ap_rputs("", r);
>  ap_rprintf(r, "%" APR_SIZE_T_FMT "", 
> worker->s->elected);
> -ap_rprintf(r, "%" APR_SIZE_T_FMT "", 
> worker->s->busy);
> +ap_rprintf(r, "%" APR_SIZE_T_FMT "", 
> getbusy_count(worker));
>  ap_rprintf(r, "%d", worker->s->lbstatus);
>  ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
>  ap_rputs("", r);
> 
> Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=1912245=1912244=1912245=diff
> ==
> --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
> +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Mon Sep 11 13:50:21 2023
> @@ -21,6 +21,7 @@
>  #include "apr_version.h"
>  #include "apr_strings.h"
>  #include "apr_hash.h"
> +#include "apr_atomic.h"
>  #include "http_core.h"
>  #include "proxy_util.h"
>  #include "ajp.h"
> @@ -4984,6 +4985,124 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tun
>  return APR_SUCCESS;
>  }
>  
> +PROXY_DECLARE(apr_status_t) decrement_busy_count(void *worker_)

Why can't we use the respective apr_atomic_sub/add/inc/dec* functions here
instead of the logic below?

> +{
> +apr_size_t val;
> +proxy_worker *worker = worker_;
> +
> +#if APR_SIZEOF_VOIDP == 4
> +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> +val = apr_atomic_read32(>s->busy);
> +while (val > 0) {
> +apr_size_t old = val;
> +val = apr_atomic_cas32(>s->busy, val - 1, old);
> +if (val == old) {
> +break;
> +}
> +}
> +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 1.7.4 
> */
> +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> +val = apr_atomic_read64(>s->busy);
> +while (val > 0) {
> +apr_size_t old = val;
> +val = apr_atomic_cas64(>s->busy, val - 1, old);
> +if (val == old) {
> +break;
> +}
> +}
> +#else /* Use atomics for (64bit) pointers */
> +void *volatile *busy_p = (void *)>s->busy;
> +AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> +AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> +val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> +while (val > 0) {
> +