1 /* ============================================================
2 * Copyright (c) 2003-2004, Ondrej Sury
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * mod_vhost_ldap.c --- read virtual host config from LDAP directory
28 #include "http_config.h"
29 #include "http_core.h"
31 #include "http_request.h"
32 #include "apr_version.h"
34 #include "apr_reslist.h"
35 #include "apr_strings.h"
36 #include "apr_thread_mutex.h"
37 #include "apr_thread_rwlock.h"
38 #include "apr_tables.h"
39 #include "util_ldap.h"
40 #include "util_script.h"
42 #if !defined(APU_HAS_LDAP) && !defined(APR_HAS_LDAP)
43 #error mod_vhost_ldap requires APR-util to have LDAP support built in
46 #if !defined(WIN32) && !defined(OS2) && !defined(BEOS) && !defined(NETWARE)
47 #define HAVE_UNIX_SUEXEC
50 #ifdef HAVE_UNIX_SUEXEC
51 #include "unixd.h" /* Contains the suexec_identity hook used on Unix */
57 #define MAX_FAILURES 5
59 module AP_MODULE_DECLARE_DATA vhost_ldap_module;
62 MVL_UNSET, MVL_DISABLED, MVL_ENABLED
63 } mod_vhost_ldap_status_e;
65 typedef struct mod_vhost_ldap_config_t {
66 mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */
68 /* These parameters are all derived from the VhostLDAPURL directive */
69 char *url; /* String representation of LDAP URL */
71 char *host; /* Name of the LDAP server (or space separated list) */
72 int port; /* Port of the LDAP server */
73 char *basedn; /* Base DN to do all searches from */
74 int scope; /* Scope of the search */
75 char *filter; /* Filter to further limit the search */
76 deref_options deref; /* how to handle alias dereferening */
78 char *binddn; /* DN to bind to server (can be NULL) */
79 char *bindpw; /* Password to bind to server (can be NULL) */
81 int have_deref; /* Set if we have found an Deref option */
82 int have_ldap_url; /* Set if we have found an LDAP url */
84 int secure; /* True if SSL connections are requested */
86 char *fallback; /* Fallback virtual host */
88 apr_thread_mutex_t *mutex; /* Create per worker mutex to synchronize threads */
90 } mod_vhost_ldap_config_t;
92 typedef struct mod_vhost_ldap_request_t {
93 char *dn; /* The saved dn from a successful search */
94 char *name; /* ServerName */
95 char *admin; /* ServerAdmin */
96 char *docroot; /* DocumentRoot */
97 char *cgiroot; /* ScriptAlias */
98 char *uid; /* Suexec Uid */
99 char *gid; /* Suexec Gid */
100 } mod_vhost_ldap_request_t;
103 { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 };
105 #if (APR_MAJOR_VERSION >= 1)
106 static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
107 static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
108 static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
109 static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
110 static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
111 static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
112 static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
114 static void ImportULDAPOptFn(void)
116 util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
117 util_ldap_connection_find = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
118 util_ldap_cache_comparedn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
119 util_ldap_cache_compare = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
120 util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
121 util_ldap_cache_getuserdn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
122 util_ldap_ssl_supported = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
126 /* Taken from server/core.c */
127 static int set_document_root(request_rec *r, const char *arg)
129 void *sconf = r->server->module_config;
130 core_server_config *conf = ap_get_module_config(sconf, &core_module);
132 /* Make it absolute, relative to ServerRoot */
133 arg = ap_server_root_relative(r->pool, arg);
136 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
137 "[mod_vhost_ldap.c] set_document_root: DocumentRoot [%s] must be a directory",
140 return HTTP_INTERNAL_SERVER_ERROR;
143 /* TODO: ap_configtestonly && ap_docrootcheck && */
144 if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
145 APR_FILEPATH_TRUENAME, r->pool) != APR_SUCCESS
146 || !ap_is_directory(r->pool, arg)) {
148 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
150 "[mod_vhost_ldap.c] set_document_root: Warning: DocumentRoot [%s] does not exist",
152 conf->ap_document_root = arg;
158 static int mod_vhost_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
160 /* make sure that mod_ldap (util_ldap) is loaded */
161 if (ap_find_linked_module("util_ldap.c") == NULL) {
162 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s,
163 "Module mod_ldap missing. Mod_ldap (aka. util_ldap) "
164 "must be loaded in order for mod_vhost_ldap to function properly");
165 return HTTP_INTERNAL_SERVER_ERROR;
169 ap_add_version_component(p, MOD_VHOST_LDAP_VERSION);
175 mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s)
177 mod_vhost_ldap_config_t *conf =
178 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof (mod_vhost_ldap_config_t));
180 conf->enabled = MVL_UNSET;
181 conf->have_ldap_url = 0;
182 conf->have_deref = 0;
185 conf->deref = always;
186 conf->fallback = NULL;
188 apr_thread_mutex_create(&conf->mutex, APR_THREAD_MUTEX_DEFAULT, p);
194 mod_vhost_ldap_merge_server_config(apr_pool_t *p, void *parentv, void *childv)
196 mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv;
197 mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv;
198 mod_vhost_ldap_config_t *conf =
199 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t));
201 if (child->enabled == MVL_UNSET) {
202 conf->enabled = parent->enabled;
204 conf->enabled = child->enabled;
207 if (child->have_ldap_url) {
208 conf->have_ldap_url = child->have_ldap_url;
209 conf->url = child->url;
210 conf->host = child->host;
211 conf->port = child->port;
212 conf->basedn = child->basedn;
213 conf->scope = child->scope;
214 conf->filter = child->filter;
215 conf->secure = child->secure;
217 conf->have_ldap_url = parent->have_ldap_url;
218 conf->url = parent->url;
219 conf->host = parent->host;
220 conf->port = parent->port;
221 conf->basedn = parent->basedn;
222 conf->scope = parent->scope;
223 conf->filter = parent->filter;
224 conf->secure = parent->secure;
226 if (child->have_deref) {
227 conf->have_deref = child->have_deref;
228 conf->deref = child->deref;
230 conf->have_deref = parent->have_deref;
231 conf->deref = parent->deref;
234 conf->binddn = (child->binddn ? child->binddn : parent->binddn);
235 conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw);
237 conf->fallback = (child->fallback ? child->fallback : parent->fallback);
243 * Use the ldap url parsing routines to break up the ldap url into
246 static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd,
251 apr_ldap_url_desc_t *urld;
252 #if (APR_MAJOR_VERSION >= 1)
253 apr_ldap_err_t *result_err;
256 mod_vhost_ldap_config_t *conf =
257 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
260 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
261 cmd->server, "[mod_vhost_ldap.c] url parse: `%s'",
264 #if (APR_MAJOR_VERSION >= 1) /* for apache >= 2.2 */
265 result = apr_ldap_url_parse(cmd->pool, url, &(urld), &(result_err));
266 if (result != LDAP_SUCCESS) {
267 return result_err->reason;
270 result = apr_ldap_url_parse(url, &(urld));
271 if (result != LDAP_SUCCESS) {
273 case LDAP_URL_ERR_NOTLDAP:
274 return "LDAP URL does not begin with ldap://";
275 case LDAP_URL_ERR_NODN:
276 return "LDAP URL does not have a DN";
277 case LDAP_URL_ERR_BADSCOPE:
278 return "LDAP URL has an invalid scope";
279 case LDAP_URL_ERR_MEM:
280 return "Out of memory parsing LDAP URL";
282 return "Could not parse LDAP URL";
286 conf->url = apr_pstrdup(cmd->pool, url);
288 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
289 cmd->server, "[mod_vhost_ldap.c] url parse: Host: %s", urld->lud_host);
290 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
291 cmd->server, "[mod_vhost_ldap.c] url parse: Port: %d", urld->lud_port);
292 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
293 cmd->server, "[mod_vhost_ldap.c] url parse: DN: %s", urld->lud_dn);
294 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
295 cmd->server, "[mod_vhost_ldap.c] url parse: attrib: %s", urld->lud_attrs? urld->lud_attrs[0] : "(null)");
296 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
297 cmd->server, "[mod_vhost_ldap.c] url parse: scope: %s",
298 (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" :
299 urld->lud_scope == LDAP_SCOPE_BASE? "base" :
300 urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"));
301 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
302 cmd->server, "[mod_vhost_ldap.c] url parse: filter: %s", urld->lud_filter);
304 /* Set all the values, or at least some sane defaults */
306 char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2);
307 strcpy(p, urld->lud_host);
309 strcat(p, conf->host);
313 conf->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
315 conf->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
317 conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ?
318 LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE;
320 if (urld->lud_filter) {
321 if (urld->lud_filter[0] == '(') {
323 * Get rid of the surrounding parens; later on when generating the
324 * filter, they'll be put back.
326 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1);
327 conf->filter[strlen(conf->filter)-1] = '\0';
330 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
334 conf->filter = "objectClass=apacheConfig";
337 /* "ldaps" indicates secure ldap connections desired
339 if (strncasecmp(url, "ldaps", 5) == 0)
342 conf->port = urld->lud_port? urld->lud_port : LDAPS_PORT;
343 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
344 "LDAP: vhost_ldap using SSL connections");
349 conf->port = urld->lud_port? urld->lud_port : LDAP_PORT;
350 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
351 "LDAP: vhost_ldap not using SSL connections");
354 conf->have_ldap_url = 1;
355 #if (APR_MAJOR_VERSION < 1) /* free only required for older apr */
356 apr_ldap_free_urldesc(urld);
361 static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int enabled)
363 mod_vhost_ldap_config_t *conf =
364 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
367 conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED;
372 static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const char *binddn)
374 mod_vhost_ldap_config_t *conf =
375 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
378 conf->binddn = apr_pstrdup(cmd->pool, binddn);
382 static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const char *bindpw)
384 mod_vhost_ldap_config_t *conf =
385 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
388 conf->bindpw = apr_pstrdup(cmd->pool, bindpw);
392 static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const char *deref)
394 mod_vhost_ldap_config_t *conf =
395 (mod_vhost_ldap_config_t *)ap_get_module_config (cmd->server->module_config,
398 if (strcmp(deref, "never") == 0 || strcasecmp(deref, "off") == 0) {
400 conf->have_deref = 1;
402 else if (strcmp(deref, "searching") == 0) {
403 conf->deref = searching;
404 conf->have_deref = 1;
406 else if (strcmp(deref, "finding") == 0) {
407 conf->deref = finding;
408 conf->have_deref = 1;
410 else if (strcmp(deref, "always") == 0 || strcasecmp(deref, "on") == 0) {
411 conf->deref = always;
412 conf->have_deref = 1;
415 return "Unrecognized value for VhostLDAPAliasDereference directive";
420 static const char *mod_vhost_ldap_set_fallback(cmd_parms *cmd, void *dummy, const char *fallback)
422 mod_vhost_ldap_config_t *conf =
423 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
426 conf->fallback = apr_pstrdup(cmd->pool, fallback);
430 command_rec mod_vhost_ldap_cmds[] = {
431 AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF,
432 "URL to define LDAP connection. This should be an RFC 2255 compliant\n"
433 "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n"
435 "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n"
436 "to specify redundant servers.\n"
437 "<li>Port is optional, and specifies the port to connect to.\n"
438 "<li>basedn specifies the base DN to start searches from\n"
441 AP_INIT_TAKE1 ("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF,
442 "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."),
444 AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF,
445 "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."),
447 AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF,
448 "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"),
450 AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF,
451 "Determines how aliases are handled during a search. Can be one of the"
452 "values \"never\", \"searching\", \"finding\", or \"always\". "
453 "Defaults to always."),
455 AP_INIT_TAKE1("VhostLDAPFallback", mod_vhost_ldap_set_fallback, NULL, RSRC_CONF,
456 "Set default virtual host which will be used when requested hostname"
457 "is not found in LDAP database. This option can be used to display"
458 "\"virtual host not found\" type of page."),
463 #define FILTER_LENGTH MAX_STRING_LEN
464 static int mod_vhost_ldap_translate_name(request_rec *r)
466 request_rec *top = (r->main)?r->main:r;
467 mod_vhost_ldap_request_t *reqc;
469 const char **vals = NULL;
470 char filtbuf[FILTER_LENGTH];
471 mod_vhost_ldap_config_t *conf =
472 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
473 util_ldap_connection_t *ldc = NULL;
475 const char *dn = NULL;
477 const char *hostname = NULL;
482 struct berval hostnamebv, shostnamebv;
485 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
486 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
488 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
490 // mod_vhost_ldap is disabled or we don't have LDAP Url
491 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
498 ldc = util_ldap_connection_find(r, conf->host, conf->port,
499 conf->binddn, conf->bindpw, conf->deref,
503 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
504 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
505 return HTTP_INTERNAL_SERVER_ERROR;
508 hostname = r->hostname;
509 if (hostname == NULL || hostname[0] == '\0')
514 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
515 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
518 ber_str2bv(hostname, 0, 0, &hostnamebv);
519 if (ldap_bv2escaped_filter_value(&hostnamebv, &shostnamebv) != 0)
521 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, shostnamebv.bv_val, shostnamebv.bv_val);
522 ber_memfree(shostnamebv.bv_val);
524 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
525 attributes, filtbuf, &dn, &vals);
527 util_ldap_connection_close(ldc);
529 /* sanity check - if server is down, retry it up to 5 times */
530 if (AP_LDAP_IS_SERVER_DOWN(result) ||
531 (result == LDAP_TIMEOUT) ||
532 (result == LDAP_CONNECT_ERROR)) {
533 sleep = sleep0 + sleep1;
534 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
535 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
537 if (failures++ < MAX_FAILURES) {
538 /* Back-off exponentially */
539 apr_sleep(apr_time_from_sec(sleep));
544 return HTTP_GATEWAY_TIME_OUT;
548 if (result == LDAP_NO_SUCH_OBJECT) {
549 if (strcmp(hostname, "*") != 0) {
550 if (strncmp(hostname, "*.", 2) == 0)
552 hostname += strcspn(hostname, ".");
553 hostname = apr_pstrcat(r->pool, "*", hostname, NULL);
554 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
555 "[mod_vhost_ldap.c] translate: "
556 "virtual host not found, trying wildcard %s",
562 if (conf->fallback && (is_fallback++ <= 0)) {
563 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
564 "[mod_vhost_ldap.c] translate: "
565 "virtual host %s not found, trying fallback %s",
566 hostname, conf->fallback);
567 hostname = conf->fallback;
571 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
572 "[mod_vhost_ldap.c] translate: "
573 "virtual host %s not found",
576 return HTTP_BAD_REQUEST;
579 /* handle bind failure */
580 if (result != LDAP_SUCCESS) {
581 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
582 "[mod_vhost_ldap.c] translate: "
583 "translate failed; virtual host %s; URI %s [%s]",
584 hostname, r->uri, ldap_err2string(result));
585 return HTTP_INTERNAL_SERVER_ERROR;
588 /* mark the user and DN */
589 reqc->dn = apr_pstrdup(r->pool, dn);
594 while (attributes[i]) {
596 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
597 reqc->name = apr_pstrdup (r->pool, vals[i]);
599 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
600 reqc->admin = apr_pstrdup (r->pool, vals[i]);
602 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
603 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
605 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
606 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
608 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
609 reqc->uid = apr_pstrdup(r->pool, vals[i]);
611 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
612 reqc->gid = apr_pstrdup(r->pool, vals[i]);
618 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
619 "[mod_vhost_ldap.c]: loaded from ldap: "
620 "apacheServerName: %s, "
621 "apacheServerAdmin: %s, "
622 "apacheDocumentRoot: %s, "
623 "apacheScriptAlias: %s, "
624 "apacheSuexecUid: %s, "
625 "apacheSuexecGid: %s",
626 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
628 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
629 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
630 "[mod_vhost_ldap.c] translate: "
631 "translate failed; ServerName or DocumentRoot not defined");
632 return HTTP_INTERNAL_SERVER_ERROR;
638 cgi = strstr(r->uri, "cgi-bin/");
639 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
644 /* Set exact filename for CGI script */
645 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
646 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
647 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
648 "[mod_vhost_ldap.c]: ap_document_root is: %s",
649 ap_document_root(r));
651 r->handler = "cgi-script";
652 apr_table_setn(r->notes, "alias-forced-type", r->handler);
654 } else if (r->uri[0] == '/') {
655 /* we don't set r->filename here, and let other modules do it
656 * this allows other modules (mod_rewrite.c) to work as usual
658 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
660 /* We don't handle non-file requests here */
665 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
666 "[mod_vhost_ldap.c]: locking ap_document_root mutex for [%s]",
668 apr_thread_mutex_lock(conf->mutex);
671 top->server->server_hostname = apr_pstrdup (top->pool, reqc->name);
674 top->server->server_admin = apr_pstrdup (top->pool, reqc->admin);
677 result = set_document_root(r, reqc->docroot);
679 return HTTP_INTERNAL_SERVER_ERROR;
682 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
686 #ifdef HAVE_UNIX_SUEXEC
687 static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
689 ap_unix_identity_t *ugid = NULL;
690 mod_vhost_ldap_config_t *conf =
691 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
693 mod_vhost_ldap_request_t *req =
694 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
700 // mod_vhost_ldap is disabled or we don't have LDAP Url
701 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
705 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
709 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
713 uid = (uid_t)atoll(req->uid);
714 gid = (gid_t)atoll(req->gid);
716 if ((uid < MIN_UID)||(gid < MIN_GID)) {
728 static int mod_vhost_ldap_fixups(request_rec *r)
731 mod_vhost_ldap_config_t *conf =
732 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
733 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
734 "[mod_vhost_ldap.c]: unlocking ap_document_root mutex for [%s]",
737 apr_thread_mutex_unlock(conf->mutex);
743 mod_vhost_ldap_register_hooks (apr_pool_t * p)
747 * Run before mod_rewrite
749 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
751 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
752 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
753 #ifdef HAVE_UNIX_SUEXEC
754 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
756 #if (APR_MAJOR_VERSION >= 1)
757 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
760 ap_hook_fixups(mod_vhost_ldap_fixups, NULL, NULL, APR_HOOK_LAST);
763 module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
764 STANDARD20_MODULE_STUFF,
767 mod_vhost_ldap_create_server_config,
768 mod_vhost_ldap_merge_server_config,
770 mod_vhost_ldap_register_hooks,