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