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