]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
Add more debug info on what we are translating
[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;
9122cbd6 471 int sleep = 1;
7f9875bb 472
b5043ccb 473 reqc =
7f9875bb 474 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
8503d00b 475 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
b5043ccb
OS
476
477 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
7f9875bb 478
8196fae3
OS
479 // mod_vhost_ldap is disabled or we don't have LDAP Url
480 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
481 return DECLINED;
482 }
483
484start_over:
485
8196fae3
OS
486 if (conf->host) {
487 ldc = util_ldap_connection_find(r, conf->host, conf->port,
488 conf->binddn, conf->bindpw, conf->deref,
489 conf->secure);
7f9875bb
OS
490 }
491 else {
492 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
fb323462 493 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
4cd7ff10 494 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
495 }
496
6056cddb
OS
497 hostname = r->hostname;
498
499fallback:
500
fb323462 501 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
c606ab44 502 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]", hostname, r->uri);
7f9875bb 503
6056cddb 504 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, hostname, hostname);
7f9875bb 505
8196fae3 506 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
7f9875bb
OS
507 attributes, filtbuf, &dn, &vals);
508
509 util_ldap_connection_close(ldc);
510
511 /* sanity check - if server is down, retry it up to 5 times */
9122cbd6
OS
512 if (AP_LDAP_IS_SERVER_DOWN(result) ||
513 (result == LDAP_TIMEOUT) ||
514 (result == LDAP_CONNECT_ERROR)) {
7f9875bb 515 if (failures++ <= 5) {
9122cbd6
OS
516 /* Back-off exponentially */
517 apr_sleep(apr_time_from_sec(sleep));
518 sleep = sleep*2;
7f9875bb 519 goto start_over;
4cd7ff10
OS
520 } else {
521 return HTTP_GATEWAY_TIME_OUT;
522 }
7f9875bb
OS
523 }
524
4cd7ff10 525 if (result == LDAP_NO_SUCH_OBJECT) {
6056cddb
OS
526 if (conf->fallback && (is_fallback++ <= 0)) {
527 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
528 "[mod_vhost_ldap.c] translate: "
529 "virtual host %s not found, trying fallback %s",
530 hostname, conf->fallback);
531 hostname = conf->fallback;
532 goto fallback;
533 }
534
535 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
536 "[mod_vhost_ldap.c] translate: "
537 "virtual host %s not found",
538 hostname);
539
4cd7ff10 540 return HTTP_BAD_REQUEST;
6056cddb
OS
541 }
542
7f9875bb
OS
543 /* handle bind failure */
544 if (result != LDAP_SUCCESS) {
cbd5c5f5 545 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f9875bb 546 "[mod_vhost_ldap.c] translate: "
6056cddb
OS
547 "translate failed; virtual host %s; URI %s [%s]",
548 hostname, r->uri, ldap_err2string(result));
4cd7ff10 549 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
550 }
551
552 /* mark the user and DN */
b5043ccb 553 reqc->dn = apr_pstrdup(r->pool, dn);
7f9875bb
OS
554
555 /* Optimize */
556 if (vals) {
557 int i = 0;
558 while (attributes[i]) {
559
560 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
b5043ccb 561 reqc->name = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
562 }
563 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
b5043ccb 564 reqc->admin = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
565 }
566 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
b5043ccb 567 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
568 }
569 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
b5043ccb 570 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
571 }
572 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
b5043ccb 573 reqc->uid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
574 }
575 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
b5043ccb 576 reqc->gid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
577 }
578 i++;
579 }
580 }
581
6f705808
OS
582 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
583 "[mod_vhost_ldap.c]: loaded from ldap: "
584 "apacheServerName: %s, "
585 "apacheServerAdmin: %s, "
586 "apacheDocumentRoot: %s, "
587 "apacheScriptAlias: %s, "
588 "apacheSuexecUid: %s, "
b5043ccb
OS
589 "apacheSuexecGid: %s",
590 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
6f705808 591
b5043ccb 592 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
7f9875bb
OS
593 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
594 "[mod_vhost_ldap.c] translate: "
595 "translate failed; ServerName or DocumentRoot not defined");
4cd7ff10 596 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
597 }
598
599 cgi = NULL;
600
b5043ccb 601 if (reqc->cgiroot) {
6f705808
OS
602 cgi = strstr(r->uri, "cgi-bin/");
603 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
7f9875bb
OS
604 cgi = NULL;
605 }
9ee2dda1 606 }
9ee2dda1 607 if (cgi) {
9122cbd6 608 /* Set exact filename for CGI script */
dc514643 609 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
e6d4a687
OS
610 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
611 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
612 "[mod_vhost_ldap.c]: ap_document_root is: %s", ap_document_root(r));
613 r->filename = cgi;
614 r->handler = "cgi-script";
615 apr_table_setn(r->notes, "alias-forced-type", r->handler);
616 }
4cd7ff10 617 } else if (r->uri[0] == '/') {
9122cbd6
OS
618 /* we don't set r->filename here, and let other modules do it
619 * this allows other modules (mod_rewrite.c) to work as usual
620 */
621 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
4cd7ff10 622 } else {
9122cbd6 623 /* We don't handle non-file requests here */
4cd7ff10 624 return DECLINED;
7f9875bb
OS
625 }
626
19d58500 627 top->server->server_hostname = apr_pstrdup (top->pool, reqc->name);
7f9875bb 628
b5043ccb 629 if (reqc->admin) {
19d58500 630 top->server->server_admin = apr_pstrdup (top->pool, reqc->admin);
7f9875bb
OS
631 }
632
aad41a70
OS
633 reqc->saved_docroot = apr_pstrdup(top->pool, ap_document_root(r));
634
9122cbd6
OS
635 result = set_document_root(r, reqc->docroot);
636 if (result != OK) {
100c0189 637 return HTTP_INTERNAL_SERVER_ERROR;
9122cbd6 638 }
7f9875bb 639
4cd7ff10
OS
640 // set environment variables
641 e = top->subprocess_env;
dc514643 642 apr_table_addn(e, "DOCUMENT_ROOT", reqc->docroot);
aad41a70
OS
643
644 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
645 return DECLINED;
646}
647
648static int mod_vhost_ldap_cleanup(request_rec * r)
649{
aad41a70
OS
650 mod_vhost_ldap_request_t *reqc =
651 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
652 &vhost_ldap_module);
653
9122cbd6
OS
654 /* Set ap_document_root back to saved value */
655 return set_document_root(r, reqc->saved_docroot);
7f9875bb
OS
656}
657
658#ifdef HAVE_UNIX_SUEXEC
659static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
660{
661 ap_unix_identity_t *ugid = NULL;
8196fae3 662 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
663 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
664 &vhost_ldap_module);
665 mod_vhost_ldap_request_t *req =
666 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
667 &vhost_ldap_module);
668
669 uid_t uid = -1;
670 gid_t gid = -1;
671
8196fae3
OS
672 // mod_vhost_ldap is disabled or we don't have LDAP Url
673 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
674 return NULL;
675 }
676
677 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
678 return NULL;
679 }
680
681 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
682 return NULL;
683 }
684
685 uid = (uid_t)atoll(req->uid);
686 gid = (gid_t)atoll(req->gid);
687
eea38f6d 688 if ((uid < MIN_UID)||(gid < MIN_GID)) {
7f9875bb
OS
689 return NULL;
690 }
691
692 ugid->uid = uid;
693 ugid->gid = gid;
694 ugid->userdir = 0;
695
696 return ugid;
697}
698#endif
699
700static void
701mod_vhost_ldap_register_hooks (apr_pool_t * p)
702{
aad41a70
OS
703
704 /*
705 * Run before mod_rewrite
706 */
707 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
708
7f9875bb 709 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
aad41a70
OS
710 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
711 ap_hook_fixups(mod_vhost_ldap_cleanup, aszRewrite, NULL, APR_HOOK_MIDDLE);
7f9875bb
OS
712#ifdef HAVE_UNIX_SUEXEC
713 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
714#endif
8503d00b 715#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
716 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
717#endif
7f9875bb
OS
718}
719
720module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
721 STANDARD20_MODULE_STUFF,
722 NULL,
723 NULL,
724 mod_vhost_ldap_create_server_config,
8196fae3 725 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
726 mod_vhost_ldap_cmds,
727 mod_vhost_ldap_register_hooks,
728};
This page took 0.153476 seconds and 5 git commands to generate.