From 0610f9a7495b5cc995796e8a0bbaa6bc61449c33 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Mar 27 2012 20:47:12 +0000 Subject: Ticket #316 and Ticket #70 - add post add/mod and AD add callback hooks https://fedorahosted.org/389/ticket/316 https://fedorahosted.org/389/ticket/70 Resolves: Ticket #316 and Ticket #70 Bug Description: Add user post callback hook to winsync plugin API Bug Description: Winsync API should have callback functions for new entries sync to AD Reviewed by: nkinder (Thanks!) Branch: master Fix Description: New callbacks for all post-add and post-modify (both to and from AD) operations. All post op callbacks have an int *return parameter. This parameter is the ldap result code from the add/mod op. The plugin will be called upon op success or failure, so should use this parameter to find out what happened. The plugin can also change this value to, for example, make a failed op pass, or to tell winsync to make a successful op fail (it will not roll back the op in this case though, but the plugin can tell winsync to stop on this op). There are also new callbacks for AD user/group add for ticket 70. Platforms tested: RHEL6 x86_64 Flag Day: no Doc impact: yes - doc the new functions --- diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c index 6c19e4a..72cb721 100644 --- a/ldap/servers/plugins/replication/windows_private.c +++ b/ldap/servers/plugins/replication/windows_private.c @@ -1019,6 +1019,10 @@ windows_private_set_sync_interval(Repl_Agmt *ra, char *str) /* an array of function pointers */ static void **_WinSyncAPI = NULL; +static int maxapiidx = WINSYNC_PLUGIN_VERSION_1_END; +#define DECL_WINSYNC_API_FUNC(idx,thetype,thefunc) \ + thetype thefunc = (_WinSyncAPI && (idx <= maxapiidx) && _WinSyncAPI[idx]) ? \ + (thetype)_WinSyncAPI[idx] : NULL; void windows_plugin_init(Repl_Agmt *ra) @@ -1031,14 +1035,34 @@ windows_plugin_init(Repl_Agmt *ra) /* if the function pointer array is null, get the functions - we will call init once per replication agreement, but will only grab the api once */ - if((NULL == _WinSyncAPI) && - (slapi_apib_get_interface(WINSYNC_v1_0_GUID, &_WinSyncAPI) || - (NULL == _WinSyncAPI))) - { - LDAPDebug1Arg( LDAP_DEBUG_PLUGIN, - "<-- windows_plugin_init_start -- no windows plugin API registered for GUID [%s] -- end\n", - WINSYNC_v1_0_GUID); - return; + if(NULL == _WinSyncAPI) { + if (slapi_apib_get_interface(WINSYNC_v2_0_GUID, &_WinSyncAPI) || + (NULL == _WinSyncAPI)) + { + LDAPDebug1Arg( LDAP_DEBUG_PLUGIN, + "<-- windows_plugin_init_start -- no windows plugin API registered for GUID [%s] -- end\n", + WINSYNC_v2_0_GUID); + } else if (_WinSyncAPI) { + LDAPDebug1Arg( LDAP_DEBUG_PLUGIN, + "<-- windows_plugin_init_start -- found windows plugin API registered for GUID [%s] -- end\n", + WINSYNC_v2_0_GUID); + maxapiidx = WINSYNC_PLUGIN_VERSION_2_END; + } + } + + if (NULL == _WinSyncAPI) { /* no v2 interface - look for v1 */ + if (slapi_apib_get_interface(WINSYNC_v1_0_GUID, &_WinSyncAPI) || + (NULL == _WinSyncAPI)) + { + LDAPDebug1Arg( LDAP_DEBUG_PLUGIN, + "<-- windows_plugin_init_start -- no windows plugin API registered for GUID [%s] -- end\n", + WINSYNC_v1_0_GUID); + return; + } else { + LDAPDebug1Arg( LDAP_DEBUG_PLUGIN, + "<-- windows_plugin_init_start -- found windows plugin API registered for GUID [%s] -- end\n", + WINSYNC_v1_0_GUID); + } } initfunc = (winsync_plugin_init_cb)_WinSyncAPI[WINSYNC_PLUGIN_INIT_CB]; @@ -1057,10 +1081,7 @@ winsync_plugin_call_dirsync_search_params_cb(const Repl_Agmt *ra, const char *ag char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls) { - winsync_search_params_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB]) ? - (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB,winsync_search_params_cb,thefunc); if (!thefunc) { return; @@ -1077,10 +1098,7 @@ winsync_plugin_call_pre_ad_search_cb(const Repl_Agmt *ra, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls) { - winsync_search_params_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_SEARCH_CB]) ? - (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_SEARCH_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_SEARCH_CB,winsync_search_params_cb,thefunc); if (!thefunc) { return; @@ -1097,10 +1115,7 @@ winsync_plugin_call_pre_ds_search_entry_cb(const Repl_Agmt *ra, const char *agmt char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls) { - winsync_search_params_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB]) ? - (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB,winsync_search_params_cb,thefunc); if (!thefunc) { return; @@ -1117,10 +1132,7 @@ winsync_plugin_call_pre_ds_search_all_cb(const Repl_Agmt *ra, const char *agmt_d char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls) { - winsync_search_params_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB]) ? - (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB,winsync_search_params_cb,thefunc); if (!thefunc) { return; @@ -1137,10 +1149,7 @@ winsync_plugin_call_pre_ad_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *r Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify) { - winsync_pre_mod_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB]) ? - (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB,winsync_pre_mod_cb,thefunc); if (!thefunc) { return; @@ -1157,10 +1166,7 @@ winsync_plugin_call_pre_ad_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry * Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify) { - winsync_pre_mod_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB]) ? - (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB,winsync_pre_mod_cb,thefunc); if (!thefunc) { return; @@ -1177,10 +1183,7 @@ winsync_plugin_call_pre_ds_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *r Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify) { - winsync_pre_mod_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB]) ? - (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB,winsync_pre_mod_cb,thefunc); if (!thefunc) { return; @@ -1197,10 +1200,7 @@ winsync_plugin_call_pre_ds_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry * Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify) { - winsync_pre_mod_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB]) ? - (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB,winsync_pre_mod_cb,thefunc); if (!thefunc) { return; @@ -1216,10 +1216,7 @@ void winsync_plugin_call_pre_ds_add_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry) { - winsync_pre_add_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB]) ? - (winsync_pre_add_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB,winsync_pre_add_cb,thefunc); if (!thefunc) { return; @@ -1235,10 +1232,7 @@ void winsync_plugin_call_pre_ds_add_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry) { - winsync_pre_add_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB]) ? - (winsync_pre_add_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB,winsync_pre_add_cb,thefunc); if (!thefunc) { return; @@ -1255,10 +1249,7 @@ winsync_plugin_call_get_new_ds_user_dn_cb(const Repl_Agmt *ra, const Slapi_Entry Slapi_Entry *ad_entry, char **new_dn_string, const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix) { - winsync_get_new_dn_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB]) ? - (winsync_get_new_dn_cb)_WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB,winsync_get_new_dn_cb,thefunc); if (!thefunc) { return; @@ -1275,10 +1266,7 @@ winsync_plugin_call_get_new_ds_group_dn_cb(const Repl_Agmt *ra, const Slapi_Entr Slapi_Entry *ad_entry, char **new_dn_string, const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix) { - winsync_get_new_dn_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB]) ? - (winsync_get_new_dn_cb)_WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB,winsync_get_new_dn_cb,thefunc); if (!thefunc) { return; @@ -1297,10 +1285,7 @@ winsync_plugin_call_pre_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slapi_Ent LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend) { - winsync_pre_ad_mod_mods_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB]) ? - (winsync_pre_ad_mod_mods_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB,winsync_pre_ad_mod_mods_cb,thefunc); if (!thefunc) { return; @@ -1319,10 +1304,7 @@ winsync_plugin_call_pre_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_En LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend) { - winsync_pre_ad_mod_mods_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB]) ? - (winsync_pre_ad_mod_mods_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB,winsync_pre_ad_mod_mods_cb,thefunc); if (!thefunc) { return; @@ -1338,10 +1320,7 @@ int winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn) { - winsync_can_add_to_ad_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB]) ? - (winsync_can_add_to_ad_cb)_WinSyncAPI[WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB,winsync_can_add_to_ad_cb,thefunc); if (!thefunc) { return 1; /* default is entry can be added to AD */ @@ -1354,10 +1333,7 @@ void winsync_plugin_call_begin_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree, int is_total) { - winsync_plugin_update_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_BEGIN_UPDATE_CB]) ? - (winsync_plugin_update_cb)_WinSyncAPI[WINSYNC_PLUGIN_BEGIN_UPDATE_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_BEGIN_UPDATE_CB,winsync_plugin_update_cb,thefunc); if (!thefunc) { return; @@ -1372,10 +1348,7 @@ void winsync_plugin_call_end_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree, int is_total) { - winsync_plugin_update_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_END_UPDATE_CB]) ? - (winsync_plugin_update_cb)_WinSyncAPI[WINSYNC_PLUGIN_END_UPDATE_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_END_UPDATE_CB,winsync_plugin_update_cb,thefunc); if (!thefunc) { return; @@ -1391,10 +1364,7 @@ winsync_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree) { - winsync_plugin_destroy_agmt_cb thefunc = - (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_DESTROY_AGMT_CB]) ? - (winsync_plugin_destroy_agmt_cb)_WinSyncAPI[WINSYNC_PLUGIN_DESTROY_AGMT_CB] : - NULL; + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_DESTROY_AGMT_CB,winsync_plugin_destroy_agmt_cb,thefunc); if (thefunc) { (*thefunc)(windows_private_get_api_cookie(ra), ds_subtree, ad_subtree); @@ -1403,6 +1373,204 @@ winsync_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra, return; } +void +winsync_plugin_call_post_ad_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_MOD_USER_CB,winsync_post_mod_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, smods, result); + + return; +} + +void +winsync_plugin_call_post_ad_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_MOD_GROUP_CB,winsync_post_mod_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, smods, result); + + return; +} + +void +winsync_plugin_call_post_ds_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_DS_MOD_USER_CB,winsync_post_mod_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, smods, result); + + return; +} + +void +winsync_plugin_call_post_ds_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_DS_MOD_GROUP_CB,winsync_post_mod_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, smods, result); + + return; +} + +void +winsync_plugin_call_post_ds_add_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_DS_ADD_USER_CB,winsync_post_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, result); + + return; +} + +void +winsync_plugin_call_post_ds_add_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_DS_ADD_GROUP_CB,winsync_post_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry, + ds_entry, result); + + return; +} + +void +winsync_plugin_call_pre_ad_add_user_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_ADD_USER_CB,winsync_pre_ad_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), ad_entry, ds_entry); + + return; +} + +void +winsync_plugin_call_pre_ad_add_group_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_PRE_AD_ADD_GROUP_CB,winsync_pre_ad_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), ad_entry, ds_entry); + + return; +} + +void +winsync_plugin_call_post_ad_add_user_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_ADD_USER_CB,winsync_post_ad_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), ad_entry, ds_entry, result); + + return; +} + +void +winsync_plugin_call_post_ad_add_group_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_ADD_GROUP_CB,winsync_post_ad_add_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), ad_entry, ds_entry, result); + + return; +} + +void +winsync_plugin_call_post_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + const Slapi_DN *local_dn, + const Slapi_Entry *ds_entry, + LDAPMod * const *origmods, + Slapi_DN *remote_dn, LDAPMod **modstosend, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_MOD_USER_MODS_CB,winsync_post_ad_mod_mods_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, local_dn, + ds_entry, origmods, remote_dn, modstosend, result); + + return; +} + +void +winsync_plugin_call_post_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + const Slapi_DN *local_dn, + const Slapi_Entry *ds_entry, + LDAPMod * const *origmods, + Slapi_DN *remote_dn, LDAPMod **modstosend, int *result) +{ + DECL_WINSYNC_API_FUNC(WINSYNC_PLUGIN_POST_AD_MOD_GROUP_MODS_CB,winsync_post_ad_mod_mods_cb,thefunc); + + if (!thefunc) { + return; + } + + (*thefunc)(windows_private_get_api_cookie(ra), rawentry, local_dn, + ds_entry, origmods, remote_dn, modstosend, result); + + return; +} + /* #define WINSYNC_TEST_IPA */ #ifdef WINSYNC_TEST_IPA diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c index a1b012c..d42cd96 100644 --- a/ldap/servers/plugins/replication/windows_protocol_util.c +++ b/ldap/servers/plugins/replication/windows_protocol_util.c @@ -80,7 +80,7 @@ static const char* op2string (int op); static int is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra); static int map_entry_dn_inbound(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra); static int map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int use_guid, int user_username); -static int windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry); +static int windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry,int is_user); static int is_guid_dn(Slapi_DN *remote_dn); static int map_windows_tombstone_dn(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, int *exists); static int windows_check_mods_for_rdn_change(Private_Repl_Protocol *prp, LDAPMod **original_mods, @@ -1184,6 +1184,13 @@ process_replay_add(Private_Repl_Protocol *prp, Slapi_Entry *add_entry, Slapi_Ent /* Convert entry to mods */ if (0 == rc && mapped_entry) { + if (is_user) { + winsync_plugin_call_pre_ad_add_user_cb(prp->agmt, mapped_entry, add_entry); + } else { + winsync_plugin_call_pre_ad_add_group_cb(prp->agmt, mapped_entry, add_entry); + } + /* plugin may reset DN */ + slapi_sdn_copy(slapi_entry_get_sdn(mapped_entry), remote_dn); (void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs); slapi_entry_free(mapped_entry); mapped_entry = NULL; @@ -1196,9 +1203,29 @@ process_replay_add(Private_Repl_Protocol *prp, Slapi_Entry *add_entry, Slapi_Ent } else { + int ldap_op = 0; + int ldap_result_code = 0; windows_log_add_entry_remote(local_dn, remote_dn); return_value = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL); + windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); + if ((return_value != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + /* op failed but no ldap error code ??? */ + ldap_result_code = LDAP_OPERATIONS_ERROR; + } + if (is_user) { + winsync_plugin_call_post_ad_add_user_cb(prp->agmt, mapped_entry, add_entry, &ldap_result_code); + } else { + winsync_plugin_call_post_ad_add_group_cb(prp->agmt, mapped_entry, add_entry, &ldap_result_code); + } + /* see if plugin reset success/error condition */ + if ((return_value != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + return_value = CONN_OPERATION_SUCCESS; + windows_conn_set_error(prp->conn, ldap_result_code); + } else if ((return_value == CONN_OPERATION_SUCCESS) && ldap_result_code) { + return_value = CONN_OPERATION_FAILED; + windows_conn_set_error(prp->conn, ldap_result_code); + } /* It's possible that the entry already exists in AD, in which * case we fall back to modify it */ /* NGK - This fallback doesn't seem to happen, at least not at this point @@ -1229,7 +1256,7 @@ modify_fallback: /* Fetch the remote entry */ rc = windows_get_remote_entry(prp, remote_dn,&remote_entry); if (0 == rc && remote_entry) { - return_value = windows_update_remote_entry(prp,remote_entry,local_entry); + return_value = windows_update_remote_entry(prp,remote_entry,local_entry,is_user); } if (remote_entry) { @@ -1546,6 +1573,8 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op return_value = CONN_OPERATION_SUCCESS; } else { + int ldap_op = 0; + int ldap_result_code = 0; if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) { int i = 0; @@ -1556,6 +1585,32 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op } } return_value = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(remote_dn), mapped_mods, NULL, NULL /* returned controls */); + windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); + if ((return_value != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + /* op failed but no ldap error code ??? */ + ldap_result_code = LDAP_OPERATIONS_ERROR; + } + if (is_user) { + winsync_plugin_call_post_ad_mod_user_mods_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + local_dn, local_entry, + op->p.p_modify.modify_mods, + remote_dn, mapped_mods, &ldap_result_code); + } else if (is_group) { + winsync_plugin_call_post_ad_mod_group_mods_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + local_dn, local_entry, + op->p.p_modify.modify_mods, + remote_dn, mapped_mods, &ldap_result_code); + } + /* see if plugin reset success/error condition */ + if ((return_value != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + return_value = CONN_OPERATION_SUCCESS; + windows_conn_set_error(prp->conn, ldap_result_code); + } else if ((return_value == CONN_OPERATION_SUCCESS) && ldap_result_code) { + return_value = CONN_OPERATION_FAILED; + windows_conn_set_error(prp->conn, ldap_result_code); + } } if (mapped_mods) { @@ -3872,6 +3927,7 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry, int rc = 0; char *guid_str = NULL; int is_nt4 = windows_private_get_isnt4(prp->agmt); + Slapi_Entry *post_entry = NULL; char *local_user_entry_template = "dn: %s\n" @@ -3996,11 +4052,23 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry, /* Store it */ windows_dump_entry("Adding new local entry",local_entry); pb = slapi_pblock_new(); - slapi_add_entry_internal_set_pb(pb, local_entry, NULL,repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),0); + slapi_add_entry_internal_set_pb(pb, local_entry, NULL,repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),0); + post_entry = slapi_entry_dup(local_entry); slapi_add_internal_pb(pb); local_entry = NULL; /* consumed by add */ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval); + if (is_user) { + winsync_plugin_call_post_ds_add_user_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, post_entry, &retval); + } else if (is_group) { + winsync_plugin_call_post_ds_add_group_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, post_entry, &retval); + } + slapi_entry_free(post_entry); + if (retval) { slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "add operation of entry %s returned: %d\n", slapi_sdn_get_dn(local_sdn), retval); @@ -4429,11 +4497,13 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr } static int -windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry) +windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry, int is_user) { Slapi_Mods smods = {0}; int retval = 0; int do_modify = 0; + int ldap_op = 0; + int ldap_result_code = 0; slapi_mods_init (&smods, 0); retval = windows_generate_update_mods(prp,local_entry,remote_entry,1,&smods,&do_modify); @@ -4446,6 +4516,33 @@ windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry "windows_update_remote_entry: modifying entry %s\n", escape_string(dn, dnbuf)); retval = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)),slapi_mods_get_ldapmods_byref(&smods), NULL,NULL); + + windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); + if ((retval != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + /* op failed but no ldap error code ??? */ + ldap_result_code = LDAP_OPERATIONS_ERROR; + } + if (is_user) { + winsync_plugin_call_post_ad_mod_user_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, /* the cooked ad entry */ + local_entry, /* the ds entry */ + &smods, &ldap_result_code); + } else { + winsync_plugin_call_post_ad_mod_group_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, /* the cooked ad entry */ + local_entry, /* the ds entry */ + &smods, &ldap_result_code); + } + /* see if plugin reset success/error condition */ + if ((retval != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + retval = CONN_OPERATION_SUCCESS; + windows_conn_set_error(prp->conn, ldap_result_code); + } else if ((retval == CONN_OPERATION_SUCCESS) && ldap_result_code) { + retval = CONN_OPERATION_FAILED; + windows_conn_set_error(prp->conn, ldap_result_code); + } } else { char dnbuf[BUFSIZ]; @@ -4453,7 +4550,8 @@ windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "no mods generated for remote entry: %s\n", escape_string(dn, dnbuf)); } - slapi_mods_done(&smods); + + slapi_mods_done(&smods); return retval; } @@ -4572,6 +4670,19 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); slapi_modify_internal_pb (pb); slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); + if (is_user) { + winsync_plugin_call_post_ds_mod_user_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, /* the cooked ad entry */ + local_entry, /* the ds entry */ + &smods, &rc); + } else if (is_group) { + winsync_plugin_call_post_ds_mod_group_cb(prp->agmt, + windows_private_get_raw_entry(prp->agmt), + remote_entry, /* the cooked ad entry */ + local_entry, /* the ds entry */ + &smods, &rc); + } if (rc) { slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, @@ -4624,11 +4735,17 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r } } /* Convert entry to mods */ + windows_is_local_entry_user_or_group(e, &is_user, NULL); if (0 == retval && mapped_entry) { + if (is_user) { + winsync_plugin_call_pre_ad_add_user_cb(prp->agmt, mapped_entry, e); + } else { + winsync_plugin_call_pre_ad_add_group_cb(prp->agmt, mapped_entry, e); + } + /* plugin may reset DN */ + slapi_sdn_copy(slapi_entry_get_sdn(mapped_entry), remote_dn); (void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs); - slapi_entry_free(mapped_entry); - mapped_entry = NULL; if (NULL == entryattrs) { slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_replay_update: Cannot convert entry to LDAPMods.\n",agmt_get_long_name(prp->agmt)); @@ -4636,8 +4753,28 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r } else { + int ldap_op = 0; + int ldap_result_code = 0; windows_log_add_entry_remote(local_dn, remote_dn); retval = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL /* returned controls */); + windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); + if ((retval != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + /* op failed but no ldap error code ??? */ + ldap_result_code = LDAP_OPERATIONS_ERROR; + } + if (is_user) { + winsync_plugin_call_post_ad_add_user_cb(prp->agmt, mapped_entry, e, &ldap_result_code); + } else { + winsync_plugin_call_post_ad_add_group_cb(prp->agmt, mapped_entry, e, &ldap_result_code); + } + /* see if plugin reset success/error condition */ + if ((retval != CONN_OPERATION_SUCCESS) && !ldap_result_code) { + retval = CONN_OPERATION_SUCCESS; + windows_conn_set_error(prp->conn, ldap_result_code); + } else if ((retval == CONN_OPERATION_SUCCESS) && ldap_result_code) { + retval = CONN_OPERATION_FAILED; + windows_conn_set_error(prp->conn, ldap_result_code); + } /* It's possible that the entry already exists in AD, in which case we fall back to modify it */ if (retval) { @@ -4646,7 +4783,6 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r ldap_mods_free(entryattrs, 1); entryattrs = NULL; - windows_is_local_entry_user_or_group(e, &is_user, NULL); if ((retval == 0) && is_user) { /* set the account control bits only for users */ retval = send_accountcontrol_modify(remote_dn, prp, missing_entry); @@ -4660,7 +4796,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r retval = windows_get_remote_entry(prp, remote_dn,&remote_entry); if (0 == retval && remote_entry) { - retval = windows_update_remote_entry(prp,remote_entry,e); + retval = windows_update_remote_entry(prp,remote_entry,e,is_user); /* Detect the case where the error is benign */ if (retval) { @@ -4679,6 +4815,8 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r slapi_entry_free(remote_entry); } } + slapi_entry_free(mapped_entry); + mapped_entry = NULL; slapi_ch_free_string(&password); return retval; } diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h index 52b8dac..7da855c 100644 --- a/ldap/servers/plugins/replication/windowsrepl.h +++ b/ldap/servers/plugins/replication/windowsrepl.h @@ -179,6 +179,41 @@ void winsync_plugin_call_end_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_s void winsync_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree); +void winsync_plugin_call_post_ad_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result); +void winsync_plugin_call_post_ad_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result); +void winsync_plugin_call_post_ds_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result); +void winsync_plugin_call_post_ds_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, + Slapi_Mods *smods, int *result); +void winsync_plugin_call_post_ds_add_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result); +void winsync_plugin_call_post_ds_add_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result); +void winsync_plugin_call_pre_ad_add_user_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry); +void winsync_plugin_call_pre_ad_add_group_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry); +void winsync_plugin_call_post_ad_add_user_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry, int *result); +void winsync_plugin_call_post_ad_add_group_cb(const Repl_Agmt *ra, Slapi_Entry *ad_entry, + Slapi_Entry *ds_entry, int *result); +void winsync_plugin_call_post_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + const Slapi_DN *local_dn, + const Slapi_Entry *ds_entry, + LDAPMod * const *origmods, + Slapi_DN *remote_dn, LDAPMod **modstosend, int *result); +void winsync_plugin_call_post_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, + const Slapi_DN *local_dn, + const Slapi_Entry *ds_entry, + LDAPMod * const *origmods, + Slapi_DN *remote_dn, LDAPMod **modstosend, int *result); + /* Call stack for all places where windows_LDAPMessage2Entry is called: diff --git a/ldap/servers/plugins/replication/winsync-plugin.h b/ldap/servers/plugins/replication/winsync-plugin.h index e70c4a9..9ac5621 100644 --- a/ldap/servers/plugins/replication/winsync-plugin.h +++ b/ldap/servers/plugins/replication/winsync-plugin.h @@ -49,6 +49,7 @@ * WinSync plug-in API */ #define WINSYNC_v1_0_GUID "CDA8F029-A3C6-4EBB-80B8-A2E183DB0481" +#define WINSYNC_v2_0_GUID "706B83AA-FC51-444A-ACC9-53DC73D641D4" /* * This callback is called when a winsync agreement is created. @@ -60,6 +61,8 @@ */ typedef void * (*winsync_plugin_init_cb)(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree); #define WINSYNC_PLUGIN_INIT_CB 1 +#define WINSYNC_PLUGIN_VERSION_1_BEGIN WINSYNC_PLUGIN_INIT_CB + /* agmt_dn - const - the original AD base dn from the winsync agreement scope - set directly e.g. *scope = 42; base, filter - malloced - to set, free first e.g. @@ -184,12 +187,99 @@ typedef void (*winsync_plugin_update_cb)(void *cookie, const Slapi_DN *ds_subtre */ typedef void (*winsync_plugin_destroy_agmt_cb)(void *cookie, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree); #define WINSYNC_PLUGIN_DESTROY_AGMT_CB 19 +#define WINSYNC_PLUGIN_VERSION_1_END WINSYNC_PLUGIN_DESTROY_AGMT_CB + +/* Functions added for API version 2.0 */ +/* + * These callbacks are called after a modify operation. They are called upon both + * success and failure of the modify operation. The plugin is responsible for + * looking at the result code of the modify to decide what action to take. The + * plugin may change the result code e.g. to force an error for an otherwise + * successful operation, or to ignore certain errors. + * rawentry - the raw AD entry, read directly from AD - this is read only + * ad_entry - the "cooked" AD entry - the entry passed to the pre_mod callback + * ds_entry - the entry from the ds - the DS entry passed to the pre_mod callback + * smods - the mods used in the modify operation + * result - the result code from the modify operation - the plugin can change this + */ +typedef void (*winsync_post_mod_cb)(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *result); +#define WINSYNC_PLUGIN_POST_AD_MOD_USER_CB 20 +#define WINSYNC_PLUGIN_POST_AD_MOD_GROUP_CB 21 +#define WINSYNC_PLUGIN_POST_DS_MOD_USER_CB 22 +#define WINSYNC_PLUGIN_POST_DS_MOD_GROUP_CB 23 + +#define WINSYNC_PLUGIN_VERSION_2_BEGIN WINSYNC_PLUGIN_POST_AD_MOD_USER_CB +/* + * These callbacks are called after an attempt to add a new entry to the + * local directory server from AD. They are called upon success or failure + * of the add attempt. The result code tells if the operation succeeded. + * The plugin may change the result code e.g. to force an error for an + * otherwise successful operation, or to ignore certain errors. + * rawentry - the raw AD entry, read directly from AD - this is read only + * ad_entry - the "cooked" AD entry + * ds_entry - the entry attempted to be added to the DS + * result - the result code from the add operation - plugin may change this + */ +typedef void (*winsync_post_add_cb)(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result); +#define WINSYNC_PLUGIN_POST_DS_ADD_USER_CB 24 +#define WINSYNC_PLUGIN_POST_DS_ADD_GROUP_CB 25 /* + * These callbacks are called when a new entry is being added to AD from + * the local directory server. + * ds_entry - the local DS entry + * ad_entry - the entry to be added to AD - all modifications should + * be made to this entry, including changing the DN if needed, + * since the DN of this entry will be used as the ADD target DN + * This entry will already have had the default schema mapping applied +*/ +typedef void (*winsync_pre_ad_add_cb)(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry); +#define WINSYNC_PLUGIN_PRE_AD_ADD_USER_CB 26 +#define WINSYNC_PLUGIN_PRE_AD_ADD_GROUP_CB 27 + +/* + * These callbacks are called after an attempt to add a new entry to AD from + * the local directory server. They are called upon success or failure + * of the add attempt. The result code tells if the operation succeeded. + * The plugin may change the result code e.g. to force an error for an + * otherwise successful operation, or to ignore certain errors. + * ad_entry - the AD entry + * ds_entry - the DS entry + * result - the result code from the add operation - plugin may change this + */ +typedef void (*winsync_post_ad_add_cb)(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry, int *result); +#define WINSYNC_PLUGIN_POST_AD_ADD_USER_CB 28 +#define WINSYNC_PLUGIN_POST_AD_ADD_GROUP_CB 29 + +/* + * These callbacks are called after a mod operation has been replayed + * to AD. This case is different than the pre add or pre mod callbacks + * above because in this context, we may only have the list of modifications + * and the DN to which the mods were applied. If the plugin wants the modified + * entry, the plugin can search for it from AD. The plugin is called upon + * success or failure of the modify operation. The result parameter gives + * the ldap result code of the operation. The plugin may change the result code + * e.g. to force an error for an otherwise successful operation, or to ignore + * certain errors. + * rawentry - the raw AD entry, read directly from AD - may be NULL + * local_dn - the original local DN used in the modification + * ds_entry - the current DS entry that has the operation nsUniqueID + * origmods - the original mod list + * remote_dn - the DN of the AD entry + * modstosend - the mods sent to AD + * result - the result code of the modify operation + * + */ +typedef void (*winsync_post_ad_mod_mods_cb)(void *cookie, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, const Slapi_Entry *ds_entry, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod **modstosend, int *result); +#define WINSYNC_PLUGIN_POST_AD_MOD_USER_MODS_CB 30 +#define WINSYNC_PLUGIN_POST_AD_MOD_GROUP_MODS_CB 31 +#define WINSYNC_PLUGIN_VERSION_2_END WINSYNC_PLUGIN_POST_AD_MOD_GROUP_MODS_CB +/* The following are sample code stubs to show how to implement a plugin which uses this api */ +/* #define WINSYNC_SAMPLE_CODE */ #ifdef WINSYNC_SAMPLE_CODE #include "slapi-plugin.h" @@ -373,13 +463,13 @@ test_winsync_get_new_ds_user_dn_cb(void *cbdata, const Slapi_Entry *rawentry, rdns = slapi_ldap_explode_dn(*new_dn_string, 0); if (!rdns || !rdns[0]) { - ldap_value_free(rdns); + slapi_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_ldap_value_free(rdns); slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, "<-- test_winsync_get_new_ds_user_dn_cb -- new dn [%s] -- end\n", @@ -442,7 +532,8 @@ test_winsync_can_add_entry_to_ad_cb(void *cbdata, const Slapi_Entry *local_entry slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, "<-- test_winsync_can_add_entry_to_ad_cb -- end\n"); - return 0; /* false - do not allow entries to be added to ad */ + /* return 0;*/ /* false - do not allow entries to be added to ad */ + return 1; /* true - allow entries to be added to ad */ } static void @@ -486,6 +577,200 @@ test_winsync_destroy_agmt_cb(void *cbdata, const Slapi_DN *ds_subtree, return; } +static void +test_winsync_post_ad_mod_user_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_mod_user_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying AD entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ad_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_mod_user_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ad_mod_group_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_mod_group_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying AD entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ad_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_mod_group_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ds_mod_user_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ds_mod_user_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying DS entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ds_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ds_mod_user_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ds_mod_group_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ds_mod_group_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying DS entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ds_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ds_mod_group_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ds_add_user_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ds_add_user_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of adding DS entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ds_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ds_add_user_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ds_add_group_cb(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ds_add_group_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of adding DS entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ds_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ds_add_group_cb -- end\n"); + + return; +} + +static void +test_winsync_pre_ad_add_user_cb(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_pre_ad_add_user_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Adding AD entry [%s] from add of DS entry [%s]\n", + slapi_entry_get_dn(ad_entry), slapi_entry_get_dn(ds_entry)); + /* make modifications to ad_entry here */ + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_pre_ad_add_user_cb -- end\n"); + + return; +} + +static void +test_winsync_pre_ad_add_group_cb(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_pre_ad_add_group_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Adding AD entry [%s] from add of DS entry [%s]\n", + slapi_entry_get_dn(ad_entry), slapi_entry_get_dn(ds_entry)); + /* make modifications to ad_entry here */ + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_pre_ad_add_group_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ad_add_user_cb(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_add_user_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of adding AD entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ad_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_add_user_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ad_add_group_cb(void *cookie, Slapi_Entry *ds_entry, Slapi_Entry *ad_entry, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_add_group_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of adding AD entry [%s] was [%d:%s]\n", + slapi_entry_get_dn(ad_entry), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_add_group_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ad_mod_user_mods_cb(void *cookie, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, const Slapi_Entry *ds_entry, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_mod_user_mods_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying AD entry [%s] was [%d:%s]\n", + slapi_sdn_get_dn(remote_dn), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_mod_user_mods_cb -- end\n"); + + return; +} + +static void +test_winsync_post_ad_mod_group_mods_cb(void *cookie, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, const Slapi_Entry *ds_entry, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend, int *result) +{ + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "--> test_winsync_post_ad_mod_group_mods_cb -- begin\n"); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "Result of modifying AD entry [%s] was [%d:%s]\n", + slapi_sdn_get_dn(remote_dn), *result, ldap_err2string(*result)); + + slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, + "<-- test_winsync_post_ad_mod_group_mods_cb -- end\n"); + + return; +} + /** * Plugin identifiers */ @@ -498,7 +783,8 @@ static Slapi_PluginDesc test_winsync_pdesc = { static Slapi_ComponentId *test_winsync_plugin_id = NULL; -static void *test_winsync_api[] = { +#ifdef TEST_V1_WINSYNC_API +static void *test_winsync_api_v1[] = { NULL, /* reserved for api broker use, must be zero */ test_winsync_api_init, test_winsync_dirsync_search_params_cb, @@ -520,6 +806,42 @@ static void *test_winsync_api[] = { test_winsync_end_update_cb, test_winsync_destroy_agmt_cb }; +#endif /* TEST_V1_WINSYNC_API */ + +static void *test_winsync_api_v2[] = { + NULL, /* reserved for api broker use, must be zero */ + test_winsync_api_init, + test_winsync_dirsync_search_params_cb, + test_winsync_pre_ad_search_cb, + test_winsync_pre_ds_search_entry_cb, + test_winsync_pre_ds_search_all_cb, + test_winsync_pre_ad_mod_user_cb, + test_winsync_pre_ad_mod_group_cb, + test_winsync_pre_ds_mod_user_cb, + test_winsync_pre_ds_mod_group_cb, + test_winsync_pre_ds_add_user_cb, + test_winsync_pre_ds_add_group_cb, + test_winsync_get_new_ds_user_dn_cb, + test_winsync_get_new_ds_group_dn_cb, + test_winsync_pre_ad_mod_user_mods_cb, + test_winsync_pre_ad_mod_group_mods_cb, + test_winsync_can_add_entry_to_ad_cb, + test_winsync_begin_update_cb, + test_winsync_end_update_cb, + test_winsync_destroy_agmt_cb, + test_winsync_post_ad_mod_user_cb, + test_winsync_post_ad_mod_group_cb, + test_winsync_post_ds_mod_user_cb, + test_winsync_post_ds_mod_group_cb, + test_winsync_post_ds_add_user_cb, + test_winsync_post_ds_add_group_cb, + test_winsync_pre_ad_add_user_cb, + test_winsync_pre_ad_add_group_cb, + test_winsync_post_ad_add_user_cb, + test_winsync_post_ad_add_group_cb, + test_winsync_post_ad_mod_user_mods_cb, + test_winsync_post_ad_mod_group_mods_cb +}; static int test_winsync_plugin_start(Slapi_PBlock *pb) @@ -527,7 +849,7 @@ test_winsync_plugin_start(Slapi_PBlock *pb) slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, "--> test_winsync_plugin_start -- begin\n"); - if( slapi_apib_register(WINSYNC_v1_0_GUID, test_winsync_api) ) { + if( slapi_apib_register(WINSYNC_v2_0_GUID, test_winsync_api_v2) ) { slapi_log_error( SLAPI_LOG_FATAL, test_winsync_plugin_name, "<-- test_winsync_plugin_start -- failed to register winsync api -- end\n"); return -1; @@ -544,7 +866,7 @@ test_winsync_plugin_close(Slapi_PBlock *pb) slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, "--> test_winsync_plugin_close -- begin\n"); - slapi_apib_unregister(WINSYNC_v1_0_GUID); + slapi_apib_unregister(WINSYNC_v2_0_GUID); slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name, "<-- test_winsync_plugin_close -- end\n");