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