From 63a07100b13b4405a697b8a79b1abf65c584b2b4 Mon Sep 17 00:00:00 2001 From: Piotr Wadas Date: Fri, 21 Apr 2006 13:04:04 +0000 Subject: [PATCH] Merged Piotr's work to branches/ext-config git-svn-id: svn://svn.debian.org/svn/modvhostldap/branches/ext-config/mod-vhost-ldap@44 4dd36cbf-e3fd-0310-983d-db0e06859cf4 --- ChangeLog | 8 + INSTALL | 145 +++- Makefile | 11 +- README | 1 + TODO | 14 + VERSION | 2 +- encrypt.c | 36 + examples/slapd.conf | 68 ++ examples/vhost_ldap.conf | 17 + mod_vhost_ldap.c | 1393 +++++++++++++++++++++++++------------- 10 files changed, 1207 insertions(+), 488 deletions(-) create mode 100644 encrypt.c create mode 100644 examples/slapd.conf create mode 100644 examples/vhost_ldap.conf diff --git a/ChangeLog b/ChangeLog index decc89c..14529dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-03-30 Piotr Wadas + * mod_vhost_ldap.c: add support for basic ldap auth. Yuck. + * VERSION: 2.0.0 release + +2006-01-30 Ondřej Surý + * VERSION: 1.0.0 release + * Fix small memory leak when used in subrequest (e.g. fastcgi) + 2005-10-03 Ondřej Surý * mod_vhost_ldap.c: add support for running from subrequest (ie. mod_fastcgi) * VERSION: 0.2.9 release diff --git a/INSTALL b/INSTALL index 59d42e5..61bc043 100644 --- a/INSTALL +++ b/INSTALL @@ -3,8 +3,149 @@ the module. This will use Apache's apxs to build/install from source. Have a look at vhost_ldap.conf to learn about configuration. -Your LDAP server needs to include mod_vhost_ldap.schema. If you do not use -OpenLDAP you are on your own to build a schema. +Your LDAP server needs to include mod_vhost_ldap.schema. If You want +additional access control, then include apache_ext.schema also. +If you do not use OpenLDAP you are on your own to build a schema. You should configure the LDAP server to maintain indices on apacheServerName, apacheServerAlias and anything you use in your additional search filter. + +Authentication and authorization works in the following way: + +1. Vhost configuration is checked in ldap +At this step all requested attributes such as ServerName, ServerAlias etc. +including apacheExtConfig attributes, are taken. If not - vhost is returned +OK and goes after further request processing. + +2. If vhost has set +apacheExtConfigHasRequireLine = TRUE, AND AT LEAST ONE apacheLocationOptionsDn +is set pointing to apacheExtConfig object, vhost is marked to have auth/auth. + +3. Then request URI is checked - starting from /, if for URI or any of +URIs below apacheExtConfigObject with apacheExtUri set for uri, is found below +base dn set with VhostLDAPWebLocationConfigBaseDn, processing to generate +require lines. Note, that whatever apacheExtConfigObjectName You set +for configuration, it will appear on authentication dialog box as You'd +specify it with AuthName directive. AuthType (basic) is in code. + +4. if apacheExtConfigRequireValidUser for matched extConfig object is +set to TRUE, then "require valid-user" is generated. +if apacheExtConfigRequireValidUser is set to FALSE, then +there's another search performed, under webUsersbase, to find user names, +for which apacheExtConfigUserServerName matches vhost original name. +All usernames are appended for require line, which contains at least no-user +"nobody", +if no user objects are found. so after, we have +require valid-user +or +require nobody username1 username2 +placed into apache config + +5. authentication phase - user password is checked with LDAP. Note, that +it's checked agains two conditions - with apr_validate_password, and with clear +text. So, in userPassword field, You can put password taken from .htaccess file +(or generated with htpasswd -n), or clear text, and it will be matched agains +string comparison. + +6. Then, authorization phase - if for current URI on previously generated +require line, basic-auth username is found, then access is granted. + +7. In log You shoud have information, whether authentication is successed or +failed, and then information _ONLY_ if authorization denies access. +(authorization access granted is not logged, don't ask why :) + +MORE EXPLANATION: +object of one of apacheExt* classess, have some dn-syntax attributes, which +should point like below: + +* one or more apacheLocationOptionsDn | for vhost, + pointing location config(s) + +* one or more apacheExtConfigUserDn | for location config, + pointing user object(s) + +However this is for use with some external management GUI to keep track of +what's going on - search is made for location on vhost level, and search is +made for users on location level, because apr doesn't have convenient routines, +which allows getting object directly based on its DN. So final result +must be FOUND, not GET, and is found based on another attribute value, +eg. apacheExtConfigServerName for location config, +and apacheExtConfigUserServerName This should be +implemented with ldap.h, or routines for apr should be created. + +IMPORTANT NOTE 1: +All searches for users, and location configurations, are made with +apacheServerName attribute value of current vhost - no matter via which +alias You're accessing server. So YOU DON'T NEED TO ADD EACH serverAlias +to UserObject, or configObject - just add serverName. +The concept is, that when You want to block some resource, eg. some +directory with Your pictures, You want it blocked for all aliases on current +server, no matter how it's access. If You share the same directory under +another vhost, you need to add this vhost serverName to location +extConfigServerName. + +IMPORTANT NOTE 2: +Authentication and authorization with this module is dynamic, that's +why advanced features like apache configstream are not used. Actually +auth/authz information is build against each request, to make You able +to manipulate access control information, without server restarting +(even graceful). Actually making graceful, is no problem - the point is, +that if You edit Your LDAP with some external tool, +e.g. excellent phpldapadmin, You may not want this tool to execute or force +(in any way) any kind of daemons restart. Another solution, is to put +graceful into cron somewhere, however I guess dynamic access control +is more ee.., well, its better solution :) + +IMPORTANT NOTE 3: +If Your changes in LDAP seems to not working, check some cacheTTL and +other directives with apache ldap_module, You've read this module manual, +didn't You? :) + + +TIPS and HINTS: +Enjoying LDAP power - You can have multiple values for some attributes. +actually no matters how many values You set for apacheLocationOptionsDn +(must be at least one), because search is made with uri and serverName. + +However, You can set more than one serverName with location object, +if You want the have the same URI blocked on more than one webserver, +eg. if Your vhosts has standard location "/statistics", You can +block them for all vhosts you want, no matter, whether real statistics +dir exists in filesystem, or not (auth/authz is made before returning data). +Anyway defining the same location for different vhosts as separated object +should work, however they should have different naming attribute. +If You set two objects, for the same uri and different naming attribute, and +the same vhost servername value, probably the first one found will be used, +I didn't check. +extConfigObject may also apply to more than one URI - the same. +You can also have the same user, valid for more than one vhost, exactly +the same rules apply like above. +One user can have more than one password. + +Actually defining separate objects, makes sens only if +You want to be able to quickly enable/disable particular URI +(or user, or config, etc. etc.), instead of removing it, probably +based on some attribute value defined elsewhere, and applied to ldap filter +in mod-ldap-vhost configuration. + +DEVELOPER's NOTE: +The main trick is, that ap_requires is used to SET requirelines using generated +apr_array_header_t, based on some information source, before it's later used +in normal authz procedure, at appropriate authorization hook. + +TODOs (unsorted): +* general code review (use of per-directory-config ?) +* implement php_admin_flag and php_admin_value setting for vhosts with ldap +* implement directory access control, similar to location +* implement directory/location aliasing between vhosts, based on ldap +* implement logging-related directives for ldap-based vhosts +* implement require group +* implement use of other authentication methods than basic, including X509, +and authentication based not only with apacheExtUserObject, but also with +classic posixAccount/Group, probably with use of other excellent modules +like mod_authz_ldap and others.. +* testing with apache 2.2.x + +* testers are welcomed, probably some nullpointer and overflows possibility +extists, anyway Apache The Greate works holds the line - I tested some +generated module segfaults, and they doesn't break apache itself, module only. \ No newline at end of file diff --git a/Makefile b/Makefile index 546a6d6..74d42f0 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ VERSION=`cat VERSION` DISTFILES=`cat FILES` all: mod_vhost_ldap.o + install: $(APXS) -i mod_vhost_ldap.la @@ -16,9 +17,17 @@ clean: rm -rf mod_vhost_ldap-$(VERSION) rm -rf mod_vhost_ldap-$(VERSION).tar.gz + mod_vhost_ldap.o: mod_vhost_ldap.c + $(APXS) -Wc,-Wall -Wc,-Werror -Wc,-g -Wc,-DDEBUG -Wc,-DMOD_VHOST_LDAP_VERSION=\\\"mod_vhost_ldap/$(VERSION)\\\" -c -lldap_r mod_vhost_ldap.c +encclean: + rm enc + +encrypt: + gcc -Wall encrypt.c -o enc -lcrypt + deb: make clean svn export svn+ssh://ondrej@svn.debian.org/svn/modvhostldap mod-vhost-ldap-`cat VERSION`.orig; /usr/bin/pdebuild --configfile /home/ondrej/.pbuilderrc.unstable @@ -34,4 +43,4 @@ archive: format: indent *.c -.PHONY: all install clean archive format +.PHONY: all install clean archive format encrypt encclean diff --git a/README b/README index 88e8ed7..9121929 100644 --- a/README +++ b/README @@ -1,6 +1,7 @@ mod-vhost-ldap is Apache 2.x module for storing and configuring Virtual Hosts from LDAP. It supports DocumentRoot, ScriptAlias, ServerName, ServerAlias, ServerAdmin and SuexecUserGroup directives. + Access control comes with module version 2.x . It's build on top of mod_ldap, so it uses it's caching capabilities and can be used with threaded apache. diff --git a/TODO b/TODO index 4135597..08692fc 100644 --- a/TODO +++ b/TODO @@ -1 +1,15 @@ * Put back TLS +* general code review (use of per-directory-config ?) +* implement php_admin_flag and php_admin_value setting for vhosts with ldap +* implement directory access control, similar to location +* implement directory/location aliasing between vhosts, based on ldap +* implement logging-related directives for ldap-based vhosts +* implement require group +* implement use of other authentication methods than basic, including X509, +and authentication based not only with apacheExtUserObject, but also with +classic posixAccount/Group, probably with use of other excellent modules +like mod_authz_ldap and others.. +* testing with apache 2.2.x +* testers are welcomed, probably some nullpointer and overflows possibility +extists, anyway Apache The Greate works holds the line - I tested some +generated module segfaults, and they doesn't break apache itself, module only. diff --git a/VERSION b/VERSION index 3eefcb9..227cea2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0 +2.0.0 diff --git a/encrypt.c b/encrypt.c new file mode 100644 index 0000000..c670634 --- /dev/null +++ b/encrypt.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include + +static void to64(char *s, unsigned long v, int n) +{ + static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +static char *htenc(const char *clearpasswd) { + char *res; + char salt[9]; + (void) srand((int) time((time_t *) NULL)); + to64(&salt[0], rand(), 8); + salt[8] = '\0'; + res = crypt(clearpasswd, salt); + return res; +} + +int main() { + char *orig = "abcd"; + printf("Orig: |%s| \n", orig); + char *enc = htenc(orig); + printf("Enc: |%s| \n", enc); + return 1; + +} + + diff --git a/examples/slapd.conf b/examples/slapd.conf new file mode 100644 index 0000000..8cbcf4c --- /dev/null +++ b/examples/slapd.conf @@ -0,0 +1,68 @@ +TLSCipherSuite HIGH:MEDIUM:+SSLv3 +TLSCertificateFile /etc/ldap/TLS/ldapserver.crt +TLSCertificateKeyFile /etc/ldap/TLS/ldapserver.key +TLSCACertificateFile /etc/ldap/TLS/ca.crt + +allow bind_v2 +allow update_anon + +include /etc/ldap/schema/core.schema +include /etc/ldap/schema/cosine.schema +include /etc/ldap/schema/nis.schema +include /etc/ldap/schema/inetorgperson.schema +include /etc/ldap/schema/dnsdomain2.schema +include /etc/ldap/schema/sendmail.schema +include /etc/ldap/schema/misc.schema +include /etc/ldap/schema/ISPEnv2.schema +include /etc/ldap/schema/local.schema +include /etc/ldap/schema/mod_vhost_ldap.schema +include /home/pwadas/workspace/mod-vhost-ldap/apache_ext.schema +#include /etc/ldap/schema/samba.schema + +pidfile /var/run/slapd/slapd.pid +argsfile /var/run/slapd.args +modulepath /usr/lib/ldap +moduleload back_bdb +backend bdb +schemacheck on + +checkpoint 512 30 + +#sumuja sie - np. 512+128 +# 1 trace function calls +# 2 debug packet handling +# 4 heavy trace debugging +# 8 connection management +# 16 print out packets sent and received +# 32 search filter processing +# 64 configuration file processing +# 128 access control list processing +# 256 stats log connections/operations/results +# 512 stats log entries sent +# 1024 print communication with shell backends +# 2048 entry parsing + +loglevel 256 +#loglevel 0 + +database bdb +lastmod on +suffix "dc=ROOT" +directory "/var/lib/ldap" + +index default pres,eq,sub +index uniqueMember,member pres +index cn,sn,uid,associatedDomain,memberUid,domainUid,commonUid,gecos,businessCategory pres,eq,sub +index customerName,customerCompanyName,customerDescription,customerCity,customerRegion,customerResponsiblePerson pres,eq,sub +index objectClass,homeDirectory,loginShell,uidNumber,gidNumber,customerID,authorizedService,customerRole,customerSupportCode,pTRRecord,ipHostNumber pres,eq +index MXRecord,NSRecord,SOARecord,ARecord,MDRecord,CNAMERecord,DNSTTL,DNSClass,HINFORecord,MINFORecord,TXTRecord,SIGRecord,KEYRecord,AAAARecord pres,eq +index resellerName,resellerCompanyName,resellerDescription,resellerCity,resellerRegion,resellerResponsiblePerson pres,eq,sub +index resellerID,resellerRole,resellerSupportCode pres,eq +index sendmailMTAHost,sendmailMTAAliasGrouping,sendmailMTAKey,sendmailMTAMapName,sendmailMTAMapValue,sendmailMTAClassName,sendmailMTAClassValue pres,eq +index apacheServerName,apacheServerAlias,apacheDocumentRoot,apacheServerAdmin pres,eq +index apacheExtConfigUri,apacheExtConfigServerName pres,eq,sub +index apacheLocationOptionsDn,apacheExtConfigRequireValidUser,apacheExtConfigUserDn,apacheExtConfigUserServerName,apacheExtConfigObjectName pres,eq +index vacationActive eq + +access to * + by * write diff --git a/examples/vhost_ldap.conf b/examples/vhost_ldap.conf new file mode 100644 index 0000000..36c73e9 --- /dev/null +++ b/examples/vhost_ldap.conf @@ -0,0 +1,17 @@ +# +# mod_vhost_ldap allows you to keep your virtual host configuration +# in an LDAP directory and update it in nearly realtime. +# + +### NOTE ### +### mod_vhost_ldap depends on mod_ldap ### +### you have to enable mod_ldap as well ### + +LoadModule vhost_ldap_module modules/mod_vhost_ldap.so + + + VhostLDAPEnabled on + VhostLDAPUrl "ldap://127.0.0.1/ou=vhosts,ou=web,dc=localhost" + VhostLdapBindDN "cn=admin,dc=localhost" + VhostLDAPBindPassword "changeme" + diff --git a/mod_vhost_ldap.c b/mod_vhost_ldap.c index ff8a61d..1d81bb7 100644 --- a/mod_vhost_ldap.c +++ b/mod_vhost_ldap.c @@ -1,5 +1,5 @@ /* ============================================================ - * Copyright (c) 2003-2004, Ondrej Sury + * Copyright (c) 2003-2006, Ondrej Sury, Piotr Wadas * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,13 +16,42 @@ * */ +/* NOTE: only static members must be "used" to build, so for time-to-time used routines we don't declare static */ + /* * mod_vhost_ldap.c --- read virtual host config from LDAP directory + * version 2.0 - included ldap-based basic auth & authz */ -#define CORE_PRIVATE +//remember to add "-lcrypt" in Makefile if there's a need to generate new password +// for now not needed (validation only), this below is almost copy-paste from apache source, htpasswd.c +/* + +#include "crypt.h" +#include "time.h" + +void to64(char *s, unsigned long v, int n) +{ + static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +char *htenc(const char *clearpasswd) { + char *res; + char salt[9]; + (void) srand((int) time((time_t *) NULL)); + to64(&salt[0], rand(), 8); + salt[8] = '\0'; + res = crypt(clearpasswd, salt); + return res; +} -#include +*/ + +#define CORE_PRIVATE #include "httpd.h" #include "http_config.h" @@ -33,9 +62,12 @@ #include "apr_strings.h" #include "apr_reslist.h" #include "util_ldap.h" +#include "apr_md5.h" +#include "apr_sha1.h" +#include "unistd.h" #ifndef APU_HAS_LDAP -#error mod_vhost_ldap requires APR-util to have LDAP support built in +#fatal "mod_vhost_ldap requires APR util to have LDAP support built in" #endif #if !defined(WIN32) && !defined(OS2) && !defined(BEOS) && !defined(NETWARE) @@ -43,579 +75,972 @@ #endif #ifdef HAVE_UNIX_SUEXEC -#include "unixd.h" /* Contains the suexec_identity hook used on Unix */ +#include "unixd.h" /* Contains the suexec_identity hook used on Unix */ #endif +/* do not accept empty "" strings */ +#define strtrue(s) (s && *s) + #define MIN_UID 100 #define MIN_GID 100 +#define FILTER_LENGTH MAX_STRING_LEN module AP_MODULE_DECLARE_DATA vhost_ldap_module; -typedef enum { - MVL_UNSET, MVL_DISABLED, MVL_ENABLED +typedef enum mod_vhost_ldap_status_e { + MVL_UNSET, + MVL_DISABLED, + MVL_ENABLED } mod_vhost_ldap_status_e; - typedef struct mod_vhost_ldap_config_t { - mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */ + mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */ + + char *url; /* String representation of LDAP URL */ + char *host; /* Name of the LDAP server (or space separated list) */ + int port; /* Port of the LDAP server */ + char *basedn; /* Base DN to do all searches from */ + int scope; /* Scope of the search */ + char *filter; /* Filter to further limit the search */ + deref_options deref; /* how to handle alias dereferening */ + char *binddn; /* DN to bind to server (can be NULL) */ + char *bindpw; /* Password to bind to server (can be NULL) xx */ + int have_deref; /* Set if we have found an Deref option */ + int have_ldap_url; /* Set if we have found an LDAP url */ + char *wlcbasedn; /* Base DN to do all location config searches */ + char *wucbasedn; /* Base DN to do all webuser config searches */ + int secure; /* True if SSL connections are requested */ +} mod_vhost_ldap_config_t; +typedef struct mod_vhost_ldap_request_t { + char *dn; /* The saved dn from a successful search */ + char *name; /* apacheServerName */ + char *admin; /* apacheServerAdmin */ + char *docroot; /* apacheDocumentRoot */ + char *uid; /* Suexec Uid */ + char *gid; /* Suexec Gid */ + int has_reqlines; /* placeholder */ + apr_array_header_t *serveralias; /* apacheServerAlias */ + apr_array_header_t *rqlocationlines; /* apacheServerAlias */ - /* These parameters are all derived from the VhostLDAPURL directive */ - char *url; /* String representation of LDAP URL */ +} mod_vhost_ldap_request_t; +typedef struct mod_vhost_ldap_extconfig_object_t { /* what the hell this "t" means ??. eh, whatever ;) */ + //we use apr_array_header_t for multi-value attributed, parsed later (yuck!) from grr ";" separated string + char *extconfname; /* apacheExtConfigObjectName, single-value, syntax SUP cn */ + char *exturi; /* apacheExtConfigUri, single-value, uri for which this settings are here + * should be used in combine with extconfig server name */ + int extconftype; /* apacheExtConfigRequireValidUser, single-value bool, + * if TRUE then require valid-user, if FALSE userlist-type config + */ + + apr_array_header_t *extservername; /* apacheExtConfigServerName",MULTI-value, + * e.g. for http://anyserver/statistics (?), syntax SUP cn + */ + apr_array_header_t *extusers; /* "apacheExtConfigUserDn", MULTI-value, syntax SUP DN */ + +} mod_vhost_ldap_extconfig_object_t; +typedef struct mod_vhost_ldap_webuser_t { + + char *webusername; /* apacheExtConfigUserName, single-value */ + apr_array_header_t *webuserpassword; /* userPassword, multi-value */ + char *webuserserver; /* apacheExtConfigUserServerName, server of this user, multi-value */ + +} mod_vhost_ldap_webuser_t; +static int strschrcount(apr_pool_t * p, const char *src, const char *delim) +{ + int i = 1; + int x = 0; + while(*src++) { + if(strcasecmp(apr_pstrndup(p, src, i), (char *) delim) == 0) { + x++; + } + } + return x; +} +void log_dump_apr_array(request_rec * r, apr_array_header_t * arr, const char *prefix) +{ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering log_dump_apr_array"); + int x = 0; + char **aliases = (char **) arr->elts; + for (x = 0; x < arr->nelts; x++) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " log_dump_apr_array val %d %s %s", x, prefix, aliases[x]); + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving log_dump_apr_array"); +} +static apr_array_header_t *get_parsed_string_atrr_arr(request_rec * r, const char *server_alias_attrvar_line, + const char *delim) +{ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering get_parsed_string_atrr_arr |%s|", server_alias_attrvar_line); + if(server_alias_attrvar_line) { - char *host; /* Name of the LDAP server (or space separated list) */ - int port; /* Port of the LDAP server */ - char *basedn; /* Base DN to do all searches from */ - int scope; /* Scope of the search */ - char *filter; /* Filter to further limit the search */ - deref_options deref; /* how to handle alias dereferening */ + apr_collapse_spaces((char *) server_alias_attrvar_line, server_alias_attrvar_line); + int ccount = strschrcount(r->pool, server_alias_attrvar_line, delim) + 1; - char *binddn; /* DN to bind to server (can be NULL) */ - char *bindpw; /* Password to bind to server (can be NULL) */ + apr_array_header_t *aliases_arr = apr_array_make(r->pool, ccount, sizeof(char *)); + char **curralias; + curralias = (char **) apr_array_push(aliases_arr); - int have_deref; /* Set if we have found an Deref option */ - int have_ldap_url; /* Set if we have found an LDAP url */ + char *curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';'); + char *tmp = apr_pstrdup(r->pool, (char *) curr_server_alias);; + *curralias = tmp; - int secure; /* True if SSL connections are requested */ - char *fallback; /* Fallback virtual host */ + while(server_alias_attrvar_line[0]) { + curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';'); + curralias = (char **) apr_array_push(aliases_arr); + tmp = apr_pstrdup(r->pool, (char *) curr_server_alias); + *curralias = tmp; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr OK"); + return aliases_arr; + } + else + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr NULL"); + return NULL; +} +static apr_array_header_t *get_ap_reqs(apr_pool_t * p, mod_vhost_ldap_extconfig_object_t * extreqc, + char *mainservername, char *userlist) +{ -} mod_vhost_ldap_config_t; + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," get_ap_reqs Entering"); -typedef struct mod_vhost_ldap_request_t { - char *dn; /* The saved dn from a successful search */ - char *name; /* ServerName */ - char *admin; /* ServerAdmin */ - char *docroot; /* DocumentRoot */ - char *cgiroot; /* ScriptAlias */ - char *uid; /* Suexec Uid */ - char *gid; /* Suexec Gid */ -} mod_vhost_ldap_request_t; + apr_array_header_t *res = apr_array_make(p, 2, sizeof(require_line)); -char *attributes[] = - { "apacheServerName", "apacheDocumentRoot", "apacheScriptAlias", "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", 0 }; + require_line *rline; + apr_int64_t limited = -1; -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 */ - if (ap_find_linked_module("util_ldap.c") == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s, - "Module mod_ldap missing. Mod_ldap (aka. util_ldap) " - "must be loaded in order for mod_vhost_ldap to function properly"); - return HTTP_INTERNAL_SERVER_ERROR; + rline = (require_line *) apr_array_push(res); - } + //currently we don't support playing with request types + rline->method_mask = limited; - ap_add_version_component(p, MOD_VHOST_LDAP_VERSION); + if(extreqc->extconftype == 1) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = TRUE server %s",mainservername); + rline->requirement = apr_pstrdup(p, (char *) "valid-user"); + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = FALSE server %s",mainservername); + + rline->requirement = apr_pstrdup(p, userlist); + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," Leaving get_ap_reqs, returning require line |require %s|", rline->requirement); + return res; +} +static void mod_vhost_ldap_dovhostconfig(request_rec * r, char *attributes[], const char **vals, + mod_vhost_ldap_request_t * reqc) +{ - return OK; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " dovhostconfig Entering "); + int i = 0; + while(attributes[i]) { + + if(strcasecmp(attributes[i], "apacheServerName") == 0) { + reqc->name = apr_pstrdup(r->pool, vals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d apacheServerName %s", i, reqc->name); + } + + if(strcasecmp(attributes[i], "apacheServerAdmin") == 0) { + reqc->admin = apr_pstrdup(r->pool, vals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheServerAdmin %s", i, reqc->admin); + } + + if(strcasecmp(attributes[i], "apacheDocumentRoot") == 0) { + reqc->docroot = apr_pstrdup(r->pool, vals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheDocumentRoot %s", i, reqc->docroot); + } + + if(strcasecmp(attributes[i], "apacheSuexecUid") == 0) { + reqc->uid = apr_pstrdup(r->pool, vals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheSuexecUid %s", i, reqc->uid); + } + + if(strcasecmp(attributes[i], "apacheSuexecGid") == 0) { + reqc->gid = apr_pstrdup(r->pool, vals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheSuexecGid %s", i, reqc->gid); + } + + if(strcasecmp(attributes[i], "apacheExtConfigHasRequireLine") == 0) { + if(vals[i]) { + reqc->has_reqlines = strcasecmp("TRUE", apr_pstrdup(r->pool, vals[i])) == 0 ? 1 : 0; + + if(reqc->has_reqlines) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d Vhost %s has extended access configuration", i, reqc->name); + } + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d Vhost %s doesn't have extended access configuration", i, reqc->name); + } + } + + if(strcasecmp(attributes[i], "apacheServerAlias") == 0) { + if(vals[i]) { + reqc->serveralias = + (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], + (const char *) ";"); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheServerAlias is set", i); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d No apacheServerAlias for this vhost found", i); + reqc->serveralias = NULL; + } + } + + if(strcasecmp(attributes[i], "apacheLocationOptionsDn") == 0) { + if(vals[i]) { + reqc->rqlocationlines = + (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], + (const char *) ";"); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheLocationOptionsDn is set", i); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " host %s marked ext-configured but no attributes pointing extConfig !! ldap scheme should avoid it !!", reqc->name); + reqc->rqlocationlines = NULL; + } + } + i++; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " dovhostconfig Leaving "); } +static void mod_vhost_ldap_doextconfig(request_rec * r, char *extconfigattributes[], const char **extconfvals, + mod_vhost_ldap_extconfig_object_t * extreqc) +{ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextconfig Entering "); + int i = 0; -static void * -mod_vhost_ldap_create_server_config (apr_pool_t *p, server_rec *s) + while(extconfigattributes[i]) { + if(strcasecmp(extconfigattributes[i], "apacheExtConfigObjectName") == 0) { + extreqc->extconfname = apr_pstrdup(r->pool, extconfvals[i]); + } + + if(strcasecmp(extconfigattributes[i], "apacheExtConfigUri") == 0) { + extreqc->exturi = apr_pstrdup(r->pool, extconfvals[i]); + } + + if(strcasecmp(extconfigattributes[i], "apacheExtConfigRequireValidUser") == 0) { + if(extconfvals[i]) { + + //this value determines whether we have "require valid-user" object (TRUE) , + //or (FALSE) object "require user johny mary dorothy witch" + //here set retrieved value, regardless what it is, to play with it later. + extreqc->extconftype = + strcasecmp("TRUE", apr_pstrdup(r->pool, extconfvals[i])) == 0 ? 1 : 0; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Set require valid-user to %d (%s)", extreqc->extconftype, (char *) apr_pstrdup(r->pool, extconfvals[i])); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " For this ext config require valid-user is not set"); + } + } + + if(strcasecmp(extconfigattributes[i], "apacheExtConfigServerName") == 0) { + + if(extconfvals[i]) { + extreqc->extservername = + (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], + (const char *) ";"); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + " No ExtServerName values found"); + extreqc->extservername = NULL; + } + } + + if(strcasecmp(extconfigattributes[i], "apacheExtConfigUserDn") == 0) { + + if(extconfvals[i]) { + extreqc->extusers = + (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], + (const char *) ";"); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + " apacheExtConfigUserDn values NOT found (any valid-user or no users specified."); + extreqc->extusers = NULL; + } + } + + i++; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextconfig Leaving "); +} +static void mod_vhost_ldap_doextuserconfig(request_rec * r, char *ldap_webuser_attributes[], const char **extuservals, + mod_vhost_ldap_webuser_t * extuserreqc) { - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof (mod_vhost_ldap_config_t)); - - conf->enabled = MVL_UNSET; - conf->have_ldap_url = 0; - conf->have_deref = 0; - conf->binddn = NULL; - conf->bindpw = NULL; - conf->deref = always; - conf->fallback = NULL; - - return conf; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextuserconfig Entering"); + int i = 0; + while(ldap_webuser_attributes[i]) { + if(strcasecmp(ldap_webuser_attributes[i], "apacheExtConfigUserName") == 0) { + extuserreqc->webusername = apr_pstrdup(r->pool, extuservals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "%d apacheExtConfigUserName set to %s", i, extuserreqc->webusername); + } + if(strcasecmp(ldap_webuser_attributes[i], "apacheExtConfigUserServerName") == 0) { + extuserreqc->webuserserver = apr_pstrdup(r->pool, extuservals[i]); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "%d apacheExtConfigUserServerName set to %s", i, extuserreqc->webuserserver); + } + if(strcasecmp(ldap_webuser_attributes[i], "userPassword") == 0) { + extuserreqc->webuserpassword = + (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], + (const char *) ";"); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "%d userPassword retrievied", i); + } + i++; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextuserconfig Leaving"); } +static int mod_vhost_ldap_authenticate_basic_user(request_rec * r) +{ + const char *sent_pw; + mod_vhost_ldap_webuser_t *extuserreqc; + extuserreqc = (mod_vhost_ldap_webuser_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_webuser_t)); + int rc = ap_get_basic_auth_pw(r, &sent_pw); + if(rc != OK) + return rc; + if(strtrue(r->user) && strtrue(sent_pw)) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering mod_vhost_ldap_authenticate_basic_user"); + + char userfilter[FILTER_LENGTH]; + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); + + const char *dn = NULL; + util_ldap_connection_t *ldc = NULL; + const char **extuservals = NULL; + int result = 0; + char *ldap_webuser_attributes[] = + { "apacheExtConfigUserName", "apacheExtConfigUserServerName", "userPassword", 0 }; + + apr_snprintf(userfilter, FILTER_LENGTH, "(&(apacheExtConfigUserName=%s)(apacheExtConfigUserServerName=%s))", r->user,r->server->server_hostname); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " AuthUser search filter: %s", userfilter); + ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, conf->deref, + conf->secure); + result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wucbasedn, conf->scope, + ldap_webuser_attributes, userfilter, &dn, &extuservals); + util_ldap_connection_close(ldc); + + if(extuservals) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " User %s found.", r->user); + + mod_vhost_ldap_doextuserconfig(r, ldap_webuser_attributes, extuservals, extuserreqc); + + int x = 0; + char **passwords = (char **) extuserreqc->webuserpassword->elts; + for (x = 0; x < extuserreqc->webuserpassword->nelts; x++) { + if ( ( apr_password_validate(sent_pw, passwords[x]) == OK) || strcasecmp(sent_pw,passwords[x]) == 0 ) { + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Authentication for user %s at %s successful.", extuserreqc->webusername, r->server->server_hostname); + return OK; + } + } + + } + else { + ap_log_rerror(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, r, " User %s at %s not found", extuserreqc->webusername, r->server->server_hostname); + return HTTP_UNAUTHORIZED; + } + } + else { + ap_note_basic_auth_failure(r); + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, + ": Both a username and password must be provided : authentication for user %s at %s failed.", + extuserreqc->webusername, r->server->server_hostname); + return HTTP_UNAUTHORIZED; + } + ap_note_basic_auth_failure(r); + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "Authentication for user %s at %s failed.", + extuserreqc->webusername, r->server->server_hostname); + return HTTP_UNAUTHORIZED; -static void * -mod_vhost_ldap_merge_server_config(apr_pool_t *p, void *parentv, void *childv) +} +static int check_mod_vhost_ldap_auth_require(char *user, const char *t, request_rec * r) { - mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv; - mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv; - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t)); - - if (child->enabled == MVL_UNSET) { - conf->enabled = parent->enabled; - } else { - conf->enabled = child->enabled; - } + const char *w; + w = ap_getword(r->pool, &t, ' '); + if(!strcmp(w, "valid-user")) { - if (child->have_ldap_url) { - conf->have_ldap_url = child->have_ldap_url; - conf->url = child->url; - conf->host = child->host; - conf->port = child->port; - conf->basedn = child->basedn; - conf->scope = child->scope; - conf->filter = child->filter; - conf->secure = child->secure; - } else { - conf->have_ldap_url = parent->have_ldap_url; - conf->url = parent->url; - conf->host = parent->host; - conf->port = parent->port; - conf->basedn = parent->basedn; - conf->scope = parent->scope; - conf->filter = parent->filter; - conf->secure = parent->secure; - } - if (child->have_deref) { - conf->have_deref = child->have_deref; - conf->deref = child->deref; - } else { - conf->have_deref = parent->have_deref; - conf->deref = parent->deref; - } + return OK; + } - conf->binddn = (child->binddn ? child->binddn : parent->binddn); - conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw); + if(!strcmp(w, "user")) { + while(t[0]) { + w = ap_getword_conf(r->pool, &t); + if(!strcmp(user, w)) { - conf->fallback = (child->fallback ? child->fallback : parent->fallback); + return OK; - return conf; -} + } + } + return HTTP_UNAUTHORIZED; + } + else { -/* - * Use the ldap url parsing routines to break up the ldap url into - * host and port. - */ -static const char *mod_vhost_ldap_parse_url(cmd_parms *cmd, - void *dummy, - const char *url) + return HTTP_INTERNAL_SERVER_ERROR; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + ": %s : Reached end of check_mod_vhost_ldap_auth_require!", r->server->server_hostname); + return HTTP_INTERNAL_SERVER_ERROR; +} +static int mod_vhost_ldap_check_auth(request_rec * r) { - int result; - apr_ldap_url_desc_t *urld; - - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: `%s'", - url); - - 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"; - } - } - conf->url = apr_pstrdup(cmd->pool, url); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: Host: %s", urld->lud_host); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: Port: %d", urld->lud_port); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: DN: %s", urld->lud_dn); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: attrib: %s", urld->lud_attrs? urld->lud_attrs[0] : "(null)"); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: scope: %s", - (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" : - urld->lud_scope == LDAP_SCOPE_BASE? "base" : - urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown")); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[mod_vhost_ldap.c] url parse: filter: %s", urld->lud_filter); - - /* Set all the values, or at least some sane defaults */ - if (conf->host) { - char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2); - strcpy(p, urld->lud_host); - strcat(p, " "); - strcat(p, conf->host); - conf->host = p; - } - else { - conf->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost"; - } - conf->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; - - conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? - LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; - - if (urld->lud_filter) { - if (urld->lud_filter[0] == '(') { - /* - * Get rid of the surrounding parens; later on when generating the - * filter, they'll be put back. - */ - conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1); - conf->filter[strlen(conf->filter)-1] = '\0'; - } - else { - conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter); - } - } - else { - conf->filter = "objectClass=apacheConfig"; - } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + ": mod_vhost_ldap_check_auth, parsing existing ap_requires for %s at %s ", r->user, r->server->server_hostname); + char *user = r->user; + int rv; + register int x; + const char *t; + const apr_array_header_t *reqs_arr = ap_requires(r); + + require_line *reqs; + reqs = (require_line *) reqs_arr->elts; + + for (x = 0; x < reqs_arr->nelts; x++) { + t = reqs[x].requirement; + if((rv = check_mod_vhost_ldap_auth_require(user, t, r)) != HTTP_UNAUTHORIZED) { + return rv; + } + } - /* "ldaps" indicates secure ldap connections desired - */ - if (strncasecmp(url, "ldaps", 5) == 0) - { - conf->secure = 1; - conf->port = urld->lud_port? urld->lud_port : LDAPS_PORT; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "LDAP: vhost_ldap using SSL connections"); - } - else - { - conf->secure = 0; - conf->port = urld->lud_port? urld->lud_port : LDAP_PORT; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "LDAP: vhost_ldap not using SSL connections"); - } - conf->have_ldap_url = 1; - apr_ldap_free_urldesc(urld); - return NULL; + ap_note_basic_auth_failure(r); + return HTTP_UNAUTHORIZED; } +static void *mod_vhost_ldap_create_server_config(apr_pool_t * p, server_rec * s) +{ -static const char *mod_vhost_ldap_set_enabled(cmd_parms *cmd, void *dummy, int enabled) + mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *) apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t)); + conf->enabled = MVL_UNSET; + conf->have_ldap_url = 0; + conf->have_deref = 0; + conf->binddn = NULL; + conf->bindpw = NULL; + conf->deref = always; + conf->wlcbasedn = NULL; + conf->wucbasedn = NULL; + + return conf; +} +static void *mod_vhost_ldap_merge_server_config(apr_pool_t * p, void *parentv, void *childv) { - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv; + mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv; + mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *) apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t)); + + conf->enabled = (child->enabled == MVL_UNSET ? parent->enabled : child->enabled); + + if(child->have_ldap_url) { + conf->have_ldap_url = child->have_ldap_url; + conf->url = child->url; + conf->host = child->host; + conf->port = child->port; + conf->basedn = child->basedn; + conf->scope = child->scope; + conf->filter = child->filter; + conf->secure = child->secure; + conf->wlcbasedn = child->wlcbasedn; + conf->wucbasedn = child->wucbasedn; + } + else { + conf->have_ldap_url = parent->have_ldap_url; + conf->url = parent->url; + conf->host = parent->host; + conf->port = parent->port; + conf->basedn = parent->basedn; + conf->scope = parent->scope; + conf->filter = parent->filter; + conf->secure = parent->secure; + conf->wlcbasedn = parent->wlcbasedn; + conf->wucbasedn = parent->wucbasedn; - conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED; + } + if(child->have_deref) { + conf->have_deref = child->have_deref; + conf->deref = child->deref; + } + else { + conf->have_deref = parent->have_deref; + conf->deref = parent->deref; + } - return NULL; + conf->binddn = (child->binddn ? child->binddn : parent->binddn); + conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw); + return conf; } - -static const char *mod_vhost_ldap_set_binddn(cmd_parms *cmd, void *dummy, const char *binddn) +static const char *mod_vhost_ldap_parse_url(cmd_parms * cmd, void *dummy, const char *url) { - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + int result; + apr_ldap_url_desc_t *urld; + + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + + 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"; + } + } + conf->url = apr_pstrdup(cmd->pool, url); + + /* Set all the values, or at least some sane defaults */ + if(conf->host) { + char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2); + strcpy(p, urld->lud_host); + strcat(p, " "); + strcat(p, conf->host); + conf->host = p; + } + else { + conf->host = urld->lud_host ? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost"; + } + conf->basedn = urld->lud_dn ? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; + + conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; + + if(urld->lud_filter) { + if(urld->lud_filter[0] == '(') { + /* + * Get rid of the surrounding parens; later on when generating the + * filter, they'll be put back. + */ + conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter + 1); + conf->filter[strlen(conf->filter) - 1] = '\0'; + } + else { + conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter); + } + } + else { + conf->filter = "objectClass=apacheConfig"; + } - conf->binddn = apr_pstrdup(cmd->pool, binddn); - return NULL; -} + /* "ldaps" indicates secure ldap connections desired + */ + if(strncasecmp(url, "ldaps", 5) == 0) { + conf->secure = 1; + conf->port = urld->lud_port ? urld->lud_port : LDAPS_PORT; -static const char *mod_vhost_ldap_set_bindpw(cmd_parms *cmd, void *dummy, const char *bindpw) -{ - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(cmd->server->module_config, - &vhost_ldap_module); + } + else { + conf->secure = 0; + conf->port = urld->lud_port ? urld->lud_port : LDAP_PORT; + } - conf->bindpw = apr_pstrdup(cmd->pool, bindpw); - return NULL; + conf->have_ldap_url = 1; + apr_ldap_free_urldesc(urld); + return NULL; } - -static const char *mod_vhost_ldap_set_deref(cmd_parms *cmd, void *dummy, const char *deref) +static const char *mod_vhost_ldap_set_enabled(cmd_parms * cmd, void *dummy, int enabled) { - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config (cmd->server->module_config, - &vhost_ldap_module); - - if (strcmp(deref, "never") == 0 || strcasecmp(deref, "off") == 0) { - conf->deref = never; - conf->have_deref = 1; - } - else if (strcmp(deref, "searching") == 0) { - conf->deref = searching; - conf->have_deref = 1; - } - else if (strcmp(deref, "finding") == 0) { - conf->deref = finding; - conf->have_deref = 1; - } - else if (strcmp(deref, "always") == 0 || strcasecmp(deref, "on") == 0) { - conf->deref = always; - conf->have_deref = 1; - } - else { - return "Unrecognized value for VhostLDAPAliasDereference directive"; - } - return NULL; + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED; + return NULL; } - -static const char *mod_vhost_ldap_set_fallback(cmd_parms *cmd, void *dummy, const char *fallback) +static const char *mod_vhost_ldap_set_binddn(cmd_parms * cmd, void *dummy, const char *binddn) +{ + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + conf->binddn = apr_pstrdup(cmd->pool, binddn); + return NULL; +} +static const char *mod_vhost_ldap_set_wucbasedn(cmd_parms * cmd, void *dummy, const char *wucbasedn) +{ + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + conf->wucbasedn = apr_pstrdup(cmd->pool, wucbasedn); + return NULL; +} +static const char *mod_vhost_ldap_set_wlcbasedn(cmd_parms * cmd, void *dummy, const char *wlcbasedn) { - 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; + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + conf->wlcbasedn = apr_pstrdup(cmd->pool, wlcbasedn); + return NULL; +} +static const char *mod_vhost_ldap_set_bindpw(cmd_parms * cmd, void *dummy, const char *bindpw) +{ + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + conf->bindpw = apr_pstrdup(cmd->pool, bindpw); + return NULL; +} +static const char *mod_vhost_ldap_set_deref(cmd_parms * cmd, void *dummy, const char *deref) +{ + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); + if(deref) { + if(strcmp(deref, "never") == 0 || strcmp(deref, "searching") == 0 || strcmp(deref, "finding") == 0 + || strcmp(deref, "always") == 0) { + conf->deref = *deref; + conf->have_deref = 1; + } + else { + return "Unrecognized value for VhostLDAPAliasDereference directive"; + } + } + 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" - "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n" - "
    \n" - "
  • Host is the name of the LDAP server. Use a space separated list of hosts \n" - "to specify redundant servers.\n" - "
  • Port is optional, and specifies the port to connect to.\n" - "
  • basedn specifies the base DN to start searches from\n" - "
