]> andersk Git - mod-vhost-ldap.git/blame - mod_vhost_ldap.c
This one's better, e.g., it works.
[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
OS
507 if ((result == LDAP_NO_SUCH_OBJECT)) {
508 if (conf->fallback && (is_fallback++ <= 0)) {
509 ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
510 "[mod_vhost_ldap.c] translate: "
511 "virtual host %s not found, trying fallback %s",
512 hostname, conf->fallback);
513 hostname = conf->fallback;
514 goto fallback;
515 }
516
517 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
518 "[mod_vhost_ldap.c] translate: "
519 "virtual host %s not found",
520 hostname);
521
522 return DECLINED;
523 }
524
7f9875bb
OS
525 /* handle bind failure */
526 if (result != LDAP_SUCCESS) {
cbd5c5f5 527 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
7f9875bb 528 "[mod_vhost_ldap.c] translate: "
6056cddb
OS
529 "translate failed; virtual host %s; URI %s [%s]",
530 hostname, r->uri, ldap_err2string(result));
7f9875bb
OS
531 return DECLINED;
532 }
533
534 /* mark the user and DN */
b5043ccb 535 reqc->dn = apr_pstrdup(r->pool, dn);
7f9875bb
OS
536
537 /* Optimize */
538 if (vals) {
539 int i = 0;
540 while (attributes[i]) {
541
542 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
b5043ccb 543 reqc->name = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
544 }
545 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
b5043ccb 546 reqc->admin = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
547 }
548 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
b5043ccb 549 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
550 }
551 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
b5043ccb 552 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
7f9875bb
OS
553 }
554 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
b5043ccb 555 reqc->uid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
556 }
557 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
b5043ccb 558 reqc->gid = apr_pstrdup(r->pool, vals[i]);
7f9875bb
OS
559 }
560 i++;
561 }
562 }
563
6f705808
OS
564 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
565 "[mod_vhost_ldap.c]: loaded from ldap: "
566 "apacheServerName: %s, "
567 "apacheServerAdmin: %s, "
568 "apacheDocumentRoot: %s, "
569 "apacheScriptAlias: %s, "
570 "apacheSuexecUid: %s, "
b5043ccb
OS
571 "apacheSuexecGid: %s",
572 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
6f705808 573
b5043ccb 574 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
7f9875bb
OS
575 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
576 "[mod_vhost_ldap.c] translate: "
577 "translate failed; ServerName or DocumentRoot not defined");
578 return DECLINED;
579 }
580
581 cgi = NULL;
582
553be6af 583#if 0
b5043ccb 584 if (reqc->cgiroot) {
6f705808
OS
585 cgi = strstr(r->uri, "cgi-bin/");
586 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
7f9875bb
OS
587 cgi = NULL;
588 }
9ee2dda1 589 }
9ee2dda1 590 if (cgi) {
b5043ccb 591 r->filename = apr_pstrcat (r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
9ee2dda1
OS
592 r->handler = "cgi-script";
593 apr_table_setn(r->notes, "alias-forced-type", r->handler);
553be6af
AK
594#endif
595 /* This is a quick, dirty hack. I should be shot for taking 6.170
596 * this term and being willing to write a quick, dirty hack. */
597
598 if (strncmp(r->uri, "/~", 2) == 0) {
599 char *username;
600 uid_t uid = (uid_t)atoll(reqc->uid);
601 if (apr_uid_name_get(&username, uid, r->pool) != APR_SUCCESS) {
602 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
603 "could not get username for uid %d", uid);
604 return DECLINED;
605 }
606 if (strncmp(r->uri + 2, username, strlen(username)) == 0 &&
4f5dbaf8
GT
607 (r->uri[2 + strlen(username)] == '/' ||
608 r->uri[2 + strlen(username)] == '\0')) {
553be6af
AK
609 char *homedir;
610 if (apr_uid_homepath_get(&homedir, username, r->pool) != APR_SUCCESS) {
611 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
612 "could not get home directory for user %s", username);
613 return DECLINED;
614 }
615 r->filename = apr_pstrcat(r->pool, homedir, "/", USERDIR, r->uri + 2 + strlen(username), NULL);
616 }
6f705808 617 } else if (r->uri[0] == '/') {
b5043ccb 618 r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL);
9ee2dda1 619 } else {
6f705808 620 return DECLINED;
7f9875bb
OS
621 }
622
19d58500 623 top->server->server_hostname = apr_pstrdup (top->pool, reqc->name);
7f9875bb 624
b5043ccb 625 if (reqc->admin) {
19d58500 626 top->server->server_admin = apr_pstrdup (top->pool, reqc->admin);
7f9875bb
OS
627 }
628
629 // set environment variables
b5043ccb
OS
630 e = top->subprocess_env;
631 apr_table_addn (e, "SERVER_ROOT", reqc->docroot);
7f9875bb 632
b5043ccb 633 core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot);
9ee2dda1 634
7f9875bb
OS
635 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
636 "[mod_vhost_ldap.c]: translated to %s", r->filename);
637
638 return OK;
639}
640
641#ifdef HAVE_UNIX_SUEXEC
642static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r)
643{
644 ap_unix_identity_t *ugid = NULL;
8196fae3 645 mod_vhost_ldap_config_t *conf =
7f9875bb
OS
646 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config,
647 &vhost_ldap_module);
648 mod_vhost_ldap_request_t *req =
649 (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config,
650 &vhost_ldap_module);
651
652 uid_t uid = -1;
653 gid_t gid = -1;
654
8196fae3
OS
655 // mod_vhost_ldap is disabled or we don't have LDAP Url
656 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
7f9875bb
OS
657 return NULL;
658 }
659
660 if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) {
661 return NULL;
662 }
663
664 if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) {
665 return NULL;
666 }
667
668 uid = (uid_t)atoll(req->uid);
669 gid = (gid_t)atoll(req->gid);
670
eea38f6d 671 if ((uid < MIN_UID)||(gid < MIN_GID)) {
7f9875bb
OS
672 return NULL;
673 }
674
675 ugid->uid = uid;
676 ugid->gid = gid;
677 ugid->userdir = 0;
678
679 return ugid;
680}
681#endif
682
683static void
684mod_vhost_ldap_register_hooks (apr_pool_t * p)
685{
686 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
687 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, NULL, APR_HOOK_MIDDLE);
688#ifdef HAVE_UNIX_SUEXEC
689 ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE);
690#endif
8503d00b 691#if (APR_MAJOR_VERSION >= 1)
3b8a47e0
OS
692 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
693#endif
7f9875bb
OS
694}
695
696module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
697 STANDARD20_MODULE_STUFF,
698 NULL,
699 NULL,
700 mod_vhost_ldap_create_server_config,
8196fae3 701 mod_vhost_ldap_merge_server_config,
7f9875bb
OS
702 mod_vhost_ldap_cmds,
703 mod_vhost_ldap_register_hooks,
704};
This page took 2.325079 seconds and 5 git commands to generate.