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