/* create a new updatedn list - if the entry is given, initialize the list from the replicabinddn values given in the entry */ ReplicaUpdateDNList replica_updatedn_list_new(const Slapi_Entry *entry) { /* allocate table */ PLHashTable *hash = PL_NewHashTable(4, PL_HashString, PL_CompareStrings, updatedn_compare_dns, NULL, NULL); if (hash == NULL) { slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_new_updatedn_list - " "Failed to allocate hash table; NSPR error - %d\n", PR_GetError ()); return NULL; } if (entry) { Slapi_Attr *attr = NULL; if (!slapi_entry_attr_find(entry, attr_replicaBindDn, &attr)) { Slapi_ValueSet *vs = NULL; slapi_attr_get_valueset(attr, &vs); replica_updatedn_list_replace(hash, vs); slapi_valueset_free(vs); } } return (ReplicaUpdateDNList)hash; }
Slapi_ValueSet * replica_updatedn_list_get_members(Slapi_DN *dn) { static char* const filter_groups = "(|(objectclass=groupOfNames)(objectclass=groupOfUniqueNames)(objectclass=groupOfURLs))"; static char* const type_member = "member"; static char* const type_uniquemember = "uniquemember"; static char* const type_memberURL = "memberURL"; int rval; char *attrs[4]; Slapi_PBlock *mpb = slapi_pblock_new (); Slapi_ValueSet *members = slapi_valueset_new(); attrs[0] = type_member; attrs[1] = type_uniquemember; attrs[2] = type_memberURL; attrs[3] = NULL; slapi_search_internal_set_pb ( mpb, slapi_sdn_get_ndn(dn), LDAP_SCOPE_BASE, filter_groups, &attrs[0], 0, NULL /* controls */, NULL /* uniqueid */, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); slapi_search_internal_pb(mpb); slapi_pblock_get(mpb, SLAPI_PLUGIN_INTOP_RESULT, &rval); if (rval == LDAP_SUCCESS) { Slapi_Entry **ep; slapi_pblock_get(mpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &ep); if ((ep != NULL) && (ep[0] != NULL)) { Slapi_Attr *attr = NULL; Slapi_Attr *nextAttr = NULL; Slapi_ValueSet *vs = NULL; char *attrType; slapi_entry_first_attr ( ep[0], &attr); while (attr) { slapi_attr_get_type ( attr, &attrType ); if ((strcasecmp (attrType, type_member) == 0) || (strcasecmp (attrType, type_uniquemember) == 0 )) { slapi_attr_get_valueset(attr, &vs); slapi_valueset_join_attr_valueset(attr, members, vs); slapi_valueset_free(vs); } else if (strcasecmp (attrType, type_memberURL) == 0) { /* not yet supported */ } slapi_entry_next_attr ( ep[0], attr, &nextAttr ); attr = nextAttr; } } } slapi_free_search_results_internal(mpb); slapi_pblock_destroy (mpb); return(members); }
/* * usn_start: usn_rootdse_init -- set rootdse callback to aggregate in rootDSE * usn_cleanup_start -- initialize USN tombstone cleanup task */ static int usn_start(Slapi_PBlock *pb) { int rc = 0; Slapi_Value *value; slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_start\n"); rc = usn_rootdse_init(); rc |= usn_cleanup_start(pb); if (rc) { goto bail; } if (0) { /* Not executed; test code for slapi_get_plugin_default_config */ Slapi_ValueSet *vs = NULL; Slapi_Value *v = NULL; int i; slapi_get_plugin_default_config("nsds5ReplicatedAttributeList", &vs); if (vs) { for (i = slapi_valueset_first_value(vs, &v); i != -1; i = slapi_valueset_next_value(vs, i, &v)) { slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM, "nsds5ReplicatedAttributeList: %s\n", slapi_value_get_string(v)); } } slapi_valueset_free(vs); } /* add nsds5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE entryusn * to cn=plugin default config,cn=config */ value = slapi_value_new_string("(objectclass=*) $ EXCLUDE entryusn"); rc = slapi_set_plugin_default_config("nsds5ReplicatedAttributeList", value); slapi_value_free(&value); g_plugin_started = 1; bail: slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_start (rc: %d)\n", rc); return rc; }
/* * add a list of dns to the ReplicaUpdateDNList. * The dn could be the dn of a group, so get the entry * and check the objectclass. If it is a static or dynamic group * generate the list of member dns and recursively call * replica_updatedn_list_add(). * The dn of the group is added to the list, so it will detect * potential circular group definitions */ void replica_updatedn_list_add_ext(ReplicaUpdateDNList list, const Slapi_ValueSet *vs, int group_update) { PLHashTable *hash = list; Slapi_ValueSet *vs_nc = (Slapi_ValueSet *)vs; /* cast away const */ Slapi_Value *val = NULL; int index = 0; PR_ASSERT(list && vs); for (index = slapi_valueset_first_value(vs_nc, &val); val; index = slapi_valueset_next_value(vs_nc, index, &val)) { Slapi_DN *dn = slapi_sdn_new_dn_byval(slapi_value_get_string(val)); const char *ndn = slapi_sdn_get_ndn(dn); /* make sure that the name is unique */ if (PL_HashTableLookup(hash, ndn) != NULL) { slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "replica_updatedn_list_add - " "Update DN with value (%s) already in the update DN list\n", ndn); slapi_sdn_free(&dn); } else { Slapi_ValueSet *members = NULL; PL_HashTableAdd(hash, ndn, dn); /* add it, even if it is a group dn, this will * prevent problems with circular group definitions * then check if it has mor members to add */ if (group_update) { members = replica_updatedn_list_get_members(dn); if (members) { replica_updatedn_list_add_ext(list, members, 1); /* free members */ slapi_valueset_free(members); } } } } return; }
void _ger_get_attrs_rights ( Slapi_PBlock *gerpb, Slapi_Entry *e, const char *subjectndn, char **attrs, char **gerstr, size_t *gerstrsize, size_t *gerstrcap, char **errbuf ) { int isfirstattr = 1; /* gerstr was initially allocated with enough space for one more line */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL); /* * If it's stated attribute list is given, * the first attr in the list should not be empty. * Otherwise, it's considered the list is not given. */ if (attrs && *attrs && (strlen(*attrs) > 0)) { int i = 0; char **allattrs = NULL; char **opattrs = NULL; char **noexpattrs = NULL; /* attrs not to expose */ char **myattrs = NULL; char **thisattr = NULL; int hasstar = charray_inlist(attrs, "*"); int hasplus = charray_inlist(attrs, "+"); Slapi_Attr *objclasses = NULL; Slapi_ValueSet *objclassvals = NULL; int isextensibleobj = 0; /* get all attrs available for the entry */ slapi_entry_attr_find(e, "objectclass", &objclasses); if (NULL != objclasses) { Slapi_Value *v; slapi_attr_get_valueset(objclasses, &objclassvals); i = slapi_valueset_first_value(objclassvals, &v); if (-1 != i) { const char *ocname = NULL; allattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } /* add "aci" to the allattrs to adjust to do_search */ charray_add(&allattrs, slapi_attr_syntax_normalize("aci")); while (-1 != i) { i = slapi_valueset_next_value(objclassvals, i, &v); if (-1 != i) { myattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/); charray_free(myattrs); } } } slapi_valueset_free(objclassvals); } /* get operational attrs */ opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR); noexpattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_NOEXPOSE); /* subtract no expose attrs from opattrs (e.g., unhashed pw) */ charray_subtract(opattrs, noexpattrs, NULL); if (isextensibleobj) { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } } else { if (hasstar && hasplus) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTS(opattrs); } else if (hasstar) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs); } else if (hasplus) { GER_GET_ATTR_RIGHTS(opattrs); GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs); } else { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } if (charray_inlist(noexpattrs, attrs[i])) { continue; } else if (charray_inlist(allattrs, attrs[i]) || charray_inlist(opattrs, attrs[i]) || (0 == strcasecmp(attrs[i], "dn")) || (0 == strcasecmp(attrs[i], "distinguishedName"))) { _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } else { /* if the attr does not belong to the entry, "<attr>:none" is returned */ if (!isfirstattr) { _append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL); } _append_gerstr(gerstr, gerstrsize, gerstrcap, attrs[i], ":"); _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL); isfirstattr = 0; } } } } charray_free(allattrs); charray_free(opattrs); } else { Slapi_Attr *prevattr = NULL, *attr; char *type; while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 ) { if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) ) { slapi_attr_get_type ( attr, &type ); _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } prevattr = attr; } } if ( isfirstattr ) { /* not a single attribute was retrived or specified */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL); } return; }
/* * Perform the agreement/domain specific configuration. * IPA stores its configuration in the tree. We use the * ds_subtree to search for the domain/realm specific * configuration entries. */ void ipa_winsync_config_refresh_domain( void *cbdata, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree ) { IPA_WinSync_Domain_Config *iwdc = (IPA_WinSync_Domain_Config *)cbdata; Slapi_DN *config_dn = slapi_sdn_dup(ds_subtree); char *realm_filter = NULL; char *realm_attr = NULL; char *new_entry_filter = NULL; char *new_user_oc_attr = NULL; /* don't care about groups for now */ char *homedir_prefix_attr = NULL; char *login_shell_attr = NULL; char *default_group_attr = NULL; char *default_group_filter = NULL; char *default_group_name = NULL; char *real_group_filter = NULL; char *default_gid = NULL; Slapi_ValueSet *new_user_objclasses = NULL; /* don't care about groups for now */ int loopdone = 0; int search_scope = LDAP_SCOPE_SUBTREE; int ret = LDAP_SUCCESS; int acct_disable; char *inactivated_filter = NULL; char *activated_filter = NULL; char *inactivated_group_dn = NULL; char *activated_group_dn = NULL; int upg = -1; slapi_lock_mutex(theConfig.lock); realm_filter = slapi_ch_strdup(theConfig.realm_filter); realm_attr = slapi_ch_strdup(theConfig.realm_attr); new_entry_filter = slapi_ch_strdup(theConfig.new_entry_filter); new_user_oc_attr = slapi_ch_strdup(theConfig.new_user_oc_attr); homedir_prefix_attr = slapi_ch_strdup(theConfig.homedir_prefix_attr); if (theConfig.login_shell_attr) { login_shell_attr = slapi_ch_strdup(theConfig.login_shell_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) { if (theConfig.inactivated_filter) { inactivated_filter = slapi_ch_strdup(theConfig.inactivated_filter); } if (theConfig.activated_filter) { activated_filter = slapi_ch_strdup(theConfig.activated_filter); } } slapi_unlock_mutex(theConfig.lock); /* starting at ds_subtree, search for the entry containing the Kerberos realm to use */ slapi_ch_free_string(&iwdc->realm_name); while(!loopdone && !slapi_sdn_isempty(config_dn)) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, realm_filter, realm_attr, NULL, &iwdc->realm_name); if ((0 == ret) && iwdc->realm_name) { loopdone = 1; } else if ((LDAP_NO_SUCH_OBJECT == ret) && !iwdc->realm_name) { /* try again */ Slapi_DN *parent_dn = slapi_sdn_new(); slapi_sdn_get_parent(config_dn, parent_dn); slapi_sdn_free(&config_dn); config_dn = parent_dn; } else { /* error */ goto out; } } if (!iwdc->realm_name) { /* error - could not find the IPA config entry with the realm name */ LOG_FATAL("Error: could not find the entry containing the realm name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr); goto out; } /* look for the entry containing the default objectclasses to add to new entries */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, new_user_oc_attr, &new_user_objclasses, NULL); if (!new_user_objclasses) { /* error - could not find the entry containing list of objectclasses */ LOG_FATAL("Error: could not find the entry containing the new user objectclass list " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr); goto out; } /* get the home directory prefix value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->homedir_prefix); ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, homedir_prefix_attr, NULL, &iwdc->homedir_prefix); if (!iwdc->homedir_prefix) { /* error - could not find the home dir prefix */ LOG_FATAL("Error: could not find the entry containing the home directory prefix " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr); goto out; } /* get the login shell value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->login_shell); if (login_shell_attr) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, login_shell_attr, NULL, &iwdc->login_shell); if (!iwdc->login_shell) { LOG("Warning: could not find the entry containing the login shell " "attribute [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, login_shell_attr); } } if (!iwdc->login_shell) { /* could not find the login shell or was not configured */ LOG("Warning: no login shell configured!"); } /* find the default group - the entry above contains the group name, but we need the gidNumber for posixAccount - so first find the entry and attr value which has the group name, then lookup the group number from the group name */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, default_group_attr, NULL, &default_group_name); if (!default_group_name) { /* error - could not find the default group name */ LOG_FATAL("Error: could not find the entry containing the default group name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr); goto out; } /* check if User Private Groups are enabled */ upg = ipa_winsync_upg_enabled(ds_subtree); /* next, find the group whose name is default_group_name - construct the filter based on the filter attribute value - assumes the group name is stored in the cn attribute value, and the gidNumber in the gidNumber attribute value */ real_group_filter = slapi_ch_smprintf("(&(cn=%s)%s)", default_group_name, default_group_filter); ret = internal_find_entry_get_attr_val(config_dn, search_scope, real_group_filter, "gidNumber", NULL, &default_gid); if (!default_gid) { /* error - could not find the default gidNumber This is not a fatal error if User Private Groups (UPG) are enabled. */ if (upg) { LOG_FATAL("Error: could not find the entry containing the default gidNumber " "UPG [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, "gidNumber"); goto out; } else { ret = LDAP_SUCCESS; } } /* 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) { if (inactivated_filter) { 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 */ LOG("Could not find the DN of the inactivated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), inactivated_filter); goto out; } } if (activated_filter) { 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 */ LOG("Could not find the DN of the activated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), activated_filter); goto out; } } } /* ok, we have our values */ /* first, clear out the old domain config */ slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; /* next, copy the global attr config */ slapi_lock_mutex(theConfig.lock); iwdc->domain_e = slapi_entry_dup(theConfig.config_e); slapi_unlock_mutex(theConfig.lock); /* set the objectclasses in the domain_e */ slapi_entry_attr_delete(iwdc->domain_e, "objectclass"); /* this copies new_user_objclasses */ slapi_entry_add_valueset(iwdc->domain_e, "objectclass", new_user_objclasses); /* When UPG is disabled, set the default gid number */ if (upg && default_gid) { slapi_entry_attr_set_charptr(iwdc->domain_e, "gidNumber", default_gid); } slapi_ch_free_string(&iwdc->inactivated_group_dn); iwdc->inactivated_group_dn = inactivated_group_dn; inactivated_group_dn = NULL; slapi_ch_free_string(&iwdc->activated_group_dn); iwdc->activated_group_dn = activated_group_dn; activated_group_dn = NULL; out: slapi_valueset_free(new_user_objclasses); slapi_sdn_free(&config_dn); slapi_ch_free_string(&realm_filter); slapi_ch_free_string(&realm_attr); slapi_ch_free_string(&new_entry_filter); slapi_ch_free_string(&new_user_oc_attr); slapi_ch_free_string(&homedir_prefix_attr); slapi_ch_free_string(&login_shell_attr); slapi_ch_free_string(&default_group_attr); slapi_ch_free_string(&default_group_filter); slapi_ch_free_string(&default_group_name); slapi_ch_free_string(&real_group_filter); slapi_ch_free_string(&default_gid); slapi_ch_free_string(&inactivated_filter); slapi_ch_free_string(&inactivated_group_dn); slapi_ch_free_string(&activated_filter); slapi_ch_free_string(&activated_group_dn); if (LDAP_SUCCESS != ret) { slapi_ch_free_string(&iwdc->realm_name); slapi_ch_free_string(&iwdc->homedir_prefix); slapi_ch_free_string(&iwdc->login_shell); slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; } return; }