Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 317807 Details for
Bug 459729
Windows sync support in IPA
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Add account disable and force sync
0012-Adds-winsync-account-disable-and-force-sync.patch (text/plain), 41.92 KB, created by
Rich Megginson
on 2008-09-26 16:19:20 UTC
(
hide
)
Description:
Add account disable and force sync
Filename:
MIME Type:
Creator:
Rich Megginson
Created:
2008-09-26 16:19:20 UTC
Size:
41.92 KB
patch
obsolete
>From 997169b5f69c35f6a9dfd1d96e5e7cbd6940db0b Mon Sep 17 00:00:00 2001 >From: Rich Megginson <rmeggins@redhat.com> >Date: Fri, 26 Sep 2008 10:16:04 -0600 >Subject: [PATCH] Adds winsync account disable and force sync > >--- > .../ipa-winsync/ipa-winsync-conf.ldif | 4 + > .../ipa-winsync/ipa-winsync-config.c | 201 +++++++- > .../ipa-slapi-plugins/ipa-winsync/ipa-winsync.c | 539 +++++++++++++++++++- > .../ipa-slapi-plugins/ipa-winsync/ipa-winsync.h | 35 ++- > 4 files changed, 772 insertions(+), 7 deletions(-) > >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 >index 8bf8e27..71d235e 100644 >--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif >+++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif >@@ -22,3 +22,7 @@ ipaWinSyncUserFlatten: true > ipaWinsyncHomeDirAttr: ipaHomesRootDir > ipaWinSyncDefaultGroupAttr: ipaDefaultPrimaryGroup > ipaWinSyncDefaultGroupFilter: (gidNumber=*)(objectclass=posixGroup) >+ipaWinSyncAcctDisable: none >+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 >index f4c4484..a887e89 100644 >--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c >+++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c >@@ -157,6 +157,29 @@ ipa_winsync_config(Slapi_Entry *config_e) > 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; >+ } >+ if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_TO_AD)) { >+ retval = ACCT_DISABLE_TO_AD; >+ } >+ if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_TO_DS)) { >+ retval = ACCT_DISABLE_TO_DS; >+ } >+ if (!PL_strcasecmp(theval, IPA_WINSYNC_ACCT_DISABLE_BOTH)) { >+ retval = ACCT_DISABLE_BOTH; >+ } >+ >+ return retval; >+} >+ > /* > Validate the pending changes in the e entry. > */ >@@ -167,6 +190,8 @@ ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_E > char **attrsvals = NULL; > int ii; > Slapi_Attr *testattr = NULL; >+ char *strattr = NULL; >+ int acct_disable; > > *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ > >@@ -282,10 +307,56 @@ ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_E > 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; > >@@ -297,8 +368,9 @@ done2: > } > > static int >-ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, >- int *returncode, char *returntext, void *arg) >+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; >@@ -308,9 +380,14 @@ ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr > 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 */ > >@@ -392,6 +469,52 @@ ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr > 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); >@@ -459,6 +582,14 @@ ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr > 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; >@@ -475,6 +606,9 @@ done3: > 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; >@@ -510,6 +644,8 @@ ipa_winsync_config_destroy_domain( > 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; >@@ -583,7 +719,11 @@ internal_find_entry_get_attr_val(const Slapi_DN *basedn, int scope, > } > } > if (attrval) { >- *attrval = slapi_entry_attr_get_charptr(entries[0], attrname); >+ 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; >@@ -633,6 +773,11 @@ ipa_winsync_config_refresh_domain( > 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); >@@ -642,6 +787,11 @@ ipa_winsync_config_refresh_domain( > 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 >@@ -737,6 +887,38 @@ ipa_winsync_config_refresh_domain( > 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); >@@ -759,7 +941,14 @@ ipa_winsync_config_refresh_domain( > 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); >@@ -773,6 +962,10 @@ out: > 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); >diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c >index c69a683..f18a939 100644 >--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c >+++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c >@@ -61,6 +61,25 @@ > > 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. > */ >@@ -121,6 +140,11 @@ ipa_winsync_pre_ds_search_entry_cb(void *cbdata, const char *agmt_dn, > "--> 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; >@@ -157,6 +181,9 @@ ipa_winsync_pre_ad_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, > 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"); > >@@ -185,6 +212,11 @@ ipa_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, > 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"); > >@@ -376,6 +408,8 @@ ipa_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry, > } > } > >+ 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"); > >@@ -449,12 +483,25 @@ ipa_winsync_get_new_ds_group_dn_cb(void *cbdata, const Slapi_Entry *rawentry, > > static void > ipa_winsync_pre_ad_mod_user_mods_cb(void *cbdata, const Slapi_Entry *rawentry, >- const Slapi_DN *local_dn, LDAPMod * const *origmods, >+ 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"); > >@@ -463,7 +510,9 @@ ipa_winsync_pre_ad_mod_user_mods_cb(void *cbdata, const Slapi_Entry *rawentry, > > static void > ipa_winsync_pre_ad_mod_group_mods_cb(void *cbdata, const Slapi_Entry *rawentry, >- const Slapi_DN *local_dn, LDAPMod * const *origmods, >+ 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, >@@ -663,3 +712,489 @@ int ipa_winsync_plugin_init(Slapi_PBlock *pb) > "<-- 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; >+ if (ad_is_enabled) { >+ /* add user to activated group, delete from inactivated group */ >+ adddn = ipaconfig->activated_group_dn; >+ 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 */ >+ rc = do_group_modify(adddn, "member", LDAP_MOD_ADD, dsdn); >+ 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); >+ } >+ } >+ 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 >index b625772..58a9a6c 100644 >--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h >+++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h >@@ -65,6 +65,10 @@ typedef struct ipa_winsync_config_struct { > 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; > > /* >@@ -75,6 +79,8 @@ 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); >@@ -123,5 +129,32 @@ void ipa_winsync_config_destroy_domain(void *cbdata, const Slapi_DN *ds_subtree, > #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 */ >-- >1.5.5.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 459729
:
314729
|
314730
|
314731
|
314732
|
314733
|
314844
|
314845
|
316460
|
317002
| 317807 |
318214
|
319412
|
319413
|
319414
|
319415
|
319416
|
319786
|
320039
|
320040