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