]> andersk Git - mod-vhost-ldap.git/blame_incremental - mod_vhost_ldap.c
Fix code in fixups
[mod-vhost-ldap.git] / mod_vhost_ldap.c
... / ...
CommitLineData
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
23#define CORE_PRIVATE
24
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"
32#include "apr_version.h"
33#include "apr_ldap.h"
34#include "apr_reslist.h"
35#include "apr_strings.h"
36#include "apr_tables.h"
37#include "util_ldap.h"
38#include "util_script.h"
39
40#if !defined(APU_HAS_LDAP) && !defined(APR_HAS_LDAP)
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
52#define MIN_UID 100
53#define MIN_GID 100
54
55#define MAX_FAILURES 5
56
57module AP_MODULE_DECLARE_DATA vhost_ldap_module;
58
59typedef enum {
60 MVL_UNSET, MVL_DISABLED, MVL_ENABLED
61} mod_vhost_ldap_status_e;
62
63typedef struct mod_vhost_ldap_config_t {
64 mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */
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
79 int have_deref; /* Set if we have found an Deref option */
80 int have_ldap_url; /* Set if we have found an LDAP url */
81
82 int secure; /* True if SSL connections are requested */
83
84 char *fallback; /* Fallback virtual host */
85
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 */
93 char *cgiroot; /* ScriptAlias */
94 char *uid; /* Suexec Uid */
95 char *gid; /* Suexec Gid */
96} mod_vhost_ldap_request_t;
97
98char *attributes[] =
99 { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 };
100
101#if (APR_MAJOR_VERSION >= 1)
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
122/* Taken from server/core.c */
123static int set_document_root(request_rec *r, const char *arg)
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 */
129 arg = ap_server_root_relative(r->pool, arg);
130
131 if (arg == NULL) {
132 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
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
144 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
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 }
150 return OK;
151}
152
153
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
165 ap_add_version_component(p, MOD_VHOST_LDAP_VERSION);
166
167 return OK;
168}
169
170static void *
171mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s)
172{
173 mod_vhost_ldap_config_t *conf =
174 (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof (mod_vhost_ldap_config_t));
175
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;
182 conf->fallback = NULL;
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));
194
195 if (child->enabled == MVL_UNSET) {
196 conf->enabled = parent->enabled;
197 } else {
198 conf->enabled = child->enabled;
199 }
200
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
231 conf->fallback = (child->fallback ? child->fallback : parent->fallback);
232
233 return conf;
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;
246#if (APR_MAJOR_VERSION >= 1)
247 apr_ldap_err_t *result_err;
248#endif
249
250 mod_vhost_ldap_config_t *conf =
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);
257
258#if (APR_MAJOR_VERSION >= 1) /* for apache >= 2.2 */
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
264 result = apr_ldap_url_parse(url, &(urld));
265 if (result != LDAP_SUCCESS) {
266 switch (result) {
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";
277 }
278 }
279#endif
280 conf->url = apr_pstrdup(cmd->pool, url);
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 */
299 if (conf->host) {
300 char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2);
301 strcpy(p, urld->lud_host);
302 strcat(p, " ");
303 strcat(p, conf->host);
304 conf->host = p;
305 }
306 else {
307 conf->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
308 }
309 conf->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
310
311 conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ?
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 */
320 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1);
321 conf->filter[strlen(conf->filter)-1] = '\0';
322 }
323 else {
324 conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
325 }
326 }
327 else {
328 conf->filter = "objectClass=apacheConfig";
329 }
330
331 /* "ldaps" indicates secure ldap connections desired
332 */
333 if (strncasecmp(url, "ldaps", 5) == 0)
334 {
335 conf->secure = 1;
336 conf->port = urld->lud_port? urld->lud_port : LDAPS_PORT;
337 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
338 "LDAP: vhost_ldap using SSL connections");
339 }
340 else
341 {
342 conf->secure = 0;
343 conf->port = urld->lud_port? urld->lud_port : LDAP_PORT;
344 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server,
345 "LDAP: vhost_ldap not using SSL connections");
346 }
347
348 conf->have_ldap_url = 1;
349#if (APR_MAJOR_VERSION < 1) /* free only required for older apr */
350 apr_ldap_free_urldesc(urld);
351#endif
352 return NULL;
353}
354
355static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int enabled)
356{
357 mod_vhost_ldap_config_t *conf =
358 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
359 &vhost_ldap_module);
360
361 conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED;
362
363 return NULL;
364}
365
366static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const char *binddn)
367{
368 mod_vhost_ldap_config_t *conf =
369 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
370 &vhost_ldap_module);
371
372 conf->binddn = apr_pstrdup(cmd->pool, binddn);
373 return NULL;
374}
375
376static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const char *bindpw)
377{
378 mod_vhost_ldap_config_t *conf =
379 (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config,
380 &vhost_ldap_module);
381
382 conf->bindpw = apr_pstrdup(cmd->pool, bindpw);
383 return NULL;
384}
385
386static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const char *deref)
387{
388 mod_vhost_ldap_config_t *conf =
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) {
393 conf->deref = never;
394 conf->have_deref = 1;
395 }
396 else if (strcmp(deref, "searching") == 0) {
397 conf->deref = searching;
398 conf->have_deref = 1;
399 }
400 else if (strcmp(deref, "finding") == 0) {
401 conf->deref = finding;
402 conf->have_deref = 1;
403 }
404 else if (strcmp(deref, "always") == 0 || strcasecmp(deref, "on") == 0) {
405 conf->deref = always;
406 conf->have_deref = 1;
407 }
408 else {
409 return "Unrecognized value for VhostLDAPAliasDereference directive";
410 }
411 return NULL;
412}
413
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
424command_rec mod_vhost_ldap_cmds[] = {
425 AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF,
426 "URL to define LDAP connection. This should be an RFC 2255 compliant\n"
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,
445 "Determines how aliases are handled during a search. Can be one of the"
446 "values \"never\", \"searching\", \"finding\", or \"always\". "
447 "Defaults to always."),
448
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
454 {NULL}
455};
456
457#define FILTER_LENGTH MAX_STRING_LEN
458static int mod_vhost_ldap_translate_name(request_rec *r)
459{
460 request_rec *top = (r->main)?r->main:r;
461 mod_vhost_ldap_request_t *reqc;
462 int failures = 0;
463 const char **vals = NULL;
464 char filtbuf[FILTER_LENGTH];
465 mod_vhost_ldap_config_t *conf =
466 (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module);
467 util_ldap_connection_t *ldc = NULL;
468 int result = 0;
469 const char *dn = NULL;
470 char *cgi;
471 const char *hostname = NULL;
472 int is_fallback = 0;
473 int sleep0 = 0;
474 int sleep1 = 1;
475 int sleep;
476 struct berval hostnamebv, shostnamebv;
477
478 reqc =
479 (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t));
480 memset(reqc, 0, sizeof(mod_vhost_ldap_request_t));
481
482 ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
483
484 // mod_vhost_ldap is disabled or we don't have LDAP Url
485 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
486 return DECLINED;
487 }
488
489start_over:
490
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);
495 }
496 else {
497 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
498 "[mod_vhost_ldap.c] translate: no conf->host - weird...?");
499 return HTTP_INTERNAL_SERVER_ERROR;
500 }
501
502 hostname = r->hostname;
503 if (hostname == NULL || hostname[0] == '\0')
504 goto null;
505
506fallback:
507
508 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
509 "[mod_vhost_ldap.c]: translating hostname [%s], uri [%s]",
510 hostname, r->uri);
511
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);
517
518 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope,
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 */
524 if (AP_LDAP_IS_SERVER_DOWN(result) ||
525 (result == LDAP_TIMEOUT) ||
526 (result == LDAP_CONNECT_ERROR)) {
527 sleep = sleep0 + sleep1;
528 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
529 "[mod_vhost_ldap.c]: lookup failure, retry number #[%d], sleeping for [%d] seconds",
530 failures, sleep);
531 if (failures++ < MAX_FAILURES) {
532 /* Back-off exponentially */
533 apr_sleep(apr_time_from_sec(sleep));
534 sleep0 = sleep1;
535 sleep1 = sleep;
536 goto start_over;
537 } else {
538 return HTTP_GATEWAY_TIME_OUT;
539 }
540 }
541
542 if (result == LDAP_NO_SUCH_OBJECT) {
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
555null:
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
570 return HTTP_BAD_REQUEST;
571 }
572
573 /* handle bind failure */
574 if (result != LDAP_SUCCESS) {
575 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r,
576 "[mod_vhost_ldap.c] translate: "
577 "translate failed; virtual host %s; URI %s [%s]",
578 hostname, r->uri, ldap_err2string(result));
579 return HTTP_INTERNAL_SERVER_ERROR;
580 }
581
582 /* mark the user and DN */
583 reqc->dn = apr_pstrdup(r->pool, dn);
584
585 /* Optimize */
586 if (vals) {
587 int i = 0;
588 while (attributes[i]) {
589
590 if (strcasecmp (attributes[i], "apacheServerName") == 0) {
591 reqc->name = apr_pstrdup (r->pool, vals[i]);
592 }
593 else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) {
594 reqc->admin = apr_pstrdup (r->pool, vals[i]);
595 }
596 else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) {
597 reqc->docroot = apr_pstrdup (r->pool, vals[i]);
598 }
599 else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) {
600 reqc->cgiroot = apr_pstrdup (r->pool, vals[i]);
601 }
602 else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) {
603 reqc->uid = apr_pstrdup(r->pool, vals[i]);
604 }
605 else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) {
606 reqc->gid = apr_pstrdup(r->pool, vals[i]);
607 }
608 i++;
609 }
610 }
611
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, "
619 "apacheSuexecGid: %s",
620 reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid);
621
622 if ((reqc->name == NULL)||(reqc->docroot == NULL)) {
623 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
624 "[mod_vhost_ldap.c] translate: "
625 "translate failed; ServerName or DocumentRoot not defined");
626 return HTTP_INTERNAL_SERVER_ERROR;
627 }
628
629 cgi = NULL;
630
631 if (reqc->cgiroot) {
632 cgi = strstr(r->uri, "cgi-bin/");
633 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
634 cgi = NULL;
635 }
636 }
637 if (cgi) {
638 /* Set exact filename for CGI script */
639 cgi = apr_pstrcat(r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL);
640 if ((cgi = ap_server_root_relative(r->pool, cgi))) {
641 ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
642 "[mod_vhost_ldap.c]: ap_document_root is: %s",
643 ap_document_root(r));
644 r->filename = cgi;
645 r->handler = "cgi-script";
646 apr_table_setn(r->notes, "alias-forced-type", r->handler);
647 }
648 } else if (r->uri[0] == '/') {
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); */
653 } else {
654 /* We don't handle non-file requests here */
655 return DECLINED;
656 }
657
658 top->server->server_hostname = apr_pstrdup (top->pool, reqc->name);
659
660 if (reqc->admin) {
661 top->server->server_admin = apr_pstrdup (top->pool, reqc->admin);
662 }
663
664 result = set_document_root(r, reqc->docroot);
665 if (result != OK) {
666 return HTTP_INTERNAL_SERVER_ERROR;
667 }
668 apr_table_setn(r->notes, "vhost-document-root", reqc->docroot);
669
670 /* Hack to allow post-processing by other modules (mod_rewrite, mod_alias) */
671 return DECLINED;
672}
673
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;
678 mod_vhost_ldap_config_t *conf =
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
688 // mod_vhost_ldap is disabled or we don't have LDAP Url
689 if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) {
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
704 if ((uid < MIN_UID)||(gid < MIN_GID)) {
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
716static int mod_vhost_ldap_fixups(request_rec *r)
717{
718 char *docroot =
719 apr_table_get(r->notes, "vhost-document-root");
720
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);
726}
727
728static void
729mod_vhost_ldap_register_hooks (apr_pool_t * p)
730{
731
732 /*
733 * Run before mod_rewrite
734 */
735 static const char * const aszRewrite[]={ "mod_rewrite.c", NULL };
736
737 ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE);
738 ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, aszRewrite, APR_HOOK_FIRST);
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
742#if (APR_MAJOR_VERSION >= 1)
743 ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
744#endif
745
746 ap_hook_fixups(mod_vhost_ldap_fixups, NULL, NULL, APR_HOOK_LAST);
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,
754 mod_vhost_ldap_merge_server_config,
755 mod_vhost_ldap_cmds,
756 mod_vhost_ldap_register_hooks,
757};
This page took 0.050507 seconds and 5 git commands to generate.