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