]> andersk Git - mod-vhost-ldap.git/blob - mod_vhost_ldap.c
Hard-code ~username for LDAP vhosts.
[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 const char USERDIR[] = "web_scripts";
53
54 module AP_MODULE_DECLARE_DATA vhost_ldap_module;
55
56 typedef enum {
57     MVL_UNSET, MVL_DISABLED, MVL_ENABLED
58 } mod_vhost_ldap_status_e;
59
60 typedef 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
85 typedef 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
95 char *attributes[] =
96   { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 };
97
98 static int total_modules;
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 static 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
144 static void *
145 mod_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
161 static void *
162 mod_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  */
214 static 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
329 static 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
340 static 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
350 static 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
360 static 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
388 static 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
398 command_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
432 static 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
461 start_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
478 fallback:
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
664 static 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
705 static void
706 mod_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
718 module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
719   STANDARD20_MODULE_STUFF,
720   NULL,
721   NULL,
722   mod_vhost_ldap_create_server_config,
723   mod_vhost_ldap_merge_server_config,
724   mod_vhost_ldap_cmds,
725   mod_vhost_ldap_register_hooks,
726 };
This page took 0.420149 seconds and 5 git commands to generate.