]>
Commit | Line | Data |
---|---|---|
7f9875bb | 1 | /* ============================================================ |
63a07100 | 2 | * Copyright (c) 2003-2006, Ondrej Sury, Piotr Wadas |
7f9875bb OS |
3 | * All rights reserved. |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | * | |
17 | */ | |
18 | ||
63a07100 PW |
19 | /* NOTE: only static members must be "used" to build, so for time-to-time used routines we don't declare static */ |
20 | ||
7f9875bb OS |
21 | /* |
22 | * mod_vhost_ldap.c --- read virtual host config from LDAP directory | |
63a07100 | 23 | * version 2.0 - included ldap-based basic auth & authz |
7f9875bb OS |
24 | */ |
25 | ||
63a07100 PW |
26 | //remember to add "-lcrypt" in Makefile if there's a need to generate new password |
27 | // for now not needed (validation only), this below is almost copy-paste from apache source, htpasswd.c | |
28 | /* | |
29 | ||
30 | #include "crypt.h" | |
31 | #include "time.h" | |
32 | ||
33 | void to64(char *s, unsigned long v, int n) | |
34 | { | |
35 | static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
36 | while (--n >= 0) { | |
37 | *s++ = itoa64[v&0x3f]; | |
38 | v >>= 6; | |
39 | } | |
40 | } | |
41 | ||
42 | char *htenc(const char *clearpasswd) { | |
43 | char *res; | |
44 | char salt[9]; | |
45 | (void) srand((int) time((time_t *) NULL)); | |
46 | to64(&salt[0], rand(), 8); | |
47 | salt[8] = '\0'; | |
48 | res = crypt(clearpasswd, salt); | |
49 | return res; | |
50 | } | |
9ee2dda1 | 51 | |
63a07100 PW |
52 | */ |
53 | ||
54 | #define CORE_PRIVATE | |
7f9875bb OS |
55 | |
56 | #include "httpd.h" | |
57 | #include "http_config.h" | |
58 | #include "http_core.h" | |
59 | #include "http_log.h" | |
60 | #include "http_request.h" | |
61 | #include "apr_ldap.h" | |
62 | #include "apr_strings.h" | |
63 | #include "apr_reslist.h" | |
64 | #include "util_ldap.h" | |
63a07100 PW |
65 | #include "apr_md5.h" |
66 | #include "apr_sha1.h" | |
67 | #include "unistd.h" | |
7f9875bb OS |
68 | |
69 | #ifndef APU_HAS_LDAP | |
63a07100 | 70 | #fatal "mod_vhost_ldap requires APR util to have LDAP support built in" |
7f9875bb OS |
71 | #endif |
72 | ||
73 | #if !defined(WIN32) && !defined(OS2) && !defined(BEOS) && !defined(NETWARE) | |
74 | #define HAVE_UNIX_SUEXEC | |
75 | #endif | |
76 | ||
77 | #ifdef HAVE_UNIX_SUEXEC | |
63a07100 | 78 | #include "unixd.h" /* Contains the suexec_identity hook used on Unix */ |
7f9875bb OS |
79 | #endif |
80 | ||
63a07100 PW |
81 | /* do not accept empty "" strings */ |
82 | #define strtrue(s) (s && *s) | |
83 | ||
d129bb81 OS |
84 | #define MIN_UID 100 |
85 | #define MIN_GID 100 | |
63a07100 | 86 | #define FILTER_LENGTH MAX_STRING_LEN |
7f9875bb OS |
87 | |
88 | module AP_MODULE_DECLARE_DATA vhost_ldap_module; | |
89 | ||
63a07100 PW |
90 | typedef enum mod_vhost_ldap_status_e { |
91 | MVL_UNSET, | |
92 | MVL_DISABLED, | |
93 | MVL_ENABLED | |
8196fae3 | 94 | } mod_vhost_ldap_status_e; |
7f9875bb | 95 | typedef struct mod_vhost_ldap_config_t { |
63a07100 PW |
96 | mod_vhost_ldap_status_e enabled; /* Is vhost_ldap enabled? */ |
97 | ||
98 | char *url; /* String representation of LDAP URL */ | |
99 | char *host; /* Name of the LDAP server (or space separated list) */ | |
100 | int port; /* Port of the LDAP server */ | |
101 | char *basedn; /* Base DN to do all searches from */ | |
102 | int scope; /* Scope of the search */ | |
103 | char *filter; /* Filter to further limit the search */ | |
104 | deref_options deref; /* how to handle alias dereferening */ | |
105 | char *binddn; /* DN to bind to server (can be NULL) */ | |
106 | char *bindpw; /* Password to bind to server (can be NULL) xx */ | |
107 | int have_deref; /* Set if we have found an Deref option */ | |
108 | int have_ldap_url; /* Set if we have found an LDAP url */ | |
109 | char *wlcbasedn; /* Base DN to do all location config searches */ | |
110 | char *wucbasedn; /* Base DN to do all webuser config searches */ | |
111 | int secure; /* True if SSL connections are requested */ | |
112 | } mod_vhost_ldap_config_t; | |
113 | typedef struct mod_vhost_ldap_request_t { | |
114 | char *dn; /* The saved dn from a successful search */ | |
115 | char *name; /* apacheServerName */ | |
116 | char *admin; /* apacheServerAdmin */ | |
117 | char *docroot; /* apacheDocumentRoot */ | |
118 | char *uid; /* Suexec Uid */ | |
119 | char *gid; /* Suexec Gid */ | |
120 | int has_reqlines; /* placeholder */ | |
121 | apr_array_header_t *serveralias; /* apacheServerAlias */ | |
122 | apr_array_header_t *rqlocationlines; /* apacheServerAlias */ | |
7f9875bb | 123 | |
63a07100 PW |
124 | } mod_vhost_ldap_request_t; |
125 | typedef struct mod_vhost_ldap_extconfig_object_t { /* what the hell this "t" means ??. eh, whatever ;) */ | |
126 | //we use apr_array_header_t for multi-value attributed, parsed later (yuck!) from grr ";" separated string | |
127 | char *extconfname; /* apacheExtConfigObjectName, single-value, syntax SUP cn */ | |
128 | char *exturi; /* apacheExtConfigUri, single-value, uri for which this settings are here | |
129 | * should be used in combine with extconfig server name */ | |
130 | int extconftype; /* apacheExtConfigRequireValidUser, single-value bool, | |
131 | * if TRUE then require valid-user, if FALSE userlist-type config | |
132 | */ | |
133 | ||
134 | apr_array_header_t *extservername; /* apacheExtConfigServerName",MULTI-value, | |
135 | * e.g. for http://anyserver/statistics (?), syntax SUP cn | |
136 | */ | |
137 | apr_array_header_t *extusers; /* "apacheExtConfigUserDn", MULTI-value, syntax SUP DN */ | |
138 | ||
139 | } mod_vhost_ldap_extconfig_object_t; | |
140 | typedef struct mod_vhost_ldap_webuser_t { | |
141 | ||
142 | char *webusername; /* apacheExtConfigUserName, single-value */ | |
143 | apr_array_header_t *webuserpassword; /* userPassword, multi-value */ | |
144 | char *webuserserver; /* apacheExtConfigUserServerName, server of this user, multi-value */ | |
145 | ||
146 | } mod_vhost_ldap_webuser_t; | |
147 | static int strschrcount(apr_pool_t * p, const char *src, const char *delim) | |
148 | { | |
149 | int i = 1; | |
150 | int x = 0; | |
151 | while(*src++) { | |
152 | if(strcasecmp(apr_pstrndup(p, src, i), (char *) delim) == 0) { | |
153 | x++; | |
154 | } | |
155 | } | |
156 | return x; | |
157 | } | |
158 | void log_dump_apr_array(request_rec * r, apr_array_header_t * arr, const char *prefix) | |
159 | { | |
160 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering log_dump_apr_array"); | |
161 | int x = 0; | |
162 | char **aliases = (char **) arr->elts; | |
163 | for (x = 0; x < arr->nelts; x++) { | |
164 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " log_dump_apr_array val %d %s %s", x, prefix, aliases[x]); | |
165 | } | |
166 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving log_dump_apr_array"); | |
167 | } | |
168 | static apr_array_header_t *get_parsed_string_atrr_arr(request_rec * r, const char *server_alias_attrvar_line, | |
169 | const char *delim) | |
170 | { | |
171 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering get_parsed_string_atrr_arr |%s|", server_alias_attrvar_line); | |
172 | if(server_alias_attrvar_line) { | |
7f9875bb | 173 | |
63a07100 PW |
174 | apr_collapse_spaces((char *) server_alias_attrvar_line, server_alias_attrvar_line); |
175 | int ccount = strschrcount(r->pool, server_alias_attrvar_line, delim) + 1; | |
7f9875bb | 176 | |
63a07100 PW |
177 | apr_array_header_t *aliases_arr = apr_array_make(r->pool, ccount, sizeof(char *)); |
178 | char **curralias; | |
179 | curralias = (char **) apr_array_push(aliases_arr); | |
7f9875bb | 180 | |
63a07100 PW |
181 | char *curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';'); |
182 | char *tmp = apr_pstrdup(r->pool, (char *) curr_server_alias);; | |
183 | *curralias = tmp; | |
7f9875bb | 184 | |
6056cddb | 185 | |
63a07100 PW |
186 | while(server_alias_attrvar_line[0]) { |
187 | curr_server_alias = ap_getword(r->pool, &server_alias_attrvar_line, ';'); | |
188 | curralias = (char **) apr_array_push(aliases_arr); | |
189 | tmp = apr_pstrdup(r->pool, (char *) curr_server_alias); | |
190 | *curralias = tmp; | |
191 | } | |
192 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr OK"); | |
193 | return aliases_arr; | |
194 | } | |
195 | else | |
196 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Leaving get_parsed_string_atrr_arr NULL"); | |
197 | return NULL; | |
198 | } | |
199 | static apr_array_header_t *get_ap_reqs(apr_pool_t * p, mod_vhost_ldap_extconfig_object_t * extreqc, | |
200 | char *mainservername, char *userlist) | |
201 | { | |
6056cddb | 202 | |
63a07100 | 203 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," get_ap_reqs Entering"); |
7f9875bb | 204 | |
63a07100 | 205 | apr_array_header_t *res = apr_array_make(p, 2, sizeof(require_line)); |
7f9875bb | 206 | |
63a07100 PW |
207 | require_line *rline; |
208 | apr_int64_t limited = -1; | |
7f9875bb | 209 | |
63a07100 | 210 | rline = (require_line *) apr_array_push(res); |
7f9875bb | 211 | |
63a07100 PW |
212 | //currently we don't support playing with request types |
213 | rline->method_mask = limited; | |
7f9875bb | 214 | |
63a07100 PW |
215 | if(extreqc->extconftype == 1) { |
216 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = TRUE server %s",mainservername); | |
217 | rline->requirement = apr_pstrdup(p, (char *) "valid-user"); | |
218 | } | |
219 | else { | |
220 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, " get_ap_reqs require valid-user = FALSE server %s",mainservername); | |
221 | ||
222 | rline->requirement = apr_pstrdup(p, userlist); | |
223 | } | |
224 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL," Leaving get_ap_reqs, returning require line |require %s|", rline->requirement); | |
225 | return res; | |
226 | } | |
227 | static void mod_vhost_ldap_dovhostconfig(request_rec * r, char *attributes[], const char **vals, | |
228 | mod_vhost_ldap_request_t * reqc) | |
229 | { | |
7f9875bb | 230 | |
63a07100 PW |
231 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " dovhostconfig Entering "); |
232 | int i = 0; | |
233 | while(attributes[i]) { | |
234 | ||
235 | if(strcasecmp(attributes[i], "apacheServerName") == 0) { | |
236 | reqc->name = apr_pstrdup(r->pool, vals[i]); | |
237 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d apacheServerName %s", i, reqc->name); | |
238 | } | |
239 | ||
240 | if(strcasecmp(attributes[i], "apacheServerAdmin") == 0) { | |
241 | reqc->admin = apr_pstrdup(r->pool, vals[i]); | |
242 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheServerAdmin %s", i, reqc->admin); | |
243 | } | |
244 | ||
245 | if(strcasecmp(attributes[i], "apacheDocumentRoot") == 0) { | |
246 | reqc->docroot = apr_pstrdup(r->pool, vals[i]); | |
247 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheDocumentRoot %s", i, reqc->docroot); | |
248 | } | |
249 | ||
250 | if(strcasecmp(attributes[i], "apacheSuexecUid") == 0) { | |
251 | reqc->uid = apr_pstrdup(r->pool, vals[i]); | |
252 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheSuexecUid %s", i, reqc->uid); | |
253 | } | |
254 | ||
255 | if(strcasecmp(attributes[i], "apacheSuexecGid") == 0) { | |
256 | reqc->gid = apr_pstrdup(r->pool, vals[i]); | |
257 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheSuexecGid %s", i, reqc->gid); | |
258 | } | |
259 | ||
260 | if(strcasecmp(attributes[i], "apacheExtConfigHasRequireLine") == 0) { | |
261 | if(vals[i]) { | |
262 | reqc->has_reqlines = strcasecmp("TRUE", apr_pstrdup(r->pool, vals[i])) == 0 ? 1 : 0; | |
263 | ||
264 | if(reqc->has_reqlines) { | |
265 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d Vhost %s has extended access configuration", i, reqc->name); | |
266 | } | |
267 | } | |
268 | else { | |
269 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " %d Vhost %s doesn't have extended access configuration", i, reqc->name); | |
270 | } | |
271 | } | |
272 | ||
273 | if(strcasecmp(attributes[i], "apacheServerAlias") == 0) { | |
274 | if(vals[i]) { | |
275 | reqc->serveralias = | |
276 | (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], | |
277 | (const char *) ";"); | |
278 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheServerAlias is set", i); | |
279 | } | |
280 | else { | |
281 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d No apacheServerAlias for this vhost found", i); | |
282 | reqc->serveralias = NULL; | |
283 | } | |
284 | } | |
285 | ||
286 | if(strcasecmp(attributes[i], "apacheLocationOptionsDn") == 0) { | |
287 | if(vals[i]) { | |
288 | reqc->rqlocationlines = | |
289 | (apr_array_header_t *) get_parsed_string_atrr_arr(r, vals[i], | |
290 | (const char *) ";"); | |
291 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, " %d apacheLocationOptionsDn is set", i); | |
292 | } | |
293 | else { | |
294 | 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); | |
295 | reqc->rqlocationlines = NULL; | |
296 | } | |
297 | } | |
298 | i++; | |
299 | } | |
300 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " dovhostconfig Leaving "); | |
7f9875bb | 301 | } |
63a07100 PW |
302 | static void mod_vhost_ldap_doextconfig(request_rec * r, char *extconfigattributes[], const char **extconfvals, |
303 | mod_vhost_ldap_extconfig_object_t * extreqc) | |
304 | { | |
305 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextconfig Entering "); | |
306 | int i = 0; | |
7f9875bb | 307 | |
63a07100 PW |
308 | while(extconfigattributes[i]) { |
309 | if(strcasecmp(extconfigattributes[i], "apacheExtConfigObjectName") == 0) { | |
310 | extreqc->extconfname = apr_pstrdup(r->pool, extconfvals[i]); | |
311 | } | |
312 | ||
313 | if(strcasecmp(extconfigattributes[i], "apacheExtConfigUri") == 0) { | |
314 | extreqc->exturi = apr_pstrdup(r->pool, extconfvals[i]); | |
315 | } | |
316 | ||
317 | if(strcasecmp(extconfigattributes[i], "apacheExtConfigRequireValidUser") == 0) { | |
318 | if(extconfvals[i]) { | |
319 | ||
320 | //this value determines whether we have "require valid-user" object (TRUE) , | |
321 | //or (FALSE) object "require user johny mary dorothy witch" | |
322 | //here set retrieved value, regardless what it is, to play with it later. | |
323 | extreqc->extconftype = | |
324 | strcasecmp("TRUE", apr_pstrdup(r->pool, extconfvals[i])) == 0 ? 1 : 0; | |
325 | 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])); | |
326 | } | |
327 | else { | |
328 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " For this ext config require valid-user is not set"); | |
329 | } | |
330 | } | |
331 | ||
332 | if(strcasecmp(extconfigattributes[i], "apacheExtConfigServerName") == 0) { | |
333 | ||
334 | if(extconfvals[i]) { | |
335 | extreqc->extservername = | |
336 | (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], | |
337 | (const char *) ";"); | |
338 | } | |
339 | else { | |
340 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
341 | " No ExtServerName values found"); | |
342 | extreqc->extservername = NULL; | |
343 | } | |
344 | } | |
345 | ||
346 | if(strcasecmp(extconfigattributes[i], "apacheExtConfigUserDn") == 0) { | |
347 | ||
348 | if(extconfvals[i]) { | |
349 | extreqc->extusers = | |
350 | (apr_array_header_t *) get_parsed_string_atrr_arr(r, extconfvals[i], | |
351 | (const char *) ";"); | |
352 | } | |
353 | else { | |
354 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
355 | " apacheExtConfigUserDn values NOT found (any valid-user or no users specified."); | |
356 | extreqc->extusers = NULL; | |
357 | } | |
358 | } | |
359 | ||
360 | i++; | |
361 | } | |
362 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextconfig Leaving "); | |
363 | } | |
364 | static void mod_vhost_ldap_doextuserconfig(request_rec * r, char *ldap_webuser_attributes[], const char **extuservals, | |
365 | mod_vhost_ldap_webuser_t * extuserreqc) | |
7f9875bb | 366 | { |
63a07100 PW |
367 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextuserconfig Entering"); |
368 | int i = 0; | |
369 | while(ldap_webuser_attributes[i]) { | |
370 | if(strcasecmp(ldap_webuser_attributes[i], "apacheExtConfigUserName") == 0) { | |
371 | extuserreqc->webusername = apr_pstrdup(r->pool, extuservals[i]); | |
372 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
373 | "%d apacheExtConfigUserName set to %s", i, extuserreqc->webusername); | |
374 | } | |
375 | if(strcasecmp(ldap_webuser_attributes[i], "apacheExtConfigUserServerName") == 0) { | |
376 | extuserreqc->webuserserver = apr_pstrdup(r->pool, extuservals[i]); | |
377 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
378 | "%d apacheExtConfigUserServerName set to %s", i, extuserreqc->webuserserver); | |
379 | } | |
380 | if(strcasecmp(ldap_webuser_attributes[i], "userPassword") == 0) { | |
381 | extuserreqc->webuserpassword = | |
382 | (apr_array_header_t *) get_parsed_string_atrr_arr(r, extuservals[i], | |
383 | (const char *) ";"); | |
384 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
385 | "%d userPassword retrievied", i); | |
386 | } | |
387 | i++; | |
388 | } | |
389 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " doextuserconfig Leaving"); | |
8196fae3 | 390 | } |
63a07100 PW |
391 | static int mod_vhost_ldap_authenticate_basic_user(request_rec * r) |
392 | { | |
393 | const char *sent_pw; | |
394 | mod_vhost_ldap_webuser_t *extuserreqc; | |
395 | extuserreqc = (mod_vhost_ldap_webuser_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_webuser_t)); | |
396 | int rc = ap_get_basic_auth_pw(r, &sent_pw); | |
397 | if(rc != OK) | |
398 | return rc; | |
399 | if(strtrue(r->user) && strtrue(sent_pw)) { | |
400 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " Entering mod_vhost_ldap_authenticate_basic_user"); | |
401 | ||
402 | char userfilter[FILTER_LENGTH]; | |
403 | mod_vhost_ldap_config_t *conf = | |
404 | (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); | |
405 | ||
406 | const char *dn = NULL; | |
407 | util_ldap_connection_t *ldc = NULL; | |
408 | const char **extuservals = NULL; | |
409 | int result = 0; | |
410 | char *ldap_webuser_attributes[] = | |
411 | { "apacheExtConfigUserName", "apacheExtConfigUserServerName", "userPassword", 0 }; | |
412 | ||
413 | apr_snprintf(userfilter, FILTER_LENGTH, "(&(apacheExtConfigUserName=%s)(apacheExtConfigUserServerName=%s))", r->user,r->server->server_hostname); | |
414 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " AuthUser search filter: %s", userfilter); | |
415 | ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, conf->deref, | |
416 | conf->secure); | |
417 | result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wucbasedn, conf->scope, | |
418 | ldap_webuser_attributes, userfilter, &dn, &extuservals); | |
419 | util_ldap_connection_close(ldc); | |
420 | ||
421 | if(extuservals) { | |
422 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, " User %s found.", r->user); | |
423 | ||
424 | mod_vhost_ldap_doextuserconfig(r, ldap_webuser_attributes, extuservals, extuserreqc); | |
425 | ||
426 | int x = 0; | |
427 | char **passwords = (char **) extuserreqc->webuserpassword->elts; | |
428 | for (x = 0; x < extuserreqc->webuserpassword->nelts; x++) { | |
429 | if ( ( apr_password_validate(sent_pw, passwords[x]) == OK) || strcasecmp(sent_pw,passwords[x]) == 0 ) { | |
430 | ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, " Authentication for user %s at %s successful.", extuserreqc->webusername, r->server->server_hostname); | |
431 | return OK; | |
432 | } | |
433 | } | |
434 | ||
435 | } | |
436 | else { | |
437 | ap_log_rerror(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, r, " User %s at %s not found", extuserreqc->webusername, r->server->server_hostname); | |
438 | return HTTP_UNAUTHORIZED; | |
439 | } | |
440 | } | |
441 | else { | |
442 | ap_note_basic_auth_failure(r); | |
443 | ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, | |
444 | ": Both a username and password must be provided : authentication for user %s at %s failed.", | |
445 | extuserreqc->webusername, r->server->server_hostname); | |
446 | return HTTP_UNAUTHORIZED; | |
447 | } | |
448 | ap_note_basic_auth_failure(r); | |
449 | ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "Authentication for user %s at %s failed.", | |
450 | extuserreqc->webusername, r->server->server_hostname); | |
451 | return HTTP_UNAUTHORIZED; | |
8196fae3 | 452 | |
63a07100 PW |
453 | } |
454 | static int check_mod_vhost_ldap_auth_require(char *user, const char *t, request_rec * r) | |
8196fae3 | 455 | { |
63a07100 PW |
456 | const char *w; |
457 | w = ap_getword(r->pool, &t, ' '); | |
458 | if(!strcmp(w, "valid-user")) { | |
7f9875bb | 459 | |
63a07100 PW |
460 | return OK; |
461 | } | |
8196fae3 | 462 | |
63a07100 PW |
463 | if(!strcmp(w, "user")) { |
464 | while(t[0]) { | |
465 | w = ap_getword_conf(r->pool, &t); | |
466 | if(!strcmp(user, w)) { | |
8196fae3 | 467 | |
63a07100 | 468 | return OK; |
6056cddb | 469 | |
63a07100 PW |
470 | } |
471 | } | |
472 | return HTTP_UNAUTHORIZED; | |
473 | } | |
474 | else { | |
7f9875bb | 475 | |
63a07100 PW |
476 | return HTTP_INTERNAL_SERVER_ERROR; |
477 | } | |
478 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
479 | ": %s : Reached end of check_mod_vhost_ldap_auth_require!", r->server->server_hostname); | |
480 | return HTTP_INTERNAL_SERVER_ERROR; | |
481 | } | |
482 | static int mod_vhost_ldap_check_auth(request_rec * r) | |
7f9875bb | 483 | { |
63a07100 PW |
484 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, |
485 | ": mod_vhost_ldap_check_auth, parsing existing ap_requires for %s at %s ", r->user, r->server->server_hostname); | |
486 | char *user = r->user; | |
487 | int rv; | |
488 | register int x; | |
489 | const char *t; | |
490 | const apr_array_header_t *reqs_arr = ap_requires(r); | |
491 | ||
492 | require_line *reqs; | |
493 | reqs = (require_line *) reqs_arr->elts; | |
494 | ||
495 | for (x = 0; x < reqs_arr->nelts; x++) { | |
496 | t = reqs[x].requirement; | |
497 | if((rv = check_mod_vhost_ldap_auth_require(user, t, r)) != HTTP_UNAUTHORIZED) { | |
498 | return rv; | |
499 | } | |
500 | } | |
7f9875bb | 501 | |
7f9875bb | 502 | |
63a07100 PW |
503 | ap_note_basic_auth_failure(r); |
504 | return HTTP_UNAUTHORIZED; | |
7f9875bb | 505 | } |
63a07100 PW |
506 | static void *mod_vhost_ldap_create_server_config(apr_pool_t * p, server_rec * s) |
507 | { | |
7f9875bb | 508 | |
63a07100 PW |
509 | mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *) apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t)); |
510 | conf->enabled = MVL_UNSET; | |
511 | conf->have_ldap_url = 0; | |
512 | conf->have_deref = 0; | |
513 | conf->binddn = NULL; | |
514 | conf->bindpw = NULL; | |
515 | conf->deref = always; | |
516 | conf->wlcbasedn = NULL; | |
517 | conf->wucbasedn = NULL; | |
518 | ||
519 | return conf; | |
520 | } | |
521 | static void *mod_vhost_ldap_merge_server_config(apr_pool_t * p, void *parentv, void *childv) | |
7f9875bb | 522 | { |
63a07100 PW |
523 | mod_vhost_ldap_config_t *parent = (mod_vhost_ldap_config_t *) parentv; |
524 | mod_vhost_ldap_config_t *child = (mod_vhost_ldap_config_t *) childv; | |
525 | mod_vhost_ldap_config_t *conf = (mod_vhost_ldap_config_t *) apr_pcalloc(p, sizeof(mod_vhost_ldap_config_t)); | |
526 | ||
527 | conf->enabled = (child->enabled == MVL_UNSET ? parent->enabled : child->enabled); | |
528 | ||
529 | if(child->have_ldap_url) { | |
530 | conf->have_ldap_url = child->have_ldap_url; | |
531 | conf->url = child->url; | |
532 | conf->host = child->host; | |
533 | conf->port = child->port; | |
534 | conf->basedn = child->basedn; | |
535 | conf->scope = child->scope; | |
536 | conf->filter = child->filter; | |
537 | conf->secure = child->secure; | |
538 | conf->wlcbasedn = child->wlcbasedn; | |
539 | conf->wucbasedn = child->wucbasedn; | |
540 | } | |
541 | else { | |
542 | conf->have_ldap_url = parent->have_ldap_url; | |
543 | conf->url = parent->url; | |
544 | conf->host = parent->host; | |
545 | conf->port = parent->port; | |
546 | conf->basedn = parent->basedn; | |
547 | conf->scope = parent->scope; | |
548 | conf->filter = parent->filter; | |
549 | conf->secure = parent->secure; | |
550 | conf->wlcbasedn = parent->wlcbasedn; | |
551 | conf->wucbasedn = parent->wucbasedn; | |
7f9875bb | 552 | |
63a07100 PW |
553 | } |
554 | if(child->have_deref) { | |
555 | conf->have_deref = child->have_deref; | |
556 | conf->deref = child->deref; | |
557 | } | |
558 | else { | |
559 | conf->have_deref = parent->have_deref; | |
560 | conf->deref = parent->deref; | |
561 | } | |
8196fae3 | 562 | |
63a07100 PW |
563 | conf->binddn = (child->binddn ? child->binddn : parent->binddn); |
564 | conf->bindpw = (child->bindpw ? child->bindpw : parent->bindpw); | |
565 | return conf; | |
7f9875bb | 566 | } |
63a07100 | 567 | static const char *mod_vhost_ldap_parse_url(cmd_parms * cmd, void *dummy, const char *url) |
7f9875bb | 568 | { |
63a07100 PW |
569 | int result; |
570 | apr_ldap_url_desc_t *urld; | |
571 | ||
572 | mod_vhost_ldap_config_t *conf = | |
573 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
574 | ||
575 | result = apr_ldap_url_parse(url, &(urld)); | |
576 | ||
577 | if(result != LDAP_SUCCESS) { | |
578 | switch (result) { | |
579 | case LDAP_URL_ERR_NOTLDAP: | |
580 | return "LDAP URL does not begin with ldap://"; | |
581 | case LDAP_URL_ERR_NODN: | |
582 | return "LDAP URL does not have a DN"; | |
583 | case LDAP_URL_ERR_BADSCOPE: | |
584 | return "LDAP URL has an invalid scope"; | |
585 | case LDAP_URL_ERR_MEM: | |
586 | return "Out of memory parsing LDAP URL"; | |
587 | default: | |
588 | return "Could not parse LDAP URL"; | |
589 | } | |
590 | } | |
591 | conf->url = apr_pstrdup(cmd->pool, url); | |
592 | ||
593 | /* Set all the values, or at least some sane defaults */ | |
594 | if(conf->host) { | |
595 | char *p = apr_palloc(cmd->pool, strlen(conf->host) + strlen(urld->lud_host) + 2); | |
596 | strcpy(p, urld->lud_host); | |
597 | strcat(p, " "); | |
598 | strcat(p, conf->host); | |
599 | conf->host = p; | |
600 | } | |
601 | else { | |
602 | conf->host = urld->lud_host ? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost"; | |
603 | } | |
604 | conf->basedn = urld->lud_dn ? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; | |
605 | ||
606 | conf->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; | |
607 | ||
608 | if(urld->lud_filter) { | |
609 | if(urld->lud_filter[0] == '(') { | |
610 | /* | |
611 | * Get rid of the surrounding parens; later on when generating the | |
612 | * filter, they'll be put back. | |
613 | */ | |
614 | conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter + 1); | |
615 | conf->filter[strlen(conf->filter) - 1] = '\0'; | |
616 | } | |
617 | else { | |
618 | conf->filter = apr_pstrdup(cmd->pool, urld->lud_filter); | |
619 | } | |
620 | } | |
621 | else { | |
622 | conf->filter = "objectClass=apacheConfig"; | |
623 | } | |
7f9875bb | 624 | |
63a07100 PW |
625 | /* "ldaps" indicates secure ldap connections desired |
626 | */ | |
627 | if(strncasecmp(url, "ldaps", 5) == 0) { | |
628 | conf->secure = 1; | |
629 | conf->port = urld->lud_port ? urld->lud_port : LDAPS_PORT; | |
7f9875bb | 630 | |
63a07100 PW |
631 | } |
632 | else { | |
633 | conf->secure = 0; | |
634 | conf->port = urld->lud_port ? urld->lud_port : LDAP_PORT; | |
635 | } | |
7f9875bb | 636 | |
63a07100 PW |
637 | conf->have_ldap_url = 1; |
638 | apr_ldap_free_urldesc(urld); | |
639 | return NULL; | |
7f9875bb | 640 | } |
63a07100 | 641 | static const char *mod_vhost_ldap_set_enabled(cmd_parms * cmd, void *dummy, int enabled) |
7f9875bb | 642 | { |
63a07100 PW |
643 | mod_vhost_ldap_config_t *conf = |
644 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
645 | conf->enabled = (enabled) ? MVL_ENABLED : MVL_DISABLED; | |
646 | return NULL; | |
7f9875bb | 647 | } |
63a07100 PW |
648 | static const char *mod_vhost_ldap_set_binddn(cmd_parms * cmd, void *dummy, const char *binddn) |
649 | { | |
650 | mod_vhost_ldap_config_t *conf = | |
651 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
652 | conf->binddn = apr_pstrdup(cmd->pool, binddn); | |
653 | return NULL; | |
654 | } | |
655 | static const char *mod_vhost_ldap_set_wucbasedn(cmd_parms * cmd, void *dummy, const char *wucbasedn) | |
656 | { | |
657 | mod_vhost_ldap_config_t *conf = | |
658 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
659 | conf->wucbasedn = apr_pstrdup(cmd->pool, wucbasedn); | |
660 | return NULL; | |
661 | } | |
662 | static const char *mod_vhost_ldap_set_wlcbasedn(cmd_parms * cmd, void *dummy, const char *wlcbasedn) | |
6056cddb | 663 | { |
6056cddb | 664 | |
63a07100 PW |
665 | mod_vhost_ldap_config_t *conf = |
666 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
667 | conf->wlcbasedn = apr_pstrdup(cmd->pool, wlcbasedn); | |
668 | return NULL; | |
669 | } | |
670 | static const char *mod_vhost_ldap_set_bindpw(cmd_parms * cmd, void *dummy, const char *bindpw) | |
671 | { | |
672 | mod_vhost_ldap_config_t *conf = | |
673 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
674 | conf->bindpw = apr_pstrdup(cmd->pool, bindpw); | |
675 | return NULL; | |
676 | } | |
677 | static const char *mod_vhost_ldap_set_deref(cmd_parms * cmd, void *dummy, const char *deref) | |
678 | { | |
679 | mod_vhost_ldap_config_t *conf = | |
680 | (mod_vhost_ldap_config_t *) ap_get_module_config(cmd->server->module_config, &vhost_ldap_module); | |
681 | if(deref) { | |
682 | if(strcmp(deref, "never") == 0 || strcmp(deref, "searching") == 0 || strcmp(deref, "finding") == 0 | |
683 | || strcmp(deref, "always") == 0) { | |
684 | conf->deref = *deref; | |
685 | conf->have_deref = 1; | |
686 | } | |
687 | else { | |
688 | return "Unrecognized value for VhostLDAPAliasDereference directive"; | |
689 | } | |
690 | } | |
691 | return NULL; | |
6056cddb OS |
692 | } |
693 | ||
7f9875bb | 694 | |
63a07100 PW |
695 | |
696 | static int mod_vhost_ldap_translate_name(request_rec * r) | |
7f9875bb | 697 | { |
63a07100 PW |
698 | char filtbuf[FILTER_LENGTH]; |
699 | char extconffiltbuf[FILTER_LENGTH]; | |
700 | apr_table_t *e; | |
701 | request_rec *top; | |
702 | mod_vhost_ldap_config_t *conf; | |
703 | mod_vhost_ldap_request_t *reqc; | |
704 | mod_vhost_ldap_extconfig_object_t *extreqc; | |
705 | core_server_config *core; | |
706 | ||
707 | util_ldap_connection_t *ldc = NULL; | |
708 | const char **vals, **extconfvals = NULL; | |
709 | const char *dn = NULL; | |
710 | const char *hostname = NULL; | |
711 | int failures = 0; | |
712 | int i = 0; | |
713 | int result = 0; | |
7f9875bb | 714 | |
63a07100 PW |
715 | /* |
716 | * more info about attributes in typedefs definitions and schema desc | |
717 | * PS. Did You ever wonder why they used this damned weird "\0", instead, | |
718 | * let's say, '$' or 'EndOfWord' or whatever ?? | |
719 | */ | |
7f9875bb | 720 | |
63a07100 PW |
721 | char *attributes[] = { "apacheServerName", "apacheServerAlias", "apacheDocumentRoot", |
722 | "apacheSuexecUid", "apacheSuexecGid", "apacheServerAdmin", | |
723 | "apacheExtConfigHasRequireLine", "apacheLocationOptionsDn", | |
724 | 0 | |
725 | }; | |
7f9875bb | 726 | |
63a07100 PW |
727 | char *extconfigattributes[] = { "apacheExtConfigUri", "apacheExtConfigRequireValidUser", |
728 | "apacheExtConfigServerName", "apacheExtConfigObjectName", | |
729 | "apacheExtConfigUserDn", | |
730 | 0 | |
731 | }; | |
6056cddb | 732 | |
63a07100 PW |
733 | //we assume we're in trouble, and will change it, if not. |
734 | result = LDAP_SERVER_DOWN; | |
6056cddb | 735 | |
63a07100 PW |
736 | top = r->main ? r->main : r; |
737 | hostname = r->hostname; | |
7f9875bb | 738 | |
63a07100 PW |
739 | //get our module config options |
740 | conf = (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); | |
7f9875bb | 741 | |
63a07100 PW |
742 | //a reference to core config |
743 | core = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module); | |
7f9875bb | 744 | |
63a07100 PW |
745 | //and some variable initialization |
746 | reqc = (mod_vhost_ldap_request_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_request_t)); | |
747 | extreqc = (mod_vhost_ldap_extconfig_object_t *) apr_pcalloc(r->pool, sizeof(mod_vhost_ldap_extconfig_object_t)); | |
7f9875bb | 748 | |
63a07100 PW |
749 | //current request config get set |
750 | ap_set_module_config(r->request_config, &vhost_ldap_module, reqc); | |
7f9875bb | 751 | |
63a07100 PW |
752 | // mod_vhost_ldap is disabled or we don't have LDAP Url |
753 | if((conf->enabled != MVL_ENABLED) || (!conf->have_ldap_url)) { | |
754 | return DECLINED; | |
6056cddb OS |
755 | } |
756 | ||
63a07100 | 757 | if(conf->host) { |
6056cddb | 758 | |
63a07100 PW |
759 | apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", |
760 | conf->filter, hostname, hostname); | |
6056cddb | 761 | |
63a07100 PW |
762 | while(failures++ <= 5 && result == LDAP_SERVER_DOWN) { |
763 | //searching for connection | |
764 | ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, | |
765 | conf->deref, conf->secure); | |
766 | result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->basedn, conf->scope, attributes, | |
767 | filtbuf, &dn, &vals); | |
768 | util_ldap_connection_close(ldc); | |
769 | } | |
770 | } | |
771 | else { | |
772 | return DECLINED; | |
773 | } | |
7f9875bb | 774 | |
63a07100 PW |
775 | if(result != LDAP_SUCCESS) { |
776 | return DECLINED; | |
777 | } | |
7f9875bb | 778 | |
63a07100 PW |
779 | reqc->dn = apr_pstrdup(r->pool, dn); |
780 | ||
781 | if(vals) { | |
782 | //this translate_name function we're in is long enough, don't You think? | |
783 | //we set all into reqc struct | |
784 | mod_vhost_ldap_dovhostconfig(r, attributes, vals, reqc); | |
7f9875bb | 785 | } |
7f9875bb | 786 | |
63a07100 | 787 | if((reqc->name == NULL) || (reqc->docroot == NULL)) { |
7f9875bb | 788 | |
63a07100 | 789 | return DECLINED; |
7f9875bb | 790 | } |
7f9875bb | 791 | |
63a07100 PW |
792 | if(r->uri[0] == '/') { |
793 | r->filename = apr_pstrcat(r->pool, reqc->docroot, r->uri, NULL); | |
794 | } | |
795 | else { | |
796 | return DECLINED; | |
797 | } | |
7f9875bb | 798 | |
63a07100 PW |
799 | if(reqc->has_reqlines == 1 && reqc->rqlocationlines) { |
800 | ||
801 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
802 | "This vhost has access control configured, need to check if it's enabled for current uri"); | |
803 | result = 0; | |
804 | i = 0; | |
805 | ||
806 | //we have mercy, and do not open a connection for each uri search ;) | |
807 | ||
808 | ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, conf->deref, | |
809 | conf->secure); | |
810 | ||
811 | //ask Your programming teacher, what's all about with | |
812 | // these "NO, TRY _VERY_ HARD, AND THEN TRY AGAIN _NOT_ TO USE BREAK FOR LOOP LEAVING" ;) | |
813 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extConfig Objects search"); | |
814 | while(i <= strlen(apr_pstrdup(r->pool, r->uri)) && !extconfvals) { | |
815 | i++; | |
816 | char *buff = apr_pstrndup(r->pool, r->uri, i); | |
817 | //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); | |
818 | //uncomment this, if You'd like to see in log how uri gets checked | |
819 | //ap_log_error(APLOG_MARK,APLOG_DEBUG,OK,NULL,"%s", buff); | |
820 | ||
821 | //well, we must had been connecting already, so we don't do more ldap server connection checks, | |
822 | //and we're doing a search with cache_getuser instead of using extConfigObject dn apacheConfig object attribute value(s), | |
823 | //because there's no convenient function in apr api. | |
824 | //vhost location RDN attribute is used actually by some GUI to make things easier | |
825 | //TODO: use some generic ldap functions (?) classic search or implement more ldap routines for apr | |
826 | ||
827 | //so, we do a search below locationDnBase for config object with matches current hostname and uri.. | |
828 | //note, that we took our current uri, and we're searching starting from / adding one by one chararacter | |
829 | //to match config object - access config is always the same as first matching upper url access config. | |
830 | //and more - if someone defined accessobject for /main and /main/subdir, the first one is used. | |
831 | //when upper is deleted - next below is returned, and so far.. | |
832 | //and more - if there are two or more extConfig object for the same combination of server/uri, | |
833 | //then first found is returned and search isn't processed further. | |
834 | ||
835 | //we do a search based on original reqc->name instead of current hostname, to apply rules even if we're accessing | |
836 | //site via ServerAlias name | |
837 | apr_snprintf(extconffiltbuf, FILTER_LENGTH, | |
838 | "(&(apacheExtConfigServerName=%s)(apacheExtConfigUri=%s))", reqc->name, buff); | |
839 | ||
840 | result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wlcbasedn, conf->scope, | |
841 | extconfigattributes, extconffiltbuf, &dn, &extconfvals); | |
842 | ||
843 | //matched URI, if found, is returned anyway with extconfvals as ldap attribute value. | |
844 | } | |
845 | //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Closing LDAP Connection"); | |
846 | util_ldap_connection_close(ldc); | |
847 | ||
848 | if(result != LDAP_SUCCESS) { | |
849 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
850 | "This vhost has access control, but probably not for this URI, access config entry not found"); | |
851 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
852 | "Tried with ldap search filter: %s", extconffiltbuf); | |
853 | } | |
854 | else { | |
855 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
856 | "This uri has access control, configuration object is found"); | |
857 | ||
858 | if(extconfvals) { | |
859 | //this translate_name function we're in is long enough, don't You think? | |
860 | //we set all into extreqc struct | |
861 | //ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "Entering extconfig buffer fill"); | |
862 | mod_vhost_ldap_doextconfig(r, extconfigattributes, extconfvals, extreqc); | |
863 | } | |
864 | ||
865 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Entering ap_requires generation process"); | |
866 | ||
867 | core_dir_config *coredirconf = | |
868 | (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module); | |
869 | coredirconf->ap_auth_name = extreqc->extconfname; | |
870 | coredirconf->ap_auth_type = (char *) "basic"; | |
871 | char *userlist = "user nobody"; | |
872 | ||
873 | if(extreqc->extusers) { | |
874 | mod_vhost_ldap_webuser_t *extuserreqc; | |
875 | extuserreqc = | |
876 | (mod_vhost_ldap_webuser_t *) apr_pcalloc(r->pool, | |
877 | sizeof(mod_vhost_ldap_webuser_t)); | |
878 | char *ldap_webuser_attributes[] = | |
879 | { "apacheExtConfigUserName", "apacheExtConfigUserServerName", "userPassword", | |
880 | 0 | |
881 | }; | |
882 | ldc = util_ldap_connection_find(r, conf->host, conf->port, conf->binddn, conf->bindpw, | |
883 | conf->deref, conf->secure); | |
884 | int i = 0; | |
885 | for (i = 0; i < extreqc->extusers->nelts; i++) { | |
886 | char userfilter[FILTER_LENGTH]; | |
887 | ||
888 | const char **extuservals = NULL; | |
889 | int result = 0; | |
890 | apr_snprintf(userfilter, FILTER_LENGTH, | |
891 | "(&(objectClass=apacheExtendedConfigUserObject)(apacheExtConfigUserServerName=%s))", | |
892 | reqc->name); | |
893 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
894 | "User search filter: %s", userfilter); | |
895 | result = util_ldap_cache_getuserdn(r, ldc, conf->url, conf->wucbasedn, | |
896 | conf->scope, ldap_webuser_attributes, | |
897 | userfilter, &dn, &extuservals); | |
898 | if(extuservals) { | |
899 | mod_vhost_ldap_doextuserconfig(r, ldap_webuser_attributes, extuservals, | |
900 | extuserreqc); | |
901 | } | |
902 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
903 | "current username: %s", extuserreqc->webusername); | |
904 | ||
905 | userlist = apr_pstrcat(r->pool, userlist, " ", extuserreqc->webusername, NULL); | |
906 | ||
907 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
908 | "current userlist: %s", userlist); | |
909 | } | |
910 | ||
911 | util_ldap_connection_close(ldc); | |
912 | } | |
913 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, "final userlist: %s ", userlist); | |
914 | ||
915 | ||
916 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthName set to %s", coredirconf->ap_auth_name); | |
917 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "AuthType set to %s", coredirconf->ap_auth_type); | |
918 | ap_log_error(APLOG_MARK, APLOG_DEBUG, OK, NULL, "Preparing access control line"); | |
919 | coredirconf->ap_requires = | |
920 | (apr_array_header_t *) get_ap_reqs(r->pool, extreqc, reqc->name, userlist); | |
921 | ||
922 | } | |
923 | } | |
924 | else { | |
925 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, | |
926 | "This vhost is not configured for access control, or it is disabled via apacheExtConfigHasRequireLine = FALSE skipping.."); | |
927 | } | |
7f9875bb | 928 | |
63a07100 | 929 | top->server->server_hostname = apr_pstrdup(top->pool, reqc->name); |
7f9875bb | 930 | |
9ee2dda1 | 931 | |
63a07100 PW |
932 | if(reqc->admin) { |
933 | top->server->server_admin = apr_pstrdup(top->pool, reqc->admin); | |
934 | } | |
7f9875bb | 935 | |
63a07100 PW |
936 | // set environment variables |
937 | e = top->subprocess_env; | |
938 | apr_table_addn(e, "SERVER_ROOT", reqc->docroot); | |
939 | core->ap_document_root = apr_pstrdup(top->pool, reqc->docroot); | |
940 | return OK; | |
7f9875bb OS |
941 | } |
942 | ||
943 | #ifdef HAVE_UNIX_SUEXEC | |
944 | static ap_unix_identity_t *mod_vhost_ldap_get_suexec_id_doer(const request_rec * r) | |
945 | { | |
63a07100 PW |
946 | ap_unix_identity_t *ugid = NULL; |
947 | mod_vhost_ldap_config_t *conf = | |
948 | (mod_vhost_ldap_config_t *) ap_get_module_config(r->server->module_config, &vhost_ldap_module); | |
949 | mod_vhost_ldap_request_t *req = | |
950 | (mod_vhost_ldap_request_t *) ap_get_module_config(r->request_config, &vhost_ldap_module); | |
951 | ||
952 | uid_t uid = -1; | |
953 | gid_t gid = -1; | |
954 | ||
955 | // mod_vhost_ldap is disabled or we don't have LDAP Url | |
956 | if((conf->enabled != MVL_ENABLED) || (!conf->have_ldap_url)) { | |
957 | return NULL; | |
958 | } | |
959 | ||
960 | if((req == NULL) || (req->uid == NULL) || (req->gid == NULL)) { | |
961 | return NULL; | |
962 | } | |
963 | ||
964 | if((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t))) == NULL) { | |
965 | return NULL; | |
966 | } | |
967 | ||
968 | uid = (uid_t) atoll(req->uid); | |
969 | gid = (gid_t) atoll(req->gid); | |
970 | ||
971 | if((uid < MIN_UID) || (gid < MIN_GID)) { | |
972 | return NULL; | |
973 | } | |
974 | ||
975 | ugid->uid = uid; | |
976 | ugid->gid = gid; | |
977 | ugid->userdir = 0; | |
978 | ||
979 | return ugid; | |
7f9875bb OS |
980 | } |
981 | #endif | |
982 | ||
63a07100 | 983 | static int mod_vhost_ldap_post_config(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * s) |
7f9875bb | 984 | { |
63a07100 PW |
985 | /* make sure that mod_ldap (util_ldap) is loaded */ |
986 | if(ap_find_linked_module("util_ldap.c") == NULL) { | |
987 | return HTTP_INTERNAL_SERVER_ERROR; | |
988 | } | |
989 | ||
990 | ap_add_version_component(p, MOD_VHOST_LDAP_VERSION); | |
991 | return OK; | |
992 | } | |
993 | ||
994 | static void mod_vhost_ldap_register_hooks(apr_pool_t * p) | |
995 | { | |
996 | ap_hook_post_config(mod_vhost_ldap_post_config, NULL, NULL, APR_HOOK_MIDDLE); | |
997 | ap_hook_translate_name(mod_vhost_ldap_translate_name, NULL, NULL, APR_HOOK_MIDDLE); | |
7f9875bb | 998 | #ifdef HAVE_UNIX_SUEXEC |
63a07100 | 999 | ap_hook_get_suexec_identity(mod_vhost_ldap_get_suexec_id_doer, NULL, NULL, APR_HOOK_MIDDLE); |
7f9875bb | 1000 | #endif |
63a07100 PW |
1001 | ap_hook_check_user_id(mod_vhost_ldap_authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE); |
1002 | ap_hook_auth_checker(mod_vhost_ldap_check_auth, NULL, NULL, APR_HOOK_MIDDLE); | |
7f9875bb OS |
1003 | } |
1004 | ||
63a07100 PW |
1005 | static const command_rec mod_vhost_ldap_cmds[] = { |
1006 | ||
1007 | AP_INIT_TAKE1("VhostLDAPURL", mod_vhost_ldap_parse_url, NULL, RSRC_CONF, | |
1008 | "URL to define LDAP connection. This should be an RFC 2255 compliant\n" | |
1009 | "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n" | |
1010 | "<ul>\n" | |
1011 | "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n" | |
1012 | "to specify redundant servers.\n" | |
1013 | "<li>Port is optional, and specifies the port to connect to.\n" | |
1014 | "<li>basedn specifies the base DN to start searches from\n" "</ul>\n"), | |
1015 | ||
1016 | AP_INIT_TAKE1("VhostLDAPBindDN", mod_vhost_ldap_set_binddn, NULL, RSRC_CONF, | |
1017 | "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."), | |
1018 | ||
1019 | AP_INIT_TAKE1("VhostLDAPBindPassword", mod_vhost_ldap_set_bindpw, NULL, RSRC_CONF, | |
1020 | "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."), | |
1021 | ||
1022 | AP_INIT_FLAG("VhostLDAPEnabled", mod_vhost_ldap_set_enabled, NULL, RSRC_CONF, | |
1023 | "Set to off to disable vhost_ldap, even if it's been enabled in a higher tree"), | |
1024 | ||
1025 | AP_INIT_TAKE1("VhostLDAPDereferenceAliases", mod_vhost_ldap_set_deref, NULL, RSRC_CONF, | |
1026 | "Determines how aliases are handled during a search. Can be one of the" | |
1027 | "values \"never\", \"searching\", \"finding\", or \"always\". " "Defaults to always."), | |
1028 | ||
1029 | AP_INIT_TAKE1("VhostLDAPWebLocationConfigBaseDn", mod_vhost_ldap_set_wlcbasedn, NULL, RSRC_CONF, | |
1030 | "Base DN to do all location config searches."), | |
1031 | ||
1032 | AP_INIT_TAKE1("VhostLDAPWebUsersBaseDn", mod_vhost_ldap_set_wucbasedn, NULL, RSRC_CONF, | |
1033 | "Base DN to do all location config searches"), | |
1034 | ||
1035 | {NULL} | |
1036 | }; | |
1037 | ||
7f9875bb | 1038 | module AP_MODULE_DECLARE_DATA vhost_ldap_module = { |
63a07100 PW |
1039 | STANDARD20_MODULE_STUFF, // jakas lista |
1040 | NULL, // create per-directory config structure | |
1041 | NULL, // merge per-directory config structures, default is to override | |
1042 | mod_vhost_ldap_create_server_config, // called when module configuration data needs to be created/allocated. | |
1043 | mod_vhost_ldap_merge_server_config, // merge per-server config structures | |
1044 | mod_vhost_ldap_cmds, // Here we pass in the list of new configuration directives. | |
1045 | mod_vhost_ldap_register_hooks, // register me in apache core | |
7f9875bb | 1046 | }; |