From 3e2831805395248a4781be5eaf4765c64d5d1db0 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Tue, 7 Jan 2025 15:04:23 +0000 Subject: [PATCH] *) Add the ldap-search option to mod_authnz_ldap, allowing authorization to be based on arbitrary expressions that do not include the username. Make sure that when ldap searches are too long, we explicitly log the error. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1922957 13f79535-47bb-0310-9956-ffa450edef68 --- STATUS | 19 -- docs/manual/expr.xml | 1 + docs/manual/mod/mod_authnz_ldap.xml | 28 +++ modules/aaa/mod_authnz_ldap.c | 280 ++++++++++++++++++++-------- 4 files changed, 230 insertions(+), 98 deletions(-) diff --git a/STATUS b/STATUS index 8d701cfebe4..b76df562238 100644 --- a/STATUS +++ b/STATUS @@ -157,25 +157,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) Add the ldap-search option to mod_authnz_ldap, allowing authorization - to be based on arbitrary expressions that do not include the username. - Make sure that when ldap searches are too long, we explicitly log the - error. - Trunk version of patch: - https://svn.apache.org/r1589993 - https://svn.apache.org/r1591012 - https://svn.apache.org/r1596108 - https://svn.apache.org/r1745033 - https://svn.apache.org/r1913958 - https://svn.apache.org/r1913959 - https://svn.apache.org/r1914091 - https://svn.apache.org/r1914281 - Backport version for 2.4.x of patch: - https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/httpd-2.4-httpd-2.4-ldap-search5.patch - +1: minfrin, covener, jim - rpluem says: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/httpd-2.4-ldap-search5.patch returns 404 - covener: fixed slightly diff URL above - *) mod_proxy: Honor parameters of ProxyPassMatch workers with substitution in the host name or port. PR 69233. trunk patch: https://svn.apache.org/r1912462 diff --git a/docs/manual/expr.xml b/docs/manual/expr.xml index 0c9892abfbc..6a5ea072e5a 100644 --- a/docs/manual/expr.xml +++ b/docs/manual/expr.xml @@ -61,6 +61,7 @@ Require ldap-dn Require ldap-attribute Require ldap-filter +Require ldap-search Require dbd-group Require dbm-group Require group diff --git a/docs/manual/mod/mod_authnz_ldap.xml b/docs/manual/mod/mod_authnz_ldap.xml index 8c1ae9614de..bed3a883ce3 100644 --- a/docs/manual/mod/mod_authnz_ldap.xml +++ b/docs/manual/mod/mod_authnz_ldap.xml @@ -89,6 +89,7 @@ for HTTP Basic authentication.
  • Require ldap-dn
  • Require ldap-attribute
  • Require ldap-filter
  • +
  • Require ldap-search
  • @@ -234,6 +235,11 @@ in mod_ldap for details of the cache tunables. directive, and the search filter successfully finds a single user object that matches the dn of the authenticated user. +
  • Grant access if there is a + Require ldap-search + directive, and the search filter successfully returns a single + matching object with any distinguished name.
  • +
  • otherwise, deny or decline access
  • @@ -531,6 +537,28 @@ Require ldap-filter "&(cell=*)(department=marketing)" +
    Require ldap-search + +

    The Require ldap-search directive allows the + administrator to grant access based on a generic LDAP search filter using an + expression. If there is exactly one match to the search filter, + regardless of the distinguished name, access is granted.

    + +

    The following directive would grant access to URLs that match the given objects in the + LDAP server:

    + + +<LocationMatch ^/dav/(?[^/]+)/> +Require ldap-search (cn=%{ldap:%{unescape:%{env:MATCH_SITENAME}} Website) +</LocationMatch> + + +

    Note: care must be taken to ensure that any expressions are properly escaped to guard + against LDAP injection. The ldap function can be used as per the example + above.

    + +
    +
    Examples diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c index 95d090a5cec..d5b8b80c4f7 100644 --- a/modules/aaa/mod_authnz_ldap.c +++ b/modules/aaa/mod_authnz_ldap.c @@ -84,10 +84,10 @@ typedef struct { } authn_ldap_config_t; typedef struct { - char *dn; /* The saved dn from a successful search */ - char *user; /* The username provided by the client */ + const char *dn; /* The saved dn from a successful search */ + const char *user; /* The username provided by the client */ const char **vals; /* The additional values pulled during the DN search*/ - char *password; /* if this module successfully authenticates, the basic auth password, else null */ + const char *password; /* if this module successfully authenticates, the basic auth password, else null */ } authn_ldap_request_t; enum auth_ldap_phase { @@ -192,11 +192,8 @@ static const char* authn_ldap_xlate_password(request_rec *r, /* * Build the search filter, or at least as much of the search filter that - * will fit in the buffer. We don't worry about the buffer not being able - * to hold the entire filter. If the buffer wasn't big enough to hold the - * filter, ldap_search_s will complain, but the only situation where this - * is likely to happen is if the client sent a really, really long - * username, most likely as part of an attack. + * will fit in the buffer, and return APR_EGENERAL if it won't fit, otherwise + * APR_SUCCESS. * * The search filter consists of the filter provided with the URL, * combined with a filter made up of the attribute provided with the URL, @@ -209,31 +206,24 @@ static const char* authn_ldap_xlate_password(request_rec *r, * search filter will be (&(posixid=*)(uid=userj)). */ #define FILTER_LENGTH MAX_STRING_LEN -static void authn_ldap_build_filter(char *filtbuf, +static apr_status_t authn_ldap_build_filter(char filtbuf[FILTER_LENGTH], request_rec *r, - const char* sent_user, - const char* sent_filter, + const char *user, + const char *filter, authn_ldap_config_t *sec) { - char *p, *q, *filtbuf_end; - char *user, *filter; + char *q; + const char *p, *filtbuf_end; apr_xlate_t *convset = NULL; apr_size_t inbytes; apr_size_t outbytes; char *outbuf; - int nofilter = 0; + int nofilter = 0, len; + apr_status_t rv = APR_SUCCESS; - if (sent_user != NULL) { - user = apr_pstrdup (r->pool, sent_user); - } - else - return; - - if (sent_filter != NULL) { - filter = apr_pstrdup (r->pool, sent_filter); - } - else + if (!filter) { filter = sec->filter; + } if (charset_conversions) { convset = get_conv_set(r); @@ -246,7 +236,7 @@ static void authn_ldap_build_filter(char *filtbuf, /* Convert the user name to UTF-8. This is only valid for LDAP v3 */ if (apr_xlate_conv_buffer(convset, user, &inbytes, outbuf, &outbytes) == APR_SUCCESS) { - user = apr_pstrdup(r->pool, outbuf); + user = outbuf; } } @@ -255,11 +245,11 @@ static void authn_ldap_build_filter(char *filtbuf, * config-supplied portions. */ - if ((nofilter = (filter && !strcasecmp(filter, "none")))) { - apr_snprintf(filtbuf, FILTER_LENGTH, "(%s=", sec->attribute); + if ((nofilter = (!filter || !*filter || !strcasecmp(filter, "none")))) { + len = apr_snprintf(filtbuf, FILTER_LENGTH, "(%s=", sec->attribute); } else { - apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute); + len = apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute); } /* @@ -267,12 +257,13 @@ static void authn_ldap_build_filter(char *filtbuf, * LDAP filter metachars are escaped. */ filtbuf_end = filtbuf + FILTER_LENGTH - 1; -#if APR_HAS_MICROSOFT_LDAPSDK - for (p = user, q=filtbuf + strlen(filtbuf); - *p && q < filtbuf_end; ) { + for (p = user, q = filtbuf + len; *p; ) { if (strchr("*()\\", *p) != NULL) { - if ( q + 3 >= filtbuf_end) - break; /* Don't write part of escape sequence if we can't write all of it */ +#if APR_HAS_MICROSOFT_LDAPSDK + if (q + 3 >= filtbuf_end) { /* accounts for final \0 */ + rv = APR_EGENERAL; + goto out; + } *q++ = '\\'; switch ( *p++ ) { @@ -292,23 +283,24 @@ static void authn_ldap_build_filter(char *filtbuf, *q++ = '5'; *q++ = 'c'; break; - } - } - else - *q++ = *p++; - } + } #else - for (p = user, q=filtbuf + strlen(filtbuf); - *p && q < filtbuf_end; *q++ = *p++) { - if (strchr("*()\\", *p) != NULL) { + if (q + 2 >= filtbuf_end) { /* accounts for final \0 */ + rv = APR_EGENERAL; + goto out; + } *q++ = '\\'; - if (q >= filtbuf_end) { - break; + *q++ = *p++; +#endif + } + else { + if (q + 1 >= filtbuf_end) { /* accounts for final \0 */ + rv = APR_EGENERAL; + goto out; } + *q++ = *p++; } } -#endif - *q = '\0'; /* * Append the closing parens of the filter, unless doing so would @@ -316,14 +308,24 @@ static void authn_ldap_build_filter(char *filtbuf, */ if (nofilter) { - if (q + 1 <= filtbuf_end) - strcat(filtbuf, ")"); + if (q + 1 >= filtbuf_end) { /* accounts for final \0 */ + rv = APR_EGENERAL; + goto out; + } + *q++ = ')'; } else { - if (q + 2 <= filtbuf_end) - strcat(filtbuf, "))"); + if (q + 2 >= filtbuf_end) { /* accounts for final \0 */ + rv = APR_EGENERAL; + goto out; + } + *q++ = ')'; + *q++ = ')'; } +out: + *q = '\0'; + return rv; } static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d) @@ -371,15 +373,12 @@ static apr_status_t authnz_ldap_cleanup_connection_close(void *param) return APR_SUCCESS; } -static int set_request_vars(request_rec *r, enum auth_ldap_phase phase) { +static int set_request_vars(request_rec *r, enum auth_ldap_phase phase, const char **vals) { char *prefix = NULL; int prefix_len; int remote_user_attribute_set = 0; - authn_ldap_request_t *req = - (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); authn_ldap_config_t *sec = (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); - const char **vals = req->vals; prefix = (phase == LDAP_AUTHN) ? AUTHN_PREFIX : sec->authz_prefix; prefix_len = strlen(prefix); @@ -441,8 +440,8 @@ static util_ldap_connection_t *get_connection_for_authz(request_rec *r, enum aut authn_ldap_config_t *sec = (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); - char *binddn = sec->binddn; - char *bindpw = sec->bindpw; + const char *binddn = sec->binddn; + const char *bindpw = sec->bindpw; /* If the per-request config isn't set, we didn't authenticate this user, and leave the default credentials */ if (req && req->password && @@ -549,7 +548,13 @@ static authn_status authn_ldap_check_password(request_rec *r, const char *user, "auth_ldap authenticate: using URL %s", sec->url); /* build the username filter */ - authn_ldap_build_filter(filtbuf, r, user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02622) + "auth_ldap authenticate: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + util_ldap_connection_close(ldc); + return AUTH_GENERAL_ERROR; + } ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "auth_ldap authenticate: final authn filter is %s", filtbuf); @@ -606,15 +611,15 @@ static authn_status authn_ldap_check_password(request_rec *r, const char *user, } /* mark the user and DN */ - req->dn = apr_pstrdup(r->pool, dn); - req->user = apr_pstrdup(r->pool, user); - req->password = apr_pstrdup(r->pool, password); + req->dn = dn; + req->user = user; + req->password = password; if (sec->user_is_dn) { - r->user = req->dn; + r->user = (char *)req->dn; } /* add environment variables */ - remote_user_attribute_set = set_request_vars(r, LDAP_AUTHN); + remote_user_attribute_set = set_request_vars(r, LDAP_AUTHN, req->vals); /* sanity check */ if (sec->remote_user_attribute && !remote_user_attribute_set) { @@ -696,7 +701,12 @@ static authz_status ldapuser_check_authorization(request_rec *r, sizeof(authn_ldap_request_t)); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02623) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -710,7 +720,7 @@ static authz_status ldapuser_check_authorization(request_rec *r, } ap_set_module_config(r->request_config, &authnz_ldap_module, req); - req->dn = apr_pstrdup(r->pool, dn); + req->dn = dn; req->user = r->user; } @@ -740,7 +750,7 @@ static authz_status ldapuser_check_authorization(request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01703) "auth_ldap authorize: require user: authorization " "successful"); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } default: { @@ -762,7 +772,7 @@ static authz_status ldapuser_check_authorization(request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01705) "auth_ldap authorize: " "require user: authorization successful"); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } default: { @@ -880,7 +890,12 @@ static authz_status ldapgroup_check_authorization(request_rec *r, req = (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t)); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02624) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -894,7 +909,7 @@ static authz_status ldapgroup_check_authorization(request_rec *r, } ap_set_module_config(r->request_config, &authnz_ldap_module, req); - req->dn = apr_pstrdup(r->pool, dn); + req->dn = dn; req->user = r->user; } @@ -949,7 +964,7 @@ static authz_status ldapgroup_check_authorization(request_rec *r, "[%s][%d - %s]", ent[i].name, ldc->reason, result, ldap_err2string(result)); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } else { @@ -988,7 +1003,7 @@ static authz_status ldapgroup_check_authorization(request_rec *r, "(attribute %s) [%s][%d - %s]", ent[i].name, ldc->reason, result, ldap_err2string(result)); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } else { @@ -1069,7 +1084,12 @@ static authz_status ldapdn_check_authorization(request_rec *r, req = (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t)); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02625) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -1083,7 +1103,7 @@ static authz_status ldapdn_check_authorization(request_rec *r, } ap_set_module_config(r->request_config, &authnz_ldap_module, req); - req->dn = apr_pstrdup(r->pool, dn); + req->dn = dn; req->user = r->user; } @@ -1110,7 +1130,7 @@ static authz_status ldapdn_check_authorization(request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01726) "auth_ldap authorize: " "require dn: authorization successful"); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } default: { @@ -1191,7 +1211,12 @@ static authz_status ldapattribute_check_authorization(request_rec *r, req = (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t)); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02626) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -1205,7 +1230,7 @@ static authz_status ldapattribute_check_authorization(request_rec *r, } ap_set_module_config(r->request_config, &authnz_ldap_module, req); - req->dn = apr_pstrdup(r->pool, dn); + req->dn = dn; req->user = r->user; } @@ -1239,7 +1264,7 @@ static authz_status ldapattribute_check_authorization(request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01735) "auth_ldap authorize: " "require attribute: authorization successful"); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } default: { @@ -1319,7 +1344,12 @@ static authz_status ldapfilter_check_authorization(request_rec *r, req = (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t)); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02627) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -1333,7 +1363,7 @@ static authz_status ldapfilter_check_authorization(request_rec *r, } ap_set_module_config(r->request_config, &authnz_ldap_module, req); - req->dn = apr_pstrdup(r->pool, dn); + req->dn = dn; req->user = r->user; } @@ -1359,7 +1389,12 @@ static authz_status ldapfilter_check_authorization(request_rec *r, "auth_ldap authorize: checking filter %s", t); /* Build the username filter */ - authn_ldap_build_filter(filtbuf, r, req->user, t, sec); + if (APR_SUCCESS != authn_ldap_build_filter(filtbuf, r, req->user, t, sec)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02628) + "auth_ldap authorize: ldap filter too long (>%d): %s", + FILTER_LENGTH, filtbuf); + return AUTHZ_DENIED; + } /* Search for the user DN */ result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, @@ -1384,7 +1419,7 @@ static authz_status ldapfilter_check_authorization(request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01745) "auth_ldap authorize: require ldap-filter: " "authorization successful"); - set_request_vars(r, LDAP_AUTHZ); + set_request_vars(r, LDAP_AUTHZ, req->vals); return AUTHZ_GRANTED; } case LDAP_FILTER_ERROR: { @@ -1411,6 +1446,83 @@ static authz_status ldapfilter_check_authorization(request_rec *r, return AUTHZ_DENIED; } +static authz_status ldapsearch_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + const char *t; + const char *dn = NULL; + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_SEARCH); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02636) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02629) + "auth_ldap authorize: require ldap-search: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + + if (t[0]) { + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02630) + "auth_ldap authorize: checking filter %s", t); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, t, &dn, &(req->vals)); + + /* Make sure that the filtered search returned a single dn */ + if (result == LDAP_SUCCESS && dn) { + req->dn = dn; + 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); + return AUTHZ_GRANTED; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02632) + "auth_ldap authorize: require ldap-search: " + "%s authorization failed [%s][%s]", + t, ldc->reason, ldap_err2string(result)); + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02633) + "auth_ldap authorize search: authorization denied for " + "to %s", r->uri); + + return AUTHZ_DENIED; +} + static const char *ldap_parse_config(cmd_parms *cmd, const char *require_line, const void **parsed_require_line) { @@ -1919,6 +2031,12 @@ static const authz_provider authz_ldapfilter_provider = &ldap_parse_config, }; +static const authz_provider authz_ldapsearch_provider = +{ + &ldapsearch_check_authorization, + &ldap_parse_config, +}; + static void ImportULDAPOptFn(void) { util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close); @@ -1959,6 +2077,10 @@ static void register_hooks(apr_pool_t *p) AUTHZ_PROVIDER_VERSION, &authz_ldapfilter_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-search", + AUTHZ_PROVIDER_VERSION, + &authz_ldapsearch_provider, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_post_config(authnz_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);