xref: /lighttpd1.4/src/mod_auth.c (revision e7ff9483)
1bcdc6a3bSJan Kneschke #include <sys/types.h>
2bcdc6a3bSJan Kneschke #include <sys/stat.h>
3bcdc6a3bSJan Kneschke 
4bcdc6a3bSJan Kneschke #include <stdlib.h>
5bcdc6a3bSJan Kneschke #include <string.h>
6bcdc6a3bSJan Kneschke #include <errno.h>
7bcdc6a3bSJan Kneschke #include <fcntl.h>
8bcdc6a3bSJan Kneschke #include <unistd.h>
9bcdc6a3bSJan Kneschke 
10bcdc6a3bSJan Kneschke #include "plugin.h"
11bcdc6a3bSJan Kneschke #include "http_auth.h"
12bcdc6a3bSJan Kneschke #include "log.h"
13bcdc6a3bSJan Kneschke #include "response.h"
14bcdc6a3bSJan Kneschke 
15ea7b9abaSJan Kneschke handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
16ea7b9abaSJan Kneschke 
17bcdc6a3bSJan Kneschke 
18bcdc6a3bSJan Kneschke /**
19bcdc6a3bSJan Kneschke  * the basic and digest auth framework
20bcdc6a3bSJan Kneschke  *
21bcdc6a3bSJan Kneschke  * - config handling
22bcdc6a3bSJan Kneschke  * - protocol handling
23bcdc6a3bSJan Kneschke  *
24bcdc6a3bSJan Kneschke  * http_auth.c
25bcdc6a3bSJan Kneschke  * http_auth_digest.c
26bcdc6a3bSJan Kneschke  *
27bcdc6a3bSJan Kneschke  * do the real work
28bcdc6a3bSJan Kneschke  */
29bcdc6a3bSJan Kneschke 
30bcdc6a3bSJan Kneschke INIT_FUNC(mod_auth_init) {
31bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p;
32bcdc6a3bSJan Kneschke 
33bcdc6a3bSJan Kneschke 	p = calloc(1, sizeof(*p));
34bcdc6a3bSJan Kneschke 
35bcdc6a3bSJan Kneschke 	p->tmp_buf = buffer_init();
36bcdc6a3bSJan Kneschke 
37bcdc6a3bSJan Kneschke 	p->auth_user = buffer_init();
38bcdc6a3bSJan Kneschke #ifdef USE_LDAP
39bcdc6a3bSJan Kneschke 	p->ldap_filter = buffer_init();
40bcdc6a3bSJan Kneschke #endif
41bcdc6a3bSJan Kneschke 
42bcdc6a3bSJan Kneschke 	return p;
43bcdc6a3bSJan Kneschke }
44bcdc6a3bSJan Kneschke 
45bcdc6a3bSJan Kneschke FREE_FUNC(mod_auth_free) {
46bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
47bcdc6a3bSJan Kneschke 
48bcdc6a3bSJan Kneschke 	UNUSED(srv);
49bcdc6a3bSJan Kneschke 
50bcdc6a3bSJan Kneschke 	if (!p) return HANDLER_GO_ON;
51bcdc6a3bSJan Kneschke 
52bcdc6a3bSJan Kneschke 	buffer_free(p->tmp_buf);
53bcdc6a3bSJan Kneschke 	buffer_free(p->auth_user);
54bcdc6a3bSJan Kneschke #ifdef USE_LDAP
55bcdc6a3bSJan Kneschke 	buffer_free(p->ldap_filter);
56bcdc6a3bSJan Kneschke #endif
57bcdc6a3bSJan Kneschke 
58bcdc6a3bSJan Kneschke 	if (p->config_storage) {
59bcdc6a3bSJan Kneschke 		size_t i;
60bcdc6a3bSJan Kneschke 		for (i = 0; i < srv->config_context->used; i++) {
61bcdc6a3bSJan Kneschke 			mod_auth_plugin_config *s = p->config_storage[i];
62bcdc6a3bSJan Kneschke 
634a6ce4aeSJan Kneschke 			if (!s) continue;
644a6ce4aeSJan Kneschke 
65bcdc6a3bSJan Kneschke 			array_free(s->auth_require);
66bcdc6a3bSJan Kneschke 			buffer_free(s->auth_plain_groupfile);
67bcdc6a3bSJan Kneschke 			buffer_free(s->auth_plain_userfile);
68bcdc6a3bSJan Kneschke 			buffer_free(s->auth_htdigest_userfile);
69bcdc6a3bSJan Kneschke 			buffer_free(s->auth_htpasswd_userfile);
70bcdc6a3bSJan Kneschke 			buffer_free(s->auth_backend_conf);
71bcdc6a3bSJan Kneschke 
72bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_hostname);
73bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_basedn);
749238cad6SJan Kneschke 			buffer_free(s->auth_ldap_binddn);
759238cad6SJan Kneschke 			buffer_free(s->auth_ldap_bindpw);
76bcdc6a3bSJan Kneschke 			buffer_free(s->auth_ldap_filter);
774a6ce4aeSJan Kneschke 			buffer_free(s->auth_ldap_cafile);
78bcdc6a3bSJan Kneschke 
79bcdc6a3bSJan Kneschke #ifdef USE_LDAP
80bcdc6a3bSJan Kneschke 			buffer_free(s->ldap_filter_pre);
81bcdc6a3bSJan Kneschke 			buffer_free(s->ldap_filter_post);
82bcdc6a3bSJan Kneschke 
83bcdc6a3bSJan Kneschke 			if (s->ldap) ldap_unbind_s(s->ldap);
84bcdc6a3bSJan Kneschke #endif
85bcdc6a3bSJan Kneschke 
86bcdc6a3bSJan Kneschke 			free(s);
87bcdc6a3bSJan Kneschke 		}
88bcdc6a3bSJan Kneschke 		free(p->config_storage);
89bcdc6a3bSJan Kneschke 	}
90bcdc6a3bSJan Kneschke 
91bcdc6a3bSJan Kneschke 	free(p);
92bcdc6a3bSJan Kneschke 
93bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
94bcdc6a3bSJan Kneschke }
95bcdc6a3bSJan Kneschke 
96bcdc6a3bSJan Kneschke #define PATCH(x) \
97bcdc6a3bSJan Kneschke 	p->conf.x = s->x;
984a6ce4aeSJan Kneschke static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
99bcdc6a3bSJan Kneschke 	size_t i, j;
1004a6ce4aeSJan Kneschke 	mod_auth_plugin_config *s = p->config_storage[0];
1014a6ce4aeSJan Kneschke 
1024a6ce4aeSJan Kneschke 	PATCH(auth_backend);
1034a6ce4aeSJan Kneschke 	PATCH(auth_plain_groupfile);
1044a6ce4aeSJan Kneschke 	PATCH(auth_plain_userfile);
1054a6ce4aeSJan Kneschke 	PATCH(auth_htdigest_userfile);
1064a6ce4aeSJan Kneschke 	PATCH(auth_htpasswd_userfile);
1074a6ce4aeSJan Kneschke 	PATCH(auth_require);
1084a6ce4aeSJan Kneschke 	PATCH(auth_debug);
1094a6ce4aeSJan Kneschke 	PATCH(auth_ldap_hostname);
1104a6ce4aeSJan Kneschke 	PATCH(auth_ldap_basedn);
1119238cad6SJan Kneschke 	PATCH(auth_ldap_binddn);
1129238cad6SJan Kneschke 	PATCH(auth_ldap_bindpw);
1134a6ce4aeSJan Kneschke 	PATCH(auth_ldap_filter);
1144a6ce4aeSJan Kneschke 	PATCH(auth_ldap_cafile);
1154a6ce4aeSJan Kneschke 	PATCH(auth_ldap_starttls);
116d471bcc9SMarcus Rückert 	PATCH(auth_ldap_allow_empty_pw);
1174a6ce4aeSJan Kneschke #ifdef USE_LDAP
1184a6ce4aeSJan Kneschke 	PATCH(ldap);
1194a6ce4aeSJan Kneschke 	PATCH(ldap_filter_pre);
1204a6ce4aeSJan Kneschke 	PATCH(ldap_filter_post);
1214a6ce4aeSJan Kneschke #endif
122bcdc6a3bSJan Kneschke 
123bcdc6a3bSJan Kneschke 	/* skip the first, the global context */
124bcdc6a3bSJan Kneschke 	for (i = 1; i < srv->config_context->used; i++) {
125bcdc6a3bSJan Kneschke 		data_config *dc = (data_config *)srv->config_context->data[i];
1264a6ce4aeSJan Kneschke 		s = p->config_storage[i];
127bcdc6a3bSJan Kneschke 
128bcdc6a3bSJan Kneschke 		/* condition didn't match */
129bcdc6a3bSJan Kneschke 		if (!config_check_cond(srv, con, dc)) continue;
130bcdc6a3bSJan Kneschke 
131bcdc6a3bSJan Kneschke 		/* merge config */
132bcdc6a3bSJan Kneschke 		for (j = 0; j < dc->value->used; j++) {
133bcdc6a3bSJan Kneschke 			data_unset *du = dc->value->data[j];
134bcdc6a3bSJan Kneschke 
135bcdc6a3bSJan Kneschke 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
136bcdc6a3bSJan Kneschke 				PATCH(auth_backend);
137bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
138bcdc6a3bSJan Kneschke 				PATCH(auth_plain_groupfile);
139bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
140bcdc6a3bSJan Kneschke 				PATCH(auth_plain_userfile);
141bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
142bcdc6a3bSJan Kneschke 				PATCH(auth_htdigest_userfile);
143bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
144bcdc6a3bSJan Kneschke 				PATCH(auth_htpasswd_userfile);
145bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
146bcdc6a3bSJan Kneschke 				PATCH(auth_require);
147bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
148bcdc6a3bSJan Kneschke 				PATCH(auth_debug);
149bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
150bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_hostname);
151bcdc6a3bSJan Kneschke #ifdef USE_LDAP
152bcdc6a3bSJan Kneschke 				PATCH(ldap);
153bcdc6a3bSJan Kneschke #endif
154bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
155bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_basedn);
156bcdc6a3bSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
157bcdc6a3bSJan Kneschke 				PATCH(auth_ldap_filter);
158ba715e1cSStefan Bühler #ifdef USE_LDAP
159ba715e1cSStefan Bühler 				PATCH(ldap_filter_pre);
160ba715e1cSStefan Bühler 				PATCH(ldap_filter_post);
161ba715e1cSStefan Bühler #endif
1624a6ce4aeSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
1634a6ce4aeSJan Kneschke 				PATCH(auth_ldap_cafile);
1644a6ce4aeSJan Kneschke 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
1654a6ce4aeSJan Kneschke 				PATCH(auth_ldap_starttls);
166d471bcc9SMarcus Rückert 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
167d471bcc9SMarcus Rückert 				PATCH(auth_ldap_allow_empty_pw);
168bcdc6a3bSJan Kneschke 			}
169bcdc6a3bSJan Kneschke 		}
170bcdc6a3bSJan Kneschke 	}
171bcdc6a3bSJan Kneschke 
172bcdc6a3bSJan Kneschke 	return 0;
173bcdc6a3bSJan Kneschke }
174bcdc6a3bSJan Kneschke #undef PATCH
175bcdc6a3bSJan Kneschke 
176bcdc6a3bSJan Kneschke static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
177bcdc6a3bSJan Kneschke 	size_t k;
178bcdc6a3bSJan Kneschke 	int auth_required = 0, auth_satisfied = 0;
179bcdc6a3bSJan Kneschke 	char *http_authorization = NULL;
180bcdc6a3bSJan Kneschke 	data_string *ds;
181bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
182bcdc6a3bSJan Kneschke 	array *req;
183bcdc6a3bSJan Kneschke 
184bcdc6a3bSJan Kneschke 	/* select the right config */
1854a6ce4aeSJan Kneschke 	mod_auth_patch_connection(srv, con, p);
186bcdc6a3bSJan Kneschke 
187bcdc6a3bSJan Kneschke 	if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
188bcdc6a3bSJan Kneschke 
189bcdc6a3bSJan Kneschke 	/*
190bcdc6a3bSJan Kneschke 	 * AUTH
191bcdc6a3bSJan Kneschke 	 *
192bcdc6a3bSJan Kneschke 	 */
193bcdc6a3bSJan Kneschke 
194bcdc6a3bSJan Kneschke 	/* do we have to ask for auth ? */
195bcdc6a3bSJan Kneschke 
196bcdc6a3bSJan Kneschke 	auth_required = 0;
197bcdc6a3bSJan Kneschke 	auth_satisfied = 0;
198bcdc6a3bSJan Kneschke 
199bcdc6a3bSJan Kneschke 	/* search auth-directives for path */
200bcdc6a3bSJan Kneschke 	for (k = 0; k < p->conf.auth_require->used; k++) {
20167079527SJan Kneschke 		buffer *require = p->conf.auth_require->data[k]->key;
202bcdc6a3bSJan Kneschke 
20367079527SJan Kneschke 		if (require->used == 0) continue;
20467079527SJan Kneschke 		if (con->uri.path->used < require->used) continue;
2054afd2ae2SJan Kneschke 
2064afd2ae2SJan Kneschke 		/* if we have a case-insensitive FS we have to lower-case the URI here too */
2074afd2ae2SJan Kneschke 
2084afd2ae2SJan Kneschke 		if (con->conf.force_lowercase_filenames) {
20967079527SJan Kneschke 			if (0 == strncasecmp(con->uri.path->ptr, require->ptr, require->used - 1)) {
210bcdc6a3bSJan Kneschke 				auth_required = 1;
211bcdc6a3bSJan Kneschke 				break;
212bcdc6a3bSJan Kneschke 			}
2134afd2ae2SJan Kneschke 		} else {
21467079527SJan Kneschke 			if (0 == strncmp(con->uri.path->ptr, require->ptr, require->used - 1)) {
2154afd2ae2SJan Kneschke 				auth_required = 1;
2164afd2ae2SJan Kneschke 				break;
2174afd2ae2SJan Kneschke 			}
2184afd2ae2SJan Kneschke 		}
219bcdc6a3bSJan Kneschke 	}
220bcdc6a3bSJan Kneschke 
221bcdc6a3bSJan Kneschke 	/* nothing to do for us */
222bcdc6a3bSJan Kneschke 	if (auth_required == 0) return HANDLER_GO_ON;
223bcdc6a3bSJan Kneschke 
224bcdc6a3bSJan Kneschke 	req = ((data_array *)(p->conf.auth_require->data[k]))->value;
225bcdc6a3bSJan Kneschke 
226bcdc6a3bSJan Kneschke 	/* try to get Authorization-header */
227bcdc6a3bSJan Kneschke 
228bcdc6a3bSJan Kneschke 	if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
229bcdc6a3bSJan Kneschke 		http_authorization = ds->value->ptr;
230bcdc6a3bSJan Kneschke 	}
231bcdc6a3bSJan Kneschke 
232bcdc6a3bSJan Kneschke 	if (ds && ds->value && ds->value->used) {
233bcdc6a3bSJan Kneschke 		char *auth_realm;
234bcdc6a3bSJan Kneschke 		data_string *method;
235bcdc6a3bSJan Kneschke 
236bcdc6a3bSJan Kneschke 		method = (data_string *)array_get_element(req, "method");
237bcdc6a3bSJan Kneschke 
238bcdc6a3bSJan Kneschke 		/* parse auth-header */
239bcdc6a3bSJan Kneschke 		if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
240bcdc6a3bSJan Kneschke 			int auth_type_len = auth_realm - http_authorization;
241bcdc6a3bSJan Kneschke 
242bcdc6a3bSJan Kneschke 			if ((auth_type_len == 5) &&
243708f499dSJan Kneschke 			    (0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
244bcdc6a3bSJan Kneschke 
245bcdc6a3bSJan Kneschke 				if (0 == strcmp(method->value->ptr, "basic")) {
246bcdc6a3bSJan Kneschke 					auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
247bcdc6a3bSJan Kneschke 				}
248bcdc6a3bSJan Kneschke 			} else if ((auth_type_len == 6) &&
249708f499dSJan Kneschke 				   (0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
250bcdc6a3bSJan Kneschke 				if (0 == strcmp(method->value->ptr, "digest")) {
251bcdc6a3bSJan Kneschke 					if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
252bcdc6a3bSJan Kneschke 						con->http_status = 400;
253ad12e4c5SStefan Bühler 						con->mode = DIRECT;
254bcdc6a3bSJan Kneschke 
255bcdc6a3bSJan Kneschke 						/* a field was missing */
256bcdc6a3bSJan Kneschke 
257bcdc6a3bSJan Kneschke 						return HANDLER_FINISHED;
258bcdc6a3bSJan Kneschke 					}
259bcdc6a3bSJan Kneschke 				}
260bcdc6a3bSJan Kneschke 			} else {
261bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
262bcdc6a3bSJan Kneschke 						"unknown authentification type:",
263bcdc6a3bSJan Kneschke 						http_authorization);
264bcdc6a3bSJan Kneschke 			}
265bcdc6a3bSJan Kneschke 		}
266bcdc6a3bSJan Kneschke 	}
267bcdc6a3bSJan Kneschke 
268bcdc6a3bSJan Kneschke 	if (!auth_satisfied) {
269bcdc6a3bSJan Kneschke 		data_string *method, *realm;
270bcdc6a3bSJan Kneschke 		method = (data_string *)array_get_element(req, "method");
271bcdc6a3bSJan Kneschke 		realm = (data_string *)array_get_element(req, "realm");
272bcdc6a3bSJan Kneschke 
273bcdc6a3bSJan Kneschke 		con->http_status = 401;
274ad12e4c5SStefan Bühler 		con->mode = DIRECT;
275bcdc6a3bSJan Kneschke 
276bcdc6a3bSJan Kneschke 		if (0 == strcmp(method->value->ptr, "basic")) {
27752861d77SStefan Bühler 			buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Basic realm=\""));
278bcdc6a3bSJan Kneschke 			buffer_append_string_buffer(p->tmp_buf, realm->value);
27952861d77SStefan Bühler 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\""));
280bcdc6a3bSJan Kneschke 
281bcdc6a3bSJan Kneschke 			response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
282bcdc6a3bSJan Kneschke 		} else if (0 == strcmp(method->value->ptr, "digest")) {
283bcdc6a3bSJan Kneschke 			char hh[33];
284bcdc6a3bSJan Kneschke 			http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
285bcdc6a3bSJan Kneschke 
28652861d77SStefan Bühler 			buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Digest realm=\""));
287bcdc6a3bSJan Kneschke 			buffer_append_string_buffer(p->tmp_buf, realm->value);
28852861d77SStefan Bühler 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", nonce=\""));
289bcdc6a3bSJan Kneschke 			buffer_append_string(p->tmp_buf, hh);
29052861d77SStefan Bühler 			buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", qop=\"auth\""));
291bcdc6a3bSJan Kneschke 
292bcdc6a3bSJan Kneschke 			response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
293bcdc6a3bSJan Kneschke 		} else {
294bcdc6a3bSJan Kneschke 			/* evil */
295bcdc6a3bSJan Kneschke 		}
296bcdc6a3bSJan Kneschke 		return HANDLER_FINISHED;
297bcdc6a3bSJan Kneschke 	} else {
298bcdc6a3bSJan Kneschke 		/* the REMOTE_USER header */
299bcdc6a3bSJan Kneschke 
300bcdc6a3bSJan Kneschke 		buffer_copy_string_buffer(con->authed_user, p->auth_user);
301bcdc6a3bSJan Kneschke 	}
302bcdc6a3bSJan Kneschke 
303bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
304bcdc6a3bSJan Kneschke }
305bcdc6a3bSJan Kneschke 
306bcdc6a3bSJan Kneschke SETDEFAULTS_FUNC(mod_auth_set_defaults) {
307bcdc6a3bSJan Kneschke 	mod_auth_plugin_data *p = p_d;
308bcdc6a3bSJan Kneschke 	size_t i;
309bcdc6a3bSJan Kneschke 
310bcdc6a3bSJan Kneschke 	config_values_t cv[] = {
311bcdc6a3bSJan Kneschke 		{ "auth.backend",                   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
312bcdc6a3bSJan Kneschke 		{ "auth.backend.plain.groupfile",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
313bcdc6a3bSJan Kneschke 		{ "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
314bcdc6a3bSJan Kneschke 		{ "auth.require",                   NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },
315bcdc6a3bSJan Kneschke 		{ "auth.backend.ldap.hostname",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
316bcdc6a3bSJan Kneschke 		{ "auth.backend.ldap.base-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
317bcdc6a3bSJan Kneschke 		{ "auth.backend.ldap.filter",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
3184a6ce4aeSJan Kneschke 		{ "auth.backend.ldap.ca-file",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
3194a6ce4aeSJan Kneschke 		{ "auth.backend.ldap.starttls",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
3209238cad6SJan Kneschke  		{ "auth.backend.ldap.bind-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
3219238cad6SJan Kneschke  		{ "auth.backend.ldap.bind-pw",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
322d471bcc9SMarcus Rückert 		{ "auth.backend.ldap.allow-empty-pw",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
323bcdc6a3bSJan Kneschke 		{ "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
324bcdc6a3bSJan Kneschke 		{ "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
3259238cad6SJan Kneschke 		{ "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 13 */
326bcdc6a3bSJan Kneschke 		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
327bcdc6a3bSJan Kneschke 	};
328bcdc6a3bSJan Kneschke 
329bac9212cSJan Kneschke 	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
330bcdc6a3bSJan Kneschke 
331bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->config_context->used; i++) {
332bcdc6a3bSJan Kneschke 		mod_auth_plugin_config *s;
333bcdc6a3bSJan Kneschke 		size_t n;
334bcdc6a3bSJan Kneschke 		data_array *da;
335bcdc6a3bSJan Kneschke 		array *ca;
336bcdc6a3bSJan Kneschke 
337bac9212cSJan Kneschke 		s = calloc(1, sizeof(mod_auth_plugin_config));
338bcdc6a3bSJan Kneschke 		s->auth_plain_groupfile = buffer_init();
339bcdc6a3bSJan Kneschke 		s->auth_plain_userfile = buffer_init();
340bcdc6a3bSJan Kneschke 		s->auth_htdigest_userfile = buffer_init();
341bcdc6a3bSJan Kneschke 		s->auth_htpasswd_userfile = buffer_init();
342bcdc6a3bSJan Kneschke 		s->auth_backend_conf = buffer_init();
343bcdc6a3bSJan Kneschke 
344bcdc6a3bSJan Kneschke 		s->auth_ldap_hostname = buffer_init();
345bcdc6a3bSJan Kneschke 		s->auth_ldap_basedn = buffer_init();
3469238cad6SJan Kneschke 		s->auth_ldap_binddn = buffer_init();
3479238cad6SJan Kneschke 		s->auth_ldap_bindpw = buffer_init();
348bcdc6a3bSJan Kneschke 		s->auth_ldap_filter = buffer_init();
3494a6ce4aeSJan Kneschke 		s->auth_ldap_cafile = buffer_init();
3504a6ce4aeSJan Kneschke 		s->auth_ldap_starttls = 0;
351bcdc6a3bSJan Kneschke 		s->auth_debug = 0;
352bcdc6a3bSJan Kneschke 
353bcdc6a3bSJan Kneschke 		s->auth_require = array_init();
354bcdc6a3bSJan Kneschke 
355bcdc6a3bSJan Kneschke #ifdef USE_LDAP
356bcdc6a3bSJan Kneschke 		s->ldap_filter_pre = buffer_init();
357bcdc6a3bSJan Kneschke 		s->ldap_filter_post = buffer_init();
358bcdc6a3bSJan Kneschke 		s->ldap = NULL;
359bcdc6a3bSJan Kneschke #endif
360bcdc6a3bSJan Kneschke 
361bcdc6a3bSJan Kneschke 		cv[0].destination = s->auth_backend_conf;
362bcdc6a3bSJan Kneschke 		cv[1].destination = s->auth_plain_groupfile;
363bcdc6a3bSJan Kneschke 		cv[2].destination = s->auth_plain_userfile;
364bcdc6a3bSJan Kneschke 		cv[3].destination = s->auth_require;
365bcdc6a3bSJan Kneschke 		cv[4].destination = s->auth_ldap_hostname;
366bcdc6a3bSJan Kneschke 		cv[5].destination = s->auth_ldap_basedn;
367bcdc6a3bSJan Kneschke 		cv[6].destination = s->auth_ldap_filter;
3684a6ce4aeSJan Kneschke 		cv[7].destination = s->auth_ldap_cafile;
3694a6ce4aeSJan Kneschke 		cv[8].destination = &(s->auth_ldap_starttls);
3709238cad6SJan Kneschke 		cv[9].destination = s->auth_ldap_binddn;
3719238cad6SJan Kneschke 		cv[10].destination = s->auth_ldap_bindpw;
372d471bcc9SMarcus Rückert 		cv[11].destination = &(s->auth_ldap_allow_empty_pw);
373d471bcc9SMarcus Rückert 		cv[12].destination = s->auth_htdigest_userfile;
374d471bcc9SMarcus Rückert 		cv[13].destination = s->auth_htpasswd_userfile;
375d471bcc9SMarcus Rückert 		cv[14].destination = &(s->auth_debug);
376bcdc6a3bSJan Kneschke 
377bcdc6a3bSJan Kneschke 		p->config_storage[i] = s;
378bcdc6a3bSJan Kneschke 		ca = ((data_config *)srv->config_context->data[i])->value;
379bcdc6a3bSJan Kneschke 
380bcdc6a3bSJan Kneschke 		if (0 != config_insert_values_global(srv, ca, cv)) {
381bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
382bcdc6a3bSJan Kneschke 		}
383bcdc6a3bSJan Kneschke 
384bcdc6a3bSJan Kneschke 		if (s->auth_backend_conf->used) {
385bcdc6a3bSJan Kneschke 			if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
386bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_HTPASSWD;
387bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) {
388bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_HTDIGEST;
389bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "plain")) {
390bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_PLAIN;
391bcdc6a3bSJan Kneschke 			} else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) {
392bcdc6a3bSJan Kneschke 				s->auth_backend = AUTH_BACKEND_LDAP;
393bcdc6a3bSJan Kneschke 			} else {
394bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
395bcdc6a3bSJan Kneschke 
396bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
397bcdc6a3bSJan Kneschke 			}
398bcdc6a3bSJan Kneschke 		}
399bcdc6a3bSJan Kneschke 
400*e7ff9483SStefan Bühler #ifdef USE_LDAP
401*e7ff9483SStefan Bühler 		if (s->auth_ldap_filter->used) {
402*e7ff9483SStefan Bühler 			char *dollar;
403*e7ff9483SStefan Bühler 
404*e7ff9483SStefan Bühler 			/* parse filter */
405*e7ff9483SStefan Bühler 
406*e7ff9483SStefan Bühler 			if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
407*e7ff9483SStefan Bühler 				log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
408*e7ff9483SStefan Bühler 
409*e7ff9483SStefan Bühler 				return HANDLER_ERROR;
410*e7ff9483SStefan Bühler 			}
411*e7ff9483SStefan Bühler 
412*e7ff9483SStefan Bühler 			buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
413*e7ff9483SStefan Bühler 			buffer_copy_string(s->ldap_filter_post, dollar+1);
414*e7ff9483SStefan Bühler 		}
415*e7ff9483SStefan Bühler #endif
416*e7ff9483SStefan Bühler 
417bcdc6a3bSJan Kneschke 		/* no auth.require for this section */
418bcdc6a3bSJan Kneschke 		if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
419bcdc6a3bSJan Kneschke 
420bcdc6a3bSJan Kneschke 		if (da->type != TYPE_ARRAY) continue;
421bcdc6a3bSJan Kneschke 
422bcdc6a3bSJan Kneschke 		for (n = 0; n < da->value->used; n++) {
423bcdc6a3bSJan Kneschke 			size_t m;
424bcdc6a3bSJan Kneschke 			data_array *da_file = (data_array *)da->value->data[n];
425bcdc6a3bSJan Kneschke 			const char *method, *realm, *require;
426bcdc6a3bSJan Kneschke 
427bcdc6a3bSJan Kneschke 			if (da->value->data[n]->type != TYPE_ARRAY) {
428cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
429cc7a8ae0SJan Kneschke 						"auth.require should contain an array as in:",
430cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., ...) )");
431bcdc6a3bSJan Kneschke 
432bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
433bcdc6a3bSJan Kneschke 			}
434bcdc6a3bSJan Kneschke 
435bcdc6a3bSJan Kneschke 			method = realm = require = NULL;
436bcdc6a3bSJan Kneschke 
437bcdc6a3bSJan Kneschke 			for (m = 0; m < da_file->value->used; m++) {
438bcdc6a3bSJan Kneschke 				if (da_file->value->data[m]->type == TYPE_STRING) {
439bcdc6a3bSJan Kneschke 					if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
440bcdc6a3bSJan Kneschke 						method = ((data_string *)(da_file->value->data[m]))->value->ptr;
441bcdc6a3bSJan Kneschke 					} else if (0 == strcmp(da_file->value->data[m]->key->ptr, "realm")) {
442bcdc6a3bSJan Kneschke 						realm = ((data_string *)(da_file->value->data[m]))->value->ptr;
443bcdc6a3bSJan Kneschke 					} else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
444bcdc6a3bSJan Kneschke 						require = ((data_string *)(da_file->value->data[m]))->value->ptr;
445bcdc6a3bSJan Kneschke 					} else {
446cc7a8ae0SJan Kneschke 						log_error_write(srv, __FILE__, __LINE__, "ssbs",
447cc7a8ae0SJan Kneschke 							"the field is unknown in:",
448cc7a8ae0SJan Kneschke 							"auth.require = ( \"...\" => ( ..., -> \"",
449cc7a8ae0SJan Kneschke 							da_file->value->data[m]->key,
450cc7a8ae0SJan Kneschke 							"\" <- => \"...\" ) )");
451cc7a8ae0SJan Kneschke 
452bcdc6a3bSJan Kneschke 						return HANDLER_ERROR;
453bcdc6a3bSJan Kneschke 					}
454bcdc6a3bSJan Kneschke 				} else {
455cc7a8ae0SJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ssbs",
456cc7a8ae0SJan Kneschke 						"a string was expected for:",
457cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., -> \"",
458cc7a8ae0SJan Kneschke 						da_file->value->data[m]->key,
459cc7a8ae0SJan Kneschke 						"\" <- => \"...\" ) )");
460bcdc6a3bSJan Kneschke 
461bcdc6a3bSJan Kneschke 					return HANDLER_ERROR;
462bcdc6a3bSJan Kneschke 				}
463bcdc6a3bSJan Kneschke 			}
464bcdc6a3bSJan Kneschke 
465bcdc6a3bSJan Kneschke 			if (method == NULL) {
466cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
467cc7a8ae0SJan Kneschke 						"the require field is missing in:",
468cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
469bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
4704a6ce4aeSJan Kneschke 			} else {
4714a6ce4aeSJan Kneschke 				if (0 != strcmp(method, "basic") &&
4724a6ce4aeSJan Kneschke 				    0 != strcmp(method, "digest")) {
473cc7a8ae0SJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ss",
474cc7a8ae0SJan Kneschke 							"method has to be either \"basic\" or \"digest\" in",
475cc7a8ae0SJan Kneschke 							"auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
4764a6ce4aeSJan Kneschke 					return HANDLER_ERROR;
4774a6ce4aeSJan Kneschke 				}
478bcdc6a3bSJan Kneschke 			}
479bcdc6a3bSJan Kneschke 
480bcdc6a3bSJan Kneschke 			if (realm == NULL) {
481cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
482cc7a8ae0SJan Kneschke 						"the require field is missing in:",
483cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
484bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
485bcdc6a3bSJan Kneschke 			}
486bcdc6a3bSJan Kneschke 
487bcdc6a3bSJan Kneschke 			if (require == NULL) {
488cc7a8ae0SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss",
489cc7a8ae0SJan Kneschke 						"the require field is missing in:",
490cc7a8ae0SJan Kneschke 						"auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
491bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
492bcdc6a3bSJan Kneschke 			}
493bcdc6a3bSJan Kneschke 
494bcdc6a3bSJan Kneschke 			if (method && realm && require) {
495bcdc6a3bSJan Kneschke 				data_string *ds;
496bcdc6a3bSJan Kneschke 				data_array *a;
497bcdc6a3bSJan Kneschke 
498bcdc6a3bSJan Kneschke 				a = data_array_init();
499bcdc6a3bSJan Kneschke 				buffer_copy_string_buffer(a->key, da_file->key);
500bcdc6a3bSJan Kneschke 
501bcdc6a3bSJan Kneschke 				ds = data_string_init();
502bcdc6a3bSJan Kneschke 
50352861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("method"));
504bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, method);
505bcdc6a3bSJan Kneschke 
506bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
507bcdc6a3bSJan Kneschke 
508bcdc6a3bSJan Kneschke 				ds = data_string_init();
509bcdc6a3bSJan Kneschke 
51052861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("realm"));
511bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, realm);
512bcdc6a3bSJan Kneschke 
513bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
514bcdc6a3bSJan Kneschke 
515bcdc6a3bSJan Kneschke 				ds = data_string_init();
516bcdc6a3bSJan Kneschke 
51752861d77SStefan Bühler 				buffer_copy_string_len(ds->key, CONST_STR_LEN("require"));
518bcdc6a3bSJan Kneschke 				buffer_copy_string(ds->value, require);
519bcdc6a3bSJan Kneschke 
520bcdc6a3bSJan Kneschke 				array_insert_unique(a->value, (data_unset *)ds);
521bcdc6a3bSJan Kneschke 
522bcdc6a3bSJan Kneschke 				array_insert_unique(s->auth_require, (data_unset *)a);
523bcdc6a3bSJan Kneschke 			}
524bcdc6a3bSJan Kneschke 		}
525bcdc6a3bSJan Kneschke 
526bcdc6a3bSJan Kneschke 		switch(s->auth_backend) {
527ea7b9abaSJan Kneschke 		case AUTH_BACKEND_LDAP: {
528ea7b9abaSJan Kneschke 			handler_t ret = auth_ldap_init(srv, s);
529ea7b9abaSJan Kneschke 			if (ret == HANDLER_ERROR)
530ea7b9abaSJan Kneschke 				return (ret);
531ea7b9abaSJan Kneschke 			break;
532ea7b9abaSJan Kneschke 		}
533ea7b9abaSJan Kneschke 		default:
534ea7b9abaSJan Kneschke 			break;
535ea7b9abaSJan Kneschke 		}
536ea7b9abaSJan Kneschke 	}
537ea7b9abaSJan Kneschke 
538ea7b9abaSJan Kneschke 	return HANDLER_GO_ON;
539ea7b9abaSJan Kneschke }
540ea7b9abaSJan Kneschke 
5416ca932dfSJan Kneschke handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
542bcdc6a3bSJan Kneschke #ifdef USE_LDAP
543ea7b9abaSJan Kneschke 	int ret;
544bcdc6a3bSJan Kneschke #if 0
545bcdc6a3bSJan Kneschke 	if (s->auth_ldap_basedn->used == 0) {
546bcdc6a3bSJan Kneschke 		log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
547bcdc6a3bSJan Kneschke 
548bcdc6a3bSJan Kneschke 		return HANDLER_ERROR;
549bcdc6a3bSJan Kneschke 	}
550bcdc6a3bSJan Kneschke #endif
551bcdc6a3bSJan Kneschke 
552bcdc6a3bSJan Kneschke 	if (s->auth_ldap_hostname->used) {
553bcdc6a3bSJan Kneschke 		if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
554bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
555bcdc6a3bSJan Kneschke 
556bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
557bcdc6a3bSJan Kneschke 		}
558bcdc6a3bSJan Kneschke 
559bcdc6a3bSJan Kneschke 		ret = LDAP_VERSION3;
560bcdc6a3bSJan Kneschke 		if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
561bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
562bcdc6a3bSJan Kneschke 
563bcdc6a3bSJan Kneschke 			return HANDLER_ERROR;
564bcdc6a3bSJan Kneschke 		}
565bcdc6a3bSJan Kneschke 
5664a6ce4aeSJan Kneschke 		if (s->auth_ldap_starttls) {
5676ca932dfSJan Kneschke 			/* if no CA file is given, it is ok, as we will use encryption
5686ca932dfSJan Kneschke 				* if the server requires a CAfile it will tell us */
5696ca932dfSJan Kneschke 			if (!buffer_is_empty(s->auth_ldap_cafile)) {
5706ca932dfSJan Kneschke 				if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
5716ca932dfSJan Kneschke 								s->auth_ldap_cafile->ptr))) {
5726ca932dfSJan Kneschke 					log_error_write(srv, __FILE__, __LINE__, "ss",
5736ca932dfSJan Kneschke 							"Loading CA certificate failed:", ldap_err2string(ret));
5744a6ce4aeSJan Kneschke 
5754a6ce4aeSJan Kneschke 					return HANDLER_ERROR;
5764a6ce4aeSJan Kneschke 				}
5774a6ce4aeSJan Kneschke 			}
5784a6ce4aeSJan Kneschke 
5794a6ce4aeSJan Kneschke 			if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) {
5804a6ce4aeSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
5814a6ce4aeSJan Kneschke 
5824a6ce4aeSJan Kneschke 				return HANDLER_ERROR;
5834a6ce4aeSJan Kneschke 			}
5844a6ce4aeSJan Kneschke 		}
5854a6ce4aeSJan Kneschke 
586bcdc6a3bSJan Kneschke 
587bcdc6a3bSJan Kneschke 		/* 1. */
5889238cad6SJan Kneschke 		if (s->auth_ldap_binddn->used) {
5899238cad6SJan Kneschke 			if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
5909238cad6SJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
5919238cad6SJan Kneschke 
5929238cad6SJan Kneschke 				return HANDLER_ERROR;
5939238cad6SJan Kneschke 			}
5949238cad6SJan Kneschke 		} else {
595bcdc6a3bSJan Kneschke 			if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
596bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
597bcdc6a3bSJan Kneschke 
598bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
599bcdc6a3bSJan Kneschke 			}
600bcdc6a3bSJan Kneschke 		}
6019238cad6SJan Kneschke 	}
6025a9992b1SStefan Bühler 	return HANDLER_GO_ON;
603bcdc6a3bSJan Kneschke #else
6045a9992b1SStefan Bühler 	UNUSED(s);
605bcdc6a3bSJan Kneschke 	log_error_write(srv, __FILE__, __LINE__, "s", "no ldap support available");
606bcdc6a3bSJan Kneschke 	return HANDLER_ERROR;
607bcdc6a3bSJan Kneschke #endif
608bcdc6a3bSJan Kneschke }
609bcdc6a3bSJan Kneschke 
610bcdc6a3bSJan Kneschke int mod_auth_plugin_init(plugin *p) {
611bcdc6a3bSJan Kneschke 	p->version     = LIGHTTPD_VERSION_ID;
612bcdc6a3bSJan Kneschke 	p->name        = buffer_init_string("auth");
613bcdc6a3bSJan Kneschke 	p->init        = mod_auth_init;
614bcdc6a3bSJan Kneschke 	p->set_defaults = mod_auth_set_defaults;
615bcdc6a3bSJan Kneschke 	p->handle_uri_clean = mod_auth_uri_handler;
616bcdc6a3bSJan Kneschke 	p->cleanup     = mod_auth_free;
617bcdc6a3bSJan Kneschke 
618bcdc6a3bSJan Kneschke 	p->data        = NULL;
619bcdc6a3bSJan Kneschke 
620bcdc6a3bSJan Kneschke 	return 0;
621bcdc6a3bSJan Kneschke }
622