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