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