\n"), - - AP_INIT_TAKE1 ("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF, - "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."), - - AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF, - "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."), - - AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF, - "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"), - - AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF, - "Determines how aliases are handled during a search. Can be one of the" - "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; - char filtbuf[FILTER_LENGTH]; - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, &vhost_ldap_module); - core_server_config * core = - (core_server_config *) ap_get_module_config(r->server->module_config, &core_module); - util_ldap_connection_t *ldc = NULL; - int result = 0; - const char *dn = NULL; - char *cgi; - const char *hostname = NULL; - int is_fallback = 0; - - 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, reqc); - - // mod_vhost_ldap is disabled or we don't have LDAP Url - if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) { - return DECLINED; - } + char filtbuf[FILTER_LENGTH]; + char extconffiltbuf[FILTER_LENGTH]; + apr_table_t *e; + request_rec *top; + mod_vhost_ldap_config_t *conf; + mod_vhost_ldap_request_t *reqc; + mod_vhost_ldap_extconfig_object_t *extreqc; + core_server_config *core; + + util_ldap_connection_t *ldc = NULL; + const char **vals, **extconfvals = NULL; + const char *dn = NULL; + const char *hostname = NULL; + int failures = 0; + int i = 0; + int result = 0; -start_over: + /* + * more info about attributes in typedefs definitions and schema desc + * PS. Did You ever wonder why they used this damned weird "\0", instead, + * let's say, '$' or 'EndOfWord' or whatever ?? + */ - if (conf->host) { - ldc = util_ldap_connection_find(r, conf->host, conf->port, - conf->binddn, conf->bindpw, conf->deref, - conf->secure); - } - else { - ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, - "[mod_vhost_ldap.c] translate: no conf->host - weird...?"); - return DECLINED; - } + char *attributes[] = { "apacheServerName", "apacheServerAlias", "apacheDocumentRoot", + "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", + "apacheExtConfigHasRequireLine", "apacheLocationOptionsDn", + 0 + }; - hostname = r->hostname; + char *extconfigattributes[] = { "apacheExtConfigUri", "apacheExtConfigRequireValidUser", + "apacheExtConfigServerName", "apacheExtConfigObjectName", + "apacheExtConfigUserDn", + 0 + }; -fallback: + //we assume we're in trouble, and will change it, if not. + result = LDAP_SERVER_DOWN; - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[mod_vhost_ldap.c]: translating %s", r->uri); + top = r->main ? r->main : r; + hostname = r->hostname; - apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, hostname, hostname); + //get our module config options + conf = (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); - result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, - attributes, filtbuf, &dn, &vals); + //a reference to core config + core = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module); - util_ldap_connection_close(ldc); + //and some variable initialization + reqc = (mod_vhost_ldap_request_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t)); + extreqc = (mod_vhost_ldap_extconfig_object_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_extconfig_object_t)); - /* sanity check - if server is down, retry it up to 5 times */ - if (result == LDAP_SERVER_DOWN) { - if (failures++ <= 5) { - goto start_over; - } - } + //current request config get set + ap_set_module_config(r->request_config, &vhost_ldap_module, reqc); - 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; + // mod_vhost_ldap is disabled or we don't have LDAP Url + if((conf->enabled != MVL_ENABLED) || (!conf->have_ldap_url)) { + return DECLINED; } - ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, - "[mod_vhost_ldap.c] translate: " - "virtual host %s not found", - hostname); + if(conf->host) { - return DECLINED; - } + apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", + conf->filter, hostname, hostname); - /* 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; virtual host %s; URI %s [%s]", - hostname, r->uri, ldap_err2string(result)); - return DECLINED; - } + while(failures++ <= 5 && result == LDAP_SERVER_DOWN) { + //searching for connection + ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, + conf->deref, conf->secure); + result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, attributes, + filtbuf, &dn, &vals); + util_ldap_connection_close(ldc); + } + } + else { + return DECLINED; + } - /* mark the user and DN */ - reqc->dn = apr_pstrdup(r->pool, dn); + if(result != LDAP_SUCCESS) { + return DECLINED; + } - /* Optimize */ - if (vals) { - int i = 0; - while (attributes[i]) { - - if (strcasecmp (attributes[i], "apacheServerName") == 0) { - reqc->name = apr_pstrdup (r->pool, vals[i]); - } - else if (strcasecmp (attributes[i], "apacheServerAdmin") == 0) { - reqc->admin = apr_pstrdup (r->pool, vals[i]); - } - else if (strcasecmp (attributes[i], "apacheDocumentRoot") == 0) { - reqc->docroot = apr_pstrdup (r->pool, vals[i]); - } - else if (strcasecmp (attributes[i], "apacheScriptAlias") == 0) { - reqc->cgiroot = apr_pstrdup (r->pool, vals[i]); - } - else if (strcasecmp (attributes[i], "apacheSuexecUid") == 0) { - reqc->uid = apr_pstrdup(r->pool, vals[i]); - } - else if (strcasecmp (attributes[i], "apacheSuexecGid") == 0) { - reqc->gid = apr_pstrdup(r->pool, vals[i]); - } - i++; + reqc->dn = apr_pstrdup(r->pool, dn); + + if(vals) { + //this translate_name function we're in is long enough, don't You think? + //we set all into reqc struct + mod_vhost_ldap_dovhostconfig(r, attributes, vals, reqc); } - } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[mod_vhost_ldap.c]: loaded from ldap: " - "apacheServerName: %s, " - "apacheServerAdmin: %s, " - "apacheDocumentRoot: %s, " - "apacheScriptAlias: %s, " - "apacheSuexecUid: %s, " - "apacheSuexecGid: %s", - reqc->name, reqc->admin, reqc->docroot, reqc->cgiroot, reqc->uid, reqc->gid); - - 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"); - return DECLINED; - } + if((reqc->name == NULL) || (reqc->docroot == NULL)) { - cgi = NULL; - - if (reqc->cgiroot) { - cgi = strstr(r->uri, "cgi-bin/"); - if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) { - cgi = NULL; + return DECLINED; } - } - if (cgi) { - 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, reqc->docroot, r->uri, NULL); - } else { - return DECLINED; - } - top->server->server_hostname = apr_pstrdup (top->pool, reqc->name); + if(r->uri[0] == '/') { + r->filename = apr_pstrcat(r->pool, reqc->docroot, r->uri, NULL); + } + else { + return DECLINED; + } - if (reqc->admin) { - top->server->server_admin = apr_pstrdup (top->pool, reqc->admin); - } + if(reqc->has_reqlines == 1 && reqc->rqlocationlines) { + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "This vhost has access control configured, need to check if it's enabled for current uri"); + result = 0; + i = 0; + + //we have mercy, and do not open a connection for each uri search ;) + + ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, conf->deref, + conf->secure); + + //ask Your programming teacher, what's all about with + // these "NO, TRY _VERY_ HARD, AND THEN TRY AGAIN _NOT_ TO USE BREAK FOR LOOP LEAVING" ;) + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extConfig Objects search"); + while(i <= strlen(apr_pstrdup(r->pool, r->uri)) && !extconfvals) { + i++; + char *buff = apr_pstrndup(r->pool, r->uri, i); + //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Searching for hostname %s and URI %s, origname is %s", hostname, buff, reqc->name); + //uncomment this, if You'd like to see in log how uri gets checked + //ap_log_error(APLOG_MARK,APLOG_DEBUG,OK,NULL,"%s", buff); + + //well, we must had been connecting already, so we don't do more ldap server connection checks, + //and we're doing a search with cache_getuser instead of using extConfigObject dn apacheConfig object attribute value(s), + //because there's no convenient function in apr api. + //vhost location RDN attribute is used actually by some GUI to make things easier + //TODO: use some generic ldap functions (?) classic search or implement more ldap routines for apr + + //so, we do a search below locationDnBase for config object with matches current hostname and uri.. + //note, that we took our current uri, and we're searching starting from / adding one by one chararacter + //to match config object - access config is always the same as first matching upper url access config. + //and more - if someone defined accessobject for /main and /main/subdir, the first one is used. + //when upper is deleted - next below is returned, and so far.. + //and more - if there are two or more extConfig object for the same combination of server/uri, + //then first found is returned and search isn't processed further. + + //we do a search based on original reqc->name instead of current hostname, to apply rules even if we're accessing + //site via ServerAlias name + apr_snprintf(extconffiltbuf, FILTER_LENGTH, + "(&(apacheExtConfigServerName=%s)(apacheExtConfigUri=%s))", reqc->name, buff); + + result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wlcbasedn, conf->scope, + extconfigattributes, extconffiltbuf, &dn, &extconfvals); + + //matched URI, if found, is returned anyway with extconfvals as ldap attribute value. + } + //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Closing LDAP Connection"); + util_ldap_connection_close(ldc); + + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "This vhost has access control, but probably not for this URI, access config entry not found"); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "Tried with ldap search filter: %s", extconffiltbuf); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "This uri has access control, configuration object is found"); + + if(extconfvals) { + //this translate_name function we're in is long enough, don't You think? + //we set all into extreqc struct + //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extconfig buffer fill"); + mod_vhost_ldap_doextconfig(r, extconfigattributes, extconfvals, extreqc); + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Entering ap_requires generation process"); + + core_dir_config *coredirconf = + (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module); + coredirconf->ap_auth_name = extreqc->extconfname; + coredirconf->ap_auth_type = (char *) "basic"; + char *userlist = "user nobody"; + + if(extreqc->extusers) { + mod_vhost_ldap_webuser_t *extuserreqc; + extuserreqc = + (mod_vhost_ldap_webuser_t *) apr_pcalloc(r->pool, + sizeof(mod_vhost_ldap_webuser_t)); + char *ldap_webuser_attributes[] = + { "apacheExtConfigUserName", "apacheExtConfigUserServerName", "userPassword", + 0 + }; + ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, + conf->deref, conf->secure); + int i = 0; + for (i = 0; i < extreqc->extusers->nelts; i++) { + char userfilter[FILTER_LENGTH]; + + const char **extuservals = NULL; + int result = 0; + apr_snprintf(userfilter, FILTER_LENGTH, + "(&(objectClass=apacheExtendedConfigUserObject)(apacheExtConfigUserServerName=%s))", + reqc->name); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "User search filter: %s", userfilter); + result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wucbasedn, + conf->scope, ldap_webuser_attributes, + userfilter, &dn, &extuservals); + if(extuservals) { + mod_vhost_ldap_doextuserconfig(r, ldap_webuser_attributes, extuservals, + extuserreqc); + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "current username: %s", extuserreqc->webusername); + + userlist = apr_pstrcat(r->pool, userlist, " ", extuserreqc->webusername, NULL); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "current userlist: %s", userlist); + } + + util_ldap_connection_close(ldc); + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "final userlist: %s ", userlist); + + + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthName set to %s", coredirconf->ap_auth_name); + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthType set to %s", coredirconf->ap_auth_type); + ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Preparing access control line"); + coredirconf->ap_requires = + (apr_array_header_t *) get_ap_reqs(r->pool, extreqc, reqc->name, userlist); + + } + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, + "This vhost is not configured for access control, or it is disabled via apacheExtConfigHasRequireLine = FALSE skipping.."); + } - // set environment variables - e = top->subprocess_env; - apr_table_addn (e, "SERVER_ROOT", reqc->docroot); + top->server->server_hostname = apr_pstrdup(top->pool, reqc->name); - 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); + if(reqc->admin) { + top->server->server_admin = apr_pstrdup(top->pool, reqc->admin); + } - return OK; + // set environment variables + e = top->subprocess_env; + apr_table_addn(e, "SERVER_ROOT", reqc->docroot); + core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot); + return OK; } #ifdef HAVE_UNIX_SUEXEC static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r) { - ap_unix_identity_t *ugid = NULL; - mod_vhost_ldap_config_t *conf = - (mod_vhost_ldap_config_t *)ap_get_module_config(r->server->module_config, - &vhost_ldap_module); - mod_vhost_ldap_request_t *req = - (mod_vhost_ldap_request_t *)ap_get_module_config(r->request_config, - &vhost_ldap_module); - - uid_t uid = -1; - gid_t gid = -1; - - // mod_vhost_ldap is disabled or we don't have LDAP Url - if ((conf->enabled != MVL_ENABLED)||(!conf->have_ldap_url)) { - return NULL; - } - - if ((req == NULL)||(req->uid == NULL)||(req->gid == NULL)) { - return NULL; - } - - if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) { - return NULL; - } - - uid = (uid_t)atoll(req->uid); - gid = (gid_t)atoll(req->gid); - - if ((uid < MIN_UID)||(gid < MIN_GID)) { - return NULL; - } - - ugid->uid = uid; - ugid->gid = gid; - ugid->userdir = 0; - - return ugid; + ap_unix_identity_t *ugid = NULL; + mod_vhost_ldap_config_t *conf = + (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); + mod_vhost_ldap_request_t *req = + (mod_vhost_ldap_request_t *) ap_get_module_config(r->request_config, &vhost_ldap_module); + + uid_t uid = -1; + gid_t gid = -1; + + // mod_vhost_ldap is disabled or we don't have LDAP Url + if((conf->enabled != MVL_ENABLED) || (!conf->have_ldap_url)) { + return NULL; + } + + if((req == NULL) || (req->uid == NULL) || (req->gid == NULL)) { + return NULL; + } + + if((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) { + return NULL; + } + + uid = (uid_t) atoll(req->uid); + gid = (gid_t) atoll(req->gid); + + if((uid < MIN_UID) || (gid < MIN_GID)) { + return NULL; + } + + ugid->uid = uid; + ugid->gid = gid; + ugid->userdir = 0; + + return ugid; } #endif -static void -mod_vhost_ldap_register_hooks (apr_pool_t * p) +static int mod_vhost_ldap_post_config(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * s) { - ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, NULL, APR_HOOK_MIDDLE); + /* make sure that mod_ldap (util_ldap) is loaded */ + if(ap_find_linked_module("util_ldap.c") == NULL) { + return HTTP_INTERNAL_SERVER_ERROR; + } + + ap_add_version_component(p, MOD_VHOST_LDAP_VERSION); + return OK; +} + +static void mod_vhost_ldap_register_hooks(apr_pool_t * p) +{ + ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, NULL, APR_HOOK_MIDDLE); #ifdef HAVE_UNIX_SUEXEC - ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE); #endif + ap_hook_check_user_id(mod_vhost_ldap_authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_auth_checker(mod_vhost_ldap_check_auth, NULL, NULL, APR_HOOK_MIDDLE); } +static const 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" + "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n" + "
    \n" + "
  • Host is the name of the LDAP server. Use a space separated list of hosts \n" + "to specify redundant servers.\n" + "
  • Port is optional, and specifies the port to connect to.\n" + "
  • basedn specifies the base DN to start searches from\n" "
