]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
Tag version 2.0.5
[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;
7f9875bb 455
b5043ccb 456 reqc =
7f9875bb 457 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
8503d00b 458 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
b5043ccb
OS
459
460 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
7f9875bb 461
8196fae3
OS
462 // mod_vhost_ldap is disabled or we don't have LDAP Url
463 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
464 return DECLINED;
465 }
466
467start_over:
468
8196fae3
OS
469 if (conf->host) {
470 ldc = util_ldap_connection_find(r, conf->host, conf->port,
471 conf->binddn, conf->bindpw, conf->deref,
472 conf->secure);
7f9875bb
OS
473 }
474 else {
475 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
fb323462 476 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
4cd7ff10 477 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
478 }
479
6056cddb 480 hostname = r->hostname;
303e7b48
OS
481 if (hostname == NULL || hostname[0] == '\0')
482 goto null;
6056cddb
OS
483
484fallback:
485
fb323462 486 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
487 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
488 hostname, r->uri);
7f9875bb 489
303e7b48
OS
490 ber_str2bv(hostname, 0, 0, &hostnamebv);
491 if (ldap_bv2escaped_filter_value(&hostnamebv, &shostnamebv) != 0)
492 goto null;
493 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, shostnamebv.bv_val, shostnamebv.bv_val);
494 ber_memfree(shostnamebv.bv_val);
7f9875bb 495
8196fae3 496 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
7f9875bb
OS
497 attributes, filtbuf, &dn, &vals);
498
499 util_ldap_connection_close(ldc);
500
501 /* sanity check - if server is down, retry it up to 5 times */
9122cbd6
OS
502 if (AP_LDAP_IS_SERVER_DOWN(result) ||
503 (result == LDAP_TIMEOUT) ||
504 (result == LDAP_CONNECT_ERROR)) {
4d9859cb 505 sleep = sleep0 + sleep1;
e78531ef 506 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
507 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
508 failures, sleep);
5e2a6ff5 509 if (failures++ < MAX_FAILURES) {
9122cbd6
OS
510 /* Back-off exponentially */
511 apr_sleep(apr_time_from_sec(sleep));
4d9859cb
OS
512 sleep0 = sleep1;
513 sleep1 = sleep;
7f9875bb 514 goto start_over;
4cd7ff10
OS
515 } else {
516 return HTTP_GATEWAY_TIME_OUT;
517 }
7f9875bb
OS
518 }
519
4cd7ff10 520 if (result == LDAP_NO_SUCH_OBJECT) {
a529b3b4
OS
521 if (strcmp(hostname, "*") != 0) {
522 if (strncmp(hostname, "*.", 2) == 0)
523 hostname += 2;
524 hostname += strcspn(hostname, ".");
525 hostname = apr_pstrcat(r->pool, "*", hostname, NULL);
526 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
527 "[mod_vhost_ldap.c] translate: "
528 "virtual host not found, trying wildcard %s",
529 hostname);
530 goto fallback;
531 }
532
303e7b48 533null:
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: "
649a08e8 603 "translate failed; ServerName or DocumentRoot not defined");
4cd7ff10 604 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
605 }
606
607 cgi = NULL;
b8f663f9 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,
7f5e70ed
OS
620 "[mod_vhost_ldap.c]: ap_document_root is: %s",
621 ap_document_root(r));
e6d4a687
OS
622 r->filename = cgi;
623 r->handler = "cgi-script";
624 apr_table_setn(r->notes, "alias-forced-type", r->handler);
625 }
4cd7ff10 626 } else if (r->uri[0] == '/') {
9122cbd6
OS
627 /* we don't set r->filename here, and let other modules do it
628 * this allows other modules (mod_rewrite.c) to work as usual
629 */
630 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
4cd7ff10 631 } else {
9122cbd6 632 /* We don't handle non-file requests here */
4cd7ff10 633 return DECLINED;
7f9875bb
OS
634 }
635
b8f663f9
OS
636 if ((r->server = apr_pmemdup(r->pool, r->server, sizeof(*r->server))) == NULL) {
637 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
638 "[mod_vhost_ldap.c] translate: "
639 "translate failed; Unable to copy r->server structure");
640 return HTTP_INTERNAL_SERVER_ERROR;
641 }
642
643 r->server->server_hostname = reqc->name;
7f9875bb 644
b5043ccb 645 if (reqc->admin) {
b8f663f9 646 r->server->server_admin = reqc->admin;
7f9875bb
OS
647 }
648
b8f663f9
OS
649 if ((r->server->module_config = apr_pmemdup(r->pool, r->server->module_config,
650 sizeof(void *) *
651 (total_modules + DYNAMIC_MODULE_LIMIT))) == NULL) {
652 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
653 "[mod_vhost_ldap.c] translate: "
654 "translate failed; Unable to copy r->server->module_config structure");
655 return HTTP_INTERNAL_SERVER_ERROR;
656 }
657
658 if ((core = apr_pmemdup(r->pool, core, sizeof(*core))) == NULL) {
659 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
660 "[mod_vhost_ldap.c] translate: "
661 "translate failed; Unable to copy r->core structure");
100c0189 662 return HTTP_INTERNAL_SERVER_ERROR;
9122cbd6 663 }
b8f663f9
OS
664 ap_set_module_config(r->server->module_config, &core_module, core);
665
666 /* Stolen from server/core.c */
667
668 /* Make it absolute, relative to ServerRoot */
669 reqc->docroot = ap_server_root_relative(r->pool, reqc->docroot);
670
671 if (reqc->docroot == NULL) {
672 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
673 "[mod_vhost_ldap.c] set_document_root: DocumentRoot must be a directory");
674
675 return HTTP_INTERNAL_SERVER_ERROR;
676 }
677
678 /* TODO: ap_configtestonly && ap_docrootcheck && */
679 if (apr_filepath_merge((char**)&core->ap_document_root, NULL, reqc->docroot,
680 APR_FILEPATH_TRUENAME, r->pool) != APR_SUCCESS
681 || !ap_is_directory(r->pool, reqc->docroot)) {
682
683 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
684 "[mod_vhost_ldap.c] set_document_root: Warning: DocumentRoot [%s] does not exist",
685 reqc->docroot);
686 core->ap_document_root = reqc->docroot;
687 }
7f9875bb 688
aad41a70
OS
689 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
690 return DECLINED;
691}
692
7f9875bb
OS
693#ifdef HAVE_UNIX_SUEXEC
694static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
695{
696 ap_unix_identity_t *ugid = NULL;
8196fae3 697 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
698 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
699 &vhost_ldap_module);
700 mod_vhost_ldap_request_t *req =
701 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
702 &vhost_ldap_module);
703
704 uid_t uid = -1;
705 gid_t gid = -1;
706
8196fae3
OS
707 // mod_vhost_ldap is disabled or we don't have LDAP Url
708 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
709 return NULL;
710 }
711
712 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
713 return NULL;
714 }
715
716 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
717 return NULL;
718 }
719
720 uid = (uid_t)atoll(req->uid);
721 gid = (gid_t)atoll(req->gid);
722
eea38f6d 723 if ((uid < MIN_UID)||(gid < MIN_GID)) {
7f9875bb
OS
724 return NULL;
725 }
726
727 ugid->uid = uid;
728 ugid->gid = gid;
729 ugid->userdir = 0;
730
731 return ugid;
732}
733#endif
734
735static void
736mod_vhost_ldap_register_hooks (apr_pool_t * p)
737{
aad41a70
OS
738
739 /*
740 * Run before mod_rewrite
741 */
742 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
743
7f9875bb 744 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
aad41a70 745 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
7f9875bb
OS
746#ifdef HAVE_UNIX_SUEXEC
747 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
748#endif
8503d00b 749#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
750 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
751#endif
7f9875bb
OS
752}
753
754module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
755 STANDARD20_MODULE_STUFF,
756 NULL,
757 NULL,
758 mod_vhost_ldap_create_server_config,
8196fae3 759 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
760 mod_vhost_ldap_cmds,
761 mod_vhost_ldap_register_hooks,
762};
This page took 0.166362 seconds and 5 git commands to generate.