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