Blame SOURCES/cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch

8b8af0
diff -up cyrus-sasl-2.1.27/configure.ac.frombdb cyrus-sasl-2.1.27/configure.ac
8b8af0
--- cyrus-sasl-2.1.27/configure.ac.frombdb	2021-06-04 13:02:07.790112263 +0200
8b8af0
+++ cyrus-sasl-2.1.27/configure.ac	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -1091,6 +1091,9 @@ AC_SUBST(SASL_STATIC_SRCS)
8b8af0
 AC_SUBST(SASL_STATIC_OBJS)
8b8af0
 AC_SUBST(SASL_STATIC_LIBS)
8b8af0
 
8b8af0
+CYRUS_BERKELEY_DB_STATIC_LIB()
8b8af0
+AC_SUBST(BDB_STATIC_LIBADD)
8b8af0
+
8b8af0
 AC_ARG_WITH(plugindir, [  --with-plugindir=DIR    set the directory where plugins will
8b8af0
                           be found [[LIBDIR/sasl2]] ],
8b8af0
   plugindir=$withval,
8b8af0
diff -up cyrus-sasl-2.1.27/m4/berkdb.m4.frombdb cyrus-sasl-2.1.27/m4/berkdb.m4
8b8af0
--- cyrus-sasl-2.1.27/m4/berkdb.m4.frombdb	2016-01-29 18:35:35.000000000 +0100
8b8af0
+++ cyrus-sasl-2.1.27/m4/berkdb.m4	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -286,3 +286,10 @@ AC_DEFUN([CYRUS_BERKELEY_DB_CHK],
8b8af0
 
8b8af0
 	CPPFLAGS=$cmu_save_CPPFLAGS
8b8af0
 ])
8b8af0
+
8b8af0
+AC_DEFUN([CYRUS_BERKELEY_DB_STATIC_LIB],
8b8af0
+[
8b8af0
+BDB_STATIC_LIBADD="/dev/null -lpthread"
8b8af0
+AC_CHECK_FILE([/usr/lib64/libdb-5.3.a],[BDB_STATIC_LIBADD="/usr/lib64/libdb-5.3.a -lpthread "],[])
8b8af0
+AC_CHECK_FILE([/usr/lib/libdb-5.3.a],[BDB_STATIC_LIBADD="/usr/lib/libdb-5.3.a -lpthread"],[])
8b8af0
+])
8b8af0
diff -up cyrus-sasl-2.1.27/m4/sasldb.m4.frombdb cyrus-sasl-2.1.27/m4/sasldb.m4
8b8af0
--- cyrus-sasl-2.1.27/m4/sasldb.m4.frombdb	2017-07-13 20:45:19.000000000 +0200
8b8af0
+++ cyrus-sasl-2.1.27/m4/sasldb.m4	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -111,7 +111,7 @@ AC_MSG_RESULT($dblib)
8b8af0
 SASL_DB_BACKEND="db_${dblib}.lo"
8b8af0
 SASL_DB_BACKEND_STATIC="db_${dblib}.o allockey.o"
8b8af0
 SASL_DB_BACKEND_STATIC_SRCS="\$(top_srcdir)/sasldb/db_${dblib}.c \$(top_srcdir)/sasldb/allockey.c"
8b8af0
-SASL_DB_UTILS="saslpasswd2 sasldblistusers2"
8b8af0
+SASL_DB_UTILS="cyrusbdb2current saslpasswd2 sasldblistusers2"
8b8af0
 SASL_DB_MANS="saslpasswd2.8 sasldblistusers2.8"
8b8af0
 
8b8af0
 case "$dblib" in
