]> andersk Git - mod-vhost-ldap.git/blob - mod_vhost_ldap.c
upstream? :-)
[mod-vhost-ldap.git] / mod_vhost_ldap.c
1 /* ============================================================
2  * Copyright (c) 2003-2006, Ondrej Sury, Piotr Wadas
3  * All rights reserved.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  * NOTE: only static members must be "used" to build, 
14  * so for time-to-time used routines we don't declare static 
15  * mod_vhost_ldap.c --- read virtual host config from LDAP directory
16  * version 2.0 - included ldap-based basic auth & authz
17  * remember to add "-lcrypt" in Makefile if there's a need to generate new password
18  * for now not needed (validation only), this below is almost copy-paste from apache source, htpasswd.c
19  */
20  
21 #include "mod_vhost_ldap.h"
22
23 module AP_MODULE_DECLARE_DATA vhost_ldap_module;
24 /******************************************************************/
25 char *pw_encrypt (const char *clear, const char *salt)
26 {
27                 //this function encrypts password in unix crypt md5 way
28                 extern char *crypt (__const char *__key, __const char *__salt);
29         static char cipher[128];
30         char *cp = crypt (clear, salt);
31         strcpy (cipher, cp);
32         return cipher;
33 }
34 /******************************************************************/
35 static int strschrcount(apr_pool_t * p, const char *src, const char *delim)
36 {
37         int i = 1;
38         int x = 0;
39         while(*src++) {
40                 if(strcasecmp(apr_pstrndup(p, src, i), (char *) delim) == 0) {
41                         x++;
42                 }
43         }
44         return x;
45 }
46 /******************************************************************/
47 static void *mvhl_dump_config_request ( mvhl_config *currentconf, request_rec *r) {
48         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "BaseDn: %s", currentconf->basedn);
49         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "BindDn: %s", currentconf->binddn);
50         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "BindPw: %s", currentconf->bindpw);
51         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Deref: %d", currentconf->deref);
52         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Enabled: %d", currentconf->enabled);
53         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "UserFilter: %s", currentconf->filter);
54         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "HaveLdapUrl: %d", currentconf->have_ldap_url);
55         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "HaveDeref: %d", currentconf->have_deref);
56         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Url: %s", currentconf->url);
57         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Port: %d", currentconf->port);
58         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Scope: %d", currentconf->scope);
59         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Fallback: %s", currentconf->fallback);
60         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "WucBaseDn: %s", currentconf->wucbasedn);
61         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "WlcBaseDn: %s", currentconf->wlcbasedn);
62         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "AliasesBaseDn: %s", currentconf->aliasesbasedn);
63         return NULL;
64 }
65 /******************************************************************/
66 void log_dump_apr_array(request_rec * r, apr_array_header_t * arr, const char *prefix)
67 {
68     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering log_dump_apr_array");
69     int x = 0;
70     char **aliases = (char **) arr->elts;
71     for (x = 0; x < arr->nelts; x++) {
72     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " log_dump_apr_array val %d %s %s", x, prefix, aliases[x]);
73     }
74     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving log_dump_apr_array");
75 }
76 /******************************************************************/
77 static apr_array_header_t *get_parsed_string_atrr_arr(request_rec * r, const char *server_alias_attrvar_line, const char *delim)
78 {
79         /*
80          * This little piece of code creates apr_array from the string seperated by delim.
81          * It's primary usage is to get array of ldap one attribute values, which is
82          * retrieved (when multi-value) as ";" separated string.
83          */
84     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering get_parsed_string_atrr_arr |%s|", server_alias_attrvar_line);
85         if(server_alias_attrvar_line) {
86
87                 apr_collapse_spaces((char *) server_alias_attrvar_line, server_alias_attrvar_line);
88                 int ccount = strschrcount(r->pool, server_alias_attrvar_line, delim) + 1;
89
90                 apr_array_header_t *aliases_arr = apr_array_make(r->pool, ccount, sizeof(char *));
91                 char **curralias;
92                 curralias = (char **) apr_array_push(aliases_arr);
93
94                 char *curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';');
95                 char *tmp = apr_pstrdup(r->pool, (char *) curr_server_alias);;
96                 *curralias = tmp;
97
98
99                 while(server_alias_attrvar_line[0]) {
100                         curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';');
101                         curralias = (char **) apr_array_push(aliases_arr);
102                         tmp = apr_pstrdup(r->pool, (char *) curr_server_alias);
103                         *curralias = tmp;
104                 }
105         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr OK");
106                 return aliases_arr;
107         }
108         else
109         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr NULL");
110                 return NULL;
111 }
112 /******************************************************************/
113 static apr_array_header_t *get_ap_reqs(apr_pool_t * p, mvhl_extconfig_object * extreqc, char *mainservername, char *userlist)
114 {
115
116     ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," get_ap_reqs Entering");
117
118         apr_array_header_t *res = apr_array_make(p, 2, sizeof(require_line));
119
120         require_line *rline;
121         apr_int64_t limited = -1;
122
123         rline = (require_line *) apr_array_push(res);
124
125         //currently we don't support playing with request types
126         rline->method_mask = limited;
127
128         if(extreqc->extconftype == 1) {
129                 ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = TRUE server %s",mainservername);
130                 rline->requirement = apr_pstrdup(p, (char *) "valid-user");
131         }
132         else {
133         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = FALSE server %s",mainservername);
134                 
135                 rline->requirement = apr_pstrdup(p, userlist);
136         }
137     ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," Leaving get_ap_reqs, returning require line |require %s|", rline->requirement);
138         return res;
139 }
140 /******************************************************************/
141 static void mvhl_dovhostconfig(request_rec * r, char *attributes[], const char **vals, mvhl_request * reqc)
142 {
143     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering vhost configuration");
144         /*
145          * we got 10 attributes to search for, counting from 0 to 9
146          */
147         int i;
148         for ( i = 0; i <= 9; i++ ) {
149       ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " VhostConfig Iteration %d :: will get %s", i, attributes[i]);
150       switch (i) {
151         /* 0 apacheServerName */
152                 case 0: reqc->name = apr_pstrdup(r->pool, vals[i]);     break;
153                 /* 1 apacheServerAlias - may be null */ 
154                 case 1: reqc->serveralias = (vals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i],(const char *) ";") : NULL; break;
155                 /* 2 apacheDocumentRoot */
156                 case 2: reqc->docroot = apr_pstrdup(r->pool, vals[i]); break;
157                 /* 3 apacheSuexecUid */
158                 case 3: reqc->uid = (vals[i]) ? apr_pstrdup(r->pool, vals[i]) : reqc->uid ; break;
159                 /* 4 apacheSuexecGid */
160                 case 4: reqc->gid = (vals[i]) ? apr_pstrdup(r->pool, vals[i]): reqc->gid ; break;
161                 /* 5 apacheServerAdmin */                       
162                 case 5: reqc->admin = (vals[i]) ? apr_pstrdup(r->pool, vals[i]) : NULL ; break;
163                 /* 6 apacheExtConfigHasRequireLine */
164                 //if there's no HasRequireLine attribute set we assume we don't have reqlines                   
165                 case 6: reqc->has_reqlines = (vals[i] && strcasecmp("TRUE", apr_pstrdup(r->pool, vals[i])) == 0) ?  1 : 0; break;                       
166                 /* 7 apacheLocationOptionsDn */
167                 case 7: reqc->rqlocationlines = (vals[i]) ? reqc->rqlocationlines = (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], (const char *) ";") : NULL ; break;                   
168                 /* 8 apacheAliasesConfigEnabled */
169                 case 8: reqc->has_aliaslines = ( vals[i] && strcasecmp("TRUE", apr_pstrdup(r->pool, vals[i])) == 0 ) ? 1 : 0; break;                            
170                 /* 9 apacheAliasConfigOptionsDn */                                                      
171                 case 9: reqc->aliaseslines = (vals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], (const char *) ";") : NULL;      
172           }
173         }
174         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving vhost configuration , exit assignments: ");
175         ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " apacheServerName \'%s\'", reqc->name);
176     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " apacheServerAdmin \'%s\'", reqc->admin);    
177     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " apacheDocumentRoot \'%s\'", reqc->docroot);    
178     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " apacheSuexecUid \'%s\'", reqc->uid);    
179     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " apacheSuexecGid \'%s\'", reqc->gid);
180     
181     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
182         /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
183         (reqc->has_reqlines && reqc->rqlocationlines ) ? 
184         apr_pstrdup(r->pool, "vhost \'%s\' has access control") : 
185         apr_pstrdup(r->pool, " vhost \'%s\' doesn't have access control"), 
186         reqc->name);
187                 
188     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
189                 /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
190                 (reqc->has_aliaslines && reqc->has_aliaslines ) ? 
191                 apr_pstrdup(r->pool, "vhost \'%s\' has dir aliases") : 
192                 apr_pstrdup(r->pool, " vhost \'%s\' doesn't have dir aliases"), 
193                 reqc->name);    
194 }
195 /******************************************************************/
196 static void mvhl_doextconfig(request_rec * r, char *extconfigattributes[], const char **extconfvals, mvhl_extconfig_object * extreqc)
197 {
198     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering Access Control config");
199         /*
200          * we got 6 attributes to search for, counting from 0 to 5
201          */
202         int i = 0;
203         for ( i = 0; i <= 4; i++ ) {
204       ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Vhost Access Control Iteration %d :: will get %s", i, extconfigattributes[i]);
205       switch (i) {
206         /* 0 apacheExtConfigUri */
207                 case 0: extreqc->exturi = (extconfvals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], (const char *) ";") : NULL ; break;
208         /* 1 apacheExtConfigRequireValidUser 
209                  * this value determines whether we have "require valid-user" object  (TRUE) , 
210                  * or (FALSE) object "require user johny mary dorothy witch"
211                  * here set retrieved value, regardless what it is, to play with it later.
212                  */     
213                 case 1: extreqc->extconftype = (extconfvals[i] && strcasecmp("TRUE", apr_pstrdup(r->pool, extconfvals[i])) == 0) ? 1 : 0; break; 
214         /* 2 apacheExtConfigServerName */
215                 case 2: extreqc->extservername = (extconfvals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], (const char *) ";") : NULL ; break; 
216         /* 3 apacheExtConfigObjectName */
217                 case 3: extreqc->extconfname = apr_pstrdup(r->pool, extconfvals[i]); break;
218         /* 4 apacheExtConfigUserDn */
219                 case 4:
220                 extreqc->extusers = (extconfvals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], (const char *) ";") : NULL; break;
221         /* 5 apacheExtConfigPath */
222                 case 5:
223                 extreqc->extdir = (extconfvals[i]) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], (const char *) ";") : NULL ; break;
224       }
225         }
226         
227         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving Access Control config :: exit assignments");
228         
229         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " This Access Object prompt is \'%s\'", extreqc->extconfname);
230         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
231                 (extreqc->exturi ) ?
232                 apr_pstrdup(r->pool, " \'%s\' extConfigUri has at least one URI value") : 
233         apr_pstrdup(r->pool, " \'%s\' has extConfigUri assigned"), 
234                 extreqc->extconfname);
235         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
236                 (extreqc->extdir ) ?
237                 apr_pstrdup(r->pool, " \'%s\' extConfigPath has at least one directory value") : 
238         apr_pstrdup(r->pool, " \'%s\' has extConfig assigned"), 
239                 extreqc->extconfname);
240         ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
241                 /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
242                 (extreqc->extconftype) ? 
243         apr_pstrdup(r->pool, " \'%s\' requires valid-user") : 
244         apr_pstrdup(r->pool, " \'%s\' requires user from userlist"), 
245         extreqc->extconfname) ;
246         ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
247                 /* following three lines evaluates to one string in which final argument (fourth line) is substituted */         
248                 (extreqc->extservername ) ?
249         apr_pstrdup(r->pool, " \'%s\' has at least one serverName assigned") : 
250         apr_pstrdup(r->pool, " \'%s\' has no assigned serverNames"), 
251         extreqc->extconfname);
252         ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
253                 /* following three lines evaluates to one string in which final argument (fourth line) is substituted */         
254                 (extreqc->extusers ) ? 
255         apr_pstrdup(r->pool, " \'%s\' has at least one webuser object assigned") : 
256         apr_pstrdup(r->pool, " \'%s\' has no assigned webusers objects"),
257         extreqc->extconfname );
258     
259 }
260 /******************************************************************/
261 static void mvhl_doextuserconfig(request_rec * r, char *ldap_webuser_attributes[], const char **extuservals, mvhl_webuser * extuserreqc)
262 {
263     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering extwebuser Config");
264     /*
265          * we got 5 attributes to search for, counting from 0 to 4
266          */
267         int i = 0;
268         for ( i = 0; i <= 4; i++ ) {
269         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Web user Iteration %d :: will get %s", i, ldap_webuser_attributes[i]);
270       switch (i) {
271         /* 0 apacheExtConfigUserName */
272                 case 0: 
273                         extuserreqc->webusername = apr_pstrdup(r->pool, extuservals[i]);
274                         break;
275                 /* 1 apacheExtConfigUserServerName */
276                 case 1: 
277                         extuserreqc->webuserserver = ( extuservals[i] ) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], (const char *) ";") : NULL;
278                         break;
279                 /* 2 userPassword */
280                 case 2: 
281                         extuserreqc->webuserpassword =  ( extuservals[i] ) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], (const char *) ";") : NULL;
282                         break;
283                 /* 3 apacheExtConfigUserDirectoryName */
284                 case 3: 
285                         extuserreqc->webuserdirectory = ( extuservals[i] ) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], (const char *) ";") : NULL;
286                         break;
287                 case 4:
288                 /* apacheExtConfigUserLocationUri */
289                         extuserreqc->webuserlocationuri = ( extuservals[i] ) ? (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], (const char *) ";") : NULL;
290                         break;
291                                                 
292                 }
293         }
294      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "  Leaving extwebuser Config :: exit assignments");
295      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " This webuser name is \'%s\'", extuserreqc->webusername);
296      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
297          /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
298         ( extuserreqc->webuserserver ) ?        
299         apr_pstrdup(r->pool, " \'%s\' has at least one server assigned") : 
300         apr_pstrdup(r->pool, " \'%s\' has no serverNames assigned"), 
301         extuserreqc->webusername );
302      ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
303         /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
304         ( extuserreqc->webuserpassword ) ?      
305         apr_pstrdup(r->pool, " \'%s\' has at least one password assigned") : 
306         apr_pstrdup(r->pool, " \'%s\' has no passwords assigned"), 
307         extuserreqc->webusername );
308     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
309         /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
310         ( extuserreqc->webuserdirectory ) ?     
311         apr_pstrdup(r->pool, " \'%s\' has at least one physical directory assigned") : 
312         apr_pstrdup(r->pool, " \'%s\' has no physical directories assigned"), 
313         extuserreqc->webusername );
314     ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
315         /* following three lines evaluates to one string in which final argument (fourth line) is substituted */ 
316         ( extuserreqc->webuserlocationuri ) ?   
317         apr_pstrdup(r->pool, " \'%s\' has at least one location assigned") : 
318         apr_pstrdup(r->pool, " \'%s\' has no locations assigned"), 
319         extuserreqc->webusername );
320         
321 }
322 /******************************************************************/
323 static void mvhl_doaliasesconfig(request_rec * r, char *aliases_attributes[], const char **aliasesvals, mvhl_aliasconf_object * aliasreqc){
324         
325     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering aliasObject Config");
326     /*
327          * we got 4 attributes to search for, counting from 0 to 3
328          */
329         int i = 0;
330
331         for (i = 0; i <= 3; i++ ) {
332                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Alias config Iteration %d :: will get %s", i, aliases_attributes[i]);
333                 switch (i) {
334                 /* 0 apacheAliasConfigSourceUri */
335                 case 0: 
336                         aliasreqc->aliassourceuri = (apr_array_header_t *) get_parsed_string_atrr_arr(r, aliasesvals[i], (const char *) ";");
337                         //aliasreqc->aliassourceuri = apr_pstrdup(r->pool, aliasesvals[i]);
338                         break;
339                 /* 1 apacheAliasConfigServerName - MULTI-VALUE */
340                 case 1: 
341                         aliasreqc->aliasconfservername = (apr_array_header_t *) get_parsed_string_atrr_arr(r, aliasesvals[i], (const char *) ";");
342                         break;
343                 /* 2 apacheAliasConfigTargetDir */
344                 case 2: 
345                         aliasreqc->aliastargetdir = apr_pstrdup(r->pool, aliasesvals[i]);
346                         break;
347                 /* 3 apacheAliasConfigObjectName */
348                 case 3:
349                         aliasreqc->aliasconfname = apr_pstrdup(r->pool, aliasesvals[i]);
350                         break;
351                 }
352         }
353          ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "  Leaving alias Config :: exit assignments");
354          /* defined ldap schema force alias object to have all of these attributes, so there's no way for existing object without any of them*/
355      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " This alias config object name is \'%s\'", aliasreqc->aliasconfname);
356      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " \'%s\' has at least one SourceUri assigned", aliasreqc->aliasconfname);
357      ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " \'%s\' target dir is \'%s\'", aliasreqc->aliasconfname, aliasreqc->aliastargetdir);
358          ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, apr_pstrdup(r->pool, " \'%s\' has at least one serverName assigned"), aliasreqc->aliasconfname );
359 }
360 /******************************************************************/
361 static int mvhl_authenticate_basic_user(request_rec * r)
362 {
363         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering mvhl_authenticate_basic_user");
364         const char *sent_pw;
365     mvhl_webuser *extuserreqc;
366     extuserreqc = (mvhl_webuser *) apr_pcalloc(r->pool, sizeof(mvhl_webuser));
367         int rc = ap_get_basic_auth_pw(r, &sent_pw);
368         if(rc != OK) return rc;
369         
370         if(strtrue(r->user) && strtrue(sent_pw)) {
371                 int result = 0;
372                 char userfilter[FILTER_LENGTH];
373                 const char *dn = NULL;
374                 const char **extuservals = NULL;
375                 util_ldap_connection_t *ldc = NULL;
376                 char *ldap_webuser_attributes[] = { "apacheExtConfigUserName", "apacheExtConfigUserServerName", "userPassword", 0 };
377                 mvhl_config *conf = (mvhl_config *) ap_get_module_config(r->server->module_config, &vhost_ldap_module);
378                 apr_snprintf(userfilter, FILTER_LENGTH, "(&(apacheExtConfigUserName=%s))", r->user);
379                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " AuthUser search filter: %s", userfilter);
380                 ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, conf->deref, conf->secure);
381                 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wucbasedn, conf->scope, ldap_webuser_attributes, userfilter, &dn, &extuservals);
382                 util_ldap_connection_close(ldc);
383
384                 if(extuservals) {
385                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " User %s found.", r->user);
386
387                         mvhl_doextuserconfig(r, ldap_webuser_attributes, extuservals, extuserreqc);
388
389                         int x = 0;
390                         //we're checking for each password - if any matches, then we return immediately
391                         char **passwords = (char **) extuserreqc->webuserpassword->elts;
392
393                         for (x = 0; x < extuserreqc->webuserpassword->nelts; x++) {
394                                 if ( apr_password_validate(sent_pw, passwords[x]) == OK ) 
395                                 {
396                                 ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " APR authentication for user %s at %s successful.", extuserreqc->webusername, r->server->server_hostname);
397                                 return OK; 
398                                 }
399                                 
400                                 char *prefix = "{CRYPT}";
401                                 int prefixlen = 7;
402                                 if ( strcasecmp( apr_pstrndup(r->pool, passwords[x], prefixlen ), prefix ) == 0 ) {
403                                         char *stripped = passwords[x] + prefixlen;
404                                         char *userinputhash = pw_encrypt (sent_pw, stripped );
405                                         ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " User entered: \'%s\' ", sent_pw );                         
406                                         ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Retrieved value: \'%s\'", passwords[x] );
407                                         ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Retrieved value (stripped): \'%s\'", stripped );
408                                         ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " User input hash: \'%s\'", userinputhash );
409                                         if ( strcasecmp( userinputhash , stripped ) == 0 ) 
410                                         {
411                                                 ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Unix authentication for user %s at %s successful.", extuserreqc->webusername, r->server->server_hostname);
412                                                 return OK; 
413                                         }
414                                 }
415                                 
416                                 if ( strcasecmp(sent_pw,passwords[x]) == 0 ) 
417                                 {
418                                 ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Clear text authentication for user %s at %s successful.", extuserreqc->webusername, r->server->server_hostname);
419                                 return OK; 
420                                 }
421                         }
422                 }
423                 else {
424                         ap_log_rerror(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, r, " User %s at %s not found", extuserreqc->webusername, r->server->server_hostname);
425                         return HTTP_UNAUTHORIZED;
426                 }
427         }
428         else {
429                 ap_note_basic_auth_failure(r);
430                 ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
431                               ": Both a username and password must be provided : authentication for user %s at %s failed.",
432                               extuserreqc->webusername, r->server->server_hostname);
433                 return HTTP_UNAUTHORIZED;
434         }
435     ap_note_basic_auth_failure(r);
436     ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "Authentication for user %s at %s failed.",
437             extuserreqc->webusername, r->server->server_hostname);
438         return HTTP_UNAUTHORIZED;
439
440 }
441 /******************************************************************/
442 static int check_mvhl_auth_require(char *user, const char *t, request_rec * r)
443 {
444         const char *w;
445         w = ap_getword(r->pool, &t, ' ');
446         if(!strcmp(w, "valid-user")) {
447
448                 return OK;
449         }
450
451         if(!strcmp(w, "user")) {
452                 while(t[0]) {
453                         w = ap_getword_conf(r->pool, &t);
454                         if(!strcmp(user, w)) {
455
456                                 return OK;
457
458                         }
459                 }
460                 return HTTP_UNAUTHORIZED;
461         }
462         else {
463
464                 return HTTP_INTERNAL_SERVER_ERROR;
465         }
466         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
467                       ": %s : Reached end of check_mvhl_auth_require!", r->server->server_hostname);
468         return HTTP_INTERNAL_SERVER_ERROR;
469 }
470 /******************************************************************/
471 static int mvhl_check_auth(request_rec * r)
472 {
473     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
474               ": mvhl_check_auth, parsing existing ap_requires for %s at %s ", r->user, r->server->server_hostname);
475         char *user = r->user;
476         int rv;
477         register int x;
478         const char *t;
479         const apr_array_header_t *reqs_arr = ap_requires(r);
480
481         require_line *reqs;
482         reqs = (require_line *) reqs_arr->elts;
483
484         for (x = 0; x < reqs_arr->nelts; x++) {
485                 t = reqs[x].requirement;
486                 if((rv = check_mvhl_auth_require(user, t, r)) != HTTP_UNAUTHORIZED) {
487                         return rv;
488                 }
489         }
490
491
492         ap_note_basic_auth_failure(r);
493         return HTTP_UNAUTHORIZED;
494 }
495 /******************************************************************/
496 static void *mvhl_create_sconfig(apr_pool_t * p, server_rec * s)
497 {
498         //ldap://host[:port]/basedn[?attrib[?scope[?filter]]]
499         mvhl_config *conf       = (mvhl_config *) apr_pcalloc(p, sizeof(mvhl_config));
500         conf->enabled           = 0;
501         conf->have_ldap_url = 0;
502         conf->have_deref        = 0;
503         conf->scope                     = LDAP_SCOPE_SUBTREE;
504         conf->deref                     = never;
505         conf->host                      = NULL;
506         conf->port                      = 389;
507         conf->url                       = NULL;
508         conf->filter            = NULL;
509         conf->binddn            = NULL;
510         conf->bindpw            = NULL;
511         conf->basedn            = NULL;
512         conf->wlcbasedn         = NULL;
513         conf->wucbasedn         = NULL;
514         conf->aliasesbasedn = NULL;
515         conf->fallback          = NULL;
516         conf->secure                    = 0;
517         conf->alias_enabled             = 0;
518         conf->loc_auth_enabled  = 0;
519         conf->dir_auth_enabled  = 0;
520         return conf;
521 }
522 /******************************************************************/
523 static void *mvhl_merge_sconfig(apr_pool_t * p, void *parentv, void *childv)
524 {
525         mvhl_config *parent = (mvhl_config *) parentv;
526         mvhl_config *child = (mvhl_config *) childv;
527         mvhl_config *conf = (mvhl_config *) apr_pcalloc(p, sizeof(mvhl_config));
528         
529         conf->enabled           = (child->enabled               ? child->enabled : parent->enabled);
530         conf->binddn            = (child->binddn                ? child->binddn : parent->binddn);
531         conf->bindpw            = (child->bindpw                ? child->bindpw : parent->bindpw);
532         conf->fallback          = (child->fallback              ? child->fallback : parent->fallback);
533         conf->alias_enabled = (child->alias_enabled ? child->alias_enabled : parent->alias_enabled);
534         conf->loc_auth_enabled  = (child->loc_auth_enabled      ? child->loc_auth_enabled : parent->loc_auth_enabled);
535         conf->dir_auth_enabled  = (child->dir_auth_enabled      ? child->dir_auth_enabled : parent->dir_auth_enabled);
536
537         if(child->have_ldap_url) {
538                 conf->have_ldap_url = child->have_ldap_url;
539                 conf->url = child->url;
540                 conf->host = child->host;
541                 conf->port = child->port;
542                 conf->basedn = child->basedn;
543                 conf->scope = child->scope;
544                 conf->filter = child->filter;
545                 conf->secure = child->secure;
546                 conf->wlcbasedn = child->wlcbasedn;
547                 conf->wucbasedn = child->wucbasedn;
548                 conf->aliasesbasedn = child->aliasesbasedn;
549         }
550         else 
551         {
552                 conf->have_ldap_url = parent->have_ldap_url;
553                 conf->url = parent->url;
554                 conf->host = parent->host;
555                 conf->port = parent->port;
556                 conf->basedn = parent->basedn;
557                 conf->scope = parent->scope;
558                 conf->filter = parent->filter;
559                 conf->secure = parent->secure;
560                 conf->wlcbasedn = parent->wlcbasedn;
561                 conf->wucbasedn = parent->wucbasedn;
562                 conf->aliasesbasedn = parent->aliasesbasedn;
563         }
564         if(child->have_deref) {
565                 conf->have_deref = child->have_deref;
566                 conf->deref = child->deref;
567         }
568         else 
569         {
570                 conf->have_deref = parent->have_deref;
571                 conf->deref = parent->deref;
572         }
573         return conf;
574 }
575 /******************************************************************/
576 static const char *conf_mvhl_url(cmd_parms * cmd, void *dummy, const char *url)
577 {
578         int result;
579         apr_ldap_url_desc_t *urld;
580
581         mvhl_config *conf =     (mvhl_config *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module);
582         result = apr_ldap_url_parse(url, &(urld));
583         
584         if(result != LDAP_SUCCESS) {
585                 switch (result) {
586                         case LDAP_URL_ERR_MEM:                  return "0x01 can't allocate memory space";
587                         case LDAP_URL_ERR_PARAM:                return "0x02 parameter is bad";
588                         case LDAP_URL_ERR_BADSCHEME:    return "0x03 URL doesn't begin with ldap[si]://";
589                         case LDAP_URL_ERR_BADENCLOSURE: return "0x04 URL is missing trailing >";
590                         case LDAP_URL_ERR_BADURL:               return "0x05 URL is bad";
591                         case LDAP_URL_ERR_BADHOST:              return "0x06 host port is bad";
592                         case LDAP_URL_ERR_BADATTRS:     return "0x07 bad (or missing) attributes";
593                         case LDAP_URL_ERR_BADSCOPE:     return "0x08 scope string is invalid (or missing)";
594                         case LDAP_URL_ERR_BADFILTER:    return "0x09 bad or missing filter";
595                         case LDAP_URL_ERR_BADEXTS:              return "0x0a bad or missing extensions";
596                         default:                                                return "Could not parse LDAP URL";
597                 }
598         }
599         conf->url = apr_pstrdup(cmd->pool, url);
600
601         /* Set all the values, or at least some sane defaults */
602         if(conf->host) {
603                 char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2);
604                 strcpy(p, urld->lud_host);
605                 strcat(p, " ");
606                 strcat(p, conf->host);
607                 conf->host = p;
608         }
609         else {
610                 conf->host = urld->lud_host ? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost";
611         }
612         
613         conf->basedn = urld->lud_dn ? apr_pstrdup(cmd->pool, urld->lud_dn) : "";
614
615         conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE;
616
617         if(urld->lud_filter) {
618                 if(urld->lud_filter[0] == '(') {
619                         /* 
620                          * Get rid of the surrounding parentheses; 
621                          * later on when generating the
622                          * filter, they'll be put back.
623                          */
624                         conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter + 1);
625                         conf->filter[strlen(conf->filter) - 1] = '\0';
626                 }
627                 else {
628                         conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter);
629                 }
630         }
631         /*else {
632                 conf->filter = "objectClass=apacheConfig";
633         }*/
634
635         /* "ldaps" indicates secure ldap connections desired
636          */
637         if(strncasecmp(url, "ldaps", 5) == 0) {
638                 conf->secure = 1;
639                 conf->port = urld->lud_port ? urld->lud_port : LDAPS_PORT;
640
641         }
642         else {
643                 conf->secure = 0;
644                 conf->port = urld->lud_port ? urld->lud_port : LDAP_PORT;
645         }
646
647         conf->have_ldap_url = 1;
648         apr_ldap_free_urldesc(urld);
649         return NULL;
650 }
651 /******************************************************************/
652 static const char *conf_mvhl(cmd_parms *cmd, void *dummy, const char *confval) {
653         
654         if ( strlen(confval) == 0 ) { return NULL; }
655           
656         {
657                 //we're getting currently set (or default from mvhl_create_config if not set already)
658                 mvhl_config *conf = (mvhl_config *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module);
659                 int *cmdtype = (int *) cmd->info;
660                 char *currval = apr_pstrdup(cmd->pool, confval);
661                 switch (*cmdtype) {
662                         case 1:
663                                 conf->enabled = ( strcmp(currval,"On") == 0 )? 1 : 0;   
664                                 break;
665                         case 2:
666                                 conf->binddn = currval;
667                                 break;
668                         case 3: 
669                                 conf->bindpw = currval;
670                                 break;
671                         case 4: 
672                                 //const values: never =  0, searching = 1, finding = 2, always = 3
673                                 if ( strcmp(currval,"never")    == 0 ) { conf->deref = never; conf->have_deref          = 1;}
674                                 if ( strcmp(currval,"searching")== 0 ) { conf->deref = searching; conf->have_deref      = 1;}
675                                 if ( strcmp(currval,"finding")  == 0 ) { conf->deref = finding; conf->have_deref        = 1;}
676                                 if ( strcmp(currval,"always")   == 0 ) { conf->deref = always; conf->have_deref         = 1;}
677                                 break;                          
678                         case 5: 
679                                 conf->wlcbasedn = currval;
680                                 break;
681                         case 6: 
682                                 conf->wucbasedn = currval;
683                                 break;
684                         case 7:
685                                 conf->fallback = currval;
686                                 break;
687                         case 8:
688                                 conf->aliasesbasedn = currval;
689                                 break;
690                         case 9:
691                                 conf->alias_enabled = ( strcmp(currval,"On") == 0 )? 1 : 0 ;
692                                 break;
693                         case 10:
694                                 conf->loc_auth_enabled = ( strcmp(currval,"On") == 0 )? 1 : 0;
695                                 break;
696                         case 11:
697                                 conf->dir_auth_enabled = ( strcmp(currval,"On") == 0 )? 1 : 0;
698                                 break;
699                 }
700                 return NULL;
701         }
702         
703 }
704 /******************************************************************/
705 static int apply_vhost(mvhl_config *conf, const char *hostname, request_rec * r, util_ldap_connection_t *ldc, const char *dn, mvhl_request *reqc  ) {
706
707         char filtbuf[FILTER_LENGTH];
708         apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, hostname, hostname);
709         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Server search filter: %s", filtbuf);
710         const char **vals                               = NULL;
711         char *attributes[]                              = { "apacheServerName", "apacheServerAlias", "apacheDocumentRoot", "apacheSuexecUid","apacheSuexecGid","apacheServerAdmin","apacheExtConfigHasRequireLine","apacheLocationOptionsDn","apacheAliasesConfigEnabled","apacheAliasConfigOptionsDn",0 };
712         int failures    = 0;
713         int result              = LDAP_SERVER_DOWN;
714         while(failures++ <= 5 && result == LDAP_SERVER_DOWN) {
715                 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, attributes, filtbuf, &dn, &vals);
716         }
717
718         /* 
719      * we don't test conf->host nor connection, because if these failed, declined was already returned
720      * instead, we do a search for specified fallback vhost
721      */ 
722     if ( result == LDAP_NO_SUCH_OBJECT ) 
723     {
724         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Vhost %s not found, will try to fall-back to defined vhost: %s", hostname, conf->fallback);
725         hostname = conf->fallback;
726                 apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", conf->filter, hostname, hostname);
727                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Server search filter: %s", filtbuf);
728                 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, attributes, filtbuf, &dn, &vals);
729     }
730     
731         if(result != LDAP_SUCCESS) {
732                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Vhost %s defined as fallback not found, err %s", hostname, ldap_err2string(result));
733                 return 0; 
734         }
735
736         reqc->dn = apr_pstrdup(r->pool, dn);
737         if (vals) { mvhl_dovhostconfig(r, attributes, vals, reqc); }
738
739         if( (reqc->name == NULL) || (reqc->docroot == NULL) || ! (r->uri[0] == '/') ) return 0;
740         r->filename = apr_pstrcat(r->pool, reqc->docroot, r->uri, NULL);
741         return 1;
742         
743 }
744 /******************************************************************/
745 static void apply_aliasing(mvhl_request *reqc, request_rec * r, mvhl_config *conf, util_ldap_connection_t *ldc, const char *dn) {
746
747         if(reqc->has_aliaslines == 1 && reqc->aliaseslines ) {
748                 const char **aliasesconfvals    = NULL;
749                 char aliasesfilter[FILTER_LENGTH];
750                 char *aliases_attributes[]              = { "apacheAliasConfigSourceUri", "apacheAliasConfigServerName", "apacheAliasConfigTargetDir", "apacheAliasConfigObjectName",0 };
751                 mvhl_aliasconf_object *aliasreqc = (mvhl_aliasconf_object *) apr_pcalloc(r->pool, sizeof(mvhl_aliasconf_object));
752                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This vhost has alias configuration, need to check if for current uri");
753                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Original r->filename: %s", r->filename);
754                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Original r->uri: %s", r->uri);
755                 int i = 0;      
756                 int result = 0;
757
758                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering Alias Objects search");
759                 while(i <= strlen(apr_pstrdup(r->pool, r->uri)) && !aliasesconfvals ) {
760                         i++;
761                         char *aliasbuff = apr_pstrndup(r->pool, r->uri, i);
762                         apr_snprintf(aliasesfilter, FILTER_LENGTH,"(&(%s)(apacheAliasConfigServerName=%s)(apacheAliasConfigSourceUri=%s))", conf->filter, reqc->name, aliasbuff);
763                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Alias Object search filter: %s", aliasesfilter);
764                         /* we reuse ldap connection opened previously with alias entries, 
765                         * access control entries and webusers entries searches changing used filter as needed (!!) */
766                         result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->aliasesbasedn, conf->scope, aliases_attributes, aliasesfilter, &dn, &aliasesconfvals);
767                 }
768                 
769                 if(result != LDAP_SUCCESS) {
770                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This vhost aliases config, but probably not for this URI, alias config entry not found");
771                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Tried with ldap search filter: %s", aliasesfilter);
772                 }
773                 else {
774                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This uri has aliases config, configuration object found");
775                         if(aliasesconfvals) { mvhl_doaliasesconfig(r, aliases_attributes, aliasesconfvals, aliasreqc); }
776                         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Entering alias substitution");
777                         r->filename = apr_pstrcat (r->pool, aliasreqc->aliastargetdir , r->uri + i, NULL);
778                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Final filename r->filename: %s", r->filename);
779                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Final uri (unchanged) r->uri: %s", r->uri);
780                 }
781                 
782         }
783         else
784         {
785                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "This vhost has no aliases, or it is disabled via apacheAliasesConfigEnabled = (FALSE|not set) skipping..");
786         } 
787 }
788 /******************************************************************/
789 static void apply_location_access_control(mvhl_request *reqc, request_rec * r, mvhl_config *conf, util_ldap_connection_t *ldc, const char *dn) {
790
791         if(reqc->has_reqlines == 1 && reqc->rqlocationlines) {
792                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This vhost has location access control configured, need to check if it's enabled for current uri");
793                 int result = 0;
794                 int i = 0;
795                 char extconffiltbuf[FILTER_LENGTH];
796                 const char **extconfvals                = NULL;
797                 char *extconfigattributes[]     = { "apacheExtConfigUri","apacheExtConfigRequireValidUser","apacheExtConfigServerName","apacheExtConfigObjectName","apacheExtConfigUserDn","apacheExtConfigPath",0}; 
798                 mvhl_extconfig_object *extreqc = (mvhl_extconfig_object *) apr_pcalloc(r->pool, sizeof(mvhl_extconfig_object));
799                 char *buff =  NULL;
800                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extConfig Location Objects search");
801                 while(i <= strlen(apr_pstrdup(r->pool, r->uri)) && !extconfvals) {
802                         i++;
803                         buff = apr_pstrndup(r->pool, r->uri, i);
804                         /*
805                          * 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);
806                          * uncomment this, if You'd like to see in log how uri gets checked
807                          * ap_log_error(APLOG_MARK,APLOG_DEBUG,OK,NULL,"%s", buff);
808
809                          * well, we must had been connecting already, so we don't do more ldap server connection checks,
810                          * and we're doing a search with cache_getuser instead of using extConfigObject dn apacheConfig object attribute value(s),
811                          * because there's no convenient function in apr api.
812                          * vhost location RDN attribute is used actually by some GUI to make things easier
813                          * TODO: use some generic ldap functions (?) classic search or implement more ldap routines for apr
814
815                          * so, we do a search below locationDnBase for config object with matches current hostname and uri..
816                          * note, that we took our current uri, and we're searching starting from / adding one by one chararacter
817                          * to match config object - access config is always the same as first matching upper url access config.
818                          * and more - if someone defined accessobject for /main and /main/subdir, the first one is used.
819                          * when upper is deleted - next below is returned, and so far..
820                          * and more - if there are two or more extConfig object for the same combination of server/uri,
821                          * then first found is returned and search isn't processed further.
822
823                          * we do a search based on original reqc->name instead of current hostname, to apply rules even if we're accessing
824                          * site via ServerAlias name
825                          */
826                         apr_snprintf(extconffiltbuf, FILTER_LENGTH,"(&(%s)(apacheExtConfigServerName=%s)(apacheExtConfigUri=%s))", conf->filter, reqc->name, buff);
827                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"ExtConfig Location Object search filter: %s", extconffiltbuf);
828                         result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wlcbasedn, conf->scope, extconfigattributes, extconffiltbuf, &dn, &extconfvals);
829                         //matched URI, if found, is returned anyway with extconfvals as ldap attribute value.
830                 }
831
832                 if(result != LDAP_SUCCESS) {
833                         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");
834                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Tried with ldap search filter: %s", extconffiltbuf);
835                 }
836                 else 
837                 {
838                         
839                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This uri has access control, configuration object is found");
840                         //we set all into extreqc struct
841                         //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extconfig buffer fill");
842                         if(extconfvals) { mvhl_doextconfig(r, extconfigattributes, extconfvals, extreqc); }
843
844                         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Entering ap_requires generation process");
845                         core_dir_config *coredirconf = (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
846                         coredirconf->ap_auth_name = extreqc->extconfname;
847                         coredirconf->ap_auth_type = (char *) "basic";
848                         char *userlist = "user nobody";
849
850             /*
851             st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module);
852             st->search_cache_ttl = 0;
853             */
854             char userfilter[FILTER_LENGTH];
855             /* we'll search for user object with custom filter applied, which has assigned matched location name and which has assigned current servername */
856             apr_snprintf(userfilter, FILTER_LENGTH, "(&(%s)(objectClass=apacheExtendedConfigUserObject)(apacheExtConfigUserServerName=%s)(apacheExtConfigUserLocationUri=%s))", conf->filter, reqc->name, buff);
857             ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"User search filter: %s", userfilter);
858
859             mvhl_webuser *extuserreqc = (mvhl_webuser *) apr_pcalloc(r->pool, sizeof(mvhl_webuser));
860             int i = 0;    
861                         if(extreqc->extusers) {
862                 log_dump_apr_array(r,extreqc->extusers,"extUser");
863                 char **extuserdns = (char **) extreqc->extusers->elts;
864                                 for (i = 0; i < extreqc->extusers->nelts; i++) {
865                                         const char **extuservals = NULL;
866                                         int result = 0;
867                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "User search basedn: %s", extuserdns[i]);
868                     //we don't use wucbasedn as we already know what webuser distinguishedname can be
869                                         char *ldap_webuser_attributes[] = { "apacheExtConfigUserName","apacheExtConfigUserServerName","userPassword", "apacheExtConfigUserDirectoryName", "apacheExtConfigUserLocationUri", 0};
870                                         result = util_ldap_cache_getuserdn(r, ldc, conf->url, extuserdns[i], LDAP_SCOPE_BASE, ldap_webuser_attributes, userfilter, &dn, &extuservals);
871                                         if(extuservals) {
872                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 0: %s", extuservals[0]);
873                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 1: %s", extuservals[1]);
874                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 2: %s", extuservals[2]);
875                                                 mvhl_doextuserconfig(r, ldap_webuser_attributes, extuservals, extuserreqc);
876                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "current username: %s", extuserreqc->webusername);
877                         userlist = apr_pstrcat(r->pool, userlist, " ", extuserreqc->webusername, NULL);
878                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "current userlist: %s", userlist);
879                                         }
880                                 }
881                         }
882                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "final userlist: %s ", userlist);
883                         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthName set to %s", coredirconf->ap_auth_name);
884                         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthType set to %s", coredirconf->ap_auth_type);
885                         ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Preparing access control line");
886                         coredirconf->ap_requires = (apr_array_header_t *) get_ap_reqs(r->pool, extreqc, reqc->name, userlist);
887                 }
888         }
889         else {
890                 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|not set) skipping..");
891         }
892 }
893 /******************************************************************/
894 static void apply_directory_access_control(mvhl_request *reqc, request_rec * r, mvhl_config *conf, util_ldap_connection_t *ldc, const char *dn) {
895
896         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This vhost has directory access control configured, need to check if it's enabled for current filename");
897         int result = 0;
898         int i = 0;
899         char extconffiltbuf[FILTER_LENGTH];
900         const char **extconfvals                = NULL;
901         char *extconfigattributes[]     = { "apacheExtConfigUri","apacheExtConfigRequireValidUser","apacheExtConfigServerName","apacheExtConfigObjectName","apacheExtConfigUserDn","apacheExtConfigPath",0}; 
902         mvhl_extconfig_object *extreqc  = (mvhl_extconfig_object *) apr_pcalloc(r->pool, sizeof(mvhl_extconfig_object));
903         char *buff = NULL;
904         
905         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extConfig Directory Objects search");
906         while(i <= strlen(apr_pstrdup(r->pool, r->filename)) && !extconfvals) {
907                 i++;
908                 buff = apr_pstrndup(r->pool, r->filename, i);
909                 /*
910                  * 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);
911                  * uncomment this, if You'd like to see in log how uri gets checked
912                  * ap_log_error(APLOG_MARK,APLOG_DEBUG,OK,NULL,"%s", buff);
913
914                  * well, we must had been connecting already, so we don't do more ldap server connection checks,
915                  * and we're doing a search with cache_getuser instead of using extConfigObject dn apacheConfig object attribute value(s),
916                  * because there's no convenient function in apr api.
917                  * vhost location RDN attribute is used actually by some GUI to make things easier
918                  * TODO: use some generic ldap functions (?) classic search or implement more ldap routines for apr
919
920                  * so, we do a search below locationDnBase for config object with matches current hostname and uri..
921                  * note, that we took our current uri, and we're searching starting from / adding one by one chararacter
922                  * to match config object - access config is always the same as first matching upper url access config.
923                  * and more - if someone defined accessobject for /main and /main/subdir, the first one is used.
924                  * when upper is deleted - next below is returned, and so far..
925                  * and more - if there are two or more extConfig object for the same combination of server/uri,
926                  * then first found is returned and search isn't processed further.
927
928                  * we do a search based on original reqc->name instead of current hostname, to apply rules even if we're accessing
929                  * site via ServerAlias name
930                  */
931                 apr_snprintf(extconffiltbuf, FILTER_LENGTH,"(&(%s)(apacheExtConfigPath=%s))", conf->filter, buff);
932                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"ExtConfig Directory Object search filter: %s", extconffiltbuf);
933                 result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wlcbasedn, conf->scope, extconfigattributes, extconffiltbuf, &dn, &extconfvals);
934                 //matched dir, if found, is returned anyway with extconfvals as ldap attribute value.
935         }
936
937         if(result != LDAP_SUCCESS) {
938                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This vhost has access control, but probably not for this directory, access config entry not found");
939                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"Tried with ldap search filter: %s", extconffiltbuf);
940         }
941         else 
942         {
943                 
944                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"This directory has access control, configuration object is found");
945                 //we set all into extreqc struct
946                 //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extconfig buffer fill");
947                 if(extconfvals) { mvhl_doextconfig(r, extconfigattributes, extconfvals, extreqc); }
948
949                 ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Entering ap_requires generation process");
950                 core_dir_config *coredirconf = (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
951                 coredirconf->ap_auth_name = extreqc->extconfname;
952                 coredirconf->ap_auth_type = (char *) "basic";
953                 char *userlist = "user nobody";
954
955         /*
956         st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module);
957         st->search_cache_ttl = 0;
958         */
959         char userfilter[FILTER_LENGTH];
960         /* we'll search for user object with custom filter applied, which has assigned matched directory name */
961         apr_snprintf(userfilter, FILTER_LENGTH, "(&(%s)(objectClass=apacheExtendedConfigUserObject)(apacheExtConfigUserDirectoryName=%s))", conf->filter, buff);
962         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,"User search filter: %s", userfilter);
963
964         mvhl_webuser *extuserreqc = (mvhl_webuser *) apr_pcalloc(r->pool, sizeof(mvhl_webuser));
965         int i = 0;    
966                 if(extreqc->extusers) {
967             log_dump_apr_array(r,extreqc->extusers,"extUser");
968             char **extuserdns = (char **) extreqc->extusers->elts;
969                         for (i = 0; i < extreqc->extusers->nelts; i++) {
970                                 const char **extuservals = NULL;
971                                 int result = 0;
972                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "User search basedn: %s", extuserdns[i]);
973                 //we don't use wucbasedn as we already know what webuser distinguishedname can be
974                                 char *ldap_webuser_attributes[] = { "apacheExtConfigUserName","apacheExtConfigUserServerName","userPassword", "apacheExtConfigUserDirectoryName", "apacheExtConfigUserLocationUri", 0};
975                                 result = util_ldap_cache_getuserdn(r, ldc, conf->url, extuserdns[i], LDAP_SCOPE_BASE, ldap_webuser_attributes, userfilter, &dn, &extuservals);
976                                 if(extuservals) {
977                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 0: %s", extuservals[0]);
978                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 1: %s", extuservals[1]);
979                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Val 2: %s", extuservals[2]);
980                                         mvhl_doextuserconfig(r, ldap_webuser_attributes, extuservals, extuserreqc);
981                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "current username: %s", extuserreqc->webusername);
982                     userlist = apr_pstrcat(r->pool, userlist, " ", extuserreqc->webusername, NULL);
983                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "current userlist: %s", userlist);
984                                 }
985                         }
986                 }
987                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "final userlist: %s ", userlist);
988                 ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthName set to %s", coredirconf->ap_auth_name);
989                 ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthType set to %s", coredirconf->ap_auth_type);
990                 ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Preparing access control line");
991                 coredirconf->ap_requires = (apr_array_header_t *) get_ap_reqs(r->pool, extreqc, reqc->name, userlist);
992         }
993         
994 }
995 /******************************************************************/
996 static int mvhl_translate_name(request_rec * r)
997 {
998         request_rec *top                        = r->main ? r->main : r;
999         apr_table_t *e                          = top->subprocess_env;
1000         
1001         //module config and current request config objects
1002         mvhl_config *conf                       = (mvhl_config *) ap_get_module_config(r->server->module_config, &vhost_ldap_module);
1003         mvhl_dump_config_request(conf, r);      //debug
1004         // mod_vhost_ldap is disabled or we don't have LDAP Url, we check these as soon as we can (after debugging dump)
1005         if(( conf->enabled == 0) || (! conf->have_ldap_url) || ( ! conf->host ) ) return DECLINED;
1006
1007         //get core config and current request config, then set current request config
1008         core_server_config *core        = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module);
1009         mvhl_request *reqc                      = (mvhl_request *) apr_pcalloc(r->pool, sizeof(mvhl_request));
1010         ap_set_module_config(r->request_config, &vhost_ldap_module, reqc);
1011
1012         const char *hostname = r->hostname;
1013         const char *dn  = NULL;
1014
1015         //we'll reuse ldap connection opened here
1016         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Opening LDAP Connection");
1017         util_ldap_connection_t *ldc     = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw,conf->deref, conf->secure);
1018
1019         //heart of the system :)        
1020         if ( conf->enabled == 0 || ! apply_vhost(conf, hostname, r, ldc, dn, reqc ) )  return DECLINED;  
1021         if (conf->alias_enabled > 0 ) apply_aliasing(reqc, r, conf, ldc, dn);
1022         if (conf->loc_auth_enabled > 0 ) apply_location_access_control(reqc, r, conf, ldc, dn);
1023         if (conf->dir_auth_enabled > 0 ) apply_directory_access_control(reqc, r, conf, ldc, dn);
1024         
1025         ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Closing LDAP Connection");
1026         util_ldap_connection_close(ldc);
1027         
1028         /* finished with Access control for location **********************************/
1029         top->server->server_hostname = apr_pstrdup(top->pool, reqc->name);
1030         if(reqc->admin) {top->server->server_admin = apr_pstrdup(top->pool, reqc->admin); }
1031
1032         // set environment variables
1033         apr_table_addn(e, "SERVER_ROOT", reqc->docroot);
1034         core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot);
1035         return OK;
1036 }
1037 /******************************************************************/
1038 static ap_unix_identity_t *mvhl_suexec_doer(const request_rec * r)
1039 {
1040         ap_unix_identity_t *ugid = NULL;
1041         mvhl_config *conf = (mvhl_config *) ap_get_module_config(r->server->module_config, &vhost_ldap_module);
1042         mvhl_request *req = (mvhl_request *) ap_get_module_config(r->request_config, &vhost_ldap_module);
1043
1044         uid_t uid = -1;
1045         gid_t gid = -1;
1046
1047         uid = (uid_t) atoll(req->uid);
1048         gid = (gid_t) atoll(req->gid);
1049
1050         // mod_vhost_ldap is disabled or we don't have LDAP Url
1051         if(
1052                 (uid < MIN_UID) || 
1053                 (gid < MIN_GID) ||
1054                 ( conf->enabled == 0 ) || 
1055                 (!conf->have_ldap_url) || 
1056                 (req == NULL) || 
1057                 (req->uid == NULL) || 
1058                 (req->gid == NULL) ||
1059                 (ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL
1060         ) {     return NULL; }
1061
1062         ugid->uid = uid;
1063         ugid->gid = gid;
1064         ugid->userdir = 0;
1065         return ugid;
1066 }
1067 /******************************************************************/
1068 static int mvhl_post_config(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * s)
1069 {
1070         /* make sure that mod_ldap (util_ldap) is loaded */
1071         if(ap_find_linked_module("util_ldap.c") == NULL) {return HTTP_INTERNAL_SERVER_ERROR;}
1072         ap_add_version_component(p, MOD_VHOST_LDAP_VERSION);
1073         return OK;
1074 }
1075 /******************************************************************/
1076 static const command_rec mvhl_cmds[] = {
1077         AP_INIT_TAKE1("VhostLdapUrl",                   conf_mvhl_url,  NULL,                           RSRC_CONF,"RFC 2255 URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]]."),
1078         AP_INIT_TAKE1("VhostLdapEnabled",               conf_mvhl,              MVHL_ENABLED,           RSRC_CONF,"Set to off or unset to disable vhost_ldap module completely"),
1079         AP_INIT_TAKE1("VhostAliasesEnabled",    conf_mvhl,              MVHL_ALIASENABLED,      RSRC_CONF,"Set to off or unset to disable ldap-based dir aliases"),
1080         AP_INIT_TAKE1("VhostLocAuthEnabled",    conf_mvhl,              MVHL_LAUTHENABLED,      RSRC_CONF,"Set to off or unset to disable per-location authentication"),
1081         AP_INIT_TAKE1("VhostDirAuthEnabled",    conf_mvhl,              MVHL_DAUTHENABLED,      RSRC_CONF,"Set to off or unset to disable per-location authentication"),
1082         AP_INIT_TAKE1("VhostLdapBindDn",                conf_mvhl,              MVHL_BINDDN,            RSRC_CONF,"DN to use to bind to LDAP server"),
1083         AP_INIT_TAKE1("VhostLdapBindPw",                conf_mvhl,              MVHL_BINDPW,            RSRC_CONF,"Password to use to bind to LDAP server"),
1084         AP_INIT_TAKE1("VhostLdapWlcBaseDn",             conf_mvhl,              MVHL_WLCBASEDN,         RSRC_CONF,"Base DN to do all access control config searches."),
1085         AP_INIT_TAKE1("VhostLdapWucBaseDn",             conf_mvhl,              MVHL_WUCBASEDN,         RSRC_CONF,"Base DN to do all user config searches"),
1086         AP_INIT_TAKE1("VhostLdapAliasesBaseDn", conf_mvhl,              MVHL_ALIASBASEDN,       RSRC_CONF,"Base DN to do all aliases config searches"),
1087         AP_INIT_TAKE1("VhostLdapFallback",      conf_mvhl,              MVHL_FALLBACK,          RSRC_CONF,"Fallback vhost server name to use - to display not-found info"),
1088         AP_INIT_TAKE1("VhostLdapDeref",                 conf_mvhl,              MVHL_DEREF,                     RSRC_CONF,"values: never, searching, finding, always"),  
1089         {NULL}
1090 };
1091 /******************************************************************/
1092 static void mvhl_register_hooks(apr_pool_t * p)
1093 {
1094         ap_hook_post_config(mvhl_post_config, NULL, NULL, APR_HOOK_MIDDLE);
1095         ap_hook_translate_name(mvhl_translate_name, NULL, NULL, APR_HOOK_MIDDLE);
1096         ap_hook_get_suexec_identity(mvhl_suexec_doer, NULL, NULL, APR_HOOK_MIDDLE);
1097         ap_hook_check_user_id(mvhl_authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE);
1098         ap_hook_auth_checker(mvhl_check_auth, NULL, NULL, APR_HOOK_MIDDLE);
1099 }
1100 /******************************************************************/
1101 module AP_MODULE_DECLARE_DATA vhost_ldap_module = {
1102         STANDARD20_MODULE_STUFF,                                
1103         NULL,                           // create per-directory config structure
1104         NULL,                           // merge per-directory config structures, default is to override
1105         mvhl_create_sconfig,// called when module configuration data needs to be created/allocated.
1106         mvhl_merge_sconfig,     // merge per-server config structures
1107         mvhl_cmds,                      // Here we pass in the list of new configuration directives.
1108         mvhl_register_hooks,// register me in apache core
1109 };
This page took 0.708447 seconds and 5 git commands to generate.