1/* COPYRIGHT
2 * Copyright (c) 2002-2003 Igor Brezac
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY IGOR BREZAC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL IGOR BREZAC OR
18 * ITS EMPLOYEES OR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
21 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
24 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25 * DAMAGE.
26 * END COPYRIGHT */
27
28#ifndef AUTH_LDAP
29	#include "mechanisms.h"
30	#include "utils.h"
31#endif
32
33#ifdef AUTH_LDAP
34
35#include <sys/time.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <syslog.h>
40#include <ctype.h>
41
42#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
46#ifdef HAVE_CRYPT_H
47#include <crypt.h>
48#endif
49
50#ifdef HAVE_OPENSSL
51#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
52#define OPENSSL_DISABLE_OLD_DES_SUPPORT
53#endif
54#include <openssl/evp.h>
55#include <openssl/des.h>
56#endif
57
58#define LDAP_DEPRECATED 1
59#include <ldap.h>
60#include <lber.h>
61#include <sasl.h>
62#include "lak.h"
63
64typedef struct lak_auth_method {
65	int method;
66	int (*check) (LAK *lak, const char *user, const char *service, const char *realm, const char *password) ;
67} LAK_AUTH_METHOD;
68
69typedef struct lak_hash_rock {
70	const char *mda;
71	int salted;
72} LAK_HASH_ROCK;
73
74typedef struct lak_password_scheme {
75	char *hash;
76	int (*check) (const char *cred, const char *passwd, void *rock);
77	void *rock;
78} LAK_PASSWORD_SCHEME;
79
80static int lak_config_read(LAK_CONF *, const char *);
81static int lak_config_int(const char *);
82static int lak_config_switch(const char *);
83static void lak_config_free(LAK_CONF *);
84static int lak_config(const char *, LAK_CONF **);
85static int lak_escape(const char *, const unsigned int, char **);
86static int lak_tokenize_domains(const char *, int, char **);
87static int lak_expand_tokens(const char *, const char *, const char *, const char *, const char *, char **);
88static int lak_connect(LAK *);
89static int lak_bind(LAK *, LAK_USER *);
90static void lak_unbind(LAK *);
91static int lak_auth_custom(LAK *, const char *, const char *, const char *, const char *);
92static int lak_auth_bind(LAK *, const char *, const char *, const char *, const char *);
93static int lak_auth_fastbind(LAK *, const char *, const char *, const char *, const char *);
94static int lak_group_member(LAK *, const char *, const char *, const char *, const char *);
95static char *lak_result_get(const LAK_RESULT *, const char *);
96static int lak_result_add(const char *, const char *, LAK_RESULT **);
97static int lak_check_password(const char *, const char *, void *);
98static int lak_check_crypt(const char *, const char *, void *);
99#ifdef HAVE_OPENSSL
100static int lak_base64_decode(const char *, char **, int *);
101static int lak_check_hashed(const char *, const char *, void *);
102#endif
103static int lak_sasl_interact(LDAP *, unsigned, void *, void *);
104static int lak_user(const char *, const char *, const char *, const char *, const char *, const char *, LAK_USER **);
105static int lak_user_copy(LAK_USER **, const LAK_USER *);
106static int lak_user_cmp(const LAK_USER *, const LAK_USER *);
107static void lak_user_free(LAK_USER *);
108
109static LAK_AUTH_METHOD authenticator[] = {
110	{ LAK_AUTH_METHOD_BIND, lak_auth_bind },
111	{ LAK_AUTH_METHOD_CUSTOM, lak_auth_custom },
112	{ LAK_AUTH_METHOD_FASTBIND, lak_auth_fastbind },
113	{ -1, NULL }
114};
115
116static LAK_HASH_ROCK hash_rock[] = {
117	{ "md5", 0 },
118	{ "md5", 1 },
119	{ "sha1", 0 },
120	{ "sha1", 1 }
121};
122
123static LAK_PASSWORD_SCHEME password_scheme[] = {
124	{ "{CRYPT}", lak_check_crypt, NULL },
125	{ "{UNIX}", lak_check_crypt, NULL },
126#ifdef HAVE_OPENSSL
127	{ "{MD5}", lak_check_hashed, &hash_rock[0] },
128	{ "{SMD5}", lak_check_hashed, &hash_rock[1] },
129	{ "{SHA}", lak_check_hashed, &hash_rock[2] },
130	{ "{SSHA}", lak_check_hashed, &hash_rock[3] },
131#endif
132	{ NULL, NULL, NULL }
133};
134
135static const char *dn_attr = "dn";
136
137#define ISSET(x)  ((x != NULL) && (*(x) != '\0'))
138#define EMPTY(x)  ((x == NULL) || (*(x) == '\0'))
139
140static int lak_config_read(
141	LAK_CONF *conf,
142	const char *configfile)
143{
144	FILE *infile;
145	int lineno = 0;
146	char buf[4096];
147	char *p, *key;
148
149	infile = fopen(configfile, "r");
150	if (!infile) {
151	    syslog(LOG_ERR|LOG_AUTH,
152		   "Could not open saslauthd config file: %s (%m)",
153		   configfile);
154	    return LAK_FAIL;
155	}
156
157	while (fgets(buf, sizeof(buf), infile)) {
158		lineno++;
159
160		if (buf[strlen(buf)-1] == '\n')
161			buf[strlen(buf)-1] = '\0';
162		for (p = buf; *p && isspace((int) *p); p++);
163		if (!*p || *p == '#')
164		    continue;
165
166		key = p;
167		while (*p && (isalnum((int) *p) || *p == '-' || *p == '_')) {
168			if (isupper((int) *p))
169				*p = tolower(*p);
170			p++;
171		}
172		if (*p != ':') {
173			fclose(infile);
174			return LAK_FAIL;
175		}
176
177		*p++ = '\0';
178
179		while (*p && isspace((int) *p))
180			p++;
181
182		if (!*p) {
183			fclose(infile);
184			return LAK_FAIL;
185		}
186
187		if (!strcasecmp(key, "ldap_servers"))
188			strlcpy(conf->servers, p, LAK_URL_LEN);
189
190		else if (!strcasecmp(key, "ldap_bind_dn"))
191			strlcpy(conf->bind_dn, p, LAK_DN_LEN);
192
193		else if (!strcasecmp(key, "ldap_bind_pw") ||
194		         !strcasecmp(key, "ldap_password"))
195			strlcpy(conf->password, p, LAK_BUF_LEN);
196
197		else if (!strcasecmp(key, "ldap_version"))
198			conf->version = lak_config_int(p);
199
200		else if (!strcasecmp(key, "ldap_search_base"))
201			strlcpy(conf->search_base, p, LAK_DN_LEN);
202
203		else if (!strcasecmp(key, "ldap_filter"))
204			strlcpy(conf->filter, p, LAK_DN_LEN);
205
206		else if (!strcasecmp(key, "ldap_password_attr"))
207			strlcpy(conf->password_attr, p, LAK_BUF_LEN);
208
209		else if (!strcasecmp(key, "ldap_group_dn"))
210			strlcpy(conf->group_dn, p, LAK_DN_LEN);
211
212		else if (!strcasecmp(key, "ldap_group_attr"))
213			strlcpy(conf->group_attr, p, LAK_BUF_LEN);
214
215		else if (!strcasecmp(key, "ldap_group_filter"))
216			strlcpy(conf->group_filter, p, LAK_BUF_LEN);
217
218		else if (!strcasecmp(key, "ldap_group_search_base"))
219			strlcpy(conf->group_search_base, p, LAK_BUF_LEN);
220
221		else if (!strcasecmp(key, "ldap_group_scope")) {
222			if (!strcasecmp(p, "one")) {
223				conf->group_scope = LDAP_SCOPE_ONELEVEL;
224			} else if (!strcasecmp(p, "base")) {
225				conf->group_scope = LDAP_SCOPE_BASE;
226			}
227		} else if (!strcasecmp(key, "ldap_group_match_method")) {
228			if (!strcasecmp(p, "filter")) {
229				conf->group_match_method = LAK_GROUP_MATCH_METHOD_FILTER;
230			} else if (!strcasecmp(p, "attr")) {
231				conf->group_match_method = LAK_GROUP_MATCH_METHOD_ATTR;
232			}
233		} else if (!strcasecmp(key, "ldap_default_realm") ||
234		         !strcasecmp(key, "ldap_default_domain"))
235			strlcpy(conf->default_realm, p, LAK_BUF_LEN);
236
237		else if (!strcasecmp(key, "ldap_auth_method")) {
238			if (!strcasecmp(p, "custom")) {
239				conf->auth_method = LAK_AUTH_METHOD_CUSTOM;
240			} else if (!strcasecmp(p, "fastbind")) {
241				conf->auth_method = LAK_AUTH_METHOD_FASTBIND;
242			}
243		} else if (!strcasecmp(key, "ldap_timeout")) {
244			conf->timeout.tv_sec = lak_config_int(p);
245			conf->timeout.tv_usec = 0;
246		} else if (!strcasecmp(key, "ldap_size_limit"))
247			conf->size_limit = lak_config_int(p);
248
249		else if (!strcasecmp(key, "ldap_time_limit"))
250			conf->time_limit = lak_config_int(p);
251
252		else if (!strcasecmp(key, "ldap_deref")) {
253			if (!strcasecmp(p, "search")) {
254				conf->deref = LDAP_DEREF_SEARCHING;
255			} else if (!strcasecmp(p, "find")) {
256				conf->deref = LDAP_DEREF_FINDING;
257			} else if (!strcasecmp(p, "always")) {
258				conf->deref = LDAP_DEREF_ALWAYS;
259			} else if (!strcasecmp(p, "never")) {
260				conf->deref = LDAP_DEREF_NEVER;
261			}
262		} else if (!strcasecmp(key, "ldap_referrals")) {
263			conf->referrals = lak_config_switch(p);
264
265		} else if (!strcasecmp(key, "ldap_restart")) {
266			conf->restart = lak_config_switch(p);
267
268		} else if (!strcasecmp(key, "ldap_scope")) {
269			if (!strcasecmp(p, "one")) {
270				conf->scope = LDAP_SCOPE_ONELEVEL;
271			} else if (!strcasecmp(p, "base")) {
272				conf->scope = LDAP_SCOPE_BASE;
273			}
274		} else if (!strcasecmp(key, "ldap_use_sasl")) {
275			conf->use_sasl = lak_config_switch(p);
276
277		} else if (!strcasecmp(key, "ldap_id") ||
278                   !strcasecmp(key, "ldap_sasl_authc_id"))
279			strlcpy(conf->id, p, LAK_BUF_LEN);
280
281		else if (!strcasecmp(key, "ldap_authz_id") ||
282                 !strcasecmp(key, "ldap_sasl_authz_id"))
283			strlcpy(conf->authz_id, p, LAK_BUF_LEN);
284
285		else if (!strcasecmp(key, "ldap_realm") ||
286                 !strcasecmp(key, "ldap_sasl_realm"))
287			strlcpy(conf->realm, p, LAK_BUF_LEN);
288
289		else if (!strcasecmp(key, "ldap_mech") ||
290                 !strcasecmp(key, "ldap_sasl_mech"))
291			strlcpy(conf->mech, p, LAK_BUF_LEN);
292
293		else if (!strcasecmp(key, "ldap_sasl_secprops"))
294			strlcpy(conf->sasl_secprops, p, LAK_BUF_LEN);
295
296		else if (!strcasecmp(key, "ldap_start_tls"))
297			conf->start_tls = lak_config_switch(p);
298
299		else if (!strcasecmp(key, "ldap_tls_check_peer"))
300			conf->tls_check_peer = lak_config_switch(p);
301
302		else if (!strcasecmp(key, "ldap_tls_cacert_file"))
303			strlcpy(conf->tls_cacert_file, p, LAK_PATH_LEN);
304
305		else if (!strcasecmp(key, "ldap_tls_cacert_dir"))
306			strlcpy(conf->tls_cacert_dir, p, LAK_PATH_LEN);
307
308		else if (!strcasecmp(key, "ldap_tls_ciphers"))
309			strlcpy(conf->tls_ciphers, p, LAK_BUF_LEN);
310
311		else if (!strcasecmp(key, "ldap_tls_cert"))
312			strlcpy(conf->tls_cert, p, LAK_PATH_LEN);
313
314		else if (!strcasecmp(key, "ldap_tls_key"))
315			strlcpy(conf->tls_key, p, LAK_PATH_LEN);
316
317		else if (!strcasecmp(key, "ldap_debug"))
318			conf->debug = lak_config_int(p);
319	}
320
321	if (conf->version != LDAP_VERSION3 &&
322	    (conf->use_sasl ||
323	     conf->start_tls))
324	    conf->version = LDAP_VERSION3;
325
326    if (conf->use_sasl &&
327        conf->auth_method == LAK_AUTH_METHOD_BIND)
328        conf->auth_method = LAK_AUTH_METHOD_FASTBIND;
329
330    if ( ISSET(conf->group_filter) &&
331         ISSET(conf->search_base) &&
332         EMPTY(conf->group_search_base) )
333        strlcpy(conf->group_search_base, conf->search_base, LAK_DN_LEN);
334
335	fclose(infile);
336
337	return LAK_OK;
338}
339
340static int lak_config_int(
341	const char *val)
342{
343    if (!val) return 0;
344
345    if (!isdigit((int) *val) && (*val != '-' || !isdigit((int) val[1]))) return 0;
346
347    return atoi(val);
348}
349
350static int lak_config_switch(
351	const char *val)
352{
353    if (!val) return 0;
354
355    if (*val == '0' || *val == 'n' ||
356	(*val == 'o' && val[1] == 'f') || *val == 'f') {
357	return 0;
358    } else if (*val == '1' || *val == 'y' ||
359	     (*val == 'o' && val[1] == 'n') || *val == 't') {
360	return 1;
361    }
362    return 0;
363}
364
365static int lak_config(
366	const char *configfile,
367	LAK_CONF **ret)
368{
369	LAK_CONF *conf;
370	int rc = 0;
371
372	conf = malloc( sizeof(LAK_CONF) );
373	if (conf == NULL) {
374		return LAK_NOMEM;
375	}
376
377	memset(conf, 0, sizeof(LAK_CONF));
378
379	strlcpy(conf->servers, "ldap://localhost/", LAK_BUF_LEN);
380	conf->version = LDAP_VERSION3;
381	strlcpy(conf->filter, "(uid=%u)", LAK_DN_LEN);
382	strlcpy(conf->password_attr, "userPassword", LAK_BUF_LEN);
383	conf->scope = LDAP_SCOPE_SUBTREE;
384	strlcpy(conf->group_attr, "uniqueMember", LAK_BUF_LEN);
385	conf->group_scope = LDAP_SCOPE_SUBTREE;
386    conf->group_match_method = LAK_GROUP_MATCH_METHOD_ATTR;
387	conf->auth_method = LAK_AUTH_METHOD_BIND;
388	conf->timeout.tv_sec = 5;
389	conf->timeout.tv_usec = 0;
390	conf->size_limit = 1;
391	conf->time_limit = 5;
392	conf->deref = LDAP_DEREF_NEVER;
393	conf->restart = 1;
394	conf->start_tls = 0;
395	conf->use_sasl = 0;
396
397	strlcpy(conf->path, configfile, LAK_PATH_LEN);
398
399	rc = lak_config_read(conf, conf->path);
400	if (rc != LAK_OK) {
401		lak_config_free(conf);
402		return rc;
403	}
404
405	*ret = conf;
406	return LAK_OK;
407}
408
409static void lak_config_free(
410	LAK_CONF *conf)
411{
412	if (conf == NULL) {
413		return;
414	}
415
416	memset(conf, 0, sizeof(LAK_CONF));
417
418	free (conf);
419
420	return;
421}
422
423/*
424 * Note: calling function must free memory.
425 */
426static int lak_escape(
427	const char *s,
428	const unsigned int n,
429	char **result)
430{
431	char *buf;
432	char *end, *ptr, *temp;
433
434	if (n > strlen(s))  // Sanity check, just in case
435		return LAK_FAIL;
436
437	buf = malloc(n * 5 + 1);
438	if (buf == NULL) {
439		return LAK_NOMEM;
440	}
441
442	buf[0] = '\0';
443	ptr = (char *)s;
444	end = ptr + n;
445
446	while (((temp = strpbrk(ptr, "*()\\\0"))!=NULL) && (temp<end)) {
447
448		if (temp>ptr)
449			strncat(buf, ptr, temp-ptr);
450
451		switch (*temp) {
452			case '*':
453				strcat(buf, "\\2a");
454				break;
455			case '(':
456				strcat(buf, "\\28");
457				break;
458			case ')':
459				strcat(buf, "\\29");
460				break;
461			case '\\':
462				strcat(buf, "\\5c");
463				break;
464			case '\0':
465				strcat(buf, "\\00");
466				break;
467		}
468		ptr=temp+1;
469	}
470	if (ptr<end)
471		strncat(buf, ptr, end-ptr);
472
473	*result = buf;
474
475	return LAK_OK;
476}
477
478static int lak_tokenize_domains(
479	const char *d,
480	int n,
481	char **result)
482{
483	char *s, *s1;
484	char *lasts;
485	int nt, i, rc;
486
487	*result = NULL;
488
489	if (d == NULL || n < 1 || n > 9)
490		return LAK_FAIL;
491
492	s = strdup(d);
493	if (s == NULL)
494		return LAK_NOMEM;
495
496	for( nt=0, s1=s; *s1; s1++ )
497		if( *s1 == '.' ) nt++;
498	nt++;
499
500	if (n > nt) {
501		free(s);
502		return LAK_FAIL;
503	}
504
505	i = nt - n;
506	s1 = (char *)strtok_r(s, ".", &lasts);
507	while(s1) {
508		if (i == 0) {
509			rc = lak_escape(s1, strlen(s1), result);
510			free(s);
511			return rc;
512		}
513		s1 = (char *)strtok_r(NULL, ".", &lasts);
514		i--;
515	}
516
517	free(s);
518	return LAK_FAIL;
519}
520
521#define LAK_MAX(a,b) (a>b?a:b)
522
523/*
524 * lak_expand_tokens
525 * Parts with the strings provided.
526 *   %%   = %
527 *   %u   = user
528 *   %U   = user part of %u
529 *   %d   = domain part of %u if available, othwise same as %r
530 *   %1-9 = domain if not available realm, token
531 *          (%1 = tld, %2 = domain when %r = domain.tld)
532 *   %s   = service
533 *   %r   = realm
534 *   %R   = prepend '@' to realm
535 *   %D   = user DN
536 * Note: calling function must free memory.
537 */
538static int lak_expand_tokens(
539	const char *pattern,
540	const char *username,
541	const char *service,
542	const char *realm,
543	const char *dn,
544	char **result)
545{
546	char *buf;
547	char *end, *ptr, *temp;
548	char *ebuf, *user;
549	char *domain;
550	int rc;
551
552	/* to permit multiple occurences of username and/or realm in filter */
553	/* and avoid memory overflow in filter build [eg: (|(uid=%u)(userid=%u)) ] */
554	int percents, service_len, realm_len, dn_len, user_len, maxparamlength;
555
556	if (pattern == NULL) {
557		syslog(LOG_ERR|LOG_AUTH, "filter pattern not setup");
558		return LAK_FAIL;
559	}
560
561	/* find the longest param of username and realm,
562	   do not worry about domain because it is always shorter
563	   then username                                           */
564	user_len=ISSET(username) ? strlen(username) : 0;
565	service_len=ISSET(service) ? strlen(service) : 0;
566	realm_len=ISSET(realm) ? strlen(realm) : 0;
567	dn_len=ISSET(dn) ? strlen(dn) : 0;
568
569	maxparamlength = LAK_MAX(user_len, service_len);
570	maxparamlength = LAK_MAX(maxparamlength, realm_len + 1);  /* +1 for %R when '@' is prepended */
571	maxparamlength = LAK_MAX(maxparamlength, dn_len);
572
573	/* find the number of occurences of percent sign in filter */
574	for( percents=0, buf=(char *)pattern; *buf; buf++ ) {
575		if( *buf == '%' ) percents++;
576	}
577
578	/* percents * 3 * maxparamlength because we need to account for
579         * an entirely-escaped worst-case-length parameter */
580	buf=malloc(strlen(pattern) + (percents * 3 * maxparamlength) + 1);
581	if(buf == NULL)
582		return LAK_NOMEM;
583	buf[0] = '\0';
584
585	ptr = (char *)pattern;
586	end = ptr + strlen(ptr);
587
588	while ((temp=strchr(ptr,'%'))!=NULL ) {
589
590		if ((temp-ptr) > 0)
591			strncat(buf, ptr, temp-ptr);
592
593		if ((temp+1) >= end) {
594			syslog(LOG_DEBUG|LOG_AUTH, "Incomplete lookup substitution format");
595			break;
596		}
597
598		switch (*(temp+1)) {
599			case '%':
600				strncat(buf,temp+1,1);
601				break;
602			case 'u':
603				if (ISSET(username)) {
604					rc=lak_escape(username, strlen(username), &ebuf);
605					if (rc == LAK_OK) {
606						strcat(buf,ebuf);
607						free(ebuf);
608					}
609				} else
610					syslog(LOG_DEBUG|LOG_AUTH, "Username not available.");
611				break;
612			case 'U':
613				if (ISSET(username)) {
614					user = strchr(username, '@');
615					rc=lak_escape(username, (user ? user - username : strlen(username)), &ebuf);
616					if (rc == LAK_OK) {
617						strcat(buf,ebuf);
618						free(ebuf);
619					}
620				} else
621					syslog(LOG_DEBUG|LOG_AUTH, "Username not available.");
622				break;
623			case '1':
624			case '2':
625			case '3':
626			case '4':
627			case '5':
628			case '6':
629			case '7':
630			case '8':
631			case '9':
632				if (ISSET(username) &&
633				    ((domain = strchr(username, '@')) && domain[1]!='\0')) {
634					rc=lak_tokenize_domains(domain+1, (int) *(temp+1)-48, &ebuf);
635					if (rc == LAK_OK) {
636						strcat(buf,ebuf);
637						free(ebuf);
638					}
639				} else if (ISSET(realm)) {
640					rc=lak_tokenize_domains(realm, (int) *(temp+1)-48, &ebuf);
641					if (rc == LAK_OK) {
642						strcat(buf,ebuf);
643						free(ebuf);
644					}
645				} else
646					syslog(LOG_DEBUG|LOG_AUTH, "Domain/Realm not available.");
647				break;
648			case 'd':
649				if (ISSET(username) &&
650				    ((domain = strchr(username, '@')) && domain[1]!='\0')) {
651					rc=lak_escape(domain+1, strlen(domain+1), &ebuf);
652					if (rc == LAK_OK) {
653						strcat(buf,ebuf);
654						free(ebuf);
655					}
656					break;
657				}
658			case 'R':
659			case 'r':
660				if (ISSET(realm)) {
661					rc = lak_escape(realm, strlen(realm), &ebuf);
662					if (rc == LAK_OK) {
663						if (*(temp+1) == 'R')
664							strcat(buf,"@");
665						strcat(buf,ebuf);
666						free(ebuf);
667					}
668				} else
669					syslog(LOG_DEBUG|LOG_AUTH, "Domain/Realm not available.");
670				break;
671			case 's':
672				if (ISSET(service)) {
673					rc = lak_escape(service, strlen(service), &ebuf);
674					if (rc == LAK_OK) {
675						strcat(buf,ebuf);
676						free(ebuf);
677					}
678				} else
679					syslog(LOG_DEBUG|LOG_AUTH, "Service not available.");
680				break;
681			case 'D':
682				if (ISSET(dn)) {
683					rc = lak_escape(dn, strlen(dn), &ebuf);
684					if (rc == LAK_OK) {
685						strcat(buf,ebuf);
686						free(ebuf);
687					}
688				} else
689					syslog(LOG_DEBUG|LOG_AUTH, "User DN not available.");
690				break;
691			default:
692				break;
693		}
694		ptr=temp+2;
695	}
696	if (temp<end)
697		strcat(buf, ptr);
698
699	*result = buf;
700
701	return LAK_OK;
702}
703
704int lak_init(
705	const char *configfile,
706	LAK **ret)
707{
708	LAK *lak;
709	int rc;
710
711	lak = *ret;
712
713	if (lak != NULL) {
714		return LAK_OK;
715	}
716
717	lak = (LAK *)malloc(sizeof(LAK));
718	if (lak == NULL)
719		return LAK_NOMEM;
720
721	lak->status=LAK_NOT_BOUND;
722	lak->ld=NULL;
723	lak->conf=NULL;
724	lak->user=NULL;
725
726	rc = lak_config(configfile, &lak->conf);
727	if (rc != LAK_OK) {
728		free(lak);
729		return rc;
730	}
731
732#ifdef HAVE_OPENSSL
733	OpenSSL_add_all_digests();
734#endif
735
736	*ret=lak;
737	return LAK_OK;
738}
739
740void lak_close(
741	LAK *lak)
742{
743
744	if (lak == NULL)
745		return;
746
747	lak_config_free(lak->conf);
748
749	lak_unbind(lak);
750
751	free(lak);
752
753#ifdef HAVE_OPENSSL
754	EVP_cleanup();
755#endif
756
757	return;
758}
759
760static int lak_connect(
761	LAK *lak)
762{
763	int rc = 0;
764	char *p = NULL;
765
766	if (ISSET(lak->conf->tls_cacert_file)) {
767		rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, lak->conf->tls_cacert_file);
768		if (rc != LDAP_SUCCESS) {
769			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_CACERTFILE (%s).", ldap_err2string (rc));
770		}
771	}
772
773	if (ISSET(lak->conf->tls_cacert_dir)) {
774		rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, lak->conf->tls_cacert_dir);
775		if (rc != LDAP_SUCCESS) {
776			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_CACERTDIR (%s).", ldap_err2string (rc));
777		}
778	}
779
780	if (lak->conf->tls_check_peer != 0) {
781		rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &lak->conf->tls_check_peer);
782		if (rc != LDAP_SUCCESS) {
783			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_REQUIRE_CERT (%s).", ldap_err2string (rc));
784		}
785	}
786
787	if (ISSET(lak->conf->tls_ciphers)) {
788		/* set cipher suite, certificate and private key: */
789		rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, lak->conf->tls_ciphers);
790		if (rc != LDAP_SUCCESS) {
791			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_CIPHER_SUITE (%s).", ldap_err2string (rc));
792		}
793	}
794
795	if (ISSET(lak->conf->tls_cert)) {
796		rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, lak->conf->tls_cert);
797		if (rc != LDAP_SUCCESS) {
798			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_CERTFILE (%s).", ldap_err2string (rc));
799		}
800	}
801
802	if (ISSET(lak->conf->tls_key)) {
803		rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE, lak->conf->tls_key);
804		if (rc != LDAP_SUCCESS) {
805			syslog (LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_X_TLS_KEYFILE (%s).", ldap_err2string (rc));
806		}
807	}
808
809	rc = ldap_initialize(&lak->ld, lak->conf->servers);
810	if (rc != LDAP_SUCCESS) {
811		syslog(LOG_ERR|LOG_AUTH, "ldap_initialize failed (%s)", lak->conf->servers);
812		return LAK_CONNECT_FAIL;
813	}
814
815	if (lak->conf->debug) {
816		rc = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &(lak->conf->debug));
817		if (rc != LDAP_OPT_SUCCESS)
818			syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_DEBUG_LEVEL %x.", lak->conf->debug);
819	}
820
821	rc = ldap_set_option(lak->ld, LDAP_OPT_PROTOCOL_VERSION, &(lak->conf->version));
822	if (rc != LDAP_OPT_SUCCESS) {
823
824		if (lak->conf->use_sasl ||
825		    lak->conf->start_tls) {
826			syslog(LOG_ERR|LOG_AUTH, "Failed to set LDAP_OPT_PROTOCOL_VERSION %d, required for ldap_start_tls and ldap_use_sasl.", lak->conf->version);
827			lak_unbind(lak);
828			return LAK_CONNECT_FAIL;
829		} else
830			syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_PROTOCOL_VERSION %d.", lak->conf->version);
831
832		lak->conf->version = LDAP_VERSION2;
833
834	}
835
836	rc = ldap_set_option(lak->ld, LDAP_OPT_NETWORK_TIMEOUT, &(lak->conf->timeout));
837	if (rc != LDAP_OPT_SUCCESS) {
838		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_NETWORK_TIMEOUT %d.%d.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec);
839	}
840
841	rc = ldap_set_option(lak->ld, LDAP_OPT_TIMELIMIT, &(lak->conf->time_limit));
842	if (rc != LDAP_OPT_SUCCESS) {
843		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_TIMELIMIT %d.", lak->conf->time_limit);
844	}
845
846	rc = ldap_set_option(lak->ld, LDAP_OPT_DEREF, &(lak->conf->deref));
847	if (rc != LDAP_OPT_SUCCESS) {
848		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_DEREF %d.", lak->conf->deref);
849	}
850
851	rc = ldap_set_option(lak->ld, LDAP_OPT_REFERRALS, lak->conf->referrals ? LDAP_OPT_ON : LDAP_OPT_OFF);
852	if (rc != LDAP_OPT_SUCCESS) {
853		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_REFERRALS.");
854	}
855
856	rc = ldap_set_option(lak->ld, LDAP_OPT_SIZELIMIT, &(lak->conf->size_limit));
857	if (rc != LDAP_OPT_SUCCESS)
858		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_SIZELIMIT %d.", lak->conf->size_limit);
859
860	rc = ldap_set_option(lak->ld, LDAP_OPT_RESTART, lak->conf->restart ? LDAP_OPT_ON : LDAP_OPT_OFF);
861	if (rc != LDAP_OPT_SUCCESS) {
862		syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_RESTART.");
863	}
864
865	if (lak->conf->start_tls) {
866
867		rc = ldap_start_tls_s(lak->ld, NULL, NULL);
868		if (rc != LDAP_SUCCESS) {
869			syslog(LOG_ERR|LOG_AUTH, "start tls failed (%s).", ldap_err2string(rc));
870			lak_unbind(lak);
871			return LAK_CONNECT_FAIL;
872		}
873	}
874
875	if (lak->conf->use_sasl) {
876
877		if (EMPTY(lak->conf->mech)) {
878			ldap_get_option(lak->ld, LDAP_OPT_X_SASL_MECH, &p);
879			if (p)
880				strlcpy(lak->conf->mech, p, LAK_BUF_LEN);
881		}
882
883		if (EMPTY(lak->conf->realm)) {
884			ldap_get_option(lak->ld, LDAP_OPT_X_SASL_REALM, &p);
885			if (p)
886				strlcpy(lak->conf->realm, p, LAK_BUF_LEN);
887		}
888
889		if (ISSET(lak->conf->sasl_secprops)) {
890			rc = ldap_set_option(lak->ld, LDAP_OPT_X_SASL_SECPROPS, (void *) lak->conf->sasl_secprops);
891			if( rc != LDAP_OPT_SUCCESS ) {
892				syslog(LOG_ERR|LOG_AUTH, "Unable to set LDAP_OPT_X_SASL_SECPROPS.");
893				lak_unbind(lak);
894				return LAK_CONNECT_FAIL;
895			}
896		}
897	}
898
899
900	return LAK_OK;
901}
902
903static int lak_user(
904	const char *bind_dn,
905	const char *id,
906	const char *authz_id,
907	const char *mech,
908	const char *realm,
909	const char *password,
910	LAK_USER **ret)
911{
912	LAK_USER *lu = NULL;
913
914	*ret = NULL;
915
916	lu = (LAK_USER *)malloc(sizeof(LAK_USER));
917	if (lu == NULL)
918		return LAK_NOMEM;
919
920	memset(lu, 0, sizeof(LAK_USER));
921
922	if (ISSET(bind_dn))
923		strlcpy(lu->bind_dn, bind_dn, LAK_DN_LEN);
924
925	if (ISSET(id))
926		strlcpy(lu->id, id, LAK_BUF_LEN);
927
928	if (ISSET(authz_id))
929		strlcpy(lu->authz_id, authz_id, LAK_BUF_LEN);
930
931	if (ISSET(mech))
932		strlcpy(lu->mech, mech, LAK_BUF_LEN);
933
934	if (ISSET(realm))
935		strlcpy(lu->realm, realm, LAK_BUF_LEN);
936
937	if (ISSET(password))
938		strlcpy(lu->password, password, LAK_BUF_LEN);
939
940	*ret = lu;
941	return LAK_OK;
942}
943
944static int lak_user_cmp(
945	const LAK_USER *lu1,
946	const LAK_USER *lu2)
947{
948
949	if (lu1 == NULL ||
950	    lu2 == NULL)
951		return LAK_FAIL;
952
953	if (memcmp(lu1, lu2, sizeof(LAK_USER)) == 0)
954		return LAK_OK;
955
956	return LAK_FAIL;
957}
958
959static int lak_user_copy(
960	LAK_USER **lu1,
961	const LAK_USER *lu2)
962{
963	LAK_USER *lu;
964
965	lu = *lu1;
966
967	if (lu2 == NULL)
968		return LAK_FAIL;
969
970	if (lu == NULL) {
971		lu = (LAK_USER *)malloc(sizeof(LAK_USER));
972		if (lu == NULL)
973			return LAK_NOMEM;
974
975		*lu1 = lu;
976	}
977
978	memcpy((void *)lu, (void *)lu2, sizeof(LAK_USER));
979
980	return LAK_OK;
981}
982
983static void lak_user_free(
984	LAK_USER *user)
985{
986	if (user == NULL) {
987		return;
988	}
989
990	memset(user, 0, sizeof(LAK_USER));
991
992	free(user);
993
994	return;
995}
996
997static int lak_sasl_interact(
998	LDAP *ld,
999	unsigned flags __attribute__((unused)),
1000	void *def,
1001	void *inter)
1002{
1003	sasl_interact_t *in = inter;
1004	const char *p;
1005	LAK_USER *lu = def;
1006
1007	for (;in->id != SASL_CB_LIST_END;in++) {
1008		p = NULL;
1009		switch(in->id) {
1010			case SASL_CB_AUTHNAME:
1011				if (ISSET(lu->id))
1012					p = lu->id;
1013				if (!p)
1014					ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &p);
1015				break;
1016			case SASL_CB_USER:
1017				if (ISSET(lu->authz_id))
1018					p = lu->authz_id;
1019				if (!p)
1020					ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &p);
1021				break;
1022			case SASL_CB_GETREALM:
1023				if (ISSET(lu->realm))
1024					p = lu->realm;
1025				break;
1026			case SASL_CB_PASS:
1027				if (ISSET(lu->password))
1028					p = lu->password;
1029				break;
1030		}
1031
1032		in->result = ISSET(p) ? p : "";
1033		in->len = strlen(in->result);
1034	}
1035
1036	return LDAP_SUCCESS;
1037}
1038
1039static int lak_bind(
1040	LAK *lak,
1041	LAK_USER *user)
1042{
1043	int rc;
1044
1045	if (user == NULL)  // Sanity Check
1046		return LAK_FAIL;
1047
1048	if ((lak->status == LAK_BOUND) &&
1049	    (lak_user_cmp(lak->user, user) == LAK_OK))
1050		return LAK_OK;
1051
1052	lak_user_free(lak->user);
1053	lak->user = NULL;
1054
1055	if (
1056#if LDAP_VENDOR_VERSION < 20204
1057        lak->conf->use_sasl ||
1058#endif
1059	    lak->conf->version == LDAP_VERSION2)
1060		lak->status = LAK_NOT_BOUND;
1061
1062	if (lak->status == LAK_NOT_BOUND) {
1063		lak_unbind(lak);
1064		rc = lak_connect(lak);
1065		if (rc != LAK_OK)
1066			return rc;
1067	}
1068
1069	if (lak->conf->use_sasl)
1070		rc = ldap_sasl_interactive_bind_s(
1071			lak->ld,
1072			user->bind_dn,
1073			user->mech,
1074			NULL,
1075			NULL,
1076			LDAP_SASL_QUIET,
1077			lak_sasl_interact,
1078			user);
1079	else
1080		rc = ldap_simple_bind_s(lak->ld, user->bind_dn, user->password);
1081
1082	switch (rc) {
1083		case LDAP_SUCCESS:
1084			break;
1085        case LDAP_INVALID_CREDENTIALS:
1086        case LDAP_INSUFFICIENT_ACCESS:
1087        case LDAP_INVALID_DN_SYNTAX:
1088        case LDAP_OTHER:
1089			lak->status = LAK_NOT_BOUND;
1090            return LAK_BIND_FAIL;
1091		case LDAP_TIMEOUT:
1092		case LDAP_SERVER_DOWN:
1093		default:
1094			syslog(LOG_DEBUG|LOG_AUTH,
1095				   (lak->conf->use_sasl ? "ldap_sasl_interactive_bind() failed %d (%s)." : "ldap_simple_bind() failed %d (%s)."), rc, ldap_err2string(rc));
1096			lak->status = LAK_NOT_BOUND;
1097			return LAK_RETRY;
1098	}
1099
1100	rc = lak_user_copy(&(lak->user), user);
1101	if (rc != LAK_OK)
1102		return rc;
1103
1104	lak->status = LAK_BOUND;
1105
1106	return LAK_OK;
1107}
1108
1109static void lak_unbind(
1110	LAK *lak)
1111{
1112	if (!lak)
1113		return;
1114
1115	lak_user_free(lak->user);
1116
1117	if (lak->ld)
1118		ldap_unbind(lak->ld);
1119
1120	lak->ld = NULL;
1121	lak->user = NULL;
1122	lak->status = LAK_NOT_BOUND;
1123
1124	return;
1125}
1126
1127/*
1128 * lak_retrieve - retrieve user@realm values specified by 'attrs'
1129 */
1130int lak_retrieve(
1131	LAK *lak,
1132	const char *user,
1133	const char *service,
1134	const char *realm,
1135	const char **attrs,
1136	LAK_RESULT **ret)
1137{
1138	int rc = 0, i;
1139	char *filter = NULL;
1140	char *search_base = NULL;
1141	LDAPMessage *res = NULL;
1142	LDAPMessage *entry = NULL;
1143	BerElement *ber = NULL;
1144	char *attr = NULL, **vals = NULL, *dn = NULL;
1145	LAK_USER *lu = NULL;
1146
1147	*ret = NULL;
1148
1149	if (lak == NULL) {
1150		syslog(LOG_ERR|LOG_AUTH, "lak_init did not run.");
1151		return LAK_FAIL;
1152	}
1153
1154	if (EMPTY(user))
1155		return LAK_FAIL;
1156
1157	if (EMPTY(realm))
1158		realm = lak->conf->default_realm;
1159
1160	rc = lak_user(
1161		lak->conf->bind_dn,
1162		lak->conf->id,
1163		lak->conf->authz_id,
1164		lak->conf->mech,
1165		lak->conf->realm,
1166		lak->conf->password,
1167		&lu);
1168	if (rc != LAK_OK)
1169		return rc;
1170
1171	rc = lak_bind(lak, lu);
1172	if (rc != LAK_OK)
1173		goto done;
1174
1175	rc = lak_expand_tokens(lak->conf->filter, user, service, realm, NULL, &filter);
1176	if (rc != LAK_OK)
1177        goto done;
1178
1179	rc = lak_expand_tokens(lak->conf->search_base, user, service, realm, NULL, &search_base);
1180	if (rc != LAK_OK)
1181        goto done;
1182
1183	rc = ldap_search_st(lak->ld, search_base, lak->conf->scope, filter, (char **) attrs, 0, &(lak->conf->timeout), &res);
1184	switch (rc) {
1185		case LDAP_SUCCESS:
1186		case LDAP_NO_SUCH_OBJECT:
1187			break;
1188		case LDAP_TIMELIMIT_EXCEEDED:
1189		case LDAP_BUSY:
1190		case LDAP_UNAVAILABLE:
1191		case LDAP_INSUFFICIENT_ACCESS:
1192			/*  We do not need to re-connect to the LDAP server
1193			    under these conditions */
1194			syslog(LOG_ERR|LOG_AUTH, "user ldap_search_st() failed: %s", ldap_err2string(rc));
1195            rc = LAK_USER_NOT_FOUND;
1196			goto done;
1197		case LDAP_TIMEOUT:
1198		case LDAP_SERVER_DOWN:
1199		default:
1200			syslog(LOG_ERR|LOG_AUTH, "user ldap_search_st() failed: %s", ldap_err2string(rc));
1201            rc = LAK_RETRY;
1202			lak->status = LAK_NOT_BOUND;
1203			goto done;
1204	}
1205
1206    i = ldap_count_entries(lak->ld, res);
1207    if (i != 1) {
1208        if (i == 0)
1209			syslog(LOG_DEBUG|LOG_AUTH, "Entry not found (%s).", filter);
1210        else
1211            syslog(LOG_DEBUG|LOG_AUTH, "Duplicate entries found (%s).", filter);
1212        rc = LAK_USER_NOT_FOUND;
1213        goto done;
1214    }
1215
1216    rc = LAK_FAIL;
1217
1218	if ((entry = ldap_first_entry(lak->ld, res)) != NULL)  {
1219        for (i=0; attrs[i] != NULL; i++) {
1220
1221            if (!strcmp(attrs[i], dn_attr)) {
1222                dn = ldap_get_dn(lak->ld, entry);
1223                if (dn == NULL)
1224                    goto done;
1225
1226                rc = lak_result_add(dn_attr, dn, ret);
1227                if (rc != LAK_OK) {
1228                    lak_result_free(*ret);
1229                    *ret = NULL;
1230                    goto done;
1231                }
1232            }
1233        }
1234
1235        for (attr = ldap_first_attribute(lak->ld, entry, &ber); attr != NULL;
1236            attr = ldap_next_attribute(lak->ld, entry, ber)) {
1237
1238            vals = ldap_get_values(lak->ld, entry, attr);
1239            if (vals == NULL)
1240                continue;
1241
1242            for (i = 0; vals[i] != NULL; i++) {
1243                rc = lak_result_add(attr, vals[i], ret);
1244                if (rc != LAK_OK) {
1245                    lak_result_free(*ret);
1246                    *ret = NULL;
1247                    goto done;
1248                }
1249            }
1250
1251            ldap_value_free(vals);
1252            vals = NULL;
1253            ldap_memfree(attr);
1254            attr = NULL;
1255        }
1256    }
1257
1258done:;
1259	if (res)
1260		ldap_msgfree(res);
1261	if (dn)
1262		ldap_memfree(dn);
1263	if (vals)
1264		ldap_value_free(vals);
1265	if (attr)
1266		ldap_memfree(attr);
1267	if (ber != NULL)
1268		ber_free(ber, 0);
1269	if (filter)
1270		free(filter);
1271	if (search_base)
1272		free(search_base);
1273	if (lu)
1274		lak_user_free(lu);
1275
1276	return rc;
1277}
1278
1279static int lak_group_member(
1280	LAK *lak,
1281	const char *user,
1282	const char *service,
1283	const char *realm,
1284	const char *dn)
1285{
1286	char *group_dn = NULL, *user_dn = NULL;
1287    char *group_filter = NULL;
1288    char *group_search_base = NULL;
1289	struct berval *dn_bv = NULL;
1290	int rc;
1291    LAK_RESULT *lres = NULL;
1292    const char *attrs[] = { dn_attr, NULL };
1293    const char *group_attrs[] = {"1.1", NULL};
1294
1295	LDAPMessage *res = NULL;
1296
1297    user_dn = (char *)dn;
1298
1299    if (EMPTY(user_dn)) {
1300        if (lak->conf->use_sasl) {
1301
1302#if LDAP_VENDOR_VERSION >= 20122
1303            if (ldap_whoami_s(lak->ld, &dn_bv, NULL, NULL) != LDAP_SUCCESS || !dn_bv) {
1304                syslog(LOG_ERR|LOG_AUTH, "ldap_whoami_s() failed.");
1305                rc =  LAK_NOT_GROUP_MEMBER;
1306                goto done;
1307            }
1308
1309            user_dn = dn_bv->bv_val;
1310#else
1311            syslog(LOG_ERR|LOG_AUTH, "Your OpenLDAP API does not supported ldap_whoami().");
1312            rc =  LAK_NOT_GROUP_MEMBER;
1313            goto done;
1314#endif
1315
1316        } else {
1317
1318            rc = lak_retrieve(lak, user, service, realm, attrs, &lres);
1319            if (rc != LAK_OK)
1320                goto done;
1321
1322            user_dn = lres->value;
1323        }
1324    }
1325
1326    if (lak->conf->group_match_method == LAK_GROUP_MATCH_METHOD_ATTR) {
1327
1328            rc = lak_expand_tokens(lak->conf->group_dn, user, service, realm, NULL, &group_dn);
1329            if (rc != LAK_OK)
1330                goto done;
1331
1332            rc = ((ldap_compare_s(lak->ld, group_dn, lak->conf->group_attr, user_dn)) == LDAP_COMPARE_TRUE ?
1333                     LAK_OK : LAK_NOT_GROUP_MEMBER);
1334
1335    } else if (lak->conf->group_match_method == LAK_GROUP_MATCH_METHOD_FILTER) {
1336
1337        rc = lak_expand_tokens(lak->conf->group_filter, user, service, realm, user_dn, &group_filter);
1338        if (rc != LAK_OK)
1339            goto done;
1340
1341        rc = lak_expand_tokens(lak->conf->group_search_base, user, service, realm, user_dn, &group_search_base);
1342        if (rc != LAK_OK)
1343            goto done;
1344
1345        rc = ldap_search_st(lak->ld, group_search_base, lak->conf->group_scope, group_filter, (char **) group_attrs, 0, &(lak->conf->timeout), &res);
1346        switch (rc) {
1347            case LDAP_SUCCESS:
1348            case LDAP_NO_SUCH_OBJECT:
1349                break;
1350            case LDAP_TIMELIMIT_EXCEEDED:
1351            case LDAP_BUSY:
1352            case LDAP_UNAVAILABLE:
1353            case LDAP_INSUFFICIENT_ACCESS:
1354                syslog(LOG_ERR|LOG_AUTH, "group ldap_search_st() failed: %s", ldap_err2string(rc));
1355                rc = LAK_NOT_GROUP_MEMBER;
1356                goto done;
1357            case LDAP_TIMEOUT:
1358            case LDAP_SERVER_DOWN:
1359            default:
1360                syslog(LOG_ERR|LOG_AUTH, "group ldap_search_st() failed: %s", ldap_err2string(rc));
1361                rc = LAK_RETRY;
1362                lak->status = LAK_NOT_BOUND;
1363                goto done;
1364        }
1365
1366        rc = ( (ldap_count_entries(lak->ld, res) >= 1) ? LAK_OK : LAK_NOT_GROUP_MEMBER );
1367
1368    } else {
1369
1370            syslog(LOG_WARNING|LOG_AUTH, "Unknown ldap_group_match_method value.");
1371            rc = LAK_FAIL;
1372
1373    }
1374
1375done:;
1376	if (res)
1377		ldap_msgfree(res);
1378    if (group_dn)
1379        free(group_dn);
1380    if (group_filter)
1381        free(group_filter);
1382    if (group_search_base)
1383        free(group_search_base);
1384    if (lres)
1385        lak_result_free(lres);
1386    if (dn_bv)
1387        ber_bvfree(dn_bv);
1388
1389	return rc;
1390}
1391
1392static int lak_auth_custom(
1393	LAK *lak,
1394	const char *user,
1395	const char *service,
1396	const char *realm,
1397	const char *password)
1398{
1399	LAK_RESULT *lres;
1400	int rc;
1401	const char *attrs[] = { lak->conf->password_attr, NULL};
1402
1403	rc = lak_retrieve(lak, user, service, realm, attrs, &lres);
1404	if (rc != LAK_OK)
1405		return rc;
1406
1407    rc = lak_check_password(lres->value, password, NULL);
1408
1409	if ( rc == LAK_OK &&
1410	    (ISSET(lak->conf->group_dn) ||
1411         ISSET(lak->conf->group_filter)) )
1412        rc = lak_group_member(lak, user, service, realm, NULL);
1413
1414	lak_result_free(lres);
1415
1416	return(rc);
1417}
1418
1419static int lak_auth_bind(
1420	LAK *lak,
1421	const char *user,
1422	const char *service,
1423	const char *realm,
1424	const char *password)
1425{
1426    LAK_USER *lu = NULL;
1427	LAK_RESULT *dn = NULL;
1428	int rc;
1429	const char *attrs[] = {dn_attr, NULL};
1430
1431	rc = lak_retrieve(lak, user, service, realm, attrs, &dn);
1432	if (rc != LAK_OK)
1433		goto done;
1434
1435	rc = lak_user(
1436		dn->value,
1437		NULL,
1438		NULL,
1439		NULL,
1440		NULL,
1441		password,
1442		&lu);
1443	if (rc != LAK_OK)
1444		goto done;
1445
1446	rc = lak_bind(lak, lu);
1447
1448	if ( rc == LAK_OK &&
1449	    (ISSET(lak->conf->group_dn) ||
1450         ISSET(lak->conf->group_filter)) )
1451		rc = lak_group_member(lak, user, service, realm, dn->value);
1452
1453done:;
1454	if (lu)
1455		lak_user_free(lu);
1456	if (dn)
1457		lak_result_free(dn);
1458
1459	return rc;
1460}
1461
1462static int lak_auth_fastbind(
1463	LAK *lak,
1464	const char *user,
1465	const char *service,
1466	const char *realm,
1467	const char *password)
1468{
1469	int rc;
1470	LAK_USER *lu = NULL;
1471	char *dn = NULL;
1472	char id[LAK_BUF_LEN];
1473
1474	*id = '\0';
1475
1476	if (lak->conf->use_sasl) {
1477		strlcpy(id, user, LAK_BUF_LEN);
1478		if (!strchr(id, '@') &&
1479		    (ISSET(realm))) {
1480			strlcat(id, "@", LAK_BUF_LEN);
1481			strlcat(id, realm, LAK_BUF_LEN);
1482		}
1483	} else {
1484		rc = lak_expand_tokens(lak->conf->filter, user, service, realm, NULL, &dn);
1485		if (rc != LAK_OK ||
1486            EMPTY(dn))
1487			goto done;
1488	}
1489
1490	rc = lak_user(
1491		dn,
1492		id,
1493		NULL,
1494		lak->conf->mech,
1495		lak->conf->realm,
1496		password,
1497		&lu);
1498	if (rc != LAK_OK)
1499		goto done;
1500
1501	rc = lak_bind(lak, lu);
1502
1503	if ( rc == LAK_OK &&
1504	    (ISSET(lak->conf->group_dn) ||
1505         ISSET(lak->conf->group_filter)) )
1506            rc = lak_group_member(lak, user, service, realm, dn);
1507
1508done:;
1509	if (lu)
1510		lak_user_free(lu);
1511	if (dn != NULL)
1512		free(dn);
1513
1514	return rc;
1515}
1516
1517int lak_authenticate(
1518	LAK *lak,
1519	const char *user,
1520	const char *service,
1521	const char *realm,
1522	const char *password)
1523{
1524	int i;
1525	int rc;
1526    int retry = 2;
1527
1528	if (lak == NULL) {
1529		syslog(LOG_ERR|LOG_AUTH, "lak_init did not run.");
1530		return LAK_FAIL;
1531	}
1532
1533	if (EMPTY(user))
1534		return LAK_FAIL;
1535
1536	if (EMPTY(realm))
1537		realm = lak->conf->default_realm;
1538
1539	for (i = 0; authenticator[i].method != -1; i++) {
1540		if (authenticator[i].method == lak->conf->auth_method) {
1541			if (authenticator[i].check) {
1542                for (;retry > 0; retry--) {
1543                    rc = (authenticator[i].check)(lak, user, service, realm, password);
1544                    switch(rc) {
1545                        case LAK_OK:
1546                            return LAK_OK;
1547                        case LAK_RETRY:
1548                            if (retry > 1) {
1549                                syslog(LOG_INFO|LOG_AUTH, "Retrying authentication");
1550                                break;
1551                            }
1552                        default:
1553                            syslog(
1554                                LOG_DEBUG|LOG_AUTH,
1555                                "Authentication failed for %s%s%s: %s (%d)",
1556                                user,
1557                                (ISSET(realm) ? "/" : ""),
1558                                (ISSET(realm) ? realm : ""),
1559                                lak_error(rc),
1560                                rc);
1561                            return LAK_FAIL;
1562                    }
1563                }
1564            }
1565			break;
1566		}
1567	}
1568
1569    /* Should not get here */
1570    syslog(LOG_DEBUG|LOG_AUTH, "Authentication method not setup properly (%d)", lak->conf->auth_method);
1571
1572	return LAK_FAIL;
1573}
1574
1575char *lak_error(
1576    const int errno)
1577{
1578
1579    switch (errno) {
1580        case LAK_OK:
1581            return "Success";
1582        case LAK_FAIL:
1583            return "Generic error";
1584        case LAK_NOMEM:
1585            return "Out of memory";
1586        case LAK_RETRY:
1587            return "Retry condition (ldap server connection reset or broken)";
1588        case LAK_NOT_GROUP_MEMBER:
1589            return "Group member check failed";
1590        case LAK_INVALID_PASSWORD:
1591            return "Invalid password";
1592        case LAK_USER_NOT_FOUND:
1593            return "User not found";
1594        case LAK_BIND_FAIL:
1595            return "Bind to ldap server failed (invalid user/password or insufficient access)";
1596        case LAK_CONNECT_FAIL:
1597            return "Cannot connect to ldap server (configuration error)";
1598        default:
1599            return "Unknow error";
1600    }
1601}
1602
1603static char *lak_result_get(
1604    const LAK_RESULT *lres,
1605    const char *attr)
1606{
1607    LAK_RESULT *ptr;
1608
1609
1610    for (ptr = (LAK_RESULT *)lres; ptr != NULL; ptr = ptr->next)
1611        if (!strcasecmp(ptr->attribute, attr))
1612            return ptr->value;
1613
1614    return NULL;
1615}
1616
1617static int lak_result_add(
1618	const char *attr,
1619	const char *val,
1620	LAK_RESULT **ret)
1621{
1622	LAK_RESULT *lres;
1623
1624	lres = (LAK_RESULT *) malloc(sizeof(LAK_RESULT));
1625	if (lres == NULL) {
1626		return LAK_NOMEM;
1627	}
1628
1629	lres->next = NULL;
1630
1631	lres->attribute = strdup(attr);
1632	if (lres->attribute == NULL) {
1633		lak_result_free(lres);
1634		return LAK_NOMEM;
1635	}
1636
1637	lres->value = strdup(val);
1638	if (lres->value == NULL) {
1639		lak_result_free(lres);
1640		return LAK_NOMEM;
1641	}
1642	lres->len = strlen(lres->value);
1643
1644	lres->next = *ret;
1645
1646	*ret = lres;
1647	return LAK_OK;
1648}
1649
1650void lak_result_free(
1651	LAK_RESULT *res)
1652{
1653	LAK_RESULT *lres, *ptr = res;
1654
1655	if (ptr == NULL)
1656		return;
1657
1658	for (lres = ptr; lres != NULL; lres = ptr) {
1659
1660		ptr = lres->next;
1661
1662		if (lres->attribute != NULL) {
1663			memset(lres->attribute, 0, strlen(lres->attribute));
1664			free(lres->attribute);
1665		}
1666
1667		if (lres->value != NULL) {
1668			memset(lres->value, 0, strlen(lres->value));
1669			free(lres->value);
1670		}
1671
1672		lres->next = NULL;
1673
1674		free(lres);
1675	}
1676
1677	return;
1678}
1679
1680static int lak_check_password(
1681	const char *hash,
1682	const char *passwd,
1683	void *rock __attribute__((unused)))
1684{
1685	int i, hlen;
1686
1687	if (EMPTY(hash))
1688		return LAK_INVALID_PASSWORD;
1689
1690	if (EMPTY(passwd))
1691		return LAK_INVALID_PASSWORD;
1692
1693	for (i = 0; password_scheme[i].hash != NULL; i++) {
1694
1695		hlen = strlen(password_scheme[i].hash);
1696		if (!strncasecmp(password_scheme[i].hash, hash, hlen)) {
1697			if (password_scheme[i].check) {
1698				return (password_scheme[i].check)(hash+hlen, passwd,
1699								password_scheme[i].rock);
1700			}
1701			return LAK_FAIL;
1702		}
1703	}
1704
1705	return strcmp(hash, passwd) ? LAK_INVALID_PASSWORD : LAK_OK;
1706}
1707
1708#ifdef HAVE_OPENSSL
1709
1710static int lak_base64_decode(
1711	const char *src,
1712	char **ret,
1713	int *rlen)
1714{
1715
1716	int rc, i, tlen = 0;
1717	char *text;
1718	EVP_ENCODE_CTX EVP_ctx;
1719
1720	text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1);
1721	if (text == NULL)
1722		return LAK_NOMEM;
1723
1724	EVP_DecodeInit(&EVP_ctx);
1725	rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src));
1726	if (rc < 0) {
1727		free(text);
1728		return LAK_FAIL;
1729	}
1730	tlen += i;
1731	EVP_DecodeFinal(&EVP_ctx, text, &i);
1732
1733	*ret = text;
1734	if (rlen != NULL)
1735		*rlen = tlen;
1736
1737	return LAK_OK;
1738}
1739
1740static int lak_check_hashed(
1741	const char *hash,
1742	const char *passwd,
1743	void *rock)
1744{
1745	int rc, clen;
1746	LAK_HASH_ROCK *hrock = (LAK_HASH_ROCK *) rock;
1747	EVP_MD_CTX mdctx;
1748	const EVP_MD *md;
1749	unsigned char digest[EVP_MAX_MD_SIZE];
1750	char *cred;
1751
1752	md = EVP_get_digestbyname(hrock->mda);
1753	if (!md)
1754		return LAK_FAIL;
1755
1756	rc = lak_base64_decode(hash, &cred, &clen);
1757	if (rc != LAK_OK)
1758		return rc;
1759
1760	EVP_DigestInit(&mdctx, md);
1761	EVP_DigestUpdate(&mdctx, passwd, strlen(passwd));
1762	if (hrock->salted) {
1763		EVP_DigestUpdate(&mdctx, &cred[EVP_MD_size(md)],
1764				 clen - EVP_MD_size(md));
1765	}
1766	EVP_DigestFinal(&mdctx, digest, NULL);
1767
1768	rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md));
1769	free(cred);
1770	return rc ? LAK_INVALID_PASSWORD : LAK_OK;
1771}
1772
1773#endif /* HAVE_OPENSSL */
1774
1775static int lak_check_crypt(
1776	const char *hash,
1777	const char *passwd,
1778	void *rock __attribute__((unused)))
1779{
1780	char *cred;
1781
1782	if (strlen(hash) < 2 )
1783		return LAK_INVALID_PASSWORD;
1784
1785	cred = crypt(passwd, hash);
1786	if (EMPTY(cred))
1787		return LAK_INVALID_PASSWORD;
1788
1789	return strcmp(hash, cred) ? LAK_INVALID_PASSWORD : LAK_OK;
1790}
1791
1792#endif /* AUTH_LDAP */
1793