\n"), + + AP_INIT_TAKE1("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF, + "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."), + + AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF, + "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."), + + AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF, + "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"), + + AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF, + "Determines how aliases are handled during a search. Can be one of the" + "values \"never\", \"searching\", \"finding\", or \"always\". " "Defaults to always."), + + AP_INIT_TAKE1("VhostLDAPWebLocationConfigBaseDn", mod_vhost_ldap_set_wlcbasedn, NULL, RSRC_CONF, + "Base DN to do all location config searches."), + + AP_INIT_TAKE1("VhostLDAPWebUsersBaseDn", mod_vhost_ldap_set_wucbasedn, NULL, RSRC_CONF, + "Base DN to do all location config searches"), + + {NULL} +}; + module AP_MODULE_DECLARE_DATA vhost_ldap_module = { - STANDARD20_MODULE_STUFF, - NULL, - NULL, - mod_vhost_ldap_create_server_config, - mod_vhost_ldap_merge_server_config, - mod_vhost_ldap_cmds, - mod_vhost_ldap_register_hooks, + STANDARD20_MODULE_STUFF, // jakas lista + NULL, // create per-directory config structure + NULL, // merge per-directory config structures, default is to override + mod_vhost_ldap_create_server_config, // called when module configuration data needs to be created/allocated. + mod_vhost_ldap_merge_server_config, // merge per-server config structures + mod_vhost_ldap_cmds, // Here we pass in the list of new configuration directives. + mod_vhost_ldap_register_hooks, // register me in apache core }; -- 2.45.1