xref: /lighttpd1.4/src/mod_auth.c (revision 00cc4d7c)
18abd06a7SGlenn Strauss #include "first.h"
28abd06a7SGlenn Strauss 
322e8b456SStefan Bühler #include "plugin.h"
422e8b456SStefan Bühler #include "http_auth.h"
522e8b456SStefan Bühler #include "log.h"
622e8b456SStefan Bühler #include "response.h"
722e8b456SStefan Bühler 
8bcdc6a3bSJan Kneschke #include <sys/types.h>
9bcdc6a3bSJan Kneschke #include <sys/stat.h>
10bcdc6a3bSJan Kneschke 
11bcdc6a3bSJan Kneschke #include <stdlib.h>
12bcdc6a3bSJan Kneschke #include <string.h>
13bcdc6a3bSJan Kneschke #include <errno.h>
14bcdc6a3bSJan Kneschke #include <fcntl.h>
15bcdc6a3bSJan Kneschke #include <unistd.h>
16bcdc6a3bSJan Kneschke 
17ea7b9abaSJan Kneschke handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
18ea7b9abaSJan Kneschke 
19bcdc6a3bSJan Kneschke 
20bcdc6a3bSJan Kneschke /**
21bcdc6a3bSJan Kneschke  * the basic and digest auth framework
22bcdc6a3bSJan Kneschke  *
23bcdc6a3bSJan Kneschke  * - config handling
24bcdc6a3bSJan Kneschke  * - protocol handling
25bcdc6a3bSJan Kneschke  *
26bcdc6a3bSJan Kneschke  * http_auth.c
27bcdc6a3bSJan Kneschke  * http_auth_digest.c
28bcdc6a3bSJan Kneschke  *
29bcdc6a3bSJan Kneschke  * do the real work
30bcdc6a3bSJan Kneschke  */
31bcdc6a3bSJan Kneschke 
32bcdc6a3bSJan Kneschke INIT_FUNC(mod_auth_init) {
33bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p;
34bcdc6a3bSJan Kneschke 
35bcdc6a3bSJan Kneschke 	p = calloc(1, sizeof(*p));
36bcdc6a3bSJan Kneschke 
37bcdc6a3bSJan Kneschke 	p->tmp_buf = buffer_init();
38bcdc6a3bSJan Kneschke 
39bcdc6a3bSJan Kneschke 	p->auth_user = buffer_init();
40bcdc6a3bSJan Kneschke #ifdef USE_LDAP
41bcdc6a3bSJan Kneschke 	p->ldap_filter = buffer_init();
42bcdc6a3bSJan Kneschke #endif
43bcdc6a3bSJan Kneschke 
44bcdc6a3bSJan Kneschke 	return p;
45bcdc6a3bSJan Kneschke }
46bcdc6a3bSJan Kneschke 
47bcdc6a3bSJan Kneschke FREE_FUNC(mod_auth_free) {
48bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
49bcdc6a3bSJan Kneschke 
50bcdc6a3bSJan Kneschke 	UNUSED(srv);
51bcdc6a3bSJan Kneschke 
52bcdc6a3bSJan Kneschke 	if (!p) return HANDLER_GO_ON;
53bcdc6a3bSJan Kneschke 
54bcdc6a3bSJan Kneschke 	buffer_free(p->tmp_buf);
55bcdc6a3bSJan Kneschke 	buffer_free(p->auth_user);
56bcdc6a3bSJan Kneschke #ifdef USE_LDAP
57bcdc6a3bSJan Kneschke 	buffer_free(p->ldap_filter);
58bcdc6a3bSJan Kneschke #endif
59bcdc6a3bSJan Kneschke 
60bcdc6a3bSJan Kneschke 	if (p->config_storage) {
61bcdc6a3bSJan Kneschke 		size_t i;
62bcdc6a3bSJan Kneschke 		for (i = 0; i < srv->config_context->used; i++) {
63bcdc6a3bSJan Kneschke 			mod_auth_plugin_config *s = p->config_storage[i];
64bcdc6a3bSJan Kneschke 
6533cebeb0SStefan Bühler 			if (NULL == s) continue;
664a6ce4aeSJan Kneschke 
67bcdc6a3bSJan Kneschke 			array_free(s->auth_require);
68bcdc6a3bSJan Kneschke 			buffer_free(s->auth_plain_groupfile);
69bcdc6a3bSJan Kneschke 			buffer_free(s->auth_plain_userfile);
70bcdc6a3bSJan Kneschke 			buffer_free(s->auth_htdigest_userfile);
71bcdc6a3bSJan Kneschke 			buffer_free(s->auth_htpasswd_userfile);
72bcdc6a3bSJan Kneschke 			buffer_free(s->auth_backend_conf);
73bcdc6a3bSJan Kneschke 
74bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_hostname);
75bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_basedn);
769238cad6SJan Kneschke 			buffer_free(s->auth_ldap_binddn);
779238cad6SJan Kneschke 			buffer_free(s->auth_ldap_bindpw);
78bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_filter);
794a6ce4aeSJan Kneschke 			buffer_free(s->auth_ldap_cafile);
80bcdc6a3bSJan Kneschke 
81bcdc6a3bSJan Kneschke #ifdef USE_LDAP
82bcdc6a3bSJan Kneschke 			buffer_free(s->ldap_filter_pre);
83bcdc6a3bSJan Kneschke 			buffer_free(s->ldap_filter_post);
84bcdc6a3bSJan Kneschke 
85bcdc6a3bSJan Kneschke 			if (s->ldap) ldap_unbind_s(s->ldap);
86bcdc6a3bSJan Kneschke #endif
87bcdc6a3bSJan Kneschke 
88bcdc6a3bSJan Kneschke 			free(s);
89bcdc6a3bSJan Kneschke 		}
90bcdc6a3bSJan Kneschke 		free(p->config_storage);
91bcdc6a3bSJan Kneschke 	}
92bcdc6a3bSJan Kneschke 
93bcdc6a3bSJan Kneschke 	free(p);
94bcdc6a3bSJan Kneschke 
95bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
96bcdc6a3bSJan Kneschke }
97bcdc6a3bSJan Kneschke 
98bcdc6a3bSJan Kneschke #define PATCH(x) \
99bcdc6a3bSJan Kneschke 	p->conf.x = s->x;
1004a6ce4aeSJan Kneschke static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
101bcdc6a3bSJan Kneschke 	size_t i, j;
1024a6ce4aeSJan Kneschke 	mod_auth_plugin_config *s = p->config_storage[0];
1034a6ce4aeSJan Kneschke 
1044a6ce4aeSJan Kneschke 	PATCH(auth_backend);
1054a6ce4aeSJan Kneschke 	PATCH(auth_plain_groupfile);
1064a6ce4aeSJan Kneschke 	PATCH(auth_plain_userfile);
1074a6ce4aeSJan Kneschke 	PATCH(auth_htdigest_userfile);
1084a6ce4aeSJan Kneschke 	PATCH(auth_htpasswd_userfile);
1094a6ce4aeSJan Kneschke 	PATCH(auth_require);
1104a6ce4aeSJan Kneschke 	PATCH(auth_debug);
1114a6ce4aeSJan Kneschke 	PATCH(auth_ldap_hostname);
1124a6ce4aeSJan Kneschke 	PATCH(auth_ldap_basedn);
1139238cad6SJan Kneschke 	PATCH(auth_ldap_binddn);
1149238cad6SJan Kneschke 	PATCH(auth_ldap_bindpw);
1154a6ce4aeSJan Kneschke 	PATCH(auth_ldap_filter);
1164a6ce4aeSJan Kneschke 	PATCH(auth_ldap_cafile);
1174a6ce4aeSJan Kneschke 	PATCH(auth_ldap_starttls);
118d471bcc9SMarcus Rückert 	PATCH(auth_ldap_allow_empty_pw);
1194a6ce4aeSJan Kneschke #ifdef USE_LDAP
120cfba07cbSStefan Bühler 	p->anon_conf = s;
1214a6ce4aeSJan Kneschke 	PATCH(ldap_filter_pre);
1224a6ce4aeSJan Kneschke 	PATCH(ldap_filter_post);
1234a6ce4aeSJan Kneschke #endif
124bcdc6a3bSJan Kneschke 
125bcdc6a3bSJan Kneschke 	/* skip the first, the global context */
126bcdc6a3bSJan Kneschke 	for (i = 1; i < srv->config_context->used; i++) {
127bcdc6a3bSJan Kneschke 		data_config *dc = (data_config *)srv->config_context->data[i];
1284a6ce4aeSJan Kneschke 		s = p->config_storage[i];
129bcdc6a3bSJan Kneschke 
130bcdc6a3bSJan Kneschke 		/* condition didn't match */
131bcdc6a3bSJan Kneschke 		if (!config_check_cond(srv, con, dc)) continue;
132bcdc6a3bSJan Kneschke 
133bcdc6a3bSJan Kneschke 		/* merge config */
134bcdc6a3bSJan Kneschke 		for (j = 0; j < dc->value->used; j++) {
135bcdc6a3bSJan Kneschke 			data_unset *du = dc->value->data[j];
136bcdc6a3bSJan Kneschke 
137bcdc6a3bSJan Kneschke 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
138bcdc6a3bSJan Kneschke 				PATCH(auth_backend);
139bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
140bcdc6a3bSJan Kneschke 				PATCH(auth_plain_groupfile);
141bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
142bcdc6a3bSJan Kneschke 				PATCH(auth_plain_userfile);
143bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
144bcdc6a3bSJan Kneschke 				PATCH(auth_htdigest_userfile);
145bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
146bcdc6a3bSJan Kneschke 				PATCH(auth_htpasswd_userfile);
147bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
148bcdc6a3bSJan Kneschke 				PATCH(auth_require);
149bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
150bcdc6a3bSJan Kneschke 				PATCH(auth_debug);
151bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
152bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_hostname);
153bcdc6a3bSJan Kneschke #ifdef USE_LDAP
154cfba07cbSStefan Bühler 				p->anon_conf = s;
155bcdc6a3bSJan Kneschke #endif
156bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
157bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_basedn);
158bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
159bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_filter);
160ba715e1cSStefan Bühler #ifdef USE_LDAP
161ba715e1cSStefan Bühler 				PATCH(ldap_filter_pre);
162ba715e1cSStefan Bühler 				PATCH(ldap_filter_post);
163ba715e1cSStefan Bühler #endif
1644a6ce4aeSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
1654a6ce4aeSJan Kneschke 				PATCH(auth_ldap_cafile);
1664a6ce4aeSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
1674a6ce4aeSJan Kneschke 				PATCH(auth_ldap_starttls);
16886766c10SStefan Bühler 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-dn"))) {
16986766c10SStefan Bühler 				PATCH(auth_ldap_binddn);
17086766c10SStefan Bühler 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-pw"))) {
17186766c10SStefan Bühler 				PATCH(auth_ldap_bindpw);
172d471bcc9SMarcus Rückert 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
173d471bcc9SMarcus Rückert 				PATCH(auth_ldap_allow_empty_pw);
174bcdc6a3bSJan Kneschke 			}
175bcdc6a3bSJan Kneschke 		}
176bcdc6a3bSJan Kneschke 	}
177bcdc6a3bSJan Kneschke 
178bcdc6a3bSJan Kneschke 	return 0;
179bcdc6a3bSJan Kneschke }
180bcdc6a3bSJan Kneschke #undef PATCH
181bcdc6a3bSJan Kneschke 
182bcdc6a3bSJan Kneschke static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
183bcdc6a3bSJan Kneschke 	size_t k;
184bcdc6a3bSJan Kneschke 	int auth_required = 0, auth_satisfied = 0;
185bcdc6a3bSJan Kneschke 	char *http_authorization = NULL;
1867187271fSStefan Bühler 	const char *auth_type = NULL;
187bcdc6a3bSJan Kneschke 	data_string *ds;
188bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
189bcdc6a3bSJan Kneschke 	array *req;
190f9d58670SStefan Bühler 	data_string *req_method;
191bcdc6a3bSJan Kneschke 
192bcdc6a3bSJan Kneschke 	/* select the right config */
1934a6ce4aeSJan Kneschke 	mod_auth_patch_connection(srv, con, p);
194bcdc6a3bSJan Kneschke 
195bcdc6a3bSJan Kneschke 	if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
196bcdc6a3bSJan Kneschke 
197bcdc6a3bSJan Kneschke 	/*
198bcdc6a3bSJan Kneschke 	 * AUTH
199bcdc6a3bSJan Kneschke 	 *
200bcdc6a3bSJan Kneschke 	 */
201bcdc6a3bSJan Kneschke 
202bcdc6a3bSJan Kneschke 	/* do we have to ask for auth ? */
203bcdc6a3bSJan Kneschke 
204bcdc6a3bSJan Kneschke 	auth_required = 0;
205bcdc6a3bSJan Kneschke 	auth_satisfied = 0;
206bcdc6a3bSJan Kneschke 
207bcdc6a3bSJan Kneschke 	/* search auth-directives for path */
208bcdc6a3bSJan Kneschke 	for (k = 0; k < p->conf.auth_require->used; k++) {
20967079527SJan Kneschke 		buffer *require = p->conf.auth_require->data[k]->key;
210bcdc6a3bSJan Kneschke 
211ad3e93eaSStefan Bühler 		if (buffer_is_empty(require)) continue;
212ad3e93eaSStefan Bühler 		if (buffer_string_length(con->uri.path) < buffer_string_length(require)) continue;
2134afd2ae2SJan Kneschke 
2144afd2ae2SJan Kneschke 		/* if we have a case-insensitive FS we have to lower-case the URI here too */
2154afd2ae2SJan Kneschke 
2164afd2ae2SJan Kneschke 		if (con->conf.force_lowercase_filenames) {
217ad3e93eaSStefan Bühler 			if (0 == strncasecmp(con->uri.path->ptr, require->ptr, buffer_string_length(require))) {
218bcdc6a3bSJan Kneschke 				auth_required = 1;
219bcdc6a3bSJan Kneschke 				break;
220bcdc6a3bSJan Kneschke 			}
2214afd2ae2SJan Kneschke 		} else {
222ad3e93eaSStefan Bühler 			if (0 == strncmp(con->uri.path->ptr, require->ptr, buffer_string_length(require))) {
2234afd2ae2SJan Kneschke 				auth_required = 1;
2244afd2ae2SJan Kneschke 				break;
2254afd2ae2SJan Kneschke 			}
2264afd2ae2SJan Kneschke 		}
227bcdc6a3bSJan Kneschke 	}
228bcdc6a3bSJan Kneschke 
229bcdc6a3bSJan Kneschke 	/* nothing to do for us */
230bcdc6a3bSJan Kneschke 	if (auth_required == 0) return HANDLER_GO_ON;
231bcdc6a3bSJan Kneschke 
232bcdc6a3bSJan Kneschke 	req = ((data_array *)(p->conf.auth_require->data[k]))->value;
233f9d58670SStefan Bühler 	req_method = (data_string *)array_get_element(req, "method");
234f9d58670SStefan Bühler 
235f9d58670SStefan Bühler 	if (0 == strcmp(req_method->value->ptr, "extern")) {
236f9d58670SStefan Bühler 		/* require REMOTE_USER to be already set */
237f9d58670SStefan Bühler 		if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
238f9d58670SStefan Bühler 			con->http_status = 401;
239f9d58670SStefan Bühler 			con->mode = DIRECT;
240f9d58670SStefan Bühler 			return HANDLER_FINISHED;
241f9d58670SStefan Bühler 		} else if (http_auth_match_rules(srv, req, ds->value->ptr, NULL, NULL)) {
242f9d58670SStefan Bühler 			log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
243f9d58670SStefan Bühler 			con->http_status = 401;
244f9d58670SStefan Bühler 			con->mode = DIRECT;
245f9d58670SStefan Bühler 			return HANDLER_FINISHED;
246f9d58670SStefan Bühler 		} else {
247f9d58670SStefan Bühler 			return HANDLER_GO_ON;
248f9d58670SStefan Bühler 		}
249f9d58670SStefan Bühler 	}
250bcdc6a3bSJan Kneschke 
251bcdc6a3bSJan Kneschke 	/* try to get Authorization-header */
252bcdc6a3bSJan Kneschke 
253ad3e93eaSStefan Bühler 	if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization")) && !buffer_is_empty(ds->value)) {
254bcdc6a3bSJan Kneschke 		char *auth_realm;
255bcdc6a3bSJan Kneschke 
256f9d58670SStefan Bühler 		http_authorization = ds->value->ptr;
257bcdc6a3bSJan Kneschke 
258bcdc6a3bSJan Kneschke 		/* parse auth-header */
259bcdc6a3bSJan Kneschke 		if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
260bcdc6a3bSJan Kneschke 			int auth_type_len = auth_realm - http_authorization;
261bcdc6a3bSJan Kneschke 
262bcdc6a3bSJan Kneschke 			if ((auth_type_len == 5) &&
263708f499dSJan Kneschke 			    (0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
2647187271fSStefan Bühler 				auth_type = "Basic";
265bcdc6a3bSJan Kneschke 
266f9d58670SStefan Bühler 				if (0 == strcmp(req_method->value->ptr, "basic")) {
2672bcf65c2SStefan Bühler 					auth_satisfied = http_auth_basic_check(srv, con, p, req, auth_realm+1);
268bcdc6a3bSJan Kneschke 				}
269bcdc6a3bSJan Kneschke 			} else if ((auth_type_len == 6) &&
270708f499dSJan Kneschke 				   (0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
2717187271fSStefan Bühler 				auth_type = "Digest";
272f9d58670SStefan Bühler 				if (0 == strcmp(req_method->value->ptr, "digest")) {
2732bcf65c2SStefan Bühler 					if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, auth_realm+1))) {
274bcdc6a3bSJan Kneschke 						con->http_status = 400;
275ad12e4c5SStefan Bühler 						con->mode = DIRECT;
276bcdc6a3bSJan Kneschke 
277bcdc6a3bSJan Kneschke 						/* a field was missing */
278bcdc6a3bSJan Kneschke 
279bcdc6a3bSJan Kneschke 						return HANDLER_FINISHED;
280bcdc6a3bSJan Kneschke 					}
281bcdc6a3bSJan Kneschke 				}
282bcdc6a3bSJan Kneschke 			} else {
283bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
284780e8e6eSStefan Bühler 						"unknown authentication type:",
285bcdc6a3bSJan Kneschke 						http_authorization);
286bcdc6a3bSJan Kneschke 			}
287bcdc6a3bSJan Kneschke 		}
288bcdc6a3bSJan Kneschke 	}
289bcdc6a3bSJan Kneschke 
290*00cc4d7cSGlenn Strauss 	if (1 != auth_satisfied) { /*(0 or -2)*/
291bcdc6a3bSJan Kneschke 		data_string *method, *realm;
292bcdc6a3bSJan Kneschke 		method = (data_string *)array_get_element(req, "method");
293bcdc6a3bSJan Kneschke 		realm = (data_string *)array_get_element(req, "realm");
294bcdc6a3bSJan Kneschke 
295bcdc6a3bSJan Kneschke 		con->http_status = 401;
296ad12e4c5SStefan Bühler 		con->mode = DIRECT;
297bcdc6a3bSJan Kneschke 
29872b133f5SGlenn Strauss 		if (!method) return HANDLER_FINISHED;/*(should not happen; config is validated at startup)*/
29972b133f5SGlenn Strauss 		if (!realm) return HANDLER_FINISHED; /*(should not happen; config is validated at startup)*/
30072b133f5SGlenn Strauss 
301bcdc6a3bSJan Kneschke 		if (0 == strcmp(method->value->ptr, "basic")) {
30252861d77SStefan Bühler 			buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Basic realm=\""));
303bcdc6a3bSJan Kneschke 			buffer_append_string_buffer(p->tmp_buf, realm->value);
3044b412797SGlenn Strauss 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", charset=\"UTF-8\""));
305bcdc6a3bSJan Kneschke 
306bcdc6a3bSJan Kneschke 			response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
307bcdc6a3bSJan Kneschke 		} else if (0 == strcmp(method->value->ptr, "digest")) {
308bcdc6a3bSJan Kneschke 			char hh[33];
309e5006d88SGlenn Strauss 			http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, &hh);
310bcdc6a3bSJan Kneschke 
31152861d77SStefan Bühler 			buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Digest realm=\""));
312bcdc6a3bSJan Kneschke 			buffer_append_string_buffer(p->tmp_buf, realm->value);
3134b412797SGlenn Strauss 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", charset=\"UTF-8\", nonce=\""));
314*00cc4d7cSGlenn Strauss 			buffer_append_uint_hex(p->tmp_buf, (uintmax_t)srv->cur_ts);
315*00cc4d7cSGlenn Strauss 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN(":"));
316bcdc6a3bSJan Kneschke 			buffer_append_string(p->tmp_buf, hh);
31752861d77SStefan Bühler 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", qop=\"auth\""));
318*00cc4d7cSGlenn Strauss 			if (-2 == auth_satisfied) {
319*00cc4d7cSGlenn Strauss 				buffer_append_string_len(p->tmp_buf, CONST_STR_LEN(", stale=true"));
320*00cc4d7cSGlenn Strauss 			}
321bcdc6a3bSJan Kneschke 
322bcdc6a3bSJan Kneschke 			response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
323bcdc6a3bSJan Kneschke 		} else {
324bcdc6a3bSJan Kneschke 			/* evil */
325bcdc6a3bSJan Kneschke 		}
326bcdc6a3bSJan Kneschke 		return HANDLER_FINISHED;
327bcdc6a3bSJan Kneschke 	} else {
328bcdc6a3bSJan Kneschke 		/* the REMOTE_USER header */
329bcdc6a3bSJan Kneschke 
330559b198fSStefan Bühler 		if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
3317187271fSStefan Bühler 			if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
3327187271fSStefan Bühler 				ds = data_string_init();
3337187271fSStefan Bühler 			}
334559b198fSStefan Bühler 			buffer_copy_string(ds->key, "REMOTE_USER");
3357187271fSStefan Bühler 			array_insert_unique(con->environment, (data_unset *)ds);
336bcdc6a3bSJan Kneschke 		}
3376afad87dSStefan Bühler 		buffer_copy_buffer(ds->value, p->auth_user);
338559b198fSStefan Bühler 
339559b198fSStefan Bühler 		/* AUTH_TYPE environment */
340559b198fSStefan Bühler 
341559b198fSStefan Bühler 		if (NULL == (ds = (data_string *)array_get_element(con->environment, "AUTH_TYPE"))) {
342559b198fSStefan Bühler 			if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
343559b198fSStefan Bühler 				ds = data_string_init();
344559b198fSStefan Bühler 			}
345559b198fSStefan Bühler 			buffer_copy_string(ds->key, "AUTH_TYPE");
346559b198fSStefan Bühler 			array_insert_unique(con->environment, (data_unset *)ds);
347559b198fSStefan Bühler 		}
348559b198fSStefan Bühler 		buffer_copy_string(ds->value, auth_type);
349559b198fSStefan Bühler 	}
350bcdc6a3bSJan Kneschke 
351bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
352bcdc6a3bSJan Kneschke }
353bcdc6a3bSJan Kneschke 
354bcdc6a3bSJan Kneschke SETDEFAULTS_FUNC(mod_auth_set_defaults) {
355bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
356bcdc6a3bSJan Kneschke 	size_t i;
357bcdc6a3bSJan Kneschke 
358bcdc6a3bSJan Kneschke 	config_values_t cv[] = {
359bcdc6a3bSJan Kneschke 		{ "auth.backend",                   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
36075d22698SStefan Bühler 		{ "auth.backend.plain.groupfile",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
36175d22698SStefan Bühler 		{ "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
36275d22698SStefan Bühler 		{ "auth.require",                   NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },  /* 3 */
36375d22698SStefan Bühler 		{ "auth.backend.ldap.hostname",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
36475d22698SStefan Bühler 		{ "auth.backend.ldap.base-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
36575d22698SStefan Bühler 		{ "auth.backend.ldap.filter",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
36675d22698SStefan Bühler 		{ "auth.backend.ldap.ca-file",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
36775d22698SStefan Bühler 		{ "auth.backend.ldap.starttls",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
36875d22698SStefan Bühler  		{ "auth.backend.ldap.bind-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
3699238cad6SJan Kneschke  		{ "auth.backend.ldap.bind-pw",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
37075d22698SStefan Bühler 		{ "auth.backend.ldap.allow-empty-pw",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
37175d22698SStefan Bühler 		{ "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
37275d22698SStefan Bühler 		{ "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
37375d22698SStefan Bühler 		{ "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
374bcdc6a3bSJan Kneschke 		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
375bcdc6a3bSJan Kneschke 	};
376bcdc6a3bSJan Kneschke 
3776f208cfdSStefan Bühler 	p->config_storage = calloc(1, srv->config_context->used * sizeof(mod_auth_plugin_config *));
378bcdc6a3bSJan Kneschke 
379bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->config_context->used; i++) {
380c512345fSStefan Bühler 		data_config const* config = (data_config const*)srv->config_context->data[i];
381bcdc6a3bSJan Kneschke 		mod_auth_plugin_config *s;
382bcdc6a3bSJan Kneschke 		size_t n;
383bcdc6a3bSJan Kneschke 		data_array *da;
384bcdc6a3bSJan Kneschke 
385bac9212cSJan Kneschke 		s = calloc(1, sizeof(mod_auth_plugin_config));
386bcdc6a3bSJan Kneschke 		s->auth_plain_groupfile = buffer_init();
387bcdc6a3bSJan Kneschke 		s->auth_plain_userfile = buffer_init();
388bcdc6a3bSJan Kneschke 		s->auth_htdigest_userfile = buffer_init();
389bcdc6a3bSJan Kneschke 		s->auth_htpasswd_userfile = buffer_init();
390bcdc6a3bSJan Kneschke 		s->auth_backend_conf = buffer_init();
391bcdc6a3bSJan Kneschke 
392bcdc6a3bSJan Kneschke 		s->auth_ldap_hostname = buffer_init();
393bcdc6a3bSJan Kneschke 		s->auth_ldap_basedn = buffer_init();
3949238cad6SJan Kneschke 		s->auth_ldap_binddn = buffer_init();
3959238cad6SJan Kneschke 		s->auth_ldap_bindpw = buffer_init();
396bcdc6a3bSJan Kneschke 		s->auth_ldap_filter = buffer_init();
3974a6ce4aeSJan Kneschke 		s->auth_ldap_cafile = buffer_init();
3984a6ce4aeSJan Kneschke 		s->auth_ldap_starttls = 0;
399bcdc6a3bSJan Kneschke 		s->auth_debug = 0;
400bcdc6a3bSJan Kneschke 
401bcdc6a3bSJan Kneschke 		s->auth_require = array_init();
402bcdc6a3bSJan Kneschke 
403bcdc6a3bSJan Kneschke #ifdef USE_LDAP
404bcdc6a3bSJan Kneschke 		s->ldap_filter_pre = buffer_init();
405bcdc6a3bSJan Kneschke 		s->ldap_filter_post = buffer_init();
406bcdc6a3bSJan Kneschke 		s->ldap = NULL;
407bcdc6a3bSJan Kneschke #endif
408bcdc6a3bSJan Kneschke 
409bcdc6a3bSJan Kneschke 		cv[0].destination = s->auth_backend_conf;
410bcdc6a3bSJan Kneschke 		cv[1].destination = s->auth_plain_groupfile;
411bcdc6a3bSJan Kneschke 		cv[2].destination = s->auth_plain_userfile;
412bcdc6a3bSJan Kneschke 		cv[3].destination = s->auth_require;
413bcdc6a3bSJan Kneschke 		cv[4].destination = s->auth_ldap_hostname;
414bcdc6a3bSJan Kneschke 		cv[5].destination = s->auth_ldap_basedn;
415bcdc6a3bSJan Kneschke 		cv[6].destination = s->auth_ldap_filter;
4164a6ce4aeSJan Kneschke 		cv[7].destination = s->auth_ldap_cafile;
4174a6ce4aeSJan Kneschke 		cv[8].destination = &(s->auth_ldap_starttls);
4189238cad6SJan Kneschke 		cv[9].destination = s->auth_ldap_binddn;
4199238cad6SJan Kneschke 		cv[10].destination = s->auth_ldap_bindpw;
420d471bcc9SMarcus Rückert 		cv[11].destination = &(s->auth_ldap_allow_empty_pw);
421d471bcc9SMarcus Rückert 		cv[12].destination = s->auth_htdigest_userfile;
422d471bcc9SMarcus Rückert 		cv[13].destination = s->auth_htpasswd_userfile;
423d471bcc9SMarcus Rückert 		cv[14].destination = &(s->auth_debug);
424bcdc6a3bSJan Kneschke 
425bcdc6a3bSJan Kneschke 		p->config_storage[i] = s;
426bcdc6a3bSJan Kneschke 
427c512345fSStefan Bühler 		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
428bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
429bcdc6a3bSJan Kneschke 		}
430bcdc6a3bSJan Kneschke 
431ad3e93eaSStefan Bühler 		if (!buffer_string_is_empty(s->auth_backend_conf)) {
432bcdc6a3bSJan Kneschke 			if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
433bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_HTPASSWD;
434bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) {
435bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_HTDIGEST;
436bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "plain")) {
437bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_PLAIN;
438bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) {
439bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_LDAP;
440bcdc6a3bSJan Kneschke 			} else {
441bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
442bcdc6a3bSJan Kneschke 
443bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
444bcdc6a3bSJan Kneschke 			}
445bcdc6a3bSJan Kneschke 		}
446bcdc6a3bSJan Kneschke 
447e7ff9483SStefan Bühler #ifdef USE_LDAP
448ad3e93eaSStefan Bühler 		if (!buffer_string_is_empty(s->auth_ldap_filter)) {
449e7ff9483SStefan Bühler 			char *dollar;
450e7ff9483SStefan Bühler 
451e7ff9483SStefan Bühler 			/* parse filter */
452e7ff9483SStefan Bühler 
453e7ff9483SStefan Bühler 			if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
454e7ff9483SStefan Bühler 				log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
455e7ff9483SStefan Bühler 
456e7ff9483SStefan Bühler 				return HANDLER_ERROR;
457e7ff9483SStefan Bühler 			}
458e7ff9483SStefan Bühler 
459e7ff9483SStefan Bühler 			buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
460e7ff9483SStefan Bühler 			buffer_copy_string(s->ldap_filter_post, dollar+1);
461e7ff9483SStefan Bühler 		}
462e7ff9483SStefan Bühler #endif
463e7ff9483SStefan Bühler 
464bcdc6a3bSJan Kneschke 		/* no auth.require for this section */
465c512345fSStefan Bühler 		if (NULL == (da = (data_array *)array_get_element(config->value, "auth.require"))) continue;
466bcdc6a3bSJan Kneschke 
467bcdc6a3bSJan Kneschke 		if (da->type != TYPE_ARRAY) continue;
468bcdc6a3bSJan Kneschke 
469bcdc6a3bSJan Kneschke 		for (n = 0; n < da->value->used; n++) {
470bcdc6a3bSJan Kneschke 			size_t m;
471bcdc6a3bSJan Kneschke 			data_array *da_file = (data_array *)da->value->data[n];
472bcdc6a3bSJan Kneschke 			const char *method, *realm, *require;
473bcdc6a3bSJan Kneschke 
474bcdc6a3bSJan Kneschke 			if (da->value->data[n]->type != TYPE_ARRAY) {
475cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
476cc7a8ae0SJan Kneschke 						"auth.require should contain an array as in:",
477cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., ...) )");
478bcdc6a3bSJan Kneschke 
479bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
480bcdc6a3bSJan Kneschke 			}
481bcdc6a3bSJan Kneschke 
482bcdc6a3bSJan Kneschke 			method = realm = require = NULL;
483bcdc6a3bSJan Kneschke 
484bcdc6a3bSJan Kneschke 			for (m = 0; m < da_file->value->used; m++) {
485bcdc6a3bSJan Kneschke 				if (da_file->value->data[m]->type == TYPE_STRING) {
486bcdc6a3bSJan Kneschke 					if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
487bcdc6a3bSJan Kneschke 						method = ((data_string *)(da_file->value->data[m]))->value->ptr;
488bcdc6a3bSJan Kneschke 					} else if (0 == strcmp(da_file->value->data[m]->key->ptr, "realm")) {
489bcdc6a3bSJan Kneschke 						realm = ((data_string *)(da_file->value->data[m]))->value->ptr;
490bcdc6a3bSJan Kneschke 					} else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
491bcdc6a3bSJan Kneschke 						require = ((data_string *)(da_file->value->data[m]))->value->ptr;
492bcdc6a3bSJan Kneschke 					} else {
493cc7a8ae0SJan Kneschke 						log_error_write(srv, __FILE__, __LINE__, "ssbs",
494cc7a8ae0SJan Kneschke 							"the field is unknown in:",
495cc7a8ae0SJan Kneschke 							"auth.require = ( \"...\" => ( ..., -> \"",
496cc7a8ae0SJan Kneschke 							da_file->value->data[m]->key,
497cc7a8ae0SJan Kneschke 							"\" <- => \"...\" ) )");
498cc7a8ae0SJan Kneschke 
499bcdc6a3bSJan Kneschke 						return HANDLER_ERROR;
500bcdc6a3bSJan Kneschke 					}
501bcdc6a3bSJan Kneschke 				} else {
502cc7a8ae0SJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ssbs",
503cc7a8ae0SJan Kneschke 						"a string was expected for:",
504cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., -> \"",
505cc7a8ae0SJan Kneschke 						da_file->value->data[m]->key,
506cc7a8ae0SJan Kneschke 						"\" <- => \"...\" ) )");
507bcdc6a3bSJan Kneschke 
508bcdc6a3bSJan Kneschke 					return HANDLER_ERROR;
509bcdc6a3bSJan Kneschke 				}
510bcdc6a3bSJan Kneschke 			}
511bcdc6a3bSJan Kneschke 
512bcdc6a3bSJan Kneschke 			if (method == NULL) {
513cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
5144df22f2aSStefan Bühler 						"the method field is missing in:",
515cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
516bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
5174a6ce4aeSJan Kneschke 			} else {
5184a6ce4aeSJan Kneschke 				if (0 != strcmp(method, "basic") &&
519f9d58670SStefan Bühler 				    0 != strcmp(method, "digest") &&
520f9d58670SStefan Bühler 				    0 != strcmp(method, "extern")) {
521cc7a8ae0SJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ss",
522f9d58670SStefan Bühler 							"method has to be either \"basic\", \"digest\" or \"extern\" in",
523cc7a8ae0SJan Kneschke 							"auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
5244a6ce4aeSJan Kneschke 					return HANDLER_ERROR;
5254a6ce4aeSJan Kneschke 				}
526bcdc6a3bSJan Kneschke 			}
527bcdc6a3bSJan Kneschke 
528bcdc6a3bSJan Kneschke 			if (realm == NULL) {
529cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
5304df22f2aSStefan Bühler 						"the realm field is missing in:",
531cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
532bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
533bcdc6a3bSJan Kneschke 			}
534bcdc6a3bSJan Kneschke 
535bcdc6a3bSJan Kneschke 			if (require == NULL) {
536cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
537cc7a8ae0SJan Kneschke 						"the require field is missing in:",
538cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
539bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
540bcdc6a3bSJan Kneschke 			}
541bcdc6a3bSJan Kneschke 
542bcdc6a3bSJan Kneschke 			if (method && realm && require) {
543bcdc6a3bSJan Kneschke 				data_string *ds;
544bcdc6a3bSJan Kneschke 				data_array *a;
545bcdc6a3bSJan Kneschke 
546bcdc6a3bSJan Kneschke 				a = data_array_init();
5476afad87dSStefan Bühler 				buffer_copy_buffer(a->key, da_file->key);
548bcdc6a3bSJan Kneschke 
549bcdc6a3bSJan Kneschke 				ds = data_string_init();
550bcdc6a3bSJan Kneschke 
55152861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("method"));
552bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, method);
553bcdc6a3bSJan Kneschke 
554bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
555bcdc6a3bSJan Kneschke 
556bcdc6a3bSJan Kneschke 				ds = data_string_init();
557bcdc6a3bSJan Kneschke 
55852861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("realm"));
559bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, realm);
560bcdc6a3bSJan Kneschke 
561bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
562bcdc6a3bSJan Kneschke 
563bcdc6a3bSJan Kneschke 				ds = data_string_init();
564bcdc6a3bSJan Kneschke 
56552861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("require"));
566bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, require);
567bcdc6a3bSJan Kneschke 
568bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
569bcdc6a3bSJan Kneschke 
570bcdc6a3bSJan Kneschke 				array_insert_unique(s->auth_require, (data_unset *)a);
571bcdc6a3bSJan Kneschke 			}
572bcdc6a3bSJan Kneschke 		}
573bcdc6a3bSJan Kneschke 
574ad3e93eaSStefan Bühler 		switch(s->auth_backend) {
575ea7b9abaSJan Kneschke 		case AUTH_BACKEND_LDAP: {
576ea7b9abaSJan Kneschke 			handler_t ret = auth_ldap_init(srv, s);
577ea7b9abaSJan Kneschke 			if (ret == HANDLER_ERROR)
578ea7b9abaSJan Kneschke 				return (ret);
579ea7b9abaSJan Kneschke 			break;
580ea7b9abaSJan Kneschke 		}
581ea7b9abaSJan Kneschke 		default:
582ea7b9abaSJan Kneschke 			break;
583ea7b9abaSJan Kneschke 		}
584ea7b9abaSJan Kneschke 	}
585ea7b9abaSJan Kneschke 
586ea7b9abaSJan Kneschke 	return HANDLER_GO_ON;
587ea7b9abaSJan Kneschke }
588ea7b9abaSJan Kneschke 
5896ca932dfSJan Kneschke handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
590bcdc6a3bSJan Kneschke #ifdef USE_LDAP
591ea7b9abaSJan Kneschke 	int ret;
592bcdc6a3bSJan Kneschke #if 0
593bcdc6a3bSJan Kneschke 	if (s->auth_ldap_basedn->used == 0) {
594bcdc6a3bSJan Kneschke 		log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
595bcdc6a3bSJan Kneschke 
596bcdc6a3bSJan Kneschke 		return HANDLER_ERROR;
597bcdc6a3bSJan Kneschke 	}
598bcdc6a3bSJan Kneschke #endif
599bcdc6a3bSJan Kneschke 
600ad3e93eaSStefan Bühler 	if (!buffer_string_is_empty(s->auth_ldap_hostname)) {
601cfba07cbSStefan Bühler 		/* free old context */
602cfba07cbSStefan Bühler 		if (NULL != s->ldap) ldap_unbind_s(s->ldap);
603cfba07cbSStefan Bühler 
604bcdc6a3bSJan Kneschke 		if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
605bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
606bcdc6a3bSJan Kneschke 
607bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
608bcdc6a3bSJan Kneschke 		}
609bcdc6a3bSJan Kneschke 
610bcdc6a3bSJan Kneschke 		ret = LDAP_VERSION3;
611bcdc6a3bSJan Kneschke 		if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
612bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
613bcdc6a3bSJan Kneschke 
614bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
615bcdc6a3bSJan Kneschke 		}
616bcdc6a3bSJan Kneschke 
6174a6ce4aeSJan Kneschke 		if (s->auth_ldap_starttls) {
6186ca932dfSJan Kneschke 			/* if no CA file is given, it is ok, as we will use encryption
6196ca932dfSJan Kneschke 				* if the server requires a CAfile it will tell us */
6206afad87dSStefan Bühler 			if (!buffer_string_is_empty(s->auth_ldap_cafile)) {
6216ca932dfSJan Kneschke 				if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
6226ca932dfSJan Kneschke 								s->auth_ldap_cafile->ptr))) {
6236ca932dfSJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ss",
6246ca932dfSJan Kneschke 							"Loading CA certificate failed:", ldap_err2string(ret));
6254a6ce4aeSJan Kneschke 
6264a6ce4aeSJan Kneschke 					return HANDLER_ERROR;
6274a6ce4aeSJan Kneschke 				}
6284a6ce4aeSJan Kneschke 			}
6294a6ce4aeSJan Kneschke 
6304a6ce4aeSJan Kneschke 			if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) {
6314a6ce4aeSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
6324a6ce4aeSJan Kneschke 
6334a6ce4aeSJan Kneschke 				return HANDLER_ERROR;
6344a6ce4aeSJan Kneschke 			}
6354a6ce4aeSJan Kneschke 		}
6364a6ce4aeSJan Kneschke 
637bcdc6a3bSJan Kneschke 
638bcdc6a3bSJan Kneschke 		/* 1. */
639ad3e93eaSStefan Bühler 		if (!buffer_string_is_empty(s->auth_ldap_binddn)) {
6409238cad6SJan Kneschke 			if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
6419238cad6SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
6429238cad6SJan Kneschke 
6439238cad6SJan Kneschke 				return HANDLER_ERROR;
6449238cad6SJan Kneschke 			}
6459238cad6SJan Kneschke 		} else {
646bcdc6a3bSJan Kneschke 			if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
647bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
648bcdc6a3bSJan Kneschke 
649bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
650bcdc6a3bSJan Kneschke 			}
651bcdc6a3bSJan Kneschke 		}
6529238cad6SJan Kneschke 	}
6535a9992b1SStefan Bühler 	return HANDLER_GO_ON;
654bcdc6a3bSJan Kneschke #else
6555a9992b1SStefan Bühler 	UNUSED(s);
656bcdc6a3bSJan Kneschke 	log_error_write(srv, __FILE__, __LINE__, "s", "no ldap support available");
657bcdc6a3bSJan Kneschke 	return HANDLER_ERROR;
658bcdc6a3bSJan Kneschke #endif
659bcdc6a3bSJan Kneschke }
660bcdc6a3bSJan Kneschke 
66163f785a2SStefan Bühler int mod_auth_plugin_init(plugin *p);
662bcdc6a3bSJan Kneschke int mod_auth_plugin_init(plugin *p) {
663bcdc6a3bSJan Kneschke 	p->version     = LIGHTTPD_VERSION_ID;
664bcdc6a3bSJan Kneschke 	p->name        = buffer_init_string("auth");
665bcdc6a3bSJan Kneschke 	p->init        = mod_auth_init;
666bcdc6a3bSJan Kneschke 	p->set_defaults = mod_auth_set_defaults;
667bcdc6a3bSJan Kneschke 	p->handle_uri_clean = mod_auth_uri_handler;
668bcdc6a3bSJan Kneschke 	p->cleanup     = mod_auth_free;
669bcdc6a3bSJan Kneschke 
670bcdc6a3bSJan Kneschke 	p->data        = NULL;
671bcdc6a3bSJan Kneschke 
672bcdc6a3bSJan Kneschke 	return 0;
673bcdc6a3bSJan Kneschke }
674