X-Git-Url: http://andersk.mit.edu/gitweb/mod-vhost-ldap.git/blobdiff_plain/cbd5c5f55314ac4f02927b5368856fab339c0eb1..HEAD:/mod_vhost_ldap.c diff --git a/mod_vhost_ldap.c b/mod_vhost_ldap.c index e0ae7de..f3b729a 100644 --- a/mod_vhost_ldap.c +++ b/mod_vhost_ldap.c @@ -29,12 +29,13 @@ #include "http_core.h" #include "http_log.h" #include "http_request.h" +#include "apr_version.h" #include "apr_ldap.h" #include "apr_strings.h" #include "apr_reslist.h" #include "util_ldap.h" -#ifndef APU_HAS_LDAP +#if !defined(APU_HAS_LDAP) && !defined(APR_HAS_LDAP) #error mod_vhost_ldap requires APR-util to have LDAP support built in #endif @@ -75,6 +76,9 @@ typedef struct mod_vhost_ldap_config_t { int have_ldap_url; /* Set if we have found an LDAP url */ int secure; /* True if SSL connections are requested */ + + char *fallback; /* Fallback virtual host */ + } mod_vhost_ldap_config_t; typedef struct mod_vhost_ldap_request_t { @@ -90,6 +94,27 @@ typedef struct mod_vhost_ldap_request_t { char *attributes[] = { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 }; +#if (APR_MAJOR_VERSION >= 1) +static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close; +static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find; +static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn; +static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare; +static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid; +static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn; +static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported; + +static void ImportULDAPOptFn(void) +{ + util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close); + util_ldap_connection_find = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find); + util_ldap_cache_comparedn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn); + util_ldap_cache_compare = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare); + util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid); + util_ldap_cache_getuserdn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn); + util_ldap_ssl_supported = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported); +} +#endif + static int mod_vhost_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { /* make sure that mod_ldap (util_ldap) is loaded */ @@ -118,6 +143,7 @@ mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s) conf->binddn = NULL; conf->bindpw = NULL; conf->deref = always; + conf->fallback = NULL; return conf; } @@ -166,6 +192,8 @@ mod_vhost_ldap_merge_server_config(apr_pool_t *p, void *parentv, void *childv) conf->binddn = (child->binddn ? child->binddn : parent->binddn); conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw); + conf->fallback = (child->fallback ? child->fallback : parent->fallback); + return conf; } @@ -179,6 +207,9 @@ static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd, { int result; apr_ldap_url_desc_t *urld; +#if (APR_MAJOR_VERSION >= 1) + apr_ldap_err_t *result_err; +#endif mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, @@ -187,22 +218,29 @@ static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[mod_vhost_ldap.c] url parse: `%s'", url); - + +#if (APR_MAJOR_VERSION >= 1) /* for apache >= 2.2 */ + result = apr_ldap_url_parse(cmd->pool, url, &(urld), &(result_err)); + if (result != LDAP_SUCCESS) { + return result_err->reason; + } +#else result = apr_ldap_url_parse(url, &(urld)); if (result != LDAP_SUCCESS) { switch (result) { - case LDAP_URL_ERR_NOTLDAP: - return "LDAP URL does not begin with ldap://"; - case LDAP_URL_ERR_NODN: - return "LDAP URL does not have a DN"; - case LDAP_URL_ERR_BADSCOPE: - return "LDAP URL has an invalid scope"; - case LDAP_URL_ERR_MEM: - return "Out of memory parsing LDAP URL"; - default: - return "Could not parse LDAP URL"; + case LDAP_URL_ERR_NOTLDAP: + return "LDAP URL does not begin with ldap://"; + case LDAP_URL_ERR_NODN: + return "LDAP URL does not have a DN"; + case LDAP_URL_ERR_BADSCOPE: + return "LDAP URL has an invalid scope"; + case LDAP_URL_ERR_MEM: + return "Out of memory parsing LDAP URL"; + default: + return "Could not parse LDAP URL"; } } +#endif conf->url = apr_pstrdup(cmd->pool, url); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, @@ -272,7 +310,9 @@ static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd, } conf->have_ldap_url = 1; +#if (APR_MAJOR_VERSION < 1) /* free only required for older apr */ apr_ldap_free_urldesc(urld); +#endif return NULL; } @@ -280,7 +320,7 @@ static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int e { mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + &vhost_ldap_module); conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED; @@ -291,7 +331,7 @@ static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const { mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + &vhost_ldap_module); conf->binddn = apr_pstrdup(cmd->pool, binddn); return NULL; @@ -301,7 +341,7 @@ static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const { mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + &vhost_ldap_module); conf->bindpw = apr_pstrdup(cmd->pool, bindpw); return NULL; @@ -335,6 +375,16 @@ static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const c return NULL; } +static const char *mod_vhost_ldap_set_fallback(cmd_parms *cmd, void *dummy, const char *fallback) +{ + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, + &vhost_ldap_module); + + conf->fallback = apr_pstrdup(cmd->pool, fallback); + return NULL; +} + command_rec mod_vhost_ldap_cmds[] = { AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF, "URL to define LDAP connection. This should be an RFC 2255 compliant\n" @@ -360,13 +410,19 @@ command_rec mod_vhost_ldap_cmds[] = { "values \"never\", \"searching\", \"finding\", or \"always\". " "Defaults to always."), + AP_INIT_TAKE1("VhostLDAPFallback", mod_vhost_ldap_set_fallback, NULL, RSRC_CONF, + "Set default virtual host which will be used when requested hostname" + "is not found in LDAP database. This option can be used to display" + "\"virtual host not found\" type of page."), + {NULL} }; #define FILTER_LENGTH MAX_STRING_LEN -static int -mod_vhost_ldap_translate_name (request_rec * r) +static int mod_vhost_ldap_translate_name(request_rec *r) { + request_rec *top = (r->main)?r->main:r; + mod_vhost_ldap_request_t *reqc; apr_table_t *e; int failures = 0; const char **vals = NULL; @@ -379,10 +435,14 @@ mod_vhost_ldap_translate_name (request_rec * r) int result = 0; const char *dn = NULL; char *cgi; + const char *hostname = NULL; + int is_fallback = 0; - mod_vhost_ldap_request_t *req = + reqc = (mod_vhost_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t)); - ap_set_module_config(r->request_config, &vhost_ldap_module, req); + memset(reqc, 0, sizeof(mod_vhost_ldap_request_t)); + + ap_set_module_config(r->request_config, &vhost_ldap_module, reqc); // mod_vhost_ldap is disabled or we don't have LDAP Url if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) { @@ -402,10 +462,14 @@ start_over: return DECLINED; } + hostname = r->hostname; + +fallback: + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap.c]: translating %s", r->uri); - apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, r->hostname, r->hostname); + apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, hostname, hostname); result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, attributes, filtbuf, &dn, &vals); @@ -419,17 +483,35 @@ start_over: } } + if ((result == LDAP_NO_SUCH_OBJECT)) { + if (conf->fallback && (is_fallback++ <= 0)) { + ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r, + "[mod_vhost_ldap.c] translate: " + "virtual host %s not found, trying fallback %s", + hostname, conf->fallback); + hostname = conf->fallback; + goto fallback; + } + + ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, + "[mod_vhost_ldap.c] translate: " + "virtual host %s not found", + hostname); + + return DECLINED; + } + /* handle bind failure */ if (result != LDAP_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap.c] translate: " - "translate failed; VHost %s; URI %s[%s]", - r->hostname, r->uri, ldap_err2string(result)); + "translate failed; virtual host %s; URI %s [%s]", + hostname, r->uri, ldap_err2string(result)); return DECLINED; } /* mark the user and DN */ - req->dn = apr_pstrdup(r->pool, dn); + reqc->dn = apr_pstrdup(r->pool, dn); /* Optimize */ if (vals) { @@ -437,22 +519,22 @@ start_over: while (attributes[i]) { if (strcasecmp (attributes[i], "apacheServerName") == 0) { - req->name = apr_pstrdup (r->pool, vals[i]); + reqc->name = apr_pstrdup (r->pool, vals[i]); } else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) { - req->admin = apr_pstrdup (r->pool, vals[i]); + reqc->admin = apr_pstrdup (r->pool, vals[i]); } else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) { - req->docroot = apr_pstrdup (r->pool, vals[i]); + reqc->docroot = apr_pstrdup (r->pool, vals[i]); } else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) { - req->cgiroot = apr_pstrdup (r->pool, vals[i]); + reqc->cgiroot = apr_pstrdup (r->pool, vals[i]); } else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) { - req->uid = apr_pstrdup(r->pool, vals[i]); + reqc->uid = apr_pstrdup(r->pool, vals[i]); } else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) { - req->gid = apr_pstrdup(r->pool, vals[i]); + reqc->gid = apr_pstrdup(r->pool, vals[i]); } i++; } @@ -465,10 +547,10 @@ start_over: "apacheDocumentRoot: %s, " "apacheScriptAlias: %s, " "apacheSuexecUid: %s, " - "apacheSuexecGid: %s" - , req->name, req->admin, req->docroot, req->cgiroot, req->uid, req->gid); + "apacheSuexecGid: %s", + reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid); - if ((req->name == NULL)||(req->docroot == NULL)) { + if ((reqc->name == NULL)||(reqc->docroot == NULL)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap.c] translate: " "translate failed; ServerName or DocumentRoot not defined"); @@ -477,33 +559,33 @@ start_over: cgi = NULL; - if (req->cgiroot) { + if (reqc->cgiroot) { cgi = strstr(r->uri, "cgi-bin/"); if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) { cgi = NULL; } } if (cgi) { - r->filename = apr_pstrcat (r->pool, req->cgiroot, cgi + strlen("cgi-bin"), NULL); + r->filename = apr_pstrcat (r->pool, reqc->cgiroot, cgi + strlen("cgi-bin"), NULL); r->handler = "cgi-script"; apr_table_setn(r->notes, "alias-forced-type", r->handler); } else if (r->uri[0] == '/') { - r->filename = apr_pstrcat (r->pool, req->docroot, r->uri, NULL); + r->filename = apr_pstrcat (r->pool, reqc->docroot, r->uri, NULL); } else { return DECLINED; } - r->server->server_hostname = apr_pstrdup (r->pool, req->name); + top->server->server_hostname = apr_pstrdup (top->pool, reqc->name); - if (req->admin) { - r->server->server_admin = apr_pstrdup (r->pool, req->admin); + if (reqc->admin) { + top->server->server_admin = apr_pstrdup (top->pool, reqc->admin); } // set environment variables - e = r->subprocess_env; - apr_table_addn (e, "SERVER_ROOT", req->docroot); + e = top->subprocess_env; + apr_table_addn (e, "SERVER_ROOT", reqc->docroot); - core->ap_document_root = apr_pstrdup(r->pool, req->docroot); + core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[mod_vhost_ldap.c]: translated to %s", r->filename); @@ -561,6 +643,9 @@ mod_vhost_ldap_register_hooks (apr_pool_t * p) #ifdef HAVE_UNIX_SUEXEC ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE); #endif +#if (APR_MAJOR_VERSION >= 1) + ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE); +#endif } module AP_MODULE_DECLARE_DATA vhost_ldap_module = {