/* * 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; }
/* * memberof_apply_config() * * Apply the pending changes in the e entry to our config struct. * memberof_validate_config() must have already been called. */ int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { Slapi_Entry *config_entry = NULL; Slapi_DN *config_sdn = NULL; char **groupattrs = NULL; char *memberof_attr = NULL; char *filter_str = NULL; int num_groupattrs = 0; int groupattr_name_len = 0; char *allBackends = NULL; char **entryScopes = NULL; char **entryScopeExcludeSubtrees = NULL; char *sharedcfg = NULL; char *skip_nested = NULL; char *auto_add_oc = NULL; int num_vals = 0; *returncode = LDAP_SUCCESS; /* * Check if this is a shared config entry */ sharedcfg = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA); if(sharedcfg){ if((config_sdn = slapi_sdn_new_dn_byval(sharedcfg))){ slapi_search_internal_get_entry(config_sdn, NULL, &config_entry, memberof_get_plugin_id()); if(config_entry){ /* Set the entry to be the shared config entry. Validation was done in preop */ e = config_entry; } else { /* This should of been checked in preop validation */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "memberof_apply_config - Failed to locate shared config entry (%s)", sharedcfg); slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM,"%s\n",returntext); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } } /* * Apply the config settings */ groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR); memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR); allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR); skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR); auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC); /* * We want to be sure we don't change the config in the middle of * a memberOf operation, so we obtain an exclusive lock here */ memberof_wlock_config(); if (groupattrs) { int i = 0; slapi_ch_array_free(theConfig.groupattrs); theConfig.groupattrs = groupattrs; groupattrs = NULL; /* config now owns memory */ /* * We allocate a list of Slapi_Attr using the groupattrs for * convenience in our memberOf comparison functions */ for (i = 0; theConfig.group_slapiattrs && theConfig.group_slapiattrs[i]; i++) { slapi_attr_free(&theConfig.group_slapiattrs[i]); } /* Count the number of groupattrs. */ for (num_groupattrs = 0; theConfig.groupattrs && theConfig.groupattrs[num_groupattrs]; num_groupattrs++) { /* * Add up the total length of all attribute names. We need * to know this for building the group check filter later. */ groupattr_name_len += strlen(theConfig.groupattrs[num_groupattrs]); } /* Realloc the list of Slapi_Attr if necessary. */ if (i < num_groupattrs) { theConfig.group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)theConfig.group_slapiattrs, sizeof(Slapi_Attr *) * (num_groupattrs + 1)); } /* Build the new list */ for (i = 0; theConfig.groupattrs[i]; i++) { theConfig.group_slapiattrs[i] = slapi_attr_new(); slapi_attr_init(theConfig.group_slapiattrs[i], theConfig.groupattrs[i]); } /* Terminate the list. */ theConfig.group_slapiattrs[i] = NULL; /* The filter is based off of the groupattr, so we update it here too. */ slapi_filter_free(theConfig.group_filter, 1); if (num_groupattrs > 1) { int bytes_out = 0; int filter_str_len = groupattr_name_len + (num_groupattrs * 4) + 4; /* Allocate enough space for the filter */ filter_str = slapi_ch_malloc(filter_str_len); /* Add beginning of filter. */ bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|"); /* Add filter section for each groupattr. */ for (i = 0; theConfig.groupattrs[i]; i++) { bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out, "(%s=*)", theConfig.groupattrs[i]); } /* Add end of filter. */ snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")"); } else { filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattrs[0]); } /* * Log an error if we were unable to build the group filter for some * reason. If this happens, the memberOf plugin will not be able to * check if an entry is a group, causing it to not catch changes. This * shouldn't happen, but there may be some garbage configuration that * could trigger this. */ if ((theConfig.group_filter = slapi_str2filter(filter_str)) == NULL) { slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_apply_config - Unable to create the group check filter. The memberOf " "plug-in will not operate on changes to groups. Please check " "your %s configuration settings. (filter: %s)\n", MEMBEROF_GROUP_ATTR, filter_str ); } slapi_ch_free_string(&filter_str); } if (memberof_attr) { slapi_ch_free_string(&theConfig.memberof_attr); theConfig.memberof_attr = memberof_attr; memberof_attr = NULL; /* config now owns memory */ } if (skip_nested){ if(strcasecmp(skip_nested,"on") == 0){ theConfig.skip_nested = 1; } else { theConfig.skip_nested = 0; } } if (allBackends) { if(strcasecmp(allBackends,"on")==0){ theConfig.allBackends = 1; } else { theConfig.allBackends = 0; } } else { theConfig.allBackends = 0; } theConfig.auto_add_oc = auto_add_oc; /* * Check and process the entry scopes */ memberof_free_scope(theConfig.entryScopes, &theConfig.entryScopeCount); entryScopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals); if(entryScopes){ int i = 0; /* Validation has already been performed in preop, just build the DN's */ theConfig.entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1); for (i = 0;i < num_vals; i++){ theConfig.entryScopes[i] = slapi_sdn_new_dn_passin(entryScopes[i]); } theConfig.entryScopeCount = num_vals; /* shortcut for config copy */ } /* * Check and process the entry exclude scopes */ memberof_free_scope(theConfig.entryScopeExcludeSubtrees, &theConfig.entryExcludeScopeCount); entryScopeExcludeSubtrees = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals); if(entryScopeExcludeSubtrees){ int i = 0; /* Validation has already been performed in preop, just build the DN's */ theConfig.entryScopeExcludeSubtrees = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1); for (i = 0;i < num_vals; i++){ theConfig.entryScopeExcludeSubtrees[i] = slapi_sdn_new_dn_passin(entryScopeExcludeSubtrees[i]); } theConfig.entryExcludeScopeCount = num_vals; /* shortcut for config copy */ } /* release the lock */ memberof_unlock_config(); done: slapi_sdn_free(&config_sdn); slapi_entry_free(config_entry); slapi_ch_array_free(groupattrs); slapi_ch_free_string(&sharedcfg); slapi_ch_free_string(&memberof_attr); slapi_ch_free_string(&allBackends); slapi_ch_free_string(&skip_nested); slapi_ch_free((void **)&entryScopes); slapi_ch_free((void **)&entryScopeExcludeSubtrees); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
/* This function is called to process operation that come over external connections */ void do_modrdn( Slapi_PBlock *pb ) { Slapi_Operation *operation; BerElement *ber; char *rawdn = NULL, *rawnewsuperior = NULL; const char *dn = NULL, *newsuperior = NULL; char *newrdn = NULL; int err = 0, deloldrdn = 0; ber_len_t len = 0; char *newdn = NULL; char *parent = NULL; Slapi_DN sdn; Slapi_DN snewdn; Slapi_DN *snewsuperior = NULL; slapi_log_err(SLAPI_LOG_TRACE, "do_modrdn", "=>\n"); /* count the modrdn request */ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps); slapi_pblock_get( pb, SLAPI_OPERATION, &operation); ber = operation->o_ber; slapi_sdn_init(&sdn); slapi_sdn_init(&snewdn); /* * Parse the modrdn request. It looks like this: * * ModifyRDNRequest := SEQUENCE { * entry DistinguishedName, * newrdn RelativeDistinguishedName, * deleteoldrdn BOOLEAN, * newSuperior [0] LDAPDN OPTIONAL -- v3 only * } */ if (ber_scanf(ber, "{aab", &rawdn, &newrdn, &deloldrdn) == LBER_ERROR) { slapi_log_err(SLAPI_LOG_ERR, "do_modrdn", "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n"); op_shared_log_error_access (pb, "MODRDN", "???", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "unable to decode DN, newRDN, or deleteOldRDN parameters", 0, NULL ); goto free_and_return; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) { /* This "len" is not used... */ if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) { slapi_log_err(SLAPI_LOG_ERR, "do_modrdn", "Got newSuperior in LDAPv2 modrdn op\n"); op_shared_log_error_access (pb, "MODRDN", rawdn?rawdn:"", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "received newSuperior in LDAPv2 modrdn", 0, NULL ); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); goto free_and_return; } if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) { slapi_log_err(SLAPI_LOG_ERR, "do_modrdn", "ber_scanf failed (op=ModRDN; params=newSuperior)\n"); op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "unable to decode newSuperior parameter", 0, NULL ); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); goto free_and_return; } } /* Check if we should be performing strict validation. */ if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, rawdn, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"", "strict: invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } /* check that the new rdn is formatted correctly */ err = slapi_dn_syntax_check(pb, newrdn, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", newrdn?newrdn:"", "strict: invalid new rdn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid new rdn", 0, NULL); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } } slapi_sdn_init_dn_passin(&sdn, rawdn); dn = slapi_sdn_get_dn(&sdn); if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) { /* normalization failed */ op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } if (rawnewsuperior) { if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, rawnewsuperior, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", rawnewsuperior, "strict: invalid new superior"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid new superior", 0, NULL); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } } snewsuperior = slapi_sdn_new_dn_passin(rawnewsuperior); newsuperior = slapi_sdn_get_dn(snewsuperior); } /* * If newsuperior is myself or my descendent, the modrdn should fail. * Note: need to check the case newrdn is given, and newsuperior * uses the newrdn, as well. */ parent = slapi_dn_parent(slapi_sdn_get_ndn(&sdn)); newdn = slapi_ch_smprintf("%s,%s", newrdn, parent); /* slapi_sdn_init_normdn_passin expects normalized but NOT * decapitalized dn */ slapi_sdn_init_dn_passin(&snewdn, newdn); if (0 == slapi_sdn_compare(&sdn, snewsuperior) || 0 == slapi_sdn_compare(&snewdn, snewsuperior)) { op_shared_log_error_access(pb, "MODRDN", newsuperior, "new superior is identical to the entry dn"); send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "new superior is identical to the entry dn", 0, NULL); goto free_and_return; } if (slapi_sdn_issuffix(snewsuperior, &sdn) || slapi_sdn_issuffix(snewsuperior, &snewdn)) { /* E.g., * newsuperior: ou=sub,ou=people,dc=example,dc=com * dn: ou=people,dc=example,dc=com */ op_shared_log_error_access(pb, "MODRDN", newsuperior, "new superior is descendent of the entry"); send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "new superior is descendent of the entry", 0, NULL); goto free_and_return; } /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and * pass them to the backend. */ if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { op_shared_log_error_access (pb, "MODRDN", dn, "failed to decode LDAP controls"); send_ldap_result( pb, err, NULL, NULL, 0, NULL ); goto free_and_return; } slapi_log_err(SLAPI_LOG_ARGS, "do_modrd", "dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn, deloldrdn ); slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot ); /* dn, newrdn and newsuperior are all normalized */ slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, (void *)slapi_sdn_get_udn(&sdn) ); slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, &sdn ); slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn ); slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, (void *)snewsuperior ); slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn ); op_shared_rename(pb, 0 /* do not pass in ownership of string arguments */ ); free_and_return: slapi_sdn_done(&sdn); slapi_ch_free_string(&newrdn); slapi_sdn_free(&snewsuperior); slapi_sdn_done(&snewdn); slapi_ch_free_string(&parent); return; }
/* * op_shared_rename() -- common frontend code for modDN operations. * * Beware: this function resets the following pblock elements that were * set by the caller: * * SLAPI_MODRDN_TARGET_SDN * SLAPI_MODRDN_NEWRDN * SLAPI_MODRDN_NEWSUPERIOR_SDN */ static void op_shared_rename(Slapi_PBlock *pb, int passin_args) { char *dn, *newrdn, *newdn = NULL; const char *newsuperior; char **rdns; int deloldrdn; Slapi_Backend *be = NULL; Slapi_DN *origsdn = NULL; Slapi_Mods smods; int internal_op, repl_op, lastmod; Slapi_Operation *operation; Slapi_Entry *referral; char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE]; int err; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; Slapi_DN *sdn = NULL; Slapi_DN *newsuperiorsdn = NULL; slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn); slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get (pb, SLAPI_OPERATION, &operation); slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &origsdn); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); /* * If ownership has not been passed to this function, we replace the * string input fields within the pblock with strdup'd copies. Why? * Because some pre- and post-op plugins may change them, and the * convention is that plugins should place a malloc'd string in the * pblock. Therefore, we need to be able to retrieve and free them * later. But the callers of the internal modrdn calls are promised * that we will not free these parameters... so if passin_args is * zero, we need to make copies. * * In the case of SLAPI_MODRDN_TARGET_SDN and SLAPI_MODRDN_NEWSUPERIOR_SDN, * we replace the existing values with normalized values (because plugins * expect these DNs to be normalized). */ if (NULL == origsdn) { sdn = slapi_sdn_new_dn_byval(dn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); } if (passin_args) { if (NULL == sdn) { /* origsdn is not NULL, so use it. */ sdn = origsdn; } } else { if (NULL == sdn) { sdn = slapi_sdn_dup(origsdn); } newrdn = slapi_ch_strdup(newrdn); newsuperiorsdn = slapi_sdn_dup(newsuperiorsdn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, newsuperiorsdn); } /* normdn = slapi_sdn_get_dn(sdn); */ newsuperior = slapi_sdn_get_dn(newsuperiorsdn); /* get the proxy auth dn if the proxy auth control is present */ proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext); /* * first, log the operation to the access log, * then check rdn and newsuperior, * and - if applicable - log reason of any error to the errors log */ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS)) { if (proxydn) { proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn); } if ( !internal_op ) { slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } } /* If we encountered an error parsing the proxy control, return an error * to the client. We do this here to ensure that we log the operation first. */ if (proxy_err != LDAP_SUCCESS) { send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL); goto free_and_return_nolock; } /* check that the rdn is formatted correctly */ if ((rdns = slapi_ldap_explode_rdn(newrdn, 0)) == NULL) { if ( !internal_op ) { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "conn=%" NSPRIu64 " op=%d MODRDN invalid new RDN (\"%s\")\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, (NULL == newrdn) ? "(null)" : newrdn); } else { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "conn=%s op=%d MODRDN invalid new RDN (\"%s\")\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, (NULL == newrdn) ? "(null)" : newrdn); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid RDN", 0, NULL); goto free_and_return_nolock; } else { slapi_ldap_value_free(rdns); } /* check if created attributes are used in the new RDN */ /* check_rdn_for_created_attrs ignores the cases */ if (check_rdn_for_created_attrs((const char *)newrdn)) { send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid attribute in RDN", 0, NULL); goto free_and_return_nolock; } /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, newsuperior, 1); if (err) { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "Syntax check of newSuperior failed\n"); if (!internal_op) { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "conn=%" NSPRIu64 " op=%d MODRDN invalid new superior (\"%s\")", pb->pb_conn->c_connid, pb->pb_op->o_opid, newsuperior ? newsuperior : "(null)"); } else { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "conn=%s op=%d MODRDN invalid new superior (\"%s\")", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, newsuperior ? newsuperior : "(null)"); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "newSuperior does not look like a DN", 0, NULL); goto free_and_return_nolock; } if (newsuperior != NULL) { slapi_log_err(SLAPI_LOG_ARGS, "op_shared_rename", "do_moddn: newsuperior (%s)\n", newsuperior); } /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (pb->pb_op, sdn); /* * Construct the new DN (code sdn from backend * and modified to handle newsuperior) */ newdn = slapi_moddn_get_newdn(sdn, newrdn, newsuperior); /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ /* slapi_mapping_tree_select_and_check ignores the case of newdn * which is generated using newrdn above. */ errorbuf[0] = '\0'; if ((err = slapi_mapping_tree_select_and_check(pb, newdn, &be, &referral, errorbuf, sizeof(errorbuf))) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); goto free_and_return_nolock; } if (referral) { int managedsait; slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait); if (managedsait) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot update referral", 0, NULL); slapi_entry_free(referral); goto free_and_return; } send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto free_and_return; } slapi_pblock_set(pb, SLAPI_BACKEND, be); /* can get lastmod only after backend is selected */ slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); /* if it is a replicated operation - leave lastmod attributes alone */ slapi_mods_init (&smods, 2); if (!repl_op && lastmod) { modify_update_last_modified_attr(pb, &smods); slapi_pblock_set(pb, SLAPI_MODIFY_MODS, (void*)slapi_mods_get_ldapmods_passout(&smods)); } else { slapi_mods_done (&smods); } /* * call the pre-modrdn plugins. if they succeed, call * the backend modrdn function. then call the * post-modrdn plugins. */ if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN : SLAPI_PLUGIN_PRE_MODRDN_FN) == SLAPI_PLUGIN_SUCCESS) { int rc= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); if (be->be_modrdn != NULL) { if ((rc = (*be->be_modrdn)(pb)) == 0) { Slapi_Entry *pse; Slapi_Entry *ecopy; /* we don't perform acl check for internal operations */ /* dont update aci store for remote acis */ if ((!internal_op) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA))) plugin_call_acl_mods_update (pb, SLAPI_OPERATION_MODRDN); if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) write_audit_log_entry(pb); /* Record the operation in the audit log */ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); /* GGOODREPL persistent search system needs the changenumber, oops. */ do_ps_service(pse, ecopy, LDAP_CHANGETYPE_MODDN, 0); } else { /* Should we also be doing a disk space check here? */ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) { write_auditfail_log_entry(pb); /* Record the operation in the audit log */ } } } else { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL); } slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN : SLAPI_PLUGIN_POST_MODRDN_FN); } free_and_return: if (be) slapi_be_Unlock(be); free_and_return_nolock: { /* Free up everything left in the PBlock */ Slapi_Entry *pse; Slapi_Entry *ecopy; LDAPMod **mods; char *s; if (passin_args) { if (NULL == origsdn) { slapi_sdn_free(&sdn); } } else { slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); /* get newrdn to free the string */ slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_ch_free_string(&newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_sdn_free(&newsuperiorsdn); } slapi_ch_free_string(&newdn); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); slapi_entry_free(ecopy); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_entry_free(pse); slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); ldap_mods_free( mods, 1 ); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &s); slapi_ch_free((void **)&s); } }
/* * preop_modify - pre-operation plug-in for modify */ static int preop_modify(Slapi_PBlock *pb) { int result = LDAP_SUCCESS; Slapi_PBlock *spb = NULL; LDAPMod **checkmods = NULL; int checkmodsCapacity = 0; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODIFY begin\n"); #endif BEGIN int err; char *markerObjectClass=NULL; char *requiredObjectClass=NULL; LDAPMod **mods; int modcount = 0; int ii; LDAPMod *mod; Slapi_DN *sdn = NULL; int isupdatedn; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(60); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; /* First argument was attribute name */ argv++; } else if (0 != result) { break; } err = slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); if (err) { result = uid_op_error(61); break; } /* There may be more than one mod that matches e.g. changetype: modify delete: uid uid: balster1950 - add: uid uid: scottg So, we need to first find all mods that contain the attribute which are add or replace ops and are bvalue encoded */ /* find out how many mods meet this criteria */ for(;*mods;mods++) { mod = *mods; if ((slapi_attr_type_cmp(mod->mod_type, attrName, 1) == 0) && /* mod contains target attr */ (mod->mod_op & LDAP_MOD_BVALUES) && /* mod is bval encoded (not string val) */ (mod->mod_bvalues && mod->mod_bvalues[0]) && /* mod actually contains some values */ (SLAPI_IS_MOD_ADD(mod->mod_op) || /* mod is add */ SLAPI_IS_MOD_REPLACE(mod->mod_op))) /* mod is replace */ { addMod(&checkmods, &checkmodsCapacity, &modcount, mod); } } if (modcount == 0) { break; /* no mods to check, we are done */ } /* Get the target DN */ err = slapi_pblock_get(pb, SLAPI_MODIFY_TARGET_SDN, &sdn); if (err) { result = uid_op_error(11); break; } /* * Check if it has the required object class */ if (requiredObjectClass && !(spb = dnHasObjectClass(sdn, requiredObjectClass))) { break; } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ /* * stop checking at first mod that fails the check */ for (ii = 0; (result == 0) && (ii < modcount); ++ii) { mod = checkmods[ii]; if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(sdn, attrName, NULL, mod->mod_bvalues, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, NULL, mod->mod_bvalues, requiredObjectClass, sdn); } } END slapi_ch_free((void **)&checkmods); freePblock(spb); if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODIFY result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }
/* * preop_modrdn - Pre-operation call for modify RDN * * Check that the new RDN does not include attributes that * cause a constraint violation */ static int preop_modrdn(Slapi_PBlock *pb) { int result = LDAP_SUCCESS; Slapi_Entry *e = NULL; Slapi_Value *sv_requiredObjectClass = NULL; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN begin\n"); #endif BEGIN int err; char *markerObjectClass=NULL; char *requiredObjectClass=NULL; Slapi_DN *sdn = NULL; Slapi_DN *superior; char *rdn; int deloldrdn = 0; int isupdatedn; Slapi_Attr *attr; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(30); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; /* First argument was attribute name */ argv++; } else if (0 != result) { break; } /* Create a Slapi_Value for the requiredObjectClass to use * for checking the entry. */ if (requiredObjectClass) { sv_requiredObjectClass = slapi_value_new_string(requiredObjectClass); } /* Get the DN of the entry being renamed */ err = slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); if (err) { result = uid_op_error(31); break; } /* Get superior value - unimplemented in 3.0/4.0/5.0 DS */ err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &superior); if (err) { result = uid_op_error(32); break; } /* * No superior means the entry is just renamed at * its current level in the tree. Use the target DN for * determining which managed tree this belongs to */ if (!superior) superior = sdn; /* Get the new RDN - this has the attribute values */ err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &rdn); if (err) { result = uid_op_error(33); break; } #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN newrdn=%s\n", rdn); #endif /* See if the old RDN value is being deleted. */ err = slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn); if (err) { result = uid_op_error(34); break; } /* Get the entry that is being renamed so we can make a dummy copy * of what it will look like after the rename. */ err = slapi_search_internal_get_entry(sdn, NULL, &e, plugin_identity); if (err != LDAP_SUCCESS) { result = uid_op_error(35); /* We want to return a no such object error if the target doesn't exist. */ if (err == LDAP_NO_SUCH_OBJECT) { result = err; } break; } /* Apply the rename operation to the dummy entry. */ /* slapi_entry_rename does not expect rdn normalized */ err = slapi_entry_rename(e, rdn, deloldrdn, superior); if (err != LDAP_SUCCESS) { result = uid_op_error(36); break; } /* * Find any unique attribute data in the new RDN */ err = slapi_entry_attr_find(e, attrName, &attr); if (err) break; /* no UID attribute */ /* * Check if it has the required object class */ if (requiredObjectClass && !slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sv_requiredObjectClass)) { break; } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(slapi_entry_get_sdn(e), attrName, attr, NULL, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, attr, NULL, requiredObjectClass, sdn); } END /* Clean-up */ slapi_value_free(&sv_requiredObjectClass); if (e) slapi_entry_free(e); if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }
int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc, struct timeval * maxtime, char **errmsg) { int rc=LDAP_SUCCESS; /* optimistic */ cb_outgoing_conn *conn=NULL; cb_outgoing_conn *connprev=NULL; LDAP *ld=NULL; time_t endbefore=0; int checktime=0; struct timeval bind_to, op_to; unsigned int maxconcurrency,maxconnections; char *password,*binddn,*hostname; unsigned int port; int secure; char *mech = NULL;; static char *error1="Can't contact remote server : %s"; int isMultiThread = ENABLE_MULTITHREAD_PER_CONN ; /* by default, we enable multiple operations per connection */ /* ** return an error if we can't get a connection ** before the operation timeout has expired ** bind_timeout: timeout for the bind operation (if bind needed) ** ( checked in ldap_result ) ** op_timeout: timeout for the op that needs a connection ** ( checked in the loop ) */ *cc=NULL; slapi_rwlock_rdlock(pool->rwl_config_lock); maxconcurrency=pool->conn.maxconcurrency; maxconnections=pool->conn.maxconnections; bind_to.tv_sec = pool->conn.bind_timeout.tv_sec; bind_to.tv_usec = pool->conn.bind_timeout.tv_usec; op_to.tv_sec = pool->conn.op_timeout.tv_sec; op_to.tv_usec = pool->conn.op_timeout.tv_usec; /* SD 02/10/2000 temp fix */ /* allow dynamic update of the binddn & password */ /* host, port and security mode */ /* previous values are NOT freed when changed */ /* won't likely to be changed often */ /* pointers put in the waste basket fields and */ /* freed when the backend is stopped. */ password=pool->password; binddn=pool->binddn; hostname=pool->hostname; port=pool->port; secure=pool->secure; if (pool->starttls) { secure = 2; } mech=pool->mech; slapi_rwlock_unlock(pool->rwl_config_lock); if (secure) { isMultiThread = DISABLE_MULTITHREAD_PER_CONN ; } /* For stupid admins */ if (maxconnections <=0) { static int warned_maxconn = 0; if (!warned_maxconn) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Error (no connection available)\n"); warned_maxconn = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } return LDAP_CONNECT_ERROR; } if (maxtime) { if (maxtime->tv_sec != 0) { checktime=1; endbefore = current_time() + maxtime->tv_sec; /* make sure bind to <= operation timeout */ if ((bind_to.tv_sec==0) || (bind_to.tv_sec > maxtime->tv_sec)) bind_to.tv_sec=maxtime->tv_sec; } } else { if (op_to.tv_sec != 0) { checktime=1; endbefore = current_time() + op_to.tv_sec; /* make sure bind to <= operation timeout */ if ((bind_to.tv_sec==0) || (bind_to.tv_sec > op_to.tv_sec)) bind_to.tv_sec=op_to.tv_sec; } } /* * Close (or mark to be closed) any connections for this farm server that have * exceeded the maximum connection lifetime. */ cb_check_for_stale_connections(pool); /* * Look for an available, already open connection */ slapi_lock_mutex( pool->conn.conn_list_mutex ); if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server %s conns: %d maxconns: %d\n", hostname, pool->conn.conn_list_count, maxconnections ); } for (;;) { /* time limit mgmt */ if (checktime) { if (current_time() > endbefore ) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server %s expired.\n", hostname ); if ( errmsg ) { *errmsg = PR_smprintf(error1,"timelimit exceeded"); } rc=LDAP_TIMELIMIT_EXCEEDED; conn=NULL; ld=NULL; goto unlock_and_return; } } /* * First, look for an available, already open/bound connection */ if (secure) { for (conn = pool->connarray[PR_ThreadSelf()]; conn != NULL; conn = conn->next) { if ((conn->ThreadId == PR_MyThreadId()) && (conn->status == CB_CONNSTATUS_OK && conn->refcount < maxconcurrency)){ if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server found conn 0x%p to use)\n", conn ); } goto unlock_and_return; /* found one */ } } } else { connprev = NULL; for ( conn = pool->conn.conn_list; conn != NULL; conn = conn->next ) { if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - conn 0x%p status %d refcount %lu\n", conn, conn->status, conn->refcount ); } if ( conn->status == CB_CONNSTATUS_OK && conn->refcount < maxconcurrency ) { if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server found conn 0x%p to use)\n", conn ); } goto unlock_and_return; /* found one */ } connprev = conn; } } if ( secure || pool->conn.conn_list_count <maxconnections) { int version=LDAP_VERSION3; /* * we have not exceeded the maximum number of connections allowed, * so we initialize a new one and add it to the end of our list. */ /* No need to lock. url can't be changed dynamically */ ld = slapi_ldap_init(hostname, port, secure, isMultiThread); if (NULL == ld) { static int warned_init = 0; if (!warned_init) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't contact server <%s> port <%d>.\n", hostname, port ); warned_init = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); /* Don't chase referrals */ ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); /* no controls and simple bind only */ /* For now, bind even if no user to detect error */ /* earlier */ if (pool->bindit) { PRErrorCode prerr = 0; LDAPControl **serverctrls=NULL; char *plain = NULL; int ret = -1; rc=LDAP_SUCCESS; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Bind to to server <%s> port <%d> as <%s>\n", hostname, port, binddn); } ret = pw_rever_decode(password, &plain, CB_CONFIG_USERPASSWORD); /* Pb occured in decryption: stop now, binding will fail */ if ( ret == -1 ) { static int warned_pw = 0; if (!warned_pw) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Internal credentials decoding error; " "password storage schemes do not match or " "encrypted password is corrupted.\n"); warned_pw = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_INVALID_CREDENTIALS; goto unlock_and_return; } /* Password-based client authentication */ rc = slapi_ldap_bind(ld, binddn, plain, mech, NULL, &serverctrls, &bind_to, NULL); if ( ret == 0 ) slapi_ch_free_string(&plain); /* free plain only if it has been duplicated */ if ( rc == LDAP_TIMEOUT ) { static int warned_bind_timeout = 0; if (!warned_bind_timeout) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't bind to server <%s> port <%d>. (%s)\n", hostname, port, "time-out expired"); warned_bind_timeout = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } else if ( rc != LDAP_SUCCESS ) { prerr=PR_GetError(); static int warned_bind_err = 0; if (!warned_bind_err) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't bind to server <%s> port <%d>. " "(LDAP error %d - %s; " SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n", hostname, port, rc, ldap_err2string(rc), prerr, slapd_pr_strerror(prerr)); warned_bind_err = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } if ( serverctrls ) { int i; for( i = 0; serverctrls[ i ] != NULL; ++i ) { if ( !(strcmp( serverctrls[ i ]->ldctl_oid, LDAP_CONTROL_PWEXPIRED)) ) { /* Bind is successful but password has expired */ slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Successfully bound as %s to remote server %s:%d, " "but password has expired.\n", binddn, hostname, port); } else if ( !(strcmp( serverctrls[ i ]->ldctl_oid, LDAP_CONTROL_PWEXPIRING)) ) { /* The password is expiring in n seconds */ if ( (serverctrls[ i ]->ldctl_value.bv_val != NULL) && (serverctrls[ i ]->ldctl_value.bv_len > 0) ) { int password_expiring = atoi( serverctrls[ i ]->ldctl_value.bv_val ); slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Successfully bound as %s to remote server %s:%d, " "but password is expiring in %d seconds.\n", binddn, hostname, port, password_expiring); } } } ldap_controls_free(serverctrls); } } else if (secure == 2) { /* the start_tls operation is usually performed in slapi_ldap_bind, but since we are not binding we still need to start_tls */ if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - doing start_tls on connection 0x%p\n", conn ); } if ((rc = ldap_start_tls_s(ld, NULL, NULL))) { PRErrorCode prerr = PR_GetError(); slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Unable to do start_tls on connection to %s:%d " "LDAP error %d:%s NSS error %d:%s\n", hostname, port, rc, ldap_err2string(rc), prerr, slapd_pr_strerror(prerr)); goto unlock_and_return; } } conn = (cb_outgoing_conn *) slapi_ch_malloc(sizeof(cb_outgoing_conn)); conn->ld=ld; conn->status=CB_CONNSTATUS_OK; conn->refcount=0; /* incremented below */ conn->opentime=current_time(); conn->ThreadId=PR_MyThreadId(); /* store the thread id */ conn->next=NULL; if (secure) { if (pool->connarray[PR_ThreadSelf()] == NULL) { pool->connarray[PR_ThreadSelf()] = conn; } else { conn->next = pool->connarray[PR_ThreadSelf()]; pool->connarray[PR_ThreadSelf()] = conn ; } } else { if ( NULL == connprev ) { pool->conn.conn_list = conn; } else { connprev->next=conn; } } ++pool->conn.conn_list_count; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - added new conn 0x%p, " "conn count now %d\n", conn->ld, pool->conn.conn_list_count ); } goto unlock_and_return; /* got a new one */ } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - waiting for conn to free up\n" ); } if (!secure) slapi_wait_condvar( pool->conn.conn_list_cv, NULL ); if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - awake again\n" ); } } unlock_and_return: if ( conn != NULL ) { ++conn->refcount; *lld=conn->ld; *cc=conn; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - ld=0x%p (concurrency now %lu)\n",*lld, conn->refcount ); } } else { if ( NULL != ld ) { slapi_ldap_unbind( ld ); } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - error %d\n", rc ); } } slapi_unlock_mutex(pool->conn.conn_list_mutex); return( rc ); }
/* * preop_add - pre-operation plug-in for add */ static int preop_add(Slapi_PBlock *pb) { int result; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD begin\n"); #endif result = LDAP_SUCCESS; /* * Do constraint check on the added entry. Set result. */ BEGIN int err; char *markerObjectClass = NULL; char *requiredObjectClass = NULL; Slapi_DN *sdn = NULL; int isupdatedn; Slapi_Entry *e; Slapi_Attr *attr; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(50); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD parameter untagged: %s\n", attrName); result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; argv++; /* First argument was attribute name */ } else if (0 != result) { break; } /* * Get the target DN for this add operation */ err = slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); if (err) { result = uid_op_error(51); break; } #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD target=%s\n", slapi_sdn_get_dn(sdn)); #endif /* * Get the entry data for this add. Check whether it * contains a value for the unique attribute */ err = slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e); if (err) { result = uid_op_error(52); break; } err = slapi_entry_attr_find(e, attrName, &attr); if (err) break; /* no unique attribute */ /* * Check if it contains the required object class */ if (NULL != requiredObjectClass) { if (!entryHasObjectClass(pb, e, requiredObjectClass)) { /* No, so we don't have to do anything */ break; } } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(sdn, attrName, attr, NULL, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, attr, NULL, requiredObjectClass, sdn); } END if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } /* Send failure to the client */ slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }
int acl_get_effective_rights ( Slapi_PBlock *pb, Slapi_Entry *e, /* target entry */ char **attrs, /* Attribute of the entry */ struct berval *val, /* value of attr. NOT USED */ int access, /* requested access rights */ char **errbuf ) { Slapi_PBlock *gerpb = NULL; void *aclcb = NULL; char *subjectndn = NULL; char *gerstr = NULL; size_t gerstrsize = 0; size_t gerstrcap = 0; int iscritical = 1; int rc = LDAP_SUCCESS; *errbuf = '\0'; if (NULL == e) /* create a template entry from SLAPI_SEARCH_GERATTRS */ { rc = _ger_generate_template_entry ( pb ); slapi_pblock_get ( pb, SLAPI_SEARCH_RESULT_ENTRY, &e ); if ( rc != LDAP_SUCCESS || NULL == e ) { goto bailout; } } /* * Get the subject */ rc = _ger_parse_control (pb, &subjectndn, &iscritical, errbuf ); if ( rc != LDAP_SUCCESS ) { goto bailout; } /* * The requestor should have g permission on the entry * to get the effective rights. */ rc = _ger_g_permission_granted (pb, e, subjectndn, errbuf); if ( rc != LDAP_SUCCESS ) { goto bailout; } /* * Construct a new pb */ rc = _ger_new_gerpb ( pb, e, subjectndn, &gerpb, &aclcb, errbuf ); if ( rc != LDAP_SUCCESS ) { goto bailout; } /* Get entry level effective rights */ _ger_get_entry_rights ( gerpb, e, subjectndn, &gerstr, &gerstrsize, &gerstrcap, errbuf ); /* * Attribute level effective rights may not be NULL * even if entry level's is. */ _ger_get_attrs_rights ( gerpb, e, subjectndn, attrs, &gerstr, &gerstrsize, &gerstrcap, errbuf ); bailout: /* * Now construct the response control */ _ger_set_response_control ( pb, iscritical, rc ); if ( rc != LDAP_SUCCESS ) { gerstr = slapi_ch_smprintf("entryLevelRights: %d\nattributeLevelRights: *:%d", rc, rc ); } slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "###### Effective Rights on Entry (%s) for Subject (%s) ######\n", e?slapi_entry_get_ndn(e):"null", subjectndn?subjectndn:"null"); slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "%s\n", gerstr); /* Restore pb */ _ger_release_gerpb ( &gerpb, &aclcb, pb ); /* * General plugin uses SLAPI_RESULT_TEXT for error text. Here * SLAPI_PB_RESULT_TEXT is exclusively shared with add, dse and schema. * slapi_pblock_set() will free any previous data, and * pblock_done() will free SLAPI_PB_RESULT_TEXT. */ slapi_pblock_set (pb, SLAPI_PB_RESULT_TEXT, gerstr); if ( !iscritical ) { /* * If return code is not LDAP_SUCCESS, the server would * abort sending the data of the entry to the client. */ rc = LDAP_SUCCESS; } slapi_ch_free ( (void **) &subjectndn ); slapi_ch_free ( (void **) &gerstr ); return rc; }
/* Modify the Password attributes of the entry */ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg, struct ipapwd_data *data, int is_krb) { int ret = 0; Slapi_Mods *smods = NULL; Slapi_Value **svals = NULL; Slapi_Value **ntvals = NULL; Slapi_Value **pwvals = NULL; char *nt = NULL; int is_smb = 0; int is_ipant = 0; int is_host = 0; Slapi_Value *sambaSamAccount; Slapi_Value *ipaNTUserAttrs; Slapi_Value *ipaHost; char *errMesg = NULL; char *modtime = NULL; LOG_TRACE("=>\n"); sambaSamAccount = slapi_value_new_string("sambaSamAccount"); if (slapi_entry_attr_has_syntax_value(data->target, "objectClass", sambaSamAccount)) { is_smb = 1; } slapi_value_free(&sambaSamAccount); ipaNTUserAttrs = slapi_value_new_string("ipaNTUserAttrs"); if (slapi_entry_attr_has_syntax_value(data->target, "objectClass", ipaNTUserAttrs)) { is_ipant = 1; } slapi_value_free(&ipaNTUserAttrs); ipaHost = slapi_value_new_string("ipaHost"); if (slapi_entry_attr_has_syntax_value(data->target, "objectClass", ipaHost)) { is_host = 1; } slapi_value_free(&ipaHost); ret = ipapwd_gen_hashes(krbcfg, data, data->password, is_krb, is_smb, is_ipant, &svals, &nt, &ntvals, &errMesg); if (ret) { goto free_and_return; } smods = slapi_mods_new(); if (svals) { slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbPrincipalKey", svals); /* krbLastPwdChange is used to tell whether a host entry has a * keytab so don't set it on hosts. */ if (!is_host) { /* change Last Password Change field with the current date */ ret = ipapwd_setdate(data->target, smods, "krbLastPwdChange", data->timeNow, false); if (ret != LDAP_SUCCESS) goto free_and_return; /* set Password Expiration date */ ret = ipapwd_setdate(data->target, smods, "krbPasswordExpiration", data->expireTime, (data->expireTime == 0)); if (ret != LDAP_SUCCESS) goto free_and_return; } } if (nt && is_smb) { slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaNTPassword", nt); } if (ntvals && is_ipant) { slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "ipaNTHash", ntvals); } if (is_smb) { /* with samba integration we need to also set sambaPwdLastSet or * samba will decide the user has to change the password again */ if (data->changetype == IPA_CHANGETYPE_ADMIN) { /* if it is an admin change instead we need to let know to * samba as well that the use rmust change its password */ modtime = slapi_ch_smprintf("0"); } else { modtime = slapi_ch_smprintf("%ld", (long)data->timeNow); } if (!modtime) { LOG_FATAL("failed to smprintf string!\n"); ret = LDAP_OPERATIONS_ERROR; goto free_and_return; } slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaPwdLastset", modtime); } if (is_krb) { if (data->changetype == IPA_CHANGETYPE_ADMIN) { slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbLoginFailedCount", "0"); } } /* let DS encode the password itself, this allows also other plugins to * intercept it to perform operations like synchronization with Active * Directory domains through the replication plugin */ slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "userPassword", data->password); /* set password history */ if (data->policy.history_length > 0) { pwvals = ipapwd_setPasswordHistory(smods, data); if (pwvals) { slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "passwordHistory", pwvals); } } /* FIXME: * instead of replace we should use a delete/add so that we are * completely sure nobody else modified the entry meanwhile and * fail if that's the case */ /* commit changes */ ret = ipapwd_apply_mods(data->dn, smods); LOG_TRACE("<= result: %d\n", ret); free_and_return: if (nt) slapi_ch_free((void **)&nt); if (modtime) slapi_ch_free((void **)&modtime); slapi_mods_free(&smods); ipapwd_free_slapi_value_array(&svals); ipapwd_free_slapi_value_array(&ntvals); ipapwd_free_slapi_value_array(&pwvals); return ret; }
int ipapwd_getPolicy(const char *dn, Slapi_Entry *target, struct ipapwd_policy *policy) { const char *krbPwdPolicyReference; char *pdn = NULL; Slapi_PBlock *pb = NULL; char *attrs[] = { "krbMaxPwdLife", "krbMinPwdLife", "krbPwdMinDiffChars", "krbPwdMinLength", "krbPwdHistoryLength", NULL}; Slapi_Entry **es = NULL; Slapi_Entry *pe = NULL; int ret, res, scope, i; int buffer_flags=0; Slapi_ValueSet* results = NULL; char *actual_type_name = NULL; LOG_TRACE("Searching policy for [%s]\n", dn); pwd_get_values(target, "krbPwdPolicyReference", &results, &actual_type_name, &buffer_flags); if (results) { Slapi_Value *sv; slapi_valueset_first_value(results, &sv); krbPwdPolicyReference = slapi_value_get_string(sv); pdn = slapi_ch_strdup(krbPwdPolicyReference); } else { /* Fallback to hardcoded value */ pdn = slapi_ch_smprintf("cn=global_policy,%s", ipa_realm_dn); } if (pdn == NULL) { LOG_OOM(); ret = -1; goto done; } LOG_TRACE("Using policy at [%s]\n", pdn); scope = LDAP_SCOPE_BASE; pb = slapi_pblock_new(); slapi_search_internal_set_pb(pb, pdn, scope, "(objectClass=krbPwdPolicy)", attrs, 0, NULL, /* Controls */ NULL, /* UniqueID */ ipapwd_plugin_id, 0); /* Flags */ /* do search the tree */ ret = slapi_search_internal_pb(pb); slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res); if (ret == -1 || res != LDAP_SUCCESS) { LOG_FATAL("Couldn't find policy, err (%d)\n", res ? res : ret); ret = -1; goto done; } /* get entries */ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es); if (!es) { LOG_TRACE("No entries ?!"); ret = -1; goto done; } /* count entries */ for (i = 0; es[i]; i++) /* count */ ; /* if there is only one, return that */ if (i == 1) { pe = es[0]; } else { LOG_TRACE("Multiple entries from a base search ?!"); ret = -1; goto done; } /* read data out of policy object */ policy->min_pwd_life = slapi_entry_attr_get_int(pe, "krbMinPwdLife"); policy->max_pwd_life = slapi_entry_attr_get_int(pe, "krbMaxPwdLife"); policy->min_pwd_length = slapi_entry_attr_get_int(pe, "krbPwdMinLength"); policy->history_length = slapi_entry_attr_get_int(pe, "krbPwdHistoryLength"); policy->min_complexity = slapi_entry_attr_get_int(pe, "krbPwdMinDiffChars"); ret = 0; done: if (results) { pwd_values_free(&results, &actual_type_name, buffer_flags); } if (pb) { slapi_free_search_results_internal(pb); slapi_pblock_destroy(pb); } slapi_ch_free_string(&pdn); return ret; }
static void linked_attrs_fixup_links(struct configEntry *config) { Slapi_PBlock *pb = slapi_pblock_new(); char *del_filter = NULL; char *add_filter = NULL; del_filter = slapi_ch_smprintf("%s=*", config->managedtype); add_filter = slapi_ch_smprintf("%s=*", config->linktype); /* Lock the attribute pair. */ slapi_lock_mutex(config->lock); if (config->scope) { /* Find all entries with the managed type present * within the scope and remove the managed type. */ slapi_search_internal_set_pb(pb, config->scope, LDAP_SCOPE_SUBTREE, del_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config->managedtype, 0, linked_attrs_remove_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); /* Find all entries with the link type present within the * scope and add backlinks to the entries they point to. */ slapi_search_internal_set_pb(pb, config->scope, LDAP_SCOPE_SUBTREE, add_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config, 0, linked_attrs_add_backlinks_callback, 0); } else { /* Loop through all non-private backend suffixes and * remove the managed type from any entry that has it. * We then find any entry with the linktype present and * generate the proper backlinks. */ void *node = NULL; Slapi_DN * suffix = slapi_get_first_suffix (&node, 0); while (suffix) { slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(suffix), LDAP_SCOPE_SUBTREE, del_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config->managedtype, 0, linked_attrs_remove_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(suffix), LDAP_SCOPE_SUBTREE, add_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config, 0, linked_attrs_add_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); suffix = slapi_get_next_suffix (&node, 0); } } /* Unlock the attribute pair. */ slapi_unlock_mutex(config->lock); slapi_ch_free_string(&del_filter); slapi_ch_free_string(&add_filter); slapi_pblock_destroy(pb); }
/* * controlType = LDAP_CONTROL_PAGEDRESULTS; * criticality = n/a; * controlValue: * realSearchControlValue ::= SEQUENCE { * size INTEGER (0..maxInt), * -- requested page size from client * -- result set size estimate from server * cookie OCTET STRING * } */ void pagedresults_set_response_control( Slapi_PBlock *pb, int iscritical, ber_int_t estimate, int current_search_count, int index ) { LDAPControl **resultctrls = NULL; LDAPControl pr_respctrl; BerElement *ber = NULL; struct berval *berval = NULL; char *cookie_str = NULL; int found = 0; int i; LDAPDebug1Arg(LDAP_DEBUG_TRACE, "--> pagedresults_set_response_control: idx=%d\n", index); if ( (ber = der_alloc()) == NULL ) { goto bailout; } /* begin sequence, payload, end sequence */ if (current_search_count < 0) { cookie_str = slapi_ch_strdup(""); } else { cookie_str = slapi_ch_smprintf("%d", index); } ber_printf ( ber, "{io}", estimate, cookie_str, strlen(cookie_str) ); if ( ber_flatten ( ber, &berval ) != LDAP_SUCCESS ) { goto bailout; } pr_respctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; pr_respctrl.ldctl_iscritical = iscritical; pr_respctrl.ldctl_value.bv_val = berval->bv_val; pr_respctrl.ldctl_value.bv_len = berval->bv_len; slapi_pblock_get ( pb, SLAPI_RESCONTROLS, &resultctrls ); for (i = 0; resultctrls && resultctrls[i]; i++) { if (strcmp(resultctrls[i]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { /* * We get here if search returns more than one entry * and this is not the first entry. */ ldap_control_free ( resultctrls[i] ); resultctrls[i] = slapi_dup_control (&pr_respctrl); found = 1; break; } } if ( !found ) { /* slapi_pblock_set() will dup the control */ slapi_pblock_set ( pb, SLAPI_ADD_RESCONTROL, &pr_respctrl ); } bailout: slapi_ch_free_string(&cookie_str); ber_free ( ber, 1 ); /* ber_free() checks for NULL param */ ber_bvfree ( berval ); /* ber_bvfree() checks for NULL param */ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_response_control: idx=%d\n", index); }