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