]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
Refactor code for processing attributes from LDAP.
[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{
95222c7f
GB
437 server_rec *server;
438 const char *error;
b5043ccb 439 mod_vhost_ldap_request_t *reqc;
7f9875bb
OS
440 int failures = 0;
441 const char **vals = NULL;
442 char filtbuf[FILTER_LENGTH];
8196fae3 443 mod_vhost_ldap_config_t *conf =
7f9875bb 444 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
95222c7f 445 core_server_config *core;
7f9875bb
OS
446 util_ldap_connection_t *ldc = NULL;
447 int result = 0;
448 const char *dn = NULL;
dc514643 449 char *cgi;
6056cddb
OS
450 const char *hostname = NULL;
451 int is_fallback = 0;
4d9859cb
OS
452 int sleep0 = 0;
453 int sleep1 = 1;
454 int sleep;
303e7b48 455 struct berval hostnamebv, shostnamebv;
7f9875bb 456
95222c7f
GB
457 if ((error = ap_init_virtual_host(r->pool, "", r->server, &server)) != NULL) {
458 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
459 "[mod_vhost_ldap.c]: Could not initialize a new VirtualHost: %s",
460 error);
461 return HTTP_INTERNAL_SERVER_ERROR;
462 }
463
464 core = core_module.create_server_config(r->pool, server);
465 ap_set_module_config(server->module_config, &core_module, core);
466
b5043ccb 467 reqc =
7f9875bb 468 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
8503d00b 469 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
b5043ccb
OS
470
471 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
7f9875bb 472
8196fae3
OS
473 // mod_vhost_ldap is disabled or we don't have LDAP Url
474 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
475 return DECLINED;
476 }
477
478start_over:
479
8196fae3
OS
480 if (conf->host) {
481 ldc = util_ldap_connection_find(r, conf->host, conf->port,
482 conf->binddn, conf->bindpw, conf->deref,
483 conf->secure);
7f9875bb
OS
484 }
485 else {
486 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
fb323462 487 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
4cd7ff10 488 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
489 }
490
6056cddb 491 hostname = r->hostname;
303e7b48
OS
492 if (hostname == NULL || hostname[0] == '\0')
493 goto null;
6056cddb
OS
494
495fallback:
496
fb323462 497 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
498 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
499 hostname, r->uri);
7f9875bb 500
303e7b48
OS
501 ber_str2bv(hostname, 0, 0, &hostnamebv);
502 if (ldap_bv2escaped_filter_value(&hostnamebv, &shostnamebv) != 0)
503 goto null;
504 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, shostnamebv.bv_val, shostnamebv.bv_val);
505 ber_memfree(shostnamebv.bv_val);
7f9875bb 506
8196fae3 507 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
7f9875bb
OS
508 attributes, filtbuf, &dn, &vals);
509
510 util_ldap_connection_close(ldc);
511
512 /* sanity check - if server is down, retry it up to 5 times */
9122cbd6
OS
513 if (AP_LDAP_IS_SERVER_DOWN(result) ||
514 (result == LDAP_TIMEOUT) ||
515 (result == LDAP_CONNECT_ERROR)) {
4d9859cb 516 sleep = sleep0 + sleep1;
e78531ef 517 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
518 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
519 failures, sleep);
5e2a6ff5 520 if (failures++ < MAX_FAILURES) {
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) {
a529b3b4
OS
532 if (strcmp(hostname, "*") != 0) {
533 if (strncmp(hostname, "*.", 2) == 0)
534 hostname += 2;
535 hostname += strcspn(hostname, ".");
536 hostname = apr_pstrcat(r->pool, "*", hostname, NULL);
537 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
538 "[mod_vhost_ldap.c] translate: "
539 "virtual host not found, trying wildcard %s",
540 hostname);
541 goto fallback;
542 }
543
303e7b48 544null:
6056cddb
OS
545 if (conf->fallback && (is_fallback++ <= 0)) {
546 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
547 "[mod_vhost_ldap.c] translate: "
548 "virtual host %s not found, trying fallback %s",
549 hostname, conf->fallback);
550 hostname = conf->fallback;
551 goto fallback;
552 }
553
554 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
555 "[mod_vhost_ldap.c] translate: "
556 "virtual host %s not found",
557 hostname);
558
4cd7ff10 559 return HTTP_BAD_REQUEST;
6056cddb
OS
560 }
561
7f9875bb
OS
562 /* handle bind failure */
563 if (result != LDAP_SUCCESS) {
cbd5c5f5 564 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f9875bb 565 "[mod_vhost_ldap.c] translate: "
6056cddb
OS
566 "translate failed; virtual host %s; URI %s [%s]",
567 hostname, r->uri, ldap_err2string(result));
4cd7ff10 568 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
569 }
570
571 /* mark the user and DN */
b5043ccb 572 reqc->dn = apr_pstrdup(r->pool, dn);
7f9875bb
OS
573
574 /* Optimize */
575 if (vals) {
a12ccb0d
GB
576 int i;
577 for (i = 0; attributes[i]; i++) {
7f9875bb 578
a12ccb0d 579 char *val = apr_pstrdup (r->pool, vals[i]);
7f9875bb 580 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
a12ccb0d 581 reqc->name = val;
7f9875bb
OS
582 }
583 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
a12ccb0d 584 reqc->admin = val;
7f9875bb
OS
585 }
586 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
a12ccb0d 587 reqc->docroot = val;
7f9875bb
OS
588 }
589 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
a12ccb0d 590 reqc->cgiroot = val;
7f9875bb
OS
591 }
592 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
a12ccb0d 593 reqc->uid = val;
7f9875bb
OS
594 }
595 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
a12ccb0d 596 reqc->gid = val;
7f9875bb 597 }
7f9875bb
OS
598 }
599 }
600
6f705808
OS
601 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
602 "[mod_vhost_ldap.c]: loaded from ldap: "
603 "apacheServerName: %s, "
604 "apacheServerAdmin: %s, "
605 "apacheDocumentRoot: %s, "
606 "apacheScriptAlias: %s, "
607 "apacheSuexecUid: %s, "
b5043ccb
OS
608 "apacheSuexecGid: %s",
609 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
6f705808 610
b5043ccb 611 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
7f9875bb
OS
612 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
613 "[mod_vhost_ldap.c] translate: "
649a08e8 614 "translate failed; ServerName or DocumentRoot not defined");
4cd7ff10 615 return HTTP_INTERNAL_SERVER_ERROR;
7f9875bb
OS
616 }
617
618 cgi = NULL;
b8f663f9 619
b5043ccb 620 if (reqc->cgiroot) {
6f705808
OS
621 cgi = strstr(r->uri, "cgi-bin/");
622 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
7f9875bb
OS
623 cgi = NULL;
624 }
9ee2dda1 625 }
9ee2dda1 626 if (cgi) {
9122cbd6 627 /* Set exact filename for CGI script */
dc514643 628 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
e6d4a687
OS
629 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
630 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
7f5e70ed
OS
631 "[mod_vhost_ldap.c]: ap_document_root is: %s",
632 ap_document_root(r));
e6d4a687
OS
633 r->filename = cgi;
634 r->handler = "cgi-script";
635 apr_table_setn(r->notes, "alias-forced-type", r->handler);
636 }
4cd7ff10 637 } else if (r->uri[0] == '/') {
9122cbd6
OS
638 /* we don't set r->filename here, and let other modules do it
639 * this allows other modules (mod_rewrite.c) to work as usual
640 */
641 /* r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); */
4cd7ff10 642 } else {
9122cbd6 643 /* We don't handle non-file requests here */
4cd7ff10 644 return DECLINED;
7f9875bb
OS
645 }
646
95222c7f 647 server->server_hostname = reqc->name;
7f9875bb 648
b5043ccb 649 if (reqc->admin) {
95222c7f 650 server->server_admin = reqc->admin;
9122cbd6 651 }
b8f663f9
OS
652
653 /* Stolen from server/core.c */
654
655 /* Make it absolute, relative to ServerRoot */
656 reqc->docroot = ap_server_root_relative(r->pool, reqc->docroot);
657
658 if (reqc->docroot == NULL) {
659 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
660 "[mod_vhost_ldap.c] set_document_root: DocumentRoot must be a directory");
661
662 return HTTP_INTERNAL_SERVER_ERROR;
663 }
664
665 /* TODO: ap_configtestonly && ap_docrootcheck && */
666 if (apr_filepath_merge((char**)&core->ap_document_root, NULL, reqc->docroot,
667 APR_FILEPATH_TRUENAME, r->pool) != APR_SUCCESS
668 || !ap_is_directory(r->pool, reqc->docroot)) {
669
670 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
671 "[mod_vhost_ldap.c] set_document_root: Warning: DocumentRoot [%s] does not exist",
672 reqc->docroot);
673 core->ap_document_root = reqc->docroot;
674 }
7f9875bb 675
95222c7f
GB
676 ap_fixup_virtual_host(r->pool, r->server, server);
677 r->server = server;
678
aad41a70
OS
679 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
680 return DECLINED;
681}
682
7f9875bb
OS
683#ifdef HAVE_UNIX_SUEXEC
684static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
685{
686 ap_unix_identity_t *ugid = NULL;
8196fae3 687 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
688 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
689 &vhost_ldap_module);
690 mod_vhost_ldap_request_t *req =
691 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
692 &vhost_ldap_module);
693
694 uid_t uid = -1;
695 gid_t gid = -1;
696
8196fae3
OS
697 // mod_vhost_ldap is disabled or we don't have LDAP Url
698 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
699 return NULL;
700 }
701
702 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
703 return NULL;
704 }
705
706 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
707 return NULL;
708 }
709
710 uid = (uid_t)atoll(req->uid);
711 gid = (gid_t)atoll(req->gid);
712
eea38f6d 713 if ((uid < MIN_UID)||(gid < MIN_GID)) {
7f9875bb
OS
714 return NULL;
715 }
716
717 ugid->uid = uid;
718 ugid->gid = gid;
719 ugid->userdir = 0;
720
721 return ugid;
722}
723#endif
724
725static void
726mod_vhost_ldap_register_hooks (apr_pool_t * p)
727{
aad41a70
OS
728
729 /*
730 * Run before mod_rewrite
731 */
732 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
733
7f9875bb 734 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
aad41a70 735 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
7f9875bb
OS
736#ifdef HAVE_UNIX_SUEXEC
737 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
738#endif
8503d00b 739#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
740 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
741#endif
7f9875bb
OS
742}
743
744module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
745 STANDARD20_MODULE_STUFF,
746 NULL,
747 NULL,
748 mod_vhost_ldap_create_server_config,
8196fae3 749 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
750 mod_vhost_ldap_cmds,
751 mod_vhost_ldap_register_hooks,
752};
This page took 0.176728 seconds and 5 git commands to generate.