From 57fbd098f0483de6c56136e88323aeacf70657c6 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Wed, 13 Aug 2008 14:43:58 -0600 Subject: Initial addition of ipa-winsync plugin --- .../ipa-slapi-plugins/ipa-winsync/Makefile.am | 43 +++ ipa-server/ipa-slapi-plugins/ipa-winsync/README | 0 .../ipa-winsync/ipa-winsync-conf.ldif | 11 + .../ipa-slapi-plugins/ipa-winsync/ipa-winsync.c | 402 +++++++++++++++++++++ 4 files changed, 456 insertions(+) create mode 100644 ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am create mode 100644 ipa-server/ipa-slapi-plugins/ipa-winsync/README create mode 100644 ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif create mode 100644 ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am b/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am new file mode 100644 index 000000000..e8375ba34 --- /dev/null +++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/Makefile.am @@ -0,0 +1,43 @@ +NULL = + +INCLUDES = \ + -I. \ + -I$(srcdir) \ + -DPREFIX=\""$(prefix)"\" \ + -DBINDIR=\""$(bindir)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + -DDATADIR=\""$(datadir)"\" \ + $(WARN_CFLAGS) \ + $(NULL) + +plugindir = $(libdir)/dirsrv/plugins +plugin_LTLIBRARIES = \ + libipa_winsync.la \ + $(NULL) + +libipa_winsync_la_SOURCES = \ + ipa_winsync.c \ + $(NULL) + +libipa_winsync_la_LDFLAGS = -avoid-version + +#libipa_winsync_la_LIBADD = \ +# $(KRB5_LIBS) \ +# $(SSL_LIBS) \ +# $(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 new file mode 100644 index 000000000..e69de29bb 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 new file mode 100644 index 000000000..ecbdbab43 --- /dev/null +++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif @@ -0,0 +1,11 @@ +dn: cn=ipa-winsync,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +objectclass: extensibleObject +cn: ipa-winsync +nsslapd-pluginpath: libipa-winsync +nsslapd-plugininitfunc: ipa_winsync_plugin_init +nsslapd-plugintype: preoperation +nsslapd-pluginenabled: on +nsslapd-plugin-depends-on-type: database +nsslapd-plugin-depends-on-named: Multimaster Replication Plugin diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c new file mode 100644 index 000000000..bad907bc6 --- /dev/null +++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c @@ -0,0 +1,402 @@ +/** 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 + * + * Copyright (C) 2008 Red Hat, Inc. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +#ifdef HAVE_CONFIG_H +# include +#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. + */ + +#include +#include + +static char *ipa_winsync_plugin_name = "ipa-winsync"; + +/* 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) +{ + 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)); + + slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name, + "<-- ipa_winsync_agmt_init -- end\n"); + + return NULL; +} + +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 -- 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 already - 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"); + + 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"); + + 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) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name, + "--> ipa_winsync_pre_ds_add_user_cb -- begin\n"); + + 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; + + 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); + + 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 = PR_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, LDAPMod * const *origmods, + Slapi_DN *remote_dn, LDAPMod ***modstosend) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name, + "--> ipa_winsync_pre_ad_mod_user_mods_cb -- begin\n"); + + 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, 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 */ +} + +/** + * Plugin identifiers + */ +static Slapi_PluginDesc ipa_winsync_pdesc = { + "ipa-winsync-plugin", + PLUGIN_MAGIC_VENDOR_STR, + PRODUCTTEXT, + "ipa winsync plugin" +}; + +static Slapi_ComponentId *ipa_winsync_plugin_id = NULL; + +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 +}; + +static int +ipa_winsync_plugin_start(Slapi_PBlock *pb) +{ + 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; + } + + 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) +{ + 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, &ipa_winsync_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; + } + + slapi_log_error( SLAPI_LOG_PLUGIN, ipa_winsync_plugin_name, + "<-- ipa_winsync_plugin_init -- end\n"); + return 0; +} -- cgit