source: trunk/server/common/oursrc/httpdmods/mod_vhost_ldap.c @ 1463

Last change on this file since 1463 was 1463, checked in by andersk, 14 years ago
mod_vhost_ldap: Copy the server_rec instead of corrupting it in place.
  • Property svn:eol-style set to native
File size: 23.9 KB
Line 
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};
Note: See TracBrowser for help on using the repository browser.