summaryrefslogtreecommitdiffstats
path: root/ipa-server/ipa-slapi-plugins
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-01-29 16:26:07 -0500
committerRob Crittenden <rcritten@redhat.com>2009-02-03 15:27:14 -0500
commite30cd6ba42c256d2016db45146d616f329455e86 (patch)
treed4c5291095c80c92bc4803fe7f20fc2838124ffa /ipa-server/ipa-slapi-plugins
parentc4ed025001895bfc65c613cabbbfcb27c19cc29f (diff)
downloadfreeipa-e30cd6ba42c256d2016db45146d616f329455e86.tar.gz
freeipa-e30cd6ba42c256d2016db45146d616f329455e86.tar.xz
freeipa-e30cd6ba42c256d2016db45146d616f329455e86.zip
Mass tree reorganization for IPAv2. To view previous history of files use:
% git log --follow -- <file> renamed: ipa-server/autogen.sh -> autogen.sh renamed: ipa-server/ipa-kpasswd/Makefile.am -> daemons/ipa-kpasswd/Makefile.am renamed: ipa-server/ipa-kpasswd/README -> daemons/ipa-kpasswd/README renamed: ipa-server/ipa-kpasswd/ipa_kpasswd.c -> daemons/ipa-kpasswd/ipa_kpasswd.c renamed: ipa-server/ipa-kpasswd/ipa_kpasswd.init -> daemons/ipa-kpasswd/ipa_kpasswd.init renamed: ipa-server/ipa-slapi-plugins/Makefile.am -> daemons/ipa-slapi-plugins/Makefile.am renamed: ipa-server/ipa-slapi-plugins/README -> daemons/ipa-slapi-plugins/README renamed: ipa-server/ipa-slapi-plugins/dna/Makefile.am -> daemons/ipa-slapi-plugins/dna/Makefile.am renamed: ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif -> daemons/ipa-slapi-plugins/dna/dna-conf.ldif renamed: ipa-server/ipa-slapi-plugins/dna/dna.c -> daemons/ipa-slapi-plugins/dna/dna.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am -> daemons/ipa-slapi-plugins/ipa-memberof/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c -> daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c renamed: ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif -> daemons/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am -> daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README -> daemons/ipa-slapi-plugins/ipa-pwd-extop/README renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c -> daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c renamed: ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif -> daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am -> daemons/ipa-slapi-plugins/ipa-winsync/Makefile.am renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/README -> daemons/ipa-slapi-plugins/ipa-winsync/README renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c renamed: ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h -> daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h renamed: ipa-server/xmlrpc-server/ipa-rewrite.conf -> install/conf/ipa-rewrite.conf renamed: ipa-server/xmlrpc-server/ipa.conf -> install/conf/ipa.conf renamed: ipa-server/xmlrpc-server/ssbrowser.html -> install/html/ssbrowser.html renamed: ipa-server/xmlrpc-server/unauthorized.html -> install/html/unauthorized.html renamed: ipa-server/ipa-install/share/60ipaconfig.ldif -> install/share/60ipaconfig.ldif renamed: ipa-server/ipa-install/share/60kerberos.ldif -> install/share/60kerberos.ldif renamed: ipa-server/ipa-install/share/60radius.ldif -> install/share/60radius.ldif renamed: ipa-server/ipa-install/share/60samba.ldif -> install/share/60samba.ldif renamed: ipa-server/ipa-install/share/Makefile.am -> install/share/Makefile.am renamed: ipa-server/ipa-install/share/bind.named.conf.template -> install/share/bind.named.conf.template renamed: ipa-server/ipa-install/share/bind.zone.db.template -> install/share/bind.zone.db.template renamed: ipa-server/ipa-install/share/bootstrap-template.ldif -> install/share/bootstrap-template.ldif renamed: ipa-server/ipa-install/share/certmap.conf.template -> install/share/certmap.conf.template renamed: ipa-server/ipa-install/share/default-aci.ldif -> install/share/default-aci.ldif renamed: ipa-server/ipa-install/share/default-keytypes.ldif -> install/share/default-keytypes.ldif renamed: ipa-server/ipa-install/share/dna-posix.ldif -> install/share/dna-posix.ldif renamed: ipa-server/ipa-install/share/encrypted_attribute.ldif -> install/share/encrypted_attribute.ldif renamed: ipa-server/ipa-install/share/fedora-ds.init.patch -> install/share/fedora-ds.init.patch renamed: ipa-server/ipa-install/share/indices.ldif -> install/share/indices.ldif renamed: ipa-server/ipa-install/share/kdc.conf.template -> install/share/kdc.conf.template renamed: ipa-server/ipa-install/share/kerberos.ldif -> install/share/kerberos.ldif renamed: ipa-server/ipa-install/share/krb.con.template -> install/share/krb.con.template renamed: ipa-server/ipa-install/share/krb5.conf.template -> install/share/krb5.conf.template renamed: ipa-server/ipa-install/share/krb5.ini.template -> install/share/krb5.ini.template renamed: ipa-server/ipa-install/share/krbrealm.con.template -> install/share/krbrealm.con.template renamed: ipa-server/ipa-install/share/master-entry.ldif -> install/share/master-entry.ldif renamed: ipa-server/ipa-install/share/memberof-task.ldif -> install/share/memberof-task.ldif renamed: ipa-server/ipa-install/share/ntp.conf.server.template -> install/share/ntp.conf.server.template renamed: ipa-server/ipa-install/share/ntpd.sysconfig.template -> install/share/ntpd.sysconfig.template renamed: ipa-server/ipa-install/share/preferences.html.template -> install/share/preferences.html.template renamed: ipa-server/ipa-install/share/referint-conf.ldif -> install/share/referint-conf.ldif renamed: ipa-server/ipa-install/share/schema_compat.uldif -> install/share/schema_compat.uldif renamed: ipa-server/ipa-install/share/unique-attributes.ldif -> install/share/unique-attributes.ldif renamed: ipa-server/ipa-install/Makefile.am -> install/tools/Makefile.am renamed: ipa-server/ipa-install/README -> install/tools/README renamed: ipa-server/ipa-compat-manage -> install/tools/ipa-compat-manage renamed: ipa-server/ipa-fix-CVE-2008-3274 -> install/tools/ipa-fix-CVE-2008-3274 renamed: ipa-server/ipa-ldap-updater -> install/tools/ipa-ldap-updater renamed: ipa-server/ipa-install/ipa-replica-install -> install/tools/ipa-replica-install renamed: ipa-server/ipa-install/ipa-replica-manage -> install/tools/ipa-replica-manage renamed: ipa-server/ipa-install/ipa-replica-prepare -> install/tools/ipa-replica-prepare renamed: ipa-server/ipa-install/ipa-server-certinstall -> install/tools/ipa-server-certinstall renamed: ipa-server/ipa-install/ipa-server-install -> install/tools/ipa-server-install renamed: ipa-server/ipa-upgradeconfig -> install/tools/ipa-upgradeconfig renamed: ipa-server/ipa-install/ipactl -> install/tools/ipactl renamed: ipa-server/man/Makefile.am -> install/tools/man/Makefile.am renamed: ipa-server/man/ipa-compat-manage.1 -> install/tools/man/ipa-compat-manage.1 renamed: ipa-server/man/ipa-ldap-updater.1 -> install/tools/man/ipa-ldap-updater.1 renamed: ipa-server/man/ipa-replica-install.1 -> install/tools/man/ipa-replica-install.1 renamed: ipa-server/man/ipa-replica-manage.1 -> install/tools/man/ipa-replica-manage.1 renamed: ipa-server/man/ipa-replica-prepare.1 -> install/tools/man/ipa-replica-prepare.1 renamed: ipa-server/man/ipa-server-certinstall.1 -> install/tools/man/ipa-server-certinstall.1 renamed: ipa-server/man/ipa-server-install.1 -> install/tools/man/ipa-server-install.1 renamed: ipa-server/man/ipa_kpasswd.8 -> install/tools/man/ipa_kpasswd.8 renamed: ipa-server/man/ipa_webgui.8 -> install/tools/man/ipa_webgui.8 renamed: ipa-server/man/ipactl.8 -> install/tools/man/ipactl.8 renamed: ipa-server/ipa-install/updates/Makefile.am -> install/updates/Makefile.am renamed: ipa-server/ipa-install/updates/RFC2307bis.update -> install/updates/RFC2307bis.update renamed: ipa-server/ipa-install/updates/RFC4876.update -> install/updates/RFC4876.update renamed: ipa-server/ipa-install/updates/indices.update -> install/updates/indices.update renamed: ipa-server/ipa-install/updates/nss_ldap.update -> install/updates/nss_ldap.update renamed: ipa-server/ipa-install/updates/replication.update -> install/updates/replication.update renamed: ipa-server/ipa-install/updates/winsync_index.update -> install/updates/winsync_index.update renamed: ipa-server/ipaserver/Makefile.am -> ipaserver/install/Makefile.am renamed: ipa-server/ipaserver/__init__.py -> ipaserver/install/__init__.py renamed: ipa-server/ipaserver/bindinstance.py -> ipaserver/install/bindinstance.py renamed: ipa-server/ipaserver/certs.py -> ipaserver/install/certs.py renamed: ipa-server/ipaserver/dsinstance.py -> ipaserver/install/dsinstance.py renamed: ipa-server/ipaserver/httpinstance.py -> ipaserver/install/httpinstance.py renamed: ipa-server/ipaserver/installutils.py -> ipaserver/install/installutils.py renamed: ipa-server/ipaserver/ipaldap.py -> ipaserver/install/ipaldap.py renamed: ipa-server/ipaserver/krbinstance.py -> ipaserver/install/krbinstance.py renamed: ipa-server/ipaserver/ldapupdate.py -> ipaserver/install/ldapupdate.py renamed: ipa-server/ipaserver/ntpinstance.py -> ipaserver/install/ntpinstance.py renamed: ipa-server/ipaserver/replication.py -> ipaserver/install/replication.py renamed: ipa-server/ipaserver/service.py -> ipaserver/install/service.py renamed: ipa-server/selinux/Makefile -> selinux/Makefile renamed: ipa-server/selinux/ipa-server-selinux.spec.in -> selinux/ipa-server-selinux.spec.in renamed: ipa-server/selinux/ipa_kpasswd/ipa_kpasswd.fc -> selinux/ipa_kpasswd/ipa_kpasswd.fc renamed: ipa-server/selinux/ipa_kpasswd/ipa_kpasswd.te -> selinux/ipa_kpasswd/ipa_kpasswd.te renamed: ipa-server/selinux/ipa_webgui/ipa_webgui.fc -> selinux/ipa_webgui/ipa_webgui.fc renamed: ipa-server/selinux/ipa_webgui/ipa_webgui.te -> selinux/ipa_webgui/ipa_webgui.te renamed: ipa-server/version.m4.in -> version.m4.in
Diffstat (limited to 'ipa-server/ipa-slapi-plugins')
-rw-r--r--ipa-server/ipa-slapi-plugins/Makefile.am16
-rw-r--r--ipa-server/ipa-slapi-plugins/README0
-rw-r--r--ipa-server/ipa-slapi-plugins/dna/Makefile.am42
-rw-r--r--ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif14
-rw-r--r--ipa-server/ipa-slapi-plugins/dna/dna.c1462
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am43
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c2244
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h100
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c312
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif14
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am46
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README0
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c4058
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif16
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am43
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/README0
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif27
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c975
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c1177
-rw-r--r--ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h160
20 files changed, 0 insertions, 10749 deletions
diff --git a/ipa-server/ipa-slapi-plugins/Makefile.am b/ipa-server/ipa-slapi-plugins/Makefile.am
deleted file mode 100644
index f316371c3..000000000
--- a/ipa-server/ipa-slapi-plugins/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-NULL =
-
-SUBDIRS = \
- ipa-pwd-extop \
- ipa-memberof \
- dna \
- ipa-winsync \
- $(NULL)
-
-EXTRA_DIST = \
- README \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipa-slapi-plugins/README b/ipa-server/ipa-slapi-plugins/README
deleted file mode 100644
index e69de29bb..000000000
--- a/ipa-server/ipa-slapi-plugins/README
+++ /dev/null
diff --git a/ipa-server/ipa-slapi-plugins/dna/Makefile.am b/ipa-server/ipa-slapi-plugins/dna/Makefile.am
deleted file mode 100644
index 4a54b8d5d..000000000
--- a/ipa-server/ipa-slapi-plugins/dna/Makefile.am
+++ /dev/null
@@ -1,42 +0,0 @@
-NULL =
-
-INCLUDES = \
- -I. \
- -I$(srcdir) \
- -DPREFIX=\""$(prefix)"\" \
- -DBINDIR=\""$(bindir)"\" \
- -DLIBDIR=\""$(libdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- $(MOZLDAP_CFLAGS) \
- $(KRB5_CFLAGS) \
- $(WARN_CFLAGS) \
- $(NULL)
-
-plugindir = $(libdir)/dirsrv/plugins
-plugin_LTLIBRARIES = \
- libipa-dna-plugin.la \
- $(NULL)
-
-libipa_dna_plugin_la_SOURCES = \
- dna.c \
- $(NULL)
-
-libipa_dna_plugin_la_LDFLAGS = -avoid-version
-
-libipa_dna_plugin_la_LIBADD = \
- $(MOZLDAP_LIBS) \
- $(NULL)
-
-appdir = $(IPA_DATA_DIR)
-app_DATA = \
- dna-conf.ldif \
- $(NULL)
-
-EXTRA_DIST = \
- $(app_DATA) \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif b/ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif
deleted file mode 100644
index 02532b4e4..000000000
--- a/ipa-server/ipa-slapi-plugins/dna/dna-conf.ldif
+++ /dev/null
@@ -1,14 +0,0 @@
-dn: cn=ipa-dna,cn=plugins,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSlapdPlugin
-objectclass: extensibleObject
-cn: ipa-dna
-nsslapd-pluginpath: libipa-dna-plugin
-nsslapd-plugininitfunc: ipa_dna_init
-nsslapd-plugintype: preoperation
-nsslapd-pluginenabled: on
-nsslapd-pluginid: ipa-dna
-nsslapd-pluginversion: 1.0
-nsslapd-pluginvendor: Red Hat
-nsslapd-plugindescription: IPA Distributed numeric assignment plugin
diff --git a/ipa-server/ipa-slapi-plugins/dna/dna.c b/ipa-server/ipa-slapi-plugins/dna/dna.c
deleted file mode 100644
index cb6a0629c..000000000
--- a/ipa-server/ipa-slapi-plugins/dna/dna.c
+++ /dev/null
@@ -1,1462 +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.
- *
- *
- * Author: Pete Rowley
- *
- * Copyright (C) 2007 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-
-/**
- * Distributed Numeric Assignment plug-in
- */
-
-#include <dirsrv/slapi-plugin.h>
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-/*#include "portable.h"*/
-#include "nspr.h"
-/*#include "slapi-private.h"*/
-/*#include "dirlite_strings.h"*/
-/*#include "dirver.h"*/
-
-#include "prclist.h"
-#include "ldif.h"
-
-/* get file mode flags for unix */
-#ifndef _WIN32
-#include <sys/stat.h>
-#endif
-
-#define DNA_PLUGIN_SUBSYSTEM "ipa-dna-plugin"
-#define DNA_PLUGIN_VERSION 0x00020000
-
-/* temporary */
-#define DNA_DN "cn=ipa-dna,cn=plugins,cn=config"
-
-#define DNA_SUCCESS 0
-#define DNA_FAILURE -1
-
-/**
- * DNA config types
- */
-#define DNA_TYPE "dnaType"
-#define DNA_PREFIX "dnaPrefix"
-#define DNA_NEXTVAL "dnaNextValue"
-#define DNA_INTERVAL "dnaInterval"
-#define DNA_GENERATE "dnaMagicRegen"
-#define DNA_FILTER "dnaFilter"
-#define DNA_SCOPE "dnaScope"
-
-/* since v2 */
-#define DNA_MAXVAL "dnaMaxValue"
-#define DNA_SHARED_CFG_DN "dnaSharedCfgDN"
-
-/* Shared Config */
-#define DNA_GLOBAL_RANGE "dnaGlobalRange"
-#define DNA_RANGE "dnaRange"
-#define DNA_MAX_RANGE_SIZE "dnaMaxRangeSize"
-#define DNA_CHUNK_SIZE "dnaChunkSize"
-
-
-
-#define FEATURE_DESC "IPA Distributed Numeric Assignment"
-#define PLUGIN_DESC "IPA Distributed Numeric Assignment plugin"
-#define PLUGIN_DESC_INT_PREOP PLUGIN_DESC " preop internal"
-#define PLUGIN_DESC_POSTOP PLUGIN_DESC " postop"
-#define PLUGIN_DESC_INT_POSTOP PLUGIN_DESC " postop internal"
-
-static Slapi_PluginDesc pdesc = { FEATURE_DESC,
- "FreeIPA project", "FreeIPA/1.0",
- PLUGIN_DESC
-};
-
-
-/**
- * linked list of config entries
- */
-
-struct configEntry {
- PRCList list;
- char *dn;
- char *type;
- char *prefix;
- PRUint64 nextval;
- PRUint64 interval;
- PRUint64 maxval;
- char *filter;
- struct slapi_filter *slapi_filter;
- char *generate;
- char *scope;
-};
-
-static PRCList *dna_global_config = NULL;
-static PRRWLock *g_dna_cache_lock;
-
-static void *_PluginID = NULL;
-static char *_PluginDN = NULL;
-
-static int g_plugin_started = 0;
-
-
-/*
- * new value lock
- */
-static Slapi_Mutex *g_new_value_lock;
-
-/**
- *
- * DNA plug-in management functions
- *
- */
-int ipa_dna_init(Slapi_PBlock * pb);
-static int dna_start(Slapi_PBlock * pb);
-static int dna_close(Slapi_PBlock * pb);
-static int dna_internal_preop_init(Slapi_PBlock *pb);
-static int dna_postop_init(Slapi_PBlock * pb);
-
-/**
- *
- * Local operation functions
- *
- */
-static int loadPluginConfig();
-static int parseConfigEntry(Slapi_Entry * e);
-static void deleteConfig();
-static void freeConfigEntry(struct configEntry ** entry);
-
-/**
- *
- * helpers
- *
- */
-static char *dna_get_dn(Slapi_PBlock * pb);
-static int dna_dn_is_config(char *dn);
-static int dna_get_next_value(struct configEntry * config_entry,
- char **next_value_ret);
-
-/**
- *
- * the ops (where the real work is done)
- *
- */
-static int dna_config_check_post_op(Slapi_PBlock * pb);
-static int dna_pre_op(Slapi_PBlock * pb, int modtype);
-static int dna_mod_pre_op(Slapi_PBlock * pb);
-static int dna_add_pre_op(Slapi_PBlock * pb);
-
-/**
- * debug functions - global, for the debugger
- */
-void dnaDumpConfig();
-void dnaDumpConfigEntry(struct configEntry *);
-
-/**
- * set the debug level
- */
-#ifdef _WIN32
-int *module_ldap_debug = 0;
-
-void plugin_init_debug_level(int *level_ptr)
-{
- module_ldap_debug = level_ptr;
-}
-#endif
-
-/**
- *
- * Deal with cache locking
- *
- */
-void dna_read_lock()
-{
- PR_RWLock_Rlock(g_dna_cache_lock);
-}
-
-void dna_write_lock()
-{
- PR_RWLock_Wlock(g_dna_cache_lock);
-}
-
-void dna_unlock()
-{
- PR_RWLock_Unlock(g_dna_cache_lock);
-}
-
-/**
- *
- * Get the dna plug-in version
- *
- */
-int dna_version()
-{
- return DNA_PLUGIN_VERSION;
-}
-
-/**
- * Plugin identity mgmt
- */
-void setPluginID(void *pluginID)
-{
- _PluginID = pluginID;
-}
-
-void *getPluginID()
-{
- return _PluginID;
-}
-
-void setPluginDN(char *pluginDN)
-{
- _PluginDN = pluginDN;
-}
-
-char *getPluginDN()
-{
- return _PluginDN;
-}
-
-/*
- dna_init
- -------------
- adds our callbacks to the list
-*/
-int ipa_dna_init(Slapi_PBlock * pb)
-{
- int status = DNA_SUCCESS;
- char *plugin_identity = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> ipa_dna_init\n");
-
- /**
- * Store the plugin identity for later use.
- * Used for internal operations
- */
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
- PR_ASSERT(plugin_identity);
- setPluginID(plugin_identity);
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) dna_start) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) dna_close) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
- (void *) dna_mod_pre_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN,
- (void *) dna_add_pre_op) != 0 ||
- /* internal preoperation */
- slapi_register_plugin("internalpreoperation", /* op type */
- 1, /* Enabled */
- "dna_internal_preop_init", /* this function desc */
- dna_internal_preop_init, /* init func */
- PLUGIN_DESC_INT_PREOP, /* plugin desc */
- NULL, /* ? */
- plugin_identity /* access control */
- ) ||
- /* the config change checking post op */
- slapi_register_plugin("postoperation", /* op type */
- 1, /* Enabled */
- "dna_postop_init", /* this function desc */
- dna_postop_init, /* init func for post op */
- PLUGIN_DESC_POSTOP, /* plugin desc */
- NULL, /* ? */
- plugin_identity /* access control */
- )
- ) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "ipa_dna_init: failed to register plugin\n");
- status = DNA_FAILURE;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- ipa_dna_init\n");
- return status;
-}
-
-
-static int
-dna_internal_preop_init(Slapi_PBlock *pb)
-{
- int status = DNA_SUCCESS;
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN,
- (void *) dna_mod_pre_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN,
- (void *) dna_add_pre_op) != 0) {
- status = DNA_FAILURE;
- }
-
- return status;
-}
-
-
-static int dna_postop_init(Slapi_PBlock * pb)
-{
- int status = DNA_SUCCESS;
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
- (void *) dna_config_check_post_op) != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_postop_init: failed to register plugin\n");
- status = DNA_FAILURE;
- }
-
- return status;
-}
-
-/*
- dna_start
- --------------
- Kicks off the config cache.
- It is called after dna_init.
-*/
-static int dna_start(Slapi_PBlock * pb)
-{
- char *plugindn = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_start\n");
-
- /* Check if we're already started */
- if (g_plugin_started) {
- goto done;
- }
-
- g_dna_cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "dna");
- g_new_value_lock = slapi_new_mutex();
-
- if (!g_dna_cache_lock || !g_new_value_lock) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: lock creation failed\n");
-
- return DNA_FAILURE;
- }
-
- /**
- * Get the plug-in target dn from the system
- * and store it for future use. This should avoid
- * hardcoding of DN's in the code.
- */
- slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn);
- if (NULL == plugindn || 0 == strlen(plugindn)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: had to use hard coded config dn\n");
- plugindn = DNA_DN;
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: config at %s\n", plugindn);
-
- }
-
- setPluginDN(plugindn);
-
- /**
- * Load the config for our plug-in
- */
- dna_global_config = (PRCList *)
- slapi_ch_calloc(1, sizeof(struct configEntry));
- PR_INIT_CLIST(dna_global_config);
-
- if (loadPluginConfig() != DNA_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: unable to load plug-in configuration\n");
- return DNA_FAILURE;
- }
-
- g_plugin_started = 1;
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna: ready for service\n");
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_start\n");
-
-done:
- return DNA_SUCCESS;
-}
-
-/*
- dna_close
- --------------
- closes down the cache
-*/
-static int dna_close(Slapi_PBlock * pb)
-{
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_close\n");
-
- deleteConfig();
-
- slapi_ch_free((void **)&dna_global_config);
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_close\n");
-
- return DNA_SUCCESS;
-}
-
-/*
- * config looks like this
- * - cn=myplugin
- * --- cn=posix
- * ------ cn=accounts
- * ------ cn=groups
- * --- cn=samba
- * --- cn=etc
- * ------ cn=etc etc
- */
-static int loadPluginConfig()
-{
- int status = DNA_SUCCESS;
- int result;
- int i;
- Slapi_PBlock *search_pb;
- Slapi_Entry **entries = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> loadPluginConfig\n");
-
- dna_write_lock();
- deleteConfig();
-
- search_pb = slapi_pblock_new();
-
- slapi_search_internal_set_pb(search_pb, getPluginDN(),
- LDAP_SCOPE_SUBTREE, "objectclass=*",
- NULL, 0, NULL, NULL, getPluginID(), 0);
- slapi_search_internal_pb(search_pb);
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
-
- if (LDAP_SUCCESS != result) {
- status = DNA_FAILURE;
- goto cleanup;
- }
-
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
- if (NULL == entries || NULL == entries[0]) {
- status = DNA_SUCCESS;
- goto cleanup;
- }
-
- for (i = 0; (entries[i] != NULL); i++) {
- status = parseConfigEntry(entries[i]);
- if (DNA_SUCCESS != status)
- break;
- }
-
- cleanup:
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
- dna_unlock();
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- loadPluginConfig\n");
-
- return status;
-}
-
-static int parseConfigEntry(Slapi_Entry * e)
-{
- char *value;
- struct configEntry *entry;
- struct configEntry *config_entry;
- PRCList *list;
- int entry_added = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> parseConfigEntry\n");
-
- entry = (struct configEntry *)
- slapi_ch_calloc(1, sizeof(struct configEntry));
- if (NULL == entry)
- goto bail;
-
- value = slapi_entry_get_ndn(e);
- if (value) {
- entry->dn = strdup(value);
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dn [%s]\n", entry->dn, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_TYPE);
- if (value) {
- entry->type = value;
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaType [%s]\n", entry->type, 0, 0);
-
- /* FIXME: check the attribute type, it must suport matching rules and be
- * indexed, these are requirements and failure to meet them should result in
- * the configuration to be disarded and an ERROR logged prominently */
-
- value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
- if (value) {
- entry->nextval = strtoul(value, 0, 0);
- slapi_ch_free_string(&value);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaNextValue [%d]\n", entry->nextval, 0,
- 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_PREFIX);
- if (value && value[0]) {
- entry->prefix = value;
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaPrefix [%s]\n", entry->prefix, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
- if (value) {
- entry->interval = strtoul(value, 0, 0);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaInterval [%s]\n", value, 0, 0);
-
- slapi_ch_free_string(&value);
-
- value = slapi_entry_attr_get_charptr(e, DNA_GENERATE);
- if (value) {
- entry->generate = value;
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaMagicRegen [%s]\n", entry->generate,
- 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_FILTER);
- if (value) {
- entry->filter = value;
- entry->slapi_filter = slapi_str2filter(value);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaFilter [%s]\n", value, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_SCOPE);
- if (value) {
- entry->scope = slapi_dn_normalize(value);
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaScope [%s]\n", entry->scope, 0, 0);
-
- /* optional, if not specified set -1 which is converted to the max unisgnee
- * value */
- value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
- if (value) {
- entry->maxval = strtoul(value, 0, 0);
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaMaxValue [%ld]\n", value, 0, 0);
-
- slapi_ch_free_string(&value);
- } else
- entry->maxval = -1;
-
-
- /**
- * Finally add the entry to the list
- * we group by type then by filter
- * and finally sort by dn length with longer dn's
- * first - this allows the scope checking
- * code to be simple and quick and
- * cunningly linear
- */
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- while (list != dna_global_config) {
- config_entry = (struct configEntry *) list;
-
- if (slapi_attr_type_cmp(config_entry->type, entry->type, 1))
- goto next;
-
- if (slapi_filter_compare(config_entry->slapi_filter,
- entry->slapi_filter))
- goto next;
-
- if (slapi_dn_issuffix(entry->scope, config_entry->scope)) {
- PR_INSERT_BEFORE(&(entry->list), list);
- slapi_log_error(SLAPI_LOG_CONFIG,
- DNA_PLUGIN_SUBSYSTEM,
- "store [%s] before [%s] \n", entry->scope,
- config_entry->scope, 0);
- entry_added = 1;
- break;
- }
-
- next:
- list = PR_NEXT_LINK(list);
-
- if (dna_global_config == list) {
- /* add to tail */
- PR_INSERT_BEFORE(&(entry->list), list);
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "store [%s] at tail\n", entry->scope, 0,
- 0);
- entry_added = 1;
- break;
- }
- }
- } else {
- /* first entry */
- PR_INSERT_LINK(&(entry->list), dna_global_config);
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "store [%s] at head \n", entry->scope, 0, 0);
- entry_added = 1;
- }
-
- bail:
- if (0 == entry_added) {
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "config entry [%s] skipped\n", entry->dn, 0, 0);
- freeConfigEntry(&entry);
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- parseConfigEntry\n");
-
- return DNA_SUCCESS;
-}
-
-static void freeConfigEntry(struct configEntry ** entry)
-{
- struct configEntry *e = *entry;
-
- if (e->dn) {
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "freeing config entry [%s]\n", e->dn, 0, 0);
- slapi_ch_free_string(&e->dn);
- }
-
- if (e->type)
- slapi_ch_free_string(&e->type);
-
- if (e->prefix)
- slapi_ch_free_string(&e->prefix);
-
- if (e->filter)
- slapi_ch_free_string(&e->filter);
-
- if (e->slapi_filter)
- slapi_filter_free(e->slapi_filter, 1);
-
- if (e->generate)
- slapi_ch_free_string(&e->generate);
-
- if (e->scope)
- slapi_ch_free_string(&e->scope);
-
- slapi_ch_free((void **) entry);
-}
-
-static void deleteConfigEntry(PRCList * entry)
-{
- PR_REMOVE_LINK(entry);
- freeConfigEntry((struct configEntry **) & entry);
-}
-
-static void deleteConfig()
-{
- PRCList *list;
-
- while (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- deleteConfigEntry(list);
- }
-
- return;
-}
-
-/****************************************************
- Distributed ranges Helpers
-****************************************************/
-
-static int dna_fix_maxval(Slapi_DN *dn, PRUint64 *cur, PRUint64 *max)
-{
- /* TODO: check the main partition to see if another range
- * is available, and set the new local configuration
- * accordingly.
- * If a new range is not available run the retrieval task
- * and simply return error
- */
-
- return LDAP_OPERATIONS_ERROR;
-}
-
-static void dna_notice_allocation(Slapi_DN *dn, PRUint64 new)
-{
- /* TODO: check if we passed a new chunk threshold and update
- * the shared configuration on the public partition.
- */
-
- return;
-}
-
-/****************************************************
- Helpers
-****************************************************/
-
-static char *dna_get_dn(Slapi_PBlock * pb)
-{
- char *dn = 0;
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_get_dn\n");
-
- if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn)) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_dn: failed to get dn of changed entry");
- goto bail;
- }
-
-/* slapi_dn_normalize( dn );
-*/
- bail:
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_get_dn\n");
-
- return dn;
-}
-
-/* config check
- matching config dn or a descendent reloads config
-*/
-static int dna_dn_is_config(char *dn)
-{
- int ret = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_is_config\n");
-
- if (slapi_dn_issuffix(dn, getPluginDN())) {
- ret = 1;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_is_config\n");
-
- return ret;
-}
-
-#define DNA_LDAP_TAG_SK_REVERSE 0x81L
-
-static LDAPControl *dna_build_sort_control(const char *attr)
-{
- LDAPControl *ctrl;
- BerElement *ber;
- int rc;
-
- ber = ber_alloc();
- if (NULL == ber)
- return NULL;
-
- rc = ber_printf(ber, "{{stb}}", attr, DNA_LDAP_TAG_SK_REVERSE, 1);
- if (-1 == rc) {
- ber_free(ber, 1);
- return NULL;
- }
-
- rc = slapi_build_control(LDAP_CONTROL_SORTREQUEST, ber, 1, &ctrl);
-
- ber_free(ber, 1);
-
- if (LDAP_SUCCESS != rc)
- return NULL;
-
- return ctrl;
-}
-
-/****************************************************
- Functions that actually do things other
- than config and startup
-****************************************************/
-
-/* we do search all values between newval and maxval asking the
- * server to sort them, then we check the first free spot and
- * use it as newval */
-static int dna_first_free_value(struct configEntry *config_entry,
- PRUint64 *newval,
- PRUint64 maxval,
- PRUint64 increment)
-{
- Slapi_Entry **entries = NULL;
- Slapi_PBlock *pb = NULL;
- LDAPControl **ctrls;
- char *attrs[2];
- char *filter;
- char *prefix;
- char *type;
- int preflen;
- int result, status;
- PRUint64 tmpval, sval, i;
- char *strval = NULL;
-
- prefix = config_entry->prefix;
- type = config_entry->type;
- tmpval = *newval;
-
- attrs[0] = type;
- attrs[1] = NULL;
-
- ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl));
- if (NULL == ctrls)
- return LDAP_OPERATIONS_ERROR;
-
- ctrls[0] = dna_build_sort_control(config_entry->type);
- if (NULL == ctrls[0]) {
- slapi_ch_free((void **)&ctrls);
- return LDAP_OPERATIONS_ERROR;
- }
-
- filter = slapi_ch_smprintf("(&%s(&(%s>=%s%llu)(%s<=%s%llu)))",
- config_entry->filter,
- type, prefix?prefix:"", tmpval,
- type, prefix?prefix:"", maxval);
- if (NULL == filter) {
- ldap_control_free(ctrls[0]);
- slapi_ch_free((void **)&ctrls);
- return LDAP_OPERATIONS_ERROR;
- }
-
- pb = slapi_pblock_new();
- if (NULL == pb) {
- ldap_control_free(ctrls[0]);
- slapi_ch_free((void **)&ctrls);
- slapi_ch_free_string(&filter);
- return LDAP_OPERATIONS_ERROR;
- }
-
- slapi_search_internal_set_pb(pb, config_entry->scope,
- LDAP_SCOPE_SUBTREE, filter,
- attrs, 0, ctrls,
- NULL, getPluginID(), 0);
- slapi_search_internal_pb(pb);
-/*
- ldap_control_free(ctrls[0]);
-*/
- slapi_ch_free_string(&filter);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
- if (LDAP_SUCCESS != result) {
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
-
- if (NULL == entries || NULL == entries[0]) {
- /* no values means we already have a good value */
- status = LDAP_SUCCESS;
- goto cleanup;
- }
-
- /* entries are sorted and filtered for value >= tval therefore if the
- * first one does not match tval it means that the value is free,
- * otherwise we need to cycle through values until we find a mismatch,
- * the first mismatch is the first free pit */
-
- preflen = prefix?strlen(prefix):0;
- sval = 0;
- for (i = 0; NULL != entries[i]; i++) {
- strval = slapi_entry_attr_get_charptr(entries[i], type);
- if (preflen) {
- if (strlen(strval) <= preflen) {
- /* something very wrong here ... */
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
- strval = &strval[preflen-1];
- }
-
- errno = 0;
- sval = strtoul(strval, 0, 0);
- if (errno) {
- /* something very wrong here ... */
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
- slapi_ch_free_string(&strval);
-
- if (tmpval != sval)
- break;
-
- if (maxval < sval)
- break;
-
- tmpval += increment;
- }
-
- *newval = tmpval;
- status = LDAP_SUCCESS;
-
-cleanup:
- slapi_ch_free_string(&strval);
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
-
- return status;
-}
-
-/*
- * Perform ldap operationally atomic increment
- * Return the next value to be assigned
- * Method:
- * 1. retrieve entry
- * 2. do increment operations
- * 3. remove current value, add new value in one operation
- * 4. if failed, and less than 3 times, goto 1
- */
-static int dna_get_next_value(struct configEntry *config_entry,
- char **next_value_ret)
-{
- Slapi_PBlock *pb = NULL;
- char *old_value = NULL;
- Slapi_Entry *e = NULL;
- Slapi_DN *dn = NULL;
- char *attrlist[4];
- int attempts;
- int ret;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_get_next_value\n");
-
- /* get pre-requisites to search */
- dn = slapi_sdn_new_dn_byref(config_entry->dn);
- attrlist[0] = DNA_NEXTVAL;
- attrlist[1] = DNA_MAXVAL;
- attrlist[2] = DNA_INTERVAL;
- attrlist[3] = NULL;
-
-
- /* the operation is constructed such that race conditions
- * to increment the value are detected and avoided - one wins,
- * one loses - however, there is no need for the server to compete
- * with itself so we lock here
- */
-
- slapi_lock_mutex(g_new_value_lock);
-
- for (attempts = 0; attempts < 3; attempts++) {
-
- LDAPMod mod_add;
- LDAPMod mod_delete;
- LDAPMod *mods[3];
- char *delete_val[2];
- char *add_val[2];
- char new_value[16];
- char *interval;
- char *max_value;
- PRUint64 increment = 1; /* default increment */
- PRUint64 setval = 0;
- PRUint64 newval = 0;
- PRUint64 maxval = -1;
-
- /* do update */
- ret = slapi_search_internal_get_entry(dn, attrlist, &e,
- getPluginID());
- if (LDAP_SUCCESS != ret) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- old_value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
- if (NULL == old_value) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- setval = strtoul(old_value, 0, 0);
-
- max_value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
- if (max_value) {
- maxval = strtoul(max_value, 0, 0);
- slapi_ch_free_string(&max_value);
- }
-
- /* if not present the default is 1 */
- interval = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
- if (NULL != interval) {
- increment = strtoul(interval, 0, 0);
- }
-
- slapi_entry_free(e);
- e = NULL;
-
- /* check the value is actually in range */
-
- /* verify the new value is actually free and get the first
- * one free if not*/
- ret = dna_first_free_value(config_entry, &setval, maxval, increment);
- if (LDAP_SUCCESS != ret)
- goto done;
-
- /* try for a new range or fail */
- if (setval > maxval) {
- ret = dna_fix_maxval(dn, &setval, &maxval);
- if (LDAP_SUCCESS != ret) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_next_value: no more IDs available!!\n");
- goto done;
- }
-
- /* verify the new value is actually free and get the first
- * one free if not */
- ret = dna_first_free_value(config_entry, &setval, maxval, increment);
- if (LDAP_SUCCESS != ret)
- goto done;
- }
-
- if (setval > maxval) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- newval = setval + increment;
-
- /* try for a new range or fail */
- if (newval > maxval) {
- ret = dna_fix_maxval(dn, &newval, &maxval);
- if (LDAP_SUCCESS != ret) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_next_value: no more IDs available!!\n");
- goto done;
- }
- }
-
- /* try to set the new value */
-
- sprintf(new_value, "%llu", newval);
-
- delete_val[0] = old_value;
- delete_val[1] = 0;
-
- mod_delete.mod_op = LDAP_MOD_DELETE;
- mod_delete.mod_type = DNA_NEXTVAL;
- mod_delete.mod_values = delete_val;
-
- add_val[0] = new_value;
- add_val[1] = 0;
-
- mod_add.mod_op = LDAP_MOD_ADD;
- mod_add.mod_type = DNA_NEXTVAL;
- mod_add.mod_values = add_val;
-
- mods[0] = &mod_delete;
- mods[1] = &mod_add;
- mods[2] = 0;
-
- pb = slapi_pblock_new();
- if (NULL == pb) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- slapi_modify_internal_set_pb(pb, config_entry->dn,
- mods, 0, 0, getPluginID(), 0);
-
- slapi_modify_internal_pb(pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
-
- slapi_pblock_destroy(pb);
- pb = NULL;
- slapi_ch_free_string(&interval);
- slapi_ch_free_string(&old_value);
-
- if (LDAP_SUCCESS == ret) {
- *next_value_ret = slapi_ch_smprintf("%llu", setval);
- if (NULL == *next_value_ret) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- dna_notice_allocation(dn, newval);
- goto done;
- }
-
- if (LDAP_NO_SUCH_ATTRIBUTE != ret) {
- /* not the result of a race
- to change the value
- */
- goto done;
- }
- }
-
- done:
-
- slapi_unlock_mutex(g_new_value_lock);
-
- if (LDAP_SUCCESS != ret)
- slapi_ch_free_string(&old_value);
-
- if (dn)
- slapi_sdn_free(&dn);
-
- if (e)
- slapi_entry_free(e);
-
- if (pb)
- slapi_pblock_destroy(pb);
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_get_next_value\n");
-
- return ret;
-}
-
-/* for mods and adds:
- where dn's are supplied, the closest in scope
- is used as long as the type and filter
- are identical - otherwise all matches count
-*/
-
-static int dna_pre_op(Slapi_PBlock * pb, int modtype)
-{
- char *dn = 0;
- PRCList *list = 0;
- struct configEntry *config_entry = 0;
- struct slapi_entry *e = 0;
- char *last_type = 0;
- char *value = 0;
- int generate = 0;
- Slapi_Mods *smods = 0;
- Slapi_Mod *smod = 0;
- LDAPMod **mods;
- int free_entry = 0;
- char *errstr = NULL;
- int ret = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_pre_op\n");
-
- /* Just bail if we aren't ready to service requests yet. */
- if (!g_plugin_started)
- goto bail;
-
- if (0 == (dn = dna_get_dn(pb)))
- goto bail;
-
- if (dna_dn_is_config(dn))
- goto bail;
-
- if (LDAP_CHANGETYPE_ADD == modtype) {
- slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
- } else {
- /* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
- * available but it turns out that is only true if you are
- * a dbm backend pre-op plugin - lucky dbm backend pre-op
- * plugins.
- * I think that is wrong since the entry is useful for filter
- * tests and schema checks and this plugin shouldn't be limited
- * to a single backend type, but I don't want that fight right
- * now so we go get the entry here
- *
- slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
- */
- Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn);
- if (tmp_dn) {
- slapi_search_internal_get_entry(tmp_dn, 0, &e, getPluginID());
- slapi_sdn_free(&tmp_dn);
- free_entry = 1;
- }
-
- /* grab the mods - we'll put them back later with
- * our modifications appended
- */
- slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
- smods = slapi_mods_new();
- slapi_mods_init_passin(smods, mods);
- }
-
- if (0 == e)
- goto bailmod;
-
- dna_read_lock();
-
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
-
- while (list != dna_global_config && LDAP_SUCCESS == ret) {
- config_entry = (struct configEntry *) list;
-
- /* did we already service this type? */
- if (last_type) {
- if (!slapi_attr_type_cmp(config_entry->type, last_type, 1))
- goto next;
- }
-
- /* is the entry in scope? */
- if (config_entry->scope) {
- if (!slapi_dn_issuffix(dn, config_entry->scope))
- goto next;
- }
-
- /* does the entry match the filter? */
- if (config_entry->slapi_filter) {
- if (LDAP_SUCCESS != slapi_vattr_filter_test(pb,
- e,
- config_entry->
- slapi_filter, 0))
- goto next;
- }
-
-
- if (LDAP_CHANGETYPE_ADD == modtype) {
- /* does attribute contain the magic value
- or is the type not there?
- */
- value =
- slapi_entry_attr_get_charptr(e, config_entry->type);
- if ((value
- && !slapi_UTF8CASECMP(config_entry->generate, value))
- || 0 == value) {
- generate = 1;
- }
- } else {
- /* check mods for magic value */
- Slapi_Mod *next_mod = slapi_mod_new();
- smod = slapi_mods_get_first_smod(smods, next_mod);
- while (smod) {
- char *type = (char *)
- slapi_mod_get_type(smod);
-
- if (slapi_attr_types_equivalent(type,
- config_entry->type)) {
- struct berval *bv =
- slapi_mod_get_first_value(smod);
- int len = strlen(config_entry->generate);
-
-
- if (len == bv->bv_len) {
- if (!slapi_UTF8NCASECMP(bv->bv_val,
- config_entry->generate,
- len))
-
- generate = 1;
- break;
- }
- }
-
- slapi_mod_done(next_mod);
- smod = slapi_mods_get_next_smod(smods, next_mod);
- }
-
- slapi_mod_free(&next_mod);
- }
-
- if (generate) {
- char *new_value;
- int len;
-
- /* create the value to add */
- ret = dna_get_next_value(config_entry, &value);
- if (DNA_SUCCESS != ret) {
- errstr = slapi_ch_smprintf("Allocation of a new value for"
- " %s failed! Unable to proceed.",
- config_entry->type);
- break;
- }
-
- len = strlen(value) + 1;
- if (config_entry->prefix) {
- len += strlen(config_entry->prefix);
- }
-
- new_value = slapi_ch_malloc(len);
-
- if (config_entry->prefix) {
- strcpy(new_value, config_entry->prefix);
- strcat(new_value, value);
- } else
- strcpy(new_value, value);
-
- /* do the mod */
- if (LDAP_CHANGETYPE_ADD == modtype) {
- /* add - add to entry */
- slapi_entry_attr_set_charptr(e,
- config_entry->type,
- new_value);
- } else {
- /* mod - add to mods */
- slapi_mods_add_string(smods,
- LDAP_MOD_REPLACE,
- config_entry->type, new_value);
- }
-
- /* free up */
- slapi_ch_free_string(&value);
- slapi_ch_free_string(&new_value);
-
- /* make sure we don't generate for this
- * type again
- */
- if (LDAP_SUCCESS == ret) {
- last_type = config_entry->type;
- }
-
- generate = 0;
- }
- next:
- list = PR_NEXT_LINK(list);
- }
- }
-
- dna_unlock();
-
- bailmod:
- if (LDAP_CHANGETYPE_MODIFY == modtype) {
- /* these are the mods you made, really,
- * I didn't change them, honest, just had a quick look
- */
- mods = slapi_mods_get_ldapmods_passout(smods);
- slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
- slapi_mods_free(&smods);
- }
-
- bail:
-
- if (free_entry && e)
- slapi_entry_free(e);
-
- if (ret) {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_pre_op: operation failure [%d]\n", ret);
- slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
- slapi_ch_free((void **)&errstr);
- ret = DNA_FAILURE;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_pre_op\n");
-
- return ret;
-}
-
-static int dna_add_pre_op(Slapi_PBlock * pb)
-{
- return dna_pre_op(pb, LDAP_CHANGETYPE_ADD);
-}
-
-static int dna_mod_pre_op(Slapi_PBlock * pb)
-{
- return dna_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
-}
-
-static int dna_config_check_post_op(Slapi_PBlock * pb)
-{
- char *dn;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_config_check_post_op\n");
-
- if ((dn = dna_get_dn(pb))) {
- if (dna_dn_is_config(dn))
- loadPluginConfig();
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_config_check_post_op\n");
-
- return 0;
-}
-
-/****************************************************
- End of
- Functions that actually do things other
- than config and startup
-****************************************************/
-
-/**
- * debug functions to print config
- */
-void dnaDumpConfig()
-{
- PRCList *list;
-
- dna_read_lock();
-
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- while (list != dna_global_config) {
- dnaDumpConfigEntry((struct configEntry *) list);
- list = PR_NEXT_LINK(list);
- }
- }
-
- dna_unlock();
-}
-
-
-void dnaDumpConfigEntry(struct configEntry * entry)
-{
- printf("<- type --------------> %s\n", entry->type);
- printf("<---- prefix ---------> %s\n", entry->prefix);
- printf("<---- next value -----> %lu\n", entry->nextval);
- printf("<---- interval -------> %lu\n", entry->interval);
- printf("<---- generate flag --> %s\n", entry->generate);
-}
diff --git a/ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am b/ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am
deleted file mode 100644
index d0ac7f935..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-memberof/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-NULL =
-
-INCLUDES = \
- -I. \
- -I$(srcdir) \
- -DPREFIX=\""$(prefix)"\" \
- -DBINDIR=\""$(bindir)"\" \
- -DLIBDIR=\""$(libdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- $(MOZLDAP_CFLAGS) \
- $(KRB5_CFLAGS) \
- $(WARN_CFLAGS) \
- $(NULL)
-
-plugindir = $(libdir)/dirsrv/plugins
-plugin_LTLIBRARIES = \
- libipa-memberof-plugin.la \
- $(NULL)
-
-libipa_memberof_plugin_la_SOURCES = \
- ipa-memberof.c \
- ipa-memberof_config.c \
- $(NULL)
-
-libipa_memberof_plugin_la_LDFLAGS = -avoid-version
-
-libipa_memberof_plugin_la_LIBADD = \
- $(MOZLDAP_LIBS) \
- $(NULL)
-
-appdir = $(IPA_DATA_DIR)
-app_DATA = \
- memberof-conf.ldif \
- $(NULL)
-
-EXTRA_DIST = \
- $(app_DATA) \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c b/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c
deleted file mode 100644
index 3baf2f6cf..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c
+++ /dev/null
@@ -1,2244 +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.
- *
- * Authors:
- * Pete Rowley <prowley@redhat.com>
- *
- * Copyright (C) 2007 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK
- **/
-
-/* The memberof plugin updates the memberof attribute of entries
- * based on modifications performed on groupofuniquenames entries
- *
- * In addition the plugin provides a DS task that may be started
- * administrative clients and that creates the initial memberof
- * list for imported entries and/or fixes the memberof list of
- * existing entries that have inconsistent state (for example,
- * if the memberof attribute was incorrectly edited directly)
- *
- * To start the memberof task add an entry like:
- *
- * dn: cn=mytask, cn=memberof task, cn=tasks, cn=config
- * objectClass: top
- * objectClass: extensibleObject
- * cn: mytask
- * basedn: dc=example, dc=com
- * filter: (uid=test4)
- *
- * where "basedn" is required and refers to the top most node to perform the
- * task on, and where "filter" is an optional attribute that provides a filter
- * describing the entries to be worked on
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <dirsrv/slapi-plugin.h>
-
-#include "string.h"
-#include "nspr.h"
-
-#include "ipa-memberof.h"
-
-static Slapi_PluginDesc pdesc = { "ipamo", "FreeIPA project", "FreeIPA/1.0",
- "IPA memberof plugin" };
-
-static void* _PluginID = NULL;
-static Slapi_Mutex *memberof_operation_lock = 0;
-MemberOfConfig *qsortConfig = 0;
-
-typedef struct _memberofstringll
-{
- const char *dn;
- void *next;
-} memberofstringll;
-
-typedef struct _memberof_get_groups_data
-{
- MemberOfConfig *config;
- Slapi_Value *memberdn_val;
- Slapi_ValueSet **groupvals;
-} memberof_get_groups_data;
-
-/****** secrets *********/
-#ifndef SLAPI_TASK_PUBLIC
-/*from FDS slap.h
- * until we get a proper api for access
- */
-#define TASK_RUNNING_AS_TASK 0x0
-
-/******************************************************************************
- * Online tasks interface (to support import, export, etc)
- * After some cleanup, we could consider making these public.
- */
-struct _slapi_task {
- struct _slapi_task *next;
- char *task_dn;
- int task_exitcode; /* for the end user */
- int task_state; /* (see above) */
- int task_progress; /* number between 0 and task_work */
- int task_work; /* "units" of work to be done */
- int task_flags; /* (see above) */
-
- /* it is the task's responsibility to allocate this memory & free it: */
- char *task_status; /* transient status info */
- char *task_log; /* appended warnings, etc */
-
- void *task_private; /* for use by backends */
- TaskCallbackFn cancel; /* task has been cancelled by user */
- TaskCallbackFn destructor; /* task entry is being destroyed */
- int task_refcount;
-};
-
-static void slapi_task_set_data(Slapi_Task *task, void *data)
-{
- if (task) {
- task->task_private = data;
- }
-}
-
-/*
- * Retrieve some opaque task specific data from the task.
- */
-static void * slapi_task_get_data(Slapi_Task *task)
-{
- if (task) {
- return task->task_private;
- }
-}
-
-static void slapi_task_begin(Slapi_Task *task, int total_work)
-{
- if (task) {
- task->task_work = total_work;
- task->task_progress = 0;
- task->task_state = SLAPI_TASK_RUNNING;
- slapi_task_status_changed(task);
- }
-}
-
-static void slapi_task_inc_progress(Slapi_Task *task)
-{
- if (task) {
- task->task_progress++;
- slapi_task_status_changed(task);
- }
-}
-
-static void slapi_task_finish(Slapi_Task *task, int rc)
-{
- if (task) {
- task->task_exitcode = rc;
- task->task_state = SLAPI_TASK_FINISHED;
- slapi_task_status_changed(task);
- }
-}
-
-static void slapi_task_set_destructor_fn(Slapi_Task *task, TaskCallbackFn func)
-{
- if (task) {
- task->destructor = func;
- }
-}
-
-#endif /* !SLAPI_TASK_PUBLIC */
-/****** secrets ********/
-
-/*** function prototypes ***/
-
-/* exported functions */
-int ipamo_postop_init(Slapi_PBlock *pb );
-
-/* plugin callbacks */
-static int memberof_postop_del(Slapi_PBlock *pb );
-static int memberof_postop_modrdn(Slapi_PBlock *pb );
-static int memberof_postop_modify(Slapi_PBlock *pb );
-static int memberof_postop_add(Slapi_PBlock *pb );
-static int memberof_postop_start(Slapi_PBlock *pb);
-static int memberof_postop_close(Slapi_PBlock *pb);
-
-/* supporting cast */
-static int memberof_oktodo(Slapi_PBlock *pb);
-static char *memberof_getdn(Slapi_PBlock *pb);
-static int memberof_modop_one(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
- char *op_this, char *op_to);
-static int memberof_modop_one_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
- char *group_dn, char *op_this, char *op_to, memberofstringll *stack);
-static int memberof_add_one(Slapi_PBlock *pb, MemberOfConfig *config, char *addthis,
- char *addto);
-static int memberof_del_one(Slapi_PBlock *pb, MemberOfConfig *config, char *delthis,
- char *delfrom);
-static int memberof_mod_smod_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
- char *groupdn, Slapi_Mod *smod);
-static int memberof_add_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Mod *smod);
-static int memberof_del_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Mod *smod);
-static int memberof_mod_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
- char *groupdn, Slapi_Attr *attr);
-static int memberof_mod_attr_list_r(Slapi_PBlock *pb, MemberOfConfig *config,
- int mod, char *group_dn, char *op_this, Slapi_Attr *attr, memberofstringll *stack);
-static int memberof_add_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Attr *attr);
-static int memberof_del_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Attr *attr);
-static int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *pre_dn, char *post_dn, Slapi_Attr *attr);
-static int memberof_replace_list(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn);
-static void memberof_set_plugin_id(void * plugin_id);
-static void *memberof_get_plugin_id();
-static int memberof_compare(MemberOfConfig *config, const void *a, const void *b);
-static int memberof_qsort_compare(const void *a, const void *b);
-static void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr);
-static int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn);
-static int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
- char *type, plugin_search_entry_callback callback, void *callback_data);
-static int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn,
- Slapi_Value *memberdn);
-static Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn);
-static int memberof_get_groups_r(MemberOfConfig *config, char *memberdn,
- memberof_get_groups_data *data);
-static int memberof_get_groups_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_test_membership(Slapi_PBlock *pb, MemberOfConfig *config,
- char *group_dn);
-static int memberof_test_membership_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_replace_dn_type_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config,
- char *pre_dn, char *post_dn);
-static int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
- int mod_op, char *group_dn, char *op_this, char *replace_with, char *op_to,
- memberofstringll *stack);
-static int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
- Slapi_Entry *eAfter, int *returncode, char *returntext,
- void *arg);
-static void memberof_task_destructor(Slapi_Task *task);
-static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
- const char *default_val);
-static void memberof_fixup_task_thread(void *arg);
-static int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str);
-static int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data);
-
-
-/*** implementation ***/
-
-
-/*** exported functions ***/
-
-/*
- * ipamo_postop_init()
- *
- * Register plugin call backs
- *
- */
-int
-ipamo_postop_init(Slapi_PBlock *pb)
-{
- int ret = 0;
- char *memberof_plugin_identity = 0;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> ipamo_postop_init\n" );
- /*
- * Get plugin identity and stored it for later use
- * Used for internal operations
- */
-
- slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &memberof_plugin_identity);
- PR_ASSERT (memberof_plugin_identity);
- memberof_set_plugin_id(memberof_plugin_identity);
-
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&pdesc ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_POST_DELETE_FN,
- (void *) memberof_postop_del ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_POST_MODRDN_FN,
- (void *) memberof_postop_modrdn ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_POST_MODIFY_FN,
- (void *) memberof_postop_modify ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_POST_ADD_FN,
- (void *) memberof_postop_add ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) memberof_postop_start ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) memberof_postop_close ) != 0)
- {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "ipamo_postop_init failed\n" );
- ret = -1;
- }
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- ipamo_postop_init\n" );
- return ret;
-}
-
-/*
- * memberof_postop_start()
- *
- * Do plugin start up stuff
- *
- */
-int memberof_postop_start(Slapi_PBlock *pb)
-{
- int rc = 0;
- Slapi_Entry *config_e = NULL; /* entry containing plugin config */
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_start\n" );
-
- memberof_operation_lock = slapi_new_mutex();
- if(0 == memberof_operation_lock)
- {
- rc = -1;
- goto bail;
- }
-
- if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &config_e ) != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "missing config entry\n" );
- rc = -1;
- goto bail;
- }
-
- if (( rc = memberof_config( config_e )) != LDAP_SUCCESS ) {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "configuration failed (%s)\n", ldap_err2string( rc ));
- return( -1 );
- }
-
- rc = slapi_task_register_handler("memberof task", memberof_task_add);
- if(rc)
- {
- goto bail;
- }
-
- /*
- * TODO: start up operation actor thread
- * need to get to a point where server failure
- * or shutdown doesn't hose our operations
- * so we should create a task entry that contains
- * all required information to complete the operation
- * then the tasks can be restarted safely if
- * interrupted
- */
-
-bail:
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_start\n" );
-
- return rc;
-}
-
-/*
- * memberof_postop_close()
- *
- * Do plugin shut down stuff
- *
- */
-int memberof_postop_close(Slapi_PBlock *pb)
-{
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_close\n" );
-
-
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_close\n" );
- return 0;
-}
-
-/*
- * memberof_postop_del()
- *
- * All entries with a memberOf attribute that contains the group DN get retrieved
- * and have the their memberOf attribute regenerated (it is far too complex and
- * error prone to attempt to change only those dn values involved in this case -
- * mainly because the deleted group may itself be a member of other groups which
- * may be members of other groups etc. in a big recursive mess involving dependency
- * chains that must be created and traversed in order to decide if an entry should
- * really have those groups removed too)
- */
-int memberof_postop_del(Slapi_PBlock *pb)
-{
- int ret = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0};
- char *dn;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_del\n" );
-
- if(memberof_oktodo(pb) && (dn = memberof_getdn(pb)))
- {
- struct slapi_entry *e = NULL;
-
- slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &e );
-
- /* We need to get the config lock first. Trying to get the
- * config lock after we already hold the op lock can cause
- * a deadlock. */
- memberof_rlock_config();
- /* copy config so it doesn't change out from under us */
- memberof_copy_config(&configCopy, memberof_get_config());
- memberof_unlock_config();
-
- /* get the memberOf operation lock */
- memberof_lock();
-
- /* remove this group DN from the
- * membership lists of groups
- */
- memberof_del_dn_from_groups(pb, &configCopy, dn);
-
- /* is the entry of interest as a group? */
- if(e && !slapi_filter_test_simple(e, configCopy.group_filter))
- {
- Slapi_Attr *attr = 0;
-
- if(0 == slapi_entry_attr_find(e, configCopy.groupattr, &attr))
- {
- memberof_del_attr_list(pb, &configCopy, dn, attr);
- }
- }
-
- memberof_unlock();
-
- memberof_free_config(&configCopy);
- }
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_del\n" );
- return ret;
-}
-
-typedef struct _memberof_del_dn_data
-{
- char *dn;
- char *type;
-} memberof_del_dn_data;
-
-int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn)
-{
- memberof_del_dn_data data = {dn, config->groupattr};
-
- return memberof_call_foreach_dn(pb, dn,
- config->groupattr, memberof_del_dn_type_callback, &data);
-}
-
-int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data)
-{
- int rc = 0;
- LDAPMod mod;
- LDAPMod *mods[2];
- char *val[2];
- Slapi_PBlock *mod_pb = 0;
-
- mod_pb = slapi_pblock_new();
-
- mods[0] = &mod;
- mods[1] = 0;
-
- val[0] = ((memberof_del_dn_data *)callback_data)->dn;
- val[1] = 0;
-
- mod.mod_op = LDAP_MOD_DELETE;
- mod.mod_type = ((memberof_del_dn_data *)callback_data)->type;
- mod.mod_values = val;
-
- slapi_modify_internal_set_pb(
- mod_pb, slapi_entry_get_dn(e),
- mods, 0, 0,
- memberof_get_plugin_id(), 0);
-
- slapi_modify_internal_pb(mod_pb);
-
- slapi_pblock_get(mod_pb,
- SLAPI_PLUGIN_INTOP_RESULT,
- &rc);
-
- slapi_pblock_destroy(mod_pb);
-
- return rc;
-}
-
-/*
- * Does a callback search of "type=dn" under the db suffix that "dn" is in.
- * If "dn" is a user, you'd want "type" to be "member". If "dn" is a group,
- * you could want type to be either "member" or "memberOf" depending on the
- * case.
- */
-int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
- char *type, plugin_search_entry_callback callback, void *callback_data)
-{
- int rc = 0;
- Slapi_PBlock *search_pb = slapi_pblock_new();
- Slapi_Backend *be = 0;
- Slapi_DN *sdn = 0;
- Slapi_DN *base_sdn = 0;
- char *filter_str = 0;
-
- /* get the base dn for the backend we are in
- (we don't support having members and groups in
- different backends - issues with offline / read only backends)
- */
- sdn = slapi_sdn_new_dn_byref(dn);
- be = slapi_be_select(sdn);
- if(be)
- {
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
- }
-
- if(base_sdn)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)", type, dn);
- }
-
- if(filter_str)
- {
- slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
- 0, 0,
- memberof_get_plugin_id(),
- 0);
-
- slapi_search_internal_callback_pb(search_pb,
- callback_data,
- 0, callback,
- 0);
- }
-
- slapi_sdn_free(&sdn);
- slapi_pblock_destroy(search_pb);
- slapi_ch_free_string(&filter_str);
- return rc;
-}
-
-/*
- * memberof_postop_modrdn()
- *
- * All entries with a memberOf attribute that contains the old group DN get retrieved
- * and have the old group DN deleted and the new group DN added to their memberOf attribute
- */
-int memberof_postop_modrdn(Slapi_PBlock *pb)
-{
- int ret = 0;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_modrdn\n" );
-
- if(memberof_oktodo(pb))
- {
- MemberOfConfig *mainConfig = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0};
- struct slapi_entry *pre_e = NULL;
- struct slapi_entry *post_e = NULL;
- char *pre_dn = 0;
- char *post_dn = 0;
- int interested = 0;
-
- slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &pre_e );
- slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &post_e );
-
- if(pre_e && post_e)
- {
- pre_dn = slapi_entry_get_ndn(pre_e);
- post_dn = slapi_entry_get_ndn(post_e);
- }
-
- /* is the entry of interest? */
- memberof_rlock_config();
- mainConfig = memberof_get_config();
- if(pre_dn && post_dn &&
- !slapi_filter_test_simple(post_e, mainConfig->group_filter))
- {
- interested = 1;
- /* copy config so it doesn't change out from under us */
- memberof_copy_config(&configCopy, mainConfig);
- }
- memberof_unlock_config();
-
- if(interested)
- {
- Slapi_Attr *attr = 0;
-
- memberof_lock();
-
- /* get a list of member attributes present in the group
- * entry that is being renamed. */
- if(0 == slapi_entry_attr_find(post_e, configCopy.groupattr, &attr))
- {
- memberof_moddn_attr_list(pb, &configCopy, pre_dn, post_dn, attr);
- }
-
- /* modrdn must change the dns in groups that have
- * this group as a member.
- */
- memberof_replace_dn_from_groups(pb, &configCopy, pre_dn, post_dn);
-
- memberof_unlock();
-
- memberof_free_config(&configCopy);
- }
- }
-
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_modrdn\n" );
- return ret;
-}
-
-typedef struct _replace_dn_data
-{
- char *pre_dn;
- char *post_dn;
- char *type;
-} replace_dn_data;
-
-int memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config,
- char *pre_dn, char *post_dn)
-{
- replace_dn_data data = {pre_dn, post_dn, config->groupattr};
-
- return memberof_call_foreach_dn(pb, pre_dn, config->groupattr,
- memberof_replace_dn_type_callback, &data);
-}
-
-
-int memberof_replace_dn_type_callback(Slapi_Entry *e, void *callback_data)
-{
- int rc = 0;
- LDAPMod delmod;
- LDAPMod addmod;
- LDAPMod *mods[3];
- char *delval[2];
- char *addval[2];
- Slapi_PBlock *mod_pb = 0;
-
- mod_pb = slapi_pblock_new();
-
- mods[0] = &delmod;
- mods[1] = &addmod;
- mods[2] = 0;
-
- delval[0] = ((replace_dn_data *)callback_data)->pre_dn;
- delval[1] = 0;
-
- delmod.mod_op = LDAP_MOD_DELETE;
- delmod.mod_type = ((replace_dn_data *)callback_data)->type;
- delmod.mod_values = delval;
-
- addval[0] = ((replace_dn_data *)callback_data)->post_dn;
- addval[1] = 0;
-
- addmod.mod_op = LDAP_MOD_ADD;
- addmod.mod_type = ((replace_dn_data *)callback_data)->type;
- addmod.mod_values = addval;
-
- slapi_modify_internal_set_pb(
- mod_pb, slapi_entry_get_dn(e),
- mods, 0, 0,
- memberof_get_plugin_id(), 0);
-
- slapi_modify_internal_pb(mod_pb);
-
- slapi_pblock_get(mod_pb,
- SLAPI_PLUGIN_INTOP_RESULT,
- &rc);
-
- slapi_pblock_destroy(mod_pb);
-
- return rc;
-}
-
-/*
- * memberof_postop_modify()
- *
- * Added members are retrieved and have the group DN added to their memberOf attribute
- * Deleted members are retrieved and have the group DN deleted from their memberOf attribute
- * On replace of the membership attribute values:
- * 1. Sort old and new values
- * 2. Iterate through both lists at same time
- * 3. Any value not in old list but in new list - add group DN to memberOf attribute
- * 4. Any value in old list but not in new list - remove group DN from memberOf attribute
- *
- * Note: this will suck for large groups but nonetheless is optimal (it's linear) given
- * current restrictions i.e. originally adding members in sorted order would allow
- * us to sort one list only (the new one) but that is under server control, not this plugin
- */
-int memberof_postop_modify(Slapi_PBlock *pb)
-{
- int ret = 0;
- char *dn = 0;
- Slapi_Mods *smods = 0;
- Slapi_Mod *smod = 0;
- LDAPMod **mods;
- Slapi_Mod *next_mod = 0;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_modify\n" );
-
- if(memberof_oktodo(pb) &&
- (dn = memberof_getdn(pb)))
- {
- int config_copied = 0;
- MemberOfConfig *mainConfig = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0};
-
- /* get the mod set */
- slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
- smods = slapi_mods_new();
- slapi_mods_init_byref(smods, mods);
-
- next_mod = slapi_mod_new();
- smod = slapi_mods_get_first_smod(smods, next_mod);
- while(smod)
- {
- int interested = 0;
- char *type = (char *)slapi_mod_get_type(smod);
-
- /* We only want to copy the config if we encounter an
- * operation that we need to act on. We also want to
- * only copy the config the first time it's needed so
- * it remains the same for all mods in the operation,
- * despite any config changes that may be made. */
- if (!config_copied)
- {
- memberof_rlock_config();
- mainConfig = memberof_get_config();
-
- if(slapi_attr_types_equivalent(type, mainConfig->groupattr))
- {
- interested = 1;
- /* copy config so it doesn't change out from under us */
- memberof_copy_config(&configCopy, mainConfig);
- config_copied = 1;
- }
-
- memberof_unlock_config();
- } else {
- if(slapi_attr_types_equivalent(type, configCopy.groupattr))
- {
- interested = 1;
- }
- }
-
- if(interested)
- {
- int op = slapi_mod_get_operation(smod);
-
- memberof_lock();
-
- /* the modify op decides the function */
- switch(op & ~LDAP_MOD_BVALUES)
- {
- case LDAP_MOD_ADD:
- {
- /* add group DN to targets */
- memberof_add_smod_list(pb, &configCopy, dn, smod);
- break;
- }
-
- case LDAP_MOD_DELETE:
- {
- /* If there are no values in the smod, we should
- * just do a replace instead. The user is just
- * trying to delete all members from this group
- * entry, which the replace code deals with. */
- if (slapi_mod_get_num_values(smod) == 0)
- {
- memberof_replace_list(pb, &configCopy, dn);
- }
- else
- {
- /* remove group DN from target values in smod*/
- memberof_del_smod_list(pb, &configCopy, dn, smod);
- }
- break;
- }
-
- case LDAP_MOD_REPLACE:
- {
- /* replace current values */
- memberof_replace_list(pb, &configCopy, dn);
- break;
- }
-
- default:
- {
- slapi_log_error(
- SLAPI_LOG_PLUGIN,
- MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_postop_modify: unknown mod type\n" );
- break;
- }
- }
-
- memberof_unlock();
- }
-
- slapi_mod_done(next_mod);
- smod = slapi_mods_get_next_smod(smods, next_mod);
- }
-
- if (config_copied)
- {
- memberof_free_config(&configCopy);
- }
-
- slapi_mod_free(&next_mod);
- slapi_mods_free(&smods);
- }
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_modify\n" );
- return ret;
-}
-
-
-/*
- * memberof_postop_add()
- *
- * All members in the membership attribute of the new entry get retrieved
- * and have the group DN added to their memberOf attribute
- */
-int memberof_postop_add(Slapi_PBlock *pb)
-{
- int ret = 0;
- int interested = 0;
- char *dn = 0;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_add\n" );
-
- if(memberof_oktodo(pb) && (dn = memberof_getdn(pb)))
- {
- MemberOfConfig *mainConfig = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0};
- struct slapi_entry *e = NULL;
-
- slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &e );
-
-
- /* is the entry of interest? */
- memberof_rlock_config();
- mainConfig = memberof_get_config();
- if(e && !slapi_filter_test_simple(e, mainConfig->group_filter))
- {
- interested = 1;
- /* copy config so it doesn't change out from under us */
- memberof_copy_config(&configCopy, mainConfig);
- }
- memberof_unlock_config();
-
- if(interested)
- {
- Slapi_Attr *attr = 0;
-
- memberof_lock();
-
- if(0 == slapi_entry_attr_find(e, configCopy.groupattr, &attr))
- {
- memberof_add_attr_list(pb, &configCopy, dn, attr);
- }
-
- memberof_unlock();
-
- memberof_free_config(&configCopy);
- }
- }
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_add\n" );
- return ret;
-}
-
-/*** Support functions ***/
-
-/*
- * memberof_oktodo()
- *
- * Check that the op succeeded
- * Note: we also respond to replicated ops so we don't test for that
- * this does require that the memberOf attribute not be replicated
- * and this means that memberof is consistent with local state
- * not the network system state
- *
- */
-int memberof_oktodo(Slapi_PBlock *pb)
-{
- int ret = 1;
- int oprc = 0;
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_oktodo\n" );
-
- if(slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0)
- {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_postop_oktodo: could not get parameters\n" );
- ret = -1;
- }
-
- /* this plugin should only execute if the operation succeeded
- */
- if(oprc != 0)
- {
- ret = 0;
- }
-
- slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "<-- memberof_postop_oktodo\n" );
-
- return ret;
-}
-
-/*
- * memberof_getdn()
- *
- * Get dn of target entry
- *
- */
-char *memberof_getdn(Slapi_PBlock *pb)
-{
- char *dn = 0;
-
- slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
-
- return dn;
-}
-
-/*
- * memberof_modop_one()
- *
- * Perform op on memberof attribute of op_to using op_this as the value
- * However, if op_to happens to be a group, we must arrange for the group
- * members to have the mod performed on them instead, and we must take
- * care to not recurse when we have visted a group before
- *
- * Also, we must not delete entries that are a member of the group
- */
-int memberof_modop_one(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
- char *op_this, char *op_to)
-{
- return memberof_modop_one_r(pb, config, mod_op, op_this, op_this, op_to, 0);
-}
-
-/* memberof_modop_one_r()
- *
- * recursive function to perform above (most things don't need the replace arg)
- */
-
-int memberof_modop_one_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
- char *group_dn, char *op_this, char *op_to, memberofstringll *stack)
-{
- return memberof_modop_one_replace_r(
- pb, config, mod_op, group_dn, op_this, 0, op_to, stack);
-}
-
-/* memberof_modop_one_replace_r()
- *
- * recursive function to perform above (with added replace arg)
- */
-int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
- int mod_op, char *group_dn, char *op_this, char *replace_with,
- char *op_to, memberofstringll *stack)
-{
- int rc = 0;
- LDAPMod mod;
- LDAPMod replace_mod;
- LDAPMod *mods[3];
- char *val[2];
- char *replace_val[2];
- Slapi_PBlock *mod_pb = 0;
- char *attrlist[2] = {config->groupattr,0};
- Slapi_DN *op_to_sdn = 0;
- Slapi_Entry *e = 0;
- memberofstringll *ll = 0;
- char *op_str = 0;
- Slapi_Value *to_dn_val = slapi_value_new_string(op_to);
- Slapi_Value *this_dn_val = slapi_value_new_string(op_this);
-
- /* determine if this is a group op or single entry */
- op_to_sdn = slapi_sdn_new_dn_byref(op_to);
- slapi_search_internal_get_entry( op_to_sdn, attrlist,
- &e, memberof_get_plugin_id());
- if(!e)
- {
- /* In the case of a delete, we need to worry about the
- * missing entry being a nested group. There's a small
- * window where another thread may have deleted a nested
- * group that our group_dn entry refers to. This has the
- * potential of us missing some indirect member entries
- * that need to be updated. */
- if(LDAP_MOD_DELETE == mod_op)
- {
- Slapi_PBlock *search_pb = slapi_pblock_new();
- Slapi_DN *base_sdn = 0;
- Slapi_Backend *be = 0;
- char *filter_str = 0;
- int n_entries = 0;
-
- /* We can't tell for sure if the op_to entry is a
- * user or a group since the entry doesn't exist
- * anymore. We can safely ignore the missing entry
- * if no other entries have a memberOf attribute that
- * points to the missing entry. */
- be = slapi_be_select(op_to_sdn);
- if(be)
- {
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
- }
-
- if(base_sdn)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)",
- config->memberof_attr, op_to);
- }
-
- if(filter_str)
- {
- slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
- memberof_get_plugin_id(), 0);
-
- if (slapi_search_internal_pb(search_pb))
- {
- /* get result and log an error */
- int res = 0;
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: error searching for members: "
- "%d", res);
- } else {
- slapi_pblock_get(search_pb, SLAPI_NENTRIES, &n_entries);
-
- if(n_entries > 0)
- {
- /* We want to fixup the membership for the
- * entries that referred to the missing group
- * entry. This will fix the references to
- * the missing group as well as the group
- * represented by op_this. */
- memberof_test_membership(pb, config, op_to);
- }
- }
-
- slapi_free_search_results_internal(search_pb);
- slapi_ch_free_string(&filter_str);
- }
-
- slapi_pblock_destroy(search_pb);
- }
-
- goto bail;
- }
-
- if(LDAP_MOD_DELETE == mod_op)
- {
- op_str = "DELETE";
- }
- else if(LDAP_MOD_ADD == mod_op)
- {
- op_str = "ADD";
- }
- else if(LDAP_MOD_REPLACE == mod_op)
- {
- op_str = "REPLACE";
- }
- else
- {
- op_str = "UNKNOWN";
- }
-
- slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: %s %s in %s\n"
- ,op_str, op_this, op_to);
-
- if(!slapi_filter_test_simple(e, config->group_filter))
- {
- /* group */
- Slapi_Value *ll_dn_val = 0;
- Slapi_Attr *members = 0;
-
- ll = stack;
-
- /* have we been here before? */
- while(ll)
- {
- ll_dn_val = slapi_value_new_string(ll->dn);
-
- if(0 == memberof_compare(config, &ll_dn_val, &to_dn_val))
- {
- slapi_value_free(&ll_dn_val);
-
- /* someone set up infinitely
- recursive groups - bail out */
- slapi_log_error( SLAPI_LOG_PLUGIN,
- MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: group recursion"
- " detected in %s\n"
- ,op_to);
- goto bail;
- }
-
- slapi_value_free(&ll_dn_val);
- ll = ll->next;
- }
-
- /* do op on group */
- slapi_log_error( SLAPI_LOG_PLUGIN,
- MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: descending into group %s\n",
- op_to);
- /* Add the nested group's DN to the stack so we can detect loops later. */
- ll = (memberofstringll*)slapi_ch_malloc(sizeof(memberofstringll));
- ll->dn = op_to;
- ll->next = stack;
-
- slapi_entry_attr_find( e, config->groupattr, &members );
- if(members)
- {
- memberof_mod_attr_list_r(pb, config, mod_op, group_dn, op_this, members, ll);
- }
-
- {
- /* crazyness follows:
- * strict-aliasing doesn't like the required cast
- * to void for slapi_ch_free so we are made to
- * juggle to get a normal thing done
- */
- void *pll = ll;
- slapi_ch_free(&pll);
- ll = 0;
- }
- }
- /* continue with operation */
- {
- /* We want to avoid listing a group as a memberOf itself
- * in case someone set up a circular grouping.
- */
- if (0 == memberof_compare(config, &this_dn_val, &to_dn_val))
- {
- slapi_log_error( SLAPI_LOG_PLUGIN,
- MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: not processing memberOf "
- "operations on self entry: %s\n", this_dn_val);
- goto bail;
- }
-
- /* For add and del modify operations, we just regenerate the
- * memberOf attribute. */
- if(LDAP_MOD_DELETE == mod_op || LDAP_MOD_ADD == mod_op)
- {
- /* find parent groups and replace our member attr */
- memberof_fix_memberof_callback(e, config);
- } else {
- /* single entry - do mod */
- mod_pb = slapi_pblock_new();
-
- mods[0] = &mod;
- if(LDAP_MOD_REPLACE == mod_op)
- {
- mods[1] = &replace_mod;
- mods[2] = 0;
- }
- else
- {
- mods[1] = 0;
- }
-
- val[0] = op_this;
- val[1] = 0;
- mod.mod_op = LDAP_MOD_REPLACE == mod_op?LDAP_MOD_DELETE:mod_op;
- mod.mod_type = config->memberof_attr;
- mod.mod_values = val;
-
- if(LDAP_MOD_REPLACE == mod_op)
- {
- replace_val[0] = replace_with;
- replace_val[1] = 0;
-
- replace_mod.mod_op = LDAP_MOD_ADD;
- replace_mod.mod_type = config->memberof_attr;
- replace_mod.mod_values = replace_val;
- }
-
- slapi_modify_internal_set_pb(
- mod_pb, op_to,
- mods, 0, 0,
- memberof_get_plugin_id(), 0);
-
- slapi_modify_internal_pb(mod_pb);
-
- slapi_pblock_get(mod_pb,
- SLAPI_PLUGIN_INTOP_RESULT,
- &rc);
-
- slapi_pblock_destroy(mod_pb);
- }
- }
-
-bail:
- slapi_sdn_free(&op_to_sdn);
- slapi_value_free(&to_dn_val);
- slapi_value_free(&this_dn_val);
- slapi_entry_free(e);
- return rc;
-}
-
-
-/*
- * memberof_add_one()
- *
- * Add addthis DN to the memberof attribute of addto
- *
- */
-int memberof_add_one(Slapi_PBlock *pb, MemberOfConfig *config, char *addthis, char *addto)
-{
- return memberof_modop_one(pb, config, LDAP_MOD_ADD, addthis, addto);
-}
-
-/*
- * memberof_del_one()
- *
- * Delete delthis DN from the memberof attribute of delfrom
- *
- */
-int memberof_del_one(Slapi_PBlock *pb, MemberOfConfig *config, char *delthis, char *delfrom)
-{
- return memberof_modop_one(pb, config, LDAP_MOD_DELETE, delthis, delfrom);
-}
-
-/*
- * memberof_mod_smod_list()
- *
- * Perform mod for group DN to the memberof attribute of the list of targets
- *
- */
-int memberof_mod_smod_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
- char *group_dn, Slapi_Mod *smod)
-{
- int rc = 0;
- struct berval *bv = slapi_mod_get_first_value(smod);
- int last_size = 0;
- char *last_str = 0;
-
- while(bv)
- {
- char *dn_str = 0;
-
- if(last_size > bv->bv_len)
- {
- dn_str = last_str;
- }
- else
- {
- int the_size = (bv->bv_len * 2) + 1;
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- dn_str = (char*)slapi_ch_malloc(the_size);
-
- last_str = dn_str;
- last_size = the_size;
- }
-
- memset(dn_str, 0, last_size);
-
- strncpy(dn_str, bv->bv_val, (size_t)bv->bv_len);
-
- memberof_modop_one(pb, config, mod, group_dn, dn_str);
-
- bv = slapi_mod_get_next_value(smod);
- }
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- return rc;
-}
-
-/*
- * memberof_add_smod_list()
- *
- * Add group DN to the memberof attribute of the list of targets
- *
- */
-int memberof_add_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Mod *smod)
-{
- return memberof_mod_smod_list(pb, config, LDAP_MOD_ADD, groupdn, smod);
-}
-
-
-/*
- * memberof_del_smod_list()
- *
- * Remove group DN from the memberof attribute of the list of targets
- *
- */
-int memberof_del_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *groupdn, Slapi_Mod *smod)
-{
- return memberof_mod_smod_list(pb, config, LDAP_MOD_DELETE, groupdn, smod);
-}
-
-/**
- * Plugin identity mgmt
- */
-void memberof_set_plugin_id(void * plugin_id)
-{
- _PluginID=plugin_id;
-}
-
-void * memberof_get_plugin_id()
-{
- return _PluginID;
-}
-
-
-/*
- * memberof_mod_attr_list()
- *
- * Perform mod for group DN to the memberof attribute of the list of targets
- *
- */
-int memberof_mod_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
- char *group_dn, Slapi_Attr *attr)
-{
- return memberof_mod_attr_list_r(pb, config, mod, group_dn, group_dn, attr, 0);
-}
-
-int memberof_mod_attr_list_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
- char *group_dn, char *op_this, Slapi_Attr *attr, memberofstringll *stack)
-{
- int rc = 0;
- Slapi_Value *val = 0;
- Slapi_Value *op_this_val = 0;
- int last_size = 0;
- char *last_str = 0;
- int hint = slapi_attr_first_value(attr, &val);
-
- op_this_val = slapi_value_new_string(op_this);
-
- while(val)
- {
- char *dn_str = 0;
- struct berval *bv = 0;
-
- /* We don't want to process a memberOf operation on ourselves. */
- if(0 != memberof_compare(config, &val, &op_this_val))
- {
- bv = (struct berval *)slapi_value_get_berval(val);
-
- if(last_size > bv->bv_len)
- {
- dn_str = last_str;
- }
- else
- {
- int the_size = (bv->bv_len * 2) + 1;
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- dn_str = (char*)slapi_ch_malloc(the_size);
-
- last_str = dn_str;
- last_size = the_size;
- }
-
- memset(dn_str, 0, last_size);
-
- strncpy(dn_str, bv->bv_val, (size_t)bv->bv_len);
-
- /* If we're doing a replace (as we would in the MODRDN case), we need
- * to specify the new group DN value */
- if(mod == LDAP_MOD_REPLACE)
- {
- memberof_modop_one_replace_r(pb, config, mod, group_dn, op_this,
- group_dn, dn_str, stack);
- }
- else
- {
- memberof_modop_one_r(pb, config, mod, group_dn, op_this, dn_str, stack);
- }
- }
-
- hint = slapi_attr_next_value(attr, hint, &val);
- }
-
- slapi_value_free(&op_this_val);
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- return rc;
-}
-
-/*
- * memberof_add_attr_list()
- *
- * Add group DN to the memberof attribute of the list of targets
- *
- */
-int memberof_add_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, char *groupdn,
- Slapi_Attr *attr)
-{
- return memberof_mod_attr_list(pb, config, LDAP_MOD_ADD, groupdn, attr);
-}
-
-/*
- * memberof_del_attr_list()
- *
- * Remove group DN from the memberof attribute of the list of targets
- *
- */
-int memberof_del_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, char *groupdn,
- Slapi_Attr *attr)
-{
- return memberof_mod_attr_list(pb, config, LDAP_MOD_DELETE, groupdn, attr);
-}
-
-/*
- * memberof_moddn_attr_list()
- *
- * Perform mod for group DN to the memberof attribute of the list of targets
- *
- */
-int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
- char *pre_dn, char *post_dn, Slapi_Attr *attr)
-{
- int rc = 0;
- Slapi_Value *val = 0;
- int last_size = 0;
- char *last_str = 0;
- int hint = slapi_attr_first_value(attr, &val);
-
- while(val)
- {
- char *dn_str = 0;
- struct berval *bv = (struct berval *)slapi_value_get_berval(val);
-
- if(last_size > bv->bv_len)
- {
- dn_str = last_str;
- }
- else
- {
- int the_size = (bv->bv_len * 2) + 1;
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- dn_str = (char*)slapi_ch_malloc(the_size);
-
- last_str = dn_str;
- last_size = the_size;
- }
-
- memset(dn_str, 0, last_size);
-
- strncpy(dn_str, bv->bv_val, (size_t)bv->bv_len);
-
- memberof_modop_one_replace_r(pb, config, LDAP_MOD_REPLACE,
- post_dn, pre_dn, post_dn, dn_str, 0);
-
- hint = slapi_attr_next_value(attr, hint, &val);
- }
-
- if(last_str)
- slapi_ch_free_string(&last_str);
-
- return rc;
-}
-
-/* memberof_get_groups()
- *
- * Gets a list of all groups that an entry is a member of.
- * This is done by looking only at member attribute values.
- * A Slapi_ValueSet* is returned. It is up to the caller to
- * free it.
- */
-Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn)
-{
- Slapi_Value *memberdn_val = slapi_value_new_string(memberdn);
- Slapi_ValueSet *groupvals = slapi_valueset_new();
- memberof_get_groups_data data = {config, memberdn_val, &groupvals};
-
- memberof_get_groups_r(config, memberdn, &data);
-
- slapi_value_free(&memberdn_val);
-
- return groupvals;
-}
-
-int memberof_get_groups_r(MemberOfConfig *config, char *memberdn, memberof_get_groups_data *data)
-{
- /* Search for member=<memberdn>
- * For each match, add it to the list, recurse and do same search */
- return memberof_call_foreach_dn(NULL, memberdn, config->groupattr,
- memberof_get_groups_callback, data);
-}
-
-/* memberof_get_groups_callback()
- *
- * Callback to perform work of memberof_get_groups()
- */
-int memberof_get_groups_callback(Slapi_Entry *e, void *callback_data)
-{
- char *group_dn = slapi_entry_get_dn(e);
- Slapi_Value *group_dn_val = 0;
- Slapi_ValueSet *groupvals = *((memberof_get_groups_data*)callback_data)->groupvals;
-
- /* get the DN of the group */
- group_dn_val = slapi_value_new_string(group_dn);
-
- /* check if e is the same as our original member entry */
- if (0 == memberof_compare(((memberof_get_groups_data*)callback_data)->config,
- &((memberof_get_groups_data*)callback_data)->memberdn_val, &group_dn_val))
- {
- /* A recursive group caused us to find our original
- * entry we passed to memberof_get_groups(). We just
- * skip processing this entry. */
- slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_get_groups_callback: group recursion"
- " detected in %s\n" ,group_dn);
- slapi_value_free(&group_dn_val);
- goto bail;
-
- }
-
- /* have we been here before? */
- if (groupvals &&
- slapi_valueset_find(((memberof_get_groups_data*)callback_data)->config->group_slapiattr,
- groupvals, group_dn_val))
- {
- /* we either hit a recursive grouping, or an entry is
- * a member of a group through multiple paths. Either
- * way, we can just skip processing this entry since we've
- * already gone through this part of the grouping hierarchy. */
- slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_get_groups_callback: possible group recursion"
- " detected in %s\n" ,group_dn);
- slapi_value_free(&group_dn_val);
- goto bail;
- }
-
- /* Push group_dn_val into the valueset. This memory is now owned
- * by the valueset. */
- slapi_valueset_add_value_ext(groupvals, group_dn_val, SLAPI_VALUE_FLAG_PASSIN);
-
- /* now recurse to find parent groups of e */
- memberof_get_groups_r(((memberof_get_groups_data*)callback_data)->config,
- group_dn, callback_data);
-
- bail:
- return 0;
-}
-
-/* memberof_is_direct_member()
- *
- * tests for direct membership of memberdn in group groupdn
- * returns non-zero when true, zero otherwise
- */
-int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn,
- Slapi_Value *memberdn)
-{
- int rc = 0;
- Slapi_DN *sdn = 0;
- char *attrlist[2] = {config->groupattr,0};
- Slapi_Entry *group_e = 0;
- Slapi_Attr *attr = 0;
-
- sdn = slapi_sdn_new_dn_byref(slapi_value_get_string(groupdn));
-
- slapi_search_internal_get_entry(sdn, attrlist,
- &group_e, memberof_get_plugin_id());
-
- if(group_e)
- {
- slapi_entry_attr_find(group_e, config->groupattr, &attr );
- if(attr)
- {
- rc = 0 == slapi_attr_value_find(
- attr, slapi_value_get_berval(memberdn));
- }
- slapi_entry_free(group_e);
- }
-
- slapi_sdn_free(&sdn);
- return rc;
-}
-
-/* memberof_test_membership()
- *
- * Finds all entries who are a "memberOf" the group
- * represented by "group_dn". For each matching entry, we
- * call memberof_test_membership_callback().
- *
- * for each attribute in the memberof attribute
- * determine if the entry is still a member.
- *
- * test each for direct membership
- * move groups entry is memberof to member group
- * test remaining groups for membership in member groups
- * iterate until a pass fails to move a group over to member groups
- * remaining groups should be deleted
- */
-int memberof_test_membership(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn)
-{
- return memberof_call_foreach_dn(pb, group_dn, config->memberof_attr,
- memberof_test_membership_callback , config);
-}
-
-/*
- * memberof_test_membership_callback()
- *
- * A callback function to do the work of memberof_test_membership().
- * Note that this not only tests membership, but updates the memberOf
- * attributes in the entry to be correct.
- */
-int memberof_test_membership_callback(Slapi_Entry *e, void *callback_data)
-{
- int rc = 0;
- Slapi_Attr *attr = 0;
- int total = 0;
- Slapi_Value **member_array = 0;
- Slapi_Value **candidate_array = 0;
- Slapi_Value *entry_dn = 0;
- MemberOfConfig *config = (MemberOfConfig *)callback_data;
-
- entry_dn = slapi_value_new_string(slapi_entry_get_dn(e));
-
- if(0 == entry_dn)
- {
- goto bail;
- }
-
- /* divide groups into member and non-member lists */
- slapi_entry_attr_find(e, config->memberof_attr, &attr );
- if(attr)
- {
- slapi_attr_get_numvalues( attr, &total);
- if(total)
- {
- Slapi_Value *val = 0;
- int hint = 0;
- int c_index = 0;
- int m_index = 0;
- int member_found = 1;
- int outer_index = 0;
-
- candidate_array =
- (Slapi_Value**)
- slapi_ch_malloc(sizeof(Slapi_Value*)*total);
- memset(candidate_array, 0, sizeof(Slapi_Value*)*total);
- member_array =
- (Slapi_Value**)
- slapi_ch_malloc(sizeof(Slapi_Value*)*total);
- memset(member_array, 0, sizeof(Slapi_Value*)*total);
-
- hint = slapi_attr_first_value(attr, &val);
-
- while(val)
- {
- /* test for direct membership */
- if(memberof_is_direct_member(config, val, entry_dn))
- {
- /* it is a member */
- member_array[m_index] = val;
- m_index++;
- }
- else
- {
- /* not a member, still a candidate */
- candidate_array[c_index] = val;
- c_index++;
- }
-
- hint = slapi_attr_next_value(attr, hint, &val);
- }
-
- /* now iterate over members testing for membership
- in candidate groups and moving candidates to members
- when successful, quit when a full iteration adds no
- new members
- */
- while(member_found)
- {
- member_found = 0;
-
- /* For each group that this entry is a verified member of, see if
- * any of the candidate groups are members. If they are, add them
- * to the list of verified groups that this entry is a member of.
- */
- while(outer_index < m_index)
- {
- int inner_index = 0;
-
- while(inner_index < c_index)
- {
- /* Check for a special value in this position
- * that indicates that the candidate was moved
- * to the member array. */
- if((void*)1 ==
- candidate_array[inner_index])
- {
- /* was moved, skip */
- inner_index++;
- continue;
- }
-
- if(memberof_is_direct_member(
- config,
- candidate_array[inner_index],
- member_array[outer_index]))
- {
- member_array[m_index] =
- candidate_array
- [inner_index];
- m_index++;
-
- candidate_array[inner_index] =
- (void*)1;
-
- member_found = 1;
- }
-
- inner_index++;
- }
-
- outer_index++;
- }
- }
-
- /* here we are left only with values to delete
- from the memberof attribute in the candidate list
- */
- outer_index = 0;
- while(outer_index < c_index)
- {
- /* Check for a special value in this position
- * that indicates that the candidate was moved
- * to the member array. */
- if((void*)1 == candidate_array[outer_index])
- {
- /* item moved, skip */
- outer_index++;
- continue;
- }
-
- memberof_del_one(
- 0, config,
- (char*)slapi_value_get_string(
- candidate_array[outer_index]),
- (char*)slapi_value_get_string(entry_dn));
-
- outer_index++;
- }
- {
- /* crazyness follows:
- * strict-aliasing doesn't like the required cast
- * to void for slapi_ch_free so we are made to
- * juggle to get a normal thing done
- */
- void *pmember_array = member_array;
- void *pcandidate_array = candidate_array;
- slapi_ch_free(&pcandidate_array);
- slapi_ch_free(&pmember_array);
- candidate_array = 0;
- member_array = 0;
- }
- }
- }
-
-bail:
- slapi_value_free(&entry_dn);
-
- return rc;
-}
-
-/*
- * memberof_replace_list()
- *
- * Perform replace the group DN list in the memberof attribute of the list of targets
- *
- */
-int memberof_replace_list(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn)
-{
- struct slapi_entry *pre_e = NULL;
- struct slapi_entry *post_e = NULL;
- Slapi_Attr *pre_attr = 0;
- Slapi_Attr *post_attr = 0;
-
- slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &pre_e );
- slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &post_e );
-
- if(pre_e && post_e)
- {
- slapi_entry_attr_find( pre_e, config->groupattr, &pre_attr );
- slapi_entry_attr_find( post_e, config->groupattr, &post_attr );
- }
-
- if(pre_attr || post_attr)
- {
- int pre_total = 0;
- int post_total = 0;
- Slapi_Value **pre_array = 0;
- Slapi_Value **post_array = 0;
- int pre_index = 0;
- int post_index = 0;
-
- /* create arrays of values */
- if(pre_attr)
- {
- slapi_attr_get_numvalues( pre_attr, &pre_total);
- }
-
- if(post_attr)
- {
- slapi_attr_get_numvalues( post_attr, &post_total);
- }
-
- /* Stash a plugin global pointer here and have memberof_qsort_compare
- * use it. We have to do this because we use memberof_qsort_compare
- * as the comparator function for qsort, which requires the function
- * to only take two void* args. This is thread-safe since we only
- * store and use the pointer while holding the memberOf operation
- * lock. */
- qsortConfig = config;
-
- if(pre_total)
- {
- pre_array =
- (Slapi_Value**)
- slapi_ch_malloc(sizeof(Slapi_Value*)*pre_total);
- memberof_load_array(pre_array, pre_attr);
- qsort(
- pre_array,
- pre_total,
- sizeof(Slapi_Value*),
- memberof_qsort_compare);
- }
-
- if(post_total)
- {
- post_array =
- (Slapi_Value**)
- slapi_ch_malloc(sizeof(Slapi_Value*)*post_total);
- memberof_load_array(post_array, post_attr);
- qsort(
- post_array,
- post_total,
- sizeof(Slapi_Value*),
- memberof_qsort_compare);
- }
-
- qsortConfig = 0;
-
-
- /* work through arrays, following these rules:
- in pre, in post, do nothing
- in pre, not in post, delete from entry
- not in pre, in post, add to entry
- */
- while(pre_index < pre_total || post_index < post_total)
- {
- if(pre_index == pre_total)
- {
- /* add the rest of post */
- memberof_add_one(
- pb, config,
- group_dn,
- (char*)slapi_value_get_string(
- post_array[post_index]));
-
- post_index++;
- }
- else if(post_index == post_total)
- {
- /* delete the rest of pre */
- memberof_del_one(
- pb, config,
- group_dn,
- (char*)slapi_value_get_string(
- pre_array[pre_index]));
-
- pre_index++;
- }
- else
- {
- /* decide what to do */
- int cmp = memberof_compare(
- config,
- &(pre_array[pre_index]),
- &(post_array[post_index]));
-
- if(cmp < 0)
- {
- /* delete pre array */
- memberof_del_one(
- pb, config,
- group_dn,
- (char*)slapi_value_get_string(
- pre_array[pre_index]));
-
- pre_index++;
- }
- else if(cmp > 0)
- {
- /* add post array */
- memberof_add_one(
- pb, config,
- group_dn,
- (char*)slapi_value_get_string(
- post_array[post_index]));
-
- post_index++;
- }
- else
- {
- /* do nothing, advance */
- pre_index++;
- post_index++;
- }
- }
- }
- slapi_ch_free((void **)&pre_array);
- slapi_ch_free((void **)&post_array);
- }
-
- return 0;
-}
-
-/* memberof_load_array()
- *
- * put attribute values in array structure
- */
-void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr)
-{
- Slapi_Value *val = 0;
- int hint = slapi_attr_first_value(attr, &val);
-
- while(val)
- {
- *array = val;
- array++;
- hint = slapi_attr_next_value(attr, hint, &val);
- }
-}
-
-/* memberof_compare()
- *
- * compare two attr values
- */
-int memberof_compare(MemberOfConfig *config, const void *a, const void *b)
-{
- Slapi_Value *val1 = *((Slapi_Value **)a);
- Slapi_Value *val2 = *((Slapi_Value **)b);
-
- return slapi_attr_value_cmp(
- config->group_slapiattr,
- slapi_value_get_berval(val1),
- slapi_value_get_berval(val2));
-}
-
-/* memberof_qsort_compare()
- *
- * This is a version of memberof_compare that uses a plugin
- * global copy of the config. We'd prefer to pass in a copy
- * of config that is local to the running thread, but we can't
- * do this since qsort is using us as a comparator function.
- * We should only use this function when using qsort, and only
- * when the memberOf lock is acquired.
- */
-int memberof_qsort_compare(const void *a, const void *b)
-{
- Slapi_Value *val1 = *((Slapi_Value **)a);
- Slapi_Value *val2 = *((Slapi_Value **)b);
-
- return slapi_attr_value_cmp(
- qsortConfig->group_slapiattr,
- slapi_value_get_berval(val1),
- slapi_value_get_berval(val2));
-}
-
-void memberof_lock()
-{
- slapi_lock_mutex(memberof_operation_lock);
-}
-
-void memberof_unlock()
-{
- slapi_unlock_mutex(memberof_operation_lock);
-}
-
-typedef struct _task_data
-{
- char *dn;
- char *filter_str;
-} task_data;
-
-void memberof_fixup_task_thread(void *arg)
-{
- MemberOfConfig configCopy = {0, 0, 0, 0};
- Slapi_Task *task = (Slapi_Task *)arg;
- task_data *td = NULL;
- int rc = 0;
-
- /* Fetch our task data from the task */
- td = (task_data *)slapi_task_get_data(task);
-
- slapi_task_begin(task, 1);
- slapi_task_log_notice(task, "Memberof task starts (arg: %s) ...\n",
- td->filter_str);
-
- /* We need to get the config lock first. Trying to get the
- * config lock after we already hold the op lock can cause
- * a deadlock. */
- memberof_rlock_config();
- /* copy config so it doesn't change out from under us */
- memberof_copy_config(&configCopy, memberof_get_config());
- memberof_unlock_config();
-
- /* get the memberOf operation lock */
- memberof_lock();
-
- /* do real work */
- rc = memberof_fix_memberof(&configCopy, td->dn, td->filter_str);
-
- /* release the memberOf operation lock */
- memberof_unlock();
-
- memberof_free_config(&configCopy);
-
- slapi_task_log_notice(task, "Memberof task finished.");
- slapi_task_log_status(task, "Memberof task finished.");
- slapi_task_inc_progress(task);
-
- /* this will queue the destruction of the task */
- slapi_task_finish(task, rc);
-}
-
-/* extract a single value from the entry (as a string) -- if it's not in the
- * entry, the default will be returned (which can be NULL).
- * you do not need to free anything returned by this.
- */
-const char *fetch_attr(Slapi_Entry *e, const char *attrname,
- const char *default_val)
-{
- Slapi_Attr *attr;
- Slapi_Value *val = NULL;
-
- if (slapi_entry_attr_find(e, attrname, &attr) != 0)
- return default_val;
- slapi_attr_first_value(attr, &val);
- return slapi_value_get_string(val);
-}
-
-int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
- Slapi_Entry *eAfter, int *returncode, char *returntext,
- void *arg)
-{
- PRThread *thread = NULL;
- int rv = SLAPI_DSE_CALLBACK_OK;
- task_data *mytaskdata = NULL;
- Slapi_Task *task = NULL;
- const char *filter;
- const char *dn = 0;
-
- *returncode = LDAP_SUCCESS;
- /* get arg(s) */
- if ((dn = fetch_attr(e, "basedn", 0)) == NULL)
- {
- *returncode = LDAP_OBJECT_CLASS_VIOLATION;
- rv = SLAPI_DSE_CALLBACK_ERROR;
- goto out;
- }
-
- if ((filter = fetch_attr(e, "filter", "(objectclass=inetuser)")) == NULL)
- {
- *returncode = LDAP_OBJECT_CLASS_VIOLATION;
- rv = SLAPI_DSE_CALLBACK_ERROR;
- goto out;
- }
-
- /* setup our task data */
- mytaskdata = (task_data*)slapi_ch_malloc(sizeof(task_data));
- if (mytaskdata == NULL)
- {
- *returncode = LDAP_OPERATIONS_ERROR;
- rv = SLAPI_DSE_CALLBACK_ERROR;
- goto out;
- }
- mytaskdata->dn = slapi_ch_strdup(dn);
- mytaskdata->filter_str = slapi_ch_strdup(filter);
-
- /* allocate new task now */
- task = slapi_new_task(slapi_entry_get_ndn(e));
-
- /* register our destructor for cleaning up our private data */
- slapi_task_set_destructor_fn(task, memberof_task_destructor);
-
- /* Stash a pointer to our data in the task */
- slapi_task_set_data(task, mytaskdata);
-
- /* start the sample task as a separate thread */
- thread = PR_CreateThread(PR_USER_THREAD, memberof_fixup_task_thread,
- (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
- if (thread == NULL)
- {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "unable to create task thread!\n");
- *returncode = LDAP_OPERATIONS_ERROR;
- rv = SLAPI_DSE_CALLBACK_ERROR;
- slapi_task_finish(task, *returncode);
- } else {
- rv = SLAPI_DSE_CALLBACK_OK;
- }
-
-out:
- return rv;
-}
-
-void
-memberof_task_destructor(Slapi_Task *task)
-{
- if (task) {
- task_data *mydata = (task_data *)slapi_task_get_data(task);
- if (mydata) {
- slapi_ch_free_string(&mydata->dn);
- slapi_ch_free_string(&mydata->filter_str);
- /* Need to cast to avoid a compiler warning */
- slapi_ch_free((void **)&mydata);
- }
- }
-}
-
-int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str)
-{
- int rc = 0;
- Slapi_PBlock *search_pb = slapi_pblock_new();
-
- slapi_search_internal_set_pb(search_pb, dn,
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
- 0, 0,
- memberof_get_plugin_id(),
- 0);
-
- rc = slapi_search_internal_callback_pb(search_pb,
- config,
- 0, memberof_fix_memberof_callback,
- 0);
-
- slapi_pblock_destroy(search_pb);
-
- return rc;
-}
-
-/* memberof_fix_memberof_callback()
- * Add initial and/or fix up broken group list in entry
- *
- * 1. Remove all present memberOf values
- * 2. Add direct group membership memberOf values
- * 3. Add indirect group membership memberOf values
- */
-int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
-{
- int rc = 0;
- char *dn = slapi_entry_get_dn(e);
- MemberOfConfig *config = (MemberOfConfig *)callback_data;
- memberof_del_dn_data del_data = {0, config->memberof_attr};
- Slapi_ValueSet *groups = 0;
-
- /* get a list of all of the groups this user belongs to */
- groups = memberof_get_groups(config, dn);
-
- /* If we found some groups, replace the existing memberOf attribute
- * with the found values. */
- if (groups && slapi_valueset_count(groups))
- {
- Slapi_PBlock *mod_pb = slapi_pblock_new();
- Slapi_Value *val = 0;
- Slapi_Mod *smod;
- LDAPMod **mods = (LDAPMod **) slapi_ch_malloc(2 * sizeof(LDAPMod *));
- int hint = 0;
-
- /* NGK - need to allocate the smod */
- smod = slapi_mod_new();
- slapi_mod_init(smod, 0);
- slapi_mod_set_operation(smod, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
- slapi_mod_set_type(smod, config->memberof_attr);
-
- /* Loop through all of our values and add them to smod */
- hint = slapi_valueset_first_value(groups, &val);
- while (val)
- {
- /* this makes a copy of the berval */
- slapi_mod_add_value(smod, slapi_value_get_berval(val));
- hint = slapi_valueset_next_value(groups, hint, &val);
- }
-
- mods[0] = slapi_mod_get_ldapmod_passout(smod);
- mods[1] = 0;
-
- slapi_modify_internal_set_pb(
- mod_pb, dn, mods, 0, 0,
- memberof_get_plugin_id(), 0);
-
- slapi_modify_internal_pb(mod_pb);
-
- slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
-
- ldap_mods_free(mods, 1);
- slapi_mod_free(&smod);
- /* NGK - need to free the smod */
- slapi_pblock_destroy(mod_pb);
- } else {
- /* No groups were found, so remove the memberOf attribute
- * from this entry. */
- memberof_del_dn_type_callback(e, &del_data);
- }
-
- slapi_valueset_free(groups);
-
- return rc;
-}
-
diff --git a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h b/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h
deleted file mode 100644
index 3e7b5cf4b..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h
+++ /dev/null
@@ -1,100 +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) 2008 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * ipa-memberof.h - memberOf shared definitions
- *
- */
-
-#ifndef _MEMBEROF_H_
-#define _MEMBEROF_H_
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <dirsrv/slapi-plugin.h>
-#include <nspr.h>
-
-/****** secrets *********/
-/*from FDS slapi-private.h
- * until we get a proper api for access
- */
-#define SLAPI_DSE_CALLBACK_OK (1)
-#define SLAPI_DSE_CALLBACK_ERROR (-1)
-#define SLAPI_DSE_CALLBACK_DO_NOT_APPLY (0)
-#define SLAPI_DSE_RETURNTEXT_SIZE 512
-#define DSE_FLAG_PREOP 0x0002
-/*********** end secrets **********/
-/*
- * macros
- */
-#define MEMBEROF_PLUGIN_SUBSYSTEM "ipa-memberof-plugin" /* used for logging */
-#define MEMBEROF_GROUP_ATTR "member"
-#define MEMBEROF_ATTR "memberOf"
-
-
-/*
- * structs
- */
-typedef struct memberofconfig {
- char *groupattr;
- char *memberof_attr;
- Slapi_Filter *group_filter;
- Slapi_Attr *group_slapiattr;
-} MemberOfConfig;
-
-
-/*
- * functions
- */
-int memberof_config(Slapi_Entry *config_e);
-void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src);
-void memberof_free_config(MemberOfConfig *config);
-MemberOfConfig *memberof_get_config();
-void memberof_lock();
-void memberof_unlock();
-void memberof_rlock_config();
-void memberof_wlock_config();
-void memberof_unlock_config();
-
-
-#endif /* _MEMBEROF_H_ */
diff --git a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c b/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c
deleted file mode 100644
index b2bd374ad..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c
+++ /dev/null
@@ -1,312 +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) 2008 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * memberof_config.c - configuration-related code for memberOf plug-in
- *
- */
-
-#include <plstr.h>
-
-#include "ipa-memberof.h"
-
-#define MEMBEROF_CONFIG_FILTER "(objectclass=*)"
-
-/*
- * The configuration attributes are contained in the plugin entry e.g.
- * cn=MemberOf Plugin,cn=plugins,cn=config
- *
- * Configuration is a two step process. The first pass is a validation step which
- * occurs pre-op - check inputs and error out if bad. The second pass actually
- * applies the changes to the run time config.
- */
-
-
-/*
- * function prototypes
- */
-static int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg);
-static int memberof_search (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- return SLAPI_DSE_CALLBACK_OK;
-}
-
-/*
- * static variables
- */
-/* This is the main configuration which is updated from dse.ldif. The
- * config will be copied when it is used by the plug-in to prevent it
- * being changed out from under a running memberOf operation. */
-static MemberOfConfig theConfig;
-static PRRWLock *memberof_config_lock = 0;
-static int inited = 0;
-
-
-static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- return SLAPI_DSE_CALLBACK_ERROR;
-}
-
-/*
- * memberof_config()
- *
- * Read configuration and create a configuration data structure.
- * This is called after the server has configured itself so we can
- * perform checks with regards to suffixes if it ever becomes
- * necessary.
- * Returns an LDAP error code (LDAP_SUCCESS if all goes well).
- */
-int
-memberof_config(Slapi_Entry *config_e)
-{
- int returncode = LDAP_SUCCESS;
- char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
-
- if ( inited ) {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "only one memberOf plugin instance can be used\n" );
- return( LDAP_PARAM_ERROR );
- }
-
- /* initialize the RW lock to protect the main config */
- memberof_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "memberof_config_lock");
-
- /* initialize fields */
- memberof_apply_config(NULL, NULL, config_e,
- &returncode, returntext, NULL);
-
- /* config DSE must be initialized before we get here */
- if (returncode == LDAP_SUCCESS) {
- const char *config_dn = slapi_entry_get_dn_const(config_e);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
- config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
- dont_allow_that,NULL);
- slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP,
- config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
- dont_allow_that, NULL);
- slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP,
- config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
- dont_allow_that, NULL);
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
- memberof_search,NULL);
- }
-
- inited = 1;
-
- if (returncode != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "Error %d: %s\n", returncode, returntext);
- }
-
- return returncode;
-}
-
-
-/*
- * memberof_apply_config()
- *
- * Just use hardcoded config values.
- */
-static int
-memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- char *groupattr = NULL;
- char *memberof_attr = NULL;
- char *filter_str = NULL;
-
- *returncode = LDAP_SUCCESS;
-
- groupattr = slapi_ch_strdup(MEMBEROF_GROUP_ATTR);
- memberof_attr = slapi_ch_strdup(MEMBEROF_ATTR);
-
- /* We want to be sure we don't change the config in the middle of
- * a memberOf operation, so we obtain an exclusive lock here */
- memberof_wlock_config();
-
- if (!theConfig.groupattr ||
- (groupattr && PL_strcmp(theConfig.groupattr, groupattr))) {
- slapi_ch_free_string(&theConfig.groupattr);
- theConfig.groupattr = groupattr;
- groupattr = NULL; /* config now owns memory */
-
- /* We allocate a Slapi_Attr using the groupattr for
- * convenience in our memberOf comparison functions */
- slapi_attr_free(&theConfig.group_slapiattr);
- theConfig.group_slapiattr = slapi_attr_new();
- slapi_attr_init(theConfig.group_slapiattr, theConfig.groupattr);
-
- /* The filter is based off of the groupattr, so we
- * update it here too. */
- slapi_filter_free(theConfig.group_filter, 1);
- filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattr);
- theConfig.group_filter = slapi_str2filter(filter_str);
- slapi_ch_free_string(&filter_str);
- }
-
- if (!theConfig.memberof_attr ||
- (memberof_attr && PL_strcmp(theConfig.memberof_attr, memberof_attr))) {
- slapi_ch_free_string(&theConfig.memberof_attr);
- theConfig.memberof_attr = memberof_attr;
- memberof_attr = NULL; /* config now owns memory */
- }
-
- /* release the lock */
- memberof_unlock_config();
-
- slapi_ch_free_string(&groupattr);
- slapi_ch_free_string(&memberof_attr);
-
- if (*returncode != LDAP_SUCCESS)
- {
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- else
- {
- return SLAPI_DSE_CALLBACK_OK;
- }
-}
-
-/*
- * memberof_copy_config()
- *
- * Makes a copy of the config in src. This function will free the
- * elements of dest if they already exist. This should only be called
- * if you hold the memberof config lock if src was obtained with
- * memberof_get_config().
- */
-void
-memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
-{
- if (dest && src)
- {
- /* Check if the copy is already up to date */
- if (!dest->groupattr || (src->groupattr
- && PL_strcmp(dest->groupattr, src->groupattr)))
- {
- slapi_ch_free_string(&dest->groupattr);
- dest->groupattr = slapi_ch_strdup(src->groupattr);
- slapi_filter_free(dest->group_filter, 1);
- dest->group_filter = slapi_filter_dup(src->group_filter);
- slapi_attr_free(&dest->group_slapiattr);
- dest->group_slapiattr = slapi_attr_dup(src->group_slapiattr);
- }
-
- if (!dest->memberof_attr || (src->memberof_attr
- && PL_strcmp(dest->memberof_attr, src->memberof_attr)))
- {
- slapi_ch_free_string(&dest->memberof_attr);
- dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
- }
- }
-}
-
-/*
- * memberof_free_config()
- *
- * Free's the contents of a config structure.
- */
-void
-memberof_free_config(MemberOfConfig *config)
-{
- if (config)
- {
- slapi_ch_free_string(&config->groupattr);
- slapi_filter_free(config->group_filter, 1);
- slapi_attr_free(&config->group_slapiattr);
- slapi_ch_free_string(&config->memberof_attr);
- }
-}
-
-/*
- * memberof_get_config()
- *
- * Returns a pointer to the main config. You should call
- * memberof_rlock_config() first so the main config doesn't
- * get modified out from under you.
- */
-MemberOfConfig *
-memberof_get_config()
-{
- return &theConfig;
-}
-
-/*
- * memberof_rlock_config()
- *
- * Gets a non-exclusive lock on the main config. This will
- * prevent the config from being changed out from under you
- * while you read it, but it will still allow other threads
- * to read the config at the same time.
- */
-void
-memberof_rlock_config()
-{
- PR_RWLock_Rlock(memberof_config_lock);
-}
-
-/*
- * memberof_wlock_config()
- *
- * Gets an exclusive lock on the main config. This should
- * be called if you need to write to the main config.
- */
-void
-memberof_wlock_config()
-{
- PR_RWLock_Wlock(memberof_config_lock);
-}
-
-/*
- * memberof_unlock_config()
- *
- * Unlocks the main config.
- */
-void
-memberof_unlock_config()
-{
- PR_RWLock_Unlock(memberof_config_lock);
-}
diff --git a/ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif b/ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif
deleted file mode 100644
index 1441afeae..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-memberof/memberof-conf.ldif
+++ /dev/null
@@ -1,14 +0,0 @@
-dn: cn=ipa-memberof,cn=plugins,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSlapdPlugin
-objectclass: extensibleObject
-cn: ipa-memberof
-nsslapd-pluginpath: libipa-memberof-plugin
-nsslapd-plugininitfunc: ipamo_postop_init
-nsslapd-plugintype: postoperation
-nsslapd-pluginenabled: on
-nsslapd-pluginid: memberof
-nsslapd-pluginversion: 1.0
-nsslapd-pluginvendor: Red Hat
-nsslapd-plugindescription: Memberof plugin
diff --git a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
deleted file mode 100644
index 540646f06..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-NULL =
-
-INCLUDES = \
- -I. \
- -I$(srcdir) \
- -DPREFIX=\""$(prefix)"\" \
- -DBINDIR=\""$(bindir)"\" \
- -DLIBDIR=\""$(libdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- $(MOZLDAP_CFLAGS) \
- $(KRB5_CFLAGS) \
- $(SSL_CFLAGS) \
- $(WARN_CFLAGS) \
- $(NULL)
-
-plugindir = $(libdir)/dirsrv/plugins
-plugin_LTLIBRARIES = \
- libipa_pwd_extop.la \
- $(NULL)
-
-libipa_pwd_extop_la_SOURCES = \
- ipa_pwd_extop.c \
- $(NULL)
-
-libipa_pwd_extop_la_LDFLAGS = -avoid-version
-
-libipa_pwd_extop_la_LIBADD = \
- $(KRB5_LIBS) \
- $(SSL_LIBS) \
- $(MOZLDAP_LIBS) \
- $(NULL)
-
-appdir = $(IPA_DATA_DIR)
-app_DATA = \
- pwd-extop-conf.ldif \
- $(NULL)
-
-EXTRA_DIST = \
- README \
- $(app_DATA) \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README b/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README
deleted file mode 100644
index e69de29bb..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/README
+++ /dev/null
diff --git a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
deleted file mode 100644
index 24acc8875..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+++ /dev/null
@@ -1,4058 +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.
- *
- * Authors:
- * Simo Sorce <ssorce@redhat.com>
- *
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * Password Modify - LDAP Extended Operation.
- * RFC 3062
- *
- *
- * This plugin implements the "Password Modify - LDAP3"
- * extended operation for LDAP. The plugin function is called by
- * the server if an LDAP client request contains the OID:
- * "1.3.6.1.4.1.4203.1.11.1".
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <prio.h>
-#include <ssl.h>
-#include <dirsrv/slapi-plugin.h>
-#define KRB5_PRIVATE 1
-#include <krb5.h>
-#include <lber.h>
-#include <time.h>
-#include <iconv.h>
-#include <openssl/des.h>
-#include <openssl/md4.h>
-
-/* Type of connection for this operation;*/
-#define LDAP_EXTOP_PASSMOD_CONN_SECURE
-
-/* Uncomment the following #undef FOR TESTING:
- * allows non-SSL connections to use the password change extended op */
-/* #undef LDAP_EXTOP_PASSMOD_CONN_SECURE */
-
-/* ber tags for the PasswdModifyRequestValue sequence */
-#define LDAP_EXTOP_PASSMOD_TAG_USERID 0x80U
-#define LDAP_EXTOP_PASSMOD_TAG_OLDPWD 0x81U
-#define LDAP_EXTOP_PASSMOD_TAG_NEWPWD 0x82U
-
-/* ber tags for the PasswdModifyResponseValue sequence */
-#define LDAP_EXTOP_PASSMOD_TAG_GENPWD 0x80U
-
-/* OID of the extended operation handled by this plug-in */
-#define EXOP_PASSWD_OID "1.3.6.1.4.1.4203.1.11.1"
-
-/* OID to retrieve keytabs */
-#define KEYTAB_SET_OID "2.16.840.1.113730.3.8.3.1"
-#define KEYTAB_RET_OID "2.16.840.1.113730.3.8.3.2"
-
-/* krbTicketFlags */
-#define KTF_DISALLOW_POSTDATED 0x00000001
-#define KTF_DISALLOW_FORWARDABLE 0x00000002
-#define KTF_DISALLOW_TGT_BASED 0x00000004
-#define KTF_DISALLOW_RENEWABLE 0x00000008
-#define KTF_DISALLOW_PROXIABLE 0x00000010
-#define KTF_DISALLOW_DUP_SKEY 0x00000020
-#define KTF_DISALLOW_ALL_TIX 0x00000040
-#define KTF_REQUIRES_PRE_AUTH 0x00000080
-#define KTF_REQUIRES_HW_AUTH 0x00000100
-#define KTF_REQUIRES_PWCHANGE 0x00000200
-#define KTF_DISALLOW_SVR 0x00001000
-#define KTF_PWCHANGE_SERVICE 0x00002000
-
-/* These are the default enc:salt types if nothing is defined.
- * TODO: retrieve the configure set of ecntypes either from the
- * kfc.conf file or by synchronizing the the file content into
- * the directory */
-
-/* Salt types */
-#define KRB5_KDB_SALTTYPE_NORMAL 0
-#define KRB5_KDB_SALTTYPE_V4 1
-#define KRB5_KDB_SALTTYPE_NOREALM 2
-#define KRB5_KDB_SALTTYPE_ONLYREALM 3
-#define KRB5_KDB_SALTTYPE_SPECIAL 4
-#define KRB5_KDB_SALTTYPE_AFS3 5
-
-#define KRB5P_SALT_SIZE 16
-
-void krb5int_c_free_keyblock_contents(krb5_context context, register krb5_keyblock *key);
-
-static const char *ipapwd_def_encsalts[] = {
- "des3-hmac-sha1:normal",
-/* "arcfour-hmac:normal",
- "des-hmac-sha1:normal",
- "des-cbc-md5:normal", */
- "des-cbc-crc:normal",
-/* "des-cbc-crc:v4",
- "des-cbc-crc:afs3", */
- NULL
-};
-
-struct ipapwd_encsalt {
- krb5_int32 enc_type;
- krb5_int32 salt_type;
-};
-
-static const char *ipa_realm_dn;
-static const char *ipa_pwd_config_dn;
-static const char *ipa_changepw_principal_dn;
-
-#define IPAPWD_PLUGIN_NAME "ipa-pwd-extop"
-#define IPAPWD_FEATURE_DESC "IPA Password Manager"
-#define IPAPWD_PLUGIN_DESC "IPA Password Extended Operation plugin"
-
-static Slapi_PluginDesc pdesc = {
- IPAPWD_FEATURE_DESC,
- "FreeIPA project",
- "FreeIPA/1.0",
- IPAPWD_PLUGIN_DESC
-};
-
-static void *ipapwd_plugin_id;
-
-#define IPA_CHANGETYPE_NORMAL 0
-#define IPA_CHANGETYPE_ADMIN 1
-#define IPA_CHANGETYPE_DSMGR 2
-
-struct ipapwd_krbcfg {
- krb5_context krbctx;
- char *realm;
- krb5_keyblock *kmkey;
- int num_supp_encsalts;
- struct ipapwd_encsalt *supp_encsalts;
- int num_pref_encsalts;
- struct ipapwd_encsalt *pref_encsalts;
- char **passsync_mgrs;
- int num_passsync_mgrs;
-};
-
-static void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
-{
- struct ipapwd_krbcfg *c = *cfg;
-
- if (!c) return;
-
- krb5_free_default_realm(c->krbctx, c->realm);
- krb5_free_context(c->krbctx);
- free(c->kmkey->contents);
- free(c->kmkey);
- free(c->supp_encsalts);
- free(c->pref_encsalts);
- slapi_ch_array_free(c->passsync_mgrs);
- free(c);
- *cfg = NULL;
-};
-
-struct ipapwd_data {
- Slapi_Entry *target;
- char *dn;
- char *password;
- time_t timeNow;
- time_t lastPwChange;
- time_t expireTime;
- int changetype;
- int pwHistoryLen;
-};
-
-struct ipapwd_krbkeydata {
- int32_t type;
- struct berval value;
-};
-
-struct ipapwd_krbkey {
- struct ipapwd_krbkeydata *salt;
- struct ipapwd_krbkeydata *ekey;
- struct berval s2kparams;
-};
-
-struct ipapwd_keyset {
- uint16_t major_vno;
- uint16_t minor_vno;
- uint32_t kvno;
- uint32_t mkvno;
- struct ipapwd_krbkey *keys;
- int num_keys;
-};
-
-static void ipapwd_keyset_free(struct ipapwd_keyset **pkset)
-{
- struct ipapwd_keyset *kset = *pkset;
- int i;
-
- if (!kset) return;
-
- for (i = 0; i < kset->num_keys; i++) {
- if (kset->keys[i].salt) {
- free(kset->keys[i].salt->value.bv_val);
- free(kset->keys[i].salt);
- }
- if (kset->keys[i].ekey) {
- free(kset->keys[i].ekey->value.bv_val);
- free(kset->keys[i].ekey);
- }
- free(kset->keys[i].s2kparams.bv_val);
- }
- free(kset->keys);
- free(kset);
- *pkset = NULL;
-}
-
-static int filter_keys(struct ipapwd_krbcfg *krbcfg, struct ipapwd_keyset *kset)
-{
- int i, j;
-
- for (i = 0; i < kset->num_keys; i++) {
- for (j = 0; j < krbcfg->num_supp_encsalts; j++) {
- if (kset->keys[i].ekey->type ==
- krbcfg->supp_encsalts[j].enc_type) {
- break;
- }
- }
- if (j == krbcfg->num_supp_encsalts) { /* not valid */
-
- /* free key */
- if (kset->keys[i].ekey) {
- free(kset->keys[i].ekey->value.bv_val);
- free(kset->keys[i].ekey);
- }
- if (kset->keys[i].salt) {
- free(kset->keys[i].salt->value.bv_val);
- free(kset->keys[i].salt);
- }
- free(kset->keys[i].s2kparams.bv_val);
-
- /* move all remaining keys up by one */
- kset->num_keys -= 1;
-
- for (j = i; j < kset->num_keys; j++) {
- kset->keys[j] = kset->keys[j + 1];
- }
-
- /* new key has been moved to this position, make sure
- * we do not skip it, by neutralizing next increment */
- i--;
- }
- }
-
- return 0;
-}
-
-/* Novell key-format scheme:
-
- KrbKeySet ::= SEQUENCE {
- attribute-major-vno [0] UInt16,
- attribute-minor-vno [1] UInt16,
- kvno [2] UInt32,
- mkvno [3] UInt32 OPTIONAL,
- keys [4] SEQUENCE OF KrbKey,
- ...
- }
-
- KrbKey ::= SEQUENCE {
- salt [0] KrbSalt OPTIONAL,
- key [1] EncryptionKey,
- s2kparams [2] OCTET STRING OPTIONAL,
- ...
- }
-
- KrbSalt ::= SEQUENCE {
- type [0] Int32,
- salt [1] OCTET STRING OPTIONAL
- }
-
- EncryptionKey ::= SEQUENCE {
- keytype [0] Int32,
- keyvalue [1] OCTET STRING
- }
-
- */
-
-static struct berval *encode_keys(struct ipapwd_keyset *kset)
-{
- BerElement *be = NULL;
- struct berval *bval = NULL;
- int ret, i;
-
- be = ber_alloc_t(LBER_USE_DER);
-
- if (!be) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- return NULL;
- }
-
- ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), kset->major_vno,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), kset->minor_vno,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2), kset->kvno,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 3), kset->mkvno,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4));
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 vno info failed\n");
- goto done;
- }
-
- for (i = 0; i < kset->num_keys; i++) {
-
- ret = ber_printf(be, "{");
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 EncryptionKey failed\n");
- goto done;
- }
-
- if (kset->keys[i].salt) {
- ret = ber_printf(be, "t[{t[i]",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
- kset->keys[i].salt->type);
- if ((ret != -1) && kset->keys[i].salt->value.bv_len) {
- ret = ber_printf(be, "t[o]",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
- kset->keys[i].salt->value.bv_val,
- kset->keys[i].salt->value.bv_len);
- }
- if (ret != -1) {
- ret = ber_printf(be, "}]");
- }
- if (ret == -1) {
- goto done;
- }
- }
-
- ret = ber_printf(be, "t[{t[i]t[o]}]",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
- kset->keys[i].ekey->type,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
- kset->keys[i].ekey->value.bv_val,
- kset->keys[i].ekey->value.bv_len);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 EncryptionKey failed\n");
- goto done;
- }
-
- /* FIXME: s2kparams not supported yet */
-
- ret = ber_printf(be, "}");
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 EncryptionKey failed\n");
- goto done;
- }
- }
-
- ret = ber_printf(be, "}]}");
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 end of sequences failed\n");
- goto done;
- }
-
- ret = ber_flatten(be, &bval);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "flattening asn1 failed\n");
- goto done;
- }
-done:
- ber_free(be, 1);
-
- return bval;
-}
-
-static int ipapwd_get_cur_kvno(Slapi_Entry *target)
-{
- Slapi_Attr *krbPrincipalKey = NULL;
- Slapi_ValueSet *svs;
- Slapi_Value *sv;
- BerElement *be = NULL;
- const struct berval *cbval;
- ber_tag_t tag, tmp;
- ber_int_t tkvno;
- int hint;
- int kvno;
- int ret;
-
- /* retrieve current kvno and and keys */
- ret = slapi_entry_attr_find(target, "krbPrincipalKey", &krbPrincipalKey);
- if (ret != 0) {
- return 0;
- }
-
- kvno = 0;
-
- slapi_attr_get_valueset(krbPrincipalKey, &svs);
- hint = slapi_valueset_first_value(svs, &sv);
- while (hint != -1) {
- cbval = slapi_value_get_berval(sv);
- if (!cbval) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Error retrieving berval from Slapi_Value\n");
- goto next;
- }
- be = ber_init(cbval);
- if (!be) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ber_init() failed!\n");
- goto next;
- }
-
- tag = ber_scanf(be, "{xxt[i]", &tmp, &tkvno);
- if (tag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Bad OLD key encoding ?!\n");
- ber_free(be, 1);
- goto next;
- }
-
- if (tkvno > kvno) {
- kvno = tkvno;
- }
-
- ber_free(be, 1);
-next:
- hint = slapi_valueset_next_value(svs, hint, &sv);
- }
-
- return kvno;
-}
-
-static inline void encode_int16(unsigned int val, unsigned char *p)
-{
- p[1] = (val >> 8) & 0xff;
- p[0] = (val ) & 0xff;
-}
-
-static Slapi_Value **encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
- struct ipapwd_data *data)
-{
- krb5_context krbctx;
- char *krbPrincipalName = NULL;
- uint32_t krbMaxTicketLife;
- int kvno, i;
- int krbTicketFlags;
- struct berval *bval = NULL;
- Slapi_Value **svals = NULL;
- krb5_principal princ;
- krb5_error_code krberr;
- krb5_data pwd;
- struct ipapwd_keyset *kset = NULL;
-
- krbctx = krbcfg->krbctx;
-
- svals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
- if (!svals) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "memory allocation failed\n");
- return NULL;
- }
-
- kvno = ipapwd_get_cur_kvno(data->target);
-
- krbPrincipalName = slapi_entry_attr_get_charptr(data->target, "krbPrincipalName");
- if (!krbPrincipalName) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "no krbPrincipalName present in this entry\n");
- return NULL;
- }
-
- krberr = krb5_parse_name(krbctx, krbPrincipalName, &princ);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_parse_name failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
-
- krbMaxTicketLife = slapi_entry_attr_get_uint(data->target, "krbMaxTicketLife");
- if (krbMaxTicketLife == 0) {
- /* FIXME: retrieve the default from config (max_life from kdc.conf) */
- krbMaxTicketLife = 86400; /* just set the default 24h for now */
- }
-
- krbTicketFlags = slapi_entry_attr_get_int(data->target, "krbTicketFlags");
-
- pwd.data = (char *)data->password;
- pwd.length = strlen(data->password);
-
- kset = malloc(sizeof(struct ipapwd_keyset));
- if (!kset) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto enc_error;
- }
-
- /* this encoding assumes all keys have the same kvno */
- /* major-vno = 1 and minor-vno = 1 */
- kset->major_vno = 1;
- kset->minor_vno = 1;
- /* increment kvno (will be 1 if this is a new entry) */
- kset->kvno = kvno + 1;
- /* we also assum mkvno is 0 */
- kset->mkvno = 0;
-
- kset->num_keys = krbcfg->num_pref_encsalts;
- kset->keys = calloc(kset->num_keys, sizeof(struct ipapwd_krbkey));
- if (!kset->keys) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto enc_error;
- }
-
- for (i = 0; i < kset->num_keys; i++) {
- krb5_keyblock key;
- krb5_data salt;
- krb5_octet *ptr;
- krb5_data plain;
- krb5_enc_data cipher;
- size_t len;
- const char *p;
-
- salt.data = NULL;
-
- switch (krbcfg->pref_encsalts[i].salt_type) {
-
- case KRB5_KDB_SALTTYPE_ONLYREALM:
-
- p = strchr(krbPrincipalName, '@');
- if (!p) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid principal name, no realm found!\n");
- goto enc_error;
- }
- p++;
- salt.data = strdup(p);
- if (!salt.data) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
- salt.length = strlen(salt.data); /* final \0 omitted on purpose */
- break;
-
- case KRB5_KDB_SALTTYPE_NOREALM:
-
- krberr = krb5_principal2salt_norealm(krbctx, princ, &salt);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_principal2salt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
- break;
-
- case KRB5_KDB_SALTTYPE_NORMAL:
-
- /* If pre auth is required we can set a random salt, otherwise
- * we have to use a more conservative approach and set the salt
- * to be REALMprincipal (the concatenation of REALM and principal
- * name without any separator) */
-#if 0
- if (krbTicketFlags & KTF_REQUIRES_PRE_AUTH) {
- salt.length = KRB5P_SALT_SIZE;
- salt.data = malloc(KRB5P_SALT_SIZE);
- if (!salt.data) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
- krberr = krb5_c_random_make_octets(krbctx, &salt);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_random_make_octets failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
- } else {
-#endif
- krberr = krb5_principal2salt(krbctx, princ, &salt);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_principal2salt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
-#if 0
- }
-#endif
- break;
-
- case KRB5_KDB_SALTTYPE_V4:
- salt.length = 0;
- break;
-
- case KRB5_KDB_SALTTYPE_AFS3:
-
- p = strchr(krbPrincipalName, '@');
- if (!p) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid principal name, no realm found!\n");
- goto enc_error;
- }
- p++;
- salt.data = strdup(p);
- if (!salt.data) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
- salt.length = SALT_TYPE_AFS_LENGTH; /* special value */
- break;
-
- default:
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid salt type [%d]\n", krbcfg->pref_encsalts[i].salt_type);
- goto enc_error;
- }
-
- /* need to build the key now to manage the AFS salt.length special case */
- krberr = krb5_c_string_to_key(krbctx, krbcfg->pref_encsalts[i].enc_type, &pwd, &salt, &key);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_string_to_key failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
- if (salt.length == SALT_TYPE_AFS_LENGTH) {
- salt.length = strlen(salt.data);
- }
-
- krberr = krb5_c_encrypt_length(krbctx, krbcfg->kmkey->enctype, key.length, &len);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_string_to_key failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
-
- if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
-
- encode_int16(key.length, ptr);
-
- plain.length = key.length;
- plain.data = (char *)key.contents;
-
- cipher.ciphertext.length = len;
- cipher.ciphertext.data = (char *)ptr+2;
-
- krberr = krb5_c_encrypt(krbctx, krbcfg->kmkey, 0, 0, &plain, &cipher);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_encrypt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- free(ptr);
- goto enc_error;
- }
-
- /* KrbSalt */
- kset->keys[i].salt = malloc(sizeof(struct ipapwd_krbkeydata));
- if (!kset->keys[i].salt) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- free(ptr);
- goto enc_error;
- }
-
- kset->keys[i].salt->type = krbcfg->pref_encsalts[i].salt_type;
-
- if (salt.length) {
- kset->keys[i].salt->value.bv_len = salt.length;
- kset->keys[i].salt->value.bv_val = salt.data;
- }
-
- /* EncryptionKey */
- kset->keys[i].ekey = malloc(sizeof(struct ipapwd_krbkeydata));
- if (!kset->keys[i].ekey) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- free(ptr);
- goto enc_error;
- }
- kset->keys[i].ekey->type = key.enctype;
- kset->keys[i].ekey->value.bv_len = len+2;
- kset->keys[i].ekey->value.bv_val = malloc(len+2);
- if (!kset->keys[i].ekey->value.bv_val) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- free(ptr);
- goto enc_error;
- }
- memcpy(kset->keys[i].ekey->value.bv_val, ptr, len+2);
-
- /* make sure we free the memory used now that we are done with it */
- krb5int_c_free_keyblock_contents(krbctx, &key);
- free(ptr);
- }
-
- bval = encode_keys(kset);
- if (!bval) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 KrbSalt failed\n");
- goto enc_error;
- }
-
- svals[0] = slapi_value_new_berval(bval);
- if (!svals[0]) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Converting berval to Slapi_Value\n");
- goto enc_error;
- }
-
- ipapwd_keyset_free(&kset);
- krb5_free_principal(krbctx, princ);
- slapi_ch_free_string(&krbPrincipalName);
- ber_bvfree(bval);
- return svals;
-
-enc_error:
- if (kset) ipapwd_keyset_free(&kset);
- krb5_free_principal(krbctx, princ);
- slapi_ch_free_string(&krbPrincipalName);
- if (bval) ber_bvfree(bval);
- free(svals);
- return NULL;
-}
-
-static void ipapwd_free_slapi_value_array(Slapi_Value ***svals)
-{
- Slapi_Value **sv = *svals;
- int i;
-
- if (sv) {
- for (i = 0; sv[i]; i++) {
- slapi_value_free(&sv[i]);
- }
- }
-
- slapi_ch_free((void **)sv);
-}
-
-
-struct ntlm_keys {
- uint8_t lm[16];
- uint8_t nt[16];
-};
-
-#define KTF_LM_HASH 0x01
-#define KTF_NT_HASH 0x02
-#define KTF_DOS_CHARSET "CP850" /* same default as samba */
-#define KTF_UTF8 "UTF-8"
-#define KTF_UCS2 "UCS-2LE"
-
-static const uint8_t parity_table[128] = {
- 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31,
- 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62,
- 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94,
- 97, 98,100,103,104,107,109,110,112,115,117,118,121,122,124,127,
- 128,131,133,134,137,138,140,143,145,146,148,151,152,155,157,158,
- 161,162,164,167,168,171,173,174,176,179,181,182,185,186,188,191,
- 193,194,196,199,200,203,205,206,208,211,213,214,217,218,220,223,
- 224,227,229,230,233,234,236,239,241,242,244,247,248,251,253,254};
-
-static void lm_shuffle(uint8_t *out, uint8_t *in)
-{
- out[0] = parity_table[in[0]>>1];
- out[1] = parity_table[((in[0]<<6)|(in[1]>>2)) & 0x7F];
- out[2] = parity_table[((in[1]<<5)|(in[2]>>3)) & 0x7F];
- out[3] = parity_table[((in[2]<<4)|(in[3]>>4)) & 0x7F];
- out[4] = parity_table[((in[3]<<3)|(in[4]>>5)) & 0x7F];
- out[5] = parity_table[((in[4]<<2)|(in[5]>>6)) & 0x7F];
- out[6] = parity_table[((in[5]<<1)|(in[6]>>7)) & 0x7F];
- out[7] = parity_table[in[6] & 0x7F];
-}
-
-/* create the lm and nt hashes
- newPassword: the clear text utf8 password
- flags: KTF_LM_HASH | KTF_NT_HASH
-*/
-static int encode_ntlm_keys(char *newPasswd, unsigned int flags, struct ntlm_keys *keys)
-{
- int ret = 0;
-
- /* do lanman first */
- if (flags & KTF_LM_HASH) {
- iconv_t cd;
- size_t cs, il, ol;
- char *inc, *outc;
- char *upperPasswd;
- char *asciiPasswd;
- DES_key_schedule schedule;
- DES_cblock deskey;
- DES_cblock magic = "KGS!@#$%";
-
- /* TODO: must store the dos charset somewhere in the directory */
- cd = iconv_open(KTF_DOS_CHARSET, KTF_UTF8);
- if (cd == (iconv_t)(-1)) {
- ret = -1;
- goto done;
- }
-
- /* the lanman password is upper case */
- upperPasswd = (char *)slapi_utf8StrToUpper((unsigned char *)newPasswd);
- if (!upperPasswd) {
- ret = -1;
- goto done;
- }
- il = strlen(upperPasswd);
-
- /* an ascii string can only be smaller than or equal to an utf8 one */
- ol = il;
- if (ol < 14) ol = 14;
- asciiPasswd = calloc(ol+1, 1);
- if (!asciiPasswd) {
- slapi_ch_free_string(&upperPasswd);
- ret = -1;
- goto done;
- }
-
- inc = upperPasswd;
- outc = asciiPasswd;
- cs = iconv(cd, &inc, &il, &outc, &ol);
- if (cs == -1) {
- ret = -1;
- slapi_ch_free_string(&upperPasswd);
- free(asciiPasswd);
- iconv_close(cd);
- goto done;
- }
-
- /* done with these */
- slapi_ch_free_string(&upperPasswd);
- iconv_close(cd);
-
- /* we are interested only in the first 14 ASCII chars for lanman */
- if (strlen(asciiPasswd) > 14) {
- asciiPasswd[14] = '\0';
- }
-
- /* first half */
- lm_shuffle(deskey, (uint8_t *)asciiPasswd);
-
- DES_set_key_unchecked(&deskey, &schedule);
- DES_ecb_encrypt(&magic, (DES_cblock *)keys->lm, &schedule, DES_ENCRYPT);
-
- /* second half */
- lm_shuffle(deskey, (uint8_t *)&asciiPasswd[7]);
-
- DES_set_key_unchecked(&deskey, &schedule);
- DES_ecb_encrypt(&magic, (DES_cblock *)&(keys->lm[8]), &schedule, DES_ENCRYPT);
-
- /* done with it */
- free(asciiPasswd);
-
- } else {
- memset(keys->lm, 0, 16);
- }
-
- if (flags & KTF_NT_HASH) {
- iconv_t cd;
- size_t cs, il, ol, sl;
- char *inc, *outc;
- char *ucs2Passwd;
- MD4_CTX md4ctx;
-
- /* TODO: must store the dos charset somewhere in the directory */
- cd = iconv_open(KTF_UCS2, KTF_UTF8);
- if (cd == (iconv_t)(-1)) {
- ret = -1;
- goto done;
- }
-
- il = strlen(newPasswd);
-
- /* an ucs2 string can be at most double than an utf8 one */
- sl = ol = (il+1)*2;
- ucs2Passwd = calloc(ol, 1);
- if (!ucs2Passwd) {
- ret = -1;
- goto done;
- }
-
- inc = newPasswd;
- outc = ucs2Passwd;
- cs = iconv(cd, &inc, &il, &outc, &ol);
- if (cs == -1) {
- ret = -1;
- free(ucs2Passwd);
- iconv_close(cd);
- goto done;
- }
-
- /* done with it */
- iconv_close(cd);
-
- /* get the final ucs2 string length */
- sl -= ol;
- /* we are interested only in the first 14 wchars for the nt password */
- if (sl > 28) {
- sl = 28;
- }
-
- ret = MD4_Init(&md4ctx);
- if (ret == 0) {
- ret = -1;
- free(ucs2Passwd);
- goto done;
- }
- ret = MD4_Update(&md4ctx, ucs2Passwd, sl);
- if (ret == 0) {
- ret = -1;
- free(ucs2Passwd);
- goto done;
- }
- ret = MD4_Final(keys->nt, &md4ctx);
- if (ret == 0) {
- ret = -1;
- free(ucs2Passwd);
- goto done;
- }
-
- } else {
- memset(keys->nt, 0, 16);
- }
-
- ret = 0;
-
-done:
- return ret;
-}
-
-/* searches the directory and finds the policy closest to the DN */
-/* return 0 on success, -1 on error or if no policy is found */
-static int ipapwd_getPolicy(const char *dn, Slapi_Entry *target, Slapi_Entry **e)
-{
- const char *krbPwdPolicyReference;
- const char *pdn;
- const Slapi_DN *psdn;
- Slapi_Backend *be;
- Slapi_PBlock *pb = NULL;
- char *attrs[] = { "krbMaxPwdLife", "krbMinPwdLife",
- "krbPwdMinDiffChars", "krbPwdMinLength",
- "krbPwdHistoryLength", NULL};
- Slapi_Entry **es = NULL;
- Slapi_Entry *pe = NULL;
- char **edn;
- int ret, res, dist, rdnc, scope, i;
- Slapi_DN *sdn = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: Searching policy for [%s]\n", dn);
-
- sdn = slapi_sdn_new_dn_byref(dn);
- if (sdn == NULL) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: Out of memory on [%s]\n", dn);
- ret = -1;
- goto done;
- }
-
- krbPwdPolicyReference = slapi_entry_attr_get_charptr(target, "krbPwdPolicyReference");
- if (krbPwdPolicyReference) {
- pdn = krbPwdPolicyReference;
- scope = LDAP_SCOPE_BASE;
- } else {
- /* Find ancestor base DN */
- be = slapi_be_select(sdn);
- psdn = slapi_be_getsuffix(be, 0);
- if (psdn == NULL) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: Invalid DN [%s]\n", dn);
- ret = -1;
- goto done;
- }
- pdn = slapi_sdn_get_dn(psdn);
- scope = LDAP_SCOPE_SUBTREE;
- }
-
- *e = NULL;
-
- pb = slapi_pblock_new();
- slapi_search_internal_set_pb (pb,
- pdn, scope,
- "(objectClass=krbPwdPolicy)",
- attrs, 0,
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id,
- 0); /* Flags */
-
- /* do search the tree */
- ret = slapi_search_internal_pb(pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (ret == -1 || res != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: Couldn't find policy, err (%d)\n",
- res?res:ret);
- ret = -1;
- goto done;
- }
-
- /* get entries */
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es);
- if (!es) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: No entries ?!");
- ret = -1;
- goto done;
- }
-
- /* count entries */
- for (i = 0; es[i]; i++) /* count */ ;
-
- /* if there is only one, return that */
- if (i == 1) {
- *e = slapi_entry_dup(es[0]);
-
- ret = 0;
- goto done;
- }
-
- /* count number of RDNs in DN */
- edn = ldap_explode_dn(dn, 0);
- if (!edn) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getPolicy: ldap_explode_dn(dn) failed ?!");
- ret = -1;
- goto done;
- }
- for (rdnc = 0; edn[rdnc]; rdnc++) /* count */ ;
- ldap_value_free(edn);
-
- pe = NULL;
- dist = -1;
-
- /* find closest entry */
- for (i = 0; es[i]; i++) {
- const Slapi_DN *esdn;
-
- esdn = slapi_entry_get_sdn_const(es[i]);
- if (esdn == NULL) continue;
- if (0 == slapi_sdn_compare(esdn, sdn)) {
- pe = es[i];
- dist = 0;
- break;
- }
- if (slapi_sdn_issuffix(sdn, esdn)) {
- const char *dn1;
- char **e1;
- int c1;
-
- dn1 = slapi_sdn_get_dn(esdn);
- if (!dn1) continue;
- e1 = ldap_explode_dn(dn1, 0);
- if (!e1) continue;
- for (c1 = 0; e1[c1]; c1++) /* count */ ;
- ldap_value_free(e1);
- if ((dist == -1) ||
- ((rdnc - c1) < dist)) {
- dist = rdnc - c1;
- pe = es[i];
- }
- }
- if (dist == 0) break; /* found closest */
- }
-
- if (pe == NULL) {
- ret = -1;
- goto done;
- }
-
- *e = slapi_entry_dup(pe);
- ret = 0;
-done:
- if (pb) {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- }
- if (sdn) slapi_sdn_free(&sdn);
- return ret;
-}
-
-#define GENERALIZED_TIME_LENGTH 15
-
-static int ipapwd_sv_pw_cmp(const void *pv1, const void *pv2)
-{
- const char *pw1 = slapi_value_get_string(*((Slapi_Value **)pv1));
- const char *pw2 = slapi_value_get_string(*((Slapi_Value **)pv2));
-
- return strncmp(pw1, pw2, GENERALIZED_TIME_LENGTH);
-}
-
-static Slapi_Value **ipapwd_setPasswordHistory(Slapi_Mods *smods, struct ipapwd_data *data)
-{
- Slapi_Value **pH = NULL;
- Slapi_Attr *passwordHistory = NULL;
- char timestr[GENERALIZED_TIME_LENGTH+1];
- char *histr, *old_pw;
- struct tm utctime;
- int ret, pc;
-
- old_pw = slapi_entry_attr_get_charptr(data->target, "userPassword");
- if (!old_pw) {
- /* no old password to store, just return */
- return NULL;
- }
-
- if (!gmtime_r(&(data->timeNow), &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "failed to retrieve current date (buggy gmtime_r ?)\n");
- return NULL;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime);
-
- histr = slapi_ch_smprintf("%s%s", timestr, old_pw);
- if (!histr) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- return NULL;
- }
-
- /* retrieve current history */
- ret = slapi_entry_attr_find(data->target, "passwordHistory", &passwordHistory);
- if (ret == 0) {
- int ret, hint, count, i;
- const char *pwstr;
- Slapi_Value *pw;
-
- hint = 0;
- count = 0;
- ret = slapi_attr_get_numvalues(passwordHistory, &count);
- /* if we have one */
- if (count > 0 && data->pwHistoryLen > 0) {
- pH = calloc(count + 2, sizeof(Slapi_Value *));
- if (!pH) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- free(histr);
- return NULL;
- }
-
- i = 0;
- hint = slapi_attr_first_value(passwordHistory, &pw);
- while (hint != -1) {
- pwstr = slapi_value_get_string(pw);
- /* if shorter than GENERALIZED_TIME_LENGTH, it
- * is garbage, we never set timeless entries */
- if (pwstr &&
- (strlen(pwstr) > GENERALIZED_TIME_LENGTH)) {
- pH[i] = pw;
- i++;
- }
- hint = slapi_attr_next_value(passwordHistory, hint, &pw);
- }
-
- qsort(pH, i, sizeof(Slapi_Value *), ipapwd_sv_pw_cmp);
-
- if (i >= data->pwHistoryLen) {
- i = data->pwHistoryLen;
- pH[i] = NULL;
- i--;
- }
-
- pc = i;
-
- /* copy only interesting entries */
- for (i = 0; i < pc; i++) {
- pH[i] = slapi_value_dup(pH[i]);
- if (pH[i] == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- while (i) {
- i--;
- slapi_value_free(&pH[i]);
- }
- free(pH);
- free(histr);
- return NULL;
- }
- }
- }
- }
-
- if (pH == NULL) {
- pH = calloc(2, sizeof(Slapi_Value *));
- if (!pH) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- free(histr);
- return NULL;
- }
- pc = 0;
- }
-
- /* add new history value */
- pH[pc] = slapi_value_new_string(histr);
-
- free(histr);
-
- return pH;
-}
-
-static Slapi_Value *ipapwd_strip_pw_date(Slapi_Value *pw)
-{
- const char *pwstr;
-
- pwstr = slapi_value_get_string(pw);
- return slapi_value_new_string(&pwstr[GENERALIZED_TIME_LENGTH]);
-}
-
-#define IPAPWD_POLICY_MASK 0x0FF
-#define IPAPWD_POLICY_ERROR 0x100
-#define IPAPWD_POLICY_OK 0
-
-/* 90 days default pwd max lifetime */
-#define IPAPWD_DEFAULT_PWDLIFE (90 * 24 *3600)
-#define IPAPWD_DEFAULT_MINLEN 0
-
-/* check password strenght and history */
-static int ipapwd_CheckPolicy(struct ipapwd_data *data)
-{
- char *krbPrincipalExpiration = NULL;
- char *krbLastPwdChange = NULL;
- char *krbPasswordExpiration = NULL;
- int krbMaxPwdLife = IPAPWD_DEFAULT_PWDLIFE;
- int krbPwdMinLength = IPAPWD_DEFAULT_MINLEN;
- int krbPwdMinDiffChars = 0;
- int krbMinPwdLife = 0;
- int pwdCharLen = 0;
- Slapi_Entry *policy = NULL;
- Slapi_Attr *passwordHistory = NULL;
- struct tm tm;
- int tmp, ret;
- char *old_pw;
-
- /* check account is not expired. Ignore unixtime = 0 (Jan 1 1970) */
- krbPrincipalExpiration = slapi_entry_attr_get_charptr(data->target, "krbPrincipalExpiration");
- if (krbPrincipalExpiration &&
- (strcasecmp("19700101000000Z", krbPrincipalExpiration) != 0)) {
- /* if expiration date is set check it */
- memset(&tm, 0, sizeof(struct tm));
- ret = sscanf(krbPrincipalExpiration,
- "%04u%02u%02u%02u%02u%02u",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
-
- if (ret == 6) {
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- if (data->timeNow > timegm(&tm)) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "Account Expired");
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_PWDMODNOTALLOWED;
- }
- }
- /* FIXME: else error out ? */
- }
- slapi_ch_free_string(&krbPrincipalExpiration);
-
- /* find the entry with the password policy */
- ret = ipapwd_getPolicy(data->dn, data->target, &policy);
- if (ret) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "No password policy");
- goto no_policy;
- }
-
- /* Retrieve Max History Len */
- data->pwHistoryLen = slapi_entry_attr_get_int(policy, "krbPwdHistoryLength");
-
- if (data->changetype != IPA_CHANGETYPE_NORMAL) {
- /* We must skip policy checks (Admin change) but
- * force a password change on the next login.
- * But not if Directory Manager */
- if (data->changetype == IPA_CHANGETYPE_ADMIN) {
- data->expireTime = data->timeNow;
- }
-
- /* skip policy checks */
- slapi_entry_free(policy);
- goto no_policy;
- }
-
- /* first of all check current password, if any */
- old_pw = slapi_entry_attr_get_charptr(data->target, "userPassword");
- if (old_pw) {
- Slapi_Value *cpw[2] = {NULL, NULL};
- Slapi_Value *pw;
-
- cpw[0] = slapi_value_new_string(old_pw);
- pw = slapi_value_new_string(data->password);
- if (!pw) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- slapi_entry_free(policy);
- slapi_ch_free_string(&old_pw);
- slapi_value_free(&cpw[0]);
- slapi_value_free(&pw);
- return LDAP_OPERATIONS_ERROR;
- }
-
- ret = slapi_pw_find_sv(cpw, pw);
- slapi_ch_free_string(&old_pw);
- slapi_value_free(&cpw[0]);
- slapi_value_free(&pw);
-
- if (ret == 0) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPassword: Password in history\n");
- slapi_entry_free(policy);
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_PWDINHISTORY;
- }
- }
-
- krbPasswordExpiration = slapi_entry_attr_get_charptr(data->target, "krbPasswordExpiration");
- krbLastPwdChange = slapi_entry_attr_get_charptr(data->target, "krbLastPwdChange");
- /* if no previous change, it means this is probably a new account
- * or imported, log and just ignore */
- if (krbLastPwdChange) {
-
- memset(&tm, 0, sizeof(struct tm));
- ret = sscanf(krbLastPwdChange,
- "%04u%02u%02u%02u%02u%02u",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
-
- if (ret == 6) {
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
- data->lastPwChange = timegm(&tm);
- }
- /* FIXME: *else* report an error ? */
- } else {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Warning: Last Password Change Time is not available");
- }
-
- /* Check min age */
- krbMinPwdLife = slapi_entry_attr_get_int(policy, "krbMinPwdLife");
- /* if no default then treat it as no limit */
- if (krbMinPwdLife != 0) {
-
- /* check for reset cases */
- if (krbLastPwdChange == NULL ||
- ((krbPasswordExpiration != NULL) &&
- strcmp(krbPasswordExpiration, krbLastPwdChange) == 0)) {
- /* Expiration and last change time are the same or
- * missing this happens only when a password is reset
- * by an admin or the account is new or no expiration
- * policy is set, PASS */
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPolicy: Ignore krbMinPwdLife Expiration, not enough info\n");
-
- } else if (data->timeNow < data->lastPwChange + krbMinPwdLife) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPolicy: Too soon to change password\n");
- slapi_entry_free(policy);
- slapi_ch_free_string(&krbPasswordExpiration);
- slapi_ch_free_string(&krbLastPwdChange);
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_PWDTOOYOUNG;
- }
- }
-
- /* free strings or we leak them */
- slapi_ch_free_string(&krbPasswordExpiration);
- slapi_ch_free_string(&krbLastPwdChange);
-
- /* Retrieve min length */
- tmp = slapi_entry_attr_get_int(policy, "krbPwdMinLength");
- if (tmp != 0) {
- krbPwdMinLength = tmp;
- }
-
- /* check complexity */
- /* FIXME: this code is partially based on Directory Server code,
- * the plan is to merge this code later making it available
- * trough a pulic DS API for slapi plugins */
- krbPwdMinDiffChars = slapi_entry_attr_get_int(policy, "krbPwdMinDiffChars");
- if (krbPwdMinDiffChars != 0) {
- int num_digits = 0;
- int num_alphas = 0;
- int num_uppers = 0;
- int num_lowers = 0;
- int num_specials = 0;
- int num_8bit = 0;
- int num_repeated = 0;
- int max_repeated = 0;
- int num_categories = 0;
- char *p, *pwd;
-
- pwd = strdup(data->password);
-
- /* check character types */
- p = pwd;
- while ( p && *p )
- {
- if ( ldap_utf8isdigit( p ) ) {
- num_digits++;
- } else if ( ldap_utf8isalpha( p ) ) {
- num_alphas++;
- if ( slapi_utf8isLower( (unsigned char *)p ) ) {
- num_lowers++;
- } else {
- num_uppers++;
- }
- } else {
- /* check if this is an 8-bit char */
- if ( *p & 128 ) {
- num_8bit++;
- } else {
- num_specials++;
- }
- }
-
- /* check for repeating characters. If this is the
- first char of the password, no need to check */
- if ( pwd != p ) {
- int len = ldap_utf8len( p );
- char *prev_p = ldap_utf8prev( p );
-
- if ( len == ldap_utf8len( prev_p ) )
- {
- if ( memcmp( p, prev_p, len ) == 0 )
- {
- num_repeated++;
- if ( max_repeated < num_repeated ) {
- max_repeated = num_repeated;
- }
- } else {
- num_repeated = 0;
- }
- } else {
- num_repeated = 0;
- }
- }
-
- p = ldap_utf8next( p );
- }
-
- free(pwd);
- p = pwd = NULL;
-
- /* tally up the number of character categories */
- if ( num_digits > 0 )
- ++num_categories;
- if ( num_uppers > 0 )
- ++num_categories;
- if ( num_lowers > 0 )
- ++num_categories;
- if ( num_specials > 0 )
- ++num_categories;
- if ( num_8bit > 0 )
- ++num_categories;
-
- /* FIXME: the kerberos plicy schema does not define separated threshold values,
- * so just treat anything as a category, we will fix this when we merge
- * with DS policies */
-
- if (max_repeated > 1)
- --num_categories;
-
- if (num_categories < krbPwdMinDiffChars) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPassword: Password not complex enough\n");
- slapi_entry_free(policy);
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_INVALIDPWDSYNTAX;
- }
- }
-
- /* Check password history */
- ret = slapi_entry_attr_find(data->target, "passwordHistory", &passwordHistory);
- if (ret == 0) {
- int ret, hint, count, i, j;
- const char *pwstr;
- Slapi_Value **pH;
- Slapi_Value *pw;
-
- hint = 0;
- count = 0;
- ret = slapi_attr_get_numvalues(passwordHistory, &count);
- /* check history only if we have one */
- if (count > 0 && data->pwHistoryLen > 0) {
- pH = calloc(count + 2, sizeof(Slapi_Value *));
- if (!pH) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- slapi_entry_free(policy);
- return LDAP_OPERATIONS_ERROR;
- }
-
- i = 0;
- hint = slapi_attr_first_value(passwordHistory, &pw);
- while (hint != -1) {
- pwstr = slapi_value_get_string(pw);
- /* if shorter than GENERALIZED_TIME_LENGTH, it
- * is garbage, we never set timeless entries */
- if (pwstr &&
- (strlen(pwstr) > GENERALIZED_TIME_LENGTH)) {
- pH[i] = pw;
- i++;
- }
- hint = slapi_attr_next_value(passwordHistory, hint, &pw);
- }
-
- qsort(pH, i, sizeof(Slapi_Value *), ipapwd_sv_pw_cmp);
-
- if (i > data->pwHistoryLen) {
- i = data->pwHistoryLen;
- pH[i] = NULL;
- }
-
- for (j = 0; pH[j]; j++) {
- pH[j] = ipapwd_strip_pw_date(pH[j]);
- }
-
- pw = slapi_value_new_string(data->password);
- if (!pw) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "ipapwd_checkPassword: Out of Memory\n");
- slapi_entry_free(policy);
- free(pH);
- return LDAP_OPERATIONS_ERROR;
- }
-
- ret = slapi_pw_find_sv(pH, pw);
-
- for (j = 0; pH[j]; j++) {
- slapi_value_free(&pH[j]);
- }
- slapi_value_free(&pw);
- free(pH);
-
- if (ret == 0) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPassword: Password in history\n");
- slapi_entry_free(policy);
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_PWDINHISTORY;
- }
- }
- }
-
- /* Calculate max age */
- tmp = slapi_entry_attr_get_int(policy, "krbMaxPwdLife");
- if (tmp != 0) {
- krbMaxPwdLife = tmp;
- }
-
- slapi_entry_free(policy);
-
-no_policy:
-
- /* check min lenght */
- pwdCharLen = ldap_utf8characters(data->password);
-
- if (pwdCharLen < krbPwdMinLength) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_checkPassword: Password too short\n");
- return IPAPWD_POLICY_ERROR | LDAP_PWPOLICY_PWDTOOSHORT;
- }
-
- if (data->expireTime == 0) {
- data->expireTime = data->timeNow + krbMaxPwdLife;
- }
-
- return IPAPWD_POLICY_OK;
-}
-
-
-/* Searches the dn in directory,
- * If found : fills in slapi_entry structure and returns 0
- * If NOT found : returns the search result as LDAP_NO_SUCH_OBJECT
- */
-static int ipapwd_getEntry(const char *dn, Slapi_Entry **e2, char **attrlist)
-{
- Slapi_DN *sdn;
- int search_result = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_getEntry\n");
-
- sdn = slapi_sdn_new_dn_byref(dn);
- if ((search_result = slapi_search_internal_get_entry( sdn, attrlist, e2,
- ipapwd_plugin_id)) != LDAP_SUCCESS ){
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "ipapwd_getEntry: No such entry-(%s), err (%d)\n",
- dn, search_result);
- }
-
- slapi_sdn_free( &sdn );
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "<= ipapwd_getEntry: %d\n", search_result);
- return search_result;
-}
-
-
-/* Construct Mods pblock and perform the modify operation
- * Sets result of operation in SLAPI_PLUGIN_INTOP_RESULT
- */
-static int ipapwd_apply_mods(const char *dn, Slapi_Mods *mods)
-{
- Slapi_PBlock *pb;
- int ret;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_apply_mods\n");
-
- if (!mods || (slapi_mods_get_num_mods(mods) == 0)) {
- return -1;
- }
-
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb (pb, dn,
- slapi_mods_get_ldapmods_byref(mods),
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id, /* PluginID */
- 0); /* Flags */
-
- ret = slapi_modify_internal_pb (pb);
- if (ret) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "WARNING: modify error %d on entry '%s'\n",
- ret, dn);
- } else {
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
-
- if (ret != LDAP_SUCCESS){
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "WARNING: modify error %d on entry '%s'\n",
- ret, dn);
- } else {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "<= ipapwd_apply_mods: Successful\n");
- }
- }
-
- slapi_pblock_destroy(pb);
-
- return ret;
-}
-
-/* ascii hex output of bytes in "in"
- * out len is 32 (preallocated)
- * in len is 16 */
-static const char hexchars[] = "0123456789ABCDEF";
-static void hexbuf(char *out, const uint8_t *in)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- out[i*2] = hexchars[in[i] >> 4];
- out[i*2+1] = hexchars[in[i] & 0x0f];
- }
-}
-
-/* Modify the Password attributes of the entry */
-static int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
- struct ipapwd_data *data)
-{
- int ret = 0, i = 0;
- Slapi_Mods *smods;
- Slapi_Value **svals = NULL;
- Slapi_Value **pwvals = NULL;
- struct tm utctime;
- char timestr[GENERALIZED_TIME_LENGTH+1];
- krb5_context krbctx;
- krb5_error_code krberr;
- char lm[33], nt[33];
- struct ntlm_keys ntlm;
- int ntlm_flags = 0;
- Slapi_Value *sambaSamAccount;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_SetPassword\n");
-
- smods = slapi_mods_new();
-
- /* generate kerberos keys to be put into krbPrincipalKey */
- svals = encrypt_encode_key(krbcfg, data);
- if (!svals) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "key encryption/encoding failed\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
-
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbPrincipalKey", svals);
-
- /* change Last Password Change field with the current date */
- if (!gmtime_r(&(data->timeNow), &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "failed to retrieve current date (buggy gmtime_r ?)\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbLastPwdChange", timestr);
-
- /* set Password Expiration date */
- if (!gmtime_r(&(data->expireTime), &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "failed to convert expiration date\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbPasswordExpiration", timestr);
-
- sambaSamAccount = slapi_value_new_string("sambaSamAccount");
- if (slapi_entry_attr_has_syntax_value(data->target, "objectClass", sambaSamAccount)) {
- /* TODO: retrieve if we want to store the LM hash or not */
- ntlm_flags = KTF_LM_HASH | KTF_NT_HASH;
- }
- slapi_value_free(&sambaSamAccount);
-
- if (ntlm_flags) {
- char *password = strdup(data->password);
- if (encode_ntlm_keys(password, ntlm_flags, &ntlm) != 0) {
- free(password);
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- if (ntlm_flags & KTF_LM_HASH) {
- hexbuf(lm, ntlm.lm);
- lm[32] = '\0';
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaLMPassword", lm);
- }
- if (ntlm_flags & KTF_NT_HASH) {
- hexbuf(nt, ntlm.nt);
- nt[32] = '\0';
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaNTPassword", nt);
- }
- free(password);
- }
-
- /* let DS encode the password itself, this allows also other plugins to
- * intercept it to perform operations like synchronization with Active
- * Directory domains through the replication plugin */
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "userPassword", data->password);
-
- /* set password history */
- pwvals = ipapwd_setPasswordHistory(smods, data);
- if (pwvals) {
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "passwordHistory", pwvals);
- }
-
- /* FIXME:
- * instead of replace we should use a delete/add so that we are
- * completely sure nobody else modified the entry meanwhile and
- * fail if that's the case */
-
- /* commit changes */
- ret = ipapwd_apply_mods(data->dn, smods);
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipapwd_SetPassword: %d\n", ret);
-
-free_and_return:
- slapi_mods_free(&smods);
- ipapwd_free_slapi_value_array(&svals);
- ipapwd_free_slapi_value_array(&pwvals);
-
- return ret;
-}
-
-static int ipapwd_chpwop(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
-{
- char *bindDN = NULL;
- char *authmethod = NULL;
- char *dn = NULL;
- char *oldPasswd = NULL;
- char *newPasswd = NULL;
- char *errMesg = NULL;
- int ret=0, rc=0, is_root=0;
- ber_tag_t tag=0;
- ber_len_t len=-1;
- struct berval *extop_value = NULL;
- BerElement *ber = NULL;
- Slapi_Entry *targetEntry=NULL;
- char *attrlist[] = {"*", "passwordHistory", NULL };
- struct ipapwd_data pwdata;
-
- /* Get the ber value of the extended operation */
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
-
- if ((ber = ber_init(extop_value)) == NULL)
- {
- errMesg = "PasswdModify Request decode failed.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- /* Format of request to parse
- *
- * PasswdModifyRequestValue ::= SEQUENCE {
- * userIdentity [0] OCTET STRING OPTIONAL
- * oldPasswd [1] OCTET STRING OPTIONAL
- * newPasswd [2] OCTET STRING OPTIONAL }
- *
- * The request value field is optional. If it is
- * provided, at least one field must be filled in.
- */
-
- /* ber parse code */
- if ( ber_scanf( ber, "{") == LBER_ERROR )
- {
- /* The request field wasn't provided. We'll
- * now try to determine the userid and verify
- * knowledge of the old password via other
- * means.
- */
- goto parse_req_done;
- } else {
- tag = ber_peek_tag( ber, &len);
- }
-
- /* identify userID field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_USERID )
- {
- if (ber_scanf(ber, "a", &dn) == LBER_ERROR) {
- slapi_ch_free_string(&dn);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "ber_scanf failed\n");
- errMesg = "ber_scanf failed at userID parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- tag = ber_peek_tag(ber, &len);
- }
-
- /* identify oldPasswd field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_OLDPWD )
- {
- if (ber_scanf(ber, "a", &oldPasswd) == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "ber_scanf failed\n");
- errMesg = "ber_scanf failed at oldPasswd parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
- tag = ber_peek_tag(ber, &len);
- }
-
- /* identify newPasswd field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_NEWPWD )
- {
- if (ber_scanf(ber, "a", &newPasswd) == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "ber_scanf failed\n");
- errMesg = "ber_scanf failed at newPasswd parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
- }
-
-parse_req_done:
- /* Uncomment for debugging, otherwise we don't want to leak the
- * password values into the log... */
- /* LDAPDebug( LDAP_DEBUG_ARGS, "passwd: dn (%s), oldPasswd (%s),
- * newPasswd (%s)\n", dn, oldPasswd, newPasswd); */
-
-
- /* Get Bind DN */
- slapi_pblock_get(pb, SLAPI_CONN_DN, &bindDN);
-
- /* If the connection is bound anonymously, we must refuse
- * to process this operation. */
- if (bindDN == NULL || *bindDN == '\0') {
- /* Refuse the operation because they're bound anonymously */
- errMesg = "Anonymous Binds are not allowed.\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
-
- /* A new password was not supplied in the request, and we do not support
- * password generation yet.
- */
- if (newPasswd == NULL || *newPasswd == '\0') {
- errMesg = "Password generation not implemented.\n";
- rc = LDAP_UNWILLING_TO_PERFORM;
- goto free_and_return;
- }
-
- if (oldPasswd == NULL || *oldPasswd == '\0') {
- /* If user is authenticated, they already gave their password during
- the bind operation (or used sasl or client cert auth or OS creds) */
- slapi_pblock_get(pb, SLAPI_CONN_AUTHMETHOD, &authmethod);
- if (!authmethod || !strcmp(authmethod, SLAPD_AUTH_NONE)) {
- errMesg = "User must be authenticated to the directory server.\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
- }
-
- /* Determine the target DN for this operation */
- /* Did they give us a DN ? */
- if (dn == NULL || *dn == '\0') {
- /* Get the DN from the bind identity on this connection */
- dn = slapi_ch_strdup(bindDN);
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Missing userIdentity in request, using the bind DN instead.\n");
- }
-
- slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn );
-
- /* Now we have the DN, look for the entry */
- ret = ipapwd_getEntry(dn, &targetEntry, attrlist);
- /* If we can't find the entry, then that's an error */
- if (ret) {
- /* Couldn't find the entry, fail */
- errMesg = "No such Entry exists.\n" ;
- rc = LDAP_NO_SUCH_OBJECT;
- goto free_and_return;
- }
-
- /* First thing to do is to ask access control if the bound identity has
- * rights to modify the userpassword attribute on this entry. If not,
- * then we fail immediately with insufficient access. This means that
- * we don't leak any useful information to the client such as current
- * password wrong, etc.
- */
-
- is_root = slapi_dn_isroot(bindDN);
- slapi_pblock_set(pb, SLAPI_REQUESTOR_ISROOT, &is_root);
-
- /* In order to perform the access control check, we need to select a
- * backend (even though we don't actually need it otherwise).
- */
- {
- Slapi_Backend *be = NULL;
-
- be = slapi_be_select(slapi_entry_get_sdn(targetEntry));
- if (NULL == be) {
- errMesg = "Failed to find backend for target entry";
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- slapi_pblock_set(pb, SLAPI_BACKEND, be);
- }
-
- ret = slapi_access_allowed( pb, targetEntry, "krbPrincipalKey", NULL, SLAPI_ACL_WRITE );
- if ( ret != LDAP_SUCCESS ) {
- errMesg = "Insufficient access rights\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
-
- /* Now we have the entry which we want to modify
- * They gave us a password (old), check it against the target entry
- * Is the old password valid ?
- */
- if (oldPasswd && *oldPasswd) {
- /* If user is authenticated, they already gave their password
- * during the bind operation (or used sasl or client cert auth
- * or OS creds) */
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "oldPasswd provided, but we will ignore it");
- }
-
- memset(&pwdata, 0, sizeof(pwdata));
- pwdata.target = targetEntry;
- pwdata.dn = dn;
- pwdata.password = newPasswd;
- pwdata.timeNow = time(NULL);
- pwdata.changetype = IPA_CHANGETYPE_NORMAL;
-
- /*
- * (technically strcasecmp to compare DNs is not absolutely correct,
- * but it should work for the cases we care about here)
- */
-
- /* determine type of password change */
- /* special cases */
- if ((strcasecmp(dn, bindDN) != 0) &&
- (strcasecmp(ipa_changepw_principal_dn, bindDN) != 0)) {
- int i;
-
- pwdata.changetype = IPA_CHANGETYPE_ADMIN;
-
- for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
- if (strcasecmp(krbcfg->passsync_mgrs[i], bindDN) == 0) {
- pwdata.changetype = IPA_CHANGETYPE_DSMGR;
- break;
- }
- }
- }
-
- /* check the policy */
- ret = ipapwd_CheckPolicy(&pwdata);
- if (ret) {
- errMesg = "Password Fails to meet minimum strength criteria";
- if (ret & IPAPWD_POLICY_ERROR) {
- slapi_pwpolicy_make_response_control(pb, -1, -1, ret & IPAPWD_POLICY_MASK);
- rc = LDAP_CONSTRAINT_VIOLATION;
- } else {
- errMesg = "Internal error";
- rc = ret;
- }
- goto free_and_return;
- }
-
- /* Now we're ready to set the kerberos key material */
- ret = ipapwd_SetPassword(krbcfg, &pwdata);
- if (ret != LDAP_SUCCESS) {
- /* Failed to modify the password,
- * e.g. because insufficient access allowed */
- errMesg = "Failed to update password";
- if (ret > 0) {
- rc = ret;
- } else {
- rc = LDAP_OPERATIONS_ERROR;
- }
- goto free_and_return;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipapwd_extop: %d\n", rc);
-
- /* Free anything that we allocated above */
-free_and_return:
- slapi_ch_free_string(&oldPasswd);
- slapi_ch_free_string(&newPasswd);
- /* Either this is the same pointer that we allocated and set above,
- * or whoever used it should have freed it and allocated a new
- * value that we need to free here */
- slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn);
- slapi_ch_free_string(&dn);
- slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET, NULL);
- slapi_ch_free_string(&authmethod);
-
- if (targetEntry) slapi_entry_free(targetEntry);
- if (ber) ber_free(ber, 1);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg ? errMesg : "success");
- slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
-
- return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
-
-}
-
-/* Password Modify Extended operation plugin function */
-static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
-{
- char *bindDN = NULL;
- char *serviceName = NULL;
- char *errMesg = NULL;
- int ret=0, rc=0, is_root=0;
- struct berval *extop_value = NULL;
- BerElement *ber = NULL;
- Slapi_PBlock *pbte = NULL;
- Slapi_Entry *targetEntry=NULL;
- struct berval *bval = NULL;
- Slapi_Value **svals = NULL;
- const char *bdn;
- const Slapi_DN *bsdn;
- Slapi_DN *sdn;
- Slapi_Backend *be;
- Slapi_Entry **es = NULL;
- int scope, res;
- char *filter;
- char *attrlist[] = {"krbPrincipalKey", "krbLastPwdChange", NULL };
- krb5_context krbctx = NULL;
- krb5_principal krbname = NULL;
- krb5_error_code krberr;
- int i, kvno;
- Slapi_Mods *smods;
- ber_tag_t rtag, ttmp;
- ber_int_t tint;
- ber_len_t tlen;
- struct ipapwd_keyset *kset = NULL;
- struct tm utctime;
- char timestr[GENERALIZED_TIME_LENGTH+1];
- time_t time_now = time(NULL);
-
- svals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
- if (!svals) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
-
- krberr = krb5_init_context(&krbctx);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_init_context failed\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
-
- /* Get Bind DN */
- slapi_pblock_get(pb, SLAPI_CONN_DN, &bindDN);
-
- /* If the connection is bound anonymously, we must refuse to process
- * this operation. */
- if (bindDN == NULL || *bindDN == '\0') {
- /* Refuse the operation because they're bound anonymously */
- errMesg = "Anonymous Binds are not allowed.\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
-
- /* Get the ber value of the extended operation */
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
-
- if ((ber = ber_init(extop_value)) == NULL)
- {
- errMesg = "KeytabGet Request decode failed.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- /* Format of request to parse
- *
- * KeytabGetRequest ::= SEQUENCE {
- * serviceIdentity OCTET STRING
- * keys SEQUENCE OF KrbKey,
- * ...
- * }
- *
- * KrbKey ::= SEQUENCE {
- * key [0] EncryptionKey,
- * salt [1] KrbSalt OPTIONAL,
- * s2kparams [2] OCTET STRING OPTIONAL,
- * ...
- * }
- *
- * EncryptionKey ::= SEQUENCE {
- * keytype [0] Int32,
- * keyvalue [1] OCTET STRING
- * }
- *
- * KrbSalt ::= SEQUENCE {
- * type [0] Int32,
- * salt [1] OCTET STRING OPTIONAL
- * }
- */
-
- /* ber parse code */
- rtag = ber_scanf(ber, "{a{", &serviceName);
- if (rtag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "ber_scanf failed\n");
- errMesg = "Invalid payload, failed to decode.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- /* make sure it is a valid name */
- krberr = krb5_parse_name(krbctx, serviceName, &krbname);
- if (krberr) {
- slapi_ch_free_string(&serviceName);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_parse_name failed\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- } else {
- /* invert so that we get the canonical form
- * (add REALM if not present for example) */
- char *canonname;
- krberr = krb5_unparse_name(krbctx, krbname, &canonname);
- if (krberr) {
- slapi_ch_free_string(&serviceName);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_unparse_name failed\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- slapi_ch_free_string(&serviceName);
- serviceName = canonname;
- }
-
- /* check entry before doing any other decoding */
-
- /* Find ancestor base DN */
- sdn = slapi_sdn_new_dn_byval(ipa_realm_dn);
- be = slapi_be_select(sdn);
- slapi_sdn_free(&sdn);
- bsdn = slapi_be_getsuffix(be, 0);
- if (bsdn == NULL) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Search for Base DN failed\n");
- errMesg = "PrincipalName not found.\n";
- rc = LDAP_NO_SUCH_OBJECT;
- goto free_and_return;
- }
- bdn = slapi_sdn_get_dn(bsdn);
- scope = LDAP_SCOPE_SUBTREE;
-
- /* get Entry by krbPrincipalName */
- filter = slapi_ch_smprintf("(krbPrincipalName=%s)", serviceName);
-
- pbte = slapi_pblock_new();
- slapi_search_internal_set_pb(pbte,
- bdn, scope, filter, attrlist, 0,
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id,
- 0); /* Flags */
-
- /* do search the tree */
- ret = slapi_search_internal_pb(pbte);
- slapi_pblock_get(pbte, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (ret == -1 || res != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Search for Principal failed, err (%d)\n",
- res?res:ret);
- errMesg = "PrincipalName not found.\n";
- rc = LDAP_NO_SUCH_OBJECT;
- goto free_and_return;
- }
-
- /* get entries */
- slapi_pblock_get(pbte, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es);
- if (!es) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "No entries ?!");
- errMesg = "PrincipalName not found.\n";
- rc = LDAP_NO_SUCH_OBJECT;
- goto free_and_return;
- }
-
- /* count entries */
- for (i = 0; es[i]; i++) /* count */ ;
-
- /* if there is none or more than one, freak out */
- if (i != 1) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Too many entries, or entry no found (%d)", i);
- errMesg = "PrincipalName not found.\n";
- rc = LDAP_NO_SUCH_OBJECT;
- goto free_and_return;
- }
- targetEntry = es[0];
-
- /* First thing to do is to ask access control if the bound identity has
- * rights to modify the userpassword attribute on this entry. If not,
- * then we fail immediately with insufficient access. This means that
- * we don't leak any useful information to the client such as current
- * password wrong, etc.
- */
-
- is_root = slapi_dn_isroot(bindDN);
- slapi_pblock_set(pb, SLAPI_REQUESTOR_ISROOT, &is_root);
-
- /* In order to perform the access control check,
- * we need to select a backend (even though
- * we don't actually need it otherwise).
- */
- slapi_pblock_set(pb, SLAPI_BACKEND, be);
-
- /* Access Strategy:
- * If the user has WRITE-ONLY access, a new keytab is set on the entry.
- */
-
- ret = slapi_access_allowed(pb, targetEntry, "krbPrincipalKey", NULL, SLAPI_ACL_WRITE);
- if (ret != LDAP_SUCCESS) {
- errMesg = "Insufficient access rights\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
-
- /* increment kvno (will be 1 if this is a new entry) */
- kvno = ipapwd_get_cur_kvno(targetEntry) + 1;
-
- /* ok access allowed, init kset and continue to parse ber buffer */
-
- errMesg = "Unable to set key\n";
- rc = LDAP_OPERATIONS_ERROR;
-
- kset = malloc(sizeof(struct ipapwd_keyset));
- if (!kset) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
-
- /* this encoding assumes all keys have the same kvno */
- /* major-vno = 1 and minor-vno = 1 */
- kset->major_vno = 1;
- kset->minor_vno = 1;
- kset->kvno = kvno;
- /* we also assum mkvno is 0 */
- kset->mkvno = 0;
-
- kset->keys = NULL;
- kset->num_keys = 0;
-
- rtag = ber_peek_tag(ber, &tlen);
- while (rtag == LBER_SEQUENCE) {
- krb5_data plain;
- krb5_enc_data cipher;
- struct berval tval;
- krb5_octet *kdata;
- size_t klen;
-
- i = kset->num_keys;
-
- if (kset->keys) {
- struct ipapwd_krbkey *newset;
-
- newset = realloc(kset->keys, sizeof(struct ipapwd_krbkey) * (i + 1));
- if (!newset) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
- kset->keys = newset;
- } else {
- kset->keys = malloc(sizeof(struct ipapwd_krbkey));
- if (!kset->keys) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
- }
- kset->num_keys += 1;
-
- kset->keys[i].salt = NULL;
- kset->keys[i].ekey = NULL;
- kset->keys[i].s2kparams.bv_len = 0;
- kset->keys[i].s2kparams.bv_val = NULL;
-
- /* EncryptionKey */
- rtag = ber_scanf(ber, "{t[{t[i]t[o]}]", &ttmp, &ttmp, &tint, &ttmp, &tval);
- if (rtag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed\n");
- errMesg = "Invalid payload, failed to decode.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- kset->keys[i].ekey = calloc(1, sizeof(struct ipapwd_krbkeydata));
- if (!kset->keys[i].ekey) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
-
- kset->keys[i].ekey->type = tint;
-
- plain.length = tval.bv_len;
- plain.data = tval.bv_val;
-
- krberr = krb5_c_encrypt_length(krbctx, krbcfg->kmkey->enctype, plain.length, &klen);
- if (krberr) {
- free(tval.bv_val);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "krb encryption failed!\n");
- goto free_and_return;
- }
-
- kdata = malloc(2 + klen);
- if (!kdata) {
- free(tval.bv_val);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
- encode_int16(plain.length, kdata);
-
- kset->keys[i].ekey->value.bv_len = 2 + klen;
- kset->keys[i].ekey->value.bv_val = (char *)kdata;
-
- cipher.ciphertext.length = klen;
- cipher.ciphertext.data = (char *)kdata + 2;
-
- krberr = krb5_c_encrypt(krbctx, krbcfg->kmkey, 0, 0, &plain, &cipher);
- if (krberr) {
- free(tval.bv_val);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "krb encryption failed!\n");
- goto free_and_return;
- }
-
- free(tval.bv_val);
-
- rtag = ber_peek_tag(ber, &tlen);
-
- /* KrbSalt */
- if (rtag == (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
-
- rtag = ber_scanf(ber, "t[{t[i]", &ttmp, &ttmp, &tint);
- if (rtag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed\n");
- errMesg = "Invalid payload, failed to decode.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- kset->keys[i].salt = calloc(1, sizeof(struct ipapwd_krbkeydata));
- if (!kset->keys[i].salt) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "malloc failed!\n");
- goto free_and_return;
- }
-
- kset->keys[i].salt->type = tint;
-
- rtag = ber_peek_tag(ber, &tlen);
- if (rtag == (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
-
- rtag = ber_scanf(ber, "t[o]}]", &ttmp, &tval);
- if (rtag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed\n");
- errMesg = "Invalid payload, failed to decode.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- kset->keys[i].salt->value = tval;
-
- rtag = ber_peek_tag(ber, &tlen);
- }
- }
-
- /* FIXME: s2kparams - NOT implemented yet */
- if (rtag == (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) {
- rtag = ber_scanf(ber, "t[x]}", &ttmp);
- } else {
- rtag = ber_scanf(ber, "}", &ttmp);
- }
- if (rtag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed\n");
- errMesg = "Invalid payload, failed to decode.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- rtag = ber_peek_tag(ber, &tlen);
- }
-
- ber_free(ber, 1);
- ber = NULL;
-
- /* filter un-supported encodings */
- ret = filter_keys(krbcfg, kset);
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "keyset filtering failed\n");
- goto free_and_return;
- }
-
- /* check if we have any left */
- if (kset->num_keys == 0) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "keyset filtering rejected all proposed keys\n");
- errMesg = "All enctypes provided are unsupported";
- rc = LDAP_UNWILLING_TO_PERFORM;
- goto free_and_return;
- }
-
- smods = slapi_mods_new();
-
- /* change Last Password Change field with the current date */
- if (!gmtime_r(&(time_now), &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "failed to retrieve current date (buggy gmtime_r ?)\n");
- slapi_mods_free(&smods);
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbLastPwdChange", timestr);
-
- /* FIXME: set Password Expiration date ? */
-#if 0
- if (!gmtime_r(&(data->expireTime), &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "failed to convert expiration date\n");
- slapi_ch_free_string(&randPasswd);
- slapi_mods_free(&smods);
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbPasswordExpiration", timestr);
-#endif
-
- bval = encode_keys(kset);
- if (!bval) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 KrbSalt failed\n");
- slapi_mods_free(&smods);
- goto free_and_return;
- }
-
- svals[0] = slapi_value_new_berval(bval);
- if (!svals[0]) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Converting berval to Slapi_Value\n");
- slapi_mods_free(&smods);
- goto free_and_return;
- }
-
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbPrincipalKey", svals);
-
- /* commit changes */
- ret = ipapwd_apply_mods(slapi_entry_get_dn_const(targetEntry), smods);
-
- if (ret != LDAP_SUCCESS) {
- slapi_mods_free(&smods);
- goto free_and_return;
-
- }
- slapi_mods_free(&smods);
-
- /* Format of response
- *
- * KeytabGetRequest ::= SEQUENCE {
- * new_kvno Int32
- * SEQUENCE OF KeyTypes
- * }
- *
- * * List of accepted enctypes *
- * KeyTypes ::= SEQUENCE {
- * enctype Int32
- * }
- */
-
- errMesg = "Internal Error\n";
- rc = LDAP_OPERATIONS_ERROR;
-
- ber = ber_alloc();
- if (!ber) {
- goto free_and_return;
- }
-
- ret = ber_printf(ber, "{i{", (ber_int_t)kvno);
- if (ret == -1) {
- goto free_and_return;
- }
-
- for (i = 0; i < kset->num_keys; i++) {
- ret = ber_printf(ber, "{i}", (ber_int_t)kset->keys[i].ekey->type);
- if (ret == -1) {
- goto free_and_return;
- }
- }
- ret = ber_printf(ber, "}}");
- if (ret == -1) {
- goto free_and_return;
- }
-
- if (ret != -1) {
- struct berval *bvp;
- LDAPControl new_ctrl = {0};
-
- ret = ber_flatten(ber, &bvp);
- if (ret == -1) {
- goto free_and_return;
- }
-
- new_ctrl.ldctl_oid = KEYTAB_RET_OID;
- new_ctrl.ldctl_value = *bvp;
- new_ctrl.ldctl_iscritical = 0;
- rc= slapi_pblock_set(pb, SLAPI_ADD_RESCONTROL, &new_ctrl);
- ber_bvfree(bvp);
- }
-
- /* Free anything that we allocated above */
-free_and_return:
- free(serviceName);
- if (kset) ipapwd_keyset_free(&kset);
-
- if (bval) ber_bvfree(bval);
- if (ber) ber_free(ber, 1);
-
- if (pbte) {
- slapi_free_search_results_internal(pbte);
- slapi_pblock_destroy(pbte);
- }
- if (svals) {
- for (i = 0; svals[i]; i++) {
- slapi_value_free(&svals[i]);
- }
- free(svals);
- }
-
- if (krbname) krb5_free_principal(krbctx, krbname);
- if (krbctx) krb5_free_context(krbctx);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg ? errMesg : "success");
- slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
-
- return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
-}
-
-static int new_ipapwd_encsalt(krb5_context krbctx, const char * const *encsalts,
- struct ipapwd_encsalt **es_types, int *num_es_types)
-{
- struct ipapwd_encsalt *es;
- int nes, i;
-
- for (i = 0; encsalts[i]; i++) /* count */ ;
- es = calloc(i + 1, sizeof(struct ipapwd_encsalt));
- if (!es) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_start", "Out of memory!\n");
- return LDAP_OPERATIONS_ERROR;
- }
-
- for (i = 0, nes = 0; encsalts[i]; i++) {
- char *enc, *salt;
- krb5_int32 tmpsalt;
- krb5_enctype tmpenc;
- krb5_boolean similar;
- krb5_error_code krberr;
- int j;
-
- enc = strdup(encsalts[i]);
- if (!enc) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipapwd_start",
- "Allocation error\n");
- return LDAP_OPERATIONS_ERROR;
- }
- salt = strchr(enc, ':');
- if (!salt) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipapwd_start",
- "Invalid krb5 enc string\n");
- free(enc);
- continue;
- }
- *salt = '\0'; /* null terminate the enc type */
- salt++; /* skip : */
-
- krberr = krb5_string_to_enctype(enc, &tmpenc);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipapwd_start",
- "Invalid krb5 enctype\n");
- free(enc);
- continue;
- }
-
- krberr = krb5_string_to_salttype(salt, &tmpsalt);
- for (j = 0; j < nes; j++) {
- krb5_c_enctype_compare(krbctx, es[j].enc_type, tmpenc, &similar);
- if (similar && (es[j].salt_type == tmpsalt)) {
- break;
- }
- }
-
- if (j == nes) {
- /* not found */
- es[j].enc_type = tmpenc;
- es[j].salt_type = tmpsalt;
- nes++;
- }
-
- free(enc);
- }
-
- *es_types = es;
- *num_es_types = nes;
-
- return LDAP_SUCCESS;
-}
-
-static struct ipapwd_krbcfg *ipapwd_getConfig(void)
-{
- krb5_error_code krberr;
- struct ipapwd_krbcfg *config = NULL;
- krb5_keyblock *kmkey = NULL;
- Slapi_Entry *realm_entry = NULL;
- Slapi_Entry *config_entry = NULL;
- Slapi_Attr *a;
- Slapi_Value *v;
- BerElement *be = NULL;
- ber_tag_t tag, tmp;
- ber_int_t ttype;
- const struct berval *bval;
- struct berval *mkey = NULL;
- char **encsalts;
- char *tmpstr;
- int i, ret;
-
- config = calloc(1, sizeof(struct ipapwd_krbcfg));
- if (!config) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Out of memory!\n");
- goto free_and_error;
- }
- kmkey = calloc(1, sizeof(krb5_keyblock));
- if (!kmkey) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Out of memory!\n");
- goto free_and_error;
- }
- config->kmkey = kmkey;
-
- krberr = krb5_init_context(&config->krbctx);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "krb5_init_context failed\n");
- goto free_and_error;
- }
-
- ret = krb5_get_default_realm(config->krbctx, &config->realm);
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Failed to get default realm?!\n");
- goto free_and_error;
- }
-
- /* get the Realm Container entry */
- ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL);
- if (ret != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "No realm Entry?\n");
- goto free_and_error;
- }
-
- /*** get the Kerberos Master Key ***/
-
- ret = slapi_entry_attr_find(realm_entry, "krbMKey", &a);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "No master key??\n");
- goto free_and_error;
- }
-
- /* there should be only one value here */
- ret = slapi_attr_first_value(a, &v);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "No master key??\n");
- goto free_and_error;
- }
-
- bval = slapi_value_get_berval(v);
- if (!bval) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Error retrieving master key berval\n");
- goto free_and_error;
- }
-
- be = ber_init(bval);
- if (!bval) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "ber_init() failed!\n");
- goto free_and_error;
- }
-
- tag = ber_scanf(be, "{i{iO}}", &tmp, &ttype, &mkey);
- if (tag == LBER_ERROR) {
- slapi_log_error(SLAPI_LOG_TRACE, "ipapwd_getConfig",
- "Bad Master key encoding ?!\n");
- goto free_and_error;
- }
-
- kmkey->magic = KV5M_KEYBLOCK;
- kmkey->enctype = ttype;
- kmkey->length = mkey->bv_len;
- kmkey->contents = malloc(mkey->bv_len);
- if (!kmkey->contents) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Out of memory!\n");
- goto free_and_error;
- }
- memcpy(kmkey->contents, mkey->bv_val, mkey->bv_len);
- ber_bvfree(mkey);
- ber_free(be, 1);
- mkey = NULL;
- be = NULL;
-
- /*** get the Supported Enc/Salt types ***/
-
- encsalts = slapi_entry_attr_get_charray(realm_entry, "krbSupportedEncSaltTypes");
- if (encsalts) {
- ret = new_ipapwd_encsalt(config->krbctx,
- (const char * const *)encsalts,
- &config->supp_encsalts,
- &config->num_supp_encsalts);
- slapi_ch_array_free(encsalts);
- } else {
- slapi_log_error(SLAPI_LOG_TRACE, "ipapwd_getConfig",
- "No configured salt types use defaults\n");
- ret = new_ipapwd_encsalt(config->krbctx,
- ipapwd_def_encsalts,
- &config->supp_encsalts,
- &config->num_supp_encsalts);
- }
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Can't get Supported EncSalt Types\n");
- goto free_and_error;
- }
-
- /*** get the Preferred Enc/Salt types ***/
-
- encsalts = slapi_entry_attr_get_charray(realm_entry, "krbDefaultEncSaltTypes");
- if (encsalts) {
- ret = new_ipapwd_encsalt(config->krbctx,
- (const char * const *)encsalts,
- &config->pref_encsalts,
- &config->num_pref_encsalts);
- slapi_ch_array_free(encsalts);
- } else {
- slapi_log_error(SLAPI_LOG_TRACE, "ipapwd_getConfig",
- "No configured salt types use defaults\n");
- ret = new_ipapwd_encsalt(config->krbctx,
- ipapwd_def_encsalts,
- &config->pref_encsalts,
- &config->num_pref_encsalts);
- }
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Can't get Preferred EncSalt Types\n");
- goto free_and_error;
- }
-
- slapi_entry_free(realm_entry);
-
- /* get the Realm Container entry */
- ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL);
- if (ret != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "No config Entry? Impossible!\n");
- goto free_and_error;
- }
- config->passsync_mgrs = slapi_entry_attr_get_charray(config_entry, "passSyncManagersDNs");
- /* now add Directory Manager, it is always added by default */
- tmpstr = slapi_ch_strdup("cn=Directory Manager");
- slapi_ch_array_add(&config->passsync_mgrs, tmpstr);
- if (config->passsync_mgrs == NULL) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_getConfig",
- "Out of memory!\n");
- goto free_and_error;
- }
- for (i = 0; config->passsync_mgrs[i]; i++) /* count */ ;
- config->num_passsync_mgrs = i;
-
- return config;
-
-free_and_error:
- if (mkey) ber_bvfree(mkey);
- if (be) ber_free(be, 1);
- if (kmkey) {
- free(kmkey->contents);
- free(kmkey);
- }
- if (config) {
- if (config->krbctx) {
- if (config->realm)
- krb5_free_default_realm(config->krbctx, config->realm);
- krb5_free_context(config->krbctx);
- }
- free(config->pref_encsalts);
- free(config->supp_encsalts);
- slapi_ch_array_free(config->passsync_mgrs);
- free(config);
- }
- slapi_entry_free(config_entry);
- slapi_entry_free(realm_entry);
- return NULL;
-}
-
-#define IPAPWD_CHECK_CONN_SECURE 0x00000001
-#define IPAPWD_CHECK_DN 0x00000002
-
-static int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
- struct ipapwd_krbcfg **config,
- int check_flags)
-{
- int ret, sasl_ssf, is_ssl;
- int rc = LDAP_SUCCESS;
- Slapi_Backend *be;
- const Slapi_DN *psdn;
- Slapi_DN *sdn;
- char *dn = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_gen_checks\n");
-
-#ifdef LDAP_EXTOP_PASSMOD_CONN_SECURE
- if (check_flags & IPAPWD_CHECK_CONN_SECURE) {
- /* Allow password modify only for SSL/TLS established connections and
- * connections using SASL privacy layers */
- if (slapi_pblock_get(pb, SLAPI_CONN_SASL_SSF, &sasl_ssf) != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Could not get SASL SSF from connection\n");
- *errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- if (slapi_pblock_get(pb, SLAPI_CONN_IS_SSL_SESSION, &is_ssl) != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Could not get IS SSL from connection\n");
- *errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- if ((0 == is_ssl) && (sasl_ssf <= 1)) {
- *errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_CONFIDENTIALITY_REQUIRED;
- goto done;
- }
- }
-#endif
-
- if (check_flags & IPAPWD_CHECK_DN) {
- /* check we have a valid DN in the pblock or just abort */
- ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- if (ret) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Tried to change password for an invalid DN [%s]\n",
- dn?dn:"<NULL>");
- *errMesg = "Invalid DN";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- sdn = slapi_sdn_new_dn_byref(dn);
- if (!sdn) {
- *errMesg = "Internal Error";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- be = slapi_be_select(sdn);
- slapi_sdn_free(&sdn);
-
- psdn = slapi_be_getsuffix(be, 0);
- if (!psdn) {
- *errMesg = "Invalid DN";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- }
-
- /* get the kerberos context and master key */
- *config = ipapwd_getConfig();
- if (NULL == *config) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Error Retrieving Master Key");
- *errMesg = "Fatal Internal Error";
- rc = LDAP_OPERATIONS_ERROR;
- }
-
-done:
- return rc;
-}
-
-static int ipapwd_extop(Slapi_PBlock *pb)
-{
- struct ipapwd_krbcfg *krbcfg = NULL;
- char *errMesg = NULL;
- char *oid = NULL;
- int rc, ret;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_extop\n");
-
- rc = ipapwd_gen_checks(pb, &errMesg, &krbcfg, IPAPWD_CHECK_CONN_SECURE);
- if (rc) {
- goto free_and_return;
- }
-
- /* Before going any further, we'll make sure that the right extended
- * operation plugin has been called: i.e., the OID shipped whithin the
- * extended operation request must match this very plugin's OIDs:
- * EXOP_PASSWD_OID or KEYTAB_SET_OID. */
- if (slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid) != 0) {
- errMesg = "Could not get OID value from request.\n";
- rc = LDAP_OPERATIONS_ERROR;
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg);
- goto free_and_return;
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Received extended operation request with OID %s\n", oid);
- }
-
- if (strcasecmp(oid, EXOP_PASSWD_OID) == 0) {
- ret = ipapwd_chpwop(pb, krbcfg);
- free_ipapwd_krbcfg(&krbcfg);
- return ret;
- }
- if (strcasecmp(oid, KEYTAB_SET_OID) == 0) {
- ret = ipapwd_setkeytab(pb, krbcfg);
- free_ipapwd_krbcfg(&krbcfg);
- return ret;
- }
-
- errMesg = "Request OID does not match supported OIDs.\n";
- rc = LDAP_OPERATIONS_ERROR;
-
-free_and_return:
- if (krbcfg) free_ipapwd_krbcfg(&krbcfg);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg);
- slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
-
- return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
-}
-
-/*****************************************************************************
- * pre/post operations to intercept writes to userPassword
- ****************************************************************************/
-
-#define IPAPWD_OP_NULL 0
-#define IPAPWD_OP_ADD 1
-#define IPAPWD_OP_MOD 2
-struct ipapwd_operation {
- struct ipapwd_data pwdata;
- int pwd_op;
- int is_krb;
-};
-
-/* structure with information for each extension */
-struct ipapwd_op_ext {
- char *object_name; /* name of the object extended */
- int object_type; /* handle to the extended object */
- int handle; /* extension handle */
-};
-
-static struct ipapwd_op_ext ipapwd_op_ext_list;
-
-static void *ipapwd_op_ext_constructor(void *object, void *parent)
-{
- struct ipapwd_operation *ext;
-
- ext = (struct ipapwd_operation *)slapi_ch_calloc(1, sizeof(struct ipapwd_operation));
- return ext;
-}
-
-static void ipapwd_op_ext_destructor(void *ext, void *object, void *parent)
-{
- struct ipapwd_operation *pwdop = (struct ipapwd_operation *)ext;
- if (!pwdop)
- return;
- if (pwdop->pwd_op != IPAPWD_OP_NULL) {
- slapi_ch_free_string(&(pwdop->pwdata.dn));
- slapi_ch_free_string(&(pwdop->pwdata.password));
- }
- slapi_ch_free((void **)&pwdop);
-}
-
-static int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
- int *is_root, int *is_krb, int *is_smb,
- char *attr, int access)
-{
- Slapi_Value *sval;
- int rc;
-
- /* Check ACIs */
- slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, is_root);
-
- if (!*is_root) {
- /* verify this user is allowed to write a user password */
- rc = slapi_access_allowed(pb, e, attr, NULL, access);
- if (rc != LDAP_SUCCESS) {
- /* we have no business here, the operation will be denied anyway */
- rc = LDAP_SUCCESS;
- goto done;
- }
- }
-
- /* Check if this is a krbPrincial and therefore needs us to generate other
- * hashes */
- sval = slapi_value_new_string("krbPrincipalAux");
- if (!sval) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- *is_krb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
- slapi_value_free(&sval);
-
- sval = slapi_value_new_string("sambaSamAccount");
- if (!sval) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- *is_smb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
- slapi_value_free(&sval);
-
- rc = LDAP_SUCCESS;
-
-done:
- return rc;
-}
-
-static int ipapwd_preop_gen_hashes(struct ipapwd_krbcfg *krbcfg,
- struct ipapwd_operation *pwdop,
- char *userpw,
- int is_krb, int is_smb,
- Slapi_Value ***svals,
- char **nthash, char **lmhash)
-{
- int rc;
-
- if (is_krb) {
-
- pwdop->is_krb = 1;
-
- *svals = encrypt_encode_key(krbcfg, &pwdop->pwdata);
-
- if (!*svals) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "key encryption/encoding failed\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- }
-
- if (is_smb) {
- char lm[33], nt[33];
- struct ntlm_keys ntlm;
- int ntlm_flags = 0;
- int ret;
-
- /* TODO: retrieve if we want to store the LM hash or not */
- ntlm_flags = KTF_LM_HASH | KTF_NT_HASH;
-
- ret = encode_ntlm_keys(userpw, ntlm_flags, &ntlm);
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "Failed to generate NT/LM hashes\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- if (ntlm_flags & KTF_LM_HASH) {
- hexbuf(lm, ntlm.lm);
- lm[32] = '\0';
- *lmhash = slapi_ch_strdup(lm);
- }
- if (ntlm_flags & KTF_NT_HASH) {
- hexbuf(nt, ntlm.nt);
- nt[32] = '\0';
- *nthash = slapi_ch_strdup(nt);
- }
- }
-
- rc = LDAP_SUCCESS;
-
-done:
-
- return rc;
-}
-
-/* PRE ADD Operation:
- * Gets the clean text password (fail the operation if the password came
- * pre-hashed, unless this is a replicated operation).
- * Check user is authorized to add it otherwise just returns, operation will
- * fail later anyway.
- * Run a password policy check.
- * Check if krb or smb hashes are required by testing if the krb or smb
- * objectclasses are present.
- * store information for the post operation
- */
-static int ipapwd_pre_add(Slapi_PBlock *pb)
-{
- struct ipapwd_krbcfg *krbcfg = NULL;
- char *errMesg = "Internal operations error\n";
- struct slapi_entry *e = NULL;
- char *userpw = NULL;
- char *dn = NULL;
- struct ipapwd_operation *pwdop = NULL;
- void *op;
- int is_repl_op, is_root, is_krb, is_smb;
- int ret, rc;
-
- slapi_log_error(SLAPI_LOG_TRACE, IPAPWD_PLUGIN_NAME, "=> ipapwd_pre_add\n");
-
- ret = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl_op);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "slapi_pblock_get failed!?\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- /* pass through if this is a replicated operation */
- if (is_repl_op)
- return 0;
-
- /* retrieve the entry */
- slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
- if (NULL == e)
- return 0;
-
- /* check this is something interesting for us first */
- userpw = slapi_entry_attr_get_charptr(e, SLAPI_USERPWD_ATTR);
- if (!userpw) {
- /* nothing interesting here */
- return 0;
- }
-
- /* Ok this is interesting,
- * Check this is a clear text password, or refuse operation */
- if ('{' == userpw[0]) {
- if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
- char *tmp = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
- if (NULL == tmp) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "Strdup failed, Out of memory\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- slapi_ch_free_string(&userpw);
- userpw = tmp;
- } else if (slapi_is_encoded(userpw)) {
-
- slapi_ch_free_string(&userpw);
-
- /* check if we have access to the unhashed user password */
- userpw = slapi_entry_attr_get_charptr(e, "unhashed#user#password");
- if (!userpw) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Pre-Encoded passwords are not valid\n");
- errMesg = "Pre-Encoded passwords are not valid\n";
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
- }
- }
- }
-
- rc = ipapwd_entry_checks(pb, e,
- &is_root, &is_krb, &is_smb,
- NULL, SLAPI_ACL_ADD);
- if (rc) {
- goto done;
- }
-
- rc = ipapwd_gen_checks(pb, &errMesg, &krbcfg, IPAPWD_CHECK_DN);
- if (rc) {
- goto done;
- }
-
- /* Get target DN */
- ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- if (ret) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- /* time to get the operation handler */
- ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "slapi_pblock_get failed!?\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- pwdop = slapi_get_object_extension(ipapwd_op_ext_list.object_type,
- op, ipapwd_op_ext_list.handle);
- if (NULL == pwdop) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- pwdop->pwd_op = IPAPWD_OP_ADD;
- pwdop->pwdata.password = slapi_ch_strdup(userpw);
-
- if (is_root) {
- pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
- } else {
- char *binddn;
- int i;
-
- pwdop->pwdata.changetype = IPA_CHANGETYPE_ADMIN;
-
- /* Check Bind DN */
- slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
-
- /* if it is a passsync manager we also need to skip resets */
- for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
- if (strcasecmp(krbcfg->passsync_mgrs[i], binddn) == 0) {
- pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
- break;
- }
- }
- }
-
- pwdop->pwdata.dn = slapi_ch_strdup(dn);
- pwdop->pwdata.timeNow = time(NULL);
- pwdop->pwdata.target = e;
-
- ret = ipapwd_CheckPolicy(&pwdop->pwdata);
- if (ret) {
- errMesg = "Password Fails to meet minimum strength criteria";
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
- }
-
- if (is_krb || is_smb) {
-
- Slapi_Value **svals = NULL;
- char *nt = NULL;
- char *lm = NULL;
-
- rc = ipapwd_preop_gen_hashes(krbcfg,
- pwdop, userpw,
- is_krb, is_smb,
- &svals, &nt, &lm);
- if (rc) {
- goto done;
- }
-
- if (svals) {
- /* add/replace values in existing entry */
- ret = slapi_entry_attr_replace_sv(e, "krbPrincipalKey", svals);
- if (ret) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "failed to set encoded values in entry\n");
- rc = LDAP_OPERATIONS_ERROR;
- ipapwd_free_slapi_value_array(&svals);
- goto done;
- }
-
- ipapwd_free_slapi_value_array(&svals);
- }
-
- if (lm) {
- /* set value */
- slapi_entry_attr_set_charptr(e, "sambaLMPassword", lm);
- slapi_ch_free_string(&lm);
- }
- if (nt) {
- /* set value */
- slapi_entry_attr_set_charptr(e, "sambaNTPassword", nt);
- slapi_ch_free_string(&nt);
- }
- }
-
- rc = LDAP_SUCCESS;
-
-done:
- if (pwdop) pwdop->pwdata.target = NULL;
- free_ipapwd_krbcfg(&krbcfg);
- slapi_ch_free_string(&userpw);
- if (rc != LDAP_SUCCESS) {
- slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
- return -1;
- }
- return 0;
-}
-
-/* PRE MOD Operation:
- * Gets the clean text password (fail the operation if the password came
- * pre-hashed, unless this is a replicated operation).
- * Check user is authorized to add it otherwise just returns, operation will
- * fail later anyway.
- * Check if krb or smb hashes are required by testing if the krb or smb
- * objectclasses are present.
- * Run a password policy check.
- * store information for the post operation
- */
-static int ipapwd_pre_mod(Slapi_PBlock *pb)
-{
- struct ipapwd_krbcfg *krbcfg = NULL;
- char *errMesg = NULL;
- LDAPMod **mods;
- Slapi_Mod *smod, *tmod;
- Slapi_Mods *smods = NULL;
- char *userpw = NULL;
- char *unhashedpw = NULL;
- char *dn = NULL;
- Slapi_DN *tmp_dn;
- struct slapi_entry *e = NULL;
- struct ipapwd_operation *pwdop = NULL;
- void *op;
- int is_repl_op, is_pwd_op, is_root, is_krb, is_smb;
- int ret, rc;
-
- slapi_log_error(SLAPI_LOG_TRACE, IPAPWD_PLUGIN_NAME, "=> ipapwd_pre_mod\n");
-
- ret = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl_op);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "slapi_pblock_get failed!?\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- /* pass through if this is a replicated operation */
- if (is_repl_op) {
- rc = LDAP_SUCCESS;
- goto done;
- }
-
- /* grab the mods - we'll put them back later with
- * our modifications appended
- */
- slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
- smods = slapi_mods_new();
- slapi_mods_init_passin(smods, mods);
-
- /* In the first pass,
- * only check there is anything we are interested in */
- is_pwd_op = 0;
- tmod = slapi_mod_new();
- smod = slapi_mods_get_first_smod(smods, tmod);
- while (smod) {
- struct berval *bv;
- const char *type;
- int mop;
-
- type = slapi_mod_get_type(smod);
- if (slapi_attr_types_equivalent(type, SLAPI_USERPWD_ATTR)) {
- mop = slapi_mod_get_operation(smod);
- /* check op filtering out LDAP_MOD_BVALUES */
- switch (mop & 0x0f) {
- case LDAP_MOD_ADD:
- case LDAP_MOD_REPLACE:
- is_pwd_op = 1;
- default:
- break;
- }
- }
-
- /* we check for unahsehd password here so that we are sure to catch them
- * early, before further checks go on, this helps checking
- * LDAP_MOD_DELETE operations in some corner cases later */
- /* we keep only the last one if multiple are provided for any absurd
- * reason */
- if (slapi_attr_types_equivalent(type, "unhashed#user#password")) {
- bv = slapi_mod_get_first_value(smod);
- if (!bv) {
- slapi_mod_free(&tmod);
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- slapi_ch_free_string(&unhashedpw);
- unhashedpw = slapi_ch_malloc(bv->bv_len+1);
- if (!unhashedpw) {
- slapi_mod_free(&tmod);
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- memcpy(unhashedpw, bv->bv_val, bv->bv_len);
- unhashedpw[bv->bv_len] = '\0';
- }
- slapi_mod_done(tmod);
- smod = slapi_mods_get_next_smod(smods, tmod);
- }
- slapi_mod_free(&tmod);
-
- /* If userPassword is not modified we are done here */
- if (! is_pwd_op) {
- rc = LDAP_SUCCESS;
- goto done;
- }
-
- /* OK swe have something interesting here, start checking for
- * pre-requisites */
-
- /* Get target DN */
- ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- if (ret) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- tmp_dn = slapi_sdn_new_dn_byref(dn);
- if (tmp_dn) {
- /* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
- * available but it turns out that is only true if you are
- * a dbm backend pre-op plugin - lucky dbm backend pre-op
- * plugins.
- * I think that is wrong since the entry is useful for filter
- * tests and schema checks and this plugin shouldn't be limited
- * to a single backend type, but I don't want that fight right
- * now so we go get the entry here
- *
- slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
- */
- ret = slapi_search_internal_get_entry(tmp_dn, 0, &e, ipapwd_plugin_id);
- slapi_sdn_free(&tmp_dn);
- if (ret != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Failed tpo retrieve entry?!?\n");
- rc = LDAP_NO_SUCH_OBJECT;
- goto done;
- }
- }
-
- rc = ipapwd_entry_checks(pb, e,
- &is_root, &is_krb, &is_smb,
- SLAPI_USERPWD_ATTR, SLAPI_ACL_WRITE);
- if (rc) {
- goto done;
- }
-
- rc = ipapwd_gen_checks(pb, &errMesg, &krbcfg, IPAPWD_CHECK_DN);
- if (rc) {
- goto done;
- }
-
- /* run through the mods again and adjust flags if operations affect them */
- tmod = slapi_mod_new();
- smod = slapi_mods_get_first_smod(smods, tmod);
- while (smod) {
- struct berval *bv;
- const char *type;
- int mop;
-
- type = slapi_mod_get_type(smod);
- if (slapi_attr_types_equivalent(type, SLAPI_USERPWD_ATTR)) {
- mop = slapi_mod_get_operation(smod);
- /* check op filtering out LDAP_MOD_BVALUES */
- switch (mop & 0x0f) {
- case LDAP_MOD_ADD:
- /* FIXME: should we try to track cases where we would end up
- * with multiple userPassword entries ?? */
- case LDAP_MOD_REPLACE:
- is_pwd_op = 1;
- bv = slapi_mod_get_first_value(smod);
- if (!bv) {
- slapi_mod_free(&tmod);
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- slapi_ch_free_string(&userpw);
- userpw = slapi_ch_malloc(bv->bv_len+1);
- if (!userpw) {
- slapi_mod_free(&tmod);
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- memcpy(userpw, bv->bv_val, bv->bv_len);
- userpw[bv->bv_len] = '\0';
- break;
- case LDAP_MOD_DELETE:
- /* reset only if we are deleting all values, or the exact
- * same value previously set, otherwise we are just trying to
- * add a new value and delete an existing one */
- bv = slapi_mod_get_first_value(smod);
- if (!bv) {
- is_pwd_op = 0;
- } else {
- if (0 == strncmp(userpw, bv->bv_val, bv->bv_len) ||
- 0 == strncmp(unhashedpw, bv->bv_val, bv->bv_len))
- is_pwd_op = 0;
- }
- default:
- break;
- }
- }
-
- if (slapi_attr_types_equivalent(type, SLAPI_ATTR_OBJECTCLASS)) {
- mop = slapi_mod_get_operation(smod);
- /* check op filtering out LDAP_MOD_BVALUES */
- switch (mop & 0x0f) {
- case LDAP_MOD_REPLACE:
- /* if objectclasses are replaced we need to start clean with
- * flags, so we sero them out and see if they get set again */
- is_krb = 0;
- is_smb = 0;
-
- case LDAP_MOD_ADD:
- bv = slapi_mod_get_first_value(smod);
- if (!bv) {
- slapi_mod_free(&tmod);
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- do {
- if (0 == strncasecmp("krbPrincipalAux", bv->bv_val, bv->bv_len))
- is_krb = 1;
- if (0 == strncasecmp("sambaSamAccount", bv->bv_val, bv->bv_len))
- is_smb = 1;
- } while ((bv = slapi_mod_get_next_value(smod)) != NULL);
-
- break;
-
- case LDAP_MOD_DELETE:
- /* can this happen for objectclasses ? */
- is_krb = 0;
- is_smb = 0;
-
- default:
- break;
- }
- }
-
- slapi_mod_done(tmod);
- smod = slapi_mods_get_next_smod(smods, tmod);
- }
- slapi_mod_free(&tmod);
-
- /* It seem like we have determined that the end result will be deletion of
- * the userPassword attribute, so we have no more business here */
- if (! is_pwd_op) {
- rc = LDAP_SUCCESS;
- goto done;
- }
-
- /* Check this is a clear text password, or refuse operation (only if we need
- * to comput other hashes */
- if (! unhashedpw) {
- if ('{' == userpw[0]) {
- if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
- unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
- if (NULL == unhashedpw) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "Strdup failed, Out of memory\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- slapi_ch_free_string(&userpw);
-
- } else if (slapi_is_encoded(userpw)) {
-
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Pre-Encoded passwords are not valid\n");
- errMesg = "Pre-Encoded passwords are not valid\n";
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
- }
- }
- }
-
- /* time to get the operation handler */
- ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "slapi_pblock_get failed!?\n");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- pwdop = slapi_get_object_extension(ipapwd_op_ext_list.object_type,
- op, ipapwd_op_ext_list.handle);
- if (NULL == pwdop) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- pwdop->pwd_op = IPAPWD_OP_MOD;
- pwdop->pwdata.password = slapi_ch_strdup(unhashedpw);
- pwdop->pwdata.changetype = IPA_CHANGETYPE_NORMAL;
-
- if (is_root) {
- pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
- } else {
- char *binddn;
- Slapi_DN *bdn, *tdn;
- int i;
-
- /* Check Bind DN */
- slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
- bdn = slapi_sdn_new_dn_byref(binddn);
- tdn = slapi_sdn_new_dn_byref(dn);
-
- /* if the change is performed by someone else,
- * it is an admin change that will require a new
- * password change immediately as per our IPA policy */
- if (slapi_sdn_compare(bdn, tdn)) {
- pwdop->pwdata.changetype = IPA_CHANGETYPE_ADMIN;
-
- /* if it is a passsync manager we also need to skip resets */
- for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
- if (strcasecmp(krbcfg->passsync_mgrs[i], binddn) == 0) {
- pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
- break;
- }
- }
-
- }
-
- slapi_sdn_free(&bdn);
- slapi_sdn_free(&tdn);
-
- }
-
- pwdop->pwdata.dn = slapi_ch_strdup(dn);
- pwdop->pwdata.timeNow = time(NULL);
- pwdop->pwdata.target = e;
-
- ret = ipapwd_CheckPolicy(&pwdop->pwdata);
- if (ret) {
- errMesg = "Password Fails to meet minimum strength criteria";
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
- }
-
- if (is_krb || is_smb) {
-
- Slapi_Value **svals = NULL;
- char *nt = NULL;
- char *lm = NULL;
-
- rc = ipapwd_preop_gen_hashes(krbcfg,
- pwdop, unhashedpw,
- is_krb, is_smb,
- &svals, &nt, &lm);
- if (rc) {
- goto done;
- }
-
- if (svals) {
- /* replace values */
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
- "krbPrincipalKey", svals);
- ipapwd_free_slapi_value_array(&svals);
- }
-
- if (lm) {
- /* replace value */
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "sambaLMPassword", lm);
- slapi_ch_free_string(&lm);
- }
- if (nt) {
- /* replace value */
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "sambaNTPassword", nt);
- slapi_ch_free_string(&nt);
- }
- }
-
- rc = LDAP_SUCCESS;
-
-done:
- free_ipapwd_krbcfg(&krbcfg);
- slapi_ch_free_string(&userpw); /* just to be sure */
- slapi_ch_free_string(&unhashedpw); /* we copied it to pwdop */
- if (e) slapi_entry_free(e); /* this is a copy in this function */
- if (pwdop) pwdop->pwdata.target = NULL;
-
- /* put back a, possibly modified, set of mods */
- if (smods) {
- mods = slapi_mods_get_ldapmods_passout(smods);
- slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
- slapi_mods_free(&smods);
- }
-
- if (rc != LDAP_SUCCESS) {
- slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
- return -1;
- }
-
- return 0;
-}
-
-static int ipapwd_post_op(Slapi_PBlock *pb)
-{
- char *errMesg = "Internal operations error\n";
- void *op;
- struct ipapwd_operation *pwdop = NULL;
- Slapi_Mods *smods;
- Slapi_Value **pwvals;
- struct tm utctime;
- char timestr[GENERALIZED_TIME_LENGTH+1];
- int ret;
-
- slapi_log_error(SLAPI_LOG_TRACE, IPAPWD_PLUGIN_NAME,
- "=> ipapwd_post_add\n");
-
- /* time to get the operation handler */
- ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
- "slapi_pblock_get failed!?\n");
- return 0;
- }
-
- pwdop = slapi_get_object_extension(ipapwd_op_ext_list.object_type,
- op, ipapwd_op_ext_list.handle);
- if (NULL == pwdop) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Internal error, couldn't find pluginextension ?!\n");
- return 0;
- }
-
- /* not interesting */
- if (IPAPWD_OP_NULL == pwdop->pwd_op)
- return 0;
-
- if ( ! (pwdop->is_krb)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Not a kerberos user, ignore krb attributes\n");
- return 0;
- }
-
- /* prepare changes that can be made only as root */
- smods = slapi_mods_new();
-
- /* change Last Password Change field with the current date */
- if (!gmtime_r(&(pwdop->pwdata.timeNow), &utctime)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "failed to parse current date (buggy gmtime_r ?)\n");
- goto done;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbLastPwdChange", timestr);
-
- /* set Password Expiration date */
- if (!gmtime_r(&(pwdop->pwdata.expireTime), &utctime)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "failed to parse expiration date (buggy gmtime_r ?)\n");
- goto done;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbPasswordExpiration", timestr);
-
- /* This was a mod operation on an existing entry, make sure we also update
- * the password history based on the entry we saved from the pre-op */
- if (IPAPWD_OP_MOD == pwdop->pwd_op) {
- Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(pwdop->pwdata.dn);
- if (tmp_dn) {
- ret = slapi_search_internal_get_entry(tmp_dn, 0,
- &pwdop->pwdata.target,
- ipapwd_plugin_id);
- slapi_sdn_free(&tmp_dn);
- if (ret != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Failed tpo retrieve entry?!?\n");
- goto done;
- }
- }
- pwvals = ipapwd_setPasswordHistory(smods, &pwdop->pwdata);
- if (pwvals) {
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
- "passwordHistory", pwvals);
- }
- }
-
- ret = ipapwd_apply_mods(pwdop->pwdata.dn, smods);
- if (ret)
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Failed to set additional password attributes in the post-op!\n");
-
-done:
- if (pwdop && pwdop->pwdata.target) slapi_entry_free(pwdop->pwdata.target);
- slapi_mods_free(&smods);
- return 0;
-}
-
-/* Copied from ipamo_string2filter()
- *
- * ipapwd_string2filter()
- *
- * For some reason slapi_str2filter writes to its input
- * which means you cannot pass in a string constant
- * so this is a fix up function for that
- */
-Slapi_Filter *ipapwd_string2filter(char *strfilter)
-{
- Slapi_Filter *ret = NULL;
- char *idontbelieveit = slapi_ch_strdup(strfilter);
-
- ret = slapi_str2filter(idontbelieveit);
-
- slapi_ch_free_string(&idontbelieveit);
-
- return ret;
-}
-
-/* Init data structs */
-static int ipapwd_start( Slapi_PBlock *pb )
-{
- krb5_context krbctx;
- krb5_error_code krberr;
- char *realm = NULL;
- char *config_dn;
- char *partition_dn;
- Slapi_Entry *config_entry = NULL;
- int ret;
-
- krberr = krb5_init_context(&krbctx);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipapwd_start", "krb5_init_context failed\n");
- return LDAP_OPERATIONS_ERROR;
- }
-
- if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &config_dn) != 0) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "No config DN?\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- if (ipapwd_getEntry(config_dn, &config_entry, NULL) != LDAP_SUCCESS) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "No config Entry?\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- partition_dn = slapi_entry_attr_get_charptr(config_entry, "nsslapd-realmtree");
- if (!partition_dn) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Missing partition configuration entry (nsslapd-realmTree)!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = krb5_get_default_realm(krbctx, &realm);
- if (ret) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Failed to get default realm?!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- ipa_realm_dn = slapi_ch_smprintf("cn=%s,cn=kerberos,%s", realm, partition_dn);
- if (!ipa_realm_dn) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Out of memory ?\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- ipa_pwd_config_dn = slapi_ch_strdup(config_dn);
- if (!ipa_pwd_config_dn) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Out of memory ?\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- ipa_changepw_principal_dn =
- slapi_ch_smprintf("krbprincipalname=kadmin/changepw@%s,%s",
- realm, ipa_realm_dn);
- if (!ipa_changepw_principal_dn) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Out of memory ?\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = LDAP_SUCCESS;
-
-done:
- free(realm);
- krb5_free_context(krbctx);
- if (config_entry) slapi_entry_free(config_entry);
- return ret;
-}
-
-
-static int ipapwd_ext_init()
-{
- int ret;
-
- ipapwd_op_ext_list.object_name = SLAPI_EXT_OPERATION;
-
- ret = slapi_register_object_extension(IPAPWD_PLUGIN_NAME,
- SLAPI_EXT_OPERATION,
- ipapwd_op_ext_constructor,
- ipapwd_op_ext_destructor,
- &ipapwd_op_ext_list.object_type,
- &ipapwd_op_ext_list.handle);
-
- return ret;
-}
-
-
-static char *ipapwd_oid_list[] = {
- EXOP_PASSWD_OID,
- KEYTAB_SET_OID,
- NULL
-};
-
-
-static char *ipapwd_name_list[] = {
- "Password Change Extended Operation",
- "Keytab Retrieval Extended Operation",
- NULL
-};
-
-/* Init pre ops */
-static int ipapwd_pre_init(Slapi_PBlock *pb)
-{
- int ret;
-
- ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void *)ipapwd_pre_add);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void *)ipapwd_pre_mod);
-
- return ret;
-}
-
-/* Init post ops */
-static int ipapwd_post_init(Slapi_PBlock *pb)
-{
- int ret;
-
- ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *)ipapwd_post_op);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *)ipapwd_post_op);
-
- return ret;
-}
-
-/* Initialization function */
-int ipapwd_init( Slapi_PBlock *pb )
-{
- int ret;
-
- /* Get the arguments appended to the plugin extendedop directive. The first argument
- * (after the standard arguments for the directive) should contain the OID of the
- * extended operation. */
-
- ret = slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipapwd_plugin_id);
- if ((ret != 0) || (NULL == ipapwd_plugin_id)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipapwd_init",
- "Could not get identity or identity was NULL\n");
- return -1;
- }
-
- if (ipapwd_ext_init() != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
- "Object Extension Operation failed\n");
- return -1;
- }
-
- /* Register the plug-in function as an extended operation
- * plug-in function that handles the operation identified by
- * OID 1.3.6.1.4.1.4203.1.11.1 . Also specify the version of the server
- * plug-in */
- ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *)ipapwd_start);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, ipapwd_oid_list);
- if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, ipapwd_name_list);
- if (!ret) slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)ipapwd_extop);
- if (ret) {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_init",
- "Failed to set plug-in version, function, and OID.\n" );
- return -1;
- }
-
- slapi_register_plugin("preoperation", 1,
- "ipapwd_pre_init", ipapwd_pre_init,
- "IPA pwd pre ops", NULL,
- ipapwd_plugin_id);
-
- slapi_register_plugin("postoperation", 1,
- "ipapwd_post_init", ipapwd_post_init,
- "IPA pwd post ops", NULL,
- ipapwd_plugin_id);
-
- return 0;
-}
diff --git a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif b/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif
deleted file mode 100644
index e31a8e79b..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif
+++ /dev/null
@@ -1,16 +0,0 @@
-dn: cn=ipa_pwd_extop,cn=plugins,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSlapdPlugin
-objectclass: extensibleObject
-cn: ipa_pwd_extop
-nsslapd-pluginpath: libipa_pwd_extop
-nsslapd-plugininitfunc: ipapwd_init
-nsslapd-plugintype: extendedop
-nsslapd-pluginenabled: on
-nsslapd-pluginid: ipa_pwd_extop
-nsslapd-pluginversion: 1.0
-nsslapd-pluginvendor: RedHat
-nsslapd-plugindescription: Support saving passwords in multiple formats for different consumers (krb5, samba, freeradius, etc.)
-nsslapd-plugin-depends-on-type: database
-nsslapd-realmTree: $SUFFIX
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am b/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am
deleted file mode 100644
index 94bc2dc68..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-NULL =
-
-INCLUDES = \
- -I. \
- -I$(srcdir) \
- -DPREFIX=\""$(prefix)"\" \
- -DBINDIR=\""$(bindir)"\" \
- -DLIBDIR=\""$(libdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- $(MOZLDAP_CFLAGS) \
- $(WARN_CFLAGS) \
- $(NULL)
-
-plugindir = $(libdir)/dirsrv/plugins
-plugin_LTLIBRARIES = \
- libipa_winsync.la \
- $(NULL)
-
-libipa_winsync_la_SOURCES = \
- ipa-winsync.c \
- ipa-winsync-config.c \
- $(NULL)
-
-libipa_winsync_la_LDFLAGS = -avoid-version
-
-#libipa_winsync_la_LIBADD = \
-# $(MOZLDAP_LIBS) \
-# $(NULL)
-
-appdir = $(IPA_DATA_DIR)
-app_DATA = \
- ipa-winsync-conf.ldif \
- $(NULL)
-
-EXTRA_DIST = \
- README \
- $(app_DATA) \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/README b/ipa-server/ipa-slapi-plugins/ipa-winsync/README
deleted file mode 100644
index e69de29bb..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/README
+++ /dev/null
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif
deleted file mode 100644
index 5b5c56acb..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif
+++ /dev/null
@@ -1,27 +0,0 @@
-dn: cn=ipa-winsync,cn=plugins,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSlapdPlugin
-objectclass: extensibleObject
-cn: ipa-winsync
-nsslapd-pluginpath: libipa_winsync
-nsslapd-plugininitfunc: ipa_winsync_plugin_init
-nsslapd-pluginDescription: Allows IPA to work with the DS windows sync feature
-nsslapd-pluginid: ipa-winsync
-nsslapd-pluginversion: 1.0
-nsslapd-pluginvendor: Red Hat
-nsslapd-plugintype: preoperation
-nsslapd-pluginenabled: on
-nsslapd-plugin-depends-on-type: database
-ipaWinSyncRealmFilter: (objectclass=krbRealmContainer)
-ipaWinSyncRealmAttr: cn
-ipaWinSyncNewEntryFilter: (cn=ipaConfig)
-ipaWinSyncNewUserOCAttr: ipauserobjectclasses
-ipaWinSyncUserFlatten: true
-ipaWinsyncHomeDirAttr: ipaHomesRootDir
-ipaWinSyncDefaultGroupAttr: ipaDefaultPrimaryGroup
-ipaWinSyncDefaultGroupFilter: (gidNumber=*)(objectclass=posixGroup)(objectclass=groupOfNames)
-ipaWinSyncAcctDisable: both
-ipaWinSyncInactivatedFilter: (&(cn=inactivated)(objectclass=groupOfNames))
-ipaWinSyncActivatedFilter: (&(cn=activated)(objectclass=groupOfNames))
-ipaWinSyncForceSync: true
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c
deleted file mode 100644
index 45efa6df0..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c
+++ /dev/null
@@ -1,975 +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.
- *
- * Authors:
- * Rich Megginson <rmeggins@redhat.com>
- *
- * Copyright (C) 2008 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * Windows Synchronization Plug-in for IPA
- * This plugin allows IPA to intercept operations sent from
- * Windows to the directory server and vice versa. This allows
- * IPA to intercept new users added to Windows and synced to the
- * directory server, and allows IPA to modify the entry, adding
- * objectclasses and attributes, and changing the DN.
- */
-
-#ifdef WINSYNC_TEST_IPA
-#include <slapi-plugin.h>
-#include "winsync-plugin.h"
-#else
-#include <dirsrv/slapi-plugin.h>
-#include <dirsrv/winsync-plugin.h>
-#endif
-#include "ipa-winsync.h"
-
-#include <string.h>
-
-#define IPA_WINSYNC_CONFIG_FILTER "(objectclass=*)"
-
-/*
- * function prototypes
- */
-static int ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg);
-static int ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg);
-static int ipa_winsync_search (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- return SLAPI_DSE_CALLBACK_OK;
-}
-
-/*
- * static variables
- */
-/* for now, there is only one configuration and it is global to the plugin */
-static IPA_WinSync_Config theConfig;
-static int inited = 0;
-
-static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- return SLAPI_DSE_CALLBACK_ERROR;
-}
-
-IPA_WinSync_Config *
-ipa_winsync_get_config()
-{
- return &theConfig;
-}
-
-/*
- * Read configuration and create a configuration data structure.
- * This is called after the server has configured itself so we can check
- * schema and whatnot.
- * Returns an LDAP error code (LDAP_SUCCESS if all goes well).
- */
-int
-ipa_winsync_config(Slapi_Entry *config_e)
-{
- int returncode = LDAP_SUCCESS;
- char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
-
- if ( inited ) {
- slapi_log_error( SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: IPA WinSync plug-in already configured. "
- "Please remove the plugin config entry [%s]\n",
- slapi_entry_get_dn_const(config_e));
- return( LDAP_PARAM_ERROR );
- }
-
- /* initialize fields */
- if ((theConfig.lock = slapi_new_mutex()) == NULL) {
- return( LDAP_LOCAL_ERROR );
- }
-
- /* init defaults */
- theConfig.config_e = slapi_entry_alloc();
- slapi_entry_init(theConfig.config_e, slapi_ch_strdup(""), NULL);
- theConfig.flatten = PR_TRUE;
-
- if (SLAPI_DSE_CALLBACK_OK == ipa_winsync_validate_config(NULL, NULL, config_e,
- &returncode, returntext, NULL)) {
- ipa_winsync_apply_config(NULL, NULL, config_e,
- &returncode, returntext, NULL);
- }
-
- /* config DSE must be initialized before we get here */
- if (returncode == LDAP_SUCCESS) {
- const char *config_dn = slapi_entry_get_dn_const(config_e);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE,
- IPA_WINSYNC_CONFIG_FILTER, ipa_winsync_validate_config,NULL);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, config_dn, LDAP_SCOPE_BASE,
- IPA_WINSYNC_CONFIG_FILTER, ipa_winsync_apply_config,NULL);
- slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE,
- IPA_WINSYNC_CONFIG_FILTER, dont_allow_that, NULL);
- slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE,
- IPA_WINSYNC_CONFIG_FILTER, dont_allow_that, NULL);
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE,
- IPA_WINSYNC_CONFIG_FILTER, ipa_winsync_search,NULL);
- }
-
- inited = 1;
-
- if (returncode != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error %d: %s\n", returncode, returntext);
- }
-
- return returncode;
-}
-
-static int
-parse_acct_disable(const char *theval)
-{
- int retval = ACCT_DISABLE_INVALID;
- if (!theval || !*theval) {
- return retval;
- }
- if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_NONE)) {
- retval = ACCT_DISABLE_NONE;
- } else if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_TO_AD)) {
- retval = ACCT_DISABLE_TO_AD;
- } else if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_TO_DS)) {
- retval = ACCT_DISABLE_TO_DS;
- } else if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_BOTH)) {
- retval = ACCT_DISABLE_BOTH;
- }
-
- return retval;
-}
-
-/*
- Validate the pending changes in the e entry.
-*/
-static int
-ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
- int *returncode, char *returntext, void *arg)
-{
- char **attrsvals = NULL;
- int ii;
- Slapi_Attr *testattr = NULL;
- char *strattr = NULL;
- int acct_disable;
-
- *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */
-
- /* get realm filter */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_FILTER_ATTR, &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_REALM_FILTER_ATTR);
- goto done2;
- }
-
- /* get realm attr */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_ATTR_ATTR, &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_REALM_ATTR_ATTR);
- goto done2;
- }
-
- /* get new_entry_filter */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR);
- goto done2;
- }
-
- /* get new_user_oc_attr */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_USER_OC_ATTR,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_NEW_USER_OC_ATTR);
- goto done2;
- }
-
- /* get homedir_prefix_attr */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_HOMEDIR_PREFIX_ATTR);
- goto done2;
- }
-
- /* get default_group_attr */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_ATTR,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_DEFAULTGROUP_ATTR);
- goto done2;
- }
-
- /* get default_group_filter */
- if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR);
- goto done2;
- }
-
- /* get the list of attributes & values */
- /* get new_user_oc_attr */
- if (!(attrsvals = slapi_entry_attr_get_charray(
- e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPA_WINSYNC_PLUGIN_NAME,
- "Info: no default attributes and values given in [%s]\n",
- IPA_WINSYNC_NEW_USER_ATTRS_VALS);
- }
-
- /* format of *attrsvals is "attrname value" */
- /* attrname <space> value */
- /* value may contain spaces - attrname is everything up to the first
- space - value is everything after the first space */
- for (ii = 0; attrsvals && attrsvals[ii]; ++ii) {
- Slapi_Attr *attr = NULL;
- char *oidp = NULL;
- char *val = strchr(attrsvals[ii], ' ');
- if (!val || !*(val+1)) { /* incorrect format or no value */
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value or incorrect value given for [%s] "
- "value [%s] index [%d] - correct format is attrname SPACE value",
- IPA_WINSYNC_NEW_USER_ATTRS_VALS,
- attrsvals[ii], ii);
- goto done2;
- }
- *val = '\0'; /* separate attr from val */
- /* check to make sure attribute is in the schema */
- attr = slapi_attr_new();
- slapi_attr_set_type(attr, attrsvals[ii]);
- slapi_attr_get_oid_copy(attr, &oidp);
- slapi_attr_free(&attr);
- if (oidp == NULL) { /* no such attribute */
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: invalid attribute name [%s] given for [%s] "
- "at index [%d] - attribute is not in server schema",
- attrsvals[ii], IPA_WINSYNC_NEW_USER_ATTRS_VALS,
- ii);
- goto done2;
- }
-
- /* attribute is valid - continue */
- slapi_ch_free_string(&oidp);
- }
-
- /* get account disable sync direction */
- if (!(strattr = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_ACCT_DISABLE))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_ACCT_DISABLE);
- goto done2;
- }
-
- acct_disable = parse_acct_disable(strattr);
- if (ACCT_DISABLE_INVALID == acct_disable) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: invalid value [%s] given for [%s] - valid "
- "values are " IPA_WINSYNC_ACCT_DISABLE_NONE
- ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD
- ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS
- ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH,
- strattr, IPA_WINSYNC_ACCT_DISABLE);
- goto done2;
- }
-
- /* if using acct disable sync, must have the attributes
- IPA_WINSYNC_INACTIVATED_FILTER and IPA_WINSYNC_ACTIVATED_FILTER
- */
- if (acct_disable != ACCT_DISABLE_NONE) {
- if (slapi_entry_attr_find(e, IPA_WINSYNC_INACTIVATED_FILTER,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s - "
- "required for account disable sync",
- IPA_WINSYNC_INACTIVATED_FILTER);
- goto done2;
- }
- if (slapi_entry_attr_find(e, IPA_WINSYNC_ACTIVATED_FILTER,
- &testattr) ||
- (NULL == testattr)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s - "
- "required for account disable sync",
- IPA_WINSYNC_ACTIVATED_FILTER);
- goto done2;
- }
- }
-
- /* success */
- *returncode = LDAP_SUCCESS;
-
-done2:
- slapi_ch_free_string(&strattr);
- slapi_ch_array_free(attrsvals);
- attrsvals = NULL;
-
- if (*returncode != LDAP_SUCCESS) {
- return SLAPI_DSE_CALLBACK_ERROR;
- } else {
- return SLAPI_DSE_CALLBACK_OK;
- }
-}
-
-static int
-ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
- Slapi_Entry* e, int *returncode, char *returntext,
- void *arg)
-{
- PRBool flatten = PR_TRUE;
- char *realm_filter = NULL;
- char *realm_attr = NULL;
- char *new_entry_filter = NULL;
- char *new_user_oc_attr = NULL; /* don't care about groups for now */
- char *homedir_prefix_attr = NULL;
- char *default_group_attr = NULL;
- char *default_group_filter = NULL;
- char *acct_disable = NULL;
- int acct_disable_int;
- char *inactivated_filter = NULL;
- char *activated_filter = NULL;
- char **attrsvals = NULL;
- int ii;
- Slapi_Attr *testattr = NULL;
- PRBool forceSync = PR_FALSE;
-
- *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */
-
- /* get flatten value */
- if (!slapi_entry_attr_find(e, IPA_WINSYNC_USER_FLATTEN, &testattr) &&
- (NULL != testattr)) {
- flatten = slapi_entry_attr_get_bool(e, IPA_WINSYNC_USER_FLATTEN);
- }
-
- /* get realm filter */
- if (!(realm_filter = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_REALM_FILTER_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_REALM_FILTER_ATTR);
- goto done3;
- }
-
- /* get realm attr */
- if (!(realm_attr = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_REALM_ATTR_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_REALM_ATTR_ATTR);
- goto done3;
- }
-
- /* get new_entry_filter */
- if (!(new_entry_filter = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR);
- goto done3;
- }
-
- /* get new_user_oc_attr */
- if (!(new_user_oc_attr = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_NEW_USER_OC_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_NEW_USER_OC_ATTR);
- goto done3;
- }
-
- /* get homedir_prefix_attr */
- if (!(homedir_prefix_attr = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_HOMEDIR_PREFIX_ATTR);
- goto done3;
- }
-
- /* get default_group_attr */
- if (!(default_group_attr = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_DEFAULTGROUP_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_DEFAULTGROUP_ATTR);
- goto done3;
- }
-
- /* get default_group_filter */
- if (!(default_group_filter = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR);
- goto done3;
- }
-
- /* get the list of attributes & values */
- /* get new_user_oc_attr */
- if (!(attrsvals = slapi_entry_attr_get_charray(
- e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) {
- slapi_log_error(SLAPI_LOG_PLUGIN, IPA_WINSYNC_PLUGIN_NAME,
- "Info: no default attributes and values given in [%s]\n",
- IPA_WINSYNC_NEW_USER_ATTRS_VALS);
- }
-
- /* get acct disable sync value */
- if (!(acct_disable = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_ACCT_DISABLE))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s",
- IPA_WINSYNC_ACCT_DISABLE);
- goto done3;
- }
-
- acct_disable_int = parse_acct_disable(acct_disable);
- if (ACCT_DISABLE_INVALID == acct_disable_int) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: invalid value [%s] given for [%s] - valid "
- "values are " IPA_WINSYNC_ACCT_DISABLE_NONE
- ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD
- ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS
- ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH,
- acct_disable, IPA_WINSYNC_ACCT_DISABLE);
- goto done3;
- }
-
- if (acct_disable_int != ACCT_DISABLE_NONE) {
- /* get inactivated group filter */
- if (!(inactivated_filter = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_INACTIVATED_FILTER))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s - required for account disable sync",
- IPA_WINSYNC_INACTIVATED_FILTER);
- goto done3;
- }
- /* get activated group filter */
- if (!(activated_filter = slapi_entry_attr_get_charptr(
- e, IPA_WINSYNC_ACTIVATED_FILTER))) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value given for %s - required for account disable sync",
- IPA_WINSYNC_ACTIVATED_FILTER);
- goto done3;
- }
- }
-
- /* get forceSync value */
- if (!slapi_entry_attr_find(e, IPA_WINSYNC_FORCE_SYNC, &testattr) &&
- (NULL != testattr)) {
- forceSync = slapi_entry_attr_get_bool(e, IPA_WINSYNC_FORCE_SYNC);
- }
-
- /* if we got here, we have valid values for everything
- set the config entry */
- slapi_lock_mutex(theConfig.lock);
- slapi_entry_free(theConfig.config_e);
- theConfig.config_e = slapi_entry_alloc();
- slapi_entry_init(theConfig.config_e, slapi_ch_strdup(""), NULL);
-
- /* format of *attrsvals is "attrname value" */
- /* attrname <space> value */
- /* value may contain spaces - attrname is everything up to the first
- space - value is everything after the first space */
- for (ii = 0; attrsvals && attrsvals[ii]; ++ii) {
- int rc;
- Slapi_Value *sva[2];
- Slapi_Value *sv = NULL;
- char *val = strchr(attrsvals[ii], ' ');
- if (!val || !*(val+1)) { /* incorrect format or no value */
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: no value or incorrect value given for [%s] "
- "value [%s] index [%d] - correct format is attrname SPACE value",
- IPA_WINSYNC_NEW_USER_ATTRS_VALS,
- attrsvals[ii], ii);
- goto done3;
- }
- *val++ = '\0'; /* separate attr from val */
- sv = slapi_value_new_string(val);
- sva[0] = sv;
- sva[1] = NULL;
- if ((rc = slapi_entry_add_values_sv(theConfig.config_e,
- attrsvals[ii], sva)) &&
- (rc != LDAP_SUCCESS)) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Error: could not add value [%s] for attribute name "
- "[%s] - ldap error [%d: %s]", val, attrsvals[ii],
- attrsvals[ii], IPA_WINSYNC_NEW_USER_ATTRS_VALS,
- rc, ldap_err2string(rc));
- slapi_entry_free(theConfig.config_e);
- theConfig.config_e = NULL;
- slapi_value_free(&sv);
- goto done3;
- }
- slapi_value_free(&sv);
- }
-
- /* all of the attrs and vals have been set - set the other values */
- slapi_ch_free_string(&theConfig.realm_filter);
- theConfig.realm_filter = realm_filter;
- realm_filter = NULL;
- slapi_ch_free_string(&theConfig.realm_attr);
- theConfig.realm_attr = realm_attr;
- realm_attr = NULL;
- slapi_ch_free_string(&theConfig.new_entry_filter);
- theConfig.new_entry_filter = new_entry_filter;
- new_entry_filter = NULL;
- slapi_ch_free_string(&theConfig.new_user_oc_attr);
- theConfig.new_user_oc_attr = new_user_oc_attr;
- new_user_oc_attr = NULL;
- slapi_ch_free_string(&theConfig.homedir_prefix_attr);
- theConfig.homedir_prefix_attr = homedir_prefix_attr;
- homedir_prefix_attr = NULL;
- slapi_ch_free_string(&theConfig.default_group_attr);
- theConfig.default_group_attr = default_group_attr;
- default_group_attr = NULL;
- slapi_ch_free_string(&theConfig.default_group_filter);
- theConfig.default_group_filter = default_group_filter;
- default_group_filter = NULL;
- theConfig.flatten = flatten;
- theConfig.acct_disable = parse_acct_disable(acct_disable);
- slapi_ch_free_string(&theConfig.inactivated_filter);
- theConfig.inactivated_filter = inactivated_filter;
- inactivated_filter = NULL;
- slapi_ch_free_string(&theConfig.activated_filter);
- theConfig.activated_filter = activated_filter;
- activated_filter = NULL;
- theConfig.forceSync = forceSync;
-
- /* success */
- *returncode = LDAP_SUCCESS;
-
-done3:
- slapi_unlock_mutex(theConfig.lock);
-
- slapi_ch_free_string(&realm_filter);
- slapi_ch_free_string(&realm_attr);
- slapi_ch_free_string(&new_entry_filter);
- slapi_ch_free_string(&new_user_oc_attr);
- slapi_ch_free_string(&homedir_prefix_attr);
- slapi_ch_free_string(&default_group_attr);
- slapi_ch_free_string(&default_group_filter);
- slapi_ch_array_free(attrsvals);
- attrsvals = NULL;
- slapi_ch_free_string(&acct_disable);
- slapi_ch_free_string(&inactivated_filter);
- slapi_ch_free_string(&activated_filter);
-
- if (*returncode != LDAP_SUCCESS) {
- return SLAPI_DSE_CALLBACK_ERROR;
- } else {
- return SLAPI_DSE_CALLBACK_OK;
- }
-}
-
-/* create per-domain config object */
-void *
-ipa_winsync_config_new_domain(
- const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree
-)
-{
- IPA_WinSync_Domain_Config *iwdc =
- (IPA_WinSync_Domain_Config *)
- slapi_ch_calloc(1, sizeof(IPA_WinSync_Domain_Config));
-
- return (void *)iwdc;
-}
-
-/* destroy per-domain config object */
-void
-ipa_winsync_config_destroy_domain(
- void *cbdata, const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree
-)
-{
- IPA_WinSync_Domain_Config *iwdc =
- (IPA_WinSync_Domain_Config *)cbdata;
- slapi_entry_free(iwdc->domain_e);
- iwdc->domain_e = NULL;
- slapi_ch_free_string(&iwdc->realm_name);
- slapi_ch_free_string(&iwdc->homedir_prefix);
- slapi_ch_free_string(&iwdc->inactivated_group_dn);
- slapi_ch_free_string(&iwdc->activated_group_dn);
- slapi_ch_free((void **)&iwdc);
-
- return;
-}
-
-/*
- return the value(s) of the given attribute in the entry that
- matches the given criteria. The criteria must match one
- and only one entry.
- Returns:
- -1 - problem doing internal search
- LDAP_UNWILLING_TO_PERFORM - more than one matching entry
- LDAP_NO_SUCH_OBJECT - no entry found that matched
- 0 and attrval == NULL - entry found but no attribute
- other ldap error - error doing search for given basedn
-*/
-static int
-internal_find_entry_get_attr_val(const Slapi_DN *basedn, int scope,
- const char *filter, const char *attrname,
- Slapi_ValueSet **svs, char **attrval)
-{
- Slapi_Entry **entries = NULL;
- Slapi_PBlock *pb = NULL;
- const char *search_basedn = slapi_sdn_get_dn(basedn);
- int search_scope = scope;
- int ret = LDAP_SUCCESS;
- const char *attrs[2] = {attrname, NULL};
-
- if (svs) {
- *svs = NULL;
- }
- if (attrval) {
- *attrval = NULL;
- }
- pb = slapi_pblock_new();
- slapi_search_internal_set_pb(pb, search_basedn, search_scope, filter,
- (char **)attrs, 0, NULL, NULL,
- ipa_winsync_get_plugin_identity(), 0);
- slapi_search_internal_pb(pb);
-
- /* This search may return no entries, but should never
- return an error
- */
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
- if (ret != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error [%d:%s] searching for base [%s] filter [%s]"
- " attr [%s]\n", ret, ldap_err2string(ret),
- search_basedn, filter, attrs[0]);
- goto out1;
- }
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (entries && entries[0] && entries[1]) {
- /* error - should never be more than one matching entry */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: more than one entry matches search for "
- "base [%s] filter [%s] attr [%s]\n",
- search_basedn, filter, attrs[0]);
- ret = LDAP_UNWILLING_TO_PERFORM;
- goto out1;
- }
-
- if (entries && entries[0]) { /* found one */
- if (svs) {
- Slapi_Attr *attr = NULL;
- slapi_entry_attr_find(entries[0], attrname, &attr);
- if (attr) {
- /* slapi_attr_get_valueset allocates svs - must be freed later */
- slapi_attr_get_valueset(attr, svs);
- }
- }
- if (attrval) {
- if (!strcmp(attrname, "dn")) { /* special - to just get the DN */
- *attrval = slapi_ch_strdup(slapi_entry_get_dn_const(entries[0]));
- } else {
- *attrval = slapi_entry_attr_get_charptr(entries[0], attrname);
- }
- }
- } else {
- ret = LDAP_NO_SUCH_OBJECT;
- slapi_log_error(SLAPI_LOG_PLUGIN, IPA_WINSYNC_PLUGIN_NAME,
- "Did not find an entry for search "
- "base [%s] filter [%s] attr [%s]\n",
- search_basedn, filter, attrs[0]);
- }
-
-out1:
- if (pb) {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- pb = NULL;
- }
-
- return ret;
-}
-
-/*
- * Perform the agreement/domain specific configuration.
- * IPA stores its configuration in the tree. We use the
- * ds_subtree to search for the domain/realm specific
- * configuration entries.
- */
-void
-ipa_winsync_config_refresh_domain(
- void *cbdata, const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree
-)
-{
- IPA_WinSync_Domain_Config *iwdc =
- (IPA_WinSync_Domain_Config *)cbdata;
- Slapi_DN *config_dn = slapi_sdn_dup(ds_subtree);
- char *realm_filter = NULL;
- char *realm_attr = NULL;
- char *new_entry_filter = NULL;
- char *new_user_oc_attr = NULL; /* don't care about groups for now */
- char *homedir_prefix_attr = NULL;
- char *default_group_attr = NULL;
- char *default_group_filter = NULL;
- char *default_group_name = NULL;
- char *real_group_filter = NULL;
- char *default_gid = NULL;
- Slapi_ValueSet *new_user_objclasses = NULL; /* don't care about groups for now */
- int loopdone = 0;
- int search_scope = LDAP_SCOPE_SUBTREE;
- int ret = LDAP_SUCCESS;
- Slapi_Value *sv = NULL;
- int acct_disable;
- char *inactivated_filter = NULL;
- char *activated_filter = NULL;
- char *inactivated_group_dn = NULL;
- char *activated_group_dn = NULL;
-
- slapi_lock_mutex(theConfig.lock);
- realm_filter = slapi_ch_strdup(theConfig.realm_filter);
- realm_attr = slapi_ch_strdup(theConfig.realm_attr);
- new_entry_filter = slapi_ch_strdup(theConfig.new_entry_filter);
- new_user_oc_attr = slapi_ch_strdup(theConfig.new_user_oc_attr);
- homedir_prefix_attr = slapi_ch_strdup(theConfig.homedir_prefix_attr);
- default_group_attr = slapi_ch_strdup(theConfig.default_group_attr);
- default_group_filter = slapi_ch_strdup(theConfig.default_group_filter);
- acct_disable = theConfig.acct_disable;
- if (acct_disable != ACCT_DISABLE_NONE) {
- inactivated_filter = slapi_ch_strdup(theConfig.inactivated_filter);
- activated_filter = slapi_ch_strdup(theConfig.activated_filter);
- }
- slapi_unlock_mutex(theConfig.lock);
-
- /* starting at ds_subtree, search for the entry
- containing the Kerberos realm to use */
- slapi_ch_free_string(&iwdc->realm_name);
- while(!loopdone && !slapi_sdn_isempty(config_dn)) {
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- realm_filter, realm_attr,
- NULL, &iwdc->realm_name);
-
- if ((0 == ret) && iwdc->realm_name) {
- loopdone = 1;
- } else if ((LDAP_NO_SUCH_OBJECT == ret) && !iwdc->realm_name) {
- /* try again */
- Slapi_DN *parent_dn = slapi_sdn_new();
- slapi_sdn_get_parent(config_dn, parent_dn);
- slapi_sdn_free(&config_dn);
- config_dn = parent_dn;
- } else { /* error */
- goto out;
- }
- }
-
- if (!iwdc->realm_name) {
- /* error - could not find the IPA config entry with the realm name */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the entry containing the realm name for "
- "ds subtree [%s] filter [%s] attr [%s]\n",
- slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr);
- goto out;
- }
-
- /* look for the entry containing the default objectclasses
- to add to new entries */
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- new_entry_filter, new_user_oc_attr,
- &new_user_objclasses, NULL);
- if (!new_user_objclasses) {
- /* error - could not find the entry containing list of objectclasses */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the entry containing the new user objectclass list for "
- "ds subtree [%s] filter [%s] attr [%s]\n",
- slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr);
- goto out;
- }
-
- /* get the home directory prefix value */
- /* note - this is in the same entry as the new entry template, so
- use the same filter */
- slapi_ch_free_string(&iwdc->homedir_prefix);
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- new_entry_filter, homedir_prefix_attr,
- NULL, &iwdc->homedir_prefix);
- if (!iwdc->homedir_prefix) {
- /* error - could not find the home dir prefix */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the entry containing the home directory prefix for "
- "ds subtree [%s] filter [%s] attr [%s]\n",
- slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr);
- goto out;
- }
-
- /* find the default group - the entry above contains the group name, but
- we need the gidNumber for posixAccount - so first find the entry
- and attr value which has the group name, then lookup the group
- number from the group name */
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- new_entry_filter, default_group_attr,
- NULL, &default_group_name);
- if (!default_group_name) {
- /* error - could not find the default group name */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the entry containing the default group name for "
- "ds subtree [%s] filter [%s] attr [%s]\n",
- slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr);
- goto out;
- }
-
- /* next, find the group whose name is default_group_name - construct the filter
- based on the filter attribute value - assumes the group name is stored
- in the cn attribute value, and the gidNumber in the gidNumber attribute value */
- real_group_filter = slapi_ch_smprintf("(&(cn=%s)%s)", default_group_name,
- default_group_filter);
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- real_group_filter, "gidNumber",
- NULL, &default_gid);
- if (!default_gid) {
- /* error - could not find the default gidNumber */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the entry containing the default gidNumber "
- "ds subtree [%s] filter [%s] attr [%s]\n",
- slapi_sdn_get_dn(ds_subtree), new_entry_filter, "gidNumber");
- goto out;
- }
-
- /* If we are syncing account disable, we need to find the groups used
- to denote active and inactive users e.g.
- dn: cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX
-
- dn: cn=Activated,cn=Account Inactivation,cn=accounts,$SUFFIX
-
- */
- if (acct_disable != ACCT_DISABLE_NONE) {
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- inactivated_filter, "dn",
- NULL, &inactivated_group_dn);
- if (!inactivated_group_dn) {
- /* error - could not find the inactivated group dn */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the DN of the inactivated users group "
- "ds subtree [%s] filter [%s]\n",
- slapi_sdn_get_dn(ds_subtree), inactivated_filter);
- goto out;
- }
- ret = internal_find_entry_get_attr_val(config_dn, search_scope,
- activated_filter, "dn",
- NULL, &activated_group_dn);
- if (!activated_group_dn) {
- /* error - could not find the activated group dn */
- slapi_log_error(SLAPI_LOG_FATAL, IPA_WINSYNC_PLUGIN_NAME,
- "Error: could not find the DN of the activated users group "
- "ds subtree [%s] filter [%s]\n",
- slapi_sdn_get_dn(ds_subtree), activated_filter);
- goto out;
- }
- }
-
- /* ok, we have our values */
- /* first, clear out the old domain config */
- slapi_entry_free(iwdc->domain_e);
- iwdc->domain_e = NULL;
-
- /* next, copy the global attr config */
- slapi_lock_mutex(theConfig.lock);
- iwdc->domain_e = slapi_entry_dup(theConfig.config_e);
- slapi_unlock_mutex(theConfig.lock);
-
- /* set the objectclasses in the domain_e */
- slapi_entry_attr_delete(iwdc->domain_e, "objectclass");
- /* this copies new_user_objclasses */
- slapi_entry_add_valueset(iwdc->domain_e, "objectclass", new_user_objclasses);
-
- /* set the default gid number */
- sv = slapi_value_new_string_passin(default_gid);
- default_gid = NULL; /* passin owns the memory */
- if (!slapi_entry_attr_has_syntax_value(iwdc->domain_e, "gidNumber", sv)) {
- slapi_entry_add_value(iwdc->domain_e, "gidNumber", sv);
- }
- slapi_value_free(&sv);
-
- slapi_ch_free_string(&iwdc->inactivated_group_dn);
- iwdc->inactivated_group_dn = inactivated_group_dn;
- inactivated_group_dn = NULL;
- slapi_ch_free_string(&iwdc->activated_group_dn);
- iwdc->activated_group_dn = activated_group_dn;
- activated_group_dn = NULL;
-
-out:
- slapi_valueset_free(new_user_objclasses);
- slapi_sdn_free(&config_dn);
- slapi_ch_free_string(&realm_filter);
- slapi_ch_free_string(&realm_attr);
- slapi_ch_free_string(&new_entry_filter);
- slapi_ch_free_string(&new_user_oc_attr);
- slapi_ch_free_string(&homedir_prefix_attr);
- slapi_ch_free_string(&default_group_attr);
- slapi_ch_free_string(&default_group_filter);
- slapi_ch_free_string(&default_group_name);
- slapi_ch_free_string(&real_group_filter);
- slapi_ch_free_string(&default_gid);
- slapi_ch_free_string(&inactivated_filter);
- slapi_ch_free_string(&inactivated_group_dn);
- slapi_ch_free_string(&activated_filter);
- slapi_ch_free_string(&activated_group_dn);
-
- if (LDAP_SUCCESS != ret) {
- slapi_ch_free_string(&iwdc->realm_name);
- slapi_ch_free_string(&iwdc->homedir_prefix);
- slapi_entry_free(iwdc->domain_e);
- iwdc->domain_e = NULL;
- }
-
- return;
-}
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c
deleted file mode 100644
index 9ee8805bb..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c
+++ /dev/null
@@ -1,1177 +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.
- *
- * Authors:
- * Rich Megginson <rmeggins@redhat.com>
- *
- * Copyright (C) 2008 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * Windows Synchronization Plug-in for IPA
- * This plugin allows IPA to intercept operations sent from
- * Windows to the directory server and vice versa. This allows
- * IPA to intercept new users added to Windows and synced to the
- * directory server, and allows IPA to modify the entry, adding
- * objectclasses and attributes, and changing the DN.
- */
-
-#ifdef WINSYNC_TEST_IPA
-#include <slapi-plugin.h>
-#include "winsync-plugin.h"
-#else
-#include <dirsrv/slapi-plugin.h>
-#include <dirsrv/winsync-plugin.h>
-#endif
-#include "ipa-winsync.h"
-
-static char *ipa_winsync_plugin_name = IPA_WINSYNC_PLUGIN_NAME;
-
-static void
-sync_acct_disable(
- void *cbdata, /* the usual domain config data */
- const Slapi_Entry *ad_entry, /* the AD entry */
- Slapi_Entry *ds_entry, /* the DS entry */
- int direction, /* the direction - TO_AD or TO_DS */
- Slapi_Entry *update_entry, /* the entry to update for ADDs */
- Slapi_Mods *smods, /* the mod list for MODIFYs */
- int *do_modify /* set to true if mods were applied */
-);
-
-static void
-do_force_sync(
- const Slapi_Entry *ad_entry, /* the AD entry */
- Slapi_Entry *ds_entry, /* the DS entry */
- Slapi_Mods *smods, /* the mod list */
- int *do_modify /* set to true if mods were applied */
-);
-
-/* This is called when a new agreement is created or loaded
- at startup.
-*/
-static void *
-ipa_winsync_agmt_init(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree)
-{
- void *cbdata = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_agmt_init [%s] [%s] -- begin\n",
- slapi_sdn_get_dn(ds_subtree),
- slapi_sdn_get_dn(ad_subtree));
-
- /* do the domain specific configuration based on the ds subtree */
- cbdata = ipa_winsync_config_new_domain(ds_subtree, ad_subtree);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_agmt_init -- end\n");
-
- return cbdata;
-}
-
-static void
-ipa_winsync_dirsync_search_params_cb(void *cbdata, const char *agmt_dn,
- char **base, int *scope, char **filter,
- char ***attrs, LDAPControl ***serverctrls)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_dirsync_search_params_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_dirsync_search_params_cb -- end\n");
-
- return;
-}
-
-/* called before searching for a single entry from AD - agmt_dn will be NULL */
-static void
-ipa_winsync_pre_ad_search_cb(void *cbdata, const char *agmt_dn,
- char **base, int *scope, char **filter,
- char ***attrs, LDAPControl ***serverctrls)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ad_search_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ad_search_cb -- end\n");
-
- return;
-}
-
-/* called before an internal search to get a single DS entry - agmt_dn will be NULL */
-static void
-ipa_winsync_pre_ds_search_entry_cb(void *cbdata, const char *agmt_dn,
- char **base, int *scope, char **filter,
- char ***attrs, LDAPControl ***serverctrls)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_search_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "-- ipa_winsync_pre_ds_search_cb - base [%s] "
- "scope [%d] filter [%s]\n",
- *base, *scope, *filter);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_search_cb -- end\n");
-
- return;
-}
-
-/* called before the total update to get all entries from the DS to sync to AD */
-static void
-ipa_winsync_pre_ds_search_all_cb(void *cbdata, const char *agmt_dn,
- char **base, int *scope, char **filter,
- char ***attrs, LDAPControl ***serverctrls)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_search_all_cb -- orig filter [%s] -- begin\n",
- ((filter && *filter) ? *filter : "NULL"));
-
- /* We only want to grab users from the ds side - no groups */
- slapi_ch_free_string(filter);
- /* maybe use ntUniqueId=* - only get users that have already been
- synced with AD - ntUniqueId and ntUserDomainId are
- indexed for equality only - need to add presence? */
- *filter = slapi_ch_strdup("(&(objectclass=ntuser)(ntUserDomainId=*))");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_search_all_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ad_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
- Slapi_Mods *smods, int *do_modify)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ad_mod_user_cb -- begin\n");
-
- sync_acct_disable(cbdata, rawentry, ds_entry, ACCT_DISABLE_TO_AD,
- NULL, smods, do_modify);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ad_mod_user_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ad_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
- Slapi_Mods *smods, int *do_modify)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ad_mod_group_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ad_mod_group_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
- Slapi_Mods *smods, int *do_modify)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_mod_user_cb -- begin\n");
-
- sync_acct_disable(cbdata, rawentry, ds_entry, ACCT_DISABLE_TO_DS,
- NULL, smods, do_modify);
-
- do_force_sync(rawentry, ds_entry, smods, do_modify);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_mod_user_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ds_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
- Slapi_Mods *smods, int *do_modify)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_mod_group_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_mod_group_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
-{
- IPA_WinSync_Domain_Config *ipaconfig = (IPA_WinSync_Domain_Config *)cbdata;
- Slapi_Attr *attr = NULL;
- Slapi_Attr *e_attr = NULL;
- char *type = NULL;
- IPA_WinSync_Config *global_ipaconfig = ipa_winsync_get_config();
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_add_user_cb -- begin\n");
-
- if (!ipaconfig || !ipaconfig->domain_e || !ipaconfig->realm_name ||
- !ipaconfig->homedir_prefix) {
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "Error: configuration failure: cannot map Windows "
- "entry dn [%s], DS entry dn [%s]\n",
- slapi_entry_get_dn_const(ad_entry),
- slapi_entry_get_dn_const(ds_entry));
- return;
- }
-
- /* add the objectclasses and attributes to the entry */
- for (slapi_entry_first_attr(ipaconfig->domain_e, &attr); attr;
- slapi_entry_next_attr(ipaconfig->domain_e, attr, &attr))
- {
- slapi_attr_get_type(attr, &type);
- if (!type) {
- continue; /* should never happen */
- }
-
- if (!slapi_entry_attr_find(ds_entry, type, &e_attr) && e_attr) {
- /* already has attribute - add missing values */
- Slapi_Value *sv = NULL;
- int ii = 0;
- for (ii = slapi_attr_first_value(attr, &sv); ii != -1;
- ii = slapi_attr_next_value(attr, ii, &sv))
- {
- if (!slapi_entry_attr_has_syntax_value(ds_entry, type, sv)) {
- /* attr-value sv not found in ds_entry; add it */
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_add_user_cb -- "
- "adding val for [%s] to new entry [%s]\n",
- type, slapi_entry_get_dn_const(ds_entry));
-
- slapi_entry_add_value(ds_entry, type, sv);
- }
- }
- } else { /* attr not found */
- Slapi_ValueSet *svs = NULL;
- slapi_attr_get_valueset(attr, &svs); /* makes a copy */
- slapi_entry_add_valueset(ds_entry, type, svs);
- slapi_valueset_free(svs); /* free the copy */
- }
- }
-
- /* add other attributes */
- type = "krbPrincipalName";
- if (slapi_entry_attr_find(ds_entry, type, &e_attr) || !e_attr) {
- char *upn = NULL;
- char *uid = NULL;
- char *samAccountName = NULL;
- /* if the ds_entry already has a uid, use that */
- if ((uid = slapi_entry_attr_get_charptr(ds_entry, "uid"))) {
- upn = slapi_ch_smprintf("%s@%s", uid, ipaconfig->realm_name);
- slapi_ch_free_string(&uid);
- /* otherwise, use the samAccountName from the ad_entry */
- } else if ((samAccountName =
- slapi_entry_attr_get_charptr(ad_entry, "samAccountName"))) {
- upn = slapi_ch_smprintf("%s@%s", samAccountName, ipaconfig->realm_name);
- slapi_ch_free_string(&samAccountName);
- } else { /* fatal error - nothing to use for krbPrincipalName */
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "Error creating %s for realm [%s] for Windows "
- "entry dn [%s], DS entry dn [%s] - Windows entry "
- "has no samAccountName, and DS entry has no uid.\n",
- type, ipaconfig->realm_name,
- slapi_entry_get_dn_const(ad_entry),
- slapi_entry_get_dn_const(ds_entry));
- }
-
- if (upn) {
- slapi_entry_attr_set_charptr(ds_entry, type, upn);
- slapi_ch_free_string(&upn);
- }
- }
-
- type = "homeDirectory";
- if (slapi_entry_attr_find(ds_entry, type, &e_attr) || !e_attr) {
- char *homeDir = NULL;
- char *uid = NULL;
- char *samAccountName = NULL;
- /* if the ds_entry already has a uid, use that */
- if ((uid = slapi_entry_attr_get_charptr(ds_entry, "uid"))) {
- homeDir = slapi_ch_smprintf("%s/%s", ipaconfig->homedir_prefix, uid);
- slapi_ch_free_string(&uid);
- /* otherwise, use the samAccountName from the ad_entry */
- } else if ((samAccountName =
- slapi_entry_attr_get_charptr(ad_entry, "samAccountName"))) {
- homeDir = slapi_ch_smprintf("%s/%s", ipaconfig->homedir_prefix,
- samAccountName);
- slapi_ch_free_string(&samAccountName);
- } else { /* fatal error - nothing to use for homeDirectory */
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "Error creating %s for realm [%s] for Windows "
- "entry dn [%s], DS entry dn [%s] - Windows entry "
- "has no samAccountName, and DS entry has no uid.\n",
- type, ipaconfig->realm_name,
- slapi_entry_get_dn_const(ad_entry),
- slapi_entry_get_dn_const(ds_entry));
- }
-
- if (homeDir) {
- slapi_entry_attr_set_charptr(ds_entry, type, homeDir);
- slapi_ch_free_string(&homeDir);
- }
- }
-
- /* gecos is not required, but nice to have */
- type = "gecos";
- if (slapi_entry_attr_find(ds_entry, type, &e_attr) || !e_attr) {
- char *cn = NULL;
- char *displayName = NULL;
- /* if the ds_entry already has a cn, use that */
- if ((cn = slapi_entry_attr_get_charptr(ds_entry, "cn"))) {
- slapi_entry_attr_set_charptr(ds_entry, type, cn);
- slapi_ch_free_string(&cn);
- /* otherwise, use the displayName from the ad_entry */
- } else if ((displayName =
- slapi_entry_attr_get_charptr(ad_entry, "displayName"))) {
- slapi_entry_attr_set_charptr(ds_entry, type, displayName);
- slapi_ch_free_string(&displayName);
- }
- }
-
- sync_acct_disable(cbdata, rawentry, ds_entry, ACCT_DISABLE_TO_DS,
- ds_entry, NULL, NULL);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_add_user_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ds_add_group_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ds_add_group_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ds_add_group_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_get_new_ds_user_dn_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, char **new_dn_string,
- const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
-{
- char **rdns = NULL;
- PRBool flatten = PR_TRUE;
- IPA_WinSync_Config *ipaconfig = ipa_winsync_get_config();
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_get_new_ds_user_dn_cb -- old dn [%s] -- begin\n",
- *new_dn_string);
-
- slapi_lock_mutex(ipaconfig->lock);
- flatten = ipaconfig->flatten;
- slapi_unlock_mutex(ipaconfig->lock);
-
- if (!flatten) {
- return;
- }
-
- rdns = ldap_explode_dn(*new_dn_string, 0);
- if (!rdns || !rdns[0]) {
- ldap_value_free(rdns);
- return;
- }
-
- slapi_ch_free_string(new_dn_string);
- *new_dn_string = slapi_ch_smprintf("%s,%s", rdns[0], slapi_sdn_get_dn(ds_suffix));
- ldap_value_free(rdns);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_get_new_ds_user_dn_cb -- new dn [%s] -- end\n",
- *new_dn_string);
-
- return;
-}
-
-static void
-ipa_winsync_get_new_ds_group_dn_cb(void *cbdata, const Slapi_Entry *rawentry,
- Slapi_Entry *ad_entry, char **new_dn_string,
- const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_get_new_ds_group_dn_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_get_new_ds_group_dn_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ad_mod_user_mods_cb(void *cbdata, const Slapi_Entry *rawentry,
- const Slapi_DN *local_dn,
- const Slapi_Entry *ds_entry,
- LDAPMod * const *origmods,
- Slapi_DN *remote_dn, LDAPMod ***modstosend)
-{
- Slapi_Mods *smods;
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ad_mod_user_mods_cb -- begin\n");
-
- /* wrap the modstosend in a Slapi_Mods for convenience */
- smods = slapi_mods_new();
- slapi_mods_init_byref(smods, *modstosend);
- sync_acct_disable(cbdata, rawentry, (Slapi_Entry *)ds_entry,
- ACCT_DISABLE_TO_AD, NULL, smods, NULL);
-
- /* convert back to LDAPMod ** and clean up */
- *modstosend = slapi_mods_get_ldapmods_passout(smods);
- slapi_mods_free(&smods);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ad_mod_user_mods_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_pre_ad_mod_group_mods_cb(void *cbdata, const Slapi_Entry *rawentry,
- const Slapi_DN *local_dn,
- const Slapi_Entry *ds_entry,
- LDAPMod * const *origmods,
- Slapi_DN *remote_dn, LDAPMod ***modstosend)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_pre_ad_mod_group_mods_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_pre_ad_mod_group_mods_cb -- end\n");
-
- return;
-}
-
-static int
-ipa_winsync_can_add_entry_to_ad_cb(void *cbdata, const Slapi_Entry *local_entry,
- const Slapi_DN *remote_dn)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_can_add_entry_to_ad_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_can_add_entry_to_ad_cb -- end\n");
-
- return 0; /* false - do not allow entries to be added to ad */
-}
-
-static void
-ipa_winsync_begin_update_cb(void *cbdata, const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree, int is_total)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_begin_update_cb -- begin\n");
-
- ipa_winsync_config_refresh_domain(cbdata, ds_subtree, ad_subtree);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_begin_update_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_end_update_cb(void *cbdata, const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree, int is_total)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_end_update_cb -- begin\n");
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_end_update_cb -- end\n");
-
- return;
-}
-
-static void
-ipa_winsync_destroy_agmt_cb(void *cbdata, const Slapi_DN *ds_subtree,
- const Slapi_DN *ad_subtree)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_destroy_agmt_cb -- begin\n");
-
- ipa_winsync_config_destroy_domain(cbdata, ds_subtree, ad_subtree);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_destroy_agmt_cb -- end\n");
-
- return;
-}
-
-static void *ipa_winsync_api[] = {
- NULL, /* reserved for api broker use, must be zero */
- ipa_winsync_agmt_init,
- ipa_winsync_dirsync_search_params_cb,
- ipa_winsync_pre_ad_search_cb,
- ipa_winsync_pre_ds_search_entry_cb,
- ipa_winsync_pre_ds_search_all_cb,
- ipa_winsync_pre_ad_mod_user_cb,
- ipa_winsync_pre_ad_mod_group_cb,
- ipa_winsync_pre_ds_mod_user_cb,
- ipa_winsync_pre_ds_mod_group_cb,
- ipa_winsync_pre_ds_add_user_cb,
- ipa_winsync_pre_ds_add_group_cb,
- ipa_winsync_get_new_ds_user_dn_cb,
- ipa_winsync_get_new_ds_group_dn_cb,
- ipa_winsync_pre_ad_mod_user_mods_cb,
- ipa_winsync_pre_ad_mod_group_mods_cb,
- ipa_winsync_can_add_entry_to_ad_cb,
- ipa_winsync_begin_update_cb,
- ipa_winsync_end_update_cb,
- ipa_winsync_destroy_agmt_cb
-};
-
-/**
- * Plugin identifiers
- */
-static Slapi_PluginDesc ipa_winsync_pdesc = {
- "ipa-winsync-plugin",
- "FreeIPA project",
- "FreeIPA/1.0",
- "ipa winsync plugin"
-};
-
-static Slapi_ComponentId *ipa_winsync_plugin_id = NULL;
-
-/*
-** Plugin identity mgmt
-*/
-
-void ipa_winsync_set_plugin_identity(void * identity)
-{
- ipa_winsync_plugin_id=identity;
-}
-
-void * ipa_winsync_get_plugin_identity()
-{
- return ipa_winsync_plugin_id;
-}
-
-static int
-ipa_winsync_plugin_start(Slapi_PBlock *pb)
-{
- int rc;
- Slapi_Entry *config_e = NULL; /* entry containing plugin config */
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_plugin_start -- begin\n");
-
- if( slapi_apib_register(WINSYNC_v1_0_GUID, ipa_winsync_api) ) {
- slapi_log_error( SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_start -- failed to register winsync api -- end\n");
- return -1;
- }
-
- if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &config_e ) != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "missing config entry\n" );
- return( -1 );
- }
-
- if (( rc = ipa_winsync_config( config_e )) != LDAP_SUCCESS ) {
- slapi_log_error( SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "configuration failed (%s)\n", ldap_err2string( rc ));
- return( -1 );
- }
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_start -- end\n");
- return 0;
-}
-
-static int
-ipa_winsync_plugin_close(Slapi_PBlock *pb)
-{
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_plugin_close -- begin\n");
-
- slapi_apib_unregister(WINSYNC_v1_0_GUID);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_close -- end\n");
- return 0;
-}
-
-/* this is the slapi plugin init function,
- not the one used by the winsync api
-*/
-int ipa_winsync_plugin_init(Slapi_PBlock *pb)
-{
- void *plugin_id = NULL;
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "--> ipa_winsync_plugin_init -- begin\n");
-
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) ipa_winsync_plugin_start ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) ipa_winsync_plugin_close ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&ipa_winsync_pdesc ) != 0 )
- {
- slapi_log_error( SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_init -- failed to register plugin -- end\n");
- return -1;
- }
-
- /* Retrieve and save the plugin identity to later pass to
- internal operations */
- if (slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_id) != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_init -- failed to retrieve plugin identity -- end\n");
- return -1;
- }
-
- ipa_winsync_set_plugin_identity(plugin_id);
-
- slapi_log_error( SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_winsync_plugin_init -- end\n");
- return 0;
-}
-
-/*
- * Check if the given entry has account lock on (i.e. entry is disabled)
- * Mostly copied from check_account_lock in the server code.
- * Returns: 0 - account is disabled (lock == "true")
- * 1 - account is enabled (lock == "false" or empty)
- * -1 - some sort of error
- */
-static int
-ipa_check_account_lock(Slapi_Entry *ds_entry, int *isvirt)
-{
- int rc = 1;
- Slapi_ValueSet *values = NULL;
- int type_name_disposition = 0;
- char *actual_type_name = NULL;
- int attr_free_flags = 0;
- char *strval;
-
- /* first, see if the attribute is a "real" attribute */
- strval = slapi_entry_attr_get_charptr(ds_entry, "nsAccountLock");
- if (strval) { /* value is real */
- *isvirt = 0; /* value is real */
- rc = 1; /* default to enabled */
- if (PL_strncasecmp(strval, "true", 4) == 0) {
- rc = 0; /* account is disabled */
- }
- slapi_ch_free_string(&strval);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_check_account_lock - entry [%s] has real "
- "attribute nsAccountLock and entry %s locked\n",
- slapi_entry_get_dn_const(ds_entry),
- rc ? "is not" : "is");
- return rc;
- }
-
- rc = slapi_vattr_values_get(ds_entry, "nsAccountLock",
- &values,
- &type_name_disposition, &actual_type_name,
- SLAPI_VIRTUALATTRS_REQUEST_POINTERS,
- &attr_free_flags);
- if (rc == 0) {
- Slapi_Value *v = NULL;
- const struct berval *bvp = NULL;
-
- rc = 1; /* default is enabled */
- *isvirt = 1; /* value is virtual */
- if ((slapi_valueset_first_value(values, &v) != -1) &&
- (bvp = slapi_value_get_berval(v)) != NULL) {
- if ( (bvp != NULL) && (PL_strncasecmp(bvp->bv_val, "true", 4) == 0) ) {
- slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
- rc = 0; /* account is disabled */
- }
- }
-
- if (values != NULL) {
- slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
- }
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_check_account_lock - entry [%s] has virtual "
- "attribute nsAccountLock and entry %s locked\n",
- slapi_entry_get_dn_const(ds_entry),
- rc ? "is not" : "is");
- } else {
- rc = 1; /* no attr == entry is enabled */
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- ipa_check_account_lock - entry [%s] does not "
- "have attribute nsAccountLock - entry %s locked\n",
- slapi_entry_get_dn_const(ds_entry),
- rc ? "is not" : "is");
- }
-
- return rc;
-}
-
-static int
-do_group_modify(const char *dn, const char *modtype, int modop, const char *modval)
-{
- int rc = 0;
- LDAPMod mod;
- LDAPMod *mods[2];
- const char *val[2];
- Slapi_PBlock *mod_pb = NULL;
-
- mod_pb = slapi_pblock_new();
-
- mods[0] = &mod;
- mods[1] = NULL;
-
- val[0] = modval;
- val[1] = NULL;
-
- mod.mod_op = modop;
- mod.mod_type = (char *)modtype;
- mod.mod_values = (char **)val;
-
- slapi_modify_internal_set_pb(
- mod_pb, dn, mods, 0, 0,
- ipa_winsync_get_plugin_identity(), 0);
-
- slapi_modify_internal_pb(mod_pb);
-
- slapi_pblock_get(mod_pb,
- SLAPI_PLUGIN_INTOP_RESULT,
- &rc);
-
- slapi_pblock_destroy(mod_pb);
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- do_group_modify - %s value [%s] in attribute [%s] "
- "in entry [%s] - result (%d: %s)\n",
- (modop & LDAP_MOD_ADD) ? "added" : "deleted",
- modval, modtype, dn,
- rc, ldap_err2string(rc));
-
- return rc;
-}
-
-/*
- * This can be used either in the to ad direction or the to ds direction, since in both
- * cases we have to read both entries and compare the values.
- * ad_entry - entry from AD
- * ds_entry - entry from DS
- * direction - either ACCT_DISABLE_TO_AD or ACCT_DISABLE_TO_DS
- *
- * If smods is given, this is the list of mods to send in the given direction. The
- * appropriate modify operation will be added to this list or changed to the correct
- * value if it already exists.
- * Otherwise, if a destination entry is given, the value will be written into
- * that entry.
- */
-static void
-sync_acct_disable(
- void *cbdata, /* the usual domain config data */
- const Slapi_Entry *ad_entry, /* the AD entry */
- Slapi_Entry *ds_entry, /* the DS entry */
- int direction, /* the direction - TO_AD or TO_DS */
- Slapi_Entry *update_entry, /* the entry to update for ADDs */
- Slapi_Mods *smods, /* the mod list for MODIFYs */
- int *do_modify /* if not NULL, set this to true if mods were added */
-)
-{
- IPA_WinSync_Domain_Config *ipaconfig = (IPA_WinSync_Domain_Config *)cbdata;
- IPA_WinSync_Config *global_ipaconfig = ipa_winsync_get_config();
- int acct_disable;
- int ds_is_enabled = 1; /* default to true */
- int ad_is_enabled = 1; /* default to true */
- unsigned long adval = 0; /* raw account val from ad entry */
- int isvirt = 1; /* default to virt */
-
- slapi_lock_mutex(global_ipaconfig->lock);
- acct_disable = global_ipaconfig->acct_disable;
- slapi_unlock_mutex(global_ipaconfig->lock);
-
- if (acct_disable == ACCT_DISABLE_NONE) {
- return; /* not supported */
- }
-
- /* get the account lock state of the ds entry */
- if (0 == ipa_check_account_lock(ds_entry, &isvirt)) {
- ds_is_enabled = 0;
- }
-
- /* get the account lock state of the ad entry */
- adval = slapi_entry_attr_get_ulong(ad_entry, "UserAccountControl");
- if (adval & 0x2) {
- /* account is disabled */
- ad_is_enabled = 0;
- }
-
- if (ad_is_enabled == ds_is_enabled) { /* both have same value - nothing to do */
- return;
- }
-
- /* have to enable or disable */
- if (direction == ACCT_DISABLE_TO_AD) {
- unsigned long mask;
- /* set the mod or entry */
- if (update_entry) {
- if (ds_is_enabled) {
- mask = ~0x2;
- adval &= mask; /* unset the 0x2 disable bit */
- } else {
- mask = 0x2;
- adval |= mask; /* set the 0x2 disable bit */
- }
- slapi_entry_attr_set_ulong(update_entry, "userAccountControl", adval);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s AD account [%s] - "
- "new value is [%ld]\n",
- (ds_is_enabled) ? "enabled" : "disabled",
- slapi_entry_get_dn_const(update_entry),
- adval);
- } else {
- /* iterate through the mods - if there is already a mod
- for userAccountControl, change it - otherwise, add it */
- char acctvalstr[32];
- LDAPMod *mod = NULL;
- struct berval *mod_bval = NULL;
- for (mod = slapi_mods_get_first_mod(smods); mod;
- mod = slapi_mods_get_next_mod(smods)) {
- if (!PL_strcasecmp(mod->mod_type, "userAccountControl") &&
- mod->mod_bvalues && mod->mod_bvalues[0]) {
- mod_bval = mod->mod_bvalues[0];
- /* mod_bval points directly to value inside mod list */
- break;
- }
- }
- if (!mod_bval) { /* not found - add it */
- struct berval tmpbval = {0, NULL};
- Slapi_Mod *smod = slapi_mod_new();
- slapi_mod_init(smod, 1); /* one element */
- slapi_mod_set_type(smod, "userAccountControl");
- slapi_mod_set_operation(smod, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES);
- slapi_mod_add_value(smod, &tmpbval);
- /* add_value makes a copy of the bval - so let's get a pointer
- to that new value - we will change the bval in place */
- mod_bval = slapi_mod_get_first_value(smod);
- /* mod_bval points directly to value inside mod list */
- /* now add the new mod to smods */
- slapi_mods_add_ldapmod(smods,
- slapi_mod_get_ldapmod_passout(smod));
- /* smods now owns the ldapmod */
- slapi_mod_free(&smod);
- if (do_modify) {
- *do_modify = 1; /* added mods */
- }
- }
- if (mod_bval) {
- /* this is where we set or update the actual value
- mod_bval points directly into the mod list we are
- sending */
- if (mod_bval->bv_val && (mod_bval->bv_len > 0)) {
- /* get the old val */
- adval = strtol(mod_bval->bv_val, NULL, 10);
- }
- if (ds_is_enabled) {
- mask = ~0x2;
- adval &= mask; /* unset the 0x2 disable bit */
- } else {
- mask = 0x2;
- adval |= mask; /* set the 0x2 disable bit */
- }
- PR_snprintf(acctvalstr, sizeof(acctvalstr), "%lu", adval);
- slapi_ch_free_string(&mod_bval->bv_val);
- mod_bval->bv_val = slapi_ch_strdup(acctvalstr);
- mod_bval->bv_len = strlen(acctvalstr);
- }
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s AD account [%s] - "
- "new value is [%ld]\n",
- (ds_is_enabled) ? "enabled" : "disabled",
- slapi_entry_get_dn_const(ad_entry),
- adval);
- }
- }
-
- if (direction == ACCT_DISABLE_TO_DS) {
- if (!isvirt) {
- char *attrtype = NULL;
- char *attrval = NULL;
- attrtype = "nsAccountLock";
- if (ad_is_enabled) {
- attrval = NULL; /* will delete the value */
- } else {
- attrval = "true";
- }
-
- if (update_entry) {
- slapi_entry_attr_set_charptr(update_entry, attrtype, attrval);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s DS account [%s]\n",
- (ad_is_enabled) ? "enabled" : "disabled",
- slapi_entry_get_dn_const(ds_entry));
- } else { /* do mod */
- struct berval tmpbval = {0, NULL};
- Slapi_Mod *smod = slapi_mod_new();
- slapi_mod_init(smod, 1); /* one element */
- slapi_mod_set_type(smod, attrtype);
- if (attrval == NULL) {
- slapi_mod_set_operation(smod, LDAP_MOD_DELETE|LDAP_MOD_BVALUES);
- } else {
- slapi_mod_set_operation(smod, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES);
- }
- slapi_mod_add_value(smod, &tmpbval);
- slapi_mods_add_ldapmod(smods,
- slapi_mod_get_ldapmod_passout(smod));
- slapi_mod_free(&smod);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s DS account [%s]\n",
- (ad_is_enabled) ? "enabled" : "disabled",
- slapi_entry_get_dn_const(ds_entry));
- if (do_modify) {
- *do_modify = 1; /* added mods */
- }
- }
- } else { /* use the virtual attr scheme */
- char *adddn, *deldn;
- const char *dsdn;
- int rc;
- /* in the case of disabling a user, need to remove that user from
- the activated group, if in there, and add to the inactivated group
- however, in the case of enabling a user, we just have to remove
- the user from the inactivated group, if in there - if the user
- is not in any group, the user is activated by default
- */
- if (ad_is_enabled) {
- /* add user to activated group, delete from inactivated group */
- adddn = NULL; /* no group means active by default */
- deldn = ipaconfig->inactivated_group_dn;
- } else {
- /* add user to inactivated group, delete from activated group */
- adddn = ipaconfig->inactivated_group_dn;
- deldn = ipaconfig->activated_group_dn;
- }
-
- dsdn = slapi_entry_get_dn_const(ds_entry);
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s DS account [%s] - "
- "deldn [%s] adddn [%s]\n",
- (ad_is_enabled) ? "enabling" : "disabling",
- slapi_entry_get_dn_const(ds_entry),
- deldn, adddn);
- /* first, delete the user from the deldn group - ignore (but log)
- value not found errors - means the user wasn't there yet */
- rc = do_group_modify(deldn, "member", LDAP_MOD_DELETE, dsdn);
- if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
- /* either the value of the attribute doesn't exist */
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "Could not delete user [%s] from the [%s] group: "
- "either the user was not in the group already, "
- "or the group had no members\n",
- dsdn, deldn);
- } else if (rc != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "Error deleting user [%s] from the [%s] group: "
- "(%d - %s)\n", dsdn, deldn, rc,
- ldap_err2string(rc));
- }
- /* next, add the user to the adddn group - ignore (but log)
- if the user is already in that group */
- if (adddn) {
- rc = do_group_modify(adddn, "member", LDAP_MOD_ADD, dsdn);
- } else {
- rc = LDAP_SUCCESS;
- }
- if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
- /* user already in that group */
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "Could not add user [%s] to the [%s] group: "
- "user is already in that group\n",
- dsdn, adddn);
- } else if (rc != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, ipa_winsync_plugin_name,
- "Error adding user [%s] to the [%s] group: "
- "(%d - %s)\n", dsdn, adddn, rc,
- ldap_err2string(rc));
- }
-#ifndef MEMBEROF_WORKS_FOR_INTERNAL_OPS
- /* memberOf doesn't currently listen for internal operations
- that change group membership - so we manually set the
- memberOf attribute in the ds entry - this should not
- conflict with memberOf */
- {
- Slapi_Value *sv = slapi_value_new();
- slapi_value_init_string(sv, deldn);
- if (slapi_entry_attr_has_syntax_value(ds_entry,
- "memberOf", sv)) {
- if (smods) {
- slapi_mods_add_string(smods, LDAP_MOD_DELETE,
- "memberOf", deldn);
- if (do_modify) {
- *do_modify = 1; /* added mods */
- }
- } else if (update_entry) {
- slapi_entry_delete_string(update_entry,
- "memberOf", deldn);
- }
- }
- if (adddn) {
- slapi_value_set_string(sv, adddn);
- if (!slapi_entry_attr_has_syntax_value(ds_entry,
- "memberOf", sv)) {
- if (smods) {
- slapi_mods_add_string(smods, LDAP_MOD_ADD,
- "memberOf", adddn);
- if (do_modify) {
- *do_modify = 1; /* added mods */
- }
- } else if (update_entry) {
- slapi_entry_add_string(update_entry,
- "memberOf", adddn);
- }
- }
- }
- slapi_value_free(&sv);
- }
-#endif /* MEMBEROF_WORKS_FOR_INTERNAL_OPS */
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- sync_acct_disable - %s DS account [%s]\n",
- (ad_is_enabled) ? "enabled" : "disabled",
- slapi_entry_get_dn_const(ds_entry));
- }
- }
-
- return;
-}
-
-/* if entry does not have attribute type and val, and neither
- does the smods, add them to the smods */
-static void
-find_and_add_mod(Slapi_Entry *ent, Slapi_Mods *smods, const char *type,
- const char *val, size_t vallen, int *do_modify)
-{
- int found = 1;
- Slapi_Value *sv = slapi_value_new();
- LDAPMod *mod = NULL;
-
- slapi_value_init_string(sv, val);
- if (!slapi_entry_attr_has_syntax_value(ent, type, sv)) {
- /* entry doesn't have type val - see if there is already
- a mod in the mods list that adds it replaces it */
- found = 0; /* not found in entry - see if in mod list */
- for (mod = slapi_mods_get_first_mod(smods);
- !found && mod;
- mod = slapi_mods_get_next_mod(smods)) {
- int ii;
- if (PL_strcasecmp(mod->mod_type, type)) {
- continue; /* skip - not a mod of this type */
- }
- if (!(mod->mod_op & (LDAP_MOD_ADD|LDAP_MOD_REPLACE))) {
- continue; /* skip - not an add or replace op */
- }
- /* now see if val is in the list of vals for this mod op */
- for (ii = 0;
- !found && mod->mod_bvalues && mod->mod_bvalues[ii];
- ++ii) {
- if (mod->mod_bvalues[ii]->bv_val) {
- found = !PL_strncasecmp(mod->mod_bvalues[ii]->bv_val,
- val, vallen);
- }
- }
- }
- }
- if (!found) {
- slapi_mods_add_string(smods, LDAP_MOD_ADD, type, val);
- if (do_modify) {
- *do_modify = 1; /* added a mod */
- }
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "<-- find_and_add_mod - added value [%s] "
- "to attribute [%s] in entry [%s]\n",
- val, type, slapi_entry_get_dn_const(ent));
- }
- slapi_value_free(&sv);
-
- return;
-}
-
-/*
- * If force sync is true, any time an entry is being added or modified
- * in DS, we must ensure the entry has the ntUser objectclass, and that
- * it has the ntUserDomainID attribute, and the value of that attribute
- * corresponds to the samAccountName in the AD entry.
- * ad_entry - entry from AD
- * ds_entry - entry from DS
- *
- * The appropriate modify operation will be added to the given smods
- * if it doesn't already exist.
- */
-static void
-do_force_sync(
- const Slapi_Entry *ad_entry, /* the AD entry */
- Slapi_Entry *ds_entry, /* the DS entry */
- Slapi_Mods *smods, /* the mod list for MODIFYs */
- int *do_modify /* if not NULL, set to true if mods were added */
-)
-{
- IPA_WinSync_Config *global_ipaconfig = ipa_winsync_get_config();
- PRBool forceSync;
-
- slapi_lock_mutex(global_ipaconfig->lock);
- forceSync = global_ipaconfig->forceSync;
- slapi_unlock_mutex(global_ipaconfig->lock);
-
- if (forceSync == PR_FALSE) {
- return; /* not supported */
- }
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name,
- "do_force_sync - forcing sync of AD entry [%s] "
- "with DS entry [%s]\n",
- slapi_entry_get_dn_const(ad_entry),
- slapi_entry_get_dn_const(ds_entry));
-
- find_and_add_mod(ds_entry, smods, "objectClass", "ntUser", (size_t)6, do_modify);
-
- return;
-}
diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h
deleted file mode 100644
index 58a9a6c40..000000000
--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h
+++ /dev/null
@@ -1,160 +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.
- *
- * Authors:
- * Rich Megginson <rmeggins@redhat.com>
- *
- * Copyright (C) 2008 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifndef IPA_WINSYNC_H
-#define IPA_WINSYNC_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef WINSYNC_TEST_IPA
-#include <slapi-plugin.h>
-#include "winsync-plugin.h"
-#else /* the default */
-#include <dirsrv/slapi-plugin.h>
-#include <dirsrv/winsync-plugin.h>
-#endif /* WINSYNC_TEST_IPA */
-
-#define IPA_WINSYNC_PLUGIN_NAME "ipa-winsync"
-
-typedef struct ipa_winsync_config_struct {
- Slapi_Mutex *lock; /* for config access */
- Slapi_Entry *config_e; /* configuration entry */
- PRBool flatten; /* flatten AD DNs */
- char *realm_filter;
- char *realm_attr;
- char *new_entry_filter;
- char *new_user_oc_attr; /* don't care about groups for now */
- char *homedir_prefix_attr;
- char *default_group_attr;
- char *default_group_filter;
- int acct_disable; /* see below for possible values */
- char *inactivated_filter;
- char *activated_filter;
- PRBool forceSync;
-} IPA_WinSync_Config;
-
-/*
- This is the structure that holds our domain
- specific configuration
-*/
-typedef struct ipa_winsync_domain_config {
- Slapi_Entry *domain_e; /* info is stored in this entry */
- char *realm_name; /* realm name */
- char *homedir_prefix;
- char *inactivated_group_dn; /* DN of inactivated group */
- char *activated_group_dn; /* DN of activated group */
-} IPA_WinSync_Domain_Config;
-
-void ipa_winsync_set_plugin_identity(void * identity);
-void * ipa_winsync_get_plugin_identity();
-
-int ipa_winsync_config( Slapi_Entry *config_e );
-IPA_WinSync_Config *ipa_winsync_get_config( void );
-
-/*
- * Agreement/domain specific configuration
- */
-/* return a new domain specific configuration object */
-void *ipa_winsync_config_new_domain(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
-/* refresh the domain specific configuration object */
-void ipa_winsync_config_refresh_domain(void *cbdata, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
-/* destroy the domain specific configuration object */
-void ipa_winsync_config_destroy_domain(void *cbdata, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
-
-/* name of attribute holding the filter to use to
- find the ipa realm value
-*/
-#define IPA_WINSYNC_REALM_FILTER_ATTR "ipaWinSyncRealmFilter"
-/* name of attribute holding the name of the attribute
- which contains the ipa realm value
-*/
-#define IPA_WINSYNC_REALM_ATTR_ATTR "ipaWinSyncRealmAttr"
-/* name of attribute holding the filter to use to
- find the new user template entry
-*/
-#define IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR "ipaWinSyncNewEntryFilter"
-/* name of attribute holding the name of the attribute
- in the new user template entry which has the list of objectclasses
-*/
-#define IPA_WINSYNC_NEW_USER_OC_ATTR "ipaWinSyncNewUserOCAttr"
-/* name of attribute holding the new user attributes and values */
-#define IPA_WINSYNC_NEW_USER_ATTRS_VALS "ipaWinSyncUserAttr"
-/* name of attribute holding the name of the attribute which
- has the homeDirectory prefix - suffix is the uid */
-#define IPA_WINSYNC_HOMEDIR_PREFIX_ATTR "ipaWinsyncHomeDirAttr"
-/* name of attribute holding the name of the attribute which is
- used to get the default posix gidNumber */
-#define IPA_WINSYNC_DEFAULTGROUP_ATTR "ipaWinSyncDefaultGroupAttr"
-/* filter used to find the group with the gid number whose group name
- is in the IPA_WINSYNC_DEFAULTGROUP_ATTR - the filter will have
- cn=valueofIPA_WINSYNC_DEFAULTGROUP_ATTR appended to it */
-#define IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR "ipaWinSyncDefaultGroupFilter"
-/* name of attribute holding boolean value to flatten user dns or not */
-#define IPA_WINSYNC_USER_FLATTEN "ipaWinSyncUserFlatten"
-/* name of attribute holding account disable sync value */
-#define IPA_WINSYNC_ACCT_DISABLE "ipaWinSyncAcctDisable"
-/* possible values of IPA_WINSYNC_ACCT_DISABLE */
-#define IPA_WINSYNC_ACCT_DISABLE_NONE "none"
-#define IPA_WINSYNC_ACCT_DISABLE_TO_AD "to_ad"
-#define IPA_WINSYNC_ACCT_DISABLE_TO_DS "to_ds"
-#define IPA_WINSYNC_ACCT_DISABLE_BOTH "both"
-/* enum representing the values above */
-enum {
- ACCT_DISABLE_INVALID, /* the invalid value */
- ACCT_DISABLE_NONE, /* do not sync acct disable status */
- ACCT_DISABLE_TO_AD, /* sync only from ds to ad */
- ACCT_DISABLE_TO_DS, /* sync only from ad to ds */
- ACCT_DISABLE_BOTH /* bi-directional sync */
-};
-/* name of attributes holding the search filters to use to find
- the DN of the groups that represent inactivated and activated users */
-#define IPA_WINSYNC_INACTIVATED_FILTER "ipaWinSyncInactivatedFilter"
-#define IPA_WINSYNC_ACTIVATED_FILTER "ipaWinSyncActivatedFilter"
-/* name of attribute holding the value of the forceSync parameter -
- this is a boolean attribute - if true, all users in AD that have
- a corresponding entry in the DS will be synced - there will be no
- way to "turn off sync" on individual entries - if this value is
- false, only users which have the ntUser objectclass and an
- ntDomainUserID attribute which corresponds to an AD account
- with the same value for samAccountName will be synced
-*/
-#define IPA_WINSYNC_FORCE_SYNC "ipaWinSyncForceSync"
-#endif /* IPA_WINSYNC_H */