From 603501ec6bbe6ee9b3f033e924a4eef2a4925aa7 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Jan 20 2015 19:46:09 +0000 Subject: Ticket 47462 - Stop using DES in the reversible password encryption plug-in Bug Description: DES is not a safe cipher to use for Password Based Encryption(pbe). AES should be used instead. Fix Description: Use AES for all new password encodings. AES requires that the algorithm ID used to encode the password, must also be used to decode it. So, the algorithm ID is now stored in the cipher prefix: {AES-} Since DES is no longer being used, the library has been renamed to a more apprpriate name: libdes-plugin -> libpbe-plugin During upgrades the DES plugin entry has its library path updated to use libpbe-plugin. The MMR plugin changes its dependency from DES to AES, and the AES plugin entry is added, and all the password attributes found in the old DES Plugin are migrated over to the new AES Plugin entry. When the server is restarted it checks for any DES passwords in the database and cn=config. If any are found they are converted to AES, and the DES plugin is disabled. Also created a new operation flag: SLAPI_OP_FLAG_IGNORE_UNINDEXED This flag prevents an internal unnidexed search from being logged in the "errors" log. When the server starts up it can potentially do unindexed searches while looking for DES passwords. We don't want this log "noise" in the errors log everytime the server starts. https://fedorahosted.org/389/ticket/47462 Design Doc: http://www.port389.org/docs/389ds/design/pbe.html Valgrind: Passed Reviewed by: nhosoi(Thanks!) (cherry picked from commit a57494fcaffccb6fdd060a93ba605d432e38bc09) --- diff --git a/Makefile.am b/Makefile.am index 049ff74..17aadff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -225,7 +225,7 @@ endif serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \ libautomember-plugin.la libback-ldbm.la libchainingdb-plugin.la \ libcollation-plugin.la libcos-plugin.la libderef-plugin.la \ - libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \ + libpbe-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \ liblinkedattrs-plugin.la libmanagedentries-plugin.la \ libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \ libcontentsync-plugin.la \ @@ -583,7 +583,9 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \ ldap/admin/src/scripts/82targetuniqueidindex.pl \ ldap/admin/src/scripts/90subtreerename.pl \ ldap/admin/src/scripts/91subtreereindex.pl \ + ldap/admin/src/scripts/50AES-pbe-plugin.ldif\ ldap/admin/src/scripts/50updateconfig.ldif \ + ldap/admin/src/scripts/52updateAESplugin.pl \ ldap/admin/src/scripts/dnaplugindepends.ldif update_SCRIPTS = ldap/admin/src/scripts/exampleupdate.sh @@ -1016,14 +1018,14 @@ libderef_plugin_la_LIBADD = libslapd.la $(LDAPSDK_LINK) $(NSPR_LINK) libderef_plugin_la_LDFLAGS = -avoid-version #------------------------ -# libdes-plugin +# libpbe-plugin #----------------------- -libdes_plugin_la_SOURCES = ldap/servers/plugins/rever/des.c \ +libpbe_plugin_la_SOURCES = ldap/servers/plugins/rever/pbe.c \ ldap/servers/plugins/rever/rever.c -libdes_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @svrcore_inc@ -libdes_plugin_la_LIBADD = libslapd.la $(NSS_LINK) -libdes_plugin_la_LDFLAGS = -avoid-version +libpbe_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @svrcore_inc@ +libpbe_plugin_la_LIBADD = libslapd.la $(NSS_LINK) +libpbe_plugin_la_LDFLAGS = -avoid-version #------------------------ # libdistrib-plugin diff --git a/Makefile.in b/Makefile.in index 24a9ddf..dff7462 100644 --- a/Makefile.in +++ b/Makefile.in @@ -396,15 +396,6 @@ libderef_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libderef_plugin_la_LDFLAGS) \ $(LDFLAGS) -o $@ -libdes_plugin_la_DEPENDENCIES = libslapd.la $(am__DEPENDENCIES_1) -am_libdes_plugin_la_OBJECTS = \ - ldap/servers/plugins/rever/libdes_plugin_la-des.lo \ - ldap/servers/plugins/rever/libdes_plugin_la-rever.lo -libdes_plugin_la_OBJECTS = $(am_libdes_plugin_la_OBJECTS) -libdes_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(libdes_plugin_la_LDFLAGS) $(LDFLAGS) \ - -o $@ libdistrib_plugin_la_DEPENDENCIES = libslapd.la am_libdistrib_plugin_la_OBJECTS = \ ldap/servers/plugins/distrib/libdistrib_plugin_la-distrib.lo @@ -548,6 +539,15 @@ libpassthru_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libpassthru_plugin_la_LDFLAGS) \ $(LDFLAGS) -o $@ +libpbe_plugin_la_DEPENDENCIES = libslapd.la $(am__DEPENDENCIES_1) +am_libpbe_plugin_la_OBJECTS = \ + ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo \ + ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo +libpbe_plugin_la_OBJECTS = $(am_libpbe_plugin_la_OBJECTS) +libpbe_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libpbe_plugin_la_LDFLAGS) $(LDFLAGS) \ + -o $@ libposix_winsync_plugin_la_DEPENDENCIES = libslapd.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libposix_winsync_plugin_la_OBJECTS = ldap/servers/plugins/posix-winsync/libposix_winsync_plugin_la-posix-winsync.lo \ @@ -1154,14 +1154,13 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \ $(libcollation_plugin_la_SOURCES) \ $(libcontentsync_plugin_la_SOURCES) \ $(libcos_plugin_la_SOURCES) $(libderef_plugin_la_SOURCES) \ - $(libdes_plugin_la_SOURCES) $(libdistrib_plugin_la_SOURCES) \ - $(libdna_plugin_la_SOURCES) \ + $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \ $(libhttp_client_plugin_la_SOURCES) \ $(liblinkedattrs_plugin_la_SOURCES) \ $(libmanagedentries_plugin_la_SOURCES) \ $(libmemberof_plugin_la_SOURCES) $(libns_dshttpd_la_SOURCES) \ $(libpam_passthru_plugin_la_SOURCES) \ - $(libpassthru_plugin_la_SOURCES) \ + $(libpassthru_plugin_la_SOURCES) $(libpbe_plugin_la_SOURCES) \ $(libposix_winsync_plugin_la_SOURCES) \ $(libpresence_plugin_la_SOURCES) \ $(libpwdstorage_plugin_la_SOURCES) \ @@ -1190,14 +1189,13 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \ $(libcollation_plugin_la_SOURCES) \ $(libcontentsync_plugin_la_SOURCES) \ $(libcos_plugin_la_SOURCES) $(libderef_plugin_la_SOURCES) \ - $(libdes_plugin_la_SOURCES) $(libdistrib_plugin_la_SOURCES) \ - $(libdna_plugin_la_SOURCES) \ + $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \ $(libhttp_client_plugin_la_SOURCES) \ $(liblinkedattrs_plugin_la_SOURCES) \ $(libmanagedentries_plugin_la_SOURCES) \ $(libmemberof_plugin_la_SOURCES) $(libns_dshttpd_la_SOURCES) \ $(libpam_passthru_plugin_la_SOURCES) \ - $(libpassthru_plugin_la_SOURCES) \ + $(libpassthru_plugin_la_SOURCES) $(libpbe_plugin_la_SOURCES) \ $(libposix_winsync_plugin_la_SOURCES) \ $(libpresence_plugin_la_SOURCES) \ $(libpwdstorage_plugin_la_SOURCES) \ @@ -1637,7 +1635,7 @@ server_LTLIBRARIES = libslapd.la libns-dshttpd.la serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \ libautomember-plugin.la libback-ldbm.la libchainingdb-plugin.la \ libcollation-plugin.la libcos-plugin.la libderef-plugin.la \ - libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \ + libpbe-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \ liblinkedattrs-plugin.la libmanagedentries-plugin.la \ libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \ libcontentsync-plugin.la \ @@ -1991,7 +1989,9 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \ ldap/admin/src/scripts/82targetuniqueidindex.pl \ ldap/admin/src/scripts/90subtreerename.pl \ ldap/admin/src/scripts/91subtreereindex.pl \ + ldap/admin/src/scripts/50AES-pbe-plugin.ldif\ ldap/admin/src/scripts/50updateconfig.ldif \ + ldap/admin/src/scripts/52updateAESplugin.pl \ ldap/admin/src/scripts/dnaplugindepends.ldif update_SCRIPTS = ldap/admin/src/scripts/exampleupdate.sh @@ -2363,14 +2363,14 @@ libderef_plugin_la_LIBADD = libslapd.la $(LDAPSDK_LINK) $(NSPR_LINK) libderef_plugin_la_LDFLAGS = -avoid-version #------------------------ -# libdes-plugin +# libpbe-plugin #----------------------- -libdes_plugin_la_SOURCES = ldap/servers/plugins/rever/des.c \ +libpbe_plugin_la_SOURCES = ldap/servers/plugins/rever/pbe.c \ ldap/servers/plugins/rever/rever.c -libdes_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @svrcore_inc@ -libdes_plugin_la_LIBADD = libslapd.la $(NSS_LINK) -libdes_plugin_la_LDFLAGS = -avoid-version +libpbe_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @svrcore_inc@ +libpbe_plugin_la_LIBADD = libslapd.la $(NSS_LINK) +libpbe_plugin_la_LDFLAGS = -avoid-version #------------------------ # libdistrib-plugin @@ -3596,21 +3596,6 @@ ldap/servers/plugins/deref/libderef_plugin_la-deref.lo: \ libderef-plugin.la: $(libderef_plugin_la_OBJECTS) $(libderef_plugin_la_DEPENDENCIES) $(EXTRA_libderef_plugin_la_DEPENDENCIES) $(AM_V_CCLD)$(libderef_plugin_la_LINK) -rpath $(serverplugindir) $(libderef_plugin_la_OBJECTS) $(libderef_plugin_la_LIBADD) $(LIBS) -ldap/servers/plugins/rever/$(am__dirstamp): - @$(MKDIR_P) ldap/servers/plugins/rever - @: > ldap/servers/plugins/rever/$(am__dirstamp) -ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) ldap/servers/plugins/rever/$(DEPDIR) - @: > ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) -ldap/servers/plugins/rever/libdes_plugin_la-des.lo: \ - ldap/servers/plugins/rever/$(am__dirstamp) \ - ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) -ldap/servers/plugins/rever/libdes_plugin_la-rever.lo: \ - ldap/servers/plugins/rever/$(am__dirstamp) \ - ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) - -libdes-plugin.la: $(libdes_plugin_la_OBJECTS) $(libdes_plugin_la_DEPENDENCIES) $(EXTRA_libdes_plugin_la_DEPENDENCIES) - $(AM_V_CCLD)$(libdes_plugin_la_LINK) -rpath $(serverplugindir) $(libdes_plugin_la_OBJECTS) $(libdes_plugin_la_LIBADD) $(LIBS) ldap/servers/plugins/distrib/$(am__dirstamp): @$(MKDIR_P) ldap/servers/plugins/distrib @: > ldap/servers/plugins/distrib/$(am__dirstamp) @@ -3900,6 +3885,21 @@ ldap/servers/plugins/passthru/libpassthru_plugin_la-ptutil.lo: \ libpassthru-plugin.la: $(libpassthru_plugin_la_OBJECTS) $(libpassthru_plugin_la_DEPENDENCIES) $(EXTRA_libpassthru_plugin_la_DEPENDENCIES) $(AM_V_CCLD)$(libpassthru_plugin_la_LINK) -rpath $(serverplugindir) $(libpassthru_plugin_la_OBJECTS) $(libpassthru_plugin_la_LIBADD) $(LIBS) +ldap/servers/plugins/rever/$(am__dirstamp): + @$(MKDIR_P) ldap/servers/plugins/rever + @: > ldap/servers/plugins/rever/$(am__dirstamp) +ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ldap/servers/plugins/rever/$(DEPDIR) + @: > ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) +ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo: \ + ldap/servers/plugins/rever/$(am__dirstamp) \ + ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) +ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo: \ + ldap/servers/plugins/rever/$(am__dirstamp) \ + ldap/servers/plugins/rever/$(DEPDIR)/$(am__dirstamp) + +libpbe-plugin.la: $(libpbe_plugin_la_OBJECTS) $(libpbe_plugin_la_DEPENDENCIES) $(EXTRA_libpbe_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(libpbe_plugin_la_LINK) -rpath $(serverplugindir) $(libpbe_plugin_la_OBJECTS) $(libpbe_plugin_la_LIBADD) $(LIBS) ldap/servers/plugins/posix-winsync/$(am__dirstamp): @$(MKDIR_P) ldap/servers/plugins/posix-winsync @: > ldap/servers/plugins/posix-winsync/$(am__dirstamp) @@ -5441,8 +5441,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/retrocl/$(DEPDIR)/libretrocl_plugin_la-retrocl_po.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/retrocl/$(DEPDIR)/libretrocl_plugin_la-retrocl_rootdse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/retrocl/$(DEPDIR)/libretrocl_plugin_la-retrocl_trim.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-des.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-pbe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-rever.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo@am__quote@ @@ -6739,20 +6739,6 @@ ldap/servers/plugins/deref/libderef_plugin_la-deref.lo: ldap/servers/plugins/der @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libderef_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/deref/libderef_plugin_la-deref.lo `test -f 'ldap/servers/plugins/deref/deref.c' || echo '$(srcdir)/'`ldap/servers/plugins/deref/deref.c -ldap/servers/plugins/rever/libdes_plugin_la-des.lo: ldap/servers/plugins/rever/des.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdes_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/rever/libdes_plugin_la-des.lo -MD -MP -MF ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-des.Tpo -c -o ldap/servers/plugins/rever/libdes_plugin_la-des.lo `test -f 'ldap/servers/plugins/rever/des.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/des.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-des.Tpo ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-des.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap/servers/plugins/rever/des.c' object='ldap/servers/plugins/rever/libdes_plugin_la-des.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdes_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/rever/libdes_plugin_la-des.lo `test -f 'ldap/servers/plugins/rever/des.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/des.c - -ldap/servers/plugins/rever/libdes_plugin_la-rever.lo: ldap/servers/plugins/rever/rever.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdes_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/rever/libdes_plugin_la-rever.lo -MD -MP -MF ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Tpo -c -o ldap/servers/plugins/rever/libdes_plugin_la-rever.lo `test -f 'ldap/servers/plugins/rever/rever.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/rever.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Tpo ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap/servers/plugins/rever/rever.c' object='ldap/servers/plugins/rever/libdes_plugin_la-rever.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdes_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/rever/libdes_plugin_la-rever.lo `test -f 'ldap/servers/plugins/rever/rever.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/rever.c - ldap/servers/plugins/distrib/libdistrib_plugin_la-distrib.lo: ldap/servers/plugins/distrib/distrib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdistrib_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/distrib/libdistrib_plugin_la-distrib.lo -MD -MP -MF ldap/servers/plugins/distrib/$(DEPDIR)/libdistrib_plugin_la-distrib.Tpo -c -o ldap/servers/plugins/distrib/libdistrib_plugin_la-distrib.lo `test -f 'ldap/servers/plugins/distrib/distrib.c' || echo '$(srcdir)/'`ldap/servers/plugins/distrib/distrib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/distrib/$(DEPDIR)/libdistrib_plugin_la-distrib.Tpo ldap/servers/plugins/distrib/$(DEPDIR)/libdistrib_plugin_la-distrib.Plo @@ -6991,6 +6977,20 @@ ldap/servers/plugins/passthru/libpassthru_plugin_la-ptutil.lo: ldap/servers/plug @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpassthru_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/passthru/libpassthru_plugin_la-ptutil.lo `test -f 'ldap/servers/plugins/passthru/ptutil.c' || echo '$(srcdir)/'`ldap/servers/plugins/passthru/ptutil.c +ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo: ldap/servers/plugins/rever/pbe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpbe_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo -MD -MP -MF ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-pbe.Tpo -c -o ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo `test -f 'ldap/servers/plugins/rever/pbe.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/pbe.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-pbe.Tpo ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-pbe.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap/servers/plugins/rever/pbe.c' object='ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpbe_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo `test -f 'ldap/servers/plugins/rever/pbe.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/pbe.c + +ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo: ldap/servers/plugins/rever/rever.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpbe_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo -MD -MP -MF ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-rever.Tpo -c -o ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo `test -f 'ldap/servers/plugins/rever/rever.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/rever.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-rever.Tpo ldap/servers/plugins/rever/$(DEPDIR)/libpbe_plugin_la-rever.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap/servers/plugins/rever/rever.c' object='ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpbe_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo `test -f 'ldap/servers/plugins/rever/rever.c' || echo '$(srcdir)/'`ldap/servers/plugins/rever/rever.c + ldap/servers/plugins/posix-winsync/libposix_winsync_plugin_la-posix-winsync.lo: ldap/servers/plugins/posix-winsync/posix-winsync.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libposix_winsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/posix-winsync/libposix_winsync_plugin_la-posix-winsync.lo -MD -MP -MF ldap/servers/plugins/posix-winsync/$(DEPDIR)/libposix_winsync_plugin_la-posix-winsync.Tpo -c -o ldap/servers/plugins/posix-winsync/libposix_winsync_plugin_la-posix-winsync.lo `test -f 'ldap/servers/plugins/posix-winsync/posix-winsync.c' || echo '$(srcdir)/'`ldap/servers/plugins/posix-winsync/posix-winsync.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/posix-winsync/$(DEPDIR)/libposix_winsync_plugin_la-posix-winsync.Tpo ldap/servers/plugins/posix-winsync/$(DEPDIR)/libposix_winsync_plugin_la-posix-winsync.Plo diff --git a/aclocal.m4 b/aclocal.m4 index 8136dd1..7afd01a 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -220,6 +220,21 @@ m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR + +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])# PKG_CHECK_VAR + # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation diff --git a/config.guess b/config.guess index b79252d..1f5c50c 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -149,7 +149,7 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac @@ -826,7 +826,7 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; - or32:Linux:*:*) + or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) @@ -1260,16 +1260,26 @@ EOF if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; @@ -1361,154 +1371,6 @@ EOF exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 <." version="\ GNU config.sub ($timestamp) -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -257,7 +257,7 @@ case $basic_machine in | avr | avr32 \ | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ @@ -265,6 +265,7 @@ case $basic_machine in | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ @@ -282,8 +283,10 @@ case $basic_machine in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ @@ -295,8 +298,7 @@ case $basic_machine in | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ + | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ @@ -324,7 +326,7 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; @@ -372,7 +374,7 @@ case $basic_machine in | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ @@ -381,6 +383,7 @@ case $basic_machine in | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ @@ -400,8 +403,10 @@ case $basic_machine in | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ @@ -413,6 +418,7 @@ case $basic_machine in | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ @@ -794,7 +800,7 @@ case $basic_machine in os=-mingw64 ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; mingw32ce) @@ -822,6 +828,10 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos @@ -830,7 +840,7 @@ case $basic_machine in basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) - basic_machine=i386-pc + basic_machine=i686-pc os=-msys ;; mvs) @@ -1367,14 +1377,14 @@ case $os in | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1546,6 +1556,9 @@ case $basic_machine in c4x-* | tic4x-*) os=-coff ;; + c8051-*) + os=-elf + ;; hexagon-*) os=-elf ;; @@ -1589,9 +1602,6 @@ case $basic_machine in mips*-*) os=-elf ;; - or1k-*) - os=-elf - ;; or32-*) os=-coff ;; diff --git a/dirsrvtests/tickets/ticket47462_test.py b/dirsrvtests/tickets/ticket47462_test.py new file mode 100644 index 0000000..a909b37 --- /dev/null +++ b/dirsrvtests/tickets/ticket47462_test.py @@ -0,0 +1,452 @@ +import os +import sys +import time +import ldap +import logging +import socket +import time +import logging +import pytest +import re +from lib389 import DirSrv, Entry, tools +from lib389.tools import DirSrvTools +from lib389._constants import * +from lib389.properties import * +from constants import * +from lib389._constants import * + +logging.getLogger(__name__).setLevel(logging.DEBUG) +log = logging.getLogger(__name__) + +# +# important part. We can deploy Master1 and Master2 on different versions +# +installation1_prefix = None +installation2_prefix = None + +DES_PLUGIN = 'cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config' +AES_PLUGIN = 'cn=AES,cn=Password Storage Schemes,cn=plugins,cn=config' +MMR_PLUGIN = 'cn=Multimaster Replication Plugin,cn=plugins,cn=config' +AGMT_DN = '' +USER_DN = 'cn=test_user,' + DEFAULT_SUFFIX +USER1_DN = 'cn=test_user1,' + DEFAULT_SUFFIX +TEST_REPL_DN = 'cn=test repl,' + DEFAULT_SUFFIX + + +class TopologyMaster1Master2(object): + def __init__(self, master1, master2): + master1.open() + self.master1 = master1 + + master2.open() + self.master2 = master2 + + +@pytest.fixture(scope="module") +def topology(request): + ''' + This fixture is used to create a replicated topology for the 'module'. + The replicated topology is MASTER1 <-> Master2. + At the beginning, It may exists a master2 instance and/or a master2 instance. + It may also exists a backup for the master1 and/or the master2. + + Principle: + If master1 instance exists: + restart it + If master2 instance exists: + restart it + If backup of master1 AND backup of master2 exists: + create or rebind to master1 + create or rebind to master2 + + restore master1 from backup + restore master2 from backup + else: + Cleanup everything + remove instances + remove backups + Create instances + Initialize replication + Create backups + ''' + global installation1_prefix + global installation2_prefix + + # allocate master1 on a given deployement + master1 = DirSrv(verbose=False) + if installation1_prefix: + args_instance[SER_DEPLOYED_DIR] = installation1_prefix + + # Args for the master1 instance + args_instance[SER_HOST] = HOST_MASTER_1 + args_instance[SER_PORT] = PORT_MASTER_1 + args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1 + args_master = args_instance.copy() + master1.allocate(args_master) + + # allocate master1 on a given deployement + master2 = DirSrv(verbose=False) + if installation2_prefix: + args_instance[SER_DEPLOYED_DIR] = installation2_prefix + + # Args for the consumer instance + args_instance[SER_HOST] = HOST_MASTER_2 + args_instance[SER_PORT] = PORT_MASTER_2 + args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2 + args_master = args_instance.copy() + master2.allocate(args_master) + + # Get the status of the backups + backup_master1 = master1.checkBackupFS() + backup_master2 = master2.checkBackupFS() + + # Get the status of the instance and restart it if it exists + instance_master1 = master1.exists() + if instance_master1: + master1.stop(timeout=10) + master1.start(timeout=10) + + instance_master2 = master2.exists() + if instance_master2: + master2.stop(timeout=10) + master2.start(timeout=10) + + if backup_master1 and backup_master2: + # The backups exist, assuming they are correct + # we just re-init the instances with them + if not instance_master1: + master1.create() + # Used to retrieve configuration information (dbdir, confdir...) + master1.open() + + if not instance_master2: + master2.create() + # Used to retrieve configuration information (dbdir, confdir...) + master2.open() + + # restore master1 from backup + master1.stop(timeout=10) + master1.restoreFS(backup_master1) + master1.start(timeout=10) + + # restore master2 from backup + master2.stop(timeout=10) + master2.restoreFS(backup_master2) + master2.start(timeout=10) + else: + # We should be here only in two conditions + # - This is the first time a test involve master-consumer + # so we need to create everything + # - Something weird happened (instance/backup destroyed) + # so we discard everything and recreate all + + # Remove all the backups. So even if we have a specific backup file + # (e.g backup_master) we clear all backups that an instance my have created + if backup_master1: + master1.clearBackupFS() + if backup_master2: + master2.clearBackupFS() + + # Remove all the instances + if instance_master1: + master1.delete() + if instance_master2: + master2.delete() + + # Create the instances + master1.create() + master1.open() + master2.create() + master2.open() + + # + # Now prepare the Master-Consumer topology + # + # First Enable replication + master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1) + master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2) + + # Initialize the supplier->consumer + + properties = {RA_NAME: r'meTo_$host:$port', + RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], + RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], + RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], + RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} + AGMT_DN = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties) + master1.agreement + if not AGMT_DN: + log.fatal("Fail to create a replica agreement") + sys.exit(1) + + log.debug("%s created" % AGMT_DN) + + properties = {RA_NAME: r'meTo_$host:$port', + RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], + RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], + RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], + RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} + master2.agreement.create(suffix=DEFAULT_SUFFIX, host=master1.host, port=master1.port, properties=properties) + + master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2) + master1.waitForReplInit(AGMT_DN) + + # Check replication is working fine + master1.add_s(Entry((TEST_REPL_DN, {'objectclass': "top person".split(), + 'sn': 'test_repl', + 'cn': 'test_repl'}))) + loop = 0 + while loop <= 10: + try: + ent = master2.getEntry(TEST_REPL_DN, ldap.SCOPE_BASE, "(objectclass=*)") + break + except ldap.NO_SUCH_OBJECT: + time.sleep(1) + loop += 1 + if not ent: + log.fatal('Replication is not working!') + assert False + + # Time to create the backups + master1.stop(timeout=10) + master1.backupfile = master1.backupFS() + master1.start(timeout=10) + + master2.stop(timeout=10) + master2.backupfile = master2.backupFS() + master2.start(timeout=10) + + # clear the tmp directory + master1.clearTmpDir(__file__) + + # + # Here we have two instances master and consumer + # with replication working. Either coming from a backup recovery + # or from a fresh (re)init + # Time to return the topology + return TopologyMaster1Master2(master1, master2) + + +def test_ticket47462(topology): + """ + Test that AES properly replaces DES during an update/restart, and that + replication also works correctly. + """ + + # + # First set config as if it's an older version. Set DES to use libdes-plugin, + # MMR to depend on DES, delete the existing AES plugin, and set a DES password + # for the replication agreement. + # + + # + # Add an extra attribute to the DES plugin args + # + try: + topology.master1.modify_s(DES_PLUGIN, + [(ldap.MOD_REPLACE, 'nsslapd-pluginPath', 'libdes-plugin'), + (ldap.MOD_ADD, 'nsslapd-pluginarg2', 'description')]) + + except ldap.LDAPError, e: + log.fatal('Failed to reset DES plugin, error: ' + e.message['desc']) + assert False + + try: + topology.master1.modify_s(MMR_PLUGIN, + [(ldap.MOD_DELETE, 'nsslapd-plugin-depends-on-named', 'AES')]) + + except ldap.NO_SUCH_ATTRIBUTE: + pass + except ldap.LDAPError, e: + log.fatal('Failed to reset DES plugin, error: ' + e.message['desc']) + assert False + + # + # Delete the AES plugin + # + try: + topology.master1.delete_s(AES_PLUGIN) + except ldap.NO_SUCH_OBJECT: + pass + except ldap.LDAPError, e: + log.fatal('Failed to delete AES plugin, error: ' + e.message['desc']) + assert False + + # restart the server so we must use DES plugin + topology.master1.restart(timeout=10) + + # + # Get the agmt dn, and set the password + # + try: + entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'objectclass=nsDS5ReplicationAgreement') + if entry: + agmt_dn = entry[0].dn + log.info('Found agmt dn (%s)' % agmt_dn) + else: + log.fatal('No replication agreements!') + assert False + except ldap.LDAPError, e: + log.fatal('Failed to search for replica credentials: ' + e.message['desc']) + assert False + + try: + properties = {RA_BINDPW: "password"} + topology.master1.agreement.setProperties(None, agmt_dn, None, properties) + log.info('Successfully modified replication agreement') + except ValueError: + log.error('Failed to update replica agreement: ' + AGMT_DN) + assert False + + # + # Check replication works with the new DES password + # + try: + topology.master1.add_s(Entry((USER1_DN, + {'objectclass': "top person".split(), + 'sn': 'sn', + 'cn': 'test_user'}))) + loop = 0 + ent = None + while loop <= 10: + try: + ent = topology.master2.getEntry(USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)") + break + except ldap.NO_SUCH_OBJECT: + time.sleep(1) + loop += 1 + if not ent: + log.fatal('Replication test failed fo user1!') + assert False + else: + log.info('Replication test passed') + except ldap.LDAPError, e: + log.fatal('Failed to add test user: ' + e.message['desc']) + assert False + + # + # Run the upgrade... + # + topology.master1.upgrade('online') + topology.master1.restart(timeout=10) + topology.master2.restart(timeout=10) + + # + # Check that the restart converted existing DES credentials + # + try: + entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'nsDS5ReplicaCredentials=*') + if entry: + val = entry[0].getValue('nsDS5ReplicaCredentials') + if val.startswith('{AES-'): + log.info('The DES credentials have been converted to AES') + else: + log.fatal('Failed to convert credentials from DES to AES!') + assert False + else: + log.fatal('Failed to find any entries with nsDS5ReplicaCredentials ') + assert False + except ldap.LDAPError, e: + log.fatal('Failed to search for replica credentials: ' + e.message['desc']) + assert False + + # + # Check that the AES plugin exists, and has all the attributes listed in DES plugin. + # The attributes might not be in the expected order so check all the attributes. + # + try: + entry = topology.master1.search_s(AES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*') + if not entry[0].hasValue('nsslapd-pluginarg0', 'description') and \ + not entry[0].hasValue('nsslapd-pluginarg1', 'description') and \ + not entry[0].hasValue('nsslapd-pluginarg2', 'description'): + log.fatal('The AES plugin did not have the DES attribute copied over correctly') + assert False + else: + log.info('The AES plugin was correctly setup') + except ldap.LDAPError, e: + log.fatal('Failed to find AES plugin: ' + e.message['desc']) + assert False + + # + # Check that the MMR plugin was updated + # + try: + entry = topology.master1.search_s(MMR_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*') + if not entry[0].hasValue('nsslapd-plugin-depends-on-named', 'AES'): + log.fatal('The MMR Plugin was not correctly updated') + assert False + else: + log.info('The MMR plugin was correctly updated') + except ldap.LDAPError, e: + log.fatal('Failed to find AES plugin: ' + e.message['desc']) + assert False + + # + # Check that the DES plugin was correctly updated + # + try: + entry = topology.master1.search_s(DES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*') + if not entry[0].hasValue('nsslapd-pluginPath', 'libpbe-plugin'): + log.fatal('The DES Plugin was not correctly updated') + assert False + else: + log.info('The DES plugin was correctly updated') + except ldap.LDAPError, e: + log.fatal('Failed to find AES plugin: ' + e.message['desc']) + assert False + + # + # Check replication one last time + # + try: + topology.master1.add_s(Entry((USER_DN, + {'objectclass': "top person".split(), + 'sn': 'sn', + 'cn': 'test_user'}))) + loop = 0 + ent = None + while loop <= 10: + try: + ent = topology.master2.getEntry(USER_DN, ldap.SCOPE_BASE, "(objectclass=*)") + break + except ldap.NO_SUCH_OBJECT: + time.sleep(1) + loop += 1 + if not ent: + log.fatal('Replication test failed!') + assert False + else: + log.info('Replication test passed') + except ldap.LDAPError, e: + log.fatal('Failed to add test user: ' + e.message['desc']) + assert False + + # + # If we got here the test passed + # + log.info('Test PASSED') + + +def test_ticket47462_final(topology): + topology.master1.stop(timeout=10) + topology.master2.stop(timeout=10) + + +def run_isolated(): + ''' + run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..) + To run isolated without py.test, you need to + - edit this file and comment '@pytest.fixture' line before 'topology' function. + - set the installation prefix + - run this program + ''' + global installation1_prefix + global installation2_prefix + installation1_prefix = None + installation2_prefix = None + + topo = topology(True) + test_ticket47462(topo) + +if __name__ == '__main__': + run_isolated() diff --git a/ldap/admin/src/scripts/50AES-pbe-plugin.ldif b/ldap/admin/src/scripts/50AES-pbe-plugin.ldif new file mode 100644 index 0000000..564ceae --- /dev/null +++ b/ldap/admin/src/scripts/50AES-pbe-plugin.ldif @@ -0,0 +1,16 @@ +dn: cn=AES,cn=Password Storage Schemes,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +objectclass: extensibleObject +cn: AES +nsslapd-pluginpath: libpbe-plugin +nsslapd-plugininitfunc: aes_init +nsslapd-plugintype: reverpwdstoragescheme +nsslapd-pluginenabled: on +nsslapd-pluginarg0: nsmultiplexorcredentials +nsslapd-pluginarg1: nsds5ReplicaCredentials +nsslapd-pluginprecedence: 1 +nsslapd-pluginid: ID +nsslapd-pluginDescription: DESC +nsslapd-pluginVersion: PACKAGE_VERSION +nsslapd-pluginVendor: VENDOR diff --git a/ldap/admin/src/scripts/52updateAESplugin.pl b/ldap/admin/src/scripts/52updateAESplugin.pl new file mode 100644 index 0000000..6a8a885 --- /dev/null +++ b/ldap/admin/src/scripts/52updateAESplugin.pl @@ -0,0 +1,84 @@ +use Mozilla::LDAP::Conn; +use Mozilla::LDAP::Entry; +use Mozilla::LDAP::Utils qw(normalizeDN); +use Mozilla::LDAP::API qw(:constant ldap_url_parse ldap_explode_dn); +use File::Basename; +use File::Copy; +use DSUtil qw(debug serverIsRunning); + +# +# Check if there is a DES plugin and make sure the AES plugin contains the same attributes +# +sub runinst { + my ($inf, $inst, $dseldif, $conn) = @_; + my @attrs; + my @attrs_to_add; + my $aes_count = 0; + my $des_count = 0; + my $i = 0; + + my $aes_dn = "cn=AES,cn=Password Storage Schemes,cn=plugins,cn=config"; + my $aes_entry = $conn->search($aes_dn, "base", "(cn=*)"); + if (!$aes_entry) { + # No AES plugin - nothing to do + return (); + } + + # We need to grab the AES plugin args... + while(1){ + my $argattr = "nsslapd-pluginarg" . $i; + my $val = $aes_entry->getValues($argattr); + if($val ne ""){ + $attrs[$aes_count] = $val; + $aes_count++; + } else { + last; + } + $i++; + } + + # Grab the DES plugin + my $des_dn = "cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config"; + my $des_entry = $conn->search($des_dn, "base", "(cn=*)"); + if (!$des_entry) { + # No DES plugin - nothing to do + return (); + } + + # We need to check the DES plugin args against the AES args. + $i = 0; + while(1){ + my $argattr = "nsslapd-pluginarg" . $i; + my $val = $des_entry->getValues($argattr); + if($val eq ""){ + last; + } + if(!($val ~~ @attrs) ){ + $attrs_to_add[$des_count] = $val; + $des_count++; + } + $i++; + } + + # Add the missing attributes to the AES plugin + if($#attrs_to_add >= 0){ + foreach $val (@attrs_to_add){ + $aes_entry->addValue("nsslapd-pluginarg" . $aes_count, $val); + $aes_count++; + } + $conn->update($aes_entry); + } + + # Change replication plugin dependency from DES to AES + my $mmr_entry = $conn->search("cn=Multimaster Replication Plugin,cn=plugins,cn=config", "base", "(cn=*)"); + $mmr_entry->removeValue("nsslapd-plugin-depends-on-named", "DES"); + $mmr_entry->addValue("nsslapd-plugin-depends-on-named", "AES"); + $conn->update($mmr_entry); + + # Change the des plugin to use the new libpbe-plugin library + $des_entry->{"nsslapd-pluginPath"} = [ "libpbe-plugin" ]; + $conn->update($des_entry); + + return (); +} + diff --git a/ldap/ldif/50replication-plugins.ldif b/ldap/ldif/50replication-plugins.ldif index 0b4924c..71afbea 100644 --- a/ldap/ldif/50replication-plugins.ldif +++ b/ldap/ldif/50replication-plugins.ldif @@ -22,6 +22,6 @@ nsslapd-plugintype: object nsslapd-pluginbetxn: on nsslapd-pluginenabled: on nsslapd-plugin-depends-on-named: ldbm database -nsslapd-plugin-depends-on-named: DES +nsslapd-plugin-depends-on-named: AES nsslapd-plugin-depends-on-named: Class of Service diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in index 720ebad..6acbfae 100644 --- a/ldap/ldif/template-dse.ldif.in +++ b/ldap/ldif/template-dse.ldif.in @@ -207,12 +207,26 @@ nsslapd-plugininitfunc: ns_mta_md5_pwd_storage_scheme_init nsslapd-plugintype: pwdstoragescheme nsslapd-pluginenabled: on +dn: cn=AES,cn=Password Storage Schemes,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +objectclass: extensibleObject +cn: AES +nsslapd-pluginpath: libpbe-plugin +nsslapd-plugininitfunc: aes_init +nsslapd-plugintype: reverpwdstoragescheme +nsslapd-pluginenabled: on +nsslapd-pluginarg0: nsmultiplexorcredentials +nsslapd-pluginarg1: nsds5ReplicaCredentials +nsslapd-pluginid: aes-storage-scheme +nsslapd-pluginprecedence: 1 + dn: cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config objectclass: top objectclass: nsSlapdPlugin objectclass: extensibleObject cn: DES -nsslapd-pluginpath: libdes-plugin +nsslapd-pluginpath: libpbe-plugin nsslapd-plugininitfunc: des_init nsslapd-plugintype: reverpwdstoragescheme nsslapd-pluginenabled: on diff --git a/ldap/servers/plugins/rever/des.c b/ldap/servers/plugins/rever/des.c deleted file mode 100644 index 73830f0..0000000 --- a/ldap/servers/plugins/rever/des.c +++ /dev/null @@ -1,551 +0,0 @@ -/** BEGIN COPYRIGHT BLOCK - * This Program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; version 2 of the License. - * - * This Program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA. - * - * In addition, as a special exception, Red Hat, Inc. gives You the additional - * right to link the code of this Program with code not covered under the GNU - * General Public License ("Non-GPL Code") and to distribute linked combinations - * including the two, subject to the limitations in this paragraph. Non-GPL Code - * permitted under this exception must only link to the code of this Program - * through those well defined interfaces identified in the file named EXCEPTION - * found in the source code files (the "Approved Interfaces"). The files of - * Non-GPL Code may instantiate templates or use macros or inline functions from - * the Approved Interfaces without causing the resulting work to be covered by - * the GNU General Public License. Only Red Hat, Inc. may make changes or - * additions to the list of Approved Interfaces. You must obey the GNU General - * Public License in all respects for all of the Program code and other code used - * in conjunction with the Program except the Non-GPL Code covered by this - * exception. If you modify this file, you may extend this exception to your - * version of the file, but you are not obligated to do so. If you do not wish to - * provide this exception without modification, you must delete this exception - * statement from your version and license this file solely under the GPL without - * exception. - * - * - * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. - * All rights reserved. - * END COPYRIGHT BLOCK **/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -/* from /usr/project/iplanet/ws/ds5.ke/ns/svrcore/pkcs7/tstarchive.c */ - -#include -#include - -#include -#include -#include -#include -/* -#include -#include -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#define NEED_TOK_DES /* see slap.h - defines tokDes and ptokDes */ -#include "rever.h" -#include -#include "slapi-plugin.h" -#include - - -struct pk11MechItem -{ - CK_MECHANISM_TYPE type; - const char *mechName; -}; -static const struct pk11MechItem mymech = { CKM_DES_CBC, "DES CBC encryption" }; - - -static Slapi_Mutex *mylock = NULL; - -struct pk11ContextStore -{ - PK11SlotInfo *slot; - const struct pk11MechItem *mech; - - PK11SymKey *key; - SECItem *params; - - int length; - unsigned char *crypt; -}; - -static int encode_path(char *inPlain, char **outCipher, char *path); -static int decode_path(char *inCipher, char **outPlain, char *path); -static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path); -static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out); -static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len); -static void freeDes(struct pk11ContextStore *out); - -void -init_des_plugin() -{ - mylock = slapi_new_mutex(); -} - -int -encode(char *inPlain, char **outCipher) -{ - return encode_path(inPlain, outCipher, NULL); -} - -static int -encode_path(char *inPlain, char **outCipher, char *path) -{ - struct pk11ContextStore *context = NULL; - int err; - - unsigned char *cipher = NULL; - char *tmp = NULL; - char *base = NULL; - - - *outCipher = NULL; - err = 1; - - if ( genKey(&context, tokDes, path) == SVRCORE_Success ) - { - /* Try an encryption */ - if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success ) - { - base = BTOA_DataToAscii(cipher, context->length); - if ( base != NULL ) - { - tmp = slapi_ch_malloc( 3 + strlen(REVER_SCHEME_NAME) + strlen(base)); - if ( tmp != NULL ) - { - sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, REVER_SCHEME_NAME, PWD_HASH_PREFIX_END, base); - *outCipher = tmp; - tmp = NULL; - err = 0; - } - PORT_Free(base); - } - } - } - - freeDes(context); - slapi_ch_free((void **) &context); - return(err); -} - -int -decode(char *inCipher, char **outPlain) -{ - return decode_path(inCipher, outPlain, NULL); -} - - -static int -decode_path(char *inCipher, char **outPlain, char *path) -{ - struct pk11ContextStore *context = NULL; - char *plain= NULL; - int err; - - unsigned char *base = NULL; - int len = 0; - - - *outPlain = NULL; - err = 1; - - if ( genKey(&context, tokDes, path) == SVRCORE_Success ) - { - /* it seems that there is memory leak in that function: bug 400170 */ - - base = ATOB_AsciiToData(inCipher, (unsigned int*)&len); - if ( base != NULL ) - { - if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success ) - { - *outPlain = plain; - err = 0; - } - } - } - - PORT_Free(base); - freeDes(context); - slapi_ch_free((void **) &context); - return(err); -} - -static void freeDes(struct pk11ContextStore *out) -{ - if (out) - { - if (out->slot) - slapd_pk11_freeSlot(out->slot); - if (out->key) - slapd_pk11_freeSymKey(out->key); - if (out->params) - SECITEM_FreeItem(out->params,PR_TRUE); - if (out->crypt) - free(out->crypt); - } -} - -static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path) -{ - SVRCOREError err = SVRCORE_Success; - struct pk11ContextStore *store = NULL; - SECItem *pwitem = NULL; - SECItem *result = NULL; - SECAlgorithmID *algid = NULL; - SECOidTag algoid; - SECItem *salt = NULL; - CK_MECHANISM pbeMech; - CK_MECHANISM cryptoMech; - - char *configdir = NULL; - char *iv = NULL; - - store = (struct pk11ContextStore*)slapi_ch_malloc(sizeof(*store)); - if (store == NULL) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - *out = store; - - /* Low-level init */ - store->slot = NULL; - store->key = NULL; - store->params = NULL; - store->crypt = NULL; - - /* Use the tokenName to find a PKCS11 slot */ - store->slot = slapd_pk11_findSlotByName((char *)token); - if (store->slot == NULL) - { - err = SVRCORE_NoSuchToken_Error; - goto done; - } - - /* Generate a key and parameters to do the encryption */ - store->mech = &mymech; - - /* Generate a unique id, used as salt for the key generation */ - if ( path == NULL ) - { - configdir = config_get_configdir(); - if ( configdir == NULL ) - { - err = SVRCORE_System_Error; - goto done; - } - } - else - { - configdir = slapi_ch_strdup(path); - } - if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, configdir, strlen(configdir)) != UID_SUCCESS ) - { - slapi_ch_free((void**)&configdir); - err = SVRCORE_System_Error; - goto done; - } - slapi_ch_free((void**)&configdir); - - pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem)); - if (pwitem == NULL) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - pwitem->type = siBuffer; - pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1); - if (pwitem->data == NULL) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - strcpy((char*)pwitem->data, iv); - pwitem->len = strlen(iv) + 1; - - algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC; - - salt = (SECItem *) PORT_Alloc(sizeof(SECItem)); - if (salt == NULL) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - salt->type = siBuffer; - salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1); - if ( salt->data == NULL ) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - strcpy((char*)salt->data, iv); - salt->len = strlen(iv) + 1; - - algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt); - - slapi_lock_mutex(mylock); - store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0); - if (store->key == 0) - { - slapi_unlock_mutex(mylock); - err = SVRCORE_System_Error; - goto done; - } - - slapi_unlock_mutex(mylock); - pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid); - result = slapd_pk11_paramFromAlgid(algid); - secoid_destroyAlgorithmID(algid, PR_TRUE); - pbeMech.pParameter = result->data; - pbeMech.ulParameterLen = result->len; - if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, - PR_FALSE) != CKR_OK) - { - SECITEM_FreeItem(result, PR_TRUE); - err = SVRCORE_System_Error; - goto done; - } - SECITEM_FreeItem(result, PR_TRUE); - SECITEM_FreeItem(pwitem, PR_TRUE); - SECITEM_FreeItem(salt, PR_TRUE); - store->params = (SECItem *) PORT_Alloc(sizeof(SECItem)); - if (store->params == NULL) - { - err = SVRCORE_System_Error; - goto done; - } - store->params->type = store->mech->type; - store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen); - if (store->params->data == NULL) - { - err = SVRCORE_System_Error; - goto done; - } - memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen); - store->params->len = cryptoMech.ulParameterLen; - PORT_Free(cryptoMech.pParameter); - -done: - slapi_ch_free((void**)&iv); - return (err); -} - -static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len) -{ - SVRCOREError err = SVRCORE_Success; - unsigned char *plain = NULL; - unsigned char *cipher_with_padding = NULL; - SECStatus rv; - PK11Context *ctx = 0; - int outLen = 0; - int blocksize = 0; - - blocksize = slapd_pk11_getBlockSize(store->mech->type, 0); - store->length = len; - - /* store->length is the max. length of the returned clear text - - must be >= length of crypted bytes - also must be a multiple - of blocksize */ - if (blocksize != 0) - { - store->length += blocksize - (store->length % blocksize); - } - - /* plain will hold the returned clear text */ - plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), - store->length+1); - if (!plain) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - - /* create a buffer holding the original cipher bytes, padded with - zeros to a multiple of blocksize - do not need +1 since buffer is not - a string */ - cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), - store->length); - if (!cipher_with_padding) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - memcpy(cipher_with_padding, cipher, len); - - ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT, - store->key, store->params); - if (!ctx) - { - err = SVRCORE_System_Error; - goto done; - } - - /* warning - there is a purify UMR in the NSS des code - you may see it when the - password is not a multiple of 8 bytes long */ - rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length, - cipher_with_padding, store->length); - if (rv) - { - err = SVRCORE_System_Error; - } - - rv = slapd_pk11_finalize(ctx); - /* we must do the finalize, but we only want to set the err return - code if it is not already set */ - if (rv && (SVRCORE_Success == err)) - err = SVRCORE_System_Error; - -done: - if (err == SVRCORE_Success) - { - *out = (char *)plain; - } - else - { - slapi_ch_free((void **)&plain); - } - - slapi_ch_free((void **)&cipher_with_padding); - /* We should free the PK11Context... Something like : */ - if (ctx) slapd_pk11_destroyContext(ctx, PR_TRUE); - - return err; -} - -static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out) -{ - SVRCOREError err = SVRCORE_Success; - SECStatus rv; - PK11Context *ctx = 0; - int outLen = 0; - int blocksize = 0; - unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */ - - blocksize = slapd_pk11_getBlockSize(store->mech->type, 0); - store->length = strlen(clear); - - /* the size of the clear text buffer passed to the des encryption functions - must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer - of this size, copy the clear text password into it, and pad the rest with - zeros */ - if (blocksize != 0) - { - store->length += blocksize - (store->length % blocksize); - } - - /* store->crypt will hold the crypted password - it must be >= clear length */ - /* store->crypt is freed in NSS; let's not use slapi_ch_calloc */ - store->crypt = (unsigned char *)calloc(sizeof(unsigned char), - store->length+1); - if (!store->crypt) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - - /* create a buffer big enough to hold the clear text password and padding */ - clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), - store->length+1); - if (!clear_with_padding) - { - err = SVRCORE_NoMemory_Error; - goto done; - } - /* copy the clear text password into the buffer - the calloc insures the - remainder is zero padded */ - strcpy((char *)clear_with_padding, clear); - - ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT, - store->key, store->params); - if (!ctx) - { - err = SVRCORE_System_Error; - goto done; - } - - rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length, - clear_with_padding, store->length); - if (rv) - { - err = SVRCORE_System_Error; - } - - rv = slapd_pk11_finalize(ctx); - /* we must do the finalize, but we only want to set the err return - code if it is not already set */ - if (rv && (SVRCORE_Success == err)) - err = SVRCORE_System_Error; - -done: - if (err == SVRCORE_Success) - *out = store->crypt; - - slapi_ch_free((void **)&clear_with_padding); - /* We should free the PK11Context... Something like : */ - if (ctx) slapd_pk11_destroyContext(ctx, PR_TRUE); - - return err; -} - -/* - The UUID name based generator was broken on x86 platforms. We use - this to generate the password encryption key. During migration, - we have to fix this so we can use the fixed generator. The env. - var USE_BROKEN_UUID tells the uuid generator to use the old - broken method to create the UUID. That will allow us to decrypt - the password to the correct clear text, then we can turn off - the broken method and use the fixed method to encrypt the - password. -*/ -char * -migrateCredentials(char *oldpath, char *newpath, char *oldcred) -{ - static char *useBrokenUUID = "USE_BROKEN_UUID=1"; - static char *disableBrokenUUID = "USE_BROKEN_UUID=0"; - char *plain = NULL; - char *cipher = NULL; - - init_des_plugin(); - - slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 ); - NSS_NoDB_Init(NULL); - - if (getenv("MIGRATE_BROKEN_PWD")) { - putenv(useBrokenUUID); - } - - if ( decode_path(oldcred, &plain, oldpath) == 0 ) - { - if (getenv("MIGRATE_BROKEN_PWD")) { - putenv(disableBrokenUUID); - } - if ( encode_path(plain, &cipher, newpath) != 0 ) - return(NULL); - else - return(cipher); - } - else - return(NULL); -} diff --git a/ldap/servers/plugins/rever/pbe.c b/ldap/servers/plugins/rever/pbe.c new file mode 100644 index 0000000..abb8d1b --- /dev/null +++ b/ldap/servers/plugins/rever/pbe.c @@ -0,0 +1,621 @@ +/** BEGIN COPYRIGHT BLOCK + * This Program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA. + * + * In addition, as a special exception, Red Hat, Inc. gives You the additional + * right to link the code of this Program with code not covered under the GNU + * General Public License ("Non-GPL Code") and to distribute linked combinations + * including the two, subject to the limitations in this paragraph. Non-GPL Code + * permitted under this exception must only link to the code of this Program + * through those well defined interfaces identified in the file named EXCEPTION + * found in the source code files (the "Approved Interfaces"). The files of + * Non-GPL Code may instantiate templates or use macros or inline functions from + * the Approved Interfaces without causing the resulting work to be covered by + * the GNU General Public License. Only Red Hat, Inc. may make changes or + * additions to the list of Approved Interfaces. You must obey the GNU General + * Public License in all respects for all of the Program code and other code used + * in conjunction with the Program except the Non-GPL Code covered by this + * exception. If you modify this file, you may extend this exception to your + * version of the file, but you are not obligated to do so. If you do not wish to + * provide this exception without modification, you must delete this exception + * statement from your version and license this file solely under the GPL without + * exception. + * + * + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. + * Copyright (C) 2015 Red Hat, Inc. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include +#include +/* +#include +#include +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define NEED_TOK_PBE /* see slap.h - defines tokPBE and ptokPBE */ +#include "rever.h" +#include +#include "slapi-plugin.h" +#include +#include + +struct pk11MechItem +{ + CK_MECHANISM_TYPE type; + const char *mechName; +}; + +static const struct pk11MechItem DESmech = { CKM_DES_CBC, "DES CBC encryption" }; +static const struct pk11MechItem AESmech = { CKM_AES_CBC, "AES CBC encryption" }; +static Slapi_Mutex *pbe_lock = NULL; + +struct pk11ContextStore +{ + PK11SlotInfo *slot; + const struct pk11MechItem *mech; + PK11SymKey *key; + SECItem *params; + int length; + unsigned char *crypt; + char *algid_base64; +}; + +/* + * der_algid converting functions: + * + * SECStatus ATOB_ConvertAsciiToItem(SECItem *binary_item, const char *ascii); + * char * BTOA_ConvertItemToAscii(SECItem *binary_item); + * + */ + +static int encode_path(char *inPlain, char **outCipher, char *path, int mech); +static int decode_path(char *inCipher, char **outPlain, char *path, int mech, char *algid); +static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path, int mech, PRArenaPool *arena, char *algid); +static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out); +static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len); +static void freePBE(struct pk11ContextStore *store); + +void +init_pbe_plugin() +{ + if(!pbe_lock){ + pbe_lock = slapi_new_mutex(); + } +} + +int +encode(char *inPlain, char **outCipher, int mech) +{ + return encode_path(inPlain, outCipher, NULL, mech); +} + +static int +encode_path(char *inPlain, char **outCipher, char *path, int mech) +{ + struct pk11ContextStore *context = NULL; + PRArenaPool *arena = NULL; + unsigned char *cipher = NULL; + char *tmp = NULL; + char *base = NULL; + int len = 0; + int err; + + *outCipher = NULL; + err = 1; + + if ( genKey(&context, tokPBE, path, mech, arena, NULL) == SVRCORE_Success ){ + /* Try an encryption */ + if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success ){ + base = BTOA_DataToAscii(cipher, context->length); + if ( base != NULL ){ + const char *scheme; + if (mech == AES_MECH){ + scheme = AES_REVER_SCHEME_NAME; + len = 3 + strlen(scheme)+ strlen(context->algid_base64) + strlen(base) + 1; + if( (tmp = slapi_ch_malloc( len )) ){ + /* + * {AES-} + */ + sprintf( tmp, "%c%s-%s%c%s", PWD_HASH_PREFIX_START, scheme, + context->algid_base64,PWD_HASH_PREFIX_END, base); + } + } else { + /* Old school DES */ + scheme = DES_REVER_SCHEME_NAME; + if((tmp = slapi_ch_malloc( 3 + strlen(scheme) + strlen(base)))){ + sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, scheme, + PWD_HASH_PREFIX_END, base); + } + } + if ( tmp != NULL ){ + *outCipher = tmp; + tmp = NULL; + err = 0; + } + PORT_Free(base); + } + } + } + freePBE(context); + + return(err); +} + +int +decode(char *inCipher, char **outPlain, int mech, char *algid) +{ + return decode_path(inCipher, outPlain, NULL, mech, algid); +} + + +static int +decode_path(char *inCipher, char **outPlain, char *path, int mech, char *algid) +{ + struct pk11ContextStore *context = NULL; + PRArenaPool *arena = NULL; + unsigned char *base = NULL; + char *plain = NULL; + int err; + int len = 0; + + *outPlain = NULL; + err = 1; + + if ( genKey(&context, tokPBE, path, mech, arena, algid) == SVRCORE_Success ){ + /* it seems that there is memory leak in that function: bug 400170 */ + base = ATOB_AsciiToData(inCipher, (unsigned int*)&len); + if ( base != NULL ){ + if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success ){ + *outPlain = plain; + err = 0; + } + } + } + + slapi_ch_free_string(&algid); + PORT_Free(base); + PORT_FreeArena(arena, PR_TRUE); + freePBE(context); + + return(err); +} + +static void +freePBE(struct pk11ContextStore *store) +{ + if (store){ + if (store->slot) + slapd_pk11_freeSlot(store->slot); + if (store->key) + slapd_pk11_freeSymKey(store->key); + if (store->params) + SECITEM_FreeItem(store->params, PR_TRUE); + slapi_ch_free((void **)&store->crypt); + slapi_ch_free_string(&store->algid_base64); + slapi_ch_free((void **)&store); + } +} + +static SVRCOREError +genKey(struct pk11ContextStore **out, const char *token, char *path, int mech, PRArenaPool *arena, char *alg) +{ + SVRCOREError err = SVRCORE_Success; + struct pk11ContextStore *store = NULL; + SECItem *pwitem = NULL; + SECItem *result = NULL; + SECItem *salt = NULL; + SECItem der_algid; + SECAlgorithmID *algid = NULL; + SECOidTag algoid; + CK_MECHANISM pbeMech; + CK_MECHANISM cryptoMech; + SECAlgorithmID my_algid; + char *configdir = NULL; + char *der_ascii = NULL; + char *iv = NULL; + int free_it = 0; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + + store = (struct pk11ContextStore*)slapi_ch_calloc(1, sizeof(*store)); + if (store == NULL){ + err = SVRCORE_NoMemory_Error; + goto done; + } + *out = store; + + /* Use the tokenName to find a PKCS11 slot */ + store->slot = slapd_pk11_findSlotByName((char *)token); + if (store->slot == NULL){ + err = SVRCORE_NoSuchToken_Error; + goto done; + } + + /* Generate a key and parameters to do the encryption */ + if(mech == AES_MECH){ + store->mech = &AESmech; + algoid = SEC_OID_AES_256_CBC; + } else { + store->mech = &DESmech; + algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC; + } + + /* Generate a unique id, used as salt for the key generation */ + if ( path == NULL ){ + configdir = config_get_configdir(); + if ( configdir == NULL ){ + err = SVRCORE_System_Error; + goto done; + } + } else { + configdir = slapi_ch_strdup(path); + } + if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, configdir, strlen(configdir)) != UID_SUCCESS ){ + err = SVRCORE_System_Error; + goto done; + } + + pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem)); + if (pwitem == NULL){ + err = SVRCORE_NoMemory_Error; + goto done; + } + pwitem->type = siBuffer; + pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1); + if (pwitem->data == NULL){ + err = SVRCORE_NoMemory_Error; + goto done; + } + strcpy((char*)pwitem->data, iv); + pwitem->len = strlen(iv) + 1; + + salt = (SECItem *) PORT_Alloc(sizeof(SECItem)); + if (salt == NULL){ + err = SVRCORE_NoMemory_Error; + goto done; + } + salt->type = siBuffer; + salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1); + if ( salt->data == NULL ){ + err = SVRCORE_NoMemory_Error; + goto done; + } + strcpy((char*)salt->data, iv); + salt->len = strlen(iv) + 1; + + PORT_Memset(&der_algid, 0, sizeof(der_algid)); + if(!alg){ + /* + * This is DES, or we are encoding AES - the process is the same. + */ + algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt); + free_it = 1; /* we need to free this algid */ + + /* + * The following is only need for AES - we need to store + * algid for future decodings(unlike with DES). So convert + * algid to its DER encoding. Then convert the DER to ascii, + * and finally convert the DER ascii to base64 so we can store + * it in the cipher prefix. + */ + SEC_ASN1EncodeItem(arena, &der_algid, algid, SEC_ASN1_GET(SECOID_AlgorithmIDTemplate)); + der_ascii = BTOA_ConvertItemToAscii(&der_algid); + store->algid_base64 = PL_Base64Encode(der_ascii,strlen(der_ascii), NULL); + slapi_ch_free_string(&der_ascii); + } else { + /* + * We are decoding AES - use the supplied algid + */ + PORT_Memset(&my_algid, 0, sizeof(my_algid)); + + /* Decode the base64 der encoding */ + der_ascii = PL_Base64Decode(alg, strlen(alg), NULL); + + /* convert the der ascii to the SEC item */ + ATOB_ConvertAsciiToItem(&der_algid, der_ascii); + SEC_ASN1DecodeItem(arena, &my_algid, SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), &der_algid); + SECITEM_FreeItem(&der_algid, PR_FALSE); + algid = &my_algid; + slapi_ch_free_string(&der_ascii); + } + + slapi_lock_mutex(pbe_lock); + store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0); + if (store->key == 0){ + slapi_unlock_mutex(pbe_lock); + err = SVRCORE_System_Error; + goto done; + } + + slapi_unlock_mutex(pbe_lock); + + if(mech == AES_MECH) + { + cryptoMech.mechanism = PK11_GetPBECryptoMechanism(algid, &store->params, pwitem); + if (cryptoMech.mechanism == CKM_INVALID_MECHANISM) { + err = SVRCORE_System_Error; + goto done; + } + } + else + { + /* DES */ + pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid); + result = slapd_pk11_paramFromAlgid(algid); + if(result){ + pbeMech.pParameter = result->data; + pbeMech.ulParameterLen = result->len; + } + if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, + PR_FALSE) != CKR_OK){ + err = SVRCORE_System_Error; + goto done; + } + + store->params = (SECItem *) PORT_Alloc(sizeof(SECItem)); + if (store->params == NULL){ + err = SVRCORE_System_Error; + goto done; + } + store->params->type = store->mech->type; + store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen); + if (store->params->data == NULL){ + err = SVRCORE_System_Error; + goto done; + } + memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen); + store->params->len = cryptoMech.ulParameterLen; + PORT_Free(cryptoMech.pParameter); + } + +done: + SECITEM_FreeItem(result, PR_TRUE); + SECITEM_FreeItem(pwitem, PR_TRUE); + SECITEM_FreeItem(salt, PR_TRUE); + if(free_it){ + secoid_destroyAlgorithmID(algid, PR_TRUE); + } + slapi_ch_free_string(&configdir); + slapi_ch_free_string(&iv); + if (arena) { + PORT_FreeArena(arena, PR_TRUE); + } + return (err); +} + +static SVRCOREError +decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len) +{ + SVRCOREError err = SVRCORE_Success; + unsigned char *plain = NULL; + unsigned char *cipher_with_padding = NULL; + SECStatus rv; + PK11Context *ctx = NULL; + int outLen = 0; + int blocksize = 0; + + blocksize = slapd_pk11_getBlockSize(store->mech->type, 0); + store->length = len; + + /* + * store->length is the max. length of the returned clear text - + * must be >= length of crypted bytes - also must be a multiple + * of blocksize + */ + if (blocksize != 0){ + store->length += blocksize - (store->length % blocksize); + } + + /* plain will hold the returned clear text */ + plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), + store->length+1); + if (!plain){ + err = SVRCORE_NoMemory_Error; + goto done; + } + + /* + * create a buffer holding the original cipher bytes, padded with + * zeros to a multiple of blocksize - do not need +1 since buffer is not + * a string + */ + cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), + store->length); + if (!cipher_with_padding){ + err = SVRCORE_NoMemory_Error; + goto done; + } + memcpy(cipher_with_padding, cipher, len); + + ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT, + store->key, store->params); + if (!ctx) { + err = SVRCORE_System_Error; + goto done; + } + + /* + * Warning - there is a purify UMR in the NSS des code - you may see it when the + * password is not a multiple of 8 bytes long + */ + rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length, + cipher_with_padding, store->length); + if (rv){ + err = SVRCORE_System_Error; + } + + rv = slapd_pk11_finalize(ctx); + /* + * We must do the finalize, but we only want to set the err return + * code if it is not already set + */ + if (rv && (SVRCORE_Success == err)) + err = SVRCORE_System_Error; + +done: + if (err == SVRCORE_Success){ + *out = (char *)plain; + } else { + slapi_ch_free((void **)&plain); + } + + slapi_ch_free((void **)&cipher_with_padding); + /* We should free the PK11Context... Something like : */ + if (ctx){ + slapd_pk11_destroyContext(ctx, PR_TRUE); + } + + return err; +} + +static SVRCOREError +cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out) +{ + SVRCOREError err = SVRCORE_Success; + SECStatus rv; + PK11Context *ctx = NULL; + unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */ + int blocksize = 0; + int outLen = 0; + + blocksize = slapd_pk11_getBlockSize(store->mech->type, 0); + store->length = strlen(clear); + + /* + * The size of the clear text buffer passed to the encryption functions + * must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer + * of this size, copy the clear text password into it, and pad the rest with + * zeros. + */ + if (blocksize != 0){ + store->length += blocksize - (store->length % blocksize); + } + + /* + * store->crypt will hold the crypted password - it must be >= clear length + * store->crypt is freed in NSS; let's not use slapi_ch_calloc + */ + store->crypt = (unsigned char *)calloc(sizeof(unsigned char), + store->length+1); + if (!store->crypt) { + err = SVRCORE_NoMemory_Error; + goto done; + } + + /* Create a buffer big enough to hold the clear text password and padding */ + clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char), + store->length+1); + if (!clear_with_padding){ + err = SVRCORE_NoMemory_Error; + goto done; + } + /* + * Copy the clear text password into the buffer - the calloc insures the + * remainder is zero padded . + */ + strcpy((char *)clear_with_padding, clear); + + ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT, + store->key, store->params); + if (!ctx) { + err = SVRCORE_System_Error; + goto done; + } + + rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length, + clear_with_padding, store->length); + if (rv) { + err = SVRCORE_System_Error; + } + + rv = slapd_pk11_finalize(ctx); + /* + * We must do the finalize, but we only want to set the err return + * code if it is not already set + */ + if (rv && (SVRCORE_Success == err)){ + err = SVRCORE_System_Error; + } + +done: + if (err == SVRCORE_Success){ + *out = store->crypt; + } + + slapi_ch_free((void **)&clear_with_padding); + /* We should free the PK11Context... Something like : */ + if (ctx){ + slapd_pk11_destroyContext(ctx, PR_TRUE); + } + + return err; +} + +/* + * The UUID name based generator was broken on x86 platforms. We use + * this to generate the password encryption key. During migration, + * we have to fix this so we can use the fixed generator. The env. + * var USE_BROKEN_UUID tells the uuid generator to use the old + * broken method to create the UUID. That will allow us to decrypt + * the password to the correct clear text, then we can turn off + * the broken method and use the fixed method to encrypt the + * password. + */ +char * +migrateCredentials(char *oldpath, char *newpath, char *oldcred) +{ + static char *useBrokenUUID = "USE_BROKEN_UUID=1"; + static char *disableBrokenUUID = "USE_BROKEN_UUID=0"; + char *plain = NULL; + char *cipher = NULL; + + init_pbe_plugin(); + + slapd_pk11_configurePKCS11(NULL, NULL, tokPBE, ptokPBE, NULL, NULL, NULL, NULL, 0, 0 ); + NSS_NoDB_Init(NULL); + + if (getenv("MIGRATE_BROKEN_PWD")) { + putenv(useBrokenUUID); + } + + if ( decode_path(oldcred, &plain, oldpath, DES_MECH, NULL) == 0 ){ + if (getenv("MIGRATE_BROKEN_PWD")) { + putenv(disableBrokenUUID); + } + if ( encode_path(plain, &cipher, newpath, AES_MECH) != 0 ){ + return(NULL); + } else { + return(cipher); + } + } else { + return(NULL); + } +} diff --git a/ldap/servers/plugins/rever/rever.c b/ldap/servers/plugins/rever/rever.c index 9d7e82d..51d602f 100644 --- a/ldap/servers/plugins/rever/rever.c +++ b/ldap/servers/plugins/rever/rever.c @@ -43,25 +43,92 @@ #include #include #include - #include "rever.h" -static Slapi_PluginDesc pdesc = { "des-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "DES storage scheme plugin" }; +static Slapi_PluginDesc pdesc_aes = { "aes-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "AES storage scheme plugin" }; +static Slapi_PluginDesc pdesc_des = { "des-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "DES storage scheme plugin" }; + static char *plugin_name = "ReverStoragePlugin"; +#define AES_MECH 1 +#define DES_MECH 2 + +int +aes_cmp( char *userpwd, char *dbpwd ) +{ + char *cipher = NULL; + int rc = 0; + + if ( encode(userpwd, &cipher, AES_MECH) != 0 ){ + rc = 1; + } else { + rc = strcmp(cipher, dbpwd); + } + slapi_ch_free_string(&cipher); + + return rc; +} + +char * +aes_enc( char *pwd ) +{ + char *cipher = NULL; + + if ( encode(pwd, &cipher, AES_MECH) != 0 ){ + return(NULL); + } else { + return( cipher ); + } +} + +char * +aes_dec( char *pwd, char *alg ) +{ + char *plain = NULL; + + if ( decode(pwd, &plain, AES_MECH, alg) != 0 ){ + return(NULL); + } else { + return( plain ); + } +} + +int +aes_init( Slapi_PBlock *pb) +{ + char *name = slapi_ch_strdup(AES_REVER_SCHEME_NAME); + int rc; + + slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "=> aes_init\n" ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc_aes ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, (void *) aes_enc); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, (void *) aes_cmp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DEC_FN, (void *) aes_dec ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, name ); + + init_pbe_plugin(); + + slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= aes_init %d\n", rc ); + + return( rc ); +} + int des_cmp( char *userpwd, char *dbpwd ) { char *cipher = NULL; int rc = 0; - if ( encode(userpwd, &cipher) != 0 ) + if ( encode(userpwd, &cipher, DES_MECH) != 0 ){ rc = 1; - else + } else { rc = strcmp(cipher, dbpwd); + } + slapi_ch_free_string(&cipher); - slapi_ch_free((void**)&cipher); return rc; } @@ -70,10 +137,11 @@ des_enc( char *pwd ) { char *cipher = NULL; - if ( encode(pwd, &cipher) != 0 ) + if ( encode(pwd, &cipher, DES_MECH ) != 0 ){ return(NULL); - else + } else { return( cipher ); + } } char * @@ -81,37 +149,31 @@ des_dec( char *pwd ) { char *plain = NULL; - if ( decode(pwd, &plain) != 0 ) + if ( decode(pwd, &plain, DES_MECH, NULL) != 0 ){ return(NULL); - else + } else { return( plain ); + } } int des_init( Slapi_PBlock *pb ) { + char *name = slapi_ch_strdup(DES_REVER_SCHEME_NAME); int rc; - char *name; slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "=> des_init\n" ); - rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, - (void *) SLAPI_PLUGIN_VERSION_01 ); - rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, - (void *)&pdesc ); - rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, - (void *) des_enc); - rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, - (void *) des_cmp ); - rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DEC_FN, - (void *) des_dec ); - name = slapi_ch_strdup(REVER_SCHEME_NAME); - rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, - name ); - - init_des_plugin(); - - slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= des_init %d\n\n", rc ); + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc_des ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, (void *) des_enc); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, (void *) des_cmp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DEC_FN, (void *) des_dec ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, name ); + + init_pbe_plugin(); + + slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= des_init %d\n", rc ); return( rc ); } diff --git a/ldap/servers/plugins/rever/rever.h b/ldap/servers/plugins/rever/rever.h index 8ea6279..9edddd8 100644 --- a/ldap/servers/plugins/rever/rever.h +++ b/ldap/servers/plugins/rever/rever.h @@ -49,7 +49,10 @@ #include "slap.h" #include "ldaplog.h" -#define REVER_SCHEME_NAME "DES" +#define AES_MECH 1 +#define DES_MECH 2 +#define AES_REVER_SCHEME_NAME "AES" +#define DES_REVER_SCHEME_NAME "DES" #define PWD_HASH_PREFIX_START '{' #define PWD_HASH_PREFIX_END '}' @@ -58,10 +61,10 @@ int rever_cmp( char *userpwd, char *dbpwd ); char *rever_enc( char *pwd ); char *rever_dec( char *pwd ); int rever_init( Slapi_PBlock *pb ); -void init_des_plugin(); +void init_pbe_plugin(); -int encode(char *inPlain, char ** outCipher); -int decode(char *inCipher, char **outPlain); +int encode(char *inPlain, char **outCipher, int mech); +int decode(char *inCipher, char **outPlain, int mech, char *algid); char *migrateCredentials(char *oldpath, char *newpath, char *oldcred); typedef char *(*migrate_fn_type)(char *, char *, char *); diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c index 0c11238..3cb8451 100644 --- a/ldap/servers/slapd/daemon.c +++ b/ldap/servers/slapd/daemon.c @@ -937,6 +937,244 @@ handle_listeners(Connection_Table *ct, listener_info *listener_idxs, int n_liste return; } +/* + * Convert any pre-existing DES passwords to AES. + * + * Grab the "password" attributes and search all the backends for + * these attributes and convert them to AES if they are DES encoded. + */ +static void +convert_pbe_des_to_aes() +{ + Slapi_PBlock *pb = NULL; + Slapi_Entry **entries = NULL; + struct slapdplugin *plugin = NULL; + char **attrs = NULL; + char **backends = NULL; + char *val = NULL; + int converted_des = 0; + int result = -1; + int have_aes = 0; + int have_des = 0; + int i = 0, ii = 0, be_idx = 0; + + /* + * Check that AES plugin is enabled, and grab all the unique + * password attributes. + */ + for ( plugin = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); + plugin != NULL; + plugin = plugin->plg_next ) + { + char *arg = NULL; + + if(plugin->plg_started && strcasecmp(plugin->plg_name, "AES") == 0){ + /* We have the AES plugin, and its enabled */ + have_aes = 1; + } + if(plugin->plg_started && strcasecmp(plugin->plg_name, "DES") == 0){ + /* We have the DES plugin, and its enabled */ + have_des = 1; + } + /* Gather all the unique password attributes from all the PBE plugins */ + for ( i = 0, arg = plugin->plg_argv[i]; + i < plugin->plg_argc; + arg = plugin->plg_argv[++i] ) + { + if(charray_inlist(attrs, arg)){ + continue; + } + charray_add(&attrs, slapi_ch_strdup(arg)); + } + } + + if(have_aes && have_des){ + /* + * Build a list of all the backend dn's + */ + Slapi_Backend *be = NULL; + struct suffixlist *list; + char *cookie = NULL; + + LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes: " + "Converting DES passwords to AES...\n",0,0,0); + + be = slapi_get_first_backend(&cookie); + while (be){ + int suffix_idx = 0; + int count = slapi_counter_get_value(be->be_suffixcounter); + + list = be->be_suffixlist; + for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) { + char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix); + if(charray_inlist(backends, suffix) || strlen(suffix) == 0){ + list = list->next; + continue; + } + charray_add(&backends, slapi_ch_strdup(suffix)); + list = list->next; + } + be = slapi_get_next_backend (cookie); + } + slapi_ch_free ((void **)&cookie); + + /* + * Search for the password attributes + */ + for (i = 0; attrs && attrs[i]; i++){ + char *filter = PR_smprintf("%s=*", attrs[i]); + /* + * Loop over all the backends looking for the password attribute + */ + for(be_idx = 0; backends[be_idx]; be_idx++){ + pb = slapi_pblock_new(); + slapi_search_internal_set_pb(pb, backends[be_idx], + LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL, + (void *)plugin_get_default_component_id(), + SLAPI_OP_FLAG_IGNORE_UNINDEXED); + slapi_search_internal_pb(pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); + if (LDAP_SUCCESS != result) { + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "failed to search for password on (%s) error (%d)\n", + backends[be_idx], result, 0); + goto done; + } + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); + for (ii = 0; entries && entries[ii]; ii++){ + if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){ + if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){ + /* + * We have a DES encoded password, convert it AES + */ + Slapi_PBlock *mod_pb = NULL; + Slapi_Value *sval = NULL; + LDAPMod mod_replace; + LDAPMod *mods[2]; + char *replace_val[2]; + char *passwd = NULL; + + /* decode the DES password */ + if(pw_rever_decode(val, &passwd, attrs[i]) == -1){ + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "failed to decode existing DES password for (%s)\n", + slapi_entry_get_dn(entries[ii]), 0, 0); + converted_des = 0; + goto done; + } + + /* encode the password */ + sval = slapi_value_new_string(passwd); + if(pw_rever_encode(&sval, attrs[i]) == -1){ + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "failed to encode AES password for (%s)\n", + slapi_entry_get_dn(entries[ii]), 0, 0); + slapi_ch_free_string(&passwd); + slapi_value_free(&sval); + converted_des = 0; + goto done; + } + + /* replace the attribute in the entry */ + replace_val[0] = (char *)slapi_value_get_string(sval); + replace_val[1] = NULL; + mod_replace.mod_op = LDAP_MOD_REPLACE; + mod_replace.mod_type = attrs[i]; + mod_replace.mod_values = replace_val; + mods[0] = &mod_replace; + mods[1] = 0; + + mod_pb = slapi_pblock_new(); + slapi_modify_internal_set_pb(mod_pb, slapi_entry_get_dn(entries[ii]), + mods, 0, 0, (void *)plugin_get_default_component_id(), 0); + slapi_modify_internal_pb(mod_pb); + + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); + if (LDAP_SUCCESS != result) { + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "failed to convert password for (%s) error (%d)\n", + slapi_entry_get_dn(entries[ii]), result, 0); + converted_des = -1; + } else { + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "successfully converted password for (%s)\n", + slapi_entry_get_dn(entries[ii]), result, 0); + converted_des = 1; + + } + slapi_ch_free_string(&passwd); + slapi_value_free(&sval); + slapi_pblock_destroy(mod_pb); + if(result){ + goto done; + } + } + slapi_ch_free_string(&val); + } + } + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + pb = NULL; + } + slapi_ch_free_string(&filter); + } + } + +done: + charray_free(attrs); + charray_free(backends); + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + + if (have_aes && have_des){ + /* + * If a conversion attempt did not fail, disable DES plugin + */ + if(converted_des != -1){ + /* + * Disable the DES plugin - this also prevents potentially expensive + * searches at every server startup. + */ + LDAPMod mod_replace; + LDAPMod *mods[2]; + char *replace_val[2]; + char *des_dn = "cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config"; + + replace_val[0] = "off"; + replace_val[1] = NULL; + mod_replace.mod_op = LDAP_MOD_REPLACE; + mod_replace.mod_type = "nsslapd-pluginEnabled"; + mod_replace.mod_values = replace_val; + mods[0] = &mod_replace; + mods[1] = 0; + + pb = slapi_pblock_new(); + slapi_modify_internal_set_pb(pb, des_dn, mods, 0, 0, + (void *)plugin_get_default_component_id(), 0); + slapi_modify_internal_pb(pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); + if (LDAP_SUCCESS != result) { + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "Failed to disable DES plugin (%s), error (%d)\n", + des_dn, result, 0); + } else { + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "Successfully disabled DES plugin (%s)\n", + des_dn, 0, 0); + } + slapi_pblock_destroy(pb); + } + if(converted_des == 1){ + LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: " + "Finished - all DES passwords have been converted to AES.\n", + 0, 0, 0); + } else if (converted_des == 0){ + LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes: " + "Finished - no DES passwords to convert.\n",0,0,0); + } + } +} + void slapd_daemon( daemon_ports_t *ports ) { /* We are passed some ports---one for regular connections, one @@ -1140,7 +1378,6 @@ void slapd_daemon( daemon_ports_t *ports ) } #endif /* ENABLE_LDAPI */ #endif - listener_idxs = (listener_info *)slapi_ch_calloc(n_listeners, sizeof(*listener_idxs)); /* Now we write the pid file, indicating that the server is finally and listening for connections */ write_pid_file(); @@ -1148,6 +1385,11 @@ void slapd_daemon( daemon_ports_t *ports ) /* The server is ready and listening for connections. Logging "slapd started" message. */ unfurl_banners(the_connection_table,ports,n_tcps,s_tcps,i_unix); + /* + * Convert old DES encoded passwords to AES + */ + convert_pbe_des_to_aes(); + /* The meat of the operation is in a loop on a call to select */ while(!g_get_shutdown()) { diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 48188ed..35b45e3 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -1123,6 +1123,7 @@ void slapd_pk11_DestroyPublicKey(SECKEYPublicKey *key); PRBool slapd_pk11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type); PK11SymKey *slapd_pk11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags, PRBool isPerm); PK11SymKey *slapd_pk11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx); +CK_MECHANISM_TYPE slapd_PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **params, SECItem *pwitem); /* * start_tls_extop.c diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c index 082f69a..43a11c7 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -384,9 +384,8 @@ pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals ) if ((!enc) && (( enc = (*pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )) { return( -1 ); } - - slapi_value_free(&vals[ i ]); - vals[ i ] = slapi_value_new_string_passin(enc); + slapi_value_free(&vals[ i ]); + vals[ i ] = slapi_value_new_string_passin(enc); } return( 0 ); @@ -396,28 +395,57 @@ pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals ) * Check if the prefix of the cipher is the one that is supposed to be * Extract from the whole cipher the encrypted password (remove the prefix) */ -int checkPrefix(char *cipher, char *schemaName, char **encrypt) +int checkPrefix(char *cipher, char *schemaName, char **encrypt, char **algid) { int namelen; /* buf contains the extracted schema name */ char *end, buf[ 3*PWD_MAX_NAME_LEN + 1 ]; + char *delim = NULL; if ( (*cipher == PWD_HASH_PREFIX_START) && - ((end = strchr(cipher, PWD_HASH_PREFIX_END)) != NULL) && - ((namelen = end - cipher - 1 ) <= (3*PWD_MAX_NAME_LEN)) ) + (end = strchr(cipher, PWD_HASH_PREFIX_END)) != NULL) { - memcpy( buf, cipher + 1, namelen ); - buf[ namelen ] = '\0'; - if ( strcasecmp( buf, schemaName) != 0 ) - { - /* schema names are different, error */ - return 1; - } - else - { - /* extract the encrypted password */ - *encrypt = cipher + strlen(schemaName) + 2; - return 0; + if((delim = strchr(cipher, PWD_PBE_DELIM)) != NULL){ + /* + * We have an algid in the prefix: + * + * {AES-} + */ + if((namelen = delim - cipher - 1) <= (3*PWD_MAX_NAME_LEN)){ + memcpy( buf, cipher + 1, namelen ); + buf[ namelen ] = '\0'; + + if ( strcasecmp( buf, schemaName) != 0 ){ + /* schema names are different, error */ + return 1; + } else { + char algid_buf[256]; + + /* extract the algid (length is never greater than 216 */ + memcpy(algid_buf, delim + 1 , (end - delim)); + algid_buf[end - delim - 1] = '\0'; + *algid = strdup(algid_buf); + + /* extract the encrypted password */ + *encrypt = cipher + strlen(*algid) + strlen (schemaName) + 3; + return 0; + } + } + } else if ((namelen = end - cipher - 1 ) <= (3*PWD_MAX_NAME_LEN)){ + /* no delimiter - must be old school DES */ + memcpy( buf, cipher + 1, namelen ); + buf[ namelen ] = '\0'; + if ( strcasecmp( buf, schemaName) != 0 ) + { + /* schema names are different, error */ + return 1; + } + else + { + /* extract the encrypted password */ + *encrypt = cipher + strlen(schemaName) + 2; + return 0; + } } } /* cipher is not prefixed, already in clear ? */ @@ -443,6 +471,7 @@ pw_rever_decode(char *cipher, char **plain, const char * attr_name) char *L_attr = NULL; int i = 0; char *encrypt = NULL; + char *algid = NULL; int prefixOK = -1; /* Get the appropriate decoding function */ @@ -450,10 +479,9 @@ pw_rever_decode(char *cipher, char **plain, const char * attr_name) { if (slapi_attr_types_equivalent(L_attr, attr_name)) { - typedef char * (*ENCFP)(char *); + typedef char * (*ENCFP)(char *, char *); pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme)); - pwsp->pws_dec = (ENCFP)p->plg_pwdstorageschemedec; pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename ); pwsp->pws_len = strlen(pwsp->pws_name) ; @@ -461,7 +489,7 @@ pw_rever_decode(char *cipher, char **plain, const char * attr_name) { /* check that the prefix of the cipher is the same name as the scheme name */ - prefixOK = checkPrefix(cipher, pwsp->pws_name, &encrypt); + prefixOK = checkPrefix(cipher, pwsp->pws_name, &encrypt, &algid); if ( prefixOK == -1 ) { /* no prefix, already in clear ? */ @@ -471,13 +499,15 @@ pw_rever_decode(char *cipher, char **plain, const char * attr_name) } else if ( prefixOK == 1 ) { - /* scheme names are different */ + /* scheme names are different, try the next plugin */ ret_code = -1; - goto free_and_return; + free_pw_scheme( pwsp ); + pwsp = NULL; + continue; } else { - if ( ( *plain = (pwsp->pws_dec)( encrypt )) == NULL ) + if ( ( *plain = (pwsp->pws_dec)( encrypt, algid )) == NULL ) { /* pb during decoding */ ret_code = -1; @@ -536,11 +566,13 @@ pw_rever_encode(Slapi_Value **vals, char * attr_name) for ( i = 0; vals[i] != NULL; ++i ) { char *encrypt = NULL; + char *algid = NULL; int prefixOK; prefixOK = checkPrefix((char*)slapi_value_get_string(vals[i]), pwsp->pws_name, - &encrypt); + &encrypt, &algid); + slapi_ch_free_string(&algid); if ( prefixOK == 0 ) { /* Don't touch already encoded value */ diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h index 7190a1d..79a90a0 100644 --- a/ldap/servers/slapd/pw.h +++ b/ldap/servers/slapd/pw.h @@ -61,7 +61,7 @@ struct pw_scheme *pw_name2scheme( char *name ); struct pw_scheme *pw_val2scheme( char *val, char **valpwdp, int first_is_default ); int pw_encodevals( Slapi_Value **vals ); int pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals ); -int checkPrefix(char *cipher, char *schemaName, char **encrypt); +int checkPrefix(char *cipher, char *schemaName, char **encrypt, char **algid); struct passwordpolicyarray *new_passwdPolicy ( Slapi_PBlock *pb, const char *dn ); void delete_passwdPolicy( struct passwordpolicyarray **pwpolicy); diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c index 2198337..544a9c7 100644 --- a/ldap/servers/slapd/result.c +++ b/ldap/servers/slapd/result.c @@ -2083,7 +2083,8 @@ log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentrie slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype ); if(optype == SLAPI_OPERATION_SEARCH && /* search, */ strcmp(notes_str,"") && /* that's unindexed, */ - !(config_get_accesslog_level() & LDAP_DEBUG_ARGS)) /* and not logged in access log */ + !(config_get_accesslog_level() & LDAP_DEBUG_ARGS) && /* and not logged in access log */ + !(op->o_flags & SLAPI_OP_FLAG_IGNORE_UNINDEXED) ) /* and not ignoring unindexed search */ { struct slapdplugin *plugin = NULL; struct slapi_componentid *cid = NULL; diff --git a/ldap/servers/slapd/security_wrappers.c b/ldap/servers/slapd/security_wrappers.c index 33d512f..4ffda8b 100644 --- a/ldap/servers/slapd/security_wrappers.c +++ b/ldap/servers/slapd/security_wrappers.c @@ -409,3 +409,9 @@ PK11SymKey *slapd_pk11_TokenKeyGenWithFlags(PK11SlotInfo *slot, return PK11_TokenKeyGenWithFlags(slot, type, param, keySize, keyid, opFlags, attrFlags, wincx); } + +CK_MECHANISM_TYPE +slapd_PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **params, SECItem *pwitem) +{ + return PK11_GetPBECryptoMechanism(algid, params, pwitem ); +} diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index d234c13..3db8fe7 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -53,9 +53,9 @@ /* Used by SSL and DES plugin */ -#ifdef NEED_TOK_DES -static char tokDes[34] = "Communicator Generic Crypto Svcs"; -static char ptokDes[34] = "Internal (Software) Token "; +#ifdef NEED_TOK_PBE +static char tokPBE[34] = "Communicator Generic Crypto Svcs"; +static char ptokPBE[34] = "Internal (Software) Token "; #endif /* @@ -307,6 +307,8 @@ typedef void (*VFPV)(); /* takes undefined arguments */ #define ATTR_NETSCAPEMDSUFFIX "netscapemdsuffix" +#define PWD_PBE_DELIM '-' + #define REFERRAL_REMOVE_CMD "remove" /* Filenames for DSE storage */ @@ -1592,7 +1594,7 @@ struct pw_scheme { char *(*pws_enc)( char *pwd ); /* thread-safe decoding function (returns pointer to malloc'd string) */ - char *(*pws_dec)( char *pwd ); + char *(*pws_dec)( char *pwd, char *algid); }; typedef struct passwordpolicyarray { diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index a61d954..41dd2c8 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -222,6 +222,7 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...) #define SLAPI_OP_FLAG_NO_ACCESS_CHECK 0x10000 /* Do not check for access control - bypass them */ #define SLAPI_OP_FLAG_BYPASS_REFERRALS 0x40000 /* Useful for performing internal operations on read-only replica */ #define SLAPI_OP_FLAG_NEVER_CACHE 0x200000 /* added entry should not be kept in cache */ +#define SLAPI_OP_FLAG_IGNORE_UNINDEXED 0x800000 /* Do not log unindexed search */ #define SLAPI_OC_FLAG_REQUIRED 0x0001 #define SLAPI_OC_FLAG_ALLOWED 0x0002 diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c index 6b51e0c..67d01cd 100644 --- a/ldap/servers/slapd/ssl.c +++ b/ldap/servers/slapd/ssl.c @@ -64,7 +64,7 @@ #include #include -#define NEED_TOK_DES /* defines tokDes and ptokDes - see slap.h */ +#define NEED_TOK_PBE /* defines tokPBE and ptokPBE - see slap.h */ #include "slap.h" #include "svrcore.h" @@ -1108,7 +1108,7 @@ slapd_nss_init(int init_ssl, int config_available) /******** Initialise NSS *********/ nssFlags &= (~NSS_INIT_READONLY); - slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 ); + slapd_pk11_configurePKCS11(NULL, NULL, tokPBE, ptokPBE, NULL, NULL, NULL, NULL, 0, 0 ); secStatus = NSS_Initialize(certdir, NULL, NULL, "secmod.db", nssFlags); dongle_file_name = PR_smprintf("%s/pin.txt", certdir);