2 * Copyright (c) 2002-2003 Igor Brezac
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include "mechanisms.h"
51 #ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
52 #define OPENSSL_DISABLE_OLD_DES_SUPPORT
54 #include <openssl/evp.h>
55 #include <openssl/des.h>
63 typedef struct lak_auth_method {
65 int (*check) (LAK *lak, const char *user, const char *service, const char *realm, const char *password) ;
68 typedef struct lak_hash_rock {
73 typedef struct lak_password_scheme {
75 int (*check) (const char *cred, const char *passwd, void *rock);
77 } LAK_PASSWORD_SCHEME;
79 static int lak_config_read(LAK_CONF *, const char *);
80 static int lak_config_int(const char *);
81 static int lak_config_switch(const char *);
82 static void lak_config_free(LAK_CONF *);
83 static int lak_config(const char *, LAK_CONF **);
84 static int lak_escape(const char *, const unsigned int, char **);
85 static int lak_tokenize_domains(const char *, int, char **);
86 static int lak_expand_tokens(const char *, const char *, const char *, const char *, const char *, char **);
87 static int lak_connect(LAK *);
88 static int lak_bind(LAK *, LAK_USER *);
89 static void lak_unbind(LAK *);
90 static int lak_auth_custom(LAK *, const char *, const char *, const char *, const char *);
91 static int lak_auth_bind(LAK *, const char *, const char *, const char *, const char *);
92 static int lak_auth_fastbind(LAK *, const char *, const char *, const char *, const char *);
93 static int lak_group_member(LAK *, const char *, const char *, const char *, const char *);
94 static char *lak_result_get(const LAK_RESULT *, const char *);
95 static int lak_result_add(const char *, const char *, LAK_RESULT **);
96 static int lak_check_password(const char *, const char *, void *);
97 static int lak_check_crypt(const char *, const char *, void *);
99 static int lak_base64_decode(const char *, char **, int *);
100 static int lak_check_hashed(const char *, const char *, void *);
102 static int lak_sasl_interact(LDAP *, unsigned, void *, void *);
103 static int lak_user(const char *, const char *, const char *, const char *, const char *, const char *, LAK_USER **);
104 static int lak_user_copy(LAK_USER **, const LAK_USER *);
105 static int lak_user_cmp(const LAK_USER *, const LAK_USER *);
106 static void lak_user_free(LAK_USER *);
108 static 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 },
115 static LAK_HASH_ROCK hash_rock[] = {
122 static LAK_PASSWORD_SCHEME password_scheme[] = {
123 { "{CRYPT}", lak_check_crypt, NULL },
124 { "{UNIX}", lak_check_crypt, NULL },
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] },
134 static const char *dn_attr = "dn";
136 #define ISSET(x) ((x != NULL) && (*(x) != '\0'))
137 #define EMPTY(x) ((x == NULL) || (*(x) == '\0'))
139 static int lak_config_read(
141 const char *configfile)
148 infile = fopen(configfile, "r");
150 syslog(LOG_ERR|LOG_AUTH,
151 "Could not open saslauthd config file: %s (%m)",
156 while (fgets(buf, sizeof(buf), infile)) {
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 == '#')
166 while (*p && (isalnum((int) *p) || *p == '-' || *p == '_')) {
167 if (isupper((int) *p))
176 while (*p && isspace((int) *p))
182 if (!strcasecmp(key, "ldap_servers"))
183 strlcpy(conf->servers, p, LAK_URL_LEN);
185 else if (!strcasecmp(key, "ldap_bind_dn"))
186 strlcpy(conf->bind_dn, p, LAK_DN_LEN);
188 else if (!strcasecmp(key, "ldap_bind_pw") ||
189 !strcasecmp(key, "ldap_password"))
190 strlcpy(conf->password, p, LAK_BUF_LEN);
192 else if (!strcasecmp(key, "ldap_version"))
193 conf->version = lak_config_int(p);
195 else if (!strcasecmp(key, "ldap_search_base"))
196 strlcpy(conf->search_base, p, LAK_DN_LEN);
198 else if (!strcasecmp(key, "ldap_filter"))
199 strlcpy(conf->filter, p, LAK_DN_LEN);
201 else if (!strcasecmp(key, "ldap_password_attr"))
202 strlcpy(conf->password_attr, p, LAK_BUF_LEN);
204 else if (!strcasecmp(key, "ldap_group_dn"))
205 strlcpy(conf->group_dn, p, LAK_DN_LEN);
207 else if (!strcasecmp(key, "ldap_group_attr"))
208 strlcpy(conf->group_attr, p, LAK_BUF_LEN);
210 else if (!strcasecmp(key, "ldap_group_filter"))
211 strlcpy(conf->group_filter, p, LAK_BUF_LEN);
213 else if (!strcasecmp(key, "ldap_group_search_base"))
214 strlcpy(conf->group_search_base, p, LAK_BUF_LEN);
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;
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;
228 } else if (!strcasecmp(key, "ldap_default_realm") ||
229 !strcasecmp(key, "ldap_default_domain"))
230 strlcpy(conf->default_realm, p, LAK_BUF_LEN);
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;
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);
244 else if (!strcasecmp(key, "ldap_time_limit"))
245 conf->time_limit = lak_config_int(p);
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;
257 } else if (!strcasecmp(key, "ldap_referrals")) {
258 conf->referrals = lak_config_switch(p);
260 } else if (!strcasecmp(key, "ldap_restart")) {
261 conf->restart = lak_config_switch(p);
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;
269 } else if (!strcasecmp(key, "ldap_use_sasl")) {
270 conf->use_sasl = lak_config_switch(p);
272 } else if (!strcasecmp(key, "ldap_id") ||
273 !strcasecmp(key, "ldap_sasl_authc_id"))
274 strlcpy(conf->id, p, LAK_BUF_LEN);
276 else if (!strcasecmp(key, "ldap_authz_id") ||
277 !strcasecmp(key, "ldap_sasl_authz_id"))
278 strlcpy(conf->authz_id, p, LAK_BUF_LEN);
280 else if (!strcasecmp(key, "ldap_realm") ||
281 !strcasecmp(key, "ldap_sasl_realm"))
282 strlcpy(conf->realm, p, LAK_BUF_LEN);
284 else if (!strcasecmp(key, "ldap_mech") ||
285 !strcasecmp(key, "ldap_sasl_mech"))
286 strlcpy(conf->mech, p, LAK_BUF_LEN);
288 else if (!strcasecmp(key, "ldap_sasl_secprops"))
289 strlcpy(conf->sasl_secprops, p, LAK_BUF_LEN);
291 else if (!strcasecmp(key, "ldap_start_tls"))
292 conf->start_tls = lak_config_switch(p);
294 else if (!strcasecmp(key, "ldap_tls_check_peer"))
295 conf->tls_check_peer = lak_config_switch(p);
297 else if (!strcasecmp(key, "ldap_tls_cacert_file"))
298 strlcpy(conf->tls_cacert_file, p, LAK_PATH_LEN);
300 else if (!strcasecmp(key, "ldap_tls_cacert_dir"))
301 strlcpy(conf->tls_cacert_dir, p, LAK_PATH_LEN);
303 else if (!strcasecmp(key, "ldap_tls_ciphers"))
304 strlcpy(conf->tls_ciphers, p, LAK_BUF_LEN);
306 else if (!strcasecmp(key, "ldap_tls_cert"))
307 strlcpy(conf->tls_cert, p, LAK_PATH_LEN);
309 else if (!strcasecmp(key, "ldap_tls_key"))
310 strlcpy(conf->tls_key, p, LAK_PATH_LEN);
312 else if (!strcasecmp(key, "ldap_debug"))
313 conf->debug = lak_config_int(p);
316 if (conf->version != LDAP_VERSION3 &&
319 conf->version = LDAP_VERSION3;
321 if (conf->use_sasl &&
322 conf->auth_method == LAK_AUTH_METHOD_BIND)
323 conf->auth_method = LAK_AUTH_METHOD_FASTBIND;
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);
335 static int lak_config_int(
340 if (!isdigit((int) *val) && (*val != '-' || !isdigit((int) val[1]))) return 0;
345 static int lak_config_switch(
350 if (*val == '0' || *val == 'n' ||
351 (*val == 'o' && val[1] == 'f') || *val == 'f') {
353 } else if (*val == '1' || *val == 'y' ||
354 (*val == 'o' && val[1] == 'n') || *val == 't') {
360 static int lak_config(
361 const char *configfile,
367 conf = malloc( sizeof(LAK_CONF) );
372 memset(conf, 0, sizeof(LAK_CONF));
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;
392 strlcpy(conf->path, configfile, LAK_PATH_LEN);
394 rc = lak_config_read(conf, conf->path);
396 lak_config_free(conf);
404 static void lak_config_free(
411 memset(conf, 0, sizeof(LAK_CONF));
419 * Note: calling function must free memory.
421 static int lak_escape(
423 const unsigned int n,
427 char *end, *ptr, *temp;
429 if (n > strlen(s)) // Sanity check, just in case
432 buf = malloc(n * 5 + 1);
441 while (((temp = strpbrk(ptr, "*()\\\0"))!=NULL) && (temp<end)) {
444 strncat(buf, ptr, temp-ptr);
466 strncat(buf, ptr, end-ptr);
473 static int lak_tokenize_domains(
484 if (d == NULL || n < 1 || n > 9)
491 for( nt=0, s1=s; *s1; s1++ )
492 if( *s1 == '.' ) nt++;
501 s1 = (char *)strtok_r(s, ".", &lasts);
504 rc = lak_escape(s1, strlen(s1), result);
508 s1 = (char *)strtok_r(NULL, ".", &lasts);
516 #define LAK_MAX(a,b) (a>b?a:b)
520 * Parts with the strings provided.
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)
529 * %R = prepend '@' to realm
531 * Note: calling function must free memory.
533 static int lak_expand_tokens(
535 const char *username,
542 char *end, *ptr, *temp;
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;
551 if (pattern == NULL) {
552 syslog(LOG_ERR|LOG_AUTH, "filter pattern not setup");
556 /* find the longest param of username and realm,
557 do not worry about domain because it is always shorter
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;
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);
568 /* find the number of occurences of percent sign in filter */
569 for( percents=0, buf=(char *)pattern; *buf; buf++ ) {
570 if( *buf == '%' ) percents++;
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);
580 ptr = (char *)pattern;
581 end = ptr + strlen(ptr);
583 while ((temp=strchr(ptr,'%'))!=NULL ) {
586 strncat(buf, ptr, temp-ptr);
588 if ((temp+1) >= end) {
589 syslog(LOG_DEBUG|LOG_AUTH, "Incomplete lookup substitution format");
595 strncat(buf,temp+1,1);
598 if (ISSET(username)) {
599 rc=lak_escape(username, strlen(username), &ebuf);
605 syslog(LOG_DEBUG|LOG_AUTH, "Username not available.");
608 if (ISSET(username)) {
609 user = strchr(username, '@');
610 rc=lak_escape(username, (user ? user - username : strlen(username)), &ebuf);
616 syslog(LOG_DEBUG|LOG_AUTH, "Username not available.");
627 if (ISSET(username) &&
628 ((domain = strchr(username, '@')) && domain[1]!='\0')) {
629 rc=lak_tokenize_domains(domain+1, (int) *(temp+1)-48, &ebuf);
634 } else if (ISSET(realm)) {
635 rc=lak_tokenize_domains(realm, (int) *(temp+1)-48, &ebuf);
641 syslog(LOG_DEBUG|LOG_AUTH, "Domain/Realm not available.");
644 if (ISSET(username) &&
645 ((domain = strchr(username, '@')) && domain[1]!='\0')) {
646 rc=lak_escape(domain+1, strlen(domain+1), &ebuf);
656 rc = lak_escape(realm, strlen(realm), &ebuf);
658 if (*(temp+1) == 'R')
664 syslog(LOG_DEBUG|LOG_AUTH, "Domain/Realm not available.");
667 if (ISSET(service)) {
668 rc = lak_escape(service, strlen(service), &ebuf);
674 syslog(LOG_DEBUG|LOG_AUTH, "Service not available.");
678 rc = lak_escape(dn, strlen(dn), &ebuf);
684 syslog(LOG_DEBUG|LOG_AUTH, "User DN not available.");
700 const char *configfile,
712 lak = (LAK *)malloc(sizeof(LAK));
716 lak->status=LAK_NOT_BOUND;
721 rc = lak_config(configfile, &lak->conf);
728 OpenSSL_add_all_digests();
742 lak_config_free(lak->conf);
755 static int lak_connect(
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));
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));
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));
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));
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));
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));
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;
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);
816 rc = ldap_set_option(lak->ld, LDAP_OPT_PROTOCOL_VERSION, &(lak->conf->version));
817 if (rc != LDAP_OPT_SUCCESS) {
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);
823 return LAK_CONNECT_FAIL;
825 syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_PROTOCOL_VERSION %d.", lak->conf->version);
827 lak->conf->version = LDAP_VERSION2;
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);
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);
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);
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.");
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);
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.");
860 if (lak->conf->start_tls) {
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));
866 return LAK_CONNECT_FAIL;
870 if (lak->conf->use_sasl) {
872 if (EMPTY(lak->conf->mech)) {
873 ldap_get_option(lak->ld, LDAP_OPT_X_SASL_MECH, &p);
875 strlcpy(lak->conf->mech, p, LAK_BUF_LEN);
878 if (EMPTY(lak->conf->realm)) {
879 ldap_get_option(lak->ld, LDAP_OPT_X_SASL_REALM, &p);
881 strlcpy(lak->conf->realm, p, LAK_BUF_LEN);
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.");
889 return LAK_CONNECT_FAIL;
901 const char *authz_id,
904 const char *password,
911 lu = (LAK_USER *)malloc(sizeof(LAK_USER));
915 memset(lu, 0, sizeof(LAK_USER));
918 strlcpy(lu->bind_dn, bind_dn, LAK_DN_LEN);
921 strlcpy(lu->id, id, LAK_BUF_LEN);
924 strlcpy(lu->authz_id, authz_id, LAK_BUF_LEN);
927 strlcpy(lu->mech, mech, LAK_BUF_LEN);
930 strlcpy(lu->realm, realm, LAK_BUF_LEN);
933 strlcpy(lu->password, password, LAK_BUF_LEN);
939 static int lak_user_cmp(
948 if (memcmp(lu1, lu2, sizeof(LAK_USER)) == 0)
954 static int lak_user_copy(
966 lu = (LAK_USER *)malloc(sizeof(LAK_USER));
973 memcpy((void *)lu, (void *)lu2, sizeof(LAK_USER));
978 static void lak_user_free(
985 memset(user, 0, sizeof(LAK_USER));
992 static int lak_sasl_interact(
994 unsigned flags __attribute__((unused)),
998 sasl_interact_t *in = inter;
1002 for (;in->id != SASL_CB_LIST_END;in++) {
1005 case SASL_CB_AUTHNAME:
1009 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &p);
1012 if (ISSET(lu->authz_id))
1015 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &p);
1017 case SASL_CB_GETREALM:
1018 if (ISSET(lu->realm))
1022 if (ISSET(lu->password))
1027 in->result = ISSET(p) ? p : "";
1028 in->len = strlen(in->result);
1031 return LDAP_SUCCESS;
1034 static int lak_bind(
1040 if (user == NULL) // Sanity Check
1043 if ((lak->status == LAK_BOUND) &&
1044 (lak_user_cmp(lak->user, user) == LAK_OK))
1047 lak_user_free(lak->user);
1051 #if LDAP_VENDOR_VERSION < 20204
1052 lak->conf->use_sasl ||
1054 lak->conf->version == LDAP_VERSION2)
1055 lak->status = LAK_NOT_BOUND;
1057 if (lak->status == LAK_NOT_BOUND) {
1059 rc = lak_connect(lak);
1064 if (lak->conf->use_sasl)
1065 rc = ldap_sasl_interactive_bind_s(
1075 rc = ldap_simple_bind_s(lak->ld, user->bind_dn, user->password);
1080 case LDAP_INVALID_CREDENTIALS:
1081 case LDAP_INSUFFICIENT_ACCESS:
1082 case LDAP_INVALID_DN_SYNTAX:
1084 lak->status = LAK_NOT_BOUND;
1085 return LAK_BIND_FAIL;
1087 case LDAP_SERVER_DOWN:
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;
1095 rc = lak_user_copy(&(lak->user), user);
1099 lak->status = LAK_BOUND;
1104 static void lak_unbind(
1110 lak_user_free(lak->user);
1113 ldap_unbind(lak->ld);
1117 lak->status = LAK_NOT_BOUND;
1123 * lak_retrieve - retrieve user@realm values specified by 'attrs'
1128 const char *service,
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;
1145 syslog(LOG_ERR|LOG_AUTH, "lak_init did not run.");
1153 realm = lak->conf->default_realm;
1158 lak->conf->authz_id,
1161 lak->conf->password,
1166 rc = lak_bind(lak, lu);
1170 rc = lak_expand_tokens(lak->conf->filter, user, service, realm, NULL, &filter);
1174 rc = lak_expand_tokens(lak->conf->search_base, user, service, realm, NULL, &search_base);
1178 rc = ldap_search_st(lak->ld, search_base, lak->conf->scope, filter, (char **) attrs, 0, &(lak->conf->timeout), &res);
1181 case LDAP_NO_SUCH_OBJECT:
1183 case LDAP_TIMELIMIT_EXCEEDED:
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;
1193 case LDAP_SERVER_DOWN:
1195 syslog(LOG_ERR|LOG_AUTH, "user ldap_search_st() failed: %s", ldap_err2string(rc));
1197 lak->status = LAK_NOT_BOUND;
1201 i = ldap_count_entries(lak->ld, res);
1204 syslog(LOG_DEBUG|LOG_AUTH, "Entry not found (%s).", filter);
1206 syslog(LOG_DEBUG|LOG_AUTH, "Duplicate entries found (%s).", filter);
1207 rc = LAK_USER_NOT_FOUND;
1213 if ((entry = ldap_first_entry(lak->ld, res)) != NULL) {
1214 for (i=0; attrs[i] != NULL; i++) {
1216 if (!strcmp(attrs[i], dn_attr)) {
1217 dn = ldap_get_dn(lak->ld, entry);
1221 rc = lak_result_add(dn_attr, dn, ret);
1223 lak_result_free(*ret);
1230 for (attr = ldap_first_attribute(lak->ld, entry, &ber); attr != NULL;
1231 attr = ldap_next_attribute(lak->ld, entry, ber)) {
1233 vals = ldap_get_values(lak->ld, entry, attr);
1237 for (i = 0; vals[i] != NULL; i++) {
1238 rc = lak_result_add(attr, vals[i], ret);
1240 lak_result_free(*ret);
1246 ldap_value_free(vals);
1259 ldap_value_free(vals);
1274 static int lak_group_member(
1277 const char *service,
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;
1286 LAK_RESULT *lres = NULL;
1287 const char *attrs[] = { dn_attr, NULL };
1288 const char *group_attrs[] = {"1.1", NULL};
1290 LDAPMessage *res = NULL;
1292 user_dn = (char *)dn;
1294 if (EMPTY(user_dn)) {
1295 if (lak->conf->use_sasl) {
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;
1304 user_dn = dn_bv->bv_val;
1306 syslog(LOG_ERR|LOG_AUTH, "Your OpenLDAP API does not supported ldap_whoami().");
1307 rc = LAK_NOT_GROUP_MEMBER;
1313 rc = lak_retrieve(lak, user, service, realm, attrs, &lres);
1317 user_dn = lres->value;
1321 if (lak->conf->group_match_method == LAK_GROUP_MATCH_METHOD_ATTR) {
1323 rc = lak_expand_tokens(lak->conf->group_dn, user, service, realm, NULL, &group_dn);
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);
1330 } else if (lak->conf->group_match_method == LAK_GROUP_MATCH_METHOD_FILTER) {
1332 rc = lak_expand_tokens(lak->conf->group_filter, user, service, realm, user_dn, &group_filter);
1336 rc = lak_expand_tokens(lak->conf->group_search_base, user, service, realm, user_dn, &group_search_base);
1340 rc = ldap_search_st(lak->ld, group_search_base, lak->conf->group_scope, group_filter, (char **) group_attrs, 0, &(lak->conf->timeout), &res);
1343 case LDAP_NO_SUCH_OBJECT:
1345 case LDAP_TIMELIMIT_EXCEEDED:
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;
1353 case LDAP_SERVER_DOWN:
1355 syslog(LOG_ERR|LOG_AUTH, "group ldap_search_st() failed: %s", ldap_err2string(rc));
1357 lak->status = LAK_NOT_BOUND;
1361 rc = ( (ldap_count_entries(lak->ld, res) >= 1) ? LAK_OK : LAK_NOT_GROUP_MEMBER );
1365 syslog(LOG_WARNING|LOG_AUTH, "Unknown ldap_group_match_method value.");
1377 if (group_search_base)
1378 free(group_search_base);
1380 lak_result_free(lres);
1387 static int lak_auth_custom(
1390 const char *service,
1392 const char *password)
1396 const char *attrs[] = { lak->conf->password_attr, NULL};
1398 rc = lak_retrieve(lak, user, service, realm, attrs, &lres);
1402 rc = lak_check_password(lres->value, password, NULL);
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);
1409 lak_result_free(lres);
1414 static int lak_auth_bind(
1417 const char *service,
1419 const char *password)
1421 LAK_USER *lu = NULL;
1422 LAK_RESULT *dn = NULL;
1424 const char *attrs[] = {dn_attr, NULL};
1426 rc = lak_retrieve(lak, user, service, realm, attrs, &dn);
1441 rc = lak_bind(lak, lu);
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);
1452 lak_result_free(dn);
1457 static int lak_auth_fastbind(
1460 const char *service,
1462 const char *password)
1465 LAK_USER *lu = NULL;
1467 char id[LAK_BUF_LEN];
1471 if (lak->conf->use_sasl) {
1472 strlcpy(id, user, LAK_BUF_LEN);
1473 if (!strchr(id, '@') &&
1475 strlcat(id, "@", LAK_BUF_LEN);
1476 strlcat(id, realm, LAK_BUF_LEN);
1479 rc = lak_expand_tokens(lak->conf->filter, user, service, realm, NULL, &dn);
1496 rc = lak_bind(lak, lu);
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);
1512 int lak_authenticate(
1515 const char *service,
1517 const char *password)
1524 syslog(LOG_ERR|LOG_AUTH, "lak_init did not run.");
1532 realm = lak->conf->default_realm;
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);
1544 syslog(LOG_INFO|LOG_AUTH, "Retrying authentication");
1550 "Authentication failed for %s%s%s: %s (%d)",
1552 (ISSET(realm) ? "/" : ""),
1553 (ISSET(realm) ? realm : ""),
1564 /* Should not get here */
1565 syslog(LOG_DEBUG|LOG_AUTH, "Authentication method not setup properly (%d)", lak->conf->auth_method);
1578 return "Generic error";
1580 return "Out of memory";
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";
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)";
1594 return "Unknow error";
1598 static char *lak_result_get(
1599 const LAK_RESULT *lres,
1605 for (ptr = (LAK_RESULT *)lres; ptr != NULL; ptr = ptr->next)
1606 if (!strcasecmp(ptr->attribute, attr))
1612 static int lak_result_add(
1619 lres = (LAK_RESULT *) malloc(sizeof(LAK_RESULT));
1626 lres->attribute = strdup(attr);
1627 if (lres->attribute == NULL) {
1628 lak_result_free(lres);
1632 lres->value = strdup(val);
1633 if (lres->value == NULL) {
1634 lak_result_free(lres);
1637 lres->len = strlen(lres->value);
1645 void lak_result_free(
1648 LAK_RESULT *lres, *ptr = res;
1653 for (lres = ptr; lres != NULL; lres = ptr) {
1657 if (lres->attribute != NULL) {
1658 memset(lres->attribute, 0, strlen(lres->attribute));
1659 free(lres->attribute);
1662 if (lres->value != NULL) {
1663 memset(lres->value, 0, strlen(lres->value));
1675 static int lak_check_password(
1678 void *rock __attribute__((unused)))
1683 return LAK_INVALID_PASSWORD;
1686 return LAK_INVALID_PASSWORD;
1688 for (i = 0; password_scheme[i].hash != NULL; i++) {
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);
1700 return strcmp(hash, passwd) ? LAK_INVALID_PASSWORD : LAK_OK;
1705 static int lak_base64_decode(
1711 int rc, i, tlen = 0;
1713 EVP_ENCODE_CTX EVP_ctx;
1715 text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1);
1719 EVP_DecodeInit(&EVP_ctx);
1720 rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src));
1726 EVP_DecodeFinal(&EVP_ctx, text, &i);
1735 static int lak_check_hashed(
1741 LAK_HASH_ROCK *hrock = (LAK_HASH_ROCK *) rock;
1744 unsigned char digest[EVP_MAX_MD_SIZE];
1747 md = EVP_get_digestbyname(hrock->mda);
1751 rc = lak_base64_decode(hash, &cred, &clen);
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));
1761 EVP_DigestFinal(&mdctx, digest, NULL);
1763 rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md));
1765 return rc ? LAK_INVALID_PASSWORD : LAK_OK;
1768 #endif /* HAVE_OPENSSL */
1770 static int lak_check_crypt(
1773 void *rock __attribute__((unused)))
1777 if (strlen(hash) < 2 )
1778 return LAK_INVALID_PASSWORD;
1780 cred = crypt(passwd, hash);
1782 return LAK_INVALID_PASSWORD;
1784 return strcmp(hash, cred) ? LAK_INVALID_PASSWORD : LAK_OK;
1787 #endif /* AUTH_LDAP */