# With this patch you can store and use encrypted passwords in auxprop
# plugins (sql or sasldb2 for example).  Supports md5, unix crypt,
# ssha, sha1 and clear text passwords.
#
# For Debian this just have to be dropped in as debian/patches/99_auxcrypt.diff
diff -urN cyrus-sasl-2.1.19.dfsg1/lib/checkpw.c cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/checkpw.c
--- cyrus-sasl-2.1.19.dfsg1/lib/checkpw.c	2004-03-17 14:58:13.000000000 +0100
+++ cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/checkpw.c	2006-07-25 23:24:06.000000000 +0200
@@ -126,6 +126,8 @@
     return SASL_OK;
 }
 
+int lak_check_password(const char *, const char *);
+
 /* erase & dispose of a sasl_secret_t
  */
 static int auxprop_verify_password(sasl_conn_t *conn,
@@ -185,7 +187,7 @@
     if(auxprop_values[0].name
        && auxprop_values[0].values
        && auxprop_values[0].values[0]
-       && !strcmp(auxprop_values[0].values[0], passwd)) {
+       && !lak_check_password(auxprop_values[0].values[0], passwd)) {
 	/* We have a plaintext version and it matched! */
 	return SASL_OK;
     } else if(auxprop_values[1].name
diff -urN cyrus-sasl-2.1.19.dfsg1/lib/lak.c cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/lak.c
--- cyrus-sasl-2.1.19.dfsg1/lib/lak.c	1970-01-01 01:00:00.000000000 +0100
+++ cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/lak.c	2006-07-25 23:09:48.000000000 +0200
@@ -0,0 +1,212 @@
+/* COPYRIGHT
+ * Copyright (c) 2002-2003 Igor Brezac
+ * Copyright (c) 2006 Gergely Risko (simple modifications for auxprop)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY IGOR BREZAC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL IGOR BREZAC OR
+ * ITS EMPLOYEES OR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * END COPYRIGHT */
+
+#define LAK_OK 0
+#define LAK_FAIL -1
+#define LAK_NOMEM -2
+#define LAK_RETRY -3
+#define LAK_NOT_GROUP_MEMBER -4
+#define LAK_INVALID_PASSWORD -5
+#define LAK_USER_NOT_FOUND -6
+#define LAK_BIND_FAIL -7
+#define LAK_CONNECT_FAIL -8
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#ifdef HAVE_OPENSSL
+#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
+#define OPENSSL_DISABLE_OLD_DES_SUPPORT
+#endif
+#include <openssl/evp.h>
+#include <openssl/des.h>
+#endif
+
+typedef struct lak_hash_rock {
+	const char *mda;
+	int salted;
+} LAK_HASH_ROCK;
+
+typedef struct lak_password_scheme {
+	char *hash;
+	int (*check) (const char *cred, const char *passwd, void *rock);
+	void *rock;
+} LAK_PASSWORD_SCHEME;
+
+int lak_check_password(const char *, const char *);
+static int lak_check_crypt(const char *, const char *, void *);
+#ifdef HAVE_OPENSSL
+static int lak_base64_decode(const char *, char **, int *);
+static int lak_check_hashed(const char *, const char *, void *);
+#endif
+
+static LAK_HASH_ROCK hash_rock[] = {
+	{ "md5", 0 },
+	{ "md5", 1 },
+	{ "sha1", 0 },
+	{ "sha1", 1 }
+};
+
+static LAK_PASSWORD_SCHEME password_scheme[] = {
+	{ "{CRYPT}", lak_check_crypt, NULL },
+	{ "{UNIX}", lak_check_crypt, NULL },
+#ifdef HAVE_OPENSSL
+	{ "{MD5}", lak_check_hashed, &hash_rock[0] },
+	{ "{SMD5}", lak_check_hashed, &hash_rock[1] },
+	{ "{SHA}", lak_check_hashed, &hash_rock[2] },
+	{ "{SSHA}", lak_check_hashed, &hash_rock[3] },
+#endif
+	{ NULL, NULL, NULL }
+};
+
+#define EMPTY(x)  ((x == NULL) || (*(x) == '\0'))
+
+int lak_check_password(
+	const char *hash,
+	const char *passwd)
+{
+	int i, hlen;
+
+	if (EMPTY(hash))
+		return LAK_INVALID_PASSWORD;
+
+	if (EMPTY(passwd))
+		return LAK_INVALID_PASSWORD;
+
+	for (i = 0; password_scheme[i].hash != NULL; i++) {
+
+		hlen = strlen(password_scheme[i].hash);
+		if (!strncasecmp(password_scheme[i].hash, hash, hlen)) {
+			if (password_scheme[i].check) {
+				return (password_scheme[i].check)(hash+hlen, passwd,
+								password_scheme[i].rock);
+			}
+			return LAK_FAIL;
+		}
+	}
+
+	return strcmp(hash, passwd) ? LAK_INVALID_PASSWORD : LAK_OK;
+}
+
+#ifdef HAVE_OPENSSL
+
+static int lak_base64_decode(
+	const char *src,
+	char **ret,
+	int *rlen) 
+{
+
+	int rc, i, tlen = 0;
+	char *text;
+	EVP_ENCODE_CTX EVP_ctx;
+
+	text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1);
+	if (text == NULL)
+		return LAK_NOMEM;
+
+	EVP_DecodeInit(&EVP_ctx);
+	rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src));
+	if (rc < 0) {
+		free(text);
+		return LAK_FAIL;
+	}
+	tlen += i;
+	EVP_DecodeFinal(&EVP_ctx, text, &i); 
+
+	*ret = text;
+	if (rlen != NULL)
+		*rlen = tlen;
+
+	return LAK_OK;
+}
+
+static int lak_check_hashed(
+	const char *hash,
+	const char *passwd,
+	void *rock)
+{
+	int rc, clen;
+	LAK_HASH_ROCK *hrock = (LAK_HASH_ROCK *) rock;
+	EVP_MD_CTX mdctx;
+	const EVP_MD *md;
+	unsigned char digest[EVP_MAX_MD_SIZE];
+	char *cred;
+
+	md = EVP_get_digestbyname(hrock->mda);
+	if (!md) {
+	  printf("%s\n", hrock->mda);
+		return LAK_FAIL;
+	}
+	rc = lak_base64_decode(hash, &cred, &clen);
+	if (rc != LAK_OK)
+		return rc;
+
+	EVP_DigestInit(&mdctx, md);
+	EVP_DigestUpdate(&mdctx, passwd, strlen(passwd));
+	if (hrock->salted) {
+		EVP_DigestUpdate(&mdctx, &cred[EVP_MD_size(md)],
+				 clen - EVP_MD_size(md));
+	}
+	EVP_DigestFinal(&mdctx, digest, NULL);
+
+	rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md));
+	free(cred);
+	return rc ? LAK_INVALID_PASSWORD : LAK_OK;
+}
+
+#endif /* HAVE_OPENSSL */
+
+static int lak_check_crypt(
+	const char *hash,
+	const char *passwd,
+	void *rock __attribute__((unused))) 
+{
+	char *cred;
+
+	if (strlen(hash) < 2 )
+		return LAK_INVALID_PASSWORD;
+
+	cred = crypt(passwd, hash);
+	if (EMPTY(cred))
+		return LAK_INVALID_PASSWORD;
+
+	return strcmp(hash, cred) ? LAK_INVALID_PASSWORD : LAK_OK;
+}
diff -urN cyrus-sasl-2.1.19.dfsg1/lib/Makefile.am cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/Makefile.am
--- cyrus-sasl-2.1.19.dfsg1/lib/Makefile.am	2006-07-25 23:26:49.000000000 +0200
+++ cyrus-sasl-2.1.19.dfsg1.auxcrypt/lib/Makefile.am	2006-07-25 23:20:43.000000000 +0200
@@ -51,7 +51,7 @@
 libsasl2_a_SOURCES=
 
 common_headers = saslint.h
-common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c dlopen.c ../plugins/plugin_common.c
+common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c dlopen.c ../plugins/plugin_common.c lak.c
 
 LTLIBOBJS = @LTLIBOBJS@
 LIBOBJS = @LIBOBJS@
@@ -65,1 +65,1 @@
-libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR)
+libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR) $(LIBSSL_LIB_FLAGS) $(LIB_CRYPT)
diff -urN cyrus-sasl-2.1.19.dfsg1/configure.in cyrus-sasl-2.1.19.dfsg1.auxcrypt/configure.in
--- cyrus-sasl-2.1.19.dfsg1/configure.in	2006-05-18 21:06:13.000000000 +0200
+++ cyrus-sasl-2.1.19.dfsg1.auxcrypt/configure.in	2006-07-26 03:27:06.000000000 +0200
@@ -395,6 +395,8 @@
 AC_MSG_CHECKING(for OpenSSL)
 AC_MSG_RESULT($with_openssl)
 
+CMU_LIBSSL
+
 SASL_DES_CHK
 
 dnl DIGEST-MD5
