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_tables.h"
37 #include "util_ldap.h"
38 #include "util_script.h"
40 #if !defined(APU_HAS_LDAP) && !defined(APR_HAS_LDAP)
41 #error mod_vhost_ldap requires APR-util to have LDAP support built in
44 #if !defined(WIN32) && !defined(OS2) && !defined(BEOS) && !defined(NETWARE)
45 #define HAVE_UNIX_SUEXEC
48 #ifdef HAVE_UNIX_SUEXEC
49 #include "unixd.h" /* Contains the suexec_identity hook used on Unix */
54 const char USERDIR[] = "web_scripts";
56 #define MAX_FAILURES 5
58 module AP_MODULE_DECLARE_DATA vhost_ldap_module;
61 MVL_UNSET, MVL_DISABLED, MVL_ENABLED
62 } mod_vhost_ldap_status_e;
64 typedef struct mod_vhost_ldap_config_t {
65 mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */
67 /* These parameters are all derived from the VhostLDAPURL directive */
68 char *url; /* String representation of LDAP URL */
70 char *host; /* Name of the LDAP server (or space separated list) */
71 int port; /* Port of the LDAP server */
72 char *basedn; /* Base DN to do all searches from */
73 int scope; /* Scope of the search */
74 char *filter; /* Filter to further limit the search */
75 deref_options deref; /* how to handle alias dereferening */
77 char *binddn; /* DN to bind to server (can be NULL) */
78 char *bindpw; /* Password to bind to server (can be NULL) */
80 int have_deref; /* Set if we have found an Deref option */
81 int have_ldap_url; /* Set if we have found an LDAP url */
83 int secure; /* True if SSL connections are requested */
85 char *fallback; /* Fallback virtual host */
87 } mod_vhost_ldap_config_t;
89 typedef struct mod_vhost_ldap_request_t {
90 char *dn; /* The saved dn from a successful search */
91 char *name; /* ServerName */
92 char *admin; /* ServerAdmin */
93 char *docroot; /* DocumentRoot */
94 char *cgiroot; /* ScriptAlias */
95 char *uid; /* Suexec Uid */
96 char *gid; /* Suexec Gid */
97 } mod_vhost_ldap_request_t;
100 { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 };
102 static int total_modules;
104 #if (APR_MAJOR_VERSION >= 1)
105 static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
106 static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
107 static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
108 static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
109 static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
110 static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
111 static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
113 static void ImportULDAPOptFn(void)
115 util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
116 util_ldap_connection_find = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
117 util_ldap_cache_comparedn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
118 util_ldap_cache_compare = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
119 util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
120 util_ldap_cache_getuserdn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
121 util_ldap_ssl_supported = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
125 static int mod_vhost_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
129 /* Stolen from modules/generators/mod_cgid.c */
131 for (m = ap_preloaded_modules; *m != NULL; m++)
134 /* make sure that mod_ldap (util_ldap) is loaded */
135 if (ap_find_linked_module("util_ldap.c") == NULL) {
136 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s,
137 "Module mod_ldap missing. Mod_ldap (aka. util_ldap) "
138 "must be loaded in order for mod_vhost_ldap to function properly");
139 return HTTP_INTERNAL_SERVER_ERROR;
143 ap_add_version_component(p, MOD_VHOST_LDAP_VERSION);
149 mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s)
151 mod_vhost_ldap_config_t *conf =
152 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof (mod_vhost_ldap_config_t));
154 conf->enabled = MVL_UNSET;
155 conf->have_ldap_url = 0;
156 conf->have_deref = 0;
159 conf->deref = always;
160 conf->fallback = NULL;
166 mod_vhost_ldap_merge_server_config(apr_pool_t *p, void *parentv, void *childv)
168 mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv;
169 mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv;
170 mod_vhost_ldap_config_t *conf =
171 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t));
173 if (child->enabled == MVL_UNSET) {
174 conf->enabled = parent->enabled;
176 conf->enabled = child->enabled;
179 if (child->have_ldap_url) {
180 conf->have_ldap_url = child->have_ldap_url;
181 conf->url = child->url;
182 conf->host = child->host;
183 conf->port = child->port;
184 conf->basedn = child->basedn;
185 conf->scope = child->scope;
186 conf->filter = child->filter;
187 conf->secure = child->secure;
189 conf->have_ldap_url = parent->have_ldap_url;
190 conf->url = parent->url;
191 conf->host = parent->host;
192 conf->port = parent->port;
193 conf->basedn = parent->basedn;
194 conf->scope = parent->scope;
195 conf->filter = parent->filter;
196 conf->secure = parent->secure;
198 if (child->have_deref) {
199 conf->have_deref = child->have_deref;
200 conf->deref = child->deref;
202 conf->have_deref = parent->have_deref;
203 conf->deref = parent->deref;
206 conf->binddn = (child->binddn ? child->binddn : parent->binddn);
207 conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw);
209 conf->fallback = (child->fallback ? child->fallback : parent->fallback);
215 * Use the ldap url parsing routines to break up the ldap url into
218 static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd,
223 apr_ldap_url_desc_t *urld;
224 #if (APR_MAJOR_VERSION >= 1)
225 apr_ldap_err_t *result_err;
228 mod_vhost_ldap_config_t *conf =
229 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
232 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
233 cmd->server, "[mod_vhost_ldap.c] url parse: `%s'",
236 #if (APR_MAJOR_VERSION >= 1) /* for apache >= 2.2 */
237 result = apr_ldap_url_parse(cmd->pool, url, &(urld), &(result_err));
238 if (result != LDAP_SUCCESS) {
239 return result_err->reason;
242 result = apr_ldap_url_parse(url, &(urld));
243 if (result != LDAP_SUCCESS) {
245 case LDAP_URL_ERR_NOTLDAP:
246 return "LDAP URL does not begin with ldap://";
247 case LDAP_URL_ERR_NODN:
248 return "LDAP URL does not have a DN";
249 case LDAP_URL_ERR_BADSCOPE:
250 return "LDAP URL has an invalid scope";
251 case LDAP_URL_ERR_MEM:
252 return "Out of memory parsing LDAP URL";
254 return "Could not parse LDAP URL";
258 conf->url = apr_pstrdup(cmd->pool, url);
260 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
261 cmd->server, "[mod_vhost_ldap.c] url parse: Host: %s", urld->lud_host);
262 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
263 cmd->server, "[mod_vhost_ldap.c] url parse: Port: %d", urld->lud_port);
264 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
265 cmd->server, "[mod_vhost_ldap.c] url parse: DN: %s", urld->lud_dn);
266 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
267 cmd->server, "[mod_vhost_ldap.c] url parse: attrib: %s", urld->lud_attrs? urld->lud_attrs[0] : "(null)");
268 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
269 cmd->server, "[mod_vhost_ldap.c] url parse: scope: %s",
270 (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" :
271 urld->lud_scope == LDAP_SCOPE_BASE? "base" :
272 urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"));
273 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
274 cmd->server, "[mod_vhost_ldap.c] url parse: filter: %s", urld->lud_filter);
276 /* Set all the values, or at least some sane defaults */
278 char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2);
279 strcpy(p, urld->lud_host);
281 strcat(p, conf->host);
285 conf->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
287 conf->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
289 conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ?
290 LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE;
292 if (urld->lud_filter) {
293 if (urld->lud_filter[0] == '(') {
295 * Get rid of the surrounding parens; later on when generating the
296 * filter, they'll be put back.
298 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1);
299 conf->filter[strlen(conf->filter)-1] = '\0';
302 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
306 conf->filter = "objectClass=apacheConfig";
309 /* "ldaps" indicates secure ldap connections desired
311 if (strncasecmp(url, "ldaps", 5) == 0)
314 conf->port = urld->lud_port? urld->lud_port : LDAPS_PORT;
315 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
316 "LDAP: vhost_ldap using SSL connections");
321 conf->port = urld->lud_port? urld->lud_port : LDAP_PORT;
322 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
323 "LDAP: vhost_ldap not using SSL connections");
326 conf->have_ldap_url = 1;
327 #if (APR_MAJOR_VERSION < 1) /* free only required for older apr */
328 apr_ldap_free_urldesc(urld);
333 static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int enabled)
335 mod_vhost_ldap_config_t *conf =
336 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
339 conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED;
344 static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const char *binddn)
346 mod_vhost_ldap_config_t *conf =
347 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
350 conf->binddn = apr_pstrdup(cmd->pool, binddn);
354 static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const char *bindpw)
356 mod_vhost_ldap_config_t *conf =
357 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
360 conf->bindpw = apr_pstrdup(cmd->pool, bindpw);
364 static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const char *deref)
366 mod_vhost_ldap_config_t *conf =
367 (mod_vhost_ldap_config_t *)ap_get_module_config (cmd->server->module_config,
370 if (strcmp(deref, "never") == 0 || strcasecmp(deref, "off") == 0) {
372 conf->have_deref = 1;
374 else if (strcmp(deref, "searching") == 0) {
375 conf->deref = searching;
376 conf->have_deref = 1;
378 else if (strcmp(deref, "finding") == 0) {
379 conf->deref = finding;
380 conf->have_deref = 1;
382 else if (strcmp(deref, "always") == 0 || strcasecmp(deref, "on") == 0) {
383 conf->deref = always;
384 conf->have_deref = 1;
387 return "Unrecognized value for VhostLDAPAliasDereference directive";
392 static const char *mod_vhost_ldap_set_fallback(cmd_parms *cmd, void *dummy, const char *fallback)
394 mod_vhost_ldap_config_t *conf =
395 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
398 conf->fallback = apr_pstrdup(cmd->pool, fallback);
402 command_rec mod_vhost_ldap_cmds[] = {
403 AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF,
404 "URL to define LDAP connection. This should be an RFC 2255 compliant\n"
405 "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n"
407 "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n"
408 "to specify redundant servers.\n"
409 "<li>Port is optional, and specifies the port to connect to.\n"
410 "<li>basedn specifies the base DN to start searches from\n"
413 AP_INIT_TAKE1 ("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF,
414 "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."),
416 AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF,
417 "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."),
419 AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF,
420 "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"),
422 AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF,
423 "Determines how aliases are handled during a search. Can be one of the"
424 "values \"never\", \"searching\", \"finding\", or \"always\". "
425 "Defaults to always."),
427 AP_INIT_TAKE1("VhostLDAPFallback", mod_vhost_ldap_set_fallback, NULL, RSRC_CONF,
428 "Set default virtual host which will be used when requested hostname"
429 "is not found in LDAP database. This option can be used to display"
430 "\"virtual host not found\" type of page."),
435 #define FILTER_LENGTH MAX_STRING_LEN
436 static int mod_vhost_ldap_translate_name(request_rec *r)
438 mod_vhost_ldap_request_t *reqc;
440 const char **vals = NULL;
441 char filtbuf[FILTER_LENGTH];
442 mod_vhost_ldap_config_t *conf =
443 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
444 core_server_config *core =
445 (core_server_config *)ap_get_module_config(r->server->module_config, &core_module);
446 util_ldap_connection_t *ldc = NULL;
448 const char *dn = NULL;
450 const char *hostname = NULL;
455 struct berval hostnamebv, shostnamebv;
459 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
460 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
462 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
464 // mod_vhost_ldap is disabled or we don't have LDAP Url
465 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
472 ldc = util_ldap_connection_find(r, conf->host, conf->port,
473 conf->binddn, conf->bindpw, conf->deref,
477 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
478 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
479 return HTTP_INTERNAL_SERVER_ERROR;
482 hostname = r->hostname;
483 if (hostname == NULL || hostname[0] == '\0')
488 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
489 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
492 ber_str2bv(hostname, 0, 0, &hostnamebv);
493 if (ldap_bv2escaped_filter_value(&hostnamebv, &shostnamebv) != 0)
495 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, shostnamebv.bv_val, shostnamebv.bv_val);
496 ber_memfree(shostnamebv.bv_val);
498 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
499 attributes, filtbuf, &dn, &vals);
501 util_ldap_connection_close(ldc);
503 /* sanity check - if server is down, retry it up to 5 times */
504 if (AP_LDAP_IS_SERVER_DOWN(result) ||
505 (result == LDAP_TIMEOUT) ||
506 (result == LDAP_CONNECT_ERROR)) {
507 sleep = sleep0 + sleep1;
508 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
509 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
511 if (failures++ < MAX_FAILURES) {
512 /* Back-off exponentially */
513 apr_sleep(apr_time_from_sec(sleep));
518 return HTTP_GATEWAY_TIME_OUT;
522 if (result == LDAP_NO_SUCH_OBJECT) {
523 if (strcmp(hostname, "*") != 0) {
524 if (strncmp(hostname, "*.", 2) == 0)
526 hostname += strcspn(hostname, ".");
527 hostname = apr_pstrcat(r->pool, "*", hostname, NULL);
528 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
529 "[mod_vhost_ldap.c] translate: "
530 "virtual host not found, trying wildcard %s",
536 if (conf->fallback && (is_fallback++ <= 0)) {
537 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
538 "[mod_vhost_ldap.c] translate: "
539 "virtual host %s not found, trying fallback %s",
540 hostname, conf->fallback);
541 hostname = conf->fallback;
545 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
546 "[mod_vhost_ldap.c] translate: "
547 "virtual host %s not found",
550 return HTTP_BAD_REQUEST;
553 /* handle bind failure */
554 if (result != LDAP_SUCCESS) {
555 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
556 "[mod_vhost_ldap.c] translate: "
557 "translate failed; virtual host %s; URI %s [%s]",
558 hostname, r->uri, ldap_err2string(result));
559 return HTTP_INTERNAL_SERVER_ERROR;
562 /* mark the user and DN */
563 reqc->dn = apr_pstrdup(r->pool, dn);
568 while (attributes[i]) {
570 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
571 reqc->name = apr_pstrdup (r->pool, vals[i]);
573 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
574 reqc->admin = apr_pstrdup (r->pool, vals[i]);
576 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
577 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
579 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
580 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
582 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
583 reqc->uid = apr_pstrdup(r->pool, vals[i]);
585 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
586 reqc->gid = apr_pstrdup(r->pool, vals[i]);
592 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
593 "[mod_vhost_ldap.c]: loaded from ldap: "
594 "apacheServerName: %s, "
595 "apacheServerAdmin: %s, "
596 "apacheDocumentRoot: %s, "
597 "apacheScriptAlias: %s, "
598 "apacheSuexecUid: %s, "
599 "apacheSuexecGid: %s",
600 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
602 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
603 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
604 "[mod_vhost_ldap.c] translate: "
605 "translate failed; ServerName or DocumentRoot not defined");
606 return HTTP_INTERNAL_SERVER_ERROR;
612 cgi = strstr(r->uri, "cgi-bin/");
613 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
618 /* Set exact filename for CGI script */
619 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
620 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
621 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
622 "[mod_vhost_ldap.c]: ap_document_root is: %s",
623 ap_document_root(r));
625 r->handler = "cgi-script";
626 apr_table_setn(r->notes, "alias-forced-type", r->handler);
629 } else if (strncmp(r->uri, "/~", 2) == 0) {
630 /* This is a quick, dirty hack. I should be shot for taking 6.170
631 * this term and being willing to write a quick, dirty hack. */
633 uid_t uid = (uid_t)atoll(reqc->uid);
634 if (apr_uid_name_get(&username, uid, r->pool) != APR_SUCCESS) {
635 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
636 "could not get username for uid %d", uid);
639 if (strncmp(r->uri + 2, username, strlen(username)) == 0 &&
640 (r->uri[2 + strlen(username)] == '/' ||
641 r->uri[2 + strlen(username)] == '\0')) {
643 if (apr_uid_homepath_get(&homedir, username, r->pool) != APR_SUCCESS) {
644 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
645 "could not get home directory for user %s", username);
648 r->filename = apr_pstrcat(r->pool, homedir, "/", USERDIR, r->uri + 2 + strlen(username), NULL);
651 } else if (r->uri[0] == '/') {
652 /* we don't set r->filename here, and let other modules do it
653 * this allows other modules (mod_rewrite.c) to work as usual
655 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
657 /* We don't handle non-file requests here */
661 if ((r->server = apr_pmemdup(r->pool, r->server, sizeof(*r->server))) == NULL) {
662 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
663 "[mod_vhost_ldap.c] translate: "
664 "translate failed; Unable to copy r->server structure");
665 return HTTP_INTERNAL_SERVER_ERROR;
668 r->server->server_hostname = reqc->name;
671 r->server->server_admin = reqc->admin;
674 if ((r->server->module_config = apr_pmemdup(r->pool, r->server->module_config,
676 (total_modules + DYNAMIC_MODULE_LIMIT))) == NULL) {
677 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
678 "[mod_vhost_ldap.c] translate: "
679 "translate failed; Unable to copy r->server->module_config structure");
680 return HTTP_INTERNAL_SERVER_ERROR;
683 if ((core = apr_pmemdup(r->pool, core, sizeof(*core))) == NULL) {
684 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
685 "[mod_vhost_ldap.c] translate: "
686 "translate failed; Unable to copy r->core structure");
687 return HTTP_INTERNAL_SERVER_ERROR;
689 ap_set_module_config(r->server->module_config, &core_module, core);
691 /* Stolen from server/core.c */
693 /* Make it absolute, relative to ServerRoot */
694 reqc->docroot = ap_server_root_relative(r->pool, reqc->docroot);
696 if (reqc->docroot == NULL) {
697 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
698 "[mod_vhost_ldap.c] set_document_root: DocumentRoot must be a directory");
700 return HTTP_INTERNAL_SERVER_ERROR;
703 /* TODO: ap_configtestonly && ap_docrootcheck && */
704 if (apr_filepath_merge((char**)&core->ap_document_root, NULL, reqc->docroot,
705 APR_FILEPATH_TRUENAME, r->pool) != APR_SUCCESS
706 || !ap_is_directory(r->pool, reqc->docroot)) {
708 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
709 "[mod_vhost_ldap.c] set_document_root: Warning: DocumentRoot [%s] does not exist",
711 core->ap_document_root = reqc->docroot;
714 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
718 #ifdef HAVE_UNIX_SUEXEC
719 static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
721 ap_unix_identity_t *ugid = NULL;
722 mod_vhost_ldap_config_t *conf =
723 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
725 mod_vhost_ldap_request_t *req =
726 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
732 // mod_vhost_ldap is disabled or we don't have LDAP Url
733 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
737 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
741 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
745 uid = (uid_t)atoll(req->uid);
746 gid = (gid_t)atoll(req->gid);
748 if ((uid < MIN_UID)||(gid < MIN_GID)) {
761 mod_vhost_ldap_register_hooks (apr_pool_t * p)
765 * Run before mod_rewrite
767 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
769 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
770 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
771 #ifdef HAVE_UNIX_SUEXEC
772 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
774 #if (APR_MAJOR_VERSION >= 1)
775 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
779 module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
780 STANDARD20_MODULE_STUFF,
783 mod_vhost_ldap_create_server_config,
784 mod_vhost_ldap_merge_server_config,
786 mod_vhost_ldap_register_hooks,