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