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