]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
Return OK when we set r->filename, to fix cgi-bin URLs.
[mod-vhost-ldap.git] / mod_vhost_ldap.c
CommitLineData
7f9875bb
OS
1/* ============================================================
2 * Copyright (c) 2003-2004, Ondrej Sury
3 * All rights reserved.
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 */
18
19/*
20 * mod_vhost_ldap.c --- read virtual host config from LDAP directory
21 */
22
9ee2dda1 23#define CORE_PRIVATE
9ee2dda1 24
7f9875bb
OS
25#include <unistd.h>
26
27#include "httpd.h"
28#include "http_config.h"
29#include "http_core.h"
30#include "http_log.h"
31#include "http_request.h"
8503d00b 32#include "apr_version.h"
7f9875bb 33#include "apr_ldap.h"
7f9875bb 34#include "apr_reslist.h"
7f5e70ed 35#include "apr_strings.h"
7f5e70ed 36#include "apr_tables.h"
7f9875bb 37#include "util_ldap.h"
7f5e70ed 38#include "util_script.h"
7f9875bb 39
3b8a47e0 40#if !defined(APU_HAS_LDAP) && !defined(APR_HAS_LDAP)
7f9875bb
OS
41#error mod_vhost_ldap requires APR-util to have LDAP support built in
42#endif
43
44#if !defined(WIN32) && !defined(OS2) && !defined(BEOS) && !defined(NETWARE)
45#define HAVE_UNIX_SUEXEC
46#endif
47
48#ifdef HAVE_UNIX_SUEXEC
49#include "unixd.h" /* Contains the suexec_identity hook used on Unix */
50#endif
51
d129bb81
OS
52#define MIN_UID 100
53#define MIN_GID 100
7f9875bb 54
5e2a6ff5
OS
55#define MAX_FAILURES 5
56
7f9875bb
OS
57module AP_MODULE_DECLARE_DATA vhost_ldap_module;
58
8196fae3
OS
59typedef enum {
60 MVL_UNSET, MVL_DISABLED, MVL_ENABLED
61} mod_vhost_ldap_status_e;
62
7f9875bb 63typedef struct mod_vhost_ldap_config_t {
8196fae3 64 mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */
7f9875bb
OS
65
66 /* These parameters are all derived from the VhostLDAPURL directive */
67 char *url; /* String representation of LDAP URL */
68
69 char *host; /* Name of the LDAP server (or space separated list) */
70 int port; /* Port of the LDAP server */
71 char *basedn; /* Base DN to do all searches from */
72 int scope; /* Scope of the search */
73 char *filter; /* Filter to further limit the search */
74 deref_options deref; /* how to handle alias dereferening */
75
76 char *binddn; /* DN to bind to server (can be NULL) */
77 char *bindpw; /* Password to bind to server (can be NULL) */
78
8196fae3 79 int have_deref; /* Set if we have found an Deref option */
7f9875bb
OS
80 int have_ldap_url; /* Set if we have found an LDAP url */
81
82 int secure; /* True if SSL connections are requested */
6056cddb
OS
83
84 char *fallback; /* Fallback virtual host */
85
7f9875bb
OS
86} mod_vhost_ldap_config_t;
87
88typedef struct mod_vhost_ldap_request_t {
89 char *dn; /* The saved dn from a successful search */
90 char *name; /* ServerName */
91 char *admin; /* ServerAdmin */
92 char *docroot; /* DocumentRoot */
9ee2dda1 93 char *cgiroot; /* ScriptAlias */
7f9875bb
OS
94 char *uid; /* Suexec Uid */
95 char *gid; /* Suexec Gid */
96} mod_vhost_ldap_request_t;
97
98char *attributes[] =
6f705808 99 { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 };
7f9875bb 100
b8f663f9
OS
101static int total_modules;
102
8503d00b 103#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
104static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
105static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
106static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
107static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
108static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
109static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
110static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
111
112static void ImportULDAPOptFn(void)
113{
114 util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
115 util_ldap_connection_find = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
116 util_ldap_cache_comparedn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
117 util_ldap_cache_compare = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
118 util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
119 util_ldap_cache_getuserdn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
120 util_ldap_ssl_supported = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
121}
122#endif
123
7f9875bb
OS
124static int mod_vhost_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
125{
b8f663f9
OS
126 module **m;
127
128 /* Stolen from modules/generators/mod_cgid.c */
129 total_modules = 0;
130 for (m = ap_preloaded_modules; *m != NULL; m++)
131 total_modules++;
132
7f9875bb
OS
133 /* make sure that mod_ldap (util_ldap) is loaded */
134 if (ap_find_linked_module("util_ldap.c") == NULL) {
135 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s,
136 "Module mod_ldap missing. Mod_ldap (aka. util_ldap) "
137 "must be loaded in order for mod_vhost_ldap to function properly");
138 return HTTP_INTERNAL_SERVER_ERROR;
139
140 }
141
9ee2dda1 142 ap_add_version_component(p, MOD_VHOST_LDAP_VERSION);
7f9875bb
OS
143
144 return OK;
145}
146
147static void *
148mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s)
149{
8196fae3 150 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
151 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof (mod_vhost_ldap_config_t));
152
8196fae3
OS
153 conf->enabled = MVL_UNSET;
154 conf->have_ldap_url = 0;
155 conf->have_deref = 0;
156 conf->binddn = NULL;
157 conf->bindpw = NULL;
158 conf->deref = always;
6056cddb 159 conf->fallback = NULL;
8196fae3
OS
160
161 return conf;
162}
163
164static void *
165mod_vhost_ldap_merge_server_config(apr_pool_t *p, void *parentv, void *childv)
166{
167 mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv;
168 mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv;
169 mod_vhost_ldap_config_t *conf =
170 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t));
7f9875bb 171
8196fae3
OS
172 if (child->enabled == MVL_UNSET) {
173 conf->enabled = parent->enabled;
174 } else {
175 conf->enabled = child->enabled;
176 }
7f9875bb 177
8196fae3
OS
178 if (child->have_ldap_url) {
179 conf->have_ldap_url = child->have_ldap_url;
180 conf->url = child->url;
181 conf->host = child->host;
182 conf->port = child->port;
183 conf->basedn = child->basedn;
184 conf->scope = child->scope;
185 conf->filter = child->filter;
186 conf->secure = child->secure;
187 } else {
188 conf->have_ldap_url = parent->have_ldap_url;
189 conf->url = parent->url;
190 conf->host = parent->host;
191 conf->port = parent->port;
192 conf->basedn = parent->basedn;
193 conf->scope = parent->scope;
194 conf->filter = parent->filter;
195 conf->secure = parent->secure;
196 }
197 if (child->have_deref) {
198 conf->have_deref = child->have_deref;
199 conf->deref = child->deref;
200 } else {
201 conf->have_deref = parent->have_deref;
202 conf->deref = parent->deref;
203 }
204
205 conf->binddn = (child->binddn ? child->binddn : parent->binddn);
206 conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw);
207
6056cddb
OS
208 conf->fallback = (child->fallback ? child->fallback : parent->fallback);
209
8196fae3 210 return conf;
7f9875bb
OS
211}
212
213/*
214 * Use the ldap url parsing routines to break up the ldap url into
215 * host and port.
216 */
217static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd,
218 void *dummy,
219 const char *url)
220{
221 int result;
222 apr_ldap_url_desc_t *urld;
8503d00b 223#if (APR_MAJOR_VERSION >= 1)
3b8a47e0 224 apr_ldap_err_t *result_err;
8503d00b 225#endif
7f9875bb 226
8196fae3 227 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
228 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
229 &vhost_ldap_module);
230
231 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
232 cmd->server, "[mod_vhost_ldap.c] url parse: `%s'",
233 url);
8503d00b
OS
234
235#if (APR_MAJOR_VERSION >= 1) /* for apache >= 2.2 */
3b8a47e0
OS
236 result = apr_ldap_url_parse(cmd->pool, url, &(urld), &(result_err));
237 if (result != LDAP_SUCCESS) {
238 return result_err->reason;
239 }
240#else
7f9875bb
OS
241 result = apr_ldap_url_parse(url, &(urld));
242 if (result != LDAP_SUCCESS) {
243 switch (result) {
3b8a47e0
OS
244 case LDAP_URL_ERR_NOTLDAP:
245 return "LDAP URL does not begin with ldap://";
246 case LDAP_URL_ERR_NODN:
247 return "LDAP URL does not have a DN";
248 case LDAP_URL_ERR_BADSCOPE:
249 return "LDAP URL has an invalid scope";
250 case LDAP_URL_ERR_MEM:
251 return "Out of memory parsing LDAP URL";
252 default:
253 return "Could not parse LDAP URL";
7f9875bb
OS
254 }
255 }
3b8a47e0 256#endif
8196fae3 257 conf->url = apr_pstrdup(cmd->pool, url);
7f9875bb
OS
258
259 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
260 cmd->server, "[mod_vhost_ldap.c] url parse: Host: %s", urld->lud_host);
261 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
262 cmd->server, "[mod_vhost_ldap.c] url parse: Port: %d", urld->lud_port);
263 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
264 cmd->server, "[mod_vhost_ldap.c] url parse: DN: %s", urld->lud_dn);
265 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
266 cmd->server, "[mod_vhost_ldap.c] url parse: attrib: %s", urld->lud_attrs? urld->lud_attrs[0] : "(null)");
267 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
268 cmd->server, "[mod_vhost_ldap.c] url parse: scope: %s",
269 (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" :
270 urld->lud_scope == LDAP_SCOPE_BASE? "base" :
271 urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"));
272 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
273 cmd->server, "[mod_vhost_ldap.c] url parse: filter: %s", urld->lud_filter);
274
275 /* Set all the values, or at least some sane defaults */
8196fae3
OS
276 if (conf->host) {
277 char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2);
7f9875bb
OS
278 strcpy(p, urld->lud_host);
279 strcat(p, " ");
8196fae3
OS
280 strcat(p, conf->host);
281 conf->host = p;
7f9875bb
OS
282 }
283 else {
8196fae3 284 conf->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
7f9875bb 285 }
8196fae3 286 conf->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
7f9875bb 287
8196fae3 288 conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ?
7f9875bb
OS
289 LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE;
290
291 if (urld->lud_filter) {
292 if (urld->lud_filter[0] == '(') {
293 /*
294 * Get rid of the surrounding parens; later on when generating the
295 * filter, they'll be put back.
296 */
8196fae3
OS
297 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1);
298 conf->filter[strlen(conf->filter)-1] = '\0';
7f9875bb
OS
299 }
300 else {
8196fae3 301 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
7f9875bb
OS
302 }
303 }
304 else {
8196fae3 305 conf->filter = "objectClass=apacheConfig";
7f9875bb
OS
306 }
307
308 /* "ldaps" indicates secure ldap connections desired
309 */
310 if (strncasecmp(url, "ldaps", 5) == 0)
311 {
8196fae3
OS
312 conf->secure = 1;
313 conf->port = urld->lud_port? urld->lud_port : LDAPS_PORT;
7f9875bb
OS
314 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
315 "LDAP: vhost_ldap using SSL connections");
316 }
317 else
318 {
8196fae3
OS
319 conf->secure = 0;
320 conf->port = urld->lud_port? urld->lud_port : LDAP_PORT;
fb323462 321 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
7f9875bb
OS
322 "LDAP: vhost_ldap not using SSL connections");
323 }
324
8196fae3 325 conf->have_ldap_url = 1;
8503d00b 326#if (APR_MAJOR_VERSION < 1) /* free only required for older apr */
7f9875bb 327 apr_ldap_free_urldesc(urld);
3b8a47e0 328#endif
7f9875bb
OS
329 return NULL;
330}
331
332static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int enabled)
333{
8196fae3 334 mod_vhost_ldap_config_t *conf =
7f9875bb 335 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
6056cddb 336 &vhost_ldap_module);
7f9875bb 337
8196fae3
OS
338 conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED;
339
7f9875bb
OS
340 return NULL;
341}
342
343static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const char *binddn)
344{
8196fae3 345 mod_vhost_ldap_config_t *conf =
7f9875bb 346 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
6056cddb 347 &vhost_ldap_module);
7f9875bb 348
8196fae3 349 conf->binddn = apr_pstrdup(cmd->pool, binddn);
7f9875bb
OS
350 return NULL;
351}
352
353static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const char *bindpw)
354{
8196fae3 355 mod_vhost_ldap_config_t *conf =
7f9875bb 356 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
6056cddb 357 &vhost_ldap_module);
7f9875bb 358
8196fae3 359 conf->bindpw = apr_pstrdup(cmd->pool, bindpw);
7f9875bb
OS
360 return NULL;
361}
362
363static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const char *deref)
364{
8196fae3 365 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
366 (mod_vhost_ldap_config_t *)ap_get_module_config (cmd->server->module_config,
367 &vhost_ldap_module);
368
369 if (strcmp(deref, "never") == 0 || strcasecmp(deref, "off") == 0) {
8196fae3
OS
370 conf->deref = never;
371 conf->have_deref = 1;
7f9875bb
OS
372 }
373 else if (strcmp(deref, "searching") == 0) {
8196fae3
OS
374 conf->deref = searching;
375 conf->have_deref = 1;
7f9875bb
OS
376 }
377 else if (strcmp(deref, "finding") == 0) {
8196fae3
OS
378 conf->deref = finding;
379 conf->have_deref = 1;
7f9875bb
OS
380 }
381 else if (strcmp(deref, "always") == 0 || strcasecmp(deref, "on") == 0) {
8196fae3
OS
382 conf->deref = always;
383 conf->have_deref = 1;
7f9875bb
OS
384 }
385 else {
386 return "Unrecognized value for VhostLDAPAliasDereference directive";
387 }
388 return NULL;
389}
390
6056cddb
OS
391static const char *mod_vhost_ldap_set_fallback(cmd_parms *cmd, void *dummy, const char *fallback)
392{
393 mod_vhost_ldap_config_t *conf =
394 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
395 &vhost_ldap_module);
396
397 conf->fallback = apr_pstrdup(cmd->pool, fallback);
398 return NULL;
399}
400
7f9875bb
OS
401command_rec mod_vhost_ldap_cmds[] = {
402 AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF,
a940f969 403 "URL to define LDAP connection. This should be an RFC 2255 compliant\n"
7f9875bb
OS
404 "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n"
405 "<ul>\n"
406 "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n"
407 "to specify redundant servers.\n"
408 "<li>Port is optional, and specifies the port to connect to.\n"
409 "<li>basedn specifies the base DN to start searches from\n"
410 "</ul>\n"),
411
412 AP_INIT_TAKE1 ("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF,
413 "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."),
414
415 AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF,
416 "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."),
417
418 AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF,
419 "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"),
420
421 AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF,
a940f969 422 "Determines how aliases are handled during a search. Can be one of the"
7f9875bb
OS
423 "values \"never\", \"searching\", \"finding\", or \"always\". "
424 "Defaults to always."),
425
6056cddb
OS
426 AP_INIT_TAKE1("VhostLDAPFallback", mod_vhost_ldap_set_fallback, NULL, RSRC_CONF,
427 "Set default virtual host which will be used when requested hostname"
428 "is not found in LDAP database. This option can be used to display"
429 "\"virtual host not found\" type of page."),
430
7f9875bb
OS
431 {NULL}
432};
433
434#define FILTER_LENGTH MAX_STRING_LEN
b5043ccb 435static int mod_vhost_ldap_translate_name(request_rec *r)
7f9875bb 436{
b5043ccb 437 mod_vhost_ldap_request_t *reqc;
7f9875bb
OS
438 int failures = 0;
439 const char **vals = NULL;
440 char filtbuf[FILTER_LENGTH];
8196fae3 441 mod_vhost_ldap_config_t *conf =
7f9875bb 442 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
b8f663f9
OS
443 core_server_config *core =
444 (core_server_config *)ap_get_module_config(r->server->module_config, &core_module);
7f9875bb
OS
445 util_ldap_connection_t *ldc = NULL;
446 int result = 0;
447 const char *dn = NULL;
dc514643 448 char *cgi;
6056cddb
OS
449 const char *hostname = NULL;
450 int is_fallback = 0;
4d9859cb
OS
451 int sleep0 = 0;
452 int sleep1 = 1;
453 int sleep;
303e7b48 454 struct berval hostnamebv, shostnamebv;
e56e6d60 455 int ret = DECLINED;
7f9875bb 456
b5043ccb 457 reqc =
7f9875bb 458 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
8503d00b 459 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
b5043ccb
OS
460
461 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
7f9875bb 462
8196fae3
OS
463 // mod_vhost_ldap is disabled or we don't have LDAP Url
464 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
465 return DECLINED;
466 }
467
468start_over:
469
8196fae3
OS
470 if (conf->host) {
471 ldc = util_ldap_connection_find(r, conf->host, conf->port,
472 conf->binddn, conf->bindpw, conf->deref,
473 conf->secure);
7f9875bb
OS
474 }
475 else {
476 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
fb323462 477 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
4cd7ff10 478 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
479 }
480
6056cddb 481 hostname = r->hostname;
303e7b48
OS
482 if (hostname == NULL || hostname[0] == '\0')
483 goto null;
6056cddb
OS
484
485fallback:
486
fb323462 487 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
488 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
489 hostname, r->uri);
7f9875bb 490
303e7b48
OS
491 ber_str2bv(hostname, 0, 0, &hostnamebv);
492 if (ldap_bv2escaped_filter_value(&hostnamebv, &shostnamebv) != 0)
493 goto null;
494 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, shostnamebv.bv_val, shostnamebv.bv_val);
495 ber_memfree(shostnamebv.bv_val);
7f9875bb 496
8196fae3 497 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
7f9875bb
OS
498 attributes, filtbuf, &dn, &vals);
499
500 util_ldap_connection_close(ldc);
501
502 /* sanity check - if server is down, retry it up to 5 times */
9122cbd6
OS
503 if (AP_LDAP_IS_SERVER_DOWN(result) ||
504 (result == LDAP_TIMEOUT) ||
505 (result == LDAP_CONNECT_ERROR)) {
4d9859cb 506 sleep = sleep0 + sleep1;
e78531ef 507 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
508 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
509 failures, sleep);
5e2a6ff5 510 if (failures++ < MAX_FAILURES) {
9122cbd6
OS
511 /* Back-off exponentially */
512 apr_sleep(apr_time_from_sec(sleep));
4d9859cb
OS
513 sleep0 = sleep1;
514 sleep1 = sleep;
7f9875bb 515 goto start_over;
4cd7ff10
OS
516 } else {
517 return HTTP_GATEWAY_TIME_OUT;
518 }
7f9875bb
OS
519 }
520
4cd7ff10 521 if (result == LDAP_NO_SUCH_OBJECT) {
a529b3b4
OS
522 if (strcmp(hostname, "*") != 0) {
523 if (strncmp(hostname, "*.", 2) == 0)
524 hostname += 2;
525 hostname += strcspn(hostname, ".");
526 hostname = apr_pstrcat(r->pool, "*", hostname, NULL);
527 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
528 "[mod_vhost_ldap.c] translate: "
529 "virtual host not found, trying wildcard %s",
530 hostname);
531 goto fallback;
532 }
533
303e7b48 534null:
6056cddb
OS
535 if (conf->fallback && (is_fallback++ <= 0)) {
536 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
537 "[mod_vhost_ldap.c] translate: "
538 "virtual host %s not found, trying fallback %s",
539 hostname, conf->fallback);
540 hostname = conf->fallback;
541 goto fallback;
542 }
543
544 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
545 "[mod_vhost_ldap.c] translate: "
546 "virtual host %s not found",
547 hostname);
548
4cd7ff10 549 return HTTP_BAD_REQUEST;
6056cddb
OS
550 }
551
7f9875bb
OS
552 /* handle bind failure */
553 if (result != LDAP_SUCCESS) {
cbd5c5f5 554 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f9875bb 555 "[mod_vhost_ldap.c] translate: "
6056cddb
OS
556 "translate failed; virtual host %s; URI %s [%s]",
557 hostname, r->uri, ldap_err2string(result));
4cd7ff10 558 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
559 }
560
561 /* mark the user and DN */
b5043ccb 562 reqc->dn = apr_pstrdup(r->pool, dn);
7f9875bb
OS
563
564 /* Optimize */
565 if (vals) {
566 int i = 0;
567 while (attributes[i]) {
568
569 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
b5043ccb 570 reqc->name = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
571 }
572 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
b5043ccb 573 reqc->admin = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
574 }
575 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
b5043ccb 576 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
577 }
578 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
b5043ccb 579 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
580 }
581 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
b5043ccb 582 reqc->uid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
583 }
584 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
b5043ccb 585 reqc->gid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
586 }
587 i++;
588 }
589 }
590
6f705808
OS
591 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
592 "[mod_vhost_ldap.c]: loaded from ldap: "
593 "apacheServerName: %s, "
594 "apacheServerAdmin: %s, "
595 "apacheDocumentRoot: %s, "
596 "apacheScriptAlias: %s, "
597 "apacheSuexecUid: %s, "
b5043ccb
OS
598 "apacheSuexecGid: %s",
599 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
6f705808 600
b5043ccb 601 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
7f9875bb
OS
602 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
603 "[mod_vhost_ldap.c] translate: "
649a08e8 604 "translate failed; ServerName or DocumentRoot not defined");
4cd7ff10 605 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
606 }
607
608 cgi = NULL;
b8f663f9 609
b5043ccb 610 if (reqc->cgiroot) {
6f705808
OS
611 cgi = strstr(r->uri, "cgi-bin/");
612 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
7f9875bb
OS
613 cgi = NULL;
614 }
9ee2dda1 615 }
9ee2dda1 616 if (cgi) {
9122cbd6 617 /* Set exact filename for CGI script */
dc514643 618 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
e6d4a687
OS
619 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
620 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
621 "[mod_vhost_ldap.c]: ap_document_root is: %s",
622 ap_document_root(r));
e6d4a687
OS
623 r->filename = cgi;
624 r->handler = "cgi-script";
625 apr_table_setn(r->notes, "alias-forced-type", r->handler);
e56e6d60 626 ret = OK;
e6d4a687 627 }
4cd7ff10 628 } else if (r->uri[0] == '/') {
9122cbd6
OS
629 /* we don't set r->filename here, and let other modules do it
630 * this allows other modules (mod_rewrite.c) to work as usual
631 */
632 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
4cd7ff10 633 } else {
9122cbd6 634 /* We don't handle non-file requests here */
4cd7ff10 635 return DECLINED;
7f9875bb
OS
636 }
637
b8f663f9
OS
638 if ((r->server = apr_pmemdup(r->pool, r->server, sizeof(*r->server))) == NULL) {
639 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
640 "[mod_vhost_ldap.c] translate: "
641 "translate failed; Unable to copy r->server structure");
642 return HTTP_INTERNAL_SERVER_ERROR;
643 }
644
645 r->server->server_hostname = reqc->name;
7f9875bb 646
b5043ccb 647 if (reqc->admin) {
b8f663f9 648 r->server->server_admin = reqc->admin;
7f9875bb
OS
649 }
650
b8f663f9
OS
651 if ((r->server->module_config = apr_pmemdup(r->pool, r->server->module_config,
652 sizeof(void *) *
653 (total_modules + DYNAMIC_MODULE_LIMIT))) == NULL) {
654 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
655 "[mod_vhost_ldap.c] translate: "
656 "translate failed; Unable to copy r->server->module_config structure");
657 return HTTP_INTERNAL_SERVER_ERROR;
658 }
659
660 if ((core = apr_pmemdup(r->pool, core, sizeof(*core))) == NULL) {
661 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
662 "[mod_vhost_ldap.c] translate: "
663 "translate failed; Unable to copy r->core structure");
100c0189 664 return HTTP_INTERNAL_SERVER_ERROR;
9122cbd6 665 }
b8f663f9
OS
666 ap_set_module_config(r->server->module_config, &core_module, core);
667
668 /* Stolen from server/core.c */
669
670 /* Make it absolute, relative to ServerRoot */
671 reqc->docroot = ap_server_root_relative(r->pool, reqc->docroot);
672
673 if (reqc->docroot == NULL) {
674 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
675 "[mod_vhost_ldap.c] set_document_root: DocumentRoot must be a directory");
676
677 return HTTP_INTERNAL_SERVER_ERROR;
678 }
679
680 /* TODO: ap_configtestonly && ap_docrootcheck && */
681 if (apr_filepath_merge((char**)&core->ap_document_root, NULL, reqc->docroot,
682 APR_FILEPATH_TRUENAME, r->pool) != APR_SUCCESS
683 || !ap_is_directory(r->pool, reqc->docroot)) {
684
685 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
686 "[mod_vhost_ldap.c] set_document_root: Warning: DocumentRoot [%s] does not exist",
687 reqc->docroot);
688 core->ap_document_root = reqc->docroot;
689 }
7f9875bb 690
aad41a70 691 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
e56e6d60 692 return ret;
aad41a70
OS
693}
694
7f9875bb
OS
695#ifdef HAVE_UNIX_SUEXEC
696static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
697{
698 ap_unix_identity_t *ugid = NULL;
8196fae3 699 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
700 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
701 &vhost_ldap_module);
702 mod_vhost_ldap_request_t *req =
703 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
704 &vhost_ldap_module);
705
706 uid_t uid = -1;
707 gid_t gid = -1;
708
8196fae3
OS
709 // mod_vhost_ldap is disabled or we don't have LDAP Url
710 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
711 return NULL;
712 }
713
714 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
715 return NULL;
716 }
717
718 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
719 return NULL;
720 }
721
722 uid = (uid_t)atoll(req->uid);
723 gid = (gid_t)atoll(req->gid);
724
eea38f6d 725 if ((uid < MIN_UID)||(gid < MIN_GID)) {
7f9875bb
OS
726 return NULL;
727 }
728
729 ugid->uid = uid;
730 ugid->gid = gid;
731 ugid->userdir = 0;
732
733 return ugid;
734}
735#endif
736
737static void
738mod_vhost_ldap_register_hooks (apr_pool_t * p)
739{
aad41a70
OS
740
741 /*
742 * Run before mod_rewrite
743 */
744 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
745
7f9875bb 746 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
aad41a70 747 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
7f9875bb
OS
748#ifdef HAVE_UNIX_SUEXEC
749 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
750#endif
8503d00b 751#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
752 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
753#endif
7f9875bb
OS
754}
755
756module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
757 STANDARD20_MODULE_STUFF,
758 NULL,
759 NULL,
760 mod_vhost_ldap_create_server_config,
8196fae3 761 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
762 mod_vhost_ldap_cmds,
763 mod_vhost_ldap_register_hooks,
764};
This page took 0.357961 seconds and 5 git commands to generate.