From 3c6d253521c6a64353136e74d72e5977d25fab1b Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Tue, 6 Sep 2016 16:05:49 -0400 Subject: [PATCH 392/394] Ticket 47462 - Add AES plugin to replace DES plugin Description: This patch is the cumulative patch of this tickets: Ticket 48862 - At startup DES to AES password conversion causes timeout in start script Ticket 48243 - replica upgrade failed in starting dirsrv service due to upgrade scripts did not run Ticket 47888 - DES to AES password conversion fails if a backend is empty Ticket 47462 - Stop using DES in the reversible password encryption plug-in This patch is just for the backport to 1.2.11 https://fedorahosted.org/389/attachment/ticket/47462 Reviewed by: nhosoi(Thanks!) (cherry picked from commit ea241668ec7be475092a0da2a5d579e31ade1058) (cherry picked from commit f98228de6324ff6946e912b30ad18e03ec404a67) --- Makefile.am | 12 +- Makefile.in | 108 ++--- ldap/admin/src/scripts/50AES-pbe-plugin.ldif | 16 + ldap/admin/src/scripts/52updateAESplugin.pl | 84 ++++ ldap/admin/src/scripts/DSCreate.pm.in | 5 +- ldap/admin/src/scripts/DSMigration.pm.in | 2 +- ldap/admin/src/scripts/DSUpdate.pm.in | 2 +- ldap/ldif/50replication-plugins.ldif | 2 +- ldap/ldif/template-dse.ldif.in | 16 +- ldap/servers/plugins/rever/des.c | 551 ------------------------ ldap/servers/plugins/rever/pbe.c | 621 +++++++++++++++++++++++++++ ldap/servers/plugins/rever/rever.c | 116 +++-- ldap/servers/plugins/rever/rever.h | 11 +- ldap/servers/slapd/daemon.c | 155 ++++++- ldap/servers/slapd/proto-slap.h | 1 + ldap/servers/slapd/pw.c | 86 ++-- ldap/servers/slapd/pw.h | 24 +- ldap/servers/slapd/security_wrappers.c | 6 + ldap/servers/slapd/slap.h | 95 ++-- ldap/servers/slapd/slapi-plugin.h | 2 + ldap/servers/slapd/ssl.c | 4 +- ldap/servers/slapd/task.c | 338 +++++++++++++++ 22 files changed, 1520 insertions(+), 737 deletions(-) create mode 100644 ldap/admin/src/scripts/50AES-pbe-plugin.ldif create mode 100644 ldap/admin/src/scripts/52updateAESplugin.pl delete mode 100644 ldap/servers/plugins/rever/des.c create mode 100644 ldap/servers/plugins/rever/pbe.c diff --git a/Makefile.am b/Makefile.am index 9ad2c3a..bc40ea7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -205,7 +205,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 \ libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \ @@ -936,14 +936,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 930d22b..7fded4f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -317,14 +317,6 @@ libderef_plugin_la_OBJECTS = $(am_libderef_plugin_la_OBJECTS) libderef_plugin_la_LINK = $(LIBTOOL) --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) --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 @@ -462,6 +454,14 @@ libpassthru_plugin_la_OBJECTS = $(am_libpassthru_plugin_la_OBJECTS) libpassthru_plugin_la_LINK = $(LIBTOOL) --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) --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 \ @@ -1011,14 +1011,14 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \ $(libbitwise_plugin_la_SOURCES) \ $(libchainingdb_plugin_la_SOURCES) \ $(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \ - $(libderef_plugin_la_SOURCES) $(libdes_plugin_la_SOURCES) \ - $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \ + $(libderef_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) \ @@ -1045,14 +1045,14 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \ $(libbitwise_plugin_la_SOURCES) \ $(libchainingdb_plugin_la_SOURCES) \ $(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \ - $(libderef_plugin_la_SOURCES) $(libdes_plugin_la_SOURCES) \ - $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \ + $(libderef_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) \ @@ -1435,7 +1435,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 \ libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \ @@ -2101,14 +2101,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 @@ -3271,20 +3271,6 @@ ldap/servers/plugins/deref/libderef_plugin_la-deref.lo: \ ldap/servers/plugins/deref/$(DEPDIR)/$(am__dirstamp) libderef-plugin.la: $(libderef_plugin_la_OBJECTS) $(libderef_plugin_la_DEPENDENCIES) $(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) - $(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) @@ -3565,6 +3551,20 @@ ldap/servers/plugins/passthru/libpassthru_plugin_la-ptutil.lo: \ ldap/servers/plugins/passthru/$(DEPDIR)/$(am__dirstamp) libpassthru-plugin.la: $(libpassthru_plugin_la_OBJECTS) $(libpassthru_plugin_la_DEPENDENCIES) $(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) + $(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) @@ -5105,10 +5105,10 @@ mostlyclean-compile: -rm -f ldap/servers/plugins/retrocl/libretrocl_plugin_la-retrocl_rootdse.lo -rm -f ldap/servers/plugins/retrocl/libretrocl_plugin_la-retrocl_trim.$(OBJEXT) -rm -f ldap/servers/plugins/retrocl/libretrocl_plugin_la-retrocl_trim.lo - -rm -f ldap/servers/plugins/rever/libdes_plugin_la-des.$(OBJEXT) - -rm -f ldap/servers/plugins/rever/libdes_plugin_la-des.lo - -rm -f ldap/servers/plugins/rever/libdes_plugin_la-rever.$(OBJEXT) - -rm -f ldap/servers/plugins/rever/libdes_plugin_la-rever.lo + -rm -f ldap/servers/plugins/rever/libpbe_plugin_la-pbe.$(OBJEXT) + -rm -f ldap/servers/plugins/rever/libpbe_plugin_la-pbe.lo + -rm -f ldap/servers/plugins/rever/libpbe_plugin_la-rever.$(OBJEXT) + -rm -f ldap/servers/plugins/rever/libpbe_plugin_la-rever.lo -rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_cache.$(OBJEXT) -rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_cache.lo -rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.$(OBJEXT) @@ -5812,8 +5812,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@ @@ -7077,20 +7077,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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__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@ 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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__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@ 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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__mv) ldap/servers/plugins/distrib/$(DEPDIR)/libdistrib_plugin_la-distrib.Tpo ldap/servers/plugins/distrib/$(DEPDIR)/libdistrib_plugin_la-distrib.Plo @@ -7329,6 +7315,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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__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@ 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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__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@ 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@ $(LIBTOOL) --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@ $(LIBTOOL) --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__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/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/admin/src/scripts/DSCreate.pm.in b/ldap/admin/src/scripts/DSCreate.pm.in index dbfcedf..8897563 100644 --- a/ldap/admin/src/scripts/DSCreate.pm.in +++ b/ldap/admin/src/scripts/DSCreate.pm.in @@ -1088,6 +1088,7 @@ sub updateTmpfilesDotD { } sub updateSystemD { + my $noservicelink = shift; my $inf = shift; my $unitdir = "@systemdsystemunitdir@"; my $confbasedir = "@systemdsystemconfdir@"; @@ -1119,7 +1120,7 @@ sub updateSystemD { next; } else { my $servicelink = "$confdir/$pkgname\@$inst.service"; - if (! -l $servicelink) { + if (! -l $servicelink && ! $noservicelink) { if (!symlink($servicefile, $servicelink)) { debug(1, "error updating link $servicelink to $servicefile - $!\n"); push @errs, [ 'error_linking_file', $servicefile, $servicelink, $! ]; @@ -1206,7 +1207,7 @@ sub createDSInstance { return @errs; } - if (@errs = updateSystemD($inf)) { + if (@errs = updateSystemD(0, $inf)) { return @errs; } diff --git a/ldap/admin/src/scripts/DSMigration.pm.in b/ldap/admin/src/scripts/DSMigration.pm.in index 3a73f98..e1069f7 100644 --- a/ldap/admin/src/scripts/DSMigration.pm.in +++ b/ldap/admin/src/scripts/DSMigration.pm.in @@ -1161,7 +1161,7 @@ sub migrateDS { } # do the systemd stuff - @errs = DSCreate::updateSystemD($inf); + @errs = DSCreate::updateSystemD(0, $inf); if (@errs) { $mig->msg(@errs); goto cleanup; diff --git a/ldap/admin/src/scripts/DSUpdate.pm.in b/ldap/admin/src/scripts/DSUpdate.pm.in index ecdfeb7..f1bc802 100644 --- a/ldap/admin/src/scripts/DSUpdate.pm.in +++ b/ldap/admin/src/scripts/DSUpdate.pm.in @@ -416,7 +416,7 @@ sub updateDSInstance { push @errs, updateTmpfilesDotD($inf); - push @errs, updateSystemD($inf); + push @errs, updateSystemD(1, $inf); return @errs; } diff --git a/ldap/ldif/50replication-plugins.ldif b/ldap/ldif/50replication-plugins.ldif index af0c46b..c259ac6 100644 --- a/ldap/ldif/50replication-plugins.ldif +++ b/ldap/ldif/50replication-plugins.ldif @@ -21,6 +21,6 @@ nsslapd-plugininitfunc: replication_multimaster_plugin_init nsslapd-plugintype: object 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 c626726..4e45145 100644 --- a/ldap/ldif/template-dse.ldif.in +++ b/ldap/ldif/template-dse.ldif.in @@ -196,12 +196,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 b34358d..56d150e 100644 --- a/ldap/servers/slapd/daemon.c +++ b/ldap/servers/slapd/daemon.c @@ -933,6 +933,155 @@ 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 *val = NULL; + int converted_des_passwd = 0; + int result = -1; + int have_aes = 0; + int have_des = 0; + int i = 0, ii = 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(strcasecmp(plugin->plg_name, "AES") == 0){ + /* We have the AES plugin, and its enabled */ + have_aes = 1; + } + if(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){ + /* + * Find any entries in cn=config that contain DES passwords and convert + * them to AES + */ + slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes", + "Converting DES passwords to AES...\n"); + + for (i = 0; attrs && attrs[i]; i++){ + char *filter = PR_smprintf("%s=*", attrs[i]); + + pb = slapi_pblock_new(); + slapi_search_internal_set_pb(pb, "cn=config", + 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_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 to AES + */ + Slapi_PBlock *mod_pb = NULL; + Slapi_Value *sval = NULL; + LDAPMod mod_replace; + LDAPMod *mods[2]; + char *replace_val[2]; + char *passwd = NULL; + int rc = 0; + + /* decode the DES password */ + if(pw_rever_decode(val, &passwd, attrs[i]) == -1){ + slapi_log_error(SLAPI_LOG_FATAL ,"convert_pbe_des_to_aes", + "Failed to decode existing DES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + rc = -1; + } + + /* encode the password */ + if (rc == 0){ + sval = slapi_value_new_string(passwd); + if(pw_rever_encode(&sval, attrs[i]) == -1){ + slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes", + "failed to encode AES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + rc = -1; + } + } + + if (rc == 0){ + /* 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) { + slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes" + "Failed to convert password for (%s) error (%d)\n", + slapi_entry_get_dn(entries[ii]), result); + } else { + slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes", + "Successfully converted password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + converted_des_passwd = 1; + } + } + slapi_ch_free_string(&passwd); + slapi_value_free(&sval); + slapi_pblock_destroy(mod_pb); + } + slapi_ch_free_string(&val); + } + } + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + pb = NULL; + slapi_ch_free_string(&filter); + } + + if (!converted_des_passwd){ + slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes", + "No DES passwords found to convert.\n"); + } + } + charray_free(attrs); +} + void slapd_daemon( daemon_ports_t *ports ) { /* We are passed some ports---one for regular connections, one @@ -1137,11 +1286,15 @@ 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(); + /* + * 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 3b00c80..b1e7474 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -1083,6 +1083,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 ab624e7..d5785ba 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -385,9 +385,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 ); @@ -397,28 +396,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 ? */ @@ -444,6 +472,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 */ @@ -451,10 +480,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) ; @@ -462,7 +490,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 ? */ @@ -472,13 +500,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; @@ -519,10 +549,10 @@ pw_rever_encode(Slapi_Value **vals, char * attr_name) for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next ) { char *L_attr = NULL; - int i = 0; + int i = 0, ii = 0; /* Get the appropriate encoding function */ - for ( L_attr = p->plg_argv[i]; iplg_argc; L_attr = p->plg_argv[++i] ) + for ( L_attr = p->plg_argv[ii]; iiplg_argc; L_attr = p->plg_argv[++ii] ) { if (slapi_attr_types_equivalent(L_attr, attr_name)) { @@ -537,11 +567,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 9bb5cc7..87d300c 100644 --- a/ldap/servers/slapd/pw.h +++ b/ldap/servers/slapd/pw.h @@ -55,35 +55,13 @@ #define PWD_HASH_PREFIX_END '}' /* - * - * structure for holding password scheme info. - */ -struct pw_scheme { - /* case-insensitive name used in prefix of passwords that use scheme */ - char *pws_name; - - /* length of pws_name */ - int pws_len; - - /* thread-safe comparison function; returns 0 for positive matches */ - /* userpwd is value sent over LDAP bind; dbpwd is from the database */ - int (*pws_cmp)( char *userpwd, char *dbpwd ); - - /* thread-safe encoding function (returns pointer to malloc'd string) */ - char *(*pws_enc)( char *pwd ); - - /* thread-safe decoding function (returns pointer to malloc'd string) */ - char *(*pws_dec)( char *pwd ); -}; - -/* * Public functions from pw.c: */ 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); int pw_is_pwp_admin(Slapi_PBlock *pb, struct passwordpolicyarray *pwp); 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 a84e802..c027a72 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 /* @@ -306,6 +306,8 @@ typedef void (*VFPV)(); /* takes undefined arguments */ #define ATTR_NETSCAPEMDSUFFIX "netscapemdsuffix" +#define PWD_PBE_DELIM '-' + #define REFERRAL_REMOVE_CMD "remove" /* Filenames for DSE storage */ @@ -1517,6 +1519,60 @@ struct slapi_task { } slapi_task; /* End of interface to support online tasks **********************************/ +/* + * structure for holding password scheme info. + */ +struct pw_scheme { + /* case-insensitive name used in prefix of passwords that use scheme */ + char *pws_name; + + /* length of pws_name */ + int pws_len; + + /* thread-safe comparison function; returns 0 for positive matches */ + /* userpwd is value sent over LDAP bind; dbpwd is from the database */ + int (*pws_cmp)( char *userpwd, char *dbpwd ); + + /* thread-safe encoding function (returns pointer to malloc'd string) */ + char *(*pws_enc)( char *pwd ); + + /* thread-safe decoding function (returns pointer to malloc'd string) */ + char *(*pws_dec)( char *pwd, char *algid); +}; + +typedef struct passwordpolicyarray { + slapi_onoff_t pw_change; /* 1 - indicates that users are allowed to change the pwd */ + slapi_onoff_t pw_must_change; /* 1 - indicates that users must change pwd upon reset */ + slapi_onoff_t pw_syntax; + int pw_minlength; + int pw_mindigits; + int pw_minalphas; + int pw_minuppers; + int pw_minlowers; + int pw_minspecials; + int pw_min8bit; + int pw_maxrepeats; + int pw_mincategories; + int pw_mintokenlength; + slapi_onoff_t pw_exp; + long pw_maxage; + long pw_minage; + long pw_warning; + slapi_onoff_t pw_history; + int pw_inhistory; + slapi_onoff_t pw_lockout; + int pw_maxfailure; + slapi_onoff_t pw_unlock; + long pw_lockduration; + long pw_resetfailurecount; + int pw_gracelimit; + slapi_onoff_t pw_is_legacy; + slapi_onoff_t pw_track_update_time; + struct pw_scheme *pw_storagescheme; + Slapi_DN *pw_admin; + Slapi_DN **pw_admin_user; +} passwdPolicy; + typedef struct slapi_pblock { /* common */ Slapi_Backend *pb_backend; @@ -2060,39 +2116,6 @@ typedef struct _slapdEntryPoints { #define MAX_ALLOWED_TIME_IN_SECS 2147483647 -typedef struct passwordpolicyarray { - int pw_change; /* 1 - indicates that users are allowed to change the pwd */ - int pw_must_change; /* 1 - indicates that users must change pwd upon reset */ - int pw_syntax; - int pw_minlength; - int pw_mindigits; - int pw_minalphas; - int pw_minuppers; - int pw_minlowers; - int pw_minspecials; - int pw_min8bit; - int pw_maxrepeats; - int pw_mincategories; - int pw_mintokenlength; - int pw_exp; - long pw_maxage; - long pw_minage; - long pw_warning; - int pw_history; - int pw_inhistory; - int pw_lockout; - int pw_maxfailure; - int pw_unlock; - long pw_lockduration; - long pw_resetfailurecount; - int pw_gracelimit; - int pw_is_legacy; - int pw_track_update_time; - struct pw_scheme *pw_storagescheme; - Slapi_DN *pw_admin; - Slapi_DN **pw_admin_user; -} passwdPolicy; - typedef struct _slapdFrontendConfig { Slapi_RWLock *cfg_rwlock; /* read/write lock to serialize access */ struct pw_scheme *rootpwstoragescheme; diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 912d407..c36822d 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -200,6 +200,8 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...) #define SLAPI_OP_FLAG_NEVER_CHAIN 0x000800 /* Do not chain the operation */ #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 529dbc6..1f64be0 100644 --- a/ldap/servers/slapd/ssl.c +++ b/ldap/servers/slapd/ssl.c @@ -63,7 +63,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" @@ -713,7 +713,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); diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c index 0488640..e595ad0 100644 --- a/ldap/servers/slapd/task.c +++ b/ldap/servers/slapd/task.c @@ -75,6 +75,7 @@ static int shutting_down = 0; #define TASK_WORK_NAME "nsTaskTotalItems" #define DEFAULT_TTL "120" /* seconds */ +#define TASK_DES2AES "des2aes task" #define LOG_BUFFER 256 /* if the cumul. log gets larger than this, it's truncated: */ @@ -105,6 +106,9 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val); static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn); static void modify_internal_entry(char *dn, LDAPMod **mods); +static void task_des2aes_thread(void *arg); +static void des2aes_task_destructor(Slapi_Task *task); + /*********************************** * Public Functions @@ -1883,6 +1887,339 @@ out: return SLAPI_DSE_CALLBACK_OK; } +/* + * des2aes Task + * + * Convert any DES passwords to AES + * + * dn: cn=convertPasswords, cn=des2aes,cn=tasks,cn=config + * objectclass: top + * objectclass: extensibleObject + * suffix: dc=example,dc=com (If empty all backends are checked) + * suffix: dc=other,dc=suffix + */ +struct task_des2aes_data +{ + char **suffixes; + Slapi_Task *task; +}; + +static int +task_des2aes(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + int *returncode, char *returntext, void *arg) +{ + struct task_des2aes_data *task_data = NULL; + PRThread *thread = NULL; + Slapi_Task *task = NULL; + char **suffix = NULL; + char **bases = NULL; + int rc = SLAPI_DSE_CALLBACK_OK; + + /* Get the suffixes */ + if((suffix = slapi_entry_attr_get_charray(e, "suffix"))){ + int i; + for (i = 0; suffix && suffix[i]; i++){ + /* Make sure "suffix" is NUL terminated string */ + char *dn = slapi_create_dn_string("%s", suffix[i]); + + if(dn){ + if(slapi_dn_syntax_check(pb, dn, 1)){ + /* invalid suffix name */ + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "Invalid DN syntax (%s) specified for \"suffix\"\n", + suffix[i]); + *returncode = LDAP_INVALID_DN_SYNTAX; + slapi_ch_free_string(&dn); + rc = SLAPI_DSE_CALLBACK_ERROR; + goto error; + } else { + slapi_ch_array_add(&bases, dn); + } + } else{ + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "Invalid DN (%s) specified for \"suffix\"\n", suffix[i]); + *returncode = LDAP_INVALID_DN_SYNTAX; + rc = SLAPI_DSE_CALLBACK_ERROR; + goto error; + } + } + } + + /* Build the task data and fire off a thread to perform the conversion */ + task = slapi_new_task(slapi_entry_get_ndn(e)); + + /* register our destructor for cleaning up our private data */ + slapi_task_set_destructor_fn(task, des2aes_task_destructor); + task_data = (struct task_des2aes_data *)slapi_ch_calloc(1, sizeof(struct task_des2aes_data)); + task_data->suffixes = bases; + task_data->task = task; + + /* Start the conversion thread */ + thread = PR_CreateThread(PR_USER_THREAD, task_des2aes_thread, + (void *)task_data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "unable to create des2aes thread!\n"); + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "unable to create des2aes thread!\n"); + *returncode = LDAP_OPERATIONS_ERROR; + slapi_task_finish(task, *returncode); + rc = SLAPI_DSE_CALLBACK_ERROR; + } + +error: + if (rc == SLAPI_DSE_CALLBACK_ERROR){ + slapi_ch_array_free(bases); + slapi_ch_array_free(suffix); + slapi_ch_free((void **)&task_data); + } + return rc; +} + +static void +task_des2aes_thread(void *arg) +{ + struct task_des2aes_data *task_data = arg; + Slapi_PBlock *pb = NULL; + Slapi_Entry **entries = NULL; + Slapi_Task *task = task_data->task; + struct slapdplugin *plugin = NULL; + char **attrs = NULL; + char **backends = NULL; + char *val = NULL; + int converted_des_passwd = 0; + int result = -1; + int have_aes = 0; + int have_des = 0; + int i = 0, ii = 0, be_idx = 0; + int rc = 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 *plugin_arg = NULL; + + if(strcasecmp(plugin->plg_name, "AES") == 0){ + /* We have the AES plugin, and its enabled */ + have_aes = 1; + } + if(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, plugin_arg = plugin->plg_argv[i]; + i < plugin->plg_argc; + plugin_arg = plugin->plg_argv[++i] ) + { + if(charray_inlist(attrs, plugin_arg)){ + continue; + } + charray_add(&attrs, slapi_ch_strdup(plugin_arg)); + } + } + + if(have_aes && have_des){ + if(task_data->suffixes == NULL){ + /* + * Build a list of all the backend dn's + */ + Slapi_Backend *be = NULL; + char *cookie = NULL; + + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "Checking for DES passwords to convert to AES...\n"); + slapi_task_log_notice(task, + "Checking for DES passwords to convert to AES...\n"); + + be = slapi_get_first_backend(&cookie); + while (be){ + PR_Lock(be->be_suffixlock); + for (i = 0; be->be_suffix && i < be->be_suffixcount; i++) { + char *suffix = (char *)slapi_sdn_get_ndn(be->be_suffix[i]); + if(charray_inlist(backends, suffix) || strlen(suffix) == 0){ + continue; + } + charray_add(&backends, slapi_ch_strdup(suffix));; + } + be = slapi_get_next_backend (cookie); + } + slapi_ch_free ((void **)&cookie); + } else { + backends = task_data->suffixes; + } + + /* + * 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 && 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) { + slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes: ", + "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n", + attrs[i], result, backends[be_idx]); + slapi_task_log_notice(task, + "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n", + attrs[i], result, backends[be_idx]); + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + pb = NULL; + continue; + } + 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){ + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "Failed to decode existing DES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + slapi_task_log_notice(task, + "Failed to decode existing DES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + rc = 1; + goto done; + } + + /* Encode the password */ + sval = slapi_value_new_string(passwd); + if(pw_rever_encode(&sval, attrs[i]) == -1){ + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "failed to encode AES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + slapi_task_log_notice(task, + "failed to encode AES password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + slapi_ch_free_string(&passwd); + slapi_value_free(&sval); + rc = 1; + 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) { + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "Failed to convert password for (%s) error (%d)\n", + slapi_entry_get_dn(entries[ii]), result); + slapi_task_log_notice(task, + "Failed to convert password for (%s) error (%d)\n", + slapi_entry_get_dn(entries[ii]), result); + rc = 1; + } else { + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "Successfully converted password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + slapi_task_log_notice(task, + "Successfully converted password for (%s)\n", + slapi_entry_get_dn(entries[ii])); + converted_des_passwd = 1; + } + slapi_ch_free_string(&passwd); + slapi_value_free(&sval); + slapi_pblock_destroy(mod_pb); + } + slapi_ch_free_string(&val); + } + } + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + pb = NULL; + } + slapi_ch_free_string(&filter); + } + if (!converted_des_passwd){ + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "No DES passwords found to convert.\n"); + slapi_task_log_notice(task, "No DES passwords found to convert.\n"); + } + } else { + /* No AES/DES */ + if (!have_des){ + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "DES plugin not enabled\n"); + slapi_task_log_notice(task, "DES plugin not enabled\n"); + } + if (!have_aes){ + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "AES plugin not enabled\n"); + slapi_task_log_notice(task, "AES plugin not enabled\n"); + } + slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES, + "Unable to convert passwords\n"); + slapi_task_log_notice(task, "Unable to convert passwords\n"); + rc = 1; + } + +done: + charray_free(attrs); + charray_free(backends); + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + slapi_task_finish(task, rc); +} + +static void +des2aes_task_destructor(Slapi_Task *task) +{ + slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES, + "des2aes_task_destructor -->\n" ); + if (task) { + struct task_des2aes_data *task_data = (struct task_des2aes_data *)slapi_task_get_data(task); + while (slapi_task_get_refcount(task) > 0) { + /* Yield to wait for the task to finish. */ + DS_Sleep (PR_MillisecondsToInterval(100)); + } + if (task_data) { + slapi_ch_array_free(task_data->suffixes); + slapi_ch_free((void **)&task_data); + } + } + slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES, + "des2aes_task_destructor <--\n" ); +} + /* cleanup old tasks that may still be in the DSE from a previous session * (this can happen if the server crashes [no matter how unlikely we like * to think that is].) @@ -1962,6 +2299,7 @@ void task_init(void) slapi_task_register_handler("restore", task_restore_add); slapi_task_register_handler("index", task_index_add); slapi_task_register_handler("upgradedb", task_upgradedb_add); + slapi_task_register_handler("des2aes", task_des2aes); } /* called when the server is shutting down -- abort all existing tasks */ -- 2.4.11