]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
Skip to the fallback vhost for hostname == NULL.
[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 485 hostname = r->hostname;
22c789a9
AK
486 if (hostname == NULL)
487 goto null;
6056cddb
OS
488
489fallback:
490
fb323462 491 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
6f705808 492 "[mod_vhost_ldap.c]: translating %s", r->uri);
7f9875bb 493
5a9ed896 494 s_hostname = mod_vhost_ldap_escape(r->pool, hostname);
43773569 495 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, s_hostname, s_hostname);
7f9875bb 496
8196fae3 497 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
7f9875bb
OS
498 attributes, filtbuf, &dn, &vals);
499
500 util_ldap_connection_close(ldc);
501
502 /* sanity check - if server is down, retry it up to 5 times */
503 if (result == LDAP_SERVER_DOWN) {
504 if (failures++ <= 5) {
505 goto start_over;
506 }
507 }
508
6056cddb 509 if ((result == LDAP_NO_SUCH_OBJECT)) {
425e2c3c
GT
510 char* parent_hostname = apr_pstrdup(r->pool, hostname);
511 do {
512 parent_hostname = strchr(parent_hostname + 1, '.');
513 } while (parent_hostname && parent_hostname[-1] != '*');
514 if (parent_hostname) {
515 *(--parent_hostname) = '*';
516 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
517 "[mod_vhost_ldap.c] translate: "
518 "virtual host not found, trying wildcard %s",
519 parent_hostname);
520 hostname = parent_hostname;
521 goto fallback;
522 }
22c789a9
AK
523
524 null:
6056cddb
OS
525 if (conf->fallback && (is_fallback++ <= 0)) {
526 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
527 "[mod_vhost_ldap.c] translate: "
528 "virtual host %s not found, trying fallback %s",
529 hostname, conf->fallback);
530 hostname = conf->fallback;
531 goto fallback;
532 }
533
534 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
535 "[mod_vhost_ldap.c] translate: "
536 "virtual host %s not found",
537 hostname);
538
539 return DECLINED;
540 }
541
7f9875bb
OS
542 /* handle bind failure */
543 if (result != LDAP_SUCCESS) {
cbd5c5f5 544 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f9875bb 545 "[mod_vhost_ldap.c] translate: "
6056cddb
OS
546 "translate failed; virtual host %s; URI %s [%s]",
547 hostname, r->uri, ldap_err2string(result));
7f9875bb
OS
548 return DECLINED;
549 }
550
551 /* mark the user and DN */
b5043ccb 552 reqc->dn = apr_pstrdup(r->pool, dn);
7f9875bb
OS
553
554 /* Optimize */
555 if (vals) {
556 int i = 0;
557 while (attributes[i]) {
558
559 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
b5043ccb 560 reqc->name = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
561 }
562 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
b5043ccb 563 reqc->admin = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
564 }
565 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
b5043ccb 566 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
567 }
568 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
b5043ccb 569 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
570 }
571 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
b5043ccb 572 reqc->uid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
573 }
574 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
b5043ccb 575 reqc->gid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
576 }
577 i++;
578 }
579 }
580
6f705808
OS
581 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
582 "[mod_vhost_ldap.c]: loaded from ldap: "
583 "apacheServerName: %s, "
584 "apacheServerAdmin: %s, "
585 "apacheDocumentRoot: %s, "
586 "apacheScriptAlias: %s, "
587 "apacheSuexecUid: %s, "
b5043ccb
OS
588 "apacheSuexecGid: %s",
589 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
6f705808 590
b5043ccb 591 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
7f9875bb
OS
592 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
593 "[mod_vhost_ldap.c] translate: "
594 "translate failed; ServerName or DocumentRoot not defined");
595 return DECLINED;
596 }
597
598 cgi = NULL;
599
553be6af 600#if 0
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) {
b5043ccb 608 r->filename = apr_pstrcat (r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
9ee2dda1
OS
609 r->handler = "cgi-script";
610 apr_table_setn(r->notes, "alias-forced-type", r->handler);
553be6af
AK
611#endif
612 /* This is a quick, dirty hack. I should be shot for taking 6.170
613 * this term and being willing to write a quick, dirty hack. */
614
615 if (strncmp(r->uri, "/~", 2) == 0) {
616 char *username;
617 uid_t uid = (uid_t)atoll(reqc->uid);
618 if (apr_uid_name_get(&username, uid, r->pool) != APR_SUCCESS) {
619 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
620 "could not get username for uid %d", uid);
621 return DECLINED;
622 }
623 if (strncmp(r->uri + 2, username, strlen(username)) == 0 &&
4f5dbaf8
GT
624 (r->uri[2 + strlen(username)] == '/' ||
625 r->uri[2 + strlen(username)] == '\0')) {
553be6af
AK
626 char *homedir;
627 if (apr_uid_homepath_get(&homedir, username, r->pool) != APR_SUCCESS) {
628 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
629 "could not get home directory for user %s", username);
630 return DECLINED;
631 }
632 r->filename = apr_pstrcat(r->pool, homedir, "/", USERDIR, r->uri + 2 + strlen(username), NULL);
633 }
6f705808 634 } else if (r->uri[0] == '/') {
b5043ccb 635 r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL);
9ee2dda1 636 } else {
6f705808 637 return DECLINED;
7f9875bb
OS
638 }
639
19d58500 640 top->server->server_hostname = apr_pstrdup (top->pool, reqc->name);
7f9875bb 641
b5043ccb 642 if (reqc->admin) {
19d58500 643 top->server->server_admin = apr_pstrdup (top->pool, reqc->admin);
7f9875bb
OS
644 }
645
646 // set environment variables
b5043ccb
OS
647 e = top->subprocess_env;
648 apr_table_addn (e, "SERVER_ROOT", reqc->docroot);
7f9875bb 649
b5043ccb 650 core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot);
9ee2dda1 651
7f9875bb
OS
652 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
653 "[mod_vhost_ldap.c]: translated to %s", r->filename);
654
655 return OK;
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{
703 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
704 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, NULL, APR_HOOK_MIDDLE);
705#ifdef HAVE_UNIX_SUEXEC
706 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
707#endif
8503d00b 708#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
709 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
710#endif
7f9875bb
OS
711}
712
713module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
714 STANDARD20_MODULE_STUFF,
715 NULL,
716 NULL,
717 mod_vhost_ldap_create_server_config,
8196fae3 718 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
719 mod_vhost_ldap_cmds,
720 mod_vhost_ldap_register_hooks,
721};
This page took 0.16648 seconds and 5 git commands to generate.