#! /bin/sh /usr/share/dpatch/dpatch-run ## 0099_auxcrypt.dpatch by ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: With this patch you can store and use encrypted passwords in auxprop ## DP: plugins (sql or sasldb2 for example). Supports md5, unix crypt, ## DP: ssha, sha1 and clear text passwords. ## ## For Debian this just have to be dropped in as debian/patches/0099_auxcrypt.dpatch @DPATCH@ diff -ruN orig/configure.in auxcrypt/configure.in --- orig/configure.in 2007-07-13 19:24:37.000000000 +0200 +++ auxcrypt/configure.in 2007-07-13 19:31:00.000000000 +0200 @@ -397,6 +397,8 @@ AC_MSG_CHECKING(for OpenSSL) AC_MSG_RESULT($with_openssl) +CMU_LIBSSL + SASL_DES_CHK dnl DIGEST-MD5 diff -ruN orig/lib/checkpw.c auxcrypt/lib/checkpw.c --- orig/lib/checkpw.c 2007-07-13 19:24:37.000000000 +0200 +++ auxcrypt/lib/checkpw.c 2007-07-12 22:02:20.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 -ruN orig/lib/lak.c auxcrypt/lib/lak.c --- orig/lib/lak.c 1970-01-01 01:00:00.000000000 +0100 +++ auxcrypt/lib/lak.c 2007-07-13 19:23:00.000000000 +0200 @@ -0,0 +1,203 @@ +/* COPYRIGHT + * Copyright (c) 2002-2003 Igor Brezac + * Copyright (c) 2006-2007 Gergely Risko (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_INVALID_PASSWORD -5 + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_CRYPT_H +#include +#endif + +#ifdef HAVE_OPENSSL +#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT +#define OPENSSL_DISABLE_OLD_DES_SUPPORT +#endif +#include +#include +#endif + +typedef struct lak_hash_rock { + const EVP_MD* (*mda) (void); + 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 *, unsigned char **, int *); +static int lak_check_hashed(const char *, const char *, void *); +#endif + +static LAK_HASH_ROCK hash_rock[] = { + { EVP_md5, 0 }, + { EVP_md5, 1 }, + { EVP_sha1, 0 }, + { EVP_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, + unsigned char **ret, + int *rlen) +{ + + int rc, i, tlen = 0; + unsigned char *text; + EVP_ENCODE_CTX EVP_ctx; + + text = (unsigned 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, (unsigned 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]; + unsigned char *cred; + + md = (hrock->mda)(); + 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 -ruN orig/lib/Makefile.am auxcrypt/lib/Makefile.am --- orig/lib/Makefile.am 2007-07-13 19:24:37.000000000 +0200 +++ auxcrypt/lib/Makefile.am 2007-07-12 22:02:20.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@ @@ -62,7 +62,7 @@ libsasl2_la_SOURCES = $(common_sources) $(common_headers) libsasl2_la_LDFLAGS = -version-info $(sasl_version) -Wl,--version-script=Versions libsasl2_la_DEPENDENCIES = $(LTLIBOBJS) Versions -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) if MACOSX framedir = /Library/Frameworks/SASL2.framework