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