8b8af0
diff -up cyrus-sasl-2.1.27/sasldb/db_gdbm.c.frombdb cyrus-sasl-2.1.27/sasldb/db_gdbm.c
8b8af0
--- cyrus-sasl-2.1.27/sasldb/db_gdbm.c.frombdb	2017-07-13 14:34:03.000000000 +0200
8b8af0
+++ cyrus-sasl-2.1.27/sasldb/db_gdbm.c	2021-06-04 13:04:24.098206887 +0200
8b8af0
@@ -67,6 +67,7 @@ int _sasldb_getdata(const sasl_utils_t *
8b8af0
   void *cntxt;
8b8af0
   sasl_getopt_t *getopt;
8b8af0
   const char *path = SASL_DB_PATH;
8b8af0
+  int fetch_errno = 0;
8b8af0
 
8b8af0
   if (!utils) return SASL_BADPARAM;
8b8af0
   if (!authid || !propName || !realm || !out || !max_out) {
8b8af0
@@ -99,6 +100,9 @@ int _sasldb_getdata(const sasl_utils_t *
8b8af0
   }
8b8af0
   db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
8b8af0
   if (! db) {
8b8af0
+      utils->log(conn, SASL_LOG_ERR,
8b8af0
+		 "SASL error opening password file. "
8b8af0
+		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
8b8af0
       utils->seterror(cntxt, 0, "Could not open %s: gdbm_errno=%d",
8b8af0
 		      path, gdbm_errno);
8b8af0
       result = SASL_FAIL;
8b8af0
@@ -107,9 +111,10 @@ int _sasldb_getdata(const sasl_utils_t *
8b8af0
   gkey.dptr = key;
8b8af0
   gkey.dsize = key_len;
8b8af0
   gvalue = gdbm_fetch(db, gkey);
8b8af0
+  fetch_errno = gdbm_errno;
8b8af0
   gdbm_close(db);
8b8af0
   if (! gvalue.dptr) {
8b8af0
-      if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
8b8af0
+      if (fetch_errno == GDBM_ITEM_NOT_FOUND) {
8b8af0
           utils->seterror(conn, SASL_NOLOG,
8b8af0
 			  "user: %s@%s property: %s not found in %s",
8b8af0
 			  authid, realm, propName, path);
8b8af0
@@ -186,7 +191,8 @@ int _sasldb_putdata(const sasl_utils_t *
8b8af0
   if (! db) {
8b8af0
       utils->log(conn, SASL_LOG_ERR,
8b8af0
 		 "SASL error opening password file. "
8b8af0
-		 "Do you have write permissions?\n");
8b8af0
+		 "Do you have write permissions?\n"
8b8af0
+		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
8b8af0
       utils->seterror(conn, 0, "Could not open %s for write: gdbm_errno=%d",
8b8af0
                      path, gdbm_errno);
8b8af0
       result = SASL_FAIL;
8b8af0
@@ -298,6 +304,9 @@ sasldb_handle _sasldb_getkeyhandle(const
8b8af0
     db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
8b8af0
 
8b8af0
     if(!db) {
8b8af0
+        utils->log(conn, SASL_LOG_ERR,
8b8af0
+		 "SASL error opening password file. "
8b8af0
+		 "Have you performed the migration from db2 using cyrusbdb2current?\n");
8b8af0
         utils->seterror(conn, 0, "Could not open %s: gdbm_errno=%d",
8b8af0
 			 path, gdbm_errno);
8b8af0
 	return NULL;
8b8af0
diff -up cyrus-sasl-2.1.27/utils/cyrusbdb2current.8.frombdb cyrus-sasl-2.1.27/utils/cyrusbdb2current.8
8b8af0
--- cyrus-sasl-2.1.27/utils/cyrusbdb2current.8.frombdb	2021-06-04 13:02:07.798112327 +0200
8b8af0
+++ cyrus-sasl-2.1.27/utils/cyrusbdb2current.8	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -0,0 +1,159 @@
8b8af0
+.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40)
8b8af0
+.\"
8b8af0
+.\" Standard preamble:
8b8af0
+.\" ========================================================================
8b8af0
+.de Sp \" Vertical space (when we can't use .PP)
8b8af0
+.if t .sp .5v
8b8af0
+.if n .sp
8b8af0
+..
8b8af0
+.de Vb \" Begin verbatim text
8b8af0
+.ft CW
8b8af0
+.nf
8b8af0
+.ne \\$1
8b8af0
+..
8b8af0
+.de Ve \" End verbatim text
8b8af0
+.ft R
8b8af0
+.fi
8b8af0
+..
8b8af0
+.\" Set up some character translations and predefined strings.  \*(-- will
8b8af0
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
8b8af0
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
8b8af0
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
8b8af0
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
8b8af0
+.\" nothing in troff, for use with C<>.
8b8af0
+.tr \(*W-
8b8af0
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
8b8af0
+.ie n \{\
8b8af0
+.    ds -- \(*W-
8b8af0
+.    ds PI pi
8b8af0
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
8b8af0
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
8b8af0
+.    ds L" ""
8b8af0
+.    ds R" ""
8b8af0
+.    ds C` ""
8b8af0
+.    ds C' ""
8b8af0
+'br\}
8b8af0
+.el\{\
8b8af0
+.    ds -- \|\(em\|
8b8af0
+.    ds PI \(*p
8b8af0
+.    ds L" ``
8b8af0
+.    ds R" ''
8b8af0
+.    ds C`
8b8af0
+.    ds C'
8b8af0
+'br\}
8b8af0
+.\"
8b8af0
+.\" Escape single quotes in literal strings from groff's Unicode transform.
8b8af0
+.ie \n(.g .ds Aq \(aq
8b8af0
+.el       .ds Aq '
8b8af0
+.\"
8b8af0
+.\" If the F register is >0, we'll generate index entries on stderr for
8b8af0
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
8b8af0
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
8b8af0
+.\" output yourself in some meaningful fashion.
8b8af0
+.\"
8b8af0
+.\" Avoid warning from groff about undefined register 'F'.
8b8af0
+.de IX
8b8af0
+..
8b8af0
+.nr rF 0
8b8af0
+.if \n(.g .if rF .nr rF 1
8b8af0
+.if (\n(rF:(\n(.g==0)) \{\
8b8af0
+.    if \nF \{\
8b8af0
+.        de IX
8b8af0
+.        tm Index:\\$1\t\\n%\t"\\$2"
8b8af0
+..
8b8af0
+.        if !\nF==2 \{\
8b8af0
+.            nr % 0
8b8af0
+.            nr F 2
8b8af0
+.        \}
8b8af0
+.    \}
8b8af0
+.\}
8b8af0
+.rr rF
8b8af0
+.\"
8b8af0
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
8b8af0
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
8b8af0
+.    \" fudge factors for nroff and troff
8b8af0
+.if n \{\
8b8af0
+.    ds #H 0
8b8af0
+.    ds #V .8m
8b8af0
+.    ds #F .3m
8b8af0
+.    ds #[ \f1
8b8af0
+.    ds #] \fP
8b8af0
+.\}
8b8af0
+.if t \{\
8b8af0
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
8b8af0
+.    ds #V .6m
8b8af0
+.    ds #F 0
8b8af0
+.    ds #[ \&
8b8af0
+.    ds #] \&
8b8af0
+.\}
8b8af0
+.    \" simple accents for nroff and troff
8b8af0
+.if n \{\
8b8af0
+.    ds ' \&
8b8af0
+.    ds ` \&
8b8af0
+.    ds ^ \&
8b8af0
+.    ds , \&
8b8af0
+.    ds ~ ~
8b8af0
+.    ds /
8b8af0
+.\}
8b8af0
+.if t \{\
8b8af0
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
8b8af0
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
8b8af0
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
8b8af0
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
8b8af0
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
8b8af0
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
8b8af0
+.\}
8b8af0
+.    \" troff and (daisy-wheel) nroff accents
8b8af0
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
8b8af0
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
8b8af0
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
8b8af0
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
8b8af0
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
8b8af0
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
8b8af0
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
8b8af0
+.ds ae a\h'-(\w'a'u*4/10)'e
8b8af0
+.ds Ae A\h'-(\w'A'u*4/10)'E
8b8af0
+.    \" corrections for vroff
8b8af0
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
8b8af0
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
8b8af0
+.    \" for low resolution devices (crt and lpr)
8b8af0
+.if \n(.H>23 .if \n(.V>19 \
8b8af0
+\{\
8b8af0
+.    ds : e
8b8af0
+.    ds 8 ss
8b8af0
+.    ds o a
8b8af0
+.    ds d- d\h'-1'\(ga
8b8af0
+.    ds D- D\h'-1'\(hy
8b8af0
+.    ds th \o'bp'
8b8af0
+.    ds Th \o'LP'
8b8af0
+.    ds ae ae
8b8af0
+.    ds Ae AE
8b8af0
+.\}
8b8af0
+.rm #[ #] #H #V #F C
8b8af0
+.\" ========================================================================
8b8af0
+.\"
8b8af0
+.IX Title "CYRUSBDB2CURRENT 1"
8b8af0
+.TH CYRUSBDB2CURRENT 1 "2021-04-28" "perl v5.30.3" "User Contributed Perl Documentation"
8b8af0
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
8b8af0
+.\" way too many mistakes in technical documents.
8b8af0
+.if n .ad l
8b8af0
+.nh
8b8af0
+.SH "NAME"
8b8af0
+cyrusbdb2current \- command\-line utility converting the SASLDB database from
8b8af0
+BerkeleyDB to the database format currently used bys sasldb.
8b8af0
+.SH "SYNOPSIS"
8b8af0
+.IX Header "SYNOPSIS"
8b8af0
+cyrusbdb2current <sasldb_old_path> <sasldb_new_path>
8b8af0
+.SH "DESCRIPTION"
8b8af0
+.IX Header "DESCRIPTION"
8b8af0
+\&\fBcyrusbdb2current\fR converts the current sasldb database from BerkeleyDB format to the
8b8af0
+currently used database format. It is \fB\s-1STRONGLY RECOMMENDED\s0\fR to make a backup
8b8af0
+of the current database before the conversion.
8b8af0
+.PP
8b8af0
+We expect that the old path is \fB/etc/sasldb2\fR and the new one is
8b8af0
+\&\fB/etc/sasl2/sasldb2\fR
8b8af0
+.SH "SEE ALSO"
8b8af0
+.IX Header "SEE ALSO"
8b8af0
+\&\fBsaslpasswd2\fR\|(8)
8b8af0
+.PP
8b8af0
+rfc4422 \- Simple Authentication and Security Layer (\s-1SASL\s0)
8b8af0
diff -up cyrus-sasl-2.1.27/utils/cyrusbdb2current.c.frombdb cyrus-sasl-2.1.27/utils/cyrusbdb2current.c
8b8af0
--- cyrus-sasl-2.1.27/utils/cyrusbdb2current.c.frombdb	2021-06-04 13:02:07.798112327 +0200
8b8af0
+++ cyrus-sasl-2.1.27/utils/cyrusbdb2current.c	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -0,0 +1,282 @@
8b8af0
+#include <config.h>
8b8af0
+
8b8af0
+#include <stdio.h>
8b8af0
+#include <stdlib.h>
8b8af0
+
8b8af0
+#include <sasl.h>
8b8af0
+#include <saslplug.h>
8b8af0
+#include "../sasldb/sasldb.h"
8b8af0
+
8b8af0
+/* Cheating to make the utils work out right */
8b8af0
+extern const sasl_utils_t *sasl_global_utils;
8b8af0
+sasl_conn_t *globalconn;
8b8af0
+
8b8af0
+typedef void *listcb_t(const char *, const char *, const char *,
8b8af0
+		       const char *, unsigned);
8b8af0
+
8b8af0
+void listusers_cb(const char *authid, const char *realm,
8b8af0
+		  const char *propName, const char *secret,
8b8af0
+		  unsigned seclen)
8b8af0
+{
8b8af0
+    if (!authid || !propName || !realm) {
8b8af0
+	fprintf(stderr,"userlist callback has bad param");
8b8af0
+	return;
8b8af0
+    }
8b8af0
+
8b8af0
+    /* the entries that just say the mechanism exists */
8b8af0
+    if (strlen(authid)==0) return;
8b8af0
+
8b8af0
+    printf("Converting: %s@%s (%s)...",authid,realm,propName);
8b8af0
+
8b8af0
+    _sasldb_putdata(sasl_global_utils, globalconn,
8b8af0
+		    authid, realm, propName,
8b8af0
+		    secret, seclen);
8b8af0
+
8b8af0
+    printf("ok\n");
8b8af0
+}
8b8af0
+
8b8af0
+/*
8b8af0
+ * List all users in database
8b8af0
+ */
8b8af0
+
8b8af0
+#include <db.h>
8b8af0
+
8b8af0
+#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
8b8af0
+/*
8b8af0
+ * Open the database
8b8af0
+ *
8b8af0
+ */
8b8af0
+static int berkeleydb_open(const char *path,DB **mbdb)
8b8af0
+{
8b8af0
+    int ret;
8b8af0
+
8b8af0
+#if DB_VERSION_FULL < 0x03000000
8b8af0
+    ret = db_open(path, DB_HASH, DB_CREATE, 0664, NULL, NULL, mbdb);
8b8af0
+#else /* DB_VERSION_FULL < 0x03000000 */
8b8af0
+    ret = db_create(mbdb, NULL, 0);
8b8af0
+    if (ret == 0 && *mbdb != NULL)
8b8af0
+    {
8b8af0
+#if DB_VERSION_FULL >= 0x04010000
8b8af0
+	ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664);
8b8af0
+#else
8b8af0
+	ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664);
8b8af0
+#endif
8b8af0
+	if (ret != 0)
8b8af0
+	{
8b8af0
+	    (void) (*mbdb)->close(*mbdb, 0);
8b8af0
+	    *mbdb = NULL;
8b8af0
+	}
8b8af0
+    }
8b8af0
+#endif /* DB_VERSION_FULL < 0x03000000 */
8b8af0
+
8b8af0
+    if (ret != 0) {
8b8af0
+	fprintf(stderr,"Error opening password file %s\n", path);
8b8af0
+	return SASL_FAIL;
8b8af0
+    }
8b8af0
+
8b8af0
+    return SASL_OK;
8b8af0
+}
8b8af0
+
8b8af0
+/*
8b8af0
+ * Close the database
8b8af0
+ *
8b8af0
+ */
8b8af0
+
8b8af0
+static void berkeleydb_close(DB *mbdb)
8b8af0
+{
8b8af0
+    int ret;
8b8af0
+    
8b8af0
+    ret = mbdb->close(mbdb, 0);
8b8af0
+    if (ret!=0) {
8b8af0
+	fprintf(stderr,"error closing sasldb: %s",
8b8af0
+		db_strerror(ret));
8b8af0
+    }
8b8af0
+}
8b8af0
+
8b8af0
+int listusers(const char *path, listcb_t *cb)
8b8af0
+{
8b8af0
+    int result;
8b8af0
+    DB *mbdb = NULL;
8b8af0
+    DBC *cursor;
8b8af0
+    DBT key, data;
8b8af0
+
8b8af0
+    /* open the db */
8b8af0
+    result=berkeleydb_open(path, &mbdb);
8b8af0
+    if (result!=SASL_OK) goto cleanup;
8b8af0
+
8b8af0
+    /* make cursor */
8b8af0
+#if DB_VERSION_FULL < 0x03060000
8b8af0
+    result = mbdb->cursor(mbdb, NULL,&cursor); 
8b8af0
+#else
8b8af0
+    result = mbdb->cursor(mbdb, NULL,&cursor, 0); 
8b8af0
+#endif /* DB_VERSION_FULL < 0x03060000 */
8b8af0
+
8b8af0
+    if (result!=0) {
8b8af0
+	fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result));
8b8af0
+      result = SASL_FAIL;
8b8af0
+      goto cleanup;
8b8af0
+    }
8b8af0
+
8b8af0
+    memset(&key,0, sizeof(key));
8b8af0
+    memset(&data,0,sizeof(data));
8b8af0
+
8b8af0
+    /* loop thru */
8b8af0
+    result = cursor->c_get(cursor, &key, &data,
8b8af0
+			   DB_FIRST);
8b8af0
+
8b8af0
+    while (result != DB_NOTFOUND)
8b8af0
+    {
8b8af0
+	char *authid;
8b8af0
+	char *realm;
8b8af0
+	char *tmp;
8b8af0
+	unsigned int len;
8b8af0
+	char prop[1024];
8b8af0
+	int numnulls = 0;
8b8af0
+	unsigned int lup;
8b8af0
+
8b8af0
+	/* make sure there are exactly 2 null's */
8b8af0
+	for (lup=0;lup
8b8af0
+	    if (((char *)key.data)[lup]=='\0')
8b8af0
+		numnulls++;
8b8af0
+
8b8af0
+	if (numnulls != 2) {
8b8af0
+	    fprintf(stderr,"warning: probable database corruption\n");
8b8af0
+	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
8b8af0
+	    continue;
8b8af0
+	}
8b8af0
+
8b8af0
+	authid = key.data;
8b8af0
+	realm  = authid + strlen(authid)+1;
8b8af0
+	tmp    = realm + strlen(realm)+1;
8b8af0
+	len = key.size - (tmp - authid);
8b8af0
+
8b8af0
+	/* make sure we have enough space of prop */
8b8af0
+	if (len >=sizeof(prop)) {
8b8af0
+	    fprintf(stderr,"warning: absurdly long prop name\n");
8b8af0
+	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
8b8af0
+	    continue;
8b8af0
+	}
8b8af0
+
8b8af0
+	memcpy(prop, tmp, key.size - (tmp - ((char *)key.data)));
8b8af0
+	prop[key.size - (tmp - ((char *)key.data))] = '\0';
8b8af0
+
8b8af0
+	if (*authid) {
8b8af0
+	    /* don't check return values */
8b8af0
+	    cb(authid,realm,prop,data.data,data.size);
8b8af0
+	}
8b8af0
+
8b8af0
+	result = cursor->c_get(cursor, &key, &data, DB_NEXT);
8b8af0
+    }
8b8af0
+
8b8af0
+    if (result != DB_NOTFOUND) {
8b8af0
+	fprintf(stderr,"failure: %s\n",db_strerror(result));
8b8af0
+	result = SASL_FAIL;
8b8af0
+	goto cleanup;
8b8af0
+    }
8b8af0
+
8b8af0
+    result = cursor->c_close(cursor);
8b8af0
+    if (result != 0) {
8b8af0
+        result = SASL_FAIL;
8b8af0
+        goto cleanup;
8b8af0
+    }
8b8af0
+
8b8af0
+    result = SASL_OK;
8b8af0
+
8b8af0
+ cleanup:
8b8af0
+
8b8af0
+    if (mbdb != NULL) berkeleydb_close(mbdb);
8b8af0
+    return result;
8b8af0
+}
8b8af0
+
8b8af0
+
8b8af0
+char *db = NULL, *db_new=NULL;
8b8af0
+
8b8af0
+int good_getopt(void *context __attribute__((unused)), 
8b8af0
+		const char *plugin_name __attribute__((unused)), 
8b8af0
+		const char *option,
8b8af0
+		const char **result,
8b8af0
+		unsigned *len)
8b8af0
+{
8b8af0
+    if (db_new && !strcmp(option, "sasldb_path")) {
8b8af0
+	*result = db_new;
8b8af0
+	if (len)
8b8af0
+	    *len = strlen(db_new);
8b8af0
+	return SASL_OK;
8b8af0
+    }
8b8af0
+
8b8af0
+    return SASL_FAIL;
8b8af0
+}
8b8af0
+
8b8af0
+static struct sasl_callback goodsasl_cb[] = {
8b8af0
+    { SASL_CB_GETOPT, (int (*)(void))&good_getopt, NULL },
8b8af0
+    { SASL_CB_LIST_END, NULL, NULL }
8b8af0
+};
8b8af0
+
8b8af0
+int main(int argc, char **argv)
8b8af0
+{
8b8af0
+    int result;
8b8af0
+    FILE *f;
8b8af0
+
8b8af0
+    if (argc != 3) {
8b8af0
+	fprintf(stderr, "Usage: cyrusbdb2current old_sasldb new_sasldb\n");
8b8af0
+	fprintf(stderr, "old_sasldb is presumably /etc/sasldb2\n");
8b8af0
+       	fprintf(stderr, "new_sasldb is presumably /etc/sasl2/sasldb2\n");
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+    db = argv[1];
8b8af0
+    db_new = argv[2];
8b8af0
+
8b8af0
+    if (strcmp(db, db_new) == 0) {
8b8af0
+	fprintf(stderr, "Old and new files should be different\n");
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+
8b8af0
+    f = fopen(db_new, "rb");
8b8af0
+    if (f != NULL) {
8b8af0
+	fprintf(stderr, "The specified target file %s already exists\n", db_new);
8b8af0
+	fclose(f);
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+    result = sasl_server_init(goodsasl_cb, "dbconverter");
8b8af0
+    if (result != SASL_OK) {
8b8af0
+	fprintf(stderr, "couldn't init saslv2\n");
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+    result = sasl_server_new("sasldb",
8b8af0
+			     "localhost",
8b8af0
+			     NULL,
8b8af0
+			     NULL,
8b8af0
+			     NULL,
8b8af0
+			     NULL,
8b8af0
+			     0,
8b8af0
+			     &globalconn);
8b8af0
+    if (result != SASL_OK) {
8b8af0
+	fprintf(stderr, "couldn't create globalconn\n");
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+    if(_sasl_check_db(sasl_global_utils,globalconn) != SASL_OK) {
8b8af0
+	fprintf(stderr, "target DB %s is not OK\n", db_new);
8b8af0
+	return 1;
8b8af0
+    }
8b8af0
+
8b8af0
+    printf("\nThis program will take the sasldb file specified on the\n"
8b8af0
+           "command line and convert it to a new sasldb specified\n"
8b8af0
+           "on the command line. It is STRONGLY RECOMMENDED that you\n"
8b8af0
+           "backup sasldb before allowing this program to run\n\n"
8b8af0
+	   "We are going to convert %s and our output will be in %s\n\n"
8b8af0
+           "Press return to continue\n", db, db_new);
8b8af0
+
8b8af0
+    getchar();
8b8af0
+
8b8af0
+    listusers(db, (listcb_t *) &listusers_cb);
8b8af0
+
8b8af0
+    sasl_dispose(&globalconn);
8b8af0
+    sasl_done();
8b8af0
+
8b8af0
+    exit(0);
8b8af0
+}
8b8af0
diff -up cyrus-sasl-2.1.27/utils/Makefile.am.frombdb cyrus-sasl-2.1.27/utils/Makefile.am
8b8af0
--- cyrus-sasl-2.1.27/utils/Makefile.am.frombdb	2018-10-05 16:40:16.000000000 +0200
8b8af0
+++ cyrus-sasl-2.1.27/utils/Makefile.am	2021-06-04 13:02:07.798112327 +0200
8b8af0
@@ -46,14 +46,14 @@ all_sasl_libs = ../lib/libsasl2.la $(SAS
8b8af0
 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)
8b8af0
 
8b8af0
 sbin_PROGRAMS = @SASL_DB_UTILS@ @SMTPTEST_PROGRAM@ pluginviewer
8b8af0
-EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest pluginviewer
8b8af0
+EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest pluginviewer cyrusbdb2current
8b8af0
 
8b8af0
 noinst_PROGRAMS = dbconverter-2
8b8af0
 
8b8af0
 if NO_SASL_DB_MANS
8b8af0
 man_MANS = 
8b8af0
 else
8b8af0
-man_MANS = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8
8b8af0
+man_MANS = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8 cyrusbdb2current.8
8b8af0
 endif
8b8af0
 
8b8af0
 saslpasswd2_LDADD = ../sasldb/libsasldb.la $(all_sasl_libs)
8b8af0
@@ -63,6 +63,7 @@ sasldblistusers2_SOURCES = sasldblistuse
8b8af0
 dbconverter_2_LDADD = ../sasldb/libsasldb.la $(all_sasl_libs)
8b8af0
 pluginviewer_LDADD = $(all_sasl_libs)
8b8af0
 pluginviewer_SOURCES = pluginviewer.c
8b8af0
+cyrusbdb2current_LDADD = ../sasldb/libsasldb.la @BDB_STATIC_LIBADD@ $(all_sasl_libs)
8b8af0
 
8b8af0
 testsuite_LDADD = $(all_sasl_libs) @DMALLOC_LIBS@
8b8af0