diff --git a/.cyrus-sasl.metadata b/.cyrus-sasl.metadata
new file mode 100644
index 0000000..82b591b
--- /dev/null
+++ b/.cyrus-sasl.metadata
@@ -0,0 +1 @@
+c9e6848d9cc6f9588e0e7a75423f9a3aed3f10db SOURCES/cyrus-sasl-2.1.27-nodlcompatorsrp.tar.gz
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07c8f97
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/cyrus-sasl-2.1.27-nodlcompatorsrp.tar.gz
diff --git a/SOURCES/0001-CVE-2022-24407-Escape-password-for-SQL-insert-update.patch b/SOURCES/0001-CVE-2022-24407-Escape-password-for-SQL-insert-update.patch
new file mode 100644
index 0000000..a430d65
--- /dev/null
+++ b/SOURCES/0001-CVE-2022-24407-Escape-password-for-SQL-insert-update.patch
@@ -0,0 +1,82 @@
+From 37f2e0f0658d78a1496dc277f402f8b577ce6aae Mon Sep 17 00:00:00 2001
+From: Klaus Espenlaub <klaus@espenlaub.com>
+Date: Tue, 8 Feb 2022 20:34:40 +0000
+Subject: [PATCH] CVE-2022-24407 Escape password for SQL insert/update
+ commands.
+
+Signed-off-by: Klaus Espenlaub <klaus@espenlaub.com>
+---
+ plugins/sql.c | 26 +++++++++++++++++++++++---
+ 1 file changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/plugins/sql.c b/plugins/sql.c
+index 31b54a78..6ac81c2f 100644
+--- a/plugins/sql.c
++++ b/plugins/sql.c
+@@ -1151,6 +1151,7 @@ static int sql_auxprop_store(void *glob_context,
+     char *statement = NULL;
+     char *escap_userid = NULL;
+     char *escap_realm = NULL;
++    char *escap_passwd = NULL;
+     const char *cmd;
+     
+     sql_settings_t *settings;
+@@ -1222,6 +1223,11 @@ static int sql_auxprop_store(void *glob_context,
+ 			    "Unable to begin transaction\n");
+     }
+     for (cur = to_store; ret == SASL_OK && cur->name; cur++) {
++	/* Free the buffer, current content is from previous loop. */
++	if (escap_passwd) {
++	    sparams->utils->free(escap_passwd);
++	    escap_passwd = NULL;
++	}
+ 
+ 	if (cur->name[0] == '*') {
+ 	    continue;
+@@ -1243,19 +1249,32 @@ static int sql_auxprop_store(void *glob_context,
+ 	}
+ 	sparams->utils->free(statement);
+ 
++	if (cur->values[0]) {
++	    escap_passwd = (char *)sparams->utils->malloc(strlen(cur->values[0])*2+1);
++	    if (!escap_passwd) {
++		ret = SASL_NOMEM;
++		break;
++	    }
++	    settings->sql_engine->sql_escape_str(escap_passwd, cur->values[0]);
++	}
++
+ 	/* create a statement that we will use */
+ 	statement = sql_create_statement(cmd, cur->name, escap_userid,
+ 					 escap_realm,
+-					 cur->values && cur->values[0] ?
+-					 cur->values[0] : SQL_NULL_VALUE,
++					 escap_passwd ?
++					 escap_passwd : SQL_NULL_VALUE,
+ 					 sparams->utils);
++	if (!statement) {
++	    ret = SASL_NOMEM;
++	    break;
++	}
+ 	
+ 	{
+ 	    char *log_statement =
+ 		sql_create_statement(cmd, cur->name,
+ 				     escap_userid,
+ 				     escap_realm,
+-				     cur->values && cur->values[0] ?
++				     escap_passwd ?
+ 				     "<omitted>" : SQL_NULL_VALUE,
+ 				     sparams->utils);
+ 	    sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
+@@ -1288,6 +1307,7 @@ static int sql_auxprop_store(void *glob_context,
+   done:
+     if (escap_userid) sparams->utils->free(escap_userid);
+     if (escap_realm) sparams->utils->free(escap_realm);
++    if (escap_passwd) sparams->utils->free(escap_passwd);
+     if (conn) settings->sql_engine->sql_close(conn);
+     if (userid) sparams->utils->free(userid);
+     if (realm) sparams->utils->free(realm);
+-- 
+2.25.1
+
diff --git a/SOURCES/autogen.sh b/SOURCES/autogen.sh
new file mode 100644
index 0000000..38e3be2
--- /dev/null
+++ b/SOURCES/autogen.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+
+olddir=`pwd`
+
+cd $srcdir
+
+(test -f configure.ac) || {
+	echo "*** ERROR: Directory "\`$srcdir\'" does not look like the top-level project directory ***"
+	exit 1
+}
+
+PKG_NAME=`autoconf --trace 'AC_INIT:$1' configure.ac`
+
+if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then
+	echo "*** WARNING: I am going to run \`configure' with no arguments." >&2
+	echo "*** If you wish to pass any to it, please specify them on the" >&2
+	echo "*** \`$0\' command line." >&2
+	echo "" >&2
+fi
+
+aclocal --install || exit 1
+autoreconf --verbose --force --install -Wno-portability || exit 1
+
+cd $olddir
+if [ "$NOCONFIGURE" = "" ]; then
+	$srcdir/configure "$@" || exit 1
+
+	if [ "$1" = "--help" ]; then exit 0 else
+		echo "Now type \`make\' to compile $PKG_NAME" || exit 1
+	fi
+else
+	echo "Skipping configure process."
+fi
+
diff --git a/SOURCES/cyrus-sasl-2.1.20-saslauthd.conf-path.patch b/SOURCES/cyrus-sasl-2.1.20-saslauthd.conf-path.patch
new file mode 100644
index 0000000..1e414ff
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.20-saslauthd.conf-path.patch
@@ -0,0 +1,26 @@
+diff -up cyrus-sasl-2.1.27/saslauthd/saslauthd.mdoc.path cyrus-sasl-2.1.27/saslauthd/saslauthd.mdoc
+--- cyrus-sasl-2.1.27/saslauthd/saslauthd.mdoc.path	2015-10-15 15:44:43.000000000 +0200
++++ cyrus-sasl-2.1.27/saslauthd/saslauthd.mdoc	2015-11-20 15:05:30.421377527 +0100
+@@ -221,7 +221,7 @@ instead.
+ .Em (All platforms that support OpenLDAP 2.0 or higher)
+ .Pp
+ Authenticate against an ldap server.  The ldap configuration parameters are
+-read from /usr/local/etc/saslauthd.conf.  The location of this file can be
++read from /etc/saslauthd.conf.  The location of this file can be
+ changed with the -O parameter. See the LDAP_SASLAUTHD file included with the
+ distribution for the list of available parameters.
+ .It Li sia
+@@ -251,10 +251,10 @@ these ticket files can cause serious per
+ servers. (Kerberos
+ was never intended to be used in this manner, anyway.)
+ .Sh FILES
+-.Bl -tag -width "/var/run/saslauthd/mux"
+-.It Pa /var/run/saslauthd/mux
++.Bl -tag -width "/run/saslauthd/mux"
++.It Pa /run/saslauthd/mux
+ The default communications socket.
+-.It Pa /usr/local/etc/saslauthd.conf
++.It Pa /etc/saslauthd.conf
+ The default configuration file for ldap support.
+ .El
+ .Sh SEE ALSO
diff --git a/SOURCES/cyrus-sasl-2.1.21-sizes.patch b/SOURCES/cyrus-sasl-2.1.21-sizes.patch
new file mode 100644
index 0000000..6373924
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.21-sizes.patch
@@ -0,0 +1,119 @@
+diff -up cyrus-sasl-2.1.27/configure.ac.sizes cyrus-sasl-2.1.27/configure.ac
+--- cyrus-sasl-2.1.27/configure.ac.sizes	2015-11-18 09:46:24.000000000 +0100
++++ cyrus-sasl-2.1.27/configure.ac	2015-11-20 15:11:20.474588247 +0100
+@@ -1312,6 +1312,10 @@ AC_HEADER_STDC
+ AC_HEADER_DIRENT
+ AC_HEADER_SYS_WAIT
+ AC_CHECK_HEADERS(crypt.h des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h krb5.h)
++AC_CHECK_TYPES([long long, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t],,,[
++#ifdef HAVE_INTTYPES_H
++#include <inttypes.h>
++#endif])
+ 
+ IPv6_CHECK_SS_FAMILY()
+ IPv6_CHECK_SA_LEN()
+diff -up cyrus-sasl-2.1.27/include/makemd5.c.sizes cyrus-sasl-2.1.27/include/makemd5.c
+--- cyrus-sasl-2.1.27/include/makemd5.c.sizes	2015-10-15 15:44:43.000000000 +0200
++++ cyrus-sasl-2.1.27/include/makemd5.c	2015-11-20 15:11:20.477588240 +0100
+@@ -82,12 +82,19 @@
+  */
+ 
+ 
++#ifdef HAVE_CONFIG_H
++#include "../config.h"
++#endif
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <ctype.h>
+ 
++#ifdef HAVE_INTTYPES_H
++#include <inttypes.h>
++#endif
++
+ 
+ static void
+ my_strupr(char *s)
+@@ -122,6 +129,18 @@ my_strupr(char *s)
+ static void
+ try_signed(FILE *f, int len)
+ {
++#ifdef HAVE_INT8_T
++    BITSIZE(int8_t);
++#endif
++#ifdef HAVE_INT16_T
++    BITSIZE(int16_t);
++#endif
++#ifdef HAVE_INT32_T
++    BITSIZE(int32_t);
++#endif
++#ifdef HAVE_INT64_T
++    BITSIZE(int64_t);
++#endif
+     BITSIZE(signed char);
+     BITSIZE(short);
+     BITSIZE(int);
+@@ -135,6 +154,18 @@ try_signed(FILE *f, int len)
+ static void
+ try_unsigned(FILE *f, int len)
+ {
++#ifdef HAVE_UINT8_T
++    BITSIZE(uint8_t);
++#endif
++#ifdef HAVE_UINT16_T
++    BITSIZE(uint16_t);
++#endif
++#ifdef HAVE_UINT32_T
++    BITSIZE(uint32_t);
++#endif
++#ifdef HAVE_UINT64_T
++    BITSIZE(uint64_t);
++#endif
+     BITSIZE(unsigned char);
+     BITSIZE(unsigned short);
+     BITSIZE(unsigned int);
+@@ -165,6 +196,11 @@ static int print_pre(FILE *f)
+ 	  "/* POINTER defines a generic pointer type */\n"
+ 	  "typedef unsigned char *POINTER;\n"
+ 	  "\n"
++#ifdef HAVE_INTTYPES_H
++	  "/* We try to define integer types for our use */\n"
++	  "#include <inttypes.h>\n"
++	  "\n"
++#endif
+ 	  );
+   return 1;
+ }
+@@ -212,31 +248,15 @@ int main(int argc, char **argv)
+ 
+   print_pre(f);
+ 
+-#ifndef HAVE_INT8_T
+     try_signed (f, 8);
+-#endif /* HAVE_INT8_T */
+-#ifndef HAVE_INT16_T
+     try_signed (f, 16);
+-#endif /* HAVE_INT16_T */
+-#ifndef HAVE_INT32_T
+     try_signed (f, 32);
+-#endif /* HAVE_INT32_T */
+-#ifndef HAVE_INT64_T
+     try_signed (f, 64);
+-#endif /* HAVE_INT64_T */
+ 
+-#ifndef HAVE_U_INT8_T
+     try_unsigned (f, 8);
+-#endif /* HAVE_INT8_T */
+-#ifndef HAVE_U_INT16_T
+     try_unsigned (f, 16);
+-#endif /* HAVE_U_INT16_T */
+-#ifndef HAVE_U_INT32_T
+     try_unsigned (f, 32);
+-#endif /* HAVE_U_INT32_T */
+-#ifndef HAVE_U_INT64_T
+     try_unsigned (f, 64);
+-#endif /* HAVE_U_INT64_T */
+ 
+     print_post(f);
+   
diff --git a/SOURCES/cyrus-sasl-2.1.23-man.patch b/SOURCES/cyrus-sasl-2.1.23-man.patch
new file mode 100644
index 0000000..21c63cd
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.23-man.patch
@@ -0,0 +1,24 @@
+diff -up cyrus-sasl-2.1.26/saslauthd/testsaslauthd.8.man cyrus-sasl-2.1.26/saslauthd/testsaslauthd.8
+--- cyrus-sasl-2.1.26/saslauthd/testsaslauthd.8.man	2013-09-03 15:25:26.818042047 +0200
++++ cyrus-sasl-2.1.26/saslauthd/testsaslauthd.8	2013-09-03 15:25:26.818042047 +0200
+@@ -0,0 +1,20 @@
++.\"                                      Hey, EMACS: -*- nroff -*-
++.TH TESTSASLAUTHD 8 "14 October 2006"
++.SH NAME
++testsaslauthd \- test utility for the SASL authentication server
++.SH SYNOPSIS
++.B testsaslauthd
++.RI "[ " \(hyr " " realm " ] [ " \(hys " " servicename " ] [ " \(hyf " " socket " " path " ] [ " \(hyR " " repeatnum " ]"
++.SH DESCRIPTION
++This manual page documents briefly the
++.B testsaslauthd
++command.
++.PP
++.SH SEE ALSO
++.BR saslauthd (8).
++.br
++.SH AUTHOR
++testsaslauthd was written by Carnegie Mellon University.
++.PP
++This manual page was written by Roberto C. Sanchez <roberto@connexer.com>,
++for the Debian project (but may be used by others).
diff --git a/SOURCES/cyrus-sasl-2.1.25-no_rpath.patch b/SOURCES/cyrus-sasl-2.1.25-no_rpath.patch
new file mode 100644
index 0000000..3ff180c
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.25-no_rpath.patch
@@ -0,0 +1,20 @@
+diff -up cyrus-sasl-2.1.25/m4/cyrus.m4.no_rpath cyrus-sasl-2.1.25/m4/cyrus.m4
+--- cyrus-sasl-2.1.25/m4/cyrus.m4.no_rpath	2010-01-22 16:12:01.000000000 +0100
++++ cyrus-sasl-2.1.25/m4/cyrus.m4	2012-12-06 14:59:47.956102057 +0100
+@@ -32,14 +32,5 @@ AC_DEFUN([CMU_ADD_LIBPATH_TO], [
+ dnl runpath initialization
+ AC_DEFUN([CMU_GUESS_RUNPATH_SWITCH], [
+    # CMU GUESS RUNPATH SWITCH
+-  AC_CACHE_CHECK(for runpath switch, andrew_cv_runpath_switch, [
+-    # first, try -R
+-    SAVE_LDFLAGS="${LDFLAGS}"
+-    LDFLAGS="-R /usr/lib"
+-    AC_TRY_LINK([],[],[andrew_cv_runpath_switch="-R"], [
+-  	LDFLAGS="-Wl,-rpath,/usr/lib"
+-    AC_TRY_LINK([],[],[andrew_cv_runpath_switch="-Wl,-rpath,"],
+-    [andrew_cv_runpath_switch="none"])
+-    ])
+-  LDFLAGS="${SAVE_LDFLAGS}"
+-  ])])
++    andrew_runpath_switch="none"
++  ])
diff --git a/SOURCES/cyrus-sasl-2.1.26-md5global.patch b/SOURCES/cyrus-sasl-2.1.26-md5global.patch
new file mode 100644
index 0000000..605c8ec
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.26-md5global.patch
@@ -0,0 +1,24 @@
+diff -up cyrus-sasl-2.1.27/include/Makefile.am.md5global.h cyrus-sasl-2.1.27/include/Makefile.am
+--- cyrus-sasl-2.1.27/include/Makefile.am.md5global.h	2018-05-17 13:33:49.588368350 +0200
++++ cyrus-sasl-2.1.27/include/Makefile.am	2018-05-17 13:38:19.377316869 +0200
+@@ -49,20 +49,7 @@ saslinclude_HEADERS = hmac-md5.h md5.h m
+ 
+ noinst_PROGRAMS = makemd5
+ 
+-makemd5_SOURCES = makemd5.c
+-
+-makemd5$(BUILD_EXEEXT) $(makemd5_OBJECTS): CC=$(CC_FOR_BUILD)
+-makemd5$(BUILD_EXEEXT) $(makemd5_OBJECTS): CFLAGS=$(CFLAGS_FOR_BUILD)
+-makemd5$(BUILD_EXEEXT): LDFLAGS=$(LDFLAGS_FOR_BUILD)
+-
+-md5global.h: makemd5$(BUILD_EXEEXT) Makefile
+-	-rm -f $@
+-	./$< $@
+-
+-BUILT_SOURCES = md5global.h
+-
+ EXTRA_DIST = NTMakefile
+-DISTCLEANFILES = md5global.h
+ 
+ if MACOSX
+ framedir = /Library/Frameworks/SASL2.framework
diff --git a/SOURCES/cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch b/SOURCES/cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch
new file mode 100644
index 0000000..242b436
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch
@@ -0,0 +1,444 @@
+From aa8b6b2275fd14ba2cca3d2339ae61c7e7ddfa70 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 5 May 2020 14:08:48 -0400
+Subject: [PATCH] Add Channel Binding support for GSSAPI/GSS-SPNEGO
+
+Backport of commit ids:
+829a6ed086432e26dafa9d1dcf892aef4c42cfbd
+944bd8a6205f840b105206ef83e8f6b9dff0138e
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ plugins/gssapi.c     | 30 +++++++++++---
+ tests/runtests.py    | 93 ++++++++++++++++++++++++++++++++++++++++----
+ tests/t_common.c     | 24 ++++++++----
+ tests/t_common.h     |  5 ++-
+ tests/t_gssapi_cli.c | 24 ++++++++++--
+ tests/t_gssapi_srv.c | 24 ++++++++++--
+ 6 files changed, 172 insertions(+), 28 deletions(-)
+
+diff --git a/plugins/gssapi.c b/plugins/gssapi.c
+index ff663da..5d900c5 100644
+--- a/plugins/gssapi.c
++++ b/plugins/gssapi.c
+@@ -830,7 +830,9 @@ gssapi_server_mech_authneg(context_t *text,
+     gss_buffer_desc name_without_realm;
+     gss_name_t client_name_MN = NULL, without = NULL;
+     gss_OID mech_type;
+-	
++    gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
++    struct gss_channel_bindings_struct cb = {0};
++
+     input_token = &real_input_token;
+     output_token = &real_output_token;
+     output_token->value = NULL; output_token->length = 0;
+@@ -902,6 +904,12 @@ gssapi_server_mech_authneg(context_t *text,
+ 	real_input_token.length = clientinlen;
+     }
+ 
++    if (params->cbinding != NULL) {
++        cb.application_data.length = params->cbinding->len;
++        cb.application_data.value = params->cbinding->data;
++        bindings = &cb;
++    }
++
+ 
+     GSS_LOCK_MUTEX_CTX(params->utils, text);
+     maj_stat =
+@@ -909,7 +917,7 @@ gssapi_server_mech_authneg(context_t *text,
+ 			       &(text->gss_ctx),
+ 			       server_creds,
+ 			       input_token,
+-			       GSS_C_NO_CHANNEL_BINDINGS,
++			       bindings,
+ 			       &text->client_name,
+ 			       &mech_type,
+ 			       output_token,
+@@ -1505,7 +1513,8 @@ static sasl_server_plug_t gssapi_server_plugins[] =
+ 	| SASL_SEC_PASS_CREDENTIALS,
+ 	SASL_FEAT_WANT_CLIENT_FIRST
+ 	| SASL_FEAT_ALLOWS_PROXY
+-	| SASL_FEAT_DONTUSE_USERPASSWD,	/* features */
++	| SASL_FEAT_DONTUSE_USERPASSWD
++	| SASL_FEAT_CHANNEL_BINDING,	/* features */
+ 	NULL,				/* glob_context */
+ 	&gssapi_server_mech_new,	/* mech_new */
+ 	&gssapi_server_mech_step,	/* mech_step */
+@@ -1529,6 +1538,7 @@ static sasl_server_plug_t gssapi_server_plugins[] =
+ 	SASL_FEAT_WANT_CLIENT_FIRST
+ 	| SASL_FEAT_ALLOWS_PROXY
+ 	| SASL_FEAT_DONTUSE_USERPASSWD
++	| SASL_FEAT_CHANNEL_BINDING
+ 	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
+ 	&gss_spnego_oid,		/* glob_context */
+ 	&gssapi_server_mech_new,	/* mech_new */
+@@ -1662,6 +1672,8 @@ static int gssapi_client_mech_step(void *conn_context,
+     input_token->value = NULL; 
+     input_token->length = 0;
+     gss_cred_id_t client_creds = (gss_cred_id_t)params->gss_creds;
++    gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
++    struct gss_channel_bindings_struct cb = {0};
+ 
+     if (clientout)
+         *clientout = NULL;
+@@ -1777,6 +1789,12 @@ static int gssapi_client_mech_step(void *conn_context,
+ 	    req_flags = req_flags |  GSS_C_DELEG_FLAG;
+ 	}
+ 
++        if (params->cbinding != NULL) {
++            cb.application_data.length = params->cbinding->len;
++            cb.application_data.value = params->cbinding->data;
++            bindings = &cb;
++        }
++
+ 	GSS_LOCK_MUTEX_CTX(params->utils, text);
+ 	maj_stat = gss_init_sec_context(&min_stat,
+ 					client_creds, /* GSS_C_NO_CREDENTIAL */
+@@ -1785,7 +1803,7 @@ static int gssapi_client_mech_step(void *conn_context,
+ 					text->mech_type,
+ 					req_flags,
+ 					0,
+-					GSS_C_NO_CHANNEL_BINDINGS,
++					bindings,
+ 					input_token,
+ 					NULL,
+ 					output_token,
+@@ -2190,7 +2208,8 @@ static sasl_client_plug_t gssapi_client_plugins[] =
+ 	| SASL_SEC_PASS_CREDENTIALS,    /* security_flags */
+ 	SASL_FEAT_NEEDSERVERFQDN
+ 	| SASL_FEAT_WANT_CLIENT_FIRST
+-	| SASL_FEAT_ALLOWS_PROXY,	/* features */
++	| SASL_FEAT_ALLOWS_PROXY
++	| SASL_FEAT_CHANNEL_BINDING,	/* features */
+ 	gssapi_required_prompts,	/* required_prompts */
+ 	GSS_C_NO_OID,			/* glob_context */
+ 	&gssapi_client_mech_new,	/* mech_new */
+@@ -2213,6 +2232,7 @@ static sasl_client_plug_t gssapi_client_plugins[] =
+ 	SASL_FEAT_NEEDSERVERFQDN
+ 	| SASL_FEAT_WANT_CLIENT_FIRST
+ 	| SASL_FEAT_ALLOWS_PROXY
++	| SASL_FEAT_CHANNEL_BINDING
+ 	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
+ 	gssapi_required_prompts,	/* required_prompts */
+ 	&gss_spnego_oid,		/* glob_context */
+diff --git a/tests/runtests.py b/tests/runtests.py
+index f645adf..fc9cf24 100755
+--- a/tests/runtests.py
++++ b/tests/runtests.py
+@@ -1,6 +1,7 @@
+ #!/usr/bin/python3
+ 
+ import argparse
++import base64
+ import os
+ import shutil
+ import signal
+@@ -126,14 +127,7 @@ def setup_kdc(testdir, env):
+ 
+     return kdc, env
+ 
+-
+-def gssapi_tests(testdir):
+-    """ SASL/GSSAPI Tests """
+-    env = setup_socket_wrappers(testdir)
+-    kdc, kenv = setup_kdc(testdir, env)
+-    #print("KDC: {}, ENV: {}".format(kdc, kenv))
+-    kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
+-
++def gssapi_basic_test(kenv):
+     try:
+         srv = subprocess.Popen(["../tests/t_gssapi_srv"],
+                                stdout=subprocess.PIPE,
+@@ -155,11 +149,94 @@ def gssapi_tests(testdir):
+                 srv.returncode, srv.stderr.read().decode('utf-8')))
+     except Exception as e:
+         print("FAIL: {}".format(e))
++        return
++
++    print("PASS: CLI({}) SRV({})".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++
++def gssapi_channel_binding_test(kenv):
++    try:
++        bindings = base64.b64encode("MATCHING CBS".encode('utf-8'))
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-c", bindings],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-c", bindings],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli.stderr.read().decode('utf-8'),
++                srv.returncode, srv.stderr.read().decode('utf-8')))
++    except Exception as e:
++        print("FAIL: {}".format(e))
++        return
+ 
+     print("PASS: CLI({}) SRV({})".format(
+         cli.stdout.read().decode('utf-8').strip(),
+         srv.stdout.read().decode('utf-8').strip()))
+ 
++def gssapi_channel_binding_mismatch_test(kenv):
++    result = "FAIL"
++    try:
++        bindings = base64.b64encode("SRV CBS".encode('utf-8'))
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-c", bindings],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        bindings = base64.b64encode("CLI CBS".encode('utf-8'))
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-c", bindings],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            cli_err = cli.stderr.read().decode('utf-8').strip()
++            srv_err = srv.stderr.read().decode('utf-8').strip()
++            if "authentication failure" in srv_err:
++                result = "PASS"
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli_err, srv.returncode, srv_err))
++    except Exception as e:
++        print("{}: {}".format(result, e))
++        return
++
++    print("FAIL: This test should fail [CLI({}) SRV({})]".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++
++def gssapi_tests(testdir):
++    """ SASL/GSSAPI Tests """
++    env = setup_socket_wrappers(testdir)
++    kdc, kenv = setup_kdc(testdir, env)
++    #print("KDC: {}, ENV: {}".format(kdc, kenv))
++    kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
++
++    print('GSSAPI BASIC:')
++    print('    ', end='')
++    gssapi_basic_test(kenv)
++
++    print('GSSAPI CHANNEL BINDING:')
++    print('    ', end='')
++    gssapi_channel_binding_test(kenv)
++
++    print('GSSAPI CHANNEL BINDING MISMTACH:')
++    print('    ', end='')
++    gssapi_channel_binding_mismatch_test(kenv)
++
+     os.killpg(kdc.pid, signal.SIGTERM)
+ 
+ 
+diff --git a/tests/t_common.c b/tests/t_common.c
+index 7168b2f..478e6a1 100644
+--- a/tests/t_common.c
++++ b/tests/t_common.c
+@@ -1,4 +1,5 @@
+-/* TBD, add (C) */
++/* Copyright (C) Simo Sorce <simo@redhat.com>
++ * See COPYING file for License */
+ 
+ #include <t_common.h>
+ 
+@@ -13,9 +14,6 @@ void send_string(int sd, const char *s, unsigned int l)
+ {
+     ssize_t ret;
+ 
+-fprintf(stderr, "s:%u ", l);
+-fflush(stderr);
+-
+     ret = send(sd, &l, sizeof(l), 0);
+     if (ret != sizeof(l)) s_error("send size", ret, sizeof(l), errno);
+ 
+@@ -34,8 +32,6 @@ void recv_string(int sd, char *buf, unsigned int *buflen)
+     if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
+ 
+     if (l == 0) {
+-fprintf(stderr, "r:0 ");
+-fflush(stderr);
+         *buflen = 0;
+         return;
+     }
+@@ -45,8 +41,6 @@ fflush(stderr);
+     ret = recv(sd, buf, l, 0);
+     if (ret != l) s_error("recv data", ret, l, errno);
+ 
+-fprintf(stderr, "r:%ld ", ret);
+-fflush(stderr);
+     *buflen = ret;
+ }
+ 
+@@ -65,4 +59,18 @@ int getpath(void *context __attribute__((unused)), const char **path)
+     return SASL_OK;
+ }
+ 
++void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in)
++{
++    unsigned len;
++    int r;
+ 
++    r = sasl_decode64(in, strlen(in), buf, max, &len);
++    if (r != SASL_OK) {
++        saslerr(r, "failed to parse channel bindings");
++        exit(-1);
++    }
++    cb->name = "TEST BINDINGS";
++    cb->critical = 0;
++    cb->data = (unsigned char *)buf;
++    cb->len = len;
++}
+diff --git a/tests/t_common.h b/tests/t_common.h
+index 4ee1976..a10def1 100644
+--- a/tests/t_common.h
++++ b/tests/t_common.h
+@@ -1,4 +1,5 @@
+-/* TBD, add (C) */
++/* Copyright (C) Simo Sorce <simo@redhat.com>
++ * See COPYING file for License */
+ 
+ #include "config.h"
+ 
+@@ -7,9 +8,11 @@
+ #include <sys/socket.h>
+ 
+ #include <sasl.h>
++#include <saslutil.h>
+ 
+ void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
+ void send_string(int sd, const char *s, unsigned int l);
+ void recv_string(int sd, char *buf, unsigned int *buflen);
+ void saslerr(int why, const char *what);
+ int getpath(void *context __attribute__((unused)), const char **path);
++void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in);
+diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
+index c833c05..a44a3f5 100644
+--- a/tests/t_gssapi_cli.c
++++ b/tests/t_gssapi_cli.c
+@@ -1,4 +1,5 @@
+-/* TBD, add (C) */
++/* Copyright (C) Simo Sorce <simo@redhat.com>
++ * See COPYING file for License */
+ 
+ #include "t_common.h"
+ 
+@@ -13,6 +14,7 @@
+ 
+ #include <arpa/inet.h>
+ #include <saslplug.h>
++#include <saslutil.h>
+ 
+ static int setup_socket(void)
+ {
+@@ -32,7 +34,7 @@ static int setup_socket(void)
+     return sock;
+ }
+ 
+-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
++int main(int argc, char *argv[])
+ {
+     sasl_callback_t callbacks[2] = {};
+     char buf[8192];
+@@ -40,8 +42,20 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
+     sasl_conn_t *conn;
+     const char *data;
+     unsigned int len;
++    sasl_channel_binding_t cb = {0};
++    char cb_buf[256];
+     int sd;
+-    int r;
++    int c, r;
++
++    while ((c = getopt(argc, argv, "c:")) != EOF) {
++        switch (c) {
++        case 'c':
++            parse_cb(&cb, cb_buf, 256, optarg);
++            break;
++        default:
++            break;
++        }
++    }
+ 
+     /* initialize the sasl library */
+     callbacks[0].id = SASL_CB_GETPATH;
+@@ -60,6 +74,10 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
+         exit(-1);
+     }
+ 
++    if (cb.name) {
++        sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
++    }
++
+     r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
+     if (r != SASL_OK && r != SASL_CONTINUE) {
+ 	saslerr(r, "starting SASL negotiation");
+diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
+index 29f538d..ef1217f 100644
+--- a/tests/t_gssapi_srv.c
++++ b/tests/t_gssapi_srv.c
+@@ -1,4 +1,5 @@
+-/* TBD, add (C) */
++/* Copyright (C) Simo Sorce <simo@redhat.com>
++ * See COPYING file for License */
+ 
+ #include "t_common.h"
+ 
+@@ -44,15 +45,28 @@ static int setup_socket(void)
+     return sd;
+ }
+ 
+-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
++int main(int argc, char *argv[])
+ {
+     sasl_callback_t callbacks[2] = {};
+     char buf[8192];
+     sasl_conn_t *conn;
+     const char *data;
+     unsigned int len;
++    sasl_channel_binding_t cb = {0};
++    unsigned char cb_buf[256];
+     int sd;
+-    int r;
++    int c, r;
++
++    while ((c = getopt(argc, argv, "c:")) != EOF) {
++        switch (c) {
++        case 'c':
++            parse_cb(&cb, cb_buf, 256, optarg);
++            break;
++        default:
++            break;
++        }
++    }
++
+ 
+     /* initialize the sasl library */
+     callbacks[0].id = SASL_CB_GETPATH;
+@@ -72,6 +86,10 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
+         exit(-1);
+     }
+ 
++    if (cb.name) {
++        sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
++    }
++
+     sd = setup_socket();
+ 
+     len = 8192;
+-- 
+2.18.2
+
diff --git a/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch b/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
new file mode 100644
index 0000000..2f6a35c
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
@@ -0,0 +1,641 @@
+From 82e299e970461c153a036bb1fbc84e808f926e12 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 5 May 2020 14:06:57 -0400
+Subject: [PATCH] Add basic test infrastructure
+
+First test is for SASL/GSSAPI
+
+Backport of upstream commit id:
+18ff41d5d18f61c2ded7235dad1d9618aa84784b
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ Makefile.am          |   2 +-
+ configure.ac         |   3 +-
+ tests/Makefile.am    |  79 +++++++++++++++++++
+ tests/runtests.py    | 179 +++++++++++++++++++++++++++++++++++++++++++
+ tests/t_common.c     |  68 ++++++++++++++++
+ tests/t_common.h     |  15 ++++
+ tests/t_gssapi_cli.c |  95 +++++++++++++++++++++++
+ tests/t_gssapi_srv.c | 111 +++++++++++++++++++++++++++
+ 8 files changed, 550 insertions(+), 2 deletions(-)
+ create mode 100644 tests/Makefile.am
+ create mode 100755 tests/runtests.py
+ create mode 100644 tests/t_common.c
+ create mode 100644 tests/t_common.h
+ create mode 100644 tests/t_gssapi_cli.c
+ create mode 100644 tests/t_gssapi_srv.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 83dae6f..fc24509 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -70,7 +70,7 @@ else
+ INSTALLOSX = 
+ endif
+ 
+-SUBDIRS=include sasldb common lib plugins utils $(PWC) $(SAM) $(JAV) $(SAD)
++SUBDIRS=include sasldb common lib plugins utils $(PWC) $(SAM) $(JAV) $(SAD) tests
+ EXTRA_DIST=config doc docsrc win32 mac dlcompat-20010505 NTMakefile \
+     INSTALL.TXT libsasl2.pc.in
+ 
+diff --git a/configure.ac b/configure.ac
+index ca5936a..c1d2182 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1575,7 +1575,8 @@ java/javax/Makefile
+ java/javax/security/Makefile
+ java/javax/security/auth/Makefile
+ java/javax/security/auth/callback/Makefile
+-pwcheck/Makefile)
++pwcheck/Makefile
++tests/Makefile)
+ 
+ AC_MSG_NOTICE([
+ 
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+new file mode 100644
+index 0000000..1edf010
+--- /dev/null
++++ b/tests/Makefile.am
+@@ -0,0 +1,79 @@
++# Makefile.am -- automake input for cyrus-sasl tests
++# Simo Sorce
++#
++################################################################
++# Copyright (c) 2000 Carnegie Mellon University.  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.
++#
++# 3. The name "Carnegie Mellon University" must not be used to
++#    endorse or promote products derived from this software without
++#    prior written permission. For permission or any other legal
++#    details, please contact
++#      Office of Technology Transfer
++#      Carnegie Mellon University
++#      5000 Forbes Avenue
++#      Pittsburgh, PA  15213-3890
++#      (412) 268-4387, fax: (412) 268-7395
++#      tech-transfer@andrew.cmu.edu
++#
++# 4. Redistributions of any form whatsoever must retain the following
++#    acknowledgment:
++#    "This product includes software developed by Computing Services
++#     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
++#
++# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
++# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
++# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
++# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
++# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++#
++################################################################
++
++AM_CPPFLAGS=-I$(top_srcdir)/include -DPLUGINDIR='"${top_srcdir}/plugins/.libs"'
++
++COMMON_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
++
++t_gssapi_cli_SOURCES = \
++	t_common.c \
++	t_gssapi_cli.c
++
++t_gssapi_cli_LDADD = $(COMMON_LDADD)
++
++t_gssapi_srv_SOURCES = \
++	t_common.c \
++	t_gssapi_srv.c
++
++t_gssapi_srv_LDADD = $(COMMON_LDADD)
++
++check_PROGRAMS = \
++	t_gssapi_cli \
++	t_gssapi_srv \
++	$(NULL)
++
++noinst_PROGRAMS = $(check_PROGRAMS)
++
++EXTRA_DIST = \
++	runtests.py \
++	$(NULL)
++
++all: $(check_PROGRAMS)
++
++check:
++if MACOSX
++# skip Mac OSX for now
++else
++	$(srcdir)/runtests.py $(CHECKARGS)
++endif
+diff --git a/tests/runtests.py b/tests/runtests.py
+new file mode 100755
+index 0000000..f645adf
+--- /dev/null
++++ b/tests/runtests.py
+@@ -0,0 +1,179 @@
++#!/usr/bin/python3
++
++import argparse
++import os
++import shutil
++import signal
++import subprocess
++import time
++from string import Template
++
++
++def setup_socket_wrappers(testdir):
++    """ Try to set up socket wrappers """
++    wrapdir = os.path.join(testdir, 'w')
++    os.makedirs(wrapdir)
++
++    wrappers = subprocess.Popen(['pkg-config', '--exists', 'socket_wrapper'])
++    wrappers.wait()
++    if wrappers.returncode != 0:
++        raise Exception('Socket Wrappers not available')
++
++    wrappers = subprocess.Popen(['pkg-config', '--exists', 'nss_wrapper'])
++    wrappers.wait()
++    if wrappers.returncode != 0:
++        raise Exception('NSS Wrappers not available')
++
++    hosts = os.path.join(wrapdir, 'hosts')
++    with open(hosts, 'w+') as conffile:
++        conffile.write('127.0.0.9 host.realm.test')
++
++    return {'LD_PRELOAD': 'libsocket_wrapper.so libnss_wrapper.so',
++            'SOCKET_WRAPPER_DIR': wrapdir,
++            'SOCKET_WRAPPER_DEFAULT_IFACE': '9',
++            'NSS_WRAPPER_HOSTNAME': 'host.realm.test',
++            'NSS_WRAPPER_HOSTS': hosts}
++
++
++KERBEROS_CONF = '''
++[libdefaults]
++  default_realm = REALM.TEST
++  dns_lookup_realm = false
++  dns_lookup_kdc = false
++  rdns = false
++  ticket_lifetime = 24h
++  forwardable = yes
++  default_ccache_name = FILE://${TESTDIR}/ccache
++  udp_preference_limit = 1
++
++[domain_realm]
++  .realm.test = REALM.TEST
++  realm.test = REALM.TEST
++
++[realms]
++ REALM.TEST = {
++  kdc = 127.0.0.9
++  admin_server = 127.0.0.9
++  acl_file = ${TESTDIR}/kadm.acl
++  dict_file = /usr/share/dict/words
++  admin_keytab = ${TESTDIR}/kadm.keytab
++  database_name = ${TESTDIR}/kdc.db
++  key_stash_file = ${TESTDIR}/kdc.stash
++ }
++
++[kdcdefaults]
++ kdc_ports = 88
++ kdc_tcp_ports = 88
++
++[logging]
++  kdc = FILE:${TESTDIR}/kdc.log
++  admin_server = FILE:${TESTDIR}/kadm.log
++  default = FILE:${TESTDIR}/krb5.log
++'''
++
++
++def setup_kdc(testdir, env):
++    """ Setup KDC and start process """
++    krbconf = os.path.join(testdir, 'krb.conf')
++    env['KRB5_CONFIG'] = krbconf
++
++    kenv = {'KRB5_KDC_PROFILE': krbconf,
++            'PATH': '/sbin:/bin:/usr/sbin:/usr/bin'}
++    kenv.update(env)
++
++    # KDC/KRB5 CONFIG
++    templ = Template(KERBEROS_CONF)
++    text = templ.substitute({'TESTDIR': testdir})
++    with open(krbconf, 'w+') as conffile:
++        conffile.write(text)
++
++    testlog = os.path.join(testdir, 'kdc.log')
++    log = open(testlog, 'a')
++
++    subprocess.check_call([
++        "kdb5_util", "create",
++        "-r", "REALM.TEST", "-s", "-P", "password"
++        ], stdout=log, stderr=log, env=kenv, timeout=5)
++
++    kdc = subprocess.Popen(['krb5kdc', '-n'], env=kenv, preexec_fn=os.setsid)
++    time.sleep(5)
++
++    # Add a user and genrate a keytab
++    keytab = os.path.join(testdir, "user.keytab")
++    subprocess.check_call([
++        "kadmin.local", "-q",
++        "addprinc -randkey user"
++        ], stdout=log, stderr=log, env=kenv, timeout=5)
++
++    subprocess.check_call([
++        "kadmin.local", "-q",
++        "ktadd -k {} user".format(keytab)
++        ], stdout=log, stderr=log, env=kenv, timeout=5)
++    env['KRB5_CLIENT_KTNAME'] = keytab
++
++    # Add a service and genrate a keytab
++    keytab = os.path.join(testdir, "test.keytab")
++    subprocess.check_call([
++        "kadmin.local", "-q",
++        "addprinc -randkey test/host.realm.test"
++        ], stdout=log, stderr=log, env=kenv, timeout=5)
++
++    subprocess.check_call([
++        "kadmin.local", "-q",
++        "ktadd -k {} test/host.realm.test".format(keytab)
++        ], stdout=log, stderr=log, env=kenv, timeout=5)
++    env['KRB5_KTNAME'] = keytab
++
++    return kdc, env
++
++
++def gssapi_tests(testdir):
++    """ SASL/GSSAPI Tests """
++    env = setup_socket_wrappers(testdir)
++    kdc, kenv = setup_kdc(testdir, env)
++    #print("KDC: {}, ENV: {}".format(kdc, kenv))
++    kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
++
++    try:
++        srv = subprocess.Popen(["../tests/t_gssapi_srv"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        cli = subprocess.Popen(["../tests/t_gssapi_cli"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli.stderr.read().decode('utf-8'),
++                srv.returncode, srv.stderr.read().decode('utf-8')))
++    except Exception as e:
++        print("FAIL: {}".format(e))
++
++    print("PASS: CLI({}) SRV({})".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++
++    os.killpg(kdc.pid, signal.SIGTERM)
++
++
++if __name__ == "__main__":
++
++    P = argparse.ArgumentParser(description='Cyrus SASL Tests')
++    P.add_argument('--testdir', default=os.path.join(os.getcwd(), '.tests'),
++                   help="Directory for running tests")
++    A = vars(P.parse_args())
++
++    T = A['testdir']
++
++    if os.path.exists(T):
++        shutil.rmtree(T)
++    os.makedirs(T)
++
++    gssapi_tests(T)
+diff --git a/tests/t_common.c b/tests/t_common.c
+new file mode 100644
+index 0000000..7168b2f
+--- /dev/null
++++ b/tests/t_common.c
+@@ -0,0 +1,68 @@
++/* TBD, add (C) */
++
++#include <t_common.h>
++
++void s_error(const char *hdr, ssize_t ret, ssize_t len, int err)
++{
++    fprintf(stderr, "%s l:%ld/%ld [%d] %s",
++            hdr, ret, len, err, strerror(err));
++    exit(-1);
++}
++
++void send_string(int sd, const char *s, unsigned int l)
++{
++    ssize_t ret;
++
++fprintf(stderr, "s:%u ", l);
++fflush(stderr);
++
++    ret = send(sd, &l, sizeof(l), 0);
++    if (ret != sizeof(l)) s_error("send size", ret, sizeof(l), errno);
++
++    if (l == 0) return;
++
++    ret = send(sd, s, l, 0);
++    if (ret != l) s_error("send data", ret, l, errno);
++}
++
++void recv_string(int sd, char *buf, unsigned int *buflen)
++{
++    unsigned int l;
++    ssize_t ret;
++
++    ret = recv(sd, &l, sizeof(l), MSG_WAITALL);
++    if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
++
++    if (l == 0) {
++fprintf(stderr, "r:0 ");
++fflush(stderr);
++        *buflen = 0;
++        return;
++    }
++
++    if (*buflen < l) s_error("recv len", l, *buflen, E2BIG);
++
++    ret = recv(sd, buf, l, 0);
++    if (ret != l) s_error("recv data", ret, l, errno);
++
++fprintf(stderr, "r:%ld ", ret);
++fflush(stderr);
++    *buflen = ret;
++}
++
++void saslerr(int why, const char *what)
++{
++    fprintf(stderr, "%s: %s", what, sasl_errstring(why, NULL, NULL));
++}
++
++int getpath(void *context __attribute__((unused)), const char **path)
++{
++    if (! path) {
++        return SASL_BADPARAM;
++    }
++
++    *path = PLUGINDIR;
++    return SASL_OK;
++}
++
++
+diff --git a/tests/t_common.h b/tests/t_common.h
+new file mode 100644
+index 0000000..4ee1976
+--- /dev/null
++++ b/tests/t_common.h
+@@ -0,0 +1,15 @@
++/* TBD, add (C) */
++
++#include "config.h"
++
++#include <errno.h>
++#include <stdio.h>
++#include <sys/socket.h>
++
++#include <sasl.h>
++
++void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
++void send_string(int sd, const char *s, unsigned int l);
++void recv_string(int sd, char *buf, unsigned int *buflen);
++void saslerr(int why, const char *what);
++int getpath(void *context __attribute__((unused)), const char **path);
+diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
+new file mode 100644
+index 0000000..c833c05
+--- /dev/null
++++ b/tests/t_gssapi_cli.c
+@@ -0,0 +1,95 @@
++/* TBD, add (C) */
++
++#include "t_common.h"
++
++#include <stdlib.h>
++#include <stdarg.h>
++#include <ctype.h>
++#include <string.h>
++
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++
++#include <arpa/inet.h>
++#include <saslplug.h>
++
++static int setup_socket(void)
++{
++    struct sockaddr_in addr;
++    int sock, ret;
++
++    sock = socket(AF_INET, SOCK_STREAM, 0);
++    if (sock < 0) s_error("socket", 0, 0, errno);
++
++    addr.sin_family = AF_INET;
++    addr.sin_addr.s_addr = inet_addr("127.0.0.9");
++    addr.sin_port = htons(9000);
++
++    ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
++    if (ret != 0) s_error("connect", 0, 0, errno);
++
++    return sock;
++}
++
++int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
++{
++    sasl_callback_t callbacks[2] = {};
++    char buf[8192];
++    const char *chosenmech;
++    sasl_conn_t *conn;
++    const char *data;
++    unsigned int len;
++    int sd;
++    int r;
++
++    /* initialize the sasl library */
++    callbacks[0].id = SASL_CB_GETPATH;
++    callbacks[0].proc = (sasl_callback_ft)&getpath;
++    callbacks[0].context = NULL;
++    callbacks[1].id = SASL_CB_LIST_END;
++    callbacks[1].proc = NULL;
++    callbacks[1].context = NULL;
++
++    r = sasl_client_init(callbacks);
++    if (r != SASL_OK) exit(-1);
++
++    r = sasl_client_new("test", "host.realm.test", NULL, NULL, NULL, 0, &conn);
++    if (r != SASL_OK) {
++        saslerr(r, "allocating connection state");
++        exit(-1);
++    }
++
++    r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
++    if (r != SASL_OK && r != SASL_CONTINUE) {
++	saslerr(r, "starting SASL negotiation");
++	printf("\n%s\n", sasl_errdetail(conn));
++	exit(-1);
++    }
++
++    sd = setup_socket();
++
++    while (r == SASL_CONTINUE) {
++        send_string(sd, data, len);
++        len = 8192;
++        recv_string(sd, buf, &len);
++
++	r = sasl_client_step(conn, buf, len, NULL, &data, &len);
++	if (r != SASL_OK && r != SASL_CONTINUE) {
++	    saslerr(r, "performing SASL negotiation");
++	    printf("\n%s\n", sasl_errdetail(conn));
++	    exit(-1);
++        }
++    }
++
++    if (r != SASL_OK) exit(-1);
++
++    if (len > 0) {
++        send_string(sd, data, len);
++    }
++
++    fprintf(stdout, "DONE\n");
++    fflush(stdout);
++    return 0;
++}
++
+diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
+new file mode 100644
+index 0000000..29f538d
+--- /dev/null
++++ b/tests/t_gssapi_srv.c
+@@ -0,0 +1,111 @@
++/* TBD, add (C) */
++
++#include "t_common.h"
++
++#include <stdlib.h>
++#include <stdarg.h>
++#include <ctype.h>
++#include <string.h>
++
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++
++#include <arpa/inet.h>
++#include <saslplug.h>
++
++static int setup_socket(void)
++{
++    struct sockaddr_in addr;
++    int sock, ret, sd;
++
++    sock = socket(AF_INET, SOCK_STREAM, 0);
++    if (sock < 0) s_error("socket", 0, 0, errno);
++
++    addr.sin_family = AF_INET;
++    addr.sin_addr.s_addr = inet_addr("127.0.0.9");
++    addr.sin_port = htons(9000);
++
++    ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
++    if (ret != 0) s_error("bind", 0, 0, errno);
++
++    ret = listen(sock, 1);
++    if (ret != 0) s_error("listen", 0, 0, errno);
++
++    /* signal we are ready */
++    fprintf(stdout, "READY\n");
++    fflush(stdout);
++
++    /* block until the client connects */
++    sd = accept(sock, NULL, NULL);
++    if (sd < 0) s_error("accept", 0, 0, errno);
++
++    close(sock);
++    return sd;
++}
++
++int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
++{
++    sasl_callback_t callbacks[2] = {};
++    char buf[8192];
++    sasl_conn_t *conn;
++    const char *data;
++    unsigned int len;
++    int sd;
++    int r;
++
++    /* initialize the sasl library */
++    callbacks[0].id = SASL_CB_GETPATH;
++    callbacks[0].proc = (sasl_callback_ft)&getpath;
++    callbacks[0].context = NULL;
++    callbacks[1].id = SASL_CB_LIST_END;
++    callbacks[1].proc = NULL;
++    callbacks[1].context = NULL;
++
++    r = sasl_server_init(callbacks, "t_gssapi_srv");
++    if (r != SASL_OK) exit(-1);
++
++    r = sasl_server_new("test", "host.realm.test", NULL, NULL, NULL,
++                        callbacks, 0, &conn);
++    if (r != SASL_OK) {
++        saslerr(r, "allocating connection state");
++        exit(-1);
++    }
++
++    sd = setup_socket();
++
++    len = 8192;
++    recv_string(sd, buf, &len);
++
++    r = sasl_server_start(conn, "GSSAPI", buf, len, &data, &len);
++    if (r != SASL_OK && r != SASL_CONTINUE) {
++	saslerr(r, "starting SASL negotiation");
++	printf("\n%s\n", sasl_errdetail(conn));
++	exit(-1);
++    }
++
++    while (r == SASL_CONTINUE) {
++        send_string(sd, data, len);
++        len = 8192;
++        recv_string(sd, buf, &len);
++
++	r = sasl_server_step(conn, buf, len, &data, &len);
++	if (r != SASL_OK && r != SASL_CONTINUE) {
++	    saslerr(r, "performing SASL negotiation");
++	    printf("\n%s\n", sasl_errdetail(conn));
++	    exit(-1);
++	}
++
++    }
++
++    if (r != SASL_OK) exit(-1);
++
++    if (len > 0) {
++        send_string(sd, data, len);
++    }
++
++    fprintf(stdout, "DONE\n");
++    fflush(stdout);
++    return 0;
++}
++
+-- 
+2.18.2
+
diff --git a/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-plain-auth.patch b/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-plain-auth.patch
new file mode 100644
index 0000000..35903d0
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Add-basic-test-plain-auth.patch
@@ -0,0 +1,411 @@
+diff -Nru cyrus-sasl-2.1.27/tests/runtests.py cyrus-sasl-2.1.27-beldmit/tests/runtests.py
+--- cyrus-sasl-2.1.27/tests/runtests.py	2020-12-23 14:31:35.564537485 +0100
++++ cyrus-sasl-2.1.27-beldmit/tests/runtests.py	2020-12-23 14:30:46.933219377 +0100
+@@ -313,6 +313,99 @@
+ 
+     return err
+ 
++def setup_plain(testdir):
++    """ Create sasldb file """
++    sasldbfile = os.path.join(testdir, 'testsasldb.db')
++
++    sasldbenv = {'SASL_PATH': os.path.join(testdir, '../../plugins/.libs'),
++                 'LD_LIBRARY_PATH' : os.path.join(testdir, '../../lib/.libs')}
++
++    passwdprog = os.path.join(testdir, '../../utils/saslpasswd2')
++
++    echo = subprocess.Popen(('echo', '1234567'), stdout=subprocess.PIPE)
++    subprocess.check_call([
++        passwdprog, "-f", sasldbfile, "-c", "test",
++        "-u", "host.realm.test", "-p"
++        ], stdin=echo.stdout, env=sasldbenv, timeout=5)
++
++    return (sasldbfile, sasldbenv)
++
++def plain_test(sasldbfile, sasldbenv):
++    try:
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-P", sasldbfile],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=sasldbenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-P", "1234567"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=sasldbenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli.stderr.read().decode('utf-8'),
++                srv.returncode, srv.stderr.read().decode('utf-8')))
++    except Exception as e:
++        print("FAIL: {}".format(e))
++        return 1
++
++    print("PASS: PLAIN CLI({}) SRV({})".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++    return 0
++
++def plain_mismatch_test(sasldbfile, sasldbenv):
++    result = "FAIL"
++    try:
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-P", sasldbfile],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=sasldbenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        bindings = base64.b64encode("CLI CBS".encode('utf-8'))
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-P", "12345678"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=sasldbenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            cli_err = cli.stderr.read().decode('utf-8').strip()
++            srv_err = srv.stderr.read().decode('utf-8').strip()
++            if "authentication failure" in srv_err:
++                result = "PASS"
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli_err, srv.returncode, srv_err))
++    except Exception as e:
++        print("{}: {}".format(result, e))
++        return 0
++
++    print("FAIL: This test should fail [CLI({}) SRV({})]".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++    return 1
++
++def plain_tests(testdir):
++    err = 0
++    sasldbfile, sasldbenv = setup_plain(testdir)
++    #print("DB file: {}, ENV: {}".format(sasldbfile, sasldbenv))
++    print('SASLDB PLAIN:')
++    print('    ', end='')
++    err += plain_test(sasldbfile, sasldbenv)
++
++    print('SASLDB PLAIN PASSWORD MISMATCH:')
++    print('    ', end='')
++    err += plain_mismatch_test(sasldbfile, sasldbenv)
++
++    return err
+ 
+ if __name__ == "__main__":
+ 
+@@ -329,5 +422,9 @@
+ 
+     err = gssapi_tests(T)
+     if err != 0:
+-        print('{} test(s) FAILED'.format(err))
++        print('{} GSSAPI test(s) FAILED'.format(err))
++
++    err = plain_tests(T)
++    if err != 0:
++        print('{} PLAIN test(s) FAILED'.format(err))
+         sys.exit(-1)
+diff -Nru cyrus-sasl-2.1.27/tests/t_gssapi_cli.c cyrus-sasl-2.1.27-beldmit/tests/t_gssapi_cli.c
+--- cyrus-sasl-2.1.27/tests/t_gssapi_cli.c	2020-12-23 14:31:35.564537485 +0100
++++ cyrus-sasl-2.1.27-beldmit/tests/t_gssapi_cli.c	2021-01-06 11:26:15.460662537 +0100
+@@ -16,6 +16,8 @@
+ #include <saslplug.h>
+ #include <saslutil.h>
+ 
++const char *testpass = NULL;
++
+ static int setup_socket(void)
+ {
+     struct sockaddr_in addr;
+@@ -34,9 +36,60 @@
+     return sock;
+ }
+ 
++static int get_user(void *context __attribute__((unused)),
++                  int id,
++                  const char **result,
++                  unsigned *len)
++{
++    const char *testuser = "test@host.realm.test";
++
++    if (! result)
++        return SASL_BADPARAM;
++
++    switch (id) {
++    case SASL_CB_USER:
++    case SASL_CB_AUTHNAME:
++        *result = testuser;
++        break;
++    default:
++        return SASL_BADPARAM;
++    }
++
++    if (len) *len = strlen(*result);
++
++    return SASL_OK;
++}
++
++static int get_pass(sasl_conn_t *conn __attribute__((unused)),
++          void *context __attribute__((unused)),
++          int id,
++          sasl_secret_t **psecret)
++{
++    size_t len;
++    static sasl_secret_t *x;
++
++    /* paranoia check */
++    if (! conn || ! psecret || id != SASL_CB_PASS)
++        return SASL_BADPARAM;
++
++    len = strlen(testpass);
++
++    x = (sasl_secret_t *) realloc(x, sizeof(sasl_secret_t) + len);
++
++    if (!x) {
++        return SASL_NOMEM;
++    }
++
++    x->len = len;
++    strcpy((char *)x->data, testpass);
++
++    *psecret = x;
++    return SASL_OK;
++}
++
+ int main(int argc, char *argv[])
+ {
+-    sasl_callback_t callbacks[2] = {};
++    sasl_callback_t callbacks[4] = {};
+     char buf[8192];
+     const char *chosenmech;
+     sasl_conn_t *conn;
+@@ -49,8 +102,9 @@
+     const char *sasl_mech = "GSSAPI";
+     bool spnego = false;
+     bool zeromaxssf = false;
++    bool plain = false;
+ 
+-    while ((c = getopt(argc, argv, "c:zN")) != EOF) {
++    while ((c = getopt(argc, argv, "c:zNP:")) != EOF) {
+         switch (c) {
+         case 'c':
+             parse_cb(&cb, cb_buf, 256, optarg);
+@@ -61,6 +115,10 @@
+         case 'N':
+             spnego = true;
+             break;
++        case 'P':
++            plain = true;
++            testpass = optarg;
++            break;
+         default:
+             break;
+         }
+@@ -73,6 +131,12 @@
+     callbacks[1].id = SASL_CB_LIST_END;
+     callbacks[1].proc = NULL;
+     callbacks[1].context = NULL;
++    callbacks[2].id = SASL_CB_LIST_END;
++    callbacks[2].proc = NULL;
++    callbacks[2].context = NULL;
++    callbacks[3].id = SASL_CB_LIST_END;
++    callbacks[3].proc = NULL;
++    callbacks[3].context = NULL;
+ 
+     r = sasl_client_init(callbacks);
+     if (r != SASL_OK) exit(-1);
+@@ -91,6 +155,16 @@
+         sasl_mech = "GSS-SPNEGO";
+     }
+ 
++    if (plain) {
++        sasl_mech = "PLAIN";
++
++        callbacks[1].id = SASL_CB_AUTHNAME;
++        callbacks[1].proc = (sasl_callback_ft)&get_user;
++
++        callbacks[2].id = SASL_CB_PASS;
++        callbacks[2].proc = (sasl_callback_ft)&get_pass;
++    }
++
+     if (zeromaxssf) {
+         /* set all security properties to 0 including maxssf */
+         sasl_security_properties_t secprops = { 0 };
+@@ -99,9 +173,9 @@
+ 
+     r = sasl_client_start(conn, sasl_mech, NULL, &data, &len, &chosenmech);
+     if (r != SASL_OK && r != SASL_CONTINUE) {
+-	saslerr(r, "starting SASL negotiation");
+-	printf("\n%s\n", sasl_errdetail(conn));
+-	exit(-1);
++        saslerr(r, "starting SASL negotiation");
++        printf("\n%s\n", sasl_errdetail(conn));
++        exit(-1);
+     }
+ 
+     sd = setup_socket();
+@@ -111,11 +185,11 @@
+         len = 8192;
+         recv_string(sd, buf, &len, false);
+ 
+-	r = sasl_client_step(conn, buf, len, NULL, &data, &len);
+-	if (r != SASL_OK && r != SASL_CONTINUE) {
+-	    saslerr(r, "performing SASL negotiation");
+-	    printf("\n%s\n", sasl_errdetail(conn));
+-	    exit(-1);
++        r = sasl_client_step(conn, buf, len, NULL, &data, &len);
++        if (r != SASL_OK && r != SASL_CONTINUE) {
++            saslerr(r, "performing SASL negotiation");
++            printf("\n%s\n", sasl_errdetail(conn));
++            exit(-1);
+         }
+     }
+ 
+diff -Nru cyrus-sasl-2.1.27/tests/t_gssapi_srv.c cyrus-sasl-2.1.27-beldmit/tests/t_gssapi_srv.c
+--- cyrus-sasl-2.1.27/tests/t_gssapi_srv.c	2020-12-23 14:31:35.565537492 +0100
++++ cyrus-sasl-2.1.27-beldmit/tests/t_gssapi_srv.c	2021-01-06 11:27:48.373257373 +0100
+@@ -1,4 +1,5 @@
+-/* Copyright (C) Simo Sorce <simo@redhat.com>
++/* Copyright (C) Simo Sorce <simo@redhat.com>,
++ * Dmitry Belyavskiy <dbelyavs@redhat.com>
+  * See COPYING file for License */
+ 
+ #include "t_common.h"
+@@ -15,6 +16,10 @@
+ #include <arpa/inet.h>
+ #include <saslplug.h>
+ 
++const char *sasldb_path = NULL,
++      *auxprop_plugin = "sasldb",
++      *pwcheck_method = "auxprop-hashed";
++
+ static int setup_socket(void)
+ {
+     struct sockaddr_in addr;
+@@ -45,9 +50,38 @@
+     return sd;
+ }
+ 
++static int test_getopt(void *context __attribute__((unused)),
++                const char *plugin_name __attribute__((unused)),
++                const char *option,
++                const char **result,
++                unsigned *len)
++{
++    if (sasldb_path && !strcmp(option, "sasldb_path")) {
++        *result = sasldb_path;
++        if (len)
++            *len = (unsigned) strlen(sasldb_path);
++        return SASL_OK;
++    }
++
++    if (sasldb_path && !strcmp(option, "auxprop_plugin")) {
++        *result = auxprop_plugin;
++        if (len)
++            *len = (unsigned) strlen(auxprop_plugin);
++        return SASL_OK;
++    }
++
++    if (sasldb_path && !strcmp(option, "pwcheck_method")) {
++        *result = pwcheck_method;
++        if (len)
++            *len = (unsigned) strlen(pwcheck_method);
++        return SASL_OK;
++    }
++    return SASL_FAIL;
++}
++
+ int main(int argc, char *argv[])
+ {
+-    sasl_callback_t callbacks[2] = {};
++    sasl_callback_t callbacks[3] = {};
+     char buf[8192];
+     sasl_conn_t *conn;
+     const char *data;
+@@ -59,8 +93,9 @@
+     const char *sasl_mech = "GSSAPI";
+     bool spnego = false;
+     bool zeromaxssf = false;
++    bool plain = false;
+ 
+-    while ((c = getopt(argc, argv, "c:zN")) != EOF) {
++    while ((c = getopt(argc, argv, "c:zNP:")) != EOF) {
+         switch (c) {
+         case 'c':
+             parse_cb(&cb, cb_buf, 256, optarg);
+@@ -71,6 +106,10 @@
+         case 'N':
+             spnego = true;
+             break;
++        case 'P':
++            plain = true;
++            sasldb_path = optarg;
++            break;
+         default:
+             break;
+         }
+@@ -81,9 +120,12 @@
+     callbacks[0].id = SASL_CB_GETPATH;
+     callbacks[0].proc = (sasl_callback_ft)&getpath;
+     callbacks[0].context = NULL;
+-    callbacks[1].id = SASL_CB_LIST_END;
+-    callbacks[1].proc = NULL;
++    callbacks[1].id = SASL_CB_GETOPT;
++    callbacks[1].proc = (sasl_callback_ft)&test_getopt;
+     callbacks[1].context = NULL;
++    callbacks[2].id = SASL_CB_LIST_END;
++    callbacks[2].proc = NULL;
++    callbacks[2].context = NULL;
+ 
+     r = sasl_server_init(callbacks, "t_gssapi_srv");
+     if (r != SASL_OK) exit(-1);
+@@ -103,6 +145,10 @@
+         sasl_mech = "GSS-SPNEGO";
+     }
+ 
++    if (plain) {
++        sasl_mech = "PLAIN";
++    }
++
+     if (zeromaxssf) {
+         /* set all security properties to 0 including maxssf */
+         sasl_security_properties_t secprops = { 0 };
+@@ -116,9 +162,9 @@
+ 
+     r = sasl_server_start(conn, sasl_mech, buf, len, &data, &len);
+     if (r != SASL_OK && r != SASL_CONTINUE) {
+-	saslerr(r, "starting SASL negotiation");
+-	printf("\n%s\n", sasl_errdetail(conn));
+-	exit(-1);
++        saslerr(r, "starting SASL negotiation");
++        printf("\n%s\n", sasl_errdetail(conn));
++        exit(-1);
+     }
+ 
+     while (r == SASL_CONTINUE) {
+@@ -126,12 +172,12 @@
+         len = 8192;
+         recv_string(sd, buf, &len, true);
+ 
+-	r = sasl_server_step(conn, buf, len, &data, &len);
+-	if (r != SASL_OK && r != SASL_CONTINUE) {
+-	    saslerr(r, "performing SASL negotiation");
+-	    printf("\n%s\n", sasl_errdetail(conn));
+-	    exit(-1);
+-	}
++        r = sasl_server_step(conn, buf, len, &data, &len);
++        if (r != SASL_OK && r != SASL_CONTINUE) {
++            saslerr(r, "performing SASL negotiation");
++            printf("\n%s\n", sasl_errdetail(conn));
++            exit(-1);
++        }
+     }
+ 
+     if (r != SASL_OK) exit(-1);
diff --git a/SOURCES/cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch b/SOURCES/cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch
new file mode 100644
index 0000000..c8c4a79
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch
@@ -0,0 +1,435 @@
+From 49e965f41257a0ed299c58a7cf1c120ddf944aaa Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 5 May 2020 14:51:36 -0400
+Subject: [PATCH] Add support for setting max ssf 0 to GSS-SPNEGO
+
+Bacport form this proposed PR (still open at bacport time):
+https://github.com/cyrusimap/cyrus-sasl/pull/603
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ m4/sasl2.m4          | 13 +++++++
+ plugins/gssapi.c     | 44 ++++++++++++++++++++-
+ tests/runtests.py    | 91 ++++++++++++++++++++++++++++++++++++++++----
+ tests/t_common.c     | 13 ++++---
+ tests/t_common.h     |  3 +-
+ tests/t_gssapi_cli.c | 25 ++++++++++--
+ tests/t_gssapi_srv.c | 28 +++++++++++---
+ 7 files changed, 194 insertions(+), 23 deletions(-)
+
+diff --git a/m4/sasl2.m4 b/m4/sasl2.m4
+index 56e0504..6effe99 100644
+--- a/m4/sasl2.m4
++++ b/m4/sasl2.m4
+@@ -287,6 +287,19 @@ if test "$gssapi" != no; then
+   AC_CHECK_FUNCS(gss_oid_equal)
+   LIBS="$cmu_save_LIBS"
+ 
++  cmu_save_LIBS="$LIBS"
++  LIBS="$LIBS $GSSAPIBASE_LIBS"
++  if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"; then
++    AC_CHECK_DECL(GSS_KRB5_CRED_NO_CI_FLAGS_X,
++                  [AC_DEFINE(HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X,1,
++                             [Define if your GSSAPI implementation supports GSS_KRB5_CRED_NO_CI_FLAGS_X])],,
++                  [
++                    AC_INCLUDES_DEFAULT
++                    #include <gssapi/gssapi_krb5.h>
++                    ])
++  fi
++  LIBS="$cmu_save_LIBS"
++
+   cmu_save_LIBS="$LIBS"
+   LIBS="$LIBS $GSSAPIBASE_LIBS"
+   AC_CHECK_FUNCS(gss_get_name_attribute)
+diff --git a/plugins/gssapi.c b/plugins/gssapi.c
+index 5d900c5..7480316 100644
+--- a/plugins/gssapi.c
++++ b/plugins/gssapi.c
+@@ -1783,7 +1783,49 @@ static int gssapi_client_mech_step(void *conn_context,
+ 		/* We want to try for privacy */
+ 		req_flags |= GSS_C_CONF_FLAG;
+ 	    }
+-	}
++#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
++        /* The krb5 mechanism automatically adds INTEG and CONF flags even when
++         * not specified, this has the effect of rendering explicit requests
++         * of no confidentiality and integrity via setting maxssf 0 moot.
++         * However to interoperate with Windows machines it needs to be
++         * possible to unset these flags as Windows machines refuse to allow
++         * two layers (say TLS and GSSAPI) to both provide these services.
++         * So if we do not suppress these flags a SASL/GSS-SPNEGO negotiation
++         * over, say, LDAPS will fail against Windows Servers */
++	} else if (params->props.max_ssf == 0) {
++            gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
++            if (client_creds == GSS_C_NO_CREDENTIAL) {
++                gss_OID_set_desc mechs = { 0 };
++                gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
++                if (text->mech_type != GSS_C_NO_OID) {
++                    mechs.count = 1;
++                    mechs.elements = text->mech_type;
++                    desired_mechs = &mechs;
++                }
++
++                maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME,
++                                            GSS_C_INDEFINITE, desired_mechs,
++                                            GSS_C_INITIATE,
++                                            &text->client_creds, NULL, NULL);
++                if (GSS_ERROR(maj_stat)) {
++                    sasl_gss_seterror(text->utils, maj_stat, min_stat);
++                    sasl_gss_free_context_contents(text);
++                    return SASL_FAIL;
++                }
++                client_creds = text->client_creds;
++            }
++
++            maj_stat = gss_set_cred_option(&min_stat, &client_creds,
++                                           (gss_OID)GSS_KRB5_CRED_NO_CI_FLAGS_X,
++                                            &empty_buffer);
++            if (GSS_ERROR(maj_stat)) {
++                sasl_gss_seterror(text->utils, maj_stat, min_stat);
++                sasl_gss_free_context_contents(text);
++                return SASL_FAIL;
++            }
++#endif
++        }
++
+ 
+ 	if (params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) {
+ 	    req_flags = req_flags |  GSS_C_DELEG_FLAG;
+diff --git a/tests/runtests.py b/tests/runtests.py
+index fc9cf24..4106401 100755
+--- a/tests/runtests.py
++++ b/tests/runtests.py
+@@ -6,6 +6,7 @@ import os
+ import shutil
+ import signal
+ import subprocess
++import sys
+ import time
+ from string import Template
+ 
+@@ -149,11 +150,12 @@ def gssapi_basic_test(kenv):
+                 srv.returncode, srv.stderr.read().decode('utf-8')))
+     except Exception as e:
+         print("FAIL: {}".format(e))
+-        return
++        return 1
+ 
+     print("PASS: CLI({}) SRV({})".format(
+         cli.stdout.read().decode('utf-8').strip(),
+         srv.stdout.read().decode('utf-8').strip()))
++    return 0
+ 
+ def gssapi_channel_binding_test(kenv):
+     try:
+@@ -178,11 +180,12 @@ def gssapi_channel_binding_test(kenv):
+                 srv.returncode, srv.stderr.read().decode('utf-8')))
+     except Exception as e:
+         print("FAIL: {}".format(e))
+-        return
++        return 1
+ 
+     print("PASS: CLI({}) SRV({})".format(
+         cli.stdout.read().decode('utf-8').strip(),
+         srv.stdout.read().decode('utf-8').strip()))
++    return 0
+ 
+ def gssapi_channel_binding_mismatch_test(kenv):
+     result = "FAIL"
+@@ -212,11 +215,70 @@ def gssapi_channel_binding_mismatch_test(kenv):
+                 cli.returncode, cli_err, srv.returncode, srv_err))
+     except Exception as e:
+         print("{}: {}".format(result, e))
+-        return
++        return 0
+ 
+     print("FAIL: This test should fail [CLI({}) SRV({})]".format(
+         cli.stdout.read().decode('utf-8').strip(),
+         srv.stdout.read().decode('utf-8').strip()))
++    return 1
++
++def gss_spnego_basic_test(kenv):
++    try:
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-N"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-N"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli.stderr.read().decode('utf-8'),
++                srv.returncode, srv.stderr.read().decode('utf-8')))
++    except Exception as e:
++        print("FAIL: {}".format(e))
++        return 1
++
++    print("PASS: CLI({}) SRV({})".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++    return 0
++
++def gss_spnego_zeromaxssf_test(kenv):
++    try:
++        srv = subprocess.Popen(["../tests/t_gssapi_srv", "-N", "-z"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        srv.stdout.readline() # Wait for srv to say it is ready
++        cli = subprocess.Popen(["../tests/t_gssapi_cli", "-N", "-z"],
++                               stdout=subprocess.PIPE,
++                               stderr=subprocess.PIPE, env=kenv)
++        try:
++            cli.wait(timeout=5)
++            srv.wait(timeout=5)
++        except Exception as e:
++            print("Failed on {}".format(e));
++            cli.kill()
++            srv.kill()
++        if cli.returncode != 0 or srv.returncode != 0:
++            raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
++                cli.returncode, cli.stderr.read().decode('utf-8'),
++                srv.returncode, srv.stderr.read().decode('utf-8')))
++    except Exception as e:
++        print("FAIL: {}".format(e))
++        return 1
++
++    print("PASS: CLI({}) SRV({})".format(
++        cli.stdout.read().decode('utf-8').strip(),
++        srv.stdout.read().decode('utf-8').strip()))
++    return 0
+ 
+ def gssapi_tests(testdir):
+     """ SASL/GSSAPI Tests """
+@@ -225,20 +287,32 @@ def gssapi_tests(testdir):
+     #print("KDC: {}, ENV: {}".format(kdc, kenv))
+     kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
+ 
++    err = 0
++
+     print('GSSAPI BASIC:')
+     print('    ', end='')
+-    gssapi_basic_test(kenv)
++    err += gssapi_basic_test(kenv)
+ 
+     print('GSSAPI CHANNEL BINDING:')
+     print('    ', end='')
+-    gssapi_channel_binding_test(kenv)
++    err += gssapi_channel_binding_test(kenv)
+ 
+     print('GSSAPI CHANNEL BINDING MISMTACH:')
+     print('    ', end='')
+-    gssapi_channel_binding_mismatch_test(kenv)
++    err += gssapi_channel_binding_mismatch_test(kenv)
++
++    print('GSS-SPNEGO BASIC:')
++    print('    ', end='')
++    err += gss_spnego_basic_test(kenv)
++
++    print('GSS-SPNEGO 0 MAXSSF:')
++    print('    ', end='')
++    err += gss_spnego_zeromaxssf_test(kenv)
+ 
+     os.killpg(kdc.pid, signal.SIGTERM)
+ 
++    return err
++
+ 
+ if __name__ == "__main__":
+ 
+@@ -253,4 +327,7 @@ if __name__ == "__main__":
+         shutil.rmtree(T)
+     os.makedirs(T)
+ 
+-    gssapi_tests(T)
++    err = gssapi_tests(T)
++    if err != 0:
++        print('{} test(s) FAILED'.format(err))
++        sys.exit(-1)
+diff --git a/tests/t_common.c b/tests/t_common.c
+index 478e6a1..f56098e 100644
+--- a/tests/t_common.c
++++ b/tests/t_common.c
+@@ -23,20 +23,21 @@ void send_string(int sd, const char *s, unsigned int l)
+     if (ret != l) s_error("send data", ret, l, errno);
+ }
+ 
+-void recv_string(int sd, char *buf, unsigned int *buflen)
++void recv_string(int sd, char *buf, unsigned int *buflen, bool allow_eof)
+ {
++    unsigned int bufsize = *buflen;
+     unsigned int l;
+     ssize_t ret;
+ 
++    *buflen = 0;
++
+     ret = recv(sd, &l, sizeof(l), MSG_WAITALL);
++    if (allow_eof && ret == 0) return;
+     if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
+ 
+-    if (l == 0) {
+-        *buflen = 0;
+-        return;
+-    }
++    if (l == 0) return;
+ 
+-    if (*buflen < l) s_error("recv len", l, *buflen, E2BIG);
++    if (bufsize < l) s_error("recv len", l, bufsize, E2BIG);
+ 
+     ret = recv(sd, buf, l, 0);
+     if (ret != l) s_error("recv data", ret, l, errno);
+diff --git a/tests/t_common.h b/tests/t_common.h
+index a10def1..be24a53 100644
+--- a/tests/t_common.h
++++ b/tests/t_common.h
+@@ -4,6 +4,7 @@
+ #include "config.h"
+ 
+ #include <errno.h>
++#include <stdbool.h>
+ #include <stdio.h>
+ #include <sys/socket.h>
+ 
+@@ -12,7 +13,7 @@
+ 
+ void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
+ void send_string(int sd, const char *s, unsigned int l);
+-void recv_string(int sd, char *buf, unsigned int *buflen);
++void recv_string(int sd, char *buf, unsigned int *buflen, bool allow_eof);
+ void saslerr(int why, const char *what);
+ int getpath(void *context __attribute__((unused)), const char **path);
+ void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in);
+diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
+index a44a3f5..d9eafe1 100644
+--- a/tests/t_gssapi_cli.c
++++ b/tests/t_gssapi_cli.c
+@@ -46,12 +46,21 @@ int main(int argc, char *argv[])
+     char cb_buf[256];
+     int sd;
+     int c, r;
++    const char *sasl_mech = "GSSAPI";
++    bool spnego = false;
++    bool zeromaxssf = false;
+ 
+-    while ((c = getopt(argc, argv, "c:")) != EOF) {
++    while ((c = getopt(argc, argv, "c:zN")) != EOF) {
+         switch (c) {
+         case 'c':
+             parse_cb(&cb, cb_buf, 256, optarg);
+             break;
++        case 'z':
++            zeromaxssf = true;
++            break;
++        case 'N':
++            spnego = true;
++            break;
+         default:
+             break;
+         }
+@@ -78,7 +87,17 @@ int main(int argc, char *argv[])
+         sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
+     }
+ 
+-    r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
++    if (spnego) {
++        sasl_mech = "GSS-SPNEGO";
++    }
++
++    if (zeromaxssf) {
++        /* set all security properties to 0 including maxssf */
++        sasl_security_properties_t secprops = { 0 };
++        sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
++    }
++
++    r = sasl_client_start(conn, sasl_mech, NULL, &data, &len, &chosenmech);
+     if (r != SASL_OK && r != SASL_CONTINUE) {
+ 	saslerr(r, "starting SASL negotiation");
+ 	printf("\n%s\n", sasl_errdetail(conn));
+@@ -90,7 +109,7 @@ int main(int argc, char *argv[])
+     while (r == SASL_CONTINUE) {
+         send_string(sd, data, len);
+         len = 8192;
+-        recv_string(sd, buf, &len);
++        recv_string(sd, buf, &len, false);
+ 
+ 	r = sasl_client_step(conn, buf, len, NULL, &data, &len);
+ 	if (r != SASL_OK && r != SASL_CONTINUE) {
+diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
+index ef1217f..448a218 100644
+--- a/tests/t_gssapi_srv.c
++++ b/tests/t_gssapi_srv.c
+@@ -56,12 +56,21 @@ int main(int argc, char *argv[])
+     unsigned char cb_buf[256];
+     int sd;
+     int c, r;
++    const char *sasl_mech = "GSSAPI";
++    bool spnego = false;
++    bool zeromaxssf = false;
+ 
+-    while ((c = getopt(argc, argv, "c:")) != EOF) {
++    while ((c = getopt(argc, argv, "c:zN")) != EOF) {
+         switch (c) {
+         case 'c':
+             parse_cb(&cb, cb_buf, 256, optarg);
+             break;
++        case 'z':
++            zeromaxssf = true;
++            break;
++        case 'N':
++            spnego = true;
++            break;
+         default:
+             break;
+         }
+@@ -90,12 +99,22 @@ int main(int argc, char *argv[])
+         sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
+     }
+ 
++    if (spnego) {
++        sasl_mech = "GSS-SPNEGO";
++    }
++
++    if (zeromaxssf) {
++        /* set all security properties to 0 including maxssf */
++        sasl_security_properties_t secprops = { 0 };
++        sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
++    }
++
+     sd = setup_socket();
+ 
+     len = 8192;
+-    recv_string(sd, buf, &len);
++    recv_string(sd, buf, &len, false);
+ 
+-    r = sasl_server_start(conn, "GSSAPI", buf, len, &data, &len);
++    r = sasl_server_start(conn, sasl_mech, buf, len, &data, &len);
+     if (r != SASL_OK && r != SASL_CONTINUE) {
+ 	saslerr(r, "starting SASL negotiation");
+ 	printf("\n%s\n", sasl_errdetail(conn));
+@@ -105,7 +124,7 @@ int main(int argc, char *argv[])
+     while (r == SASL_CONTINUE) {
+         send_string(sd, data, len);
+         len = 8192;
+-        recv_string(sd, buf, &len);
++        recv_string(sd, buf, &len, true);
+ 
+ 	r = sasl_server_step(conn, buf, len, &data, &len);
+ 	if (r != SASL_OK && r != SASL_CONTINUE) {
+@@ -113,7 +132,6 @@ int main(int argc, char *argv[])
+ 	    printf("\n%s\n", sasl_errdetail(conn));
+ 	    exit(-1);
+ 	}
+-
+     }
+ 
+     if (r != SASL_OK) exit(-1);
+-- 
+2.18.2
+
diff --git a/SOURCES/cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch b/SOURCES/cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch
new file mode 100644
index 0000000..d5e1334
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch
@@ -0,0 +1,42 @@
+From ec070b2e83a4ee698c08d6d68c205aea4d90b0bb Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 5 May 2020 14:31:10 -0400
+Subject: [PATCH] Emit debug log only in case of errors
+
+Backport of commit id:
+ccc5e547d4b40ee2b182a9945f8f6cc10b4fdf48
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ plugins/gssapi.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/plugins/gssapi.c b/plugins/gssapi.c
+index 7480316..6bcd78e 100644
+--- a/plugins/gssapi.c
++++ b/plugins/gssapi.c
+@@ -1444,9 +1444,6 @@ gssapi_server_mech_step(void *conn_context,
+ 
+     if (text == NULL) return SASL_BADPROT;
+ 
+-    params->utils->log(params->utils->conn, SASL_LOG_DEBUG,
+-		       "GSSAPI server step %d\n", text->state);
+-
+     switch (text->state) {
+ 
+     case SASL_GSSAPI_STATE_AUTHNEG:
+@@ -1496,8 +1493,10 @@ gssapi_server_mech_step(void *conn_context,
+ 	}
+ 
+ 	oparams->doneflag = 1;
++    } else {
++        params->utils->log(params->utils->conn, SASL_LOG_DEBUG,
++		           "GSSAPI server step failed: %d\n", text->state);
+     }
+-    
+     return ret;
+ }
+ 
+-- 
+2.18.2
+
diff --git a/SOURCES/cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch b/SOURCES/cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch
new file mode 100644
index 0000000..cc999e5
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch
@@ -0,0 +1,569 @@
+diff -up cyrus-sasl-2.1.27/configure.ac.frombdb cyrus-sasl-2.1.27/configure.ac
+--- cyrus-sasl-2.1.27/configure.ac.frombdb	2021-06-04 13:02:07.790112263 +0200
++++ cyrus-sasl-2.1.27/configure.ac	2021-06-04 13:02:07.798112327 +0200
+@@ -1091,6 +1091,9 @@ AC_SUBST(SASL_STATIC_SRCS)
+ AC_SUBST(SASL_STATIC_OBJS)
+ AC_SUBST(SASL_STATIC_LIBS)
+ 
++CYRUS_BERKELEY_DB_STATIC_LIB()
++AC_SUBST(BDB_STATIC_LIBADD)
++
+ AC_ARG_WITH(plugindir, [  --with-plugindir=DIR    set the directory where plugins will
+                           be found [[LIBDIR/sasl2]] ],
+   plugindir=$withval,
+diff -up cyrus-sasl-2.1.27/m4/berkdb.m4.frombdb cyrus-sasl-2.1.27/m4/berkdb.m4
+--- cyrus-sasl-2.1.27/m4/berkdb.m4.frombdb	2016-01-29 18:35:35.000000000 +0100
++++ cyrus-sasl-2.1.27/m4/berkdb.m4	2021-06-04 13:02:07.798112327 +0200
+@@ -286,3 +286,10 @@ AC_DEFUN([CYRUS_BERKELEY_DB_CHK],
+ 
+ 	CPPFLAGS=$cmu_save_CPPFLAGS
+ ])
++
++AC_DEFUN([CYRUS_BERKELEY_DB_STATIC_LIB],
++[
++BDB_STATIC_LIBADD="/dev/null -lpthread"
++AC_CHECK_FILE([/usr/lib64/libdb-5.3.a],[BDB_STATIC_LIBADD="/usr/lib64/libdb-5.3.a -lpthread "],[])
++AC_CHECK_FILE([/usr/lib/libdb-5.3.a],[BDB_STATIC_LIBADD="/usr/lib/libdb-5.3.a -lpthread"],[])
++])
+diff -up cyrus-sasl-2.1.27/m4/sasldb.m4.frombdb cyrus-sasl-2.1.27/m4/sasldb.m4
+--- cyrus-sasl-2.1.27/m4/sasldb.m4.frombdb	2017-07-13 20:45:19.000000000 +0200
++++ cyrus-sasl-2.1.27/m4/sasldb.m4	2021-06-04 13:02:07.798112327 +0200
+@@ -111,7 +111,7 @@ AC_MSG_RESULT($dblib)
+ SASL_DB_BACKEND="db_${dblib}.lo"
+ SASL_DB_BACKEND_STATIC="db_${dblib}.o allockey.o"
+ SASL_DB_BACKEND_STATIC_SRCS="\$(top_srcdir)/sasldb/db_${dblib}.c \$(top_srcdir)/sasldb/allockey.c"
+-SASL_DB_UTILS="saslpasswd2 sasldblistusers2"
++SASL_DB_UTILS="cyrusbdb2current saslpasswd2 sasldblistusers2"
+ SASL_DB_MANS="saslpasswd2.8 sasldblistusers2.8"
+ 
+ case "$dblib" in
+diff -up cyrus-sasl-2.1.27/sasldb/db_gdbm.c.frombdb cyrus-sasl-2.1.27/sasldb/db_gdbm.c
+--- cyrus-sasl-2.1.27/sasldb/db_gdbm.c.frombdb	2017-07-13 14:34:03.000000000 +0200
++++ cyrus-sasl-2.1.27/sasldb/db_gdbm.c	2021-06-04 13:04:24.098206887 +0200
+@@ -67,6 +67,7 @@ int _sasldb_getdata(const sasl_utils_t *
+   void *cntxt;
+   sasl_getopt_t *getopt;
+   const char *path = SASL_DB_PATH;
++  int fetch_errno = 0;
+ 
+   if (!utils) return SASL_BADPARAM;
+   if (!authid || !propName || !realm || !out || !max_out) {
+@@ -99,6 +100,9 @@ int _sasldb_getdata(const sasl_utils_t *
+   }
+   db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
+   if (! db) {
++      utils->log(conn, SASL_LOG_ERR,
++		 "SASL error opening password file. "
++		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
+       utils->seterror(cntxt, 0, "Could not open %s: gdbm_errno=%d",
+ 		      path, gdbm_errno);
+       result = SASL_FAIL;
+@@ -107,9 +111,10 @@ int _sasldb_getdata(const sasl_utils_t *
+   gkey.dptr = key;
+   gkey.dsize = key_len;
+   gvalue = gdbm_fetch(db, gkey);
++  fetch_errno = gdbm_errno;
+   gdbm_close(db);
+   if (! gvalue.dptr) {
+-      if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
++      if (fetch_errno == GDBM_ITEM_NOT_FOUND) {
+           utils->seterror(conn, SASL_NOLOG,
+ 			  "user: %s@%s property: %s not found in %s",
+ 			  authid, realm, propName, path);
+@@ -186,7 +191,8 @@ int _sasldb_putdata(const sasl_utils_t *
+   if (! db) {
+       utils->log(conn, SASL_LOG_ERR,
+ 		 "SASL error opening password file. "
+-		 "Do you have write permissions?\n");
++		 "Do you have write permissions?\n"
++		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
+       utils->seterror(conn, 0, "Could not open %s for write: gdbm_errno=%d",
+                      path, gdbm_errno);
+       result = SASL_FAIL;
+@@ -298,6 +304,9 @@ sasldb_handle _sasldb_getkeyhandle(const
+     db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
+ 
+     if(!db) {
++        utils->log(conn, SASL_LOG_ERR,
++		 "SASL error opening password file. "
++		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
+         utils->seterror(conn, 0, "Could not open %s: gdbm_errno=%d",
+ 			 path, gdbm_errno);
+ 	return NULL;
+diff -up cyrus-sasl-2.1.27/utils/cyrusbdb2current.8.frombdb cyrus-sasl-2.1.27/utils/cyrusbdb2current.8
+--- cyrus-sasl-2.1.27/utils/cyrusbdb2current.8.frombdb	2021-06-04 13:02:07.798112327 +0200
++++ cyrus-sasl-2.1.27/utils/cyrusbdb2current.8	2021-06-04 13:02:07.798112327 +0200
+@@ -0,0 +1,159 @@
++.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40)
++.\"
++.\" Standard preamble:
++.\" ========================================================================
++.de Sp \" Vertical space (when we can't use .PP)
++.if t .sp .5v
++.if n .sp
++..
++.de Vb \" Begin verbatim text
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve \" End verbatim text
++.ft R
++.fi
++..
++.\" Set up some character translations and predefined strings.  \*(-- will
++.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
++.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
++.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
++.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
++.\" nothing in troff, for use with C<>.
++.tr \(*W-
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.ie n \{\
++.    ds -- \(*W-
++.    ds PI pi
++.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
++.    ds L" ""
++.    ds R" ""
++.    ds C` ""
++.    ds C' ""
++'br\}
++.el\{\
++.    ds -- \|\(em\|
++.    ds PI \(*p
++.    ds L" ``
++.    ds R" ''
++.    ds C`
++.    ds C'
++'br\}
++.\"
++.\" Escape single quotes in literal strings from groff's Unicode transform.
++.ie \n(.g .ds Aq \(aq
++.el       .ds Aq '
++.\"
++.\" If the F register is >0, we'll generate index entries on stderr for
++.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
++.\" entries marked with X<> in POD.  Of course, you'll have to process the
++.\" output yourself in some meaningful fashion.
++.\"
++.\" Avoid warning from groff about undefined register 'F'.
++.de IX
++..
++.nr rF 0
++.if \n(.g .if rF .nr rF 1
++.if (\n(rF:(\n(.g==0)) \{\
++.    if \nF \{\
++.        de IX
++.        tm Index:\\$1\t\\n%\t"\\$2"
++..
++.        if !\nF==2 \{\
++.            nr % 0
++.            nr F 2
++.        \}
++.    \}
++.\}
++.rr rF
++.\"
++.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
++.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
++.    \" fudge factors for nroff and troff
++.if n \{\
++.    ds #H 0
++.    ds #V .8m
++.    ds #F .3m
++.    ds #[ \f1
++.    ds #] \fP
++.\}
++.if t \{\
++.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++.    ds #V .6m
++.    ds #F 0
++.    ds #[ \&
++.    ds #] \&
++.\}
++.    \" simple accents for nroff and troff
++.if n \{\
++.    ds ' \&
++.    ds ` \&
++.    ds ^ \&
++.    ds , \&
++.    ds ~ ~
++.    ds /
++.\}
++.if t \{\
++.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.\}
++.    \" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++.    \" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++.    \" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++.    ds : e
++.    ds 8 ss
++.    ds o a
++.    ds d- d\h'-1'\(ga
++.    ds D- D\h'-1'\(hy
++.    ds th \o'bp'
++.    ds Th \o'LP'
++.    ds ae ae
++.    ds Ae AE
++.\}
++.rm #[ #] #H #V #F C
++.\" ========================================================================
++.\"
++.IX Title "CYRUSBDB2CURRENT 1"
++.TH CYRUSBDB2CURRENT 1 "2021-04-28" "perl v5.30.3" "User Contributed Perl Documentation"
++.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
++.\" way too many mistakes in technical documents.
++.if n .ad l
++.nh
++.SH "NAME"
++cyrusbdb2current \- command\-line utility converting the SASLDB database from
++BerkeleyDB to the database format currently used bys sasldb.
++.SH "SYNOPSIS"
++.IX Header "SYNOPSIS"
++cyrusbdb2current <sasldb_old_path> <sasldb_new_path>
++.SH "DESCRIPTION"
++.IX Header "DESCRIPTION"
++\&\fBcyrusbdb2current\fR converts the current sasldb database from BerkeleyDB format to the
++currently used database format. It is \fB\s-1STRONGLY RECOMMENDED\s0\fR to make a backup
++of the current database before the conversion.
++.PP
++We expect that the old path is \fB/etc/sasldb2\fR and the new one is
++\&\fB/etc/sasl2/sasldb2\fR
++.SH "SEE ALSO"
++.IX Header "SEE ALSO"
++\&\fBsaslpasswd2\fR\|(8)
++.PP
++rfc4422 \- Simple Authentication and Security Layer (\s-1SASL\s0)
+diff -up cyrus-sasl-2.1.27/utils/cyrusbdb2current.c.frombdb cyrus-sasl-2.1.27/utils/cyrusbdb2current.c
+--- cyrus-sasl-2.1.27/utils/cyrusbdb2current.c.frombdb	2021-06-04 13:02:07.798112327 +0200
++++ cyrus-sasl-2.1.27/utils/cyrusbdb2current.c	2021-06-04 13:02:07.798112327 +0200
+@@ -0,0 +1,282 @@
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++
++#include <sasl.h>
++#include <saslplug.h>
++#include "../sasldb/sasldb.h"
++
++/* Cheating to make the utils work out right */
++extern const sasl_utils_t *sasl_global_utils;
++sasl_conn_t *globalconn;
++
++typedef void *listcb_t(const char *, const char *, const char *,
++		       const char *, unsigned);
++
++void listusers_cb(const char *authid, const char *realm,
++		  const char *propName, const char *secret,
++		  unsigned seclen)
++{
++    if (!authid || !propName || !realm) {
++	fprintf(stderr,"userlist callback has bad param");
++	return;
++    }
++
++    /* the entries that just say the mechanism exists */
++    if (strlen(authid)==0) return;
++
++    printf("Converting: %s@%s (%s)...",authid,realm,propName);
++
++    _sasldb_putdata(sasl_global_utils, globalconn,
++		    authid, realm, propName,
++		    secret, seclen);
++
++    printf("ok\n");
++}
++
++/*
++ * List all users in database
++ */
++
++#include <db.h>
++
++#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
++/*
++ * Open the database
++ *
++ */
++static int berkeleydb_open(const char *path,DB **mbdb)
++{
++    int ret;
++
++#if DB_VERSION_FULL < 0x03000000
++    ret = db_open(path, DB_HASH, DB_CREATE, 0664, NULL, NULL, mbdb);
++#else /* DB_VERSION_FULL < 0x03000000 */
++    ret = db_create(mbdb, NULL, 0);
++    if (ret == 0 && *mbdb != NULL)
++    {
++#if DB_VERSION_FULL >= 0x04010000
++	ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664);
++#else
++	ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664);
++#endif
++	if (ret != 0)
++	{
++	    (void) (*mbdb)->close(*mbdb, 0);
++	    *mbdb = NULL;
++	}
++    }
++#endif /* DB_VERSION_FULL < 0x03000000 */
++
++    if (ret != 0) {
++	fprintf(stderr,"Error opening password file %s\n", path);
++	return SASL_FAIL;
++    }
++
++    return SASL_OK;
++}
++
++/*
++ * Close the database
++ *
++ */
++
++static void berkeleydb_close(DB *mbdb)
++{
++    int ret;
++    
++    ret = mbdb->close(mbdb, 0);
++    if (ret!=0) {
++	fprintf(stderr,"error closing sasldb: %s",
++		db_strerror(ret));
++    }
++}
++
++int listusers(const char *path, listcb_t *cb)
++{
++    int result;
++    DB *mbdb = NULL;
++    DBC *cursor;
++    DBT key, data;
++
++    /* open the db */
++    result=berkeleydb_open(path, &mbdb);
++    if (result!=SASL_OK) goto cleanup;
++
++    /* make cursor */
++#if DB_VERSION_FULL < 0x03060000
++    result = mbdb->cursor(mbdb, NULL,&cursor); 
++#else
++    result = mbdb->cursor(mbdb, NULL,&cursor, 0); 
++#endif /* DB_VERSION_FULL < 0x03060000 */
++
++    if (result!=0) {
++	fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result));
++      result = SASL_FAIL;
++      goto cleanup;
++    }
++
++    memset(&key,0, sizeof(key));
++    memset(&data,0,sizeof(data));
++
++    /* loop thru */
++    result = cursor->c_get(cursor, &key, &data,
++			   DB_FIRST);
++
++    while (result != DB_NOTFOUND)
++    {
++	char *authid;
++	char *realm;
++	char *tmp;
++	unsigned int len;
++	char prop[1024];
++	int numnulls = 0;
++	unsigned int lup;
++
++	/* make sure there are exactly 2 null's */
++	for (lup=0;lup<key.size;lup++)
++	    if (((char *)key.data)[lup]=='\0')
++		numnulls++;
++
++	if (numnulls != 2) {
++	    fprintf(stderr,"warning: probable database corruption\n");
++	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
++	    continue;
++	}
++
++	authid = key.data;
++	realm  = authid + strlen(authid)+1;
++	tmp    = realm + strlen(realm)+1;
++	len = key.size - (tmp - authid);
++
++	/* make sure we have enough space of prop */
++	if (len >=sizeof(prop)) {
++	    fprintf(stderr,"warning: absurdly long prop name\n");
++	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
++	    continue;
++	}
++
++	memcpy(prop, tmp, key.size - (tmp - ((char *)key.data)));
++	prop[key.size - (tmp - ((char *)key.data))] = '\0';
++
++	if (*authid) {
++	    /* don't check return values */
++	    cb(authid,realm,prop,data.data,data.size);
++	}
++
++	result = cursor->c_get(cursor, &key, &data, DB_NEXT);
++    }
++
++    if (result != DB_NOTFOUND) {
++	fprintf(stderr,"failure: %s\n",db_strerror(result));
++	result = SASL_FAIL;
++	goto cleanup;
++    }
++
++    result = cursor->c_close(cursor);
++    if (result != 0) {
++        result = SASL_FAIL;
++        goto cleanup;
++    }
++
++    result = SASL_OK;
++
++ cleanup:
++
++    if (mbdb != NULL) berkeleydb_close(mbdb);
++    return result;
++}
++
++
++char *db = NULL, *db_new=NULL;
++
++int good_getopt(void *context __attribute__((unused)), 
++		const char *plugin_name __attribute__((unused)), 
++		const char *option,
++		const char **result,
++		unsigned *len)
++{
++    if (db_new && !strcmp(option, "sasldb_path")) {
++	*result = db_new;
++	if (len)
++	    *len = strlen(db_new);
++	return SASL_OK;
++    }
++
++    return SASL_FAIL;
++}
++
++static struct sasl_callback goodsasl_cb[] = {
++    { SASL_CB_GETOPT, (int (*)(void))&good_getopt, NULL },
++    { SASL_CB_LIST_END, NULL, NULL }
++};
++
++int main(int argc, char **argv)
++{
++    int result;
++    FILE *f;
++
++    if (argc != 3) {
++	fprintf(stderr, "Usage: cyrusbdb2current old_sasldb new_sasldb\n");
++	fprintf(stderr, "old_sasldb is presumably /etc/sasldb2\n");
++       	fprintf(stderr, "new_sasldb is presumably /etc/sasl2/sasldb2\n");
++	return 1;
++    }
++
++    db = argv[1];
++    db_new = argv[2];
++
++    if (strcmp(db, db_new) == 0) {
++	fprintf(stderr, "Old and new files should be different\n");
++	return 1;
++    }
++
++
++    f = fopen(db_new, "rb");
++    if (f != NULL) {
++	fprintf(stderr, "The specified target file %s already exists\n", db_new);
++	fclose(f);
++	return 1;
++    }
++
++    result = sasl_server_init(goodsasl_cb, "dbconverter");
++    if (result != SASL_OK) {
++	fprintf(stderr, "couldn't init saslv2\n");
++	return 1;
++    }
++
++    result = sasl_server_new("sasldb",
++			     "localhost",
++			     NULL,
++			     NULL,
++			     NULL,
++			     NULL,
++			     0,
++			     &globalconn);
++    if (result != SASL_OK) {
++	fprintf(stderr, "couldn't create globalconn\n");
++	return 1;
++    }
++
++    if(_sasl_check_db(sasl_global_utils,globalconn) != SASL_OK) {
++	fprintf(stderr, "target DB %s is not OK\n", db_new);
++	return 1;
++    }
++
++    printf("\nThis program will take the sasldb file specified on the\n"
++           "command line and convert it to a new sasldb specified\n"
++           "on the command line. It is STRONGLY RECOMMENDED that you\n"
++           "backup sasldb before allowing this program to run\n\n"
++	   "We are going to convert %s and our output will be in %s\n\n"
++           "Press return to continue\n", db, db_new);
++
++    getchar();
++
++    listusers(db, (listcb_t *) &listusers_cb);
++
++    sasl_dispose(&globalconn);
++    sasl_done();
++
++    exit(0);
++}
+diff -up cyrus-sasl-2.1.27/utils/Makefile.am.frombdb cyrus-sasl-2.1.27/utils/Makefile.am
+--- cyrus-sasl-2.1.27/utils/Makefile.am.frombdb	2018-10-05 16:40:16.000000000 +0200
++++ cyrus-sasl-2.1.27/utils/Makefile.am	2021-06-04 13:02:07.798112327 +0200
+@@ -46,14 +46,14 @@ all_sasl_libs = ../lib/libsasl2.la $(SAS
+ all_sasl_static_libs = ../lib/.libs/libsasl2.a $(SASL_DB_LIB) $(LIB_SOCKET) $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(SASL_KRB_LIB) $(LIB_DES) $(PLAIN_LIBS) $(SRP_LIBS) $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE)
+ 
+ sbin_PROGRAMS = @SASL_DB_UTILS@ @SMTPTEST_PROGRAM@ pluginviewer
+-EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest pluginviewer
++EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest pluginviewer cyrusbdb2current
+ 
+ noinst_PROGRAMS = dbconverter-2
+ 
+ if NO_SASL_DB_MANS
+ man_MANS = 
+ else
+-man_MANS = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8
++man_MANS = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8 cyrusbdb2current.8
+ endif
+ 
+ saslpasswd2_LDADD = ../sasldb/libsasldb.la $(all_sasl_libs)
+@@ -63,6 +63,7 @@ sasldblistusers2_SOURCES = sasldblistuse
+ dbconverter_2_LDADD = ../sasldb/libsasldb.la $(all_sasl_libs)
+ pluginviewer_LDADD = $(all_sasl_libs)
+ pluginviewer_SOURCES = pluginviewer.c
++cyrusbdb2current_LDADD = ../sasldb/libsasldb.la @BDB_STATIC_LIBADD@ $(all_sasl_libs)
+ 
+ testsuite_LDADD = $(all_sasl_libs) @DMALLOC_LIBS@
+ 
diff --git a/SOURCES/cyrus-sasl-2.1.27-coverity.patch b/SOURCES/cyrus-sasl-2.1.27-coverity.patch
new file mode 100644
index 0000000..871ea10
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-coverity.patch
@@ -0,0 +1,56 @@
+diff -up cyrus-sasl-2.1.27/include/makemd5.c.coverity cyrus-sasl-2.1.27/include/makemd5.c
+--- cyrus-sasl-2.1.27/include/makemd5.c.coverity	2021-04-12 15:10:25.421431535 +0200
++++ cyrus-sasl-2.1.27/include/makemd5.c	2021-04-12 15:56:46.752827737 +0200
+@@ -107,7 +107,6 @@ my_strupr(char *s)
+     }	
+ }
+ 
+-
+ #define BITSIZE(TYPE)						\
+ {								\
+     int b = 0; TYPE x = 1, zero = 0; char *pre = "U";		\
+@@ -129,6 +128,8 @@ my_strupr(char *s)
+ static void
+ try_signed(FILE *f, int len)
+ {
++/* Local macros for not-installed program. No coverity/compiler issues! */
++#pragma GCC diagnostic ignored "-Wformat-overflow"
+ #ifdef HAVE_INT8_T
+     BITSIZE(int8_t);
+ #endif
+@@ -149,6 +150,7 @@ try_signed(FILE *f, int len)
+     BITSIZE(long long);
+ #endif
+     fprintf(f, "/* There is no %d bit type */\n", len);
++#pragma GCC pop
+ }
+ 
+ static void
+diff -up cyrus-sasl-2.1.27/saslauthd/lak.c.coverity cyrus-sasl-2.1.27/saslauthd/lak.c
+--- cyrus-sasl-2.1.27/saslauthd/lak.c.coverity	2018-11-08 18:29:57.000000000 +0100
++++ cyrus-sasl-2.1.27/saslauthd/lak.c	2021-04-12 15:10:25.433431630 +0200
+@@ -337,9 +337,9 @@ static int lak_config_read(
+          EMPTY(conf->group_search_base) )
+         strlcpy(conf->group_search_base, conf->search_base, LAK_DN_LEN);
+         
+-	fclose(infile);
++    fclose(infile);
+ 
+-	return LAK_OK;
++    return LAK_OK;
+ }
+ 
+ static int lak_config_int(
+diff -up cyrus-sasl-2.1.27/saslauthd/saslauthd-main.c.coverity cyrus-sasl-2.1.27/saslauthd/saslauthd-main.c
+--- cyrus-sasl-2.1.27/saslauthd/saslauthd-main.c.coverity	2018-01-19 15:13:40.000000000 +0100
++++ cyrus-sasl-2.1.27/saslauthd/saslauthd-main.c	2021-04-12 15:10:25.433431630 +0200
+@@ -833,7 +833,8 @@ void detach_tty() {
+     }
+     
+     logger(L_INFO, L_FUNC, "master pid is: %lu", (unsigned long)master_pid);
+-    
++    /* null_fd expected to be more than 2, so it is closed after dups, no leaks occur */
++    /* coverity[leaked_handle : FALSE]*/
+     return;
+ }
+ 
diff --git a/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch b/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch
new file mode 100644
index 0000000..d61130f
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch
@@ -0,0 +1,544 @@
+diff -uPr cyrus-sasl-2.1.27/plugins/digestmd5.c cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c
+--- cyrus-sasl-2.1.27/plugins/digestmd5.c	2021-09-30 17:13:06.573093526 -0400
++++ cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c	2021-09-30 17:26:31.818378442 -0400
+@@ -80,6 +80,12 @@
+ # endif
+ #endif /* WITH_DES */
+ 
++/* legacy provider with openssl 3.0 */
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++#  include <openssl/provider.h>
++#  include <openssl/crypto.h>
++#endif
++
+ #ifdef WIN32
+ # include <winsock2.h>
+ #else /* Unix */
+@@ -170,6 +176,12 @@
+ 
+ typedef struct cipher_context cipher_context_t;
+ 
++typedef struct crypto_context {
++    void *libctx;
++    cipher_context_t *enc_ctx;
++    cipher_context_t *dec_ctx;
++} crypto_context_t;
++
+ /* cached auth info used for fast reauth */
+ typedef struct reauth_entry {
+     char *authid;
+@@ -254,12 +266,12 @@
+     decode_context_t decode_context;
+ 
+     /* if privacy mode is used use these functions for encode and decode */
++    char *cipher_name;
+     cipher_function_t *cipher_enc;
+     cipher_function_t *cipher_dec;
+     cipher_init_t *cipher_init;
+     cipher_free_t *cipher_free;
+-    struct cipher_context *cipher_enc_context;
+-    struct cipher_context *cipher_dec_context;
++    crypto_context_t crypto;
+ } context_t;
+ 
+ struct digest_cipher {
+@@ -888,7 +900,7 @@
+ 		    char *output,
+ 		    unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
++    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
+     int padding, p;
+     
+     des_ede2_cbc_encrypt((void *) input,
+@@ -925,7 +937,7 @@
+ 		    char *output,
+ 		    unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
++    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
+     int len;
+     int paddinglen;
+     
+@@ -973,7 +985,7 @@
+ 	return SASL_FAIL;
+     memcpy(c->ivec, ((char *) enckey) + 8, 8);
+ 
+-    text->cipher_enc_context = (cipher_context_t *) c;
++    text->crypto.enc_ctx = (cipher_context_t *) c;
+ 
+     /* setup dec context */
+     c++;
+@@ -987,7 +999,7 @@
+     
+     memcpy(c->ivec, ((char *) deckey) + 8, 8);
+ 
+-    text->cipher_dec_context = (cipher_context_t *) c;
++    text->crypto.dec_ctx = (cipher_context_t *) c;
+     
+     return SASL_OK;
+ }
+@@ -1006,7 +1018,7 @@
+ 		   char *output,
+ 		   unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
++    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
+     int p, padding = 0;
+     
+     des_cbc_encrypt((void *) input,
+@@ -1046,7 +1058,7 @@
+ 		   char *output,
+ 		   unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
++    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
+     int len;
+     int paddinglen;
+   
+@@ -1093,7 +1105,7 @@
+ 
+     memcpy(c->ivec, ((char *) enckey) + 8, 8);
+     
+-    text->cipher_enc_context = (cipher_context_t *) c;
++    text->crypto.enc_ctx = (cipher_context_t *) c;
+ 
+     /* setup dec context */
+     c++;
+@@ -1102,60 +1114,139 @@
+ 
+     memcpy(c->ivec, ((char *) deckey) + 8, 8);
+     
+-    text->cipher_dec_context = (cipher_context_t *) c;
++    text->crypto.dec_ctx = (cipher_context_t *) c;
+ 
+     return SASL_OK;
+ }
+ 
+ static void free_des(context_t *text)
+ {
+-    /* free des contextss. only cipher_enc_context needs to be free'd,
+-       since cipher_dec_context was allocated at the same time. */
+-    if (text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
++    /* free des contextss. only enc_ctx needs to be free'd,
++       since dec_cxt was allocated at the same time. */
++    if (text->crypto.enc_ctx) {
++        text->utils->free(text->crypto.enc_ctx);
++    }
+ }
+ 
+ #endif /* WITH_DES */
+ 
+ #ifdef WITH_RC4
+-#ifdef HAVE_OPENSSL
+ #include <openssl/evp.h>
+ 
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++typedef struct ossl3_library_context {
++    OSSL_LIB_CTX *libctx;
++    OSSL_PROVIDER *legacy_provider;
++    OSSL_PROVIDER *default_provider;
++} ossl3_context_t;
++
++static int init_ossl3_ctx(context_t *text)
++{
++    ossl3_context_t *ctx = text->utils->malloc(sizeof(ossl3_context_t));
++    if (!ctx) return SASL_NOMEM;
++
++    ctx->libctx = OSSL_LIB_CTX_new();
++    if (!ctx->libctx) {
++        text->utils->free(ctx);
++        return SASL_FAIL;
++    }
++
++    /* Load both legacy and default provider as both may be needed */
++    /* if they fail keep going and an error will be raised when we try to
++     * fetch the cipher later */
++    ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
++    ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
++    text->crypto.libctx = (void *)ctx;
++
++    return SASL_OK;
++}
++
++static void free_ossl3_ctx(context_t *text)
++{
++    ossl3_context_t *ctx;
++
++    if (!text->crypto.libctx) return;
++
++    ctx = (ossl3_context_t *)text->crypto.libctx;
++
++    if (ctx->legacy_provider) OSSL_PROVIDER_unload(ctx->legacy_provider);
++    if (ctx->default_provider) OSSL_PROVIDER_unload(ctx->default_provider);
++    if (ctx->libctx) OSSL_LIB_CTX_free(ctx->libctx);
++
++    text->utils->free(ctx);
++    text->crypto.libctx = NULL;
++}
++#endif
++
+ static void free_rc4(context_t *text)
+ {
+-    if (text->cipher_enc_context) {
+-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_enc_context);
+-        text->cipher_enc_context = NULL;
+-    }
+-    if (text->cipher_dec_context) {
+-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_dec_context);
+-        text->cipher_dec_context = NULL;
++    if (text->crypto.enc_ctx) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.enc_ctx);
++        text->crypto.enc_ctx = NULL;
++    }
++    if (text->crypto.dec_ctx) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.dec_ctx);
++        text->crypto.dec_ctx = NULL;
+     }
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++    free_ossl3_ctx(text);
++#endif
+ }
+ 
+ static int init_rc4(context_t *text,
+ 		    unsigned char enckey[16],
+ 		    unsigned char deckey[16])
+ {
++    const EVP_CIPHER *cipher;
+     EVP_CIPHER_CTX *ctx;
+     int rc;
+ 
+-    ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL) return SASL_NOMEM;
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++    ossl3_context_t *ossl3_ctx;
+ 
+-    rc = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, enckey, NULL);
+-    if (rc != 1) return SASL_FAIL;
++    rc = init_ossl3_ctx(text);
++    if (rc != SASL_OK) return rc;
++
++    ossl3_ctx = (ossl3_context_t *)text->crypto.libctx;
++    cipher = EVP_CIPHER_fetch(ossl3_ctx->libctx, "RC4", "");
++#else
++    cipher = EVP_rc4();
++#endif
+ 
+-    text->cipher_enc_context = (void *)ctx;
+ 
+     ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL) return SASL_NOMEM;
++    if (ctx == NULL) {
++        rc = SASL_NOMEM;
++        goto done;
++    }
+ 
+-    rc = EVP_DecryptInit_ex(ctx, EVP_rc4(), NULL, deckey, NULL);
+-    if (rc != 1) return SASL_FAIL;
++    rc = EVP_EncryptInit_ex(ctx, cipher, NULL, enckey, NULL);
++    if (rc != 1) {
++        rc = SASL_FAIL;
++        goto done;
++    }
++    text->crypto.enc_ctx = (void *)ctx;
+ 
+-    text->cipher_dec_context = (void *)ctx;
++    ctx = EVP_CIPHER_CTX_new();
++    if (ctx == NULL) {
++        rc = SASL_NOMEM;
++        goto done;
++    }
+ 
+-    return SASL_OK;
++    rc = EVP_DecryptInit_ex(ctx, cipher, NULL, deckey, NULL);
++    if (rc != 1) {
++        rc = SASL_FAIL;
++        goto done;
++    }
++    text->crypto.dec_ctx = (void *)ctx;
++
++    rc = SASL_OK;
++
++done:
++    if (rc != SASL_OK) {
++        free_rc4(text);
++    }
++    return rc;
+ }
+ 
+ static int dec_rc4(context_t *text,
+@@ -1169,14 +1260,14 @@
+     int rc;
+ 
+     /* decrypt the text part & HMAC */
+-    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->cipher_dec_context,
++    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
+                            (unsigned char *)output, &len,
+                            (const unsigned char *)input, inputlen);
+     if (rc != 1) return SASL_FAIL;
+ 
+     *outputlen = len;
+ 
+-    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_dec_context,
++    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
+                              (unsigned char *)output + len, &len);
+     if (rc != 1) return SASL_FAIL;
+ 
+@@ -1198,7 +1289,7 @@
+     int len;
+     int rc;
+     /* encrypt the text part */
+-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                            (unsigned char *)output, &len,
+                            (const unsigned char *)input, inputlen);
+     if (rc != 1) return SASL_FAIL;
+@@ -1206,14 +1297,14 @@
+     *outputlen = len;
+ 
+     /* encrypt the `MAC part */
+-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                            (unsigned char *)output + *outputlen, &len,
+                            digest, 10);
+     if (rc != 1) return SASL_FAIL;
+ 
+     *outputlen += len;
+ 
+-    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                              (unsigned char *)output + *outputlen, &len);
+     if (rc != 1) return SASL_FAIL;
+ 
+@@ -1221,188 +1312,11 @@
+ 
+     return SASL_OK;
+ }
+-#else
+-/* quick generic implementation of RC4 */
+-struct rc4_context_s {
+-    unsigned char sbox[256];
+-    int i, j;
+-};
+-
+-typedef struct rc4_context_s rc4_context_t;
+-
+-static void rc4_init(rc4_context_t *text,
+-		     const unsigned char *key,
+-		     unsigned keylen)
+-{
+-    int i, j;
+-    
+-    /* fill in linearly s0=0 s1=1... */
+-    for (i=0;i<256;i++)
+-	text->sbox[i]=i;
+-    
+-    j=0;
+-    for (i = 0; i < 256; i++) {
+-	unsigned char tmp;
+-	/* j = (j + Si + Ki) mod 256 */
+-	j = (j + text->sbox[i] + key[i % keylen]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-    }
+-    
+-    /* counters initialized to 0 */
+-    text->i = 0;
+-    text->j = 0;
+-}
+-
+-static void rc4_encrypt(rc4_context_t *text,
+-			const char *input,
+-			char *output,
+-			unsigned len)
+-{
+-    int tmp;
+-    int i = text->i;
+-    int j = text->j;
+-    int t;
+-    int K;
+-    const char *input_end = input + len;
+-    
+-    while (input < input_end) {
+-	i = (i + 1) % 256;
+-	
+-	j = (j + text->sbox[i]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-	
+-	t = (text->sbox[i] + text->sbox[j]) % 256;
+-	
+-	K = text->sbox[t];
+-	
+-	/* byte K is Xor'ed with plaintext */
+-	*output++ = *input++ ^ K;
+-    }
+-    
+-    text->i = i;
+-    text->j = j;
+-}
+-
+-static void rc4_decrypt(rc4_context_t *text,
+-			const char *input,
+-			char *output,
+-			unsigned len)
+-{
+-    int tmp;
+-    int i = text->i;
+-    int j = text->j;
+-    int t;
+-    int K;
+-    const char *input_end = input + len;
+-    
+-    while (input < input_end) {
+-	i = (i + 1) % 256;
+-	
+-	j = (j + text->sbox[i]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-	
+-	t = (text->sbox[i] + text->sbox[j]) % 256;
+-	
+-	K = text->sbox[t];
+-	
+-	/* byte K is Xor'ed with plaintext */
+-	*output++ = *input++ ^ K;
+-    }
+-    
+-    text->i = i;
+-    text->j = j;
+-}
+-
+-static void free_rc4(context_t *text)
+-{
+-    /* free rc4 context structures */
+-
+-    if(text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
+-    if(text->cipher_dec_context) text->utils->free(text->cipher_dec_context);
+-}
+-
+-static int init_rc4(context_t *text, 
+-		    unsigned char enckey[16],
+-		    unsigned char deckey[16])
+-{
+-    /* allocate rc4 context structures */
+-    text->cipher_enc_context=
+-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
+-    if (text->cipher_enc_context == NULL) return SASL_NOMEM;
+-    
+-    text->cipher_dec_context=
+-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
+-    if (text->cipher_dec_context == NULL) return SASL_NOMEM;
+-    
+-    /* initialize them */
+-    rc4_init((rc4_context_t *) text->cipher_enc_context,
+-             (const unsigned char *) enckey, 16);
+-    rc4_init((rc4_context_t *) text->cipher_dec_context,
+-             (const unsigned char *) deckey, 16);
+-    
+-    return SASL_OK;
+-}
+-
+-static int dec_rc4(context_t *text,
+-		   const char *input,
+-		   unsigned inputlen,
+-		   unsigned char digest[16] __attribute__((unused)),
+-		   char *output,
+-		   unsigned *outputlen)
+-{
+-    /* decrypt the text part & HMAC */
+-    rc4_decrypt((rc4_context_t *) text->cipher_dec_context, 
+-                input, output, inputlen);
+-
+-    /* no padding so we just subtract the HMAC to get the text length */
+-    *outputlen = inputlen - 10;
+-    
+-    return SASL_OK;
+-}
+-
+-static int enc_rc4(context_t *text,
+-		   const char *input,
+-		   unsigned inputlen,
+-		   unsigned char digest[16],
+-		   char *output,
+-		   unsigned *outputlen)
+-{
+-    /* pad is zero */
+-    *outputlen = inputlen+10;
+-    
+-    /* encrypt the text part */
+-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context,
+-                input,
+-                output,
+-                inputlen);
+-    
+-    /* encrypt the HMAC part */
+-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context, 
+-                (const char *) digest, 
+-		(output)+inputlen, 10);
+-    
+-    return SASL_OK;
+-}
+-#endif /* HAVE_OPENSSL */
+ #endif /* WITH_RC4 */
+ 
+ struct digest_cipher available_ciphers[] =
+ {
+ #ifdef WITH_RC4
+-    { "rc4-40", 40, 5, 0x01, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+-    { "rc4-56", 56, 7, 0x02, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+     { "rc4", 128, 16, 0x04, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+ #endif
+ #ifdef WITH_DES
+@@ -2815,6 +2729,7 @@
+ 	}
+ 	
+ 	if (cptr->name) {
++	    text->cipher_name = cptr->name;
+ 	    text->cipher_enc = cptr->cipher_enc;
+ 	    text->cipher_dec = cptr->cipher_dec;
+ 	    text->cipher_init = cptr->cipher_init;
+@@ -2958,7 +2873,10 @@
+ 	if (text->cipher_init) {
+ 	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
+ 		sparams->utils->seterror(sparams->utils->conn, 0,
+-					 "couldn't init cipher");
++					 "couldn't init cipher '%s'",
++                                         text->cipher_name);
++                result = SASL_FAIL;
++                goto FreeAllMem;
+ 	    }
+ 	}
+     }
+@@ -3509,6 +3427,7 @@
+ 	oparams->mech_ssf = ctext->cipher->ssf;
+ 
+ 	nbits = ctext->cipher->n;
++	text->cipher_name = ctext->cipher->name;
+ 	text->cipher_enc = ctext->cipher->cipher_enc;
+ 	text->cipher_dec = ctext->cipher->cipher_dec;
+ 	text->cipher_free = ctext->cipher->cipher_free;
+@@ -3733,7 +3652,13 @@
+ 	
+ 	/* initialize cipher if need be */
+ 	if (text->cipher_init) {
+-	    text->cipher_init(text, enckey, deckey);
++	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
++	        params->utils->seterror(params->utils->conn, 0,
++		         "internal error: failed to init cipher '%s'",
++                         text->cipher_name);
++                result = SASL_FAIL;
++                goto FreeAllocatedMem;
++            }
+ 	}
+     }
+     
diff --git a/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch b/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch
new file mode 100644
index 0000000..10b57cc
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch
@@ -0,0 +1,109 @@
+diff -uPr cyrus-sasl-2.1.27/configure.ac cyrus-sasl-2.1.27.ossl3/configure.ac
+--- cyrus-sasl-2.1.27/configure.ac	2021-10-06 11:29:53.274375206 -0400
++++ cyrus-sasl-2.1.27.ossl3/configure.ac	2021-10-06 11:31:19.966726775 -0400
+@@ -1115,7 +1115,11 @@
+ 	with_rc4=yes)
+ 
+ if test "$with_rc4" != no; then
+-    AC_DEFINE(WITH_RC4,[],[Use RC4])
++    if test "$with_openssl" = no; then
++        AC_WARN([OpenSSL not found -- RC4 will be disabled])
++    else
++        AC_DEFINE(WITH_RC4,[],[Use RC4])
++    fi
+ fi
+ 
+ building_for_macosx=no
+diff -uPr cyrus-sasl-2.1.27/plugins/scram.c cyrus-sasl-2.1.27.ossl3/plugins/scram.c
+--- cyrus-sasl-2.1.27/plugins/scram.c	2018-11-08 12:29:57.000000000 -0500
++++ cyrus-sasl-2.1.27.ossl3/plugins/scram.c	2021-10-06 11:31:04.407484201 -0400
+@@ -65,7 +65,9 @@
+ 
+ #include <openssl/sha.h>
+ #include <openssl/evp.h>
++#if OPENSSL_VERSION_NUMBER < 0x30000000L
+ #include <openssl/hmac.h>
++#endif
+ 
+ /*****************************  Common Section  *****************************/
+ 
+@@ -267,6 +271,32 @@
+ }
+ #endif
+ 
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++
++/* Decalre as void given functions never use the result */
++void *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
++                     const unsigned char *data, size_t data_len,
++                     unsigned char *md, unsigned int *md_len)
++{
++    const char *digest;
++    size_t digest_size;
++    size_t out_len;
++    void *ret = NULL;
++
++    digest = EVP_MD_get0_name(evp_md);
++    if (digest == NULL) {
++        return NULL;
++    }
++    digest_size = EVP_MD_size(evp_md);
++
++    ret = EVP_Q_mac(NULL, "hmac", NULL, digest, NULL, key, key_len,
++                    data, data_len, md, digest_size, &out_len);
++    if (ret != NULL) {
++        *md_len = (unsigned int)out_len;
++    }
++    return ret;
++}
++#endif
+ 
+ /* The result variable need to point to a buffer big enough for the [SHA-1] hash */
+ static void
+diff -uPr cyrus-sasl-2.1.27/saslauthd/lak.c cyrus-sasl-2.1.27.ossl3/saslauthd/lak.c
+--- cyrus-sasl-2.1.27/saslauthd/lak.c	2022-01-09 11:30:50.000000000 -0400
++++ cyrus-sasl-2.1.27.ossl3/saslauthd/lak.c	2022-01-09 11:30:50.000000001 -0400
+@@ -1806,18 +1806,36 @@
+ 		return rc;
+ 	}
+ 
+-	EVP_DigestInit(mdctx, md);
+-	EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
++	rc = EVP_DigestInit(mdctx, md);
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
++	}
++	rc = EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
++	}
+ 	if (hrock->salted) {
+-		EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)],
+-				 clen - EVP_MD_size(md));
++		rc = EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)],
++				      clen - EVP_MD_size(md));
++		if (rc != 1) {
++		    rc = LAK_FAIL;
++		    goto done;
++		}
++	}
++	rc = EVP_DigestFinal(mdctx, digest, NULL);
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
+ 	}
+-	EVP_DigestFinal(mdctx, digest, NULL);
+-	EVP_MD_CTX_free(mdctx);
+ 
+ 	rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md));
++	rc = rc ? LAK_INVALID_PASSWORD : LAK_OK;
++done:
++	EVP_MD_CTX_free(mdctx);
+ 	free(cred);
+-	return rc ? LAK_INVALID_PASSWORD : LAK_OK;
++	return rc;
+ }
+ 
+ #endif /* HAVE_OPENSSL */
diff --git a/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch b/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch
new file mode 100644
index 0000000..3c6e7be
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch
@@ -0,0 +1,74 @@
+From 3b0149cf3d235247b051b7cb7663bc3dadbb999b Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 1 Apr 2021 17:17:52 +0200
+Subject: [PATCH] configure.ac: avoid side-effects in AC_CACHE_VAL
+
+In the COMMANDS-TO-SET-IT argument, per Autoconf docs:
+https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Caching-Results.html
+---
+ configure.ac | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index a106d35e..d333496d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -220,11 +220,14 @@ void foo() { int i=0;}
+ int main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY);
+     if(self) { ptr1=dlsym(self,"foo"); ptr2=dlsym(self,"_foo");
+     if(ptr1 && !ptr2) exit(0); } exit(1); } 
+-], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no
+-	AC_DEFINE(DLSYM_NEEDS_UNDERSCORE, [], [Do we need a leading _ for dlsym?]),
++], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no,
+ 	AC_MSG_WARN(cross-compiler, we'll do our best)))
+ 	LIBS="$cmu_save_LIBS"
+       AC_MSG_RESULT($sasl_cv_dlsym_adds_uscore)
++
++      if test "$sasl_cv_dlsym_adds_uscore" = no; then
++        AC_DEFINE(DLSYM_NEEDS_UNDERSCORE, [], [Do we need a leading _ for dlsym?])
++      fi
+   fi
+ fi
+ 
+From d3bcaf62f6213e7635e9c4a574f39a831e333980 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 1 Apr 2021 17:26:28 +0200
+Subject: [PATCH] configure.ac: properly quote macro arguments
+
+Autoconf 2.70+ is more picky about the quotation (even though with
+previous versions the arguments should have been quoted, too).  When we
+don't quote macros inside the AC_CACHE_VAL macro - some of the Autoconf
+initialization is wrongly ordered in ./configure script and we keep
+seeing bugs like:
+
+    ./configure: line 2165: ac_fn_c_try_run: command not found
+
+Original report: https://bugzilla.redhat.com/1943013
+---
+ configure.ac | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index d333496d..7281cba0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -213,15 +213,16 @@ if test $sasl_cv_uscore = yes; then
+ 	AC_MSG_CHECKING(whether dlsym adds the underscore for us)
+ 	cmu_save_LIBS="$LIBS"
+ 	LIBS="$LIBS $SASL_DL_LIB"
+-	AC_CACHE_VAL(sasl_cv_dlsym_adds_uscore,AC_TRY_RUN( [
++	AC_CACHE_VAL([sasl_cv_dlsym_adds_uscore],
++	             [AC_TRY_RUN([
+ #include <dlfcn.h>
+ #include <stdio.h>
+ void foo() { int i=0;}
+ int main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY);
+     if(self) { ptr1=dlsym(self,"foo"); ptr2=dlsym(self,"_foo");
+     if(ptr1 && !ptr2) exit(0); } exit(1); } 
+-], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no,
+-	AC_MSG_WARN(cross-compiler, we'll do our best)))
++], [sasl_cv_dlsym_adds_uscore=yes], [sasl_cv_dlsym_adds_uscore=no],
++	[AC_MSG_WARN(cross-compiler, we'll do our best)])])
+ 	LIBS="$cmu_save_LIBS"
+       AC_MSG_RESULT($sasl_cv_dlsym_adds_uscore)
+ 
diff --git a/SOURCES/cyrus-sasl-2.1.27-nostrncpy.patch b/SOURCES/cyrus-sasl-2.1.27-nostrncpy.patch
new file mode 100644
index 0000000..d009047
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-nostrncpy.patch
@@ -0,0 +1,51 @@
+diff --git a/plugins/gssapi.c b/plugins/gssapi.c
+index 5d900c5e..4688bb9a 100644
+--- a/plugins/gssapi.c
++++ b/plugins/gssapi.c
+@@ -1567,7 +1567,6 @@ int gssapiv2_server_plug_init(
+ {
+ #ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
+     const char *keytab = NULL;
+-    char keytab_path[1024];
+     unsigned int rl;
+ #endif
+     
+@@ -1589,15 +1588,7 @@ int gssapiv2_server_plug_init(
+ 	    return SASL_FAIL;
+ 	}
+ 	
+-	if(strlen(keytab) > 1024) {
+-	    utils->log(NULL, SASL_LOG_ERR,
+-		       "path to keytab is > 1024 characters");
+-	    return SASL_BUFOVER;
+-	}
+-	
+-	strncpy(keytab_path, keytab, 1024);
+-	
+-	gsskrb5_register_acceptor_identity(keytab_path);
++	gsskrb5_register_acceptor_identity(keytab);
+     }
+ #endif
+     
+diff --git a/plugins/ntlm.c b/plugins/ntlm.c
+index aeb3ac34..8a7d9065 100644
+--- a/plugins/ntlm.c
++++ b/plugins/ntlm.c
+@@ -375,10 +375,15 @@ static unsigned char *P16_lm(unsigned char *P16, sasl_secret_t *passwd,
+ 			     unsigned *buflen __attribute__((unused)),
+ 			     int *result)
+ {
+-    char P14[14];
++    char P14[14] = { 0 };
++    int Plen;
+     unsigned char S8[] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
+ 
+-    strncpy(P14, (const char *) passwd->data, sizeof(P14));
++    Plen = sizeof(P14);
++    if (passwd->len < Plen) {
++        Plen = passwd->len;
++    }
++    memcpy(P14, (const char *) passwd->data, Plen);
+     ucase(P14, sizeof(P14));
+ 
+     E(P16, (unsigned char *) P14, sizeof(P14), S8, sizeof(S8));
diff --git a/SOURCES/cyrus-sasl-cve-2019-19906.patch b/SOURCES/cyrus-sasl-cve-2019-19906.patch
new file mode 100644
index 0000000..acdf682
--- /dev/null
+++ b/SOURCES/cyrus-sasl-cve-2019-19906.patch
@@ -0,0 +1,25 @@
+From dcc9f51cbd4ed622cfb0f9b1c141eb2ffe3b12f1 Mon Sep 17 00:00:00 2001
+From: Quanah Gibson-Mount <quanah@symas.com>
+Date: Tue, 18 Feb 2020 19:05:12 +0000
+Subject: [PATCH] Fix #587
+
+Off by one error in common.c, CVE-2019-19906.
+
+Thanks to Stephan Zeisberg for reporting
+---
+ lib/common.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/common.c b/lib/common.c
+index bc3bf1df..9969d6aa 100644
+--- a/lib/common.c
++++ b/lib/common.c
+@@ -190,7 +190,7 @@ int _sasl_add_string(char **out, size_t *alloclen,
+ 
+   if (add==NULL) add = "(null)";
+ 
+-  addlen=strlen(add); /* only compute once */
++  addlen=strlen(add)+1; /* only compute once */
+   if (_buf_alloc(out, alloclen, (*outlen)+addlen)!=SASL_OK)
+     return SASL_NOMEM;
+ 
diff --git a/SOURCES/cyrus-sasl-pr559-RC4-openssl.patch b/SOURCES/cyrus-sasl-pr559-RC4-openssl.patch
new file mode 100644
index 0000000..f884423
--- /dev/null
+++ b/SOURCES/cyrus-sasl-pr559-RC4-openssl.patch
@@ -0,0 +1,156 @@
+From 8aa9ae816ddf66921b4a8a0f422517e6f2e55ac6 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Wed, 27 Mar 2019 14:29:08 -0400
+Subject: [PATCH] Use Openssl RC4 when available
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ configure.ac        |   5 +--
+ plugins/digestmd5.c | 107 +++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 108 insertions(+), 4 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 388f5d02..cfdee4a2 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1103,13 +1103,12 @@ AC_ARG_WITH(configdir, [   --with-configdir=DIR    set the directory where confi
+   configdir='${plugindir}:${sysconfdir}/sasl2')
+ AC_SUBST(configdir)
+ 
+-dnl look for rc4 libraries. we accept the CMU one or one from openSSL
+-AC_ARG_WITH(rc4, [  --with-rc4              use internal rc4 routines [[yes]] ],
++AC_ARG_WITH(rc4, [  --with-rc4              use rc4 routines [[yes]] ],
+ 	with_rc4=$withval,
+ 	with_rc4=yes)
+ 
+ if test "$with_rc4" != no; then
+-    AC_DEFINE(WITH_RC4,[],[Use internal RC4 implementation?])
++    AC_DEFINE(WITH_RC4,[],[Use RC4])
+ fi
+ 
+ building_for_macosx=no
+diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
+index df35093d..c6b54317 100644
+--- a/plugins/digestmd5.c
++++ b/plugins/digestmd5.c
+@@ -1117,6 +1117,111 @@ static void free_des(context_t *text)
+ #endif /* WITH_DES */
+ 
+ #ifdef WITH_RC4
++#ifdef HAVE_OPENSSL
++#include <openssl/evp.h>
++
++static void free_rc4(context_t *text)
++{
++    if (text->cipher_enc_context) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_enc_context);
++        text->cipher_enc_context = NULL;
++    }
++    if (text->cipher_dec_context) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_dec_context);
++        text->cipher_dec_context = NULL;
++    }
++}
++
++static int init_rc4(context_t *text,
++		    unsigned char enckey[16],
++		    unsigned char deckey[16])
++{
++    EVP_CIPHER_CTX *ctx;
++    int rc;
++
++    ctx = EVP_CIPHER_CTX_new();
++    if (ctx == NULL) return SASL_NOMEM;
++
++    rc = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, enckey, NULL);
++    if (rc != 1) return SASL_FAIL;
++
++    text->cipher_enc_context = (void *)ctx;
++
++    ctx = EVP_CIPHER_CTX_new();
++    if (ctx == NULL) return SASL_NOMEM;
++
++    rc = EVP_DecryptInit_ex(ctx, EVP_rc4(), NULL, deckey, NULL);
++    if (rc != 1) return SASL_FAIL;
++
++    text->cipher_dec_context = (void *)ctx;
++
++    return SASL_OK;
++}
++
++static int dec_rc4(context_t *text,
++		   const char *input,
++		   unsigned inputlen,
++		   unsigned char digest[16] __attribute__((unused)),
++		   char *output,
++		   unsigned *outputlen)
++{
++    int len;
++    int rc;
++
++    /* decrypt the text part & HMAC */
++    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->cipher_dec_context,
++                           (unsigned char *)output, &len,
++                           (const unsigned char *)input, inputlen);
++    if (rc != 1) return SASL_FAIL;
++
++    *outputlen = len;
++
++    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_dec_context,
++                             (unsigned char *)output + len, &len);
++    if (rc != 1) return SASL_FAIL;
++
++    *outputlen += len;
++
++    /* subtract the HMAC to get the text length */
++    *outputlen -= 10;
++
++    return SASL_OK;
++}
++
++static int enc_rc4(context_t *text,
++		   const char *input,
++		   unsigned inputlen,
++		   unsigned char digest[16],
++		   char *output,
++		   unsigned *outputlen)
++{
++    int len;
++    int rc;
++    /* encrypt the text part */
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++                           (unsigned char *)output, &len,
++                           (const unsigned char *)input, inputlen);
++    if (rc != 1) return SASL_FAIL;
++
++    *outputlen = len;
++
++    /* encrypt the `MAC part */
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++                           (unsigned char *)output + *outputlen, &len,
++                           digest, 10);
++    if (rc != 1) return SASL_FAIL;
++
++    *outputlen += len;
++
++    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_enc_context,
++                             (unsigned char *)output + *outputlen, &len);
++    if (rc != 1) return SASL_FAIL;
++
++    *outputlen += len;
++
++    return SASL_OK;
++}
++#else
+ /* quick generic implementation of RC4 */
+ struct rc4_context_s {
+     unsigned char sbox[256];
+@@ -1296,7 +1401,7 @@ static int enc_rc4(context_t *text,
+     
+     return SASL_OK;
+ }
+-
++#endif /* HAVE_OPENSSL */
+ #endif /* WITH_RC4 */
+ 
+ struct digest_cipher available_ciphers[] =
diff --git a/SOURCES/make-no-dlcompatorsrp-tarball.sh b/SOURCES/make-no-dlcompatorsrp-tarball.sh
new file mode 100755
index 0000000..e58dc3b
--- /dev/null
+++ b/SOURCES/make-no-dlcompatorsrp-tarball.sh
@@ -0,0 +1,41 @@
+#!/bin/bash -e
+#
+#  See https://github.com/cyrusimap/cyrus-sasl/releases for unmodified sources.
+#
+
+tmppath=`mktemp -d ${TMPDIR:-/tmp}/make-no-dlcompat-tarball-XXXXXX`
+if test -z "$tmppath" ; then
+	echo Error creating temporary directory.
+	exit 1
+fi
+trap "rm -fr $tmppath" EXIT
+
+initialdir=`pwd`
+
+for tarball in ${initialdir}/cyrus-sasl-*.tar.{gz,bz2} ; do
+	if ! test -s "$tarball" ; then
+		continue
+	fi
+	rm -fr $tmppath/*
+	pushd $tmppath > /dev/null
+	case "$tarball" in
+	*nodlcompat*)
+		: Do nothing.
+		;;
+	*.gz)
+		gzip  -dc "$tarball" | tar xf -
+		rm -fr cyrus-sasl-*/dlcompat*
+		rm -fr cyrus-sasl-*/plugins/srp*
+		tar cf - * | gzip  -9c > \
+		$initialdir/`basename $tarball .tar.gz`-nodlcompatorsrp.tar.gz
+		;;
+	*.bz2)
+		bzip2 -dc "$tarball" | tar xf -
+		rm -fr cyrus-sasl-*/dlcompat*
+		rm -fr cyrus-sasl-*/plugins/srp*
+		tar cf - * | bzip2 -9c > \
+		$initialdir/`basename $tarball .tar.bz2`-nodlcompatorsrp.tar.bz2
+		;;
+	esac
+	popd > /dev/null
+done
diff --git a/SOURCES/sasl-mechlist.c b/SOURCES/sasl-mechlist.c
new file mode 100644
index 0000000..680e983
--- /dev/null
+++ b/SOURCES/sasl-mechlist.c
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sasl.h"
+
+static int
+my_getopt(void *context, const char *plugin_name,
+	  const char *option, const char **result, unsigned *len)
+{
+	if (result) {
+		*result = NULL;
+#if 0
+		fprintf(stderr, "Getopt plugin=%s%s%s/option=%s%s%s -> ",
+			plugin_name ? "\"" : "",
+			plugin_name ? plugin_name : "(null)",
+			plugin_name ? "\"" : "",
+			option ? "\"" : "",
+			option ? option : "(null)",
+			option ? "\"" : "");
+		fprintf(stderr, "'%s'.\n", *result ? *result : "");
+#endif
+	}
+	if (len) {
+		*len = 0;
+	}
+	return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+	int ret, i;
+	const char *mechs, **globals;
+	sasl_callback_t callbacks[] = {
+		{SASL_CB_GETOPT, my_getopt, NULL},
+		{SASL_CB_LIST_END},
+	};
+	sasl_conn_t *connection;
+	char hostname[512];
+
+	if ((argc > 1) && (argv[1][0] == '-')) {
+		fprintf(stderr, "Usage: %s [appname [hostname] ]\n", argv[0]);
+		return 0;
+	}
+
+	ret = sasl_server_init(callbacks, argc > 1 ? argv[1] : "sasl-mechlist");
+	if (ret != SASL_OK) {
+		fprintf(stderr, "Error in sasl_server_init(): %s\n",
+			sasl_errstring(ret, NULL, NULL));
+	}
+
+	connection = NULL;
+	strcpy(hostname, "localhost");
+	gethostname(hostname, sizeof(hostname));
+	ret = sasl_server_new(argc > 2 ? argv[2] : "host",
+			      hostname,
+			      NULL,
+			      NULL,
+			      NULL,
+			      callbacks,
+			      0,
+			      &connection);
+	if (ret != SASL_OK) {
+		fprintf(stderr, "Error in sasl_server_new(): %s\n",
+			sasl_errstring(ret, NULL, NULL));
+	}
+
+	ret = sasl_listmech(connection,
+			    getenv("USER") ? getenv("USER") : "root",
+			    "Available mechanisms: ",
+			    ",",
+			    "\n",
+			    &mechs,
+			    NULL,
+			    NULL);
+	if (ret != SASL_OK) {
+		fprintf(stderr, "Error in sasl_listmechs(): %s\n",
+			sasl_errstring(ret, NULL, NULL));
+	} else {
+		fprintf(stdout, "%s", mechs);
+	}
+
+	globals = sasl_global_listmech();
+	for (i = 0; (globals != NULL) && (globals[i] != NULL); i++) {
+		if (i == 0) {
+			fprintf(stdout, "Library supports: ");
+		}
+		fprintf(stdout, "%s", globals[i]);
+		if (globals[i + 1] != NULL) {
+			fprintf(stdout, ",");
+		} else {
+			fprintf(stdout, "\n");
+		}
+	}
+
+	return 0;
+}
diff --git a/SOURCES/saslauthd.service b/SOURCES/saslauthd.service
new file mode 100644
index 0000000..c7c7eca
--- /dev/null
+++ b/SOURCES/saslauthd.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=SASL authentication daemon.
+
+[Service]
+Type=forking
+PIDFile=/run/saslauthd/saslauthd.pid
+EnvironmentFile=/etc/sysconfig/saslauthd
+ExecStart=/usr/sbin/saslauthd -m $SOCKETDIR -a $MECH $FLAGS
+RuntimeDirectory=saslauthd
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SOURCES/saslauthd.sysconfig b/SOURCES/saslauthd.sysconfig
new file mode 100644
index 0000000..5413c36
--- /dev/null
+++ b/SOURCES/saslauthd.sysconfig
@@ -0,0 +1,11 @@
+# Directory in which to place saslauthd's listening socket, pid file, and so
+# on.  This directory must already exist.
+SOCKETDIR=/run/saslauthd
+
+# Mechanism to use when checking passwords.  Run "saslauthd -v" to get a list
+# of which mechanism your installation was compiled with the ablity to use.
+MECH=pam
+
+# Additional flags to pass to saslauthd on the command line.  See saslauthd(8)
+# for the list of accepted flags.
+FLAGS=
diff --git a/SPECS/cyrus-sasl.spec b/SPECS/cyrus-sasl.spec
new file mode 100644
index 0000000..6b3cff7
--- /dev/null
+++ b/SPECS/cyrus-sasl.spec
@@ -0,0 +1,1209 @@
+%global username    saslauth
+%global hint        Saslauthd user
+%global homedir     /run/saslauthd
+
+%global _plugindir2 %{_libdir}/sasl2
+%global bootstrap_cyrus_sasl 0
+%global gdbm_db_file /etc/sasl2/sasldb2
+
+Summary: The Cyrus SASL library
+Name: cyrus-sasl
+Version: 2.1.27
+Release: 20%{?dist}
+License: BSD with advertising
+URL: https://www.cyrusimap.org/sasl/
+
+# Source0 originally comes from https://www.cyrusimap.org/releases/;
+# make-no-dlcompatorsrp-tarball.sh removes the "dlcompat" subdirectory and builds a
+# new tarball.
+Source0: cyrus-sasl-%{version}-nodlcompatorsrp.tar.gz
+Source5: saslauthd.service
+Source7: sasl-mechlist.c
+Source9: saslauthd.sysconfig
+Source10: make-no-dlcompatorsrp-tarball.sh
+# From upstream git, required for reconfigure after applying patches to configure.ac
+# https://raw.githubusercontent.com/cyrusimap/cyrus-sasl/master/autogen.sh
+Source11: autogen.sh
+
+Patch11: cyrus-sasl-2.1.25-no_rpath.patch
+Patch15: cyrus-sasl-2.1.20-saslauthd.conf-path.patch
+Patch23: cyrus-sasl-2.1.23-man.patch
+Patch24: cyrus-sasl-2.1.21-sizes.patch
+# The 64 bit *INT8 type is not used anywhere and other types match
+Patch49: cyrus-sasl-2.1.26-md5global.patch
+Patch60: cyrus-sasl-pr559-RC4-openssl.patch
+
+Patch100: cyrus-sasl-cve-2019-19906.patch
+Patch101: cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
+Patch102: cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch
+Patch103: cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch
+Patch104: cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch
+Patch105: cyrus-sasl-2.1.27-fix-for-autoconf270.patch
+#https://github.com/simo5/cyrus-sasl/commit/ebd2387f06c84c7f9aac3167ec041bb01e5c6e48
+Patch106: cyrus-sasl-2.1.27-nostrncpy.patch
+# Upstream PR: https://github.com/cyrusimap/cyrus-sasl/pull/635
+Patch107: cyrus-sasl-2.1.27-Add-basic-test-plain-auth.patch
+#Migration tool should be removed from RHEL10
+Patch108: cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch
+Patch500: cyrus-sasl-2.1.27-coverity.patch
+Patch501: cyrus-sasl-2.1.27-cumulative-digestmd5.patch
+Patch502: cyrus-sasl-2.1.27-cumulative-ossl3.patch
+
+Patch900: 0001-CVE-2022-24407-Escape-password-for-SQL-insert-update.patch
+
+BuildRequires: autoconf, automake, libtool, gdbm-devel, groff
+BuildRequires: krb5-devel >= 1.19, openssl-devel, pam-devel, pkgconfig
+BuildRequires: mariadb-connector-c-devel, libpq-devel, zlib-devel
+%if ! %{bootstrap_cyrus_sasl}
+BuildRequires: openldap-devel
+%endif
+#build reqs for migration from BerkeleyDB
+#should be removed from RHEL10
+BuildRequires: libdb-devel-static
+#build reqs for make check
+BuildRequires: python3 nss_wrapper socket_wrapper krb5-server
+%{?systemd_requires}
+
+Requires: %{name}-lib = %{version}-%{release}
+Requires: systemd
+
+#Requires/Provides related to the saslauthd user creation
+Requires: /sbin/nologin
+Requires(pre): /usr/sbin/useradd /usr/sbin/groupadd
+Requires(postun): /usr/sbin/userdel /usr/sbin/groupdel
+Provides: user(%username)
+Provides: group(%username)
+
+
+%description
+The %{name} package contains the Cyrus implementation of SASL.
+SASL is the Simple Authentication and Security Layer, a method for
+adding authentication support to connection-based protocols.
+
+%package lib
+Summary: Shared libraries needed by applications which use Cyrus SASL
+
+%description lib
+The %{name}-lib package contains shared libraries which are needed by
+applications which use the Cyrus SASL library.
+
+%package devel
+Requires: %{name}-lib = %{version}-%{release}
+Requires: %{name} = %{version}-%{release}
+Requires: pkgconfig
+Summary: Files needed for developing applications with Cyrus SASL
+
+%description devel
+The %{name}-devel package contains files needed for developing and
+compiling applications which use the Cyrus SASL library.
+
+%package gssapi
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: GSSAPI authentication support for Cyrus SASL
+
+%description gssapi
+The %{name}-gssapi package contains the Cyrus SASL plugins which
+support GSSAPI authentication. GSSAPI is commonly used for Kerberos
+authentication.
+
+%package plain
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: PLAIN and LOGIN authentication support for Cyrus SASL
+
+%description plain
+The %{name}-plain package contains the Cyrus SASL plugins which support
+PLAIN and LOGIN authentication schemes.
+
+%package md5
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: CRAM-MD5 and DIGEST-MD5 authentication support for Cyrus SASL
+
+%description md5
+The %{name}-md5 package contains the Cyrus SASL plugins which support
+CRAM-MD5 and DIGEST-MD5 authentication schemes.
+
+%package ntlm
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: NTLM authentication support for Cyrus SASL
+
+%description ntlm
+The %{name}-ntlm package contains the Cyrus SASL plugin which supports
+the NTLM authentication scheme.
+
+# This would more appropriately be named cyrus-sasl-auxprop-sql.
+%package sql
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: SQL auxprop support for Cyrus SASL
+
+%description sql
+The %{name}-sql package contains the Cyrus SASL plugin which supports
+using a RDBMS for storing shared secrets.
+
+%if ! %{bootstrap_cyrus_sasl}
+# This was *almost* named cyrus-sasl-auxprop-ldapdb, but that's a lot of typing.
+%package ldap
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: LDAP auxprop support for Cyrus SASL
+
+%description ldap
+The %{name}-ldap package contains the Cyrus SASL plugin which supports using
+a directory server, accessed using LDAP, for storing shared secrets.
+%endif
+
+%package scram
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: SCRAM auxprop support for Cyrus SASL
+
+%description scram
+The %{name}-scram package contains the Cyrus SASL plugin which supports
+the SCRAM authentication scheme.
+
+%package gs2
+Requires: %{name}-lib%{?_isa} = %{version}-%{release}
+Summary: GS2 support for Cyrus SASL
+
+%description gs2
+The %{name}-gs2 package contains the Cyrus SASL plugin which supports
+the GS2 authentication scheme.
+
+###
+
+
+%prep
+%setup -q -n cyrus-sasl-%{version}
+%patch11 -p1 -b .no_rpath
+%patch15 -p1 -b .path
+%patch23 -p1 -b .man
+%patch24 -p1 -b .sizes
+%patch49 -p1 -b .md5global.h
+%patch60 -p1 -b .openssl_rc4
+%patch100 -p1 -b .cve_2019_19906
+%patch101 -p1 -b .tests
+%patch102 -p1 -b .gssapi_cbs
+%patch103 -p1 -b .maxssf0
+%patch104 -p1 -b .nolog
+%patch105 -p1 -b .autoconf270
+%patch106 -p1 -b .nostrncpy
+%patch107 -p1 -b .plaintests
+%patch108 -p1 -b .frombdb
+%patch500 -p1 -b .coverity
+%patch501 -p1 -b .digestmd5
+%patch502 -p1 -b .ossl3
+%patch900 -p1 -b .CVE-2022-24407
+
+%build
+# reconfigure
+cp %{SOURCE11} ./
+rm configure aclocal.m4 config/ltmain.sh Makefile.in
+export NOCONFIGURE=yes
+sh autogen.sh
+
+# Find Kerberos.
+krb5_prefix=`krb5-config --prefix`
+if test x$krb5_prefix = x%{_prefix} ; then
+        krb5_prefix=
+else
+        CPPFLAGS="-I${krb5_prefix}/include $CPPFLAGS"; export CPPFLAGS
+        LDFLAGS="-L${krb5_prefix}/%{_lib} $LDFLAGS"; export LDFLAGS
+fi
+
+# Find OpenSSL.
+LIBS="-lcrypt"; export LIBS
+if pkg-config openssl ; then
+        CPPFLAGS="`pkg-config --cflags-only-I openssl` $CPPFLAGS"; export CPPFLAGS
+        LDFLAGS="`pkg-config --libs-only-L openssl` $LDFLAGS"; export LDFLAGS
+fi
+
+# Find the MySQL libraries used needed by the SQL auxprop plugin.
+INC_DIR="`mysql_config --include`"
+if test x"$INC_DIR" != "x-I%{_includedir}"; then
+        CPPFLAGS="$INC_DIR $CPPFLAGS"; export CPPFLAGS
+fi
+LIB_DIR="`mysql_config --libs | sed -e 's,-[^L][^ ]*,,g' -e 's,^ *,,' -e 's, *$,,' -e 's,  *, ,g'`"
+if test x"$LIB_DIR" != "x-L%{_libdir}"; then
+        LDFLAGS="$LIB_DIR $LDFLAGS"; export LDFLAGS
+fi
+
+# Find the PostgreSQL libraries used needed by the SQL auxprop plugin.
+INC_DIR="-I`pg_config --includedir`"
+if test x"$INC_DIR" != "x-I%{_includedir}"; then
+        CPPFLAGS="$INC_DIR $CPPFLAGS"; export CPPFLAGS
+fi
+LIB_DIR="-L`pg_config --libdir`"
+if test x"$LIB_DIR" != "x-L%{_libdir}"; then
+        LDFLAGS="$LIB_DIR $LDFLAGS"; export LDFLAGS
+fi
+
+CFLAGS="$RPM_OPT_FLAGS $CFLAGS $CPPFLAGS -fPIC -pie -Wl,-z,relro -Wl,-z,now"; export CFLAGS
+
+echo "$CFLAGS"
+echo "$CPPFLAGS"
+echo "$LDFLAGS"
+
+%configure \
+        --enable-shared --disable-static \
+        --disable-java \
+        --with-plugindir=%{_plugindir2} \
+        --with-configdir=%{_plugindir2}:%{_sysconfdir}/sasl2 \
+        --disable-krb4 \
+        --enable-gssapi${krb5_prefix:+=${krb5_prefix}} \
+        --with-gss_impl=mit \
+        --with-rc4 \
+        --with-dblib=gdbm \
+        --with-dbpath=%{gdbm_db_file} \
+        --with-saslauthd=/run/saslauthd --without-pwcheck \
+%if ! %{bootstrap_cyrus_sasl}
+        --with-ldap \
+%endif
+        --with-devrandom=/dev/urandom \
+        --enable-anon \
+        --enable-cram \
+        --enable-digest \
+        --enable-ntlm \
+        --enable-plain \
+        --enable-login \
+        --enable-alwaystrue \
+        --enable-httpform \
+        --disable-otp \
+%if ! %{bootstrap_cyrus_sasl}
+        --enable-ldapdb \
+%endif
+        --enable-sql --with-mysql=yes --with-pgsql=yes \
+        --without-sqlite \
+        "$@"
+        # --enable-auth-sasldb -- EXPERIMENTAL
+make sasldir=%{_plugindir2}
+make -C saslauthd testsaslauthd
+make -C sample
+
+# Build a small program to list the available mechanisms, because I need it.
+pushd lib
+../libtool --mode=link %{__cc} -o sasl2-shared-mechlist -I../include $CFLAGS %{SOURCE7} $LDFLAGS ./libsasl2.la
+
+
+%install
+test "$RPM_BUILD_ROOT" != "/" && rm -rf $RPM_BUILD_ROOT
+
+make install DESTDIR=$RPM_BUILD_ROOT sasldir=%{_plugindir2}
+make install DESTDIR=$RPM_BUILD_ROOT sasldir=%{_plugindir2} -C plugins
+
+install -m755 -d $RPM_BUILD_ROOT%{_bindir}
+./libtool --mode=install \
+install -m755 sample/client $RPM_BUILD_ROOT%{_bindir}/sasl2-sample-client
+./libtool --mode=install \
+install -m755 sample/server $RPM_BUILD_ROOT%{_bindir}/sasl2-sample-server
+#Migration tool should be removed from RHEL10
+mv $RPM_BUILD_ROOT%{_sbindir}/cyrusbdb2current $RPM_BUILD_ROOT%{_bindir}/cyrusbdb2current
+./libtool --mode=install \
+install -m755 saslauthd/testsaslauthd $RPM_BUILD_ROOT%{_sbindir}/testsaslauthd
+
+# Install the saslauthd mdoc page in the expected location.  Sure, it's not
+# really a man page, but groff seems to be able to cope with it.
+install -m755 -d $RPM_BUILD_ROOT%{_mandir}/man8/
+install -m644 -p saslauthd/saslauthd.mdoc $RPM_BUILD_ROOT%{_mandir}/man8/saslauthd.8
+install -m644 -p saslauthd/testsaslauthd.8 $RPM_BUILD_ROOT%{_mandir}/man8/testsaslauthd.8
+
+# Install the systemd unit file for saslauthd and the config file.
+install -d -m755 $RPM_BUILD_ROOT/%{_unitdir} $RPM_BUILD_ROOT/etc/sysconfig
+install -m644 -p %{SOURCE5} $RPM_BUILD_ROOT/%{_unitdir}/saslauthd.service
+install -m644 -p %{SOURCE9} $RPM_BUILD_ROOT/etc/sysconfig/saslauthd
+
+# Install the config dirs if they're not already there.
+install -m755 -d $RPM_BUILD_ROOT/%{_sysconfdir}/sasl2
+install -m755 -d $RPM_BUILD_ROOT/%{_plugindir2}
+
+# Provide an easy way to query the list of available mechanisms.
+./libtool --mode=install \
+install -m755 lib/sasl2-shared-mechlist $RPM_BUILD_ROOT/%{_sbindir}/
+
+# Remove unpackaged files from the buildroot.
+rm -f $RPM_BUILD_ROOT%{_libdir}/sasl2/libotp.*
+rm -f $RPM_BUILD_ROOT%{_libdir}/sasl2/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/sasl2/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+rm -f $RPM_BUILD_ROOT%{_mandir}/cat8/saslauthd.8
+
+%check
+make check %{?_smp_mflags}
+
+%pre
+getent group %{username} >/dev/null || groupadd -g 76 -r %{username}
+getent passwd %{username} >/dev/null || useradd -r -g %{username} -d %{homedir} -s /sbin/nologin -c "%{hint}" %{username}
+
+%post
+%systemd_post saslauthd.service
+
+%preun
+%systemd_preun saslauthd.service
+
+%postun
+%systemd_postun_with_restart saslauthd.service
+
+%ldconfig_scriptlets lib
+
+%files
+%doc saslauthd/LDAP_SASLAUTHD
+%{_mandir}/man8/*
+%{_sbindir}/pluginviewer
+%{_sbindir}/saslauthd
+%{_sbindir}/testsaslauthd
+%config(noreplace) /etc/sysconfig/saslauthd
+%{_unitdir}/saslauthd.service
+%ghost /run/saslauthd
+
+%files lib
+%license COPYING
+%doc AUTHORS doc/html/*.html
+%{_libdir}/libsasl*.so.*
+%dir %{_sysconfdir}/sasl2
+%dir %{_plugindir2}/
+%{_plugindir2}/*anonymous*.so*
+%{_plugindir2}/*sasldb*.so*
+%{_sbindir}/saslpasswd2
+%{_sbindir}/sasldblistusers2
+%{_bindir}/cyrusbdb2current
+
+%files plain
+%{_plugindir2}/*plain*.so*
+%{_plugindir2}/*login*.so*
+
+%if ! %{bootstrap_cyrus_sasl}
+%files ldap
+%{_plugindir2}/*ldapdb*.so*
+%endif
+
+%files md5
+%{_plugindir2}/*crammd5*.so*
+%{_plugindir2}/*digestmd5*.so*
+
+%files ntlm
+%{_plugindir2}/*ntlm*.so*
+
+%files sql
+%{_plugindir2}/*sql*.so*
+
+%files gssapi
+%{_plugindir2}/*gssapi*.so*
+
+%files scram
+%{_plugindir2}/libscram.so*
+
+%files gs2
+%{_plugindir2}/libgs2.so*
+
+%files devel
+%{_bindir}/sasl2-sample-client
+%{_bindir}/sasl2-sample-server
+%{_includedir}/*
+%{_libdir}/libsasl*.*so
+%{_libdir}/pkgconfig/*.pc
+%{_mandir}/man3/*
+%{_sbindir}/sasl2-shared-mechlist
+
+%changelog
+* Thu Feb 23 2022 Simo Sorce <simo@redhat.com> - 2.1.27-6
+- Fix for CVE-2022-24407
+- Resolves: rhbz#2055848
+
+* Mon Feb  9 2022 Simo Sorce <simo@redhat.com> - 2.1.27-19
+- Fix a memleak in one of the OpenSSL 3 compat patches
+  found by covscan
+
+* Mon Feb  7 2022 Simo Sorce <simo@redhat.com> - 2.1.27-18
+- Update OpenSSL 3 related compatibility patch backports
+
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.27-17
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Wed Jul 28 2021 Simo Sorce <simo@redhat.com> - 2.1.27-16
+- Rebuild to pass gating after fixing rhbz#1983928
+
+* Wed Jul 28 2021 Florian Weimer <fweimer@redhat.com> - 2.1.27-15
+- Rebuild to pick up OpenSSL 3.0 Beta ABI (#1984097)
+
+* Mon Jul 19 2021 Simo Sorce <simo@redhat.com> - 2.1.27-14
+- Fix crashs on missing legacy algorithms
+  Resolves: rhbz#1974354
+
+* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.27-13
+- Rebuilt for RHEL 9 BETA for openssl 3.0
+  Related: rhbz#1971065
+
+* Fri Jun 04 2021 Dmitry Belyavskiy <dbelyavs@redhat.com> - 2.1.27-12
+- Incorporate the upstream gdbm specific patch from
+  https://github.com/cyrusimap/cyrus-sasl/pull/554
+- Resolves rhbz#1947971
+
+* Wed Apr 28 2021 Dmitry Belyavskiy <dbelyavs@redhat.com> - 2.1.27-11
+- Set default sasldb database to GDBM instead of BerkeleyDB
+- Add the migration tool from BerkeleyDB
+- Add some PLAIN auth tests
+- Resolves rhbz#1947971
+
+* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.27-10
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Mon Apr 12 2021 Dmitry Belyavskiy <dbelyavs@redhat.com> - 2.1.27-9
+- Coverity-related fixes (#1938700)
+
+* Mon Feb 08 2021 Pavel Raiskup <praiskup@redhat.com> - 2.1.27-8
+- rebuild for libpq ABI fix rhbz#1908268
+
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Thu May  7 2020 Simo Sorce <simo@redhat.com> - 2.1.27-5
+- Backport GSSAPI Channel Bindings support
+- Add support for setting maxssf=0 in GSS-SPNEGO
+- Reduce excessive GSSAPI plugin logging
+
+* Thu Mar 19 2020 Simo Sorce - 2.1.27-4
+- Fix CVE 2019 19906
+
+* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Wed Jul 24 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Thu Jun 13 2019 Simo Sorce - 2.1.27-1
+- Update to final 2.1.27 sources
+- Also add patch to use OpenSSL RC4, currently proposed as PR 559
+
+* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-0.6rc7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Mon Jan 14 2019 Björn Esser <besser82@fedoraproject.org> - 2.1.27-0.5rc7
+- Rebuilt for libcrypt.so.2 (#1666033)
+
+* Sun Oct 14 2018 Peter Robinson <pbrobinson@fedoraproject.org> 2.1.27-0.4rc7
+- Clean up remanents of sys-v, spec cleanups
+
+* Thu Jul 12 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.27-0.3rc7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Thu May 17 2018 Jakub Jelen <jjelen@redhat.com> - 2.1.27-0.2rc7
+- Avoid multilib conflicts between devel subpackages (#1577675)
+
+* Mon Mar 05 2018 Jakub Jelen <jjelen@redhat.com> - 2.1.27-0.1rc7
+- New upstream (pre-)release
+- Import LDFLAGS from redhat-rpm-config (#1548437)
+
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.26-37
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Sat Jan 20 2018 Björn Esser <besser82@fedoraproject.org> - 2.1.26-36
+- Rebuilt for switch to libxcrypt
+
+* Mon Oct 23 2017 Jakub Jelen <jjelen@redhat.com> - 2.1.26-35
+- Use mariadb-connector-c-devel instead of mysql-devel (#1493620)
+
+* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.26-34
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.26-33
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Wed Apr 19 2017 Jakub Jelen <jjelen@redhat.com> - 2.1.26-32
+- Add missing patch for separate mutexes per connection in GSSAPI
+
+* Tue Apr 18 2017 Jakub Jelen <jjelen@redhat.com> - 2.1.26-31
+- Allow cyrus sasl to get the ssf from gssapi
+
+* Wed Apr 12 2017 Petr Šabata <contyk@redhat.com> - 2.1.26-30
+- Removing the obsolete scriptlet /sbin/service dependency
+
+* Tue Mar 07 2017 Jakub Jelen <jjelen@redhat.com> - 2.1.26-29
+- Fix GSS SPNEGO support (#1421663)
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.26-28
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Mon Nov 07 2016 Jakub Jelen <jjelen@redhat.com> - 2.1.26-27
+- Add support for OpenSSL 1.1.0
+
+* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.26-26.2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Thu Jul 16 2015 Jakub Jelen <jjelen@redhat.com> 2.1.26-25.2
+- Revert tmpfiles.d and use new systemd feature RuntimeDirectory
+
+* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.26-24
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Fri May 29 2015 Jakub Jelen <jjelen@redhat.com> 2.1.26-23
+- Add ability to handle logging in gssapi plugin (#1187097)
+
+* Mon Mar 16 2015 Jakub Jelen <jjelen@redhat.com> 2.1.26-22
+- Rever "Do not leak memory in plugin_common.c ..." due the breakage of svn (#1202364)
+
+* Thu Mar 12 2015 Jakub Jelen <jjelen@redhat.com> 2.1.26-21
+- Add and Document ability to run saslauthd as non-root user, fix tpmfiles ownership (#1189203)
+- Do not leak memory in sample server (#852755)
+- Do not leak memory in plugin_common.c for password callback (#1191183)
+- Cleanup spec file: tmpfiles.d macros and tab/space
+
+* Wed Feb 04 2015 Petr Lautrbach <plautrba@redhat.com> 2.1.26-20
+- Change the ownership of /run/saslauth to saslauth:saslauth (#1189203)
+
+* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.26-19
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Fri Jul 11 2014 Tom Callaway <spot@fedoraproject.org> - 2.1.26-18
+- fix license handling
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.26-17
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Sun Jan 19 2014 Ville Skyttä <ville.skytta@iki.fi> - 2.1.26-16
+- Don't order service after syslog.target.
+
+* Fri Nov 15 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-15
+- Treat SCRAM-SHA-1/DIGEST-MD5 as more secure than PLAIN (#970718)
+- improve configuration error message
+
+* Fri Nov 01 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-14
+- revert upstream commit 080e51c7fa0421eb2f0210d34cf0ac48a228b1e9 (#984079)
+
+* Tue Oct 15 2013 Karsten Hopp <karsten@redhat.com> 2.1.26-13
+- add ppc64p7 subarch support in config.sub (Fedora only)
+
+* Mon Sep 09 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-12
+- build with RPM_OPT_FLAGS <ville.skytta@iki.fi> (#1005535)
+
+* Tue Sep 03 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-11
+- fix hardening for /usr/sbin/saslauthd
+- add testsaslauthd.8 man page to the package
+- use static md5global.h file
+
+* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.26-10
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Mon Jun 24 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-9
+- detect gsskrb5_register_acceptor_identity macro <nalin@redhat.com> (#976538)
+
+* Tue Jun 04 2013 Karsten Hopp <karsten@redhat.com> 2.1.26-8
+- disable incorrect check for MkLinux to allow building with shared libraries on PPC
+
+* Tue May 21 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-7
+- fix the spec file in order to build the cyrus-sasl-sql plugin
+  with support for PostgreSQL and MySQL
+
+* Thu Feb 21 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-6
+- don't include system sasl2 library needed for rebuilds after rebase
+
+* Mon Feb 11 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-5
+- enable full relro and PIE compiler flags for saslauthd
+
+* Fri Feb 01 2013 Petr Lautrbach <plautrba@redhat.com> 2.1.26-4
+- fix library symlinks
+
+* Thu Jan 31 2013 Rex Dieter <rdieter@fedoraproject.org> 2.1.26-3
+- actually apply size_t patch (#906519)
+
+* Thu Jan 31 2013 Rex Dieter <rdieter@fedoraproject.org> 2.1.26-2
+- sasl.h: +#include<sys/types.h> for missing size_t type (#906519)
+- tighten subpkg deps via %%?_isa
+
+* Thu Dec 20 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.26-1
+- update to 2.1.26
+- fix segfaults in sasl_gss_encode (#886140)
+
+* Mon Dec 10 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.25-2
+- always use the current external Berkeley DB when linking
+
+* Fri Dec 07 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.25-1
+- update to 2.1.25
+- add cyrus-sasl-scram and cyrus-sasl-gs2 packages
+
+* Fri Sep 14 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.23-36
+- replace scriptlets with systemd macros (#856666)
+
+* Wed Jul 18 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.23-35
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Tue Jul 17 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.23-34
+- move /etc/tmpfiles.d/saslauthd.conf to /usr/lib/tmpfiles.d/saslauthd.conf (#840193)
+
+* Wed Jun 20 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.23-33
+- properly deal with crypt() returning NULL (#816250)
+- use fixed gid 76 for saslauth
+
+* Mon Apr 16 2012 Jindrich Novy <jnovy@redhat.com> 2.1.23-32
+- re-enable libdb support and utilities
+
+* Wed Apr 04 2012 Jindrich Novy <jnovy@redhat.com> 2.1.23-31
+- temporarily disable libdb support to resolve cyrus-sasl
+  chicken and egg build problem against libdb
+
+* Tue Apr 03 2012 Jindrich Novy <jnovy@redhat.com> 2.1.23-30
+- rebuild against new libdb
+
+* Wed Feb 08 2012 Petr Lautrbach <plautrba@redhat.com> 2.1.23-29
+- Change saslauth user homedir to /run/saslauthd (#752889)
+- Change all /var/run/ to /run/
+- DAEMONOPTS are not supported any more in systemd units
+
+* Mon Jan 09 2012 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 2.1.23-28
+- Ship with sasl_pwcheck_method: alwaystrue
+
+* Mon Dec 12 2011 Petr Lautrbach <plautrba@redhat.com> 2.1.23-27
+- remove support for logging of the remote host via PAM (#759334)
+- fix systemd files (#750436)
+
+* Wed Aug 10 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-26
+- Add partial relro support for libraries
+
+* Mon Jul 25 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-25
+- Add support for berkeley db 5
+
+* Wed Jun 29 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-23
+- Migrate the package to full native systemd unit files, according to the Fedora
+  packaging guidelines.
+
+* Wed Jun  1 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-22
+- repair rimap support (more packets in response)
+
+* Wed May 25 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-21
+- repair ntlm support
+
+* Mon May 23 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-20
+- add logging of the remote host via PAM
+
+* Thu Apr 28 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-19
+- temporarilly revert systemd units
+
+* Tue Apr 26 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-18
+- update scriptlets
+
+* Fri Apr 22 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-17
+- Add systemd units
+
+* Wed Mar 23 2011 Tomas Mraz <tmraz@redhat.com> - 2.1.23-16
+- Rebuilt with new mysqlclient
+
+* Fri Feb 25 2011 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-15
+- set correct license tag
+- add ghost to /var/run/saslauthd
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.23-14
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Fri Apr  9 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-13
+- Add /etc/tmpfiles.d element (#662734)
+
+* Fri Apr  9 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-12
+- Update init script to impeach pid file
+
+* Thu Mar 11 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-11
+- Update pre post preun and postun scripts (#572399)
+
+* Wed Mar 10 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-10
+- Rewrite spec file, make corect CFLAGS, CPPFLAGS and LDFLAGS
+
+* Mon Feb 22 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-9
+- solve race condition (#566875)
+
+* Wed Feb 17 2010 Stepan Kasal <skasal@redhat.com> - 2.1.23-8
+- improve m4 quoting to fix saslauthd/configure (#566088)
+- call autotools in build, not in prep
+
+* Fri Feb  5 2010 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-7
+- Add man page to testtcpauthd (#526189)
+
+* Fri Oct 16 2009 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-6
+- Create the saslauth user according to fedora packaging guide
+
+* Thu Sep 24 2009 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-5
+- Repair initscript to make condrestart working properly (#522103)
+
+* Wed Sep 23 2009 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-3
+- Add possibility to run the saslauth without root privilegies (#185614)
+
+* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 2.1.23-2
+- rebuilt with new openssl
+
+* Fri Aug  7 2009 Jan F. Chadima <jchadima@redhat.com> - 2.1.23-1
+- update to 2.1.23
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.22-25
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Mon May 11 2009 Jan F. Chadima <jchadima@redhat.com> - 2.1.22-24
+- repair sasl_encode64 nul termination (#487251)
+
+* Thu Apr 16 2009 Robert Scheck <robert@fedoraproject.org> - 2.1.22-23
+- Don't build the krb4 plugin as krb5 1.7 will drop it (#225974 #c6)
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.22-22
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Fri Feb  6 2009 Tomas Mraz <tmraz@redhat.com> - 2.1.22-21
+- fix build with gcc-4.4
+
+* Fri Jan 23 2009 Tomas Mraz <tmraz@redhat.com> - 2.1.22-20
+- set LDAP_OPT_TIMEOUT (#326452)
+- provide LSB compatible init script (#246900)
+
+* Fri Sep 26 2008 Tomas Mraz <tmraz@redhat.com> - 2.1.22-19
+- always use the current external db4 when linking,
+  thanks to Dan Horak for the original patch (#464098)
+
+* Wed Sep 10 2008 Tomas Mraz <tmraz@redhat.com> - 2.1.22-18
+- fix most critical build warnings (#433583)
+- use external db4
+
+* Fri Aug 29 2008 Tomas Mraz <tmraz@redhat.com> - 2.1.22-17
+- always link against the internal db4 (#459163)
+- rediff patches for no fuzz
+
+* Wed Jul  9 2008 Tomas Mraz <tmraz@redhat.com> - 2.1.22-16
+- update internal db4 (#449737)
+
+* Tue Jul  1 2008 Tomas Mraz <tmraz@redhat.com> - 2.1.22-15
+- drop reload from initscript help (#448154)
+- fix hang in rimap auth method (#438533)
+- build the krb4 plugin (#154675)
+
+* Fri May 23 2008 Dennis Gilmore <dennis@ausil.us> - 2.1.22-14
+- make it so that bootstrap actually works
+
+* Thu May 22 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 2.1.22-13.1
+- minor release bump for sparc rebuild
+
+* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org> - 2.1.22-13
+- Autorebuild for GCC 4.3
+
+* Thu Feb 14 2008 Steve Conklin <sconklin@redhat.com> - 2.1.22-12
+- rebuild for gcc4.3
+
+* Fri Jan 25 2008 Steve Conklin <sconklin@redhat.com> - 2.1.22-11
+- Cleanup after merge review bz #225673
+- no longer mark /etc/rc.d/init.d/saslauthd as config file
+- removed -x permissions on include files
+- added devel package dependency on cyrus-sasl
+- removed some remaining .la files that were being delivered
+
+* Wed Dec 05 2007 Release Engineering <rel-eng at fedoraproject dot org> - 2.1.22-10
+ - Rebuild for deps
+
+* Wed Nov  7 2007 Steve Conklin <sconklin@redhat.com> - 2.1.22-9
+- Fixed a typo in the spec file
+
+* Wed Nov  7 2007 Steve Conklin <sconklin@redhat.com> - 2.1.22-8
+- Removed srp plugin source and added dist to NVR
+
+* Tue Sep 18 2007 Steve Conklin <sconklin@redhat.com> 2.1.22-7
+- use db4 version 4.6.19 bz#249737
+
+* Mon Feb 26 2007 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-6
+- install config files and init scripts using -p
+- pull in patch to build with current automake (#229010, Jacek Konieczny
+  and Robert Scheck)
+- remove prereq on ldconfig, RPM should pick it up based on the -libs
+  scriptlets
+- pull in patch to correctly detect gsskrb5_register_acceptor_identity
+  (#200892, Mirko Streckenbach)
+- move sasldb auxprop modules into the -lib subpackage, so that we'll pick
+  it up for multilib systems
+
+* Thu Feb 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- pull CVS fix for not tripping over extra commas in digest-md5
+  challenges (#229640)
+
+* Fri Feb 16 2007 Nalin Dahyabhai <nalin@redhat.com>
+- remove static build, which is no longer a useful option because not all of
+  our dependencies are available as static libraries
+- drop patches which were needed to keep static builds going
+- drop gssapi-generic patch due to lack of interest
+- update the bundled copy of db to 4.5.20 (#229012)
+- drop dbconverter-2, as we haven't bundled v1 libraries since FC4
+
+* Tue Dec  5 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-5
+- rebuild
+- add 'authentication' or 'auxprop' to summaries for plugin packages to
+  better indicate what the plugin provides
+- switch from automake 1.9 to automake 1.7
+
+* Fri Sep 29 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-4
+- rebuild without 'dlcompat' bits (#206119)
+
+* Mon Jul 17 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-3
+- rebuild
+
+* Tue Jun 20 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-2
+- fix a typo in sasl_client_start(3) (#196066)
+
+* Mon May 22 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.22-1
+- update to 2.1.22, adding pluginviewer to %%{_sbindir}
+
+* Tue May 16 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-12
+- add conditionalized build dependency on openldap-devel (#191855)
+- patch md5global.h to be the same on all architectures
+
+* Thu Apr 27 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-11
+- add unapplied patch which makes the DIGEST-MD5 plugin omit the realm
+  argument when the environment has $CYRUS_SASL_DIGEST_MD5_OMIT_REALM set to a
+  non-zero value, for testing purposes
+- add missing buildrequires on zlib-devel (#190113)
+
+* Mon Feb 20 2006 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-10
+- add missing buildrequires on gdbm-devel (Karsten Hopp)
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 2.1.21-9.2
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 2.1.21-9.1
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Mon Dec 19 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-9
+- use --as-needed to avoid linking dbconverter-2 with SQL libraries, which
+  it doesn't use because it manipulates files directly (#173321)
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Mon Nov 14 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-8
+- rebuild with new OpenLDAP, overriding the version checks to assume that
+  2.3.11 is acceptable
+- remove a lingering patch for 1.x which we no longer use
+
+* Sat Nov 12 2005 Tom Lane <tgl@redhat.com> 2.1.21-7
+- Rebuild due to mysql update.
+
+* Tue Nov  8 2005 Tomas Mraz <tmraz@redhat.com> 2.1.21-6
+- rebuilt with new openssl
+
+* Fri Sep  9 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-5
+- add missing buildrequires: on groff (#163032)
+
+* Thu Sep  1 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-4
+- move the ldapdb auxprop support into a subpackage (#167300)
+  (note: the ldap password check support in saslauthd doesn't use auxprop)
+
+* Tue Aug 30 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-3
+- correct a use of uninitialized memory in the bundled libdb (Arjan van de Ven)
+
+* Mon Aug 29 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-2
+- move the ANONYMOUS mech plugin to the -lib subpackage so that multilib
+  systems can use it without installing the main package
+- build the static libraries without sql auxprop support
+
+* Mon Aug 29 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.21-1
+- update to 2.1.21
+- turn off compilation of libsasl v1 (finally)
+- explicitly disable sqlite to avoid the build warning
+- change the default mechanism which is set for saslauthd from "shadow" to
+  "pam" (#159194)
+- split the shared library up from saslauthd so that multilib systems don't
+  have to pull in every dependency of saslauthd for the compat arch (#166749)
+
+* Wed Apr 13 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.20-5
+- rebuild with new deps
+
+* Tue Mar  1 2005 Nalin Dahyabhai <nalin@redhat.com> 2.1.20-4
+- rebuild with new deps
+
+* Thu Nov 11 2004 Jeff Johnson <jbj@jbj.org> 2.1.20-3
+- rebuild against db-4.3.21.
+
+* Thu Nov 11 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.20-2
+- build with mysql-devel instead of mysqlclient10
+
+* Mon Nov  1 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.20-1
+- build with mysqlclient10 instead of mysql-devel
+
+* Wed Oct 27 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.20-0
+- update to 2.1.20, including the fix for CAN-2004-0884
+
+* Tue Oct  5 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.19-3
+- use notting's fix for incorrect patch for CAN-2004-0884 for 1.5.28
+
+* Tue Oct  5 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.19-2
+- don't trust the environment in setuid/setgid contexts (CAN-2004-0884, #134660)
+
+* Thu Aug 19 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.19-1
+- rebuild (the 2.1.19 changelog for fixing a buffer overflow referred to a CVS
+  revision between 2.1.18 and 2.1.19)
+
+* Mon Jul 19 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.19-0
+- update to 2.1.19, maybe for update
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Mon Jun  7 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.18-4
+- enable sql auxprop support in a subpackage
+- include LDAP_SASLAUTHD documentation file (#124830)
+
+* Fri Jun  4 2004 Nalin Dahyabhai <nalin@redhat.com>
+- turn on ntlm in a subpackage
+
+* Thu May 13 2004 Thomas Woerner <twoerner@redhat.com> 2.1.18-3
+- removed rpath
+
+* Tue Mar 16 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.18-2
+- turn on building of libsasl v1 again
+
+* Fri Mar 12 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.18-1
+- update to 2.1.18
+- saslauthd's ldap code is no longer marked experimental, so we build it
+
+* Mon Mar  8 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.17-4
+- rebuild
+
+* Tue Mar 02 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Tue Feb  3 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.17-2
+- include default /etc/sysconfig/saslauthd configuration file for the init
+  script (#114868)
+
+* Thu Jan 29 2004 Nalin Dahyabhai <nalin@redhat.com>
+- drop saslauthd_version patch for libsasl2
+
+* Thu Jan 29 2004 Nalin Dahyabhai <nalin@redhat.com>
+- add a saslauthd_version option to libsasl's saslauthd client and teach it to
+  do the right thing
+- enable the saslauthd client code in libsasl version 1 (it's still going away!)
+- add saslauthd1-checkpass/saslauthd2-checkpass for testing the above change
+
+* Wed Jan  7 2004 Nalin Dahyabhai <nalin@redhat.com> 2.1.17-1
+- forcibly disable otp and sql plugins at compile-time
+
+* Fri Dec 19 2003 Nalin Dahyabhai <nalin@redhat.com>
+- update to 2.1.17, forcing the gssapi plugin to be shared now, as before
+- use a bundled libdb (#112215)
+- build static-with-all-plugins and normal-shared libsasl versions
+- add sasl2-{shared,static}-mechlist for very basic sanity checking
+- make inclusion of sasl1 stuffs conditional, because it's so going away
+
+* Sat Dec 13 2003 Jeff Johnson <jbj@jbj.org> 2.1.15-7
+- rebuild against db-4.2.52.
+
+* Thu Oct 23 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-6
+- use /dev/urandom instead of /dev/random for SASL2 (docs indicate that this is
+  safe if you aren't using OTP or SRP, and we build neither); SASL1 appears to
+  use it to seed the libc RNG only (#103378)
+
+* Mon Oct 20 2003 Nalin Dahyabhai <nalin@redhat.com>
+- obey RPM_OPT_FLAGS again when krb5_prefix != %%{_prefix}
+
+* Fri Oct 17 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-5
+- install saslauthd's mdoc page instead of the pre-formatted man page, which
+  would get formatted again
+
+* Thu Sep 25 2003 Jeff Johnson <jbj@jbj.org> 2.1.15-5
+- rebuild against db-4.2.42.
+
+* Mon Sep 15 2003 Nalin Dahyabhai <nalin@redhat.com>
+- include testsaslauthd
+- note in the README that the saslauthd protocol is different for v1 and v2,
+  so v1's clients can't talk to the v2 server
+
+* Thu Aug 21 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-4
+- rebuild
+
+* Thu Aug 21 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-3
+- add logic to build with gssapi libs in either /usr or /usr/kerberos
+
+* Mon Jul 21 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-2
+- rebuild
+
+* Tue Jul 15 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.15-1
+- update to 2.1.15
+
+* Mon Jul 14 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.14-1
+- update to 2.1.14
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri May  9 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.13-3
+- change -m argument to saslauthd to be a directory instead of a path
+
+* Thu May  8 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.13-2
+- link libsasl2 with -lpthread to ensure that the sasldb plug-in can always
+  be loaded
+
+* Tue Apr 29 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.13-1
+- update to 2.1.13
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Tue Jan  7 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.10-3
+- rebuild
+
+* Thu Dec 12 2002 Nalin Dahyabhai <nalin@redhat.com>
+- consider either des_cbc_encrypt or DES_cbc_encrypt to be sufficient when
+  searching for a DES implementation in libcrypto
+- pull in CPPFLAGS and LDFLAGS from openssl's pkg-config data, if it exists
+
+* Mon Dec  9 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.10-2
+- rebuild
+
+* Mon Dec  9 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.10-1
+- update to 2.1.10, fixing buffer overflows in libsasl2 noted by Timo Sirainen
+
+* Tue Nov 12 2002 Tim Powers <timp@redhat.com> 2.1.7-5
+- remove files from $RPM_BUILD_ROOT that we don't intend to include
+
+* Wed Oct  9 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.7-4
+- update to SASLv1 to final 1.5.28
+
+* Fri Sep 13 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.7-3
+- rebuild, overriding sasldir when running make so that on multilib systems
+  applications will be able to load modules for the right arch
+
+* Mon Sep  2 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.7-2
+- include dbconverter-2 (#68741)
+
+* Fri Aug  9 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.7-1
+- update to 2.1.7, fixing a race condition in digest-md5
+
+* Wed Jul 17 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.6-1
+- update to 2.1.6 and 1.5.28
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Thu Jun 13 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.5-1
+- update to 2.1.5
+
+* Mon Jun 10 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.4-1
+- update to 2.1.4
+
+* Sun May 26 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Thu May 16 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.2-1
+- modify to build with db 4.x
+
+* Thu Apr 18 2002 Nalin Dahyabhai <nalin@redhat.com>
+- update cyrus-sasl 2 to 2.1.2
+- change buildreq to db3-devel
+
+* Tue Feb 12 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.1-3
+- suppress output to stdout/stderr in %%postun
+
+* Sun Feb 10 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.1-2
+- configure sasldb2 to use berkeley DB instead of gdbm
+
+* Wed Feb  6 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.1-1
+- update to 2.1.1
+
+* Thu Jan 31 2002 Nalin Dahyabhai <nalin@redhat.com> 2.1.0-1
+- marge 1.5.24 back in, making a note that it should be removed at some
+  point in the future
+
+* Wed Jan 30 2002 Nalin Dahyabhai <nalin@redhat.com>
+- update to 2.1.0, which is designed to be installed in parallel with cyrus sasl
+  1.x, so fork the package and rename it to cyrus-sasl2
+- add the sasldb auxprop plugin to the main package
+- add disabled-by-default saslauthd init script
+- move the .la files for plugins into their respective packages -- they're
+  needed by the library
+
+* Wed Jan 23 2002 Nalin Dahyabhai <nalin@redhat.com> 1.5.24-24
+- free ride through the build system
+
+* Fri Nov  2 2001 Nalin Dahyabhai <nalin@redhat.com> 1.5.24-23
+- patch to fix possible syslog format-string vulnerability 
+
+* Mon Oct 29 2001 Nalin Dahyabhai <nalin@redhat.com> 1.5.24-22
+- add pam-devel as a buildprereq
+
+* Wed Aug 29 2001 Nalin Dahyabhai <nalin@redhat.com> 1.5.24-21
+- include sample programs in the -devel subpackage, prefixing their names
+  with "sasl-" to reduce future potential naming conflicts
+
+* Tue Aug 14 2001 Nalin Dahyabhai <nalin@redhat.com> 1.5.24-20
+- build without -ggdb
+
+* Fri Aug  3 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add gdbm-devel as a build dependency (#44990)
+- split off CRAM-MD5 and DIGEST-MD5 into a subpackage of their own (#43079,
+  and dialogs with David L. Parsley)
+
+* Fri Apr 27 2001 Nalin Dahyabhai <nalin@redhat.com>
+- split out the PLAIN and LOGIN mechanisms into their own package (this allows
+  an administrator to disable them by simply removing the package)
+
+* Fri Jan 19 2001 Nalin Dahyabhai <nalin@redhat.com>
+- rebuild in new environment
+
+* Wed Dec  6 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix gssapi-over-tls
+
+* Fri Oct 27 2000 Nalin Dahyabhai <nalin@redhat.com>
+- enable static libraries, but always build with -fPIC
+
+* Wed Oct 25 2000 Nalin Dahyabhai <nalin@redhat.com>
+- make sure the version of 1.5.24 in the package matches the masters (#18968)
+
+* Mon Oct  9 2000 Nalin Dahyabhai <nalin@redhat.com>
+- re-add the libsasl.so symlink to the -devel package (oops)
+
+* Fri Oct  6 2000 Nalin Dahyabhai <nalin@redhat.com>
+- move .so files for modules to their respective packages -- they're not -devel
+  links meant for use by ld anyway
+
+* Thu Oct  5 2000 Nalin Dahyabhai <nalin@redhat.com>
+- split off -devel subpackage
+- add a -gssapi subpackage for the gssapi plugins
+
+* Wed Aug 16 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix the summary text
+
+* Sun Aug 13 2000 Nalin Dahyabhai <nalin@redhat.com>
+- re-enable arcfour and CRAM
+
+* Fri Aug  4 2000 Nalin Dahyabhai <nalin@redhat.com>
+- force use of gdbm for database files to avoid DB migration weirdness
+- enable login mechanism
+- disable gssapi until it can coexist peacefully with non-gssapi setups
+- actually do a make in the build section (#15410)
+
+* Fri Jul 21 2000 Nalin Dahyabhai <nalin@redhat.com>
+- update to 1.5.24
+
+* Wed Jul 12 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Tue Jun 27 2000 Nalin Dahyabhai <nalin@redhat.com>
+- rebuild in new environment (release 3)
+
+* Mon Jun 19 2000 Nalin Dahyabhai <nalin@redhat.com>
+- don't muck with syslogd in post
+- remove patch for db-3.0 wackiness, no longer needed
+
+* Thu Jun  8 2000 Nalin Dahyabhai <nalin@redhat.com>
+- FHS cleanup
+- don't strip anything by default
+
+* Fri Feb 11 2000 Tim Powers <timp@redhat.com>
+- fixed man pages not being gzipped
+
+* Tue Nov 16 1999 Tim Powers <timp@redhat.com>
+- incorporated changes from Mads Kiilerich
+- release number is 1, not mk1
+
+* Wed Nov 10 1999 Mads Kiilerich <mads@kiilerich.com>
+- updated to sasl 1.5.11
+- configure --disable-krb4 --without-rc4 --disable-cram 
+  because of missing libraries and pine having cram as default...
+- handle changing libsasl.so versions
+
+* Mon Aug 30 1999 Tim Powers <timp@redhat.com>
+- changed group
+
+* Fri Aug 13 1999 Tim Powers <timp@redhat.com>
+- first build for Powertools