Example #1
0
static void free_pblock(void *arg)
{
    Slapi_PBlock *pb = (Slapi_PBlock *) arg;

    slapi_free_search_results_internal(pb);
    slapi_pblock_destroy(pb);
}
Example #2
0
int
sync_send_entry_from_changelog(Slapi_PBlock *pb,int chg_req, char *uniqueid)
{
	Slapi_Entry *db_entry = NULL;
	int chg_type = LDAP_SYNC_ADD;
	int rv;
	Slapi_PBlock *search_pb = NULL;
    	Slapi_Entry **entries = NULL;
	char *origbase;
	char *filter = slapi_ch_smprintf("(nsuniqueid=%s)",uniqueid);

	slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET_DN, &origbase );
	search_pb = slapi_pblock_new();
    	slapi_search_internal_set_pb(search_pb, origbase,
           				LDAP_SCOPE_SUBTREE, filter,
            				NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
 	slapi_search_internal_pb(search_pb);
	slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rv);
	if ( rv == LDAP_SUCCESS) {
		slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
    		if (entries)
			db_entry = *entries; /* there can only be one */
	}

	if (db_entry && sync_is_entry_in_scope(pb, db_entry)) {
		LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
		sync_create_state_control(db_entry, &ctrl[0], chg_type, NULL);
		slapi_send_ldap_search_entry (pb, db_entry, ctrl, NULL, 0);
		ldap_controls_free(ctrl);
	}
	slapi_free_search_results_internal(search_pb);
	slapi_pblock_destroy(search_pb);
	slapi_ch_free((void **)&filter);
	return (0);
}
Example #3
0
File: uid.c Project: ohamada/389ds
static void
freePblock( Slapi_PBlock *spb ) {
  if ( spb )
  {
        slapi_free_search_results_internal( spb );
        slapi_pblock_destroy( spb );
  }
}
Example #4
0
/*
 * snmp_update_cache_stats()
 *
 * Reads the backend cache stats from the backend monitor entry and 
 * updates the global counter used by the SNMP sub-agent as well as
 * the SNMP monitor entry.
 */
static void
snmp_update_cache_stats(void)
{
    Slapi_Backend       *be, *be_next;
    char                *cookie = NULL;
    Slapi_PBlock        *search_result_pb = NULL;
    Slapi_Entry         **search_entries;
    int                 search_result;

    /* set the cache hits/cache entries info */
    be = slapi_get_first_backend(&cookie);
    if (!be){
    	slapi_ch_free ((void **) &cookie);
        return;
    }

    be_next = slapi_get_next_backend(cookie);

    slapi_ch_free ((void **) &cookie);

    /* for now, only do it if there is only 1 backend, otherwise don't know 
     * which backend to pick */
    if(be_next == NULL)
    {
        Slapi_DN monitordn;
        slapi_sdn_init(&monitordn);
        be_getmonitordn(be,&monitordn);
   
        /* do a search on the monitor dn to get info */
        search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
                LDAP_SCOPE_BASE,
                "objectclass=*", 
                NULL,
                NULL,
                0);
        slapi_sdn_done(&monitordn);

        slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);

        if(search_result == 0)
        {
            slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                    &search_entries);

            /* set the entrycachehits */
            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits,
                    slapi_entry_attr_get_ulonglong(search_entries[0], "entrycachehits"));
		    
            /* set the currententrycachesize */
            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries,
                    slapi_entry_attr_get_ulonglong(search_entries[0], "currententrycachesize"));
        }

        slapi_free_search_results_internal(search_result_pb);
        slapi_pblock_destroy(search_result_pb);
    }
}
Example #5
0
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);
}
Example #6
0
File: utils.c Project: leto/389-ds
/*
 * dnHasAttribute - read an entry if it has a particular attribute
 * Return:
 *   The entry, or NULL
 */
Slapi_PBlock *
dnHasAttribute( const char *baseDN, const char *attrName ) {
	Slapi_PBlock *spb = NULL;
	char *filter = NULL;

	BEGIN
        int sres;
		Slapi_Entry **entries;
		char *attrs[2];

		/* Perform the search - the new pblock needs to be freed */
		attrs[0] = (char *)attrName;
		attrs[1] = NULL;
		filter = PR_smprintf( "%s=*", attrName );
		spb = slapi_search_internal((char *)baseDN, LDAP_SCOPE_BASE,
									filter, NULL, attrs, 0);
		if ( !spb ) {
			op_error(20);
			break;
		}
 
		if ( slapi_pblock_get( spb, SLAPI_PLUGIN_INTOP_RESULT, &sres ) ) {
			op_error(21);
			break;
		} else if (sres) {
			op_error(22);
			break;
		}

		if ( slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
							  &entries) ) {
			op_error(23);
			break;
		}
		/*
		 * Can only be one entry returned on a base search; just check
		 * the first one
		 */
		if ( !*entries ) {
			/* Clean up */
			slapi_free_search_results_internal(spb);
			slapi_pblock_destroy(spb);
			spb = NULL;
		}
    END

	if (filter) {
		PR_smprintf_free(filter);
	}
	return spb;
}
Example #7
0
static int ipa_cldap_get_domain_entry(struct ipa_cldap_ctx *ctx,
                                      char *domain,
                                      char **guid, char **sid, char **name)
{
    Slapi_PBlock *pb;
    Slapi_Entry **e = NULL;
    char *filter;
    int ret;

    pb = slapi_pblock_new();
    if (!pb) {
        return ENOMEM;
    }

    ret = asprintf(&filter, "(&(cn=%s)(objectclass=ipaNTDomainAttrs))", domain);
    if (ret == -1) {
        ret = ENOMEM;
        goto done;
    }

    slapi_search_internal_set_pb(pb, ctx->base_dn,
                                 LDAP_SCOPE_SUBTREE, filter,
                                 NULL, 0, NULL, NULL, ctx->plugin_id, 0);

    slapi_search_internal_pb(pb);
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);

    if (ret) {
        ret = ENOENT;
        goto done;
    }

    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &e);
    if (!e || !e[0] || e[1]) {
        /* no matches or too many matches */
        ret = ENOENT;
        goto done;
    }

    *guid = slapi_entry_attr_get_charptr(e[0], "ipaNTDomainGUID");
    *sid = slapi_entry_attr_get_charptr(e[0], "ipaNTSecurityIdentifier");
    *name = slapi_entry_attr_get_charptr(e[0], "ipaNTFlatName");

    ret = 0;

done:
    slapi_free_search_results_internal(pb);
    slapi_pblock_destroy(pb);
    free(filter);
    return ret;
}
Example #8
0
/* When a new instance is started, we need to read the dse to
 * find out what attributes should be encrypted.  This function
 * does that.  Returns 0 on success. */
static int 
read_instance_attrcrypt_entries(ldbm_instance *inst)
{
    Slapi_PBlock *tmp_pb;
    int scope = LDAP_SCOPE_SUBTREE;
    const char *searchfilter = ldbm_instance_attrcrypt_filter;
    char *basedn = NULL;

    /* Construct the base dn of the subtree that holds the index entries 
     * for this instance. */
    basedn = slapi_create_dn_string("cn=encrypted attributes,cn=%s,cn=%s,cn=plugins,cn=config",
                          inst->inst_name, inst->inst_li->li_plugin->plg_name); 
    if (NULL == basedn) {
        LDAPDebug2Args(LDAP_DEBUG_ANY,
                       "read_instance_attrcrypt_entries: "
                       "failed create encrypted attributes dn for plugin %s, "
                       "instance %s\n",
                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
        return 1;
    }

    /* Set up a tmp callback that will handle the init for each index entry */
    slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
        basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback,
        (void *) inst);

    /* Do a search of the subtree containing the index entries */
    tmp_pb = slapi_pblock_new();
    slapi_search_internal_set_pb(tmp_pb, basedn, LDAP_SCOPE_SUBTREE, 
        searchfilter, NULL, 0, NULL, NULL, inst->inst_li->li_identity, 0);
    slapi_search_internal_pb (tmp_pb);

    /* Remove the tmp callback */
    slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
        basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback);
    slapi_free_search_results_internal(tmp_pb);
    slapi_pblock_destroy(tmp_pb);

    slapi_ch_free_string(&basedn);
    return 0;
}
Example #9
0
File: utils.c Project: leto/389-ds
/*
 * dnHasObjectClass - read an entry if it has a particular object class
 * Return:
 *   A pblock containing the entry, or NULL
 */
Slapi_PBlock *
dnHasObjectClass( const char *baseDN, const char *objectClass ) {
	char *filter = NULL;
	Slapi_PBlock *spb = NULL;

	BEGIN
		Slapi_Entry **entries;
		char *attrs[2];

		/* Perform the search - the new pblock needs to be freed */
		attrs[0] = "objectclass";
		attrs[1] = NULL;
		filter = PR_smprintf("objectclass=%s", objectClass );
		if ( !(spb = readPblockAndEntry( baseDN, filter, attrs) ) ) {
			break;
		}
 
		if ( slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
							  &entries) ) {
			op_error(23);
			break;
		}
		/*
		 * Can only be one entry returned on a base search; just check
		 * the first one
		 */
		if ( !*entries ) {
			/* Clean up */
			slapi_free_search_results_internal(spb);
			slapi_pblock_destroy(spb);
			spb = NULL;
		}
    END

	if (filter) {
		PR_smprintf_free(filter);
	}
	return spb;
}
Example #10
0
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;
}
Example #11
0
int
update_integrity(char **argv, Slapi_DN *origSDN,
                 char *newrDN, Slapi_DN *newsuperior, 
                 int logChanges)
{
    Slapi_PBlock *search_result_pb = NULL;
    Slapi_PBlock *mod_pb = slapi_pblock_new();
    Slapi_Entry  **search_entries = NULL;
    Slapi_DN *sdn = NULL;
    Slapi_Attr *attr = NULL;
    void *node = NULL;
    const char *origDN = slapi_sdn_get_dn(origSDN);
    const char *search_base = NULL;
    char *attrName = NULL;
    char *filter = NULL;
    char *attrs[2];
    int search_result;
    int nval = 0;
    int i, j;
    int rc;

    if ( argv == NULL ){
        slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
            "referint_postop required config file arguments missing\n" );
        rc = -1;
        goto free_and_return;
    } 
    /*
     *  For now, just putting attributes to keep integrity on in conf file,
     *  until resolve the other timing mode issue
     */
    search_result_pb = slapi_pblock_new();

    /* Search each namingContext in turn */
    for ( sdn = slapi_get_first_suffix( &node, 0 ); sdn != NULL;
          sdn = slapi_get_next_suffix( &node, 0 ))
    {
        Slapi_Backend *be = slapi_be_select(sdn);
        search_base = slapi_sdn_get_dn( sdn );

        for(i = 3; argv[i] != NULL; i++){
            filter = slapi_filter_sprintf("(%s=*%s%s)", argv[i], ESC_NEXT_VAL, origDN);
            if ( filter ) {
                /* Need only the current attribute and its subtypes */
                attrs[0] = argv[i];
                attrs[1] = NULL;

                /* Use new search API */
                slapi_pblock_init(search_result_pb);
                slapi_pblock_set(search_result_pb, SLAPI_BACKEND, be);
                slapi_search_internal_set_pb(search_result_pb, search_base, 
                    LDAP_SCOPE_SUBTREE, filter, attrs, 0 /* attrs only */,
                    NULL, NULL, referint_plugin_identity, 0);
                slapi_search_internal_pb(search_result_pb);
  
                slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);

                /* if search successfull then do integrity update */
                if(search_result == LDAP_SUCCESS)
                {
                    slapi_pblock_get(search_result_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                                     &search_entries);

                    for(j = 0; search_entries[j] != NULL; j++){
                        attr = NULL;
                        attrName = NULL;
                        /*
                         *  Loop over all the attributes of the entry and search
                         *  for the integrity attribute and its subtypes
                         */
                        for (slapi_entry_first_attr(search_entries[j], &attr); attr; 
                             slapi_entry_next_attr(search_entries[j], attr, &attr))
                        {
                            /*
                             *  Take into account only the subtypes of the attribute
                             *  in argv[i] having the necessary value  - origDN
                             */
                            slapi_attr_get_type(attr, &attrName);
                            if (slapi_attr_type_cmp(argv[i], attrName,
                                                    SLAPI_TYPE_CMP_SUBTYPE) == 0)
                            {
                                nval = 0;
                                slapi_attr_get_numvalues(attr, &nval);
                                /* 
                                 * We want to reduce the "modify" call as much as
                                 * possible. But if an entry contains 1000s of 
                                 * attributes which need to be updated by the 
                                 * referint plugin (e.g., a group containing 1000s 
                                 * of members), we want to avoid to allocate too 
                                 * many mods * in one "modify" call.
                                 * This is a compromise: If an attribute type has
                                 * more than 128 values, we update the attribute 
                                 * value one by one. Otherwise, update all values
                                 * in one "modify" call.
                                 */
                                if (nval > 128) {
                                    rc = _update_one_per_mod(
                                         slapi_entry_get_sdn(search_entries[j]),
                                         attr, attrName, origSDN, newrDN, 
                                         slapi_sdn_get_dn(newsuperior),
                                         mod_pb);
                                } else {
                                    rc = _update_all_per_mod(
                                         slapi_entry_get_sdn(search_entries[j]),
                                         attr, attrName, origSDN, newrDN, 
                                         slapi_sdn_get_dn(newsuperior),
                                         mod_pb);
                                }
                                /* Should we stop if one modify returns an error? */
                            }
                        }
                    }
                } else {
                    if (isFatalSearchError(search_result)){
                        slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
                            "update_integrity search (base=%s filter=%s) returned "
                            "error %d\n", search_base, filter, search_result);
                        rc = -1;
                        goto free_and_return;
                    }
                }
                slapi_ch_free_string(&filter);
            }
            slapi_free_search_results_internal(search_result_pb);
        }
    }
    /* if got here, then everything good rc = 0 */
    rc = 0;

free_and_return:
    /* free filter and search_results_pb */
    slapi_ch_free_string(&filter);

    slapi_pblock_destroy(mod_pb);
    if (search_result_pb) {
        slapi_free_search_results_internal(search_result_pb);
        slapi_pblock_destroy(search_result_pb);
    }
 
    return(rc);
}
Example #12
0
/*
 * Read and load configuration.  Validation will also
 * be performed unless skip_validate is set to non-0.
 * Returns PAM_PASSTHRU_SUCCESS if all is well.
 */
int
pam_passthru_load_config(int skip_validate)
{
    int status = PAM_PASSTHRU_SUCCESS;
    int result;
    int i;
    int alternate = 0;
    Slapi_PBlock *search_pb;
    Slapi_Entry **entries = NULL;

    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                     "=> pam_passthru_load_config\n");

    pam_passthru_write_lock();
    pam_passthru_delete_config();

    search_pb = slapi_pblock_new();

    /* Find all entries in the active config area. */
    slapi_search_internal_set_pb(search_pb, slapi_sdn_get_ndn(pam_passthru_get_config_area()),
                                 LDAP_SCOPE_SUBTREE, "objectclass=*",
                                 NULL, 0, NULL, NULL,
                                 pam_passthruauth_get_plugin_identity(), 0);
    slapi_search_internal_pb(search_pb);
    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);

    if (LDAP_SUCCESS != result) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                     &entries);
    if (NULL == entries || NULL == entries[0]) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    /* Check if we are using an alternate config area.  We do this here
     * so we don't have to check each every time in the loop below. */
    if (slapi_sdn_compare(pam_passthru_get_config_area(),
            pam_passthruauth_get_plugin_sdn()) != 0) {
        alternate = 1;
    }

    /* Validate and apply config if valid.  If skip_validate is set, we skip
     * validation and just apply the config.  This should only be done if the
     * configuration has already been validated. */
    for (i = 0; (entries[i] != NULL); i++) {
        /* If this is the alternate config container, skip it since
         * we don't consider it to be an actual config entry. */
        if (alternate && (slapi_sdn_compare(pam_passthru_get_config_area(),
                slapi_entry_get_sdn(entries[i])) == 0)) {
            continue;
        }

        if (skip_validate || (PAM_PASSTHRU_SUCCESS == pam_passthru_validate_config(entries[i], NULL))) {
            if (PAM_PASSTHRU_FAILURE == pam_passthru_apply_config(entries[i])) {
                slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                                 "pam_passthru_load_config - Unable to apply config "
                                 "for entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
            }
        } else {
            slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                             "pam_passthru_load_config - Skipping invalid config "
                             "entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
        }
    }

  cleanup:
    slapi_free_search_results_internal(search_pb);
    slapi_pblock_destroy(search_pb);
    pam_passthru_unlock();
    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                    "<= pam_passthru_load_config\n");

    return status;
}
Example #13
0
File: uid.c Project: ohamada/389ds
static int
search_one_berval(Slapi_DN *baseDN, const char *attrName,
		const struct berval *value, const char *requiredObjectClass,
		Slapi_DN *target)
{
	int result;
    char *filter;
    Slapi_PBlock *spb;

	result = LDAP_SUCCESS;

	/* If no value, can't possibly be a conflict */
	if ( (struct berval *)NULL == value )
		return result;

    filter = 0;
    spb = 0;

    BEGIN
      int err;
      int sres;
      Slapi_Entry **entries;
      static char *attrs[] = { "1.1", 0 };

      /* Create the filter - this needs to be freed */
      filter = create_filter(attrName, value, requiredObjectClass);

#ifdef DEBUG
      slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
        "SEARCH filter=%s\n", filter);
#endif

      /* Perform the search using the new internal API */
      spb = slapi_pblock_new();
      if (!spb) { result = uid_op_error(2); break; }

      slapi_search_internal_set_pb_ext(spb, baseDN, LDAP_SCOPE_SUBTREE,
      	filter, attrs, 0 /* attrs only */, NULL, NULL, plugin_identity, 0 /* actions */);
      slapi_search_internal_pb(spb);

      err = slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_RESULT, &sres);
      if (err) { result = uid_op_error(3); break; }
    
      /* Allow search to report that there is nothing in the subtree */
      if (sres == LDAP_NO_SUCH_OBJECT) break;

      /* Other errors are bad */
      if (sres) { result = uid_op_error(3); break; }

      err = slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
              &entries);
      if (err) { result = uid_op_error(4); break; }

      /*
       * Look at entries returned.  Any entry found must be the
       * target entry or the constraint fails.
       */
      for(;*entries;entries++)
      {
#ifdef DEBUG
        slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
                        "SEARCH entry dn=%s\n", slapi_entry_get_dn(*entries));
#endif

        /*
         * It is a Constraint Violation if any entry is found, unless
         * the entry is the target entry (if any).
         */
        if (!target || slapi_sdn_compare(slapi_entry_get_sdn(*entries), target) != 0)
        {
          result = LDAP_CONSTRAINT_VIOLATION;
          break;
        }
      }

#ifdef DEBUG
      slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
        "SEARCH complete result=%d\n", result);
#endif
    END

    /* Clean-up */
    if (spb) {
	slapi_free_search_results_internal(spb);
	slapi_pblock_destroy(spb);
    }

    slapi_ch_free((void**)&filter);

  return result;
}
Example #14
0
File: urp.c Project: ohamada/389ds
/*
 * An URP Naming Collision helper function. Retreives a list of entries
 * that have the given dn excluding the unique id of the entry. Any 
 * entries returned will be entries that have been added with the same
 * dn, but caused a naming conflict when replicated. The URP to fix
 * this constraint violation is to append the unique id of the entry
 * to its RDN.
 */
static Slapi_Entry *
urp_get_min_naming_conflict_entry ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn )
{
	Slapi_PBlock *newpb = NULL;
	LDAPControl **server_ctrls = NULL;
	Slapi_Entry **entries = NULL;
	Slapi_Entry *min_naming_conflict_entry = NULL;
	const CSN *min_csn = NULL;
	char *filter = NULL;
	char *parent_dn = NULL;
	char *basedn;
	int i = 0;
	int min_i = -1;
	int op_result = LDAP_SUCCESS;

	slapi_pblock_get (pb, SLAPI_URP_NAMING_COLLISION_DN, &basedn);
	if (NULL == basedn || strncmp (basedn, SLAPI_ATTR_UNIQUEID, strlen(SLAPI_ATTR_UNIQUEID)) == 0)
		return NULL;

	slapi_log_error ( SLAPI_LOG_REPL, sessionid,
		"Enter urp_get_min_naming_conflict_entry for %s\n", basedn);

	filter = slapi_filter_sprintf("(%s=%s %s%s)", ATTR_NSDS5_REPLCONFLICT, REASON_ANNOTATE_DN,
			ESC_NEXT_VAL, basedn);

	/* server_ctrls will be freed when newpb is destroyed */
	server_ctrls = (LDAPControl **)slapi_ch_calloc (2, sizeof (LDAPControl *));
	server_ctrls[0] = create_managedsait_control();
	server_ctrls[1] = NULL;
	
	newpb = slapi_pblock_new();
	parent_dn = slapi_dn_parent (basedn);
	slapi_search_internal_set_pb(newpb,
								 parent_dn, /* Base DN */
								 LDAP_SCOPE_ONELEVEL,
								 filter,
								 NULL, /* Attrs */
								 0, /* AttrOnly */
								 server_ctrls, /* Controls */
								 NULL, /* UniqueID */
								 repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
								 0);
	slapi_search_internal_pb(newpb);
	slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
	slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
	if ( (op_result != LDAP_SUCCESS) || (entries == NULL) )
	{
		/* Log a message */
		goto done;
	}
	/* For all entries, get the one with the smallest dn csn */
	for (i = 0; NULL != entries[i]; i++)
	{
		const CSN *dncsn;
		dncsn = entry_get_dncsn(entries[i]);
		if ((dncsn != opcsn) && 
			((min_csn == NULL) || (csn_compare(dncsn, min_csn) < 0)) &&
			!is_tombstone_entry (entries[i]))
		{
			min_csn = dncsn;
			min_i = i;
		}
		/*
		 * If there are too many conflicts, the current urp code has no
		 * guarantee for all servers to converge anyway, because the
		 * urp and the backend can't be done in one transaction due
		 * to either performance or the deadlock problem.
		 * Don't sacrifice the performance too much for impossible.
		 */
		if (min_csn && i > 5)
		{
			break;
		}
	}
	
	if (min_csn != NULL) {
		/* Found one entry */
		min_naming_conflict_entry = slapi_entry_dup(entries[min_i]);
	}

done:
	slapi_ch_free_string(&parent_dn);
	if (filter) {
		PR_smprintf_free(filter);
	}
	slapi_free_search_results_internal(newpb);
	slapi_pblock_destroy(newpb);
	newpb = NULL;

	slapi_log_error ( SLAPI_LOG_REPL, sessionid,
		"Leave urp_get_min_naming_conflict_entry (found %d entries)\n", i);

	return min_naming_conflict_entry;
}
Example #15
0
/* Reads in any config information held in the dse for the given
 * entry.  Creates dse entries used to configure the given instance
 * if they don't already exist.  Registers dse callback functions to
 * maintain those dse entries.  Returns 0 on success. */
int 
ldbm_instance_config_load_dse_info(ldbm_instance *inst)
{
    struct ldbminfo *li = inst->inst_li;
    Slapi_PBlock *search_pb;
    Slapi_Entry **entries = NULL;
    char *dn = NULL;
    int rval = 0;

    /* We try to read the entry 
     * cn=instance_name, cn=ldbm database, cn=plugins, cn=config.  If the
     * entry is there, then we process the config information it stores.
     */
    dn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
                                inst->inst_name, li->li_plugin->plg_name);
    if (NULL == dn) {
        LDAPDebug2Args(LDAP_DEBUG_ANY,
                       "ldbm_instance_config_load_dse_info: "
                       "failed create instance dn %s for plugin %s\n",
                       inst->inst_name, inst->inst_li->li_plugin->plg_name);
        rval = 1;
        goto bail;
    }

    search_pb = slapi_pblock_new();
    if (!search_pb) {
        LDAPDebug(LDAP_DEBUG_ANY,
                       "ldbm_instance_config_load_dse_info: Out of memory\n",
                       0, 0, 0);
        rval = 1;
        goto bail;
    }

    slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_BASE, 
                                 "objectclass=*", NULL, 0, NULL, NULL,
                                 li->li_identity, 0);
    slapi_search_internal_pb (search_pb);
    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);

    if (rval != LDAP_SUCCESS) {
        LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n", 0, 0, 0);
        rval = 1;
        goto bail;
    } else {
        /* Need to parse the configuration information for the ldbm
         * plugin that is held in the DSE. */
        slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                         &entries);
        if ((!entries) || (!entries[0])) {
            LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n",
                      0, 0, 0);
            rval = 1;
            goto bail;
        }
        if (0 != parse_ldbm_instance_config_entry(inst, entries[0],
                                         ldbm_instance_config)) {
            LDAPDebug(LDAP_DEBUG_ANY, "Error parsing the config DSE\n",
                      0, 0, 0);
            rval = 1;
            goto bail;
        }
    }

    if (search_pb)
    {
        slapi_free_search_results_internal(search_pb);
        slapi_pblock_destroy(search_pb);
    }

    /* Add skeleton dse entries for this instance */
    /* IF they already exist, that's ok */
    ldbm_config_add_dse_entries(li, ldbm_instance_skeleton_entries,
                                inst->inst_name, li->li_plugin->plg_name,
                                inst->inst_name, 0);

    /* setup the dse callback functions for the ldbm instance config entry */
    slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)",
        ldbm_instance_search_config_entry_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)",
        ldbm_instance_modify_config_entry_callback, (void *) inst);
    slapi_config_register_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)",
        ldbm_instance_search_config_entry_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)",
        ldbm_instance_deny_config, (void *)inst);
    /* delete is handled by a callback set in ldbm_config.c */

    slapi_ch_free_string(&dn);

    /* don't forget the monitor! */
    dn = slapi_create_dn_string("cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config",
                                inst->inst_name, li->li_plugin->plg_name);
    if (NULL == dn) {
        LDAPDebug2Args(LDAP_DEBUG_ANY,
                       "ldbm_instance_config_load_dse_info: "
                       "failed create monitor instance dn for plugin %s, "
                       "instance %s\n",
                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
        rval = 1;
        goto bail;
    }
    /* make callback on search; deny add/modify/delete */
    slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search,
        (void *)inst);
    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config,
        (void *)inst);
    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config,
        (void *)inst);
    /* delete is okay */
    slapi_ch_free_string(&dn);

    /* Callbacks to handle indexes */
    dn = slapi_create_dn_string("cn=index,cn=%s,cn=%s,cn=plugins,cn=config",
                                inst->inst_name, li->li_plugin->plg_name);
    if (NULL == dn) {
        LDAPDebug2Args(LDAP_DEBUG_ANY,
                       "ldbm_instance_config_load_dse_info: "
                       "failed create index instance dn for plugin %s, "
                       "instance %s\n",
                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
        rval = 1;
        goto bail;
    }
    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
        ldbm_instance_index_config_add_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
        ldbm_instance_index_config_delete_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
        ldbm_instance_index_config_modify_callback, (void *) inst);
    slapi_ch_free_string(&dn);

    /* Callbacks to handle attribute encryption */
    dn = slapi_create_dn_string("cn=encrypted attributes,cn=%s,cn=%s,cn=plugins,cn=config",
                                inst->inst_name, li->li_plugin->plg_name);
    if (NULL == dn) {
        LDAPDebug2Args(LDAP_DEBUG_ANY,
                       "ldbm_instance_config_load_dse_info: "
                       "failed create encrypted attribute instance dn "
                       "for plugin %s, instance %s\n",
                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
        rval = 1;
        goto bail;
    }
    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
        ldbm_instance_attrcrypt_config_add_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
        ldbm_instance_attrcrypt_config_delete_callback, (void *) inst);
    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
        LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
        ldbm_instance_attrcrypt_config_modify_callback, (void *) inst);
    rval = 0;
bail:
    slapi_ch_free_string(&dn);
    return rval;
}
Example #16
0
int oath_preop_bind(Slapi_PBlock *pb) {

    char *dn;
    const char *creds;
    int creds_len, hotp_len = oath_preop_config.hotp_length, pin_len, method, rc = LDAP_SUCCESS, handled = 1;
    struct berval *credentials;
    Slapi_Value *sv_creds = NULL;
    Slapi_PBlock *upb, *tpb; // PBlocks for user and token searches
    Token token;

    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind\n");

    if (slapi_pblock_get(pb, SLAPI_BIND_METHOD, (void *) &method) != 0 ||
            slapi_pblock_get(pb, SLAPI_BIND_TARGET, (void *) &dn) != 0 ||
            slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, (void *) &credentials) != 0) {
        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Could not get parameters for bind operation\n");
        slapi_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
        return 1;
    }

    switch (method) {

    case LDAP_AUTH_SIMPLE:

        rc = LDAP_SUCCESS;
        sv_creds = slapi_value_new_berval(credentials);
        creds = slapi_value_get_string(sv_creds);
        creds_len = creds ? strlen(creds) : 0;

        Slapi_Entry **entries, *entry;
        int nentries = 0;

        upb = slapi_pblock_new();
        slapi_search_internal_set_pb(upb, dn, LDAP_SCOPE_SUB, "(objectClass=*)", NULL, 0, NULL, NULL, oath_preop_plugin_id, 0);
        slapi_search_internal_pb(upb);
        slapi_pblock_get(upb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
        slapi_pblock_get(upb, SLAPI_NENTRIES, &nentries);
        slapi_pblock_get(upb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);

        if (rc == LDAP_SUCCESS && nentries > 0 && entries != NULL && (entry = *entries) != NULL) {

            char filter[1024], *attrs[] = {"tokenSerial", "tokenSeed", "tokenCounter", "tokenPIN", NULL};
            Slapi_Entry **tokens;
            int ntokens = 0;

            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Authenticating DN: %s\n", dn);

            // search for tokens

            snprintf(filter, 1024, "(&(objectClass=oathToken)(tokenOwner=%s))", dn);

            tpb = slapi_pblock_new();
            slapi_search_internal_set_pb(tpb, oath_preop_config.token_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, oath_preop_plugin_id, 0);
            slapi_search_internal_pb(tpb);
            slapi_pblock_get(tpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
            slapi_pblock_get(tpb, SLAPI_NENTRIES, &ntokens);
            slapi_pblock_get(tpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &tokens);

            if (rc == LDAP_SUCCESS && ntokens > 0 && tokens != NULL) {

                int t, w;
                unsigned char hotp[hotp_len + 1];

                for (t = 0; t < ntokens; t++) {

                    oath_token_from_entry(&token, tokens[t]);

                    pin_len = token.pin ? strlen(token.pin) : 0;

                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Found token: %s\n", token.serial);

                    if (pin_len + hotp_len != creds_len)
                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Credentials length did not match\n");

                    else if (token.pin && strncmp(creds, token.pin, pin_len))
                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: PIN did not match\n");

                    else for (w = 0; w < oath_preop_config.hotp_inner_window; w++) {

                            if (oath_hotp(hotp, hotp_len, token.seed->bv_val, token.seed->bv_len, token.counter + w, oath_preop_config.hotp_trunc_offset, oath_preop_config.hotp_checksum)) {

                                // slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: hotp(%d) =  %s\n", token.counter + w, hotp);

                                if (!strncmp(hotp, creds + pin_len, hotp_len)) {

                                    // success
                                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: hotp(%d) =  %s\n", token.counter + w, hotp);

                                    if (oath_update_token(tokens[t], token.counter + w + 1) != 0) {
                                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Failed to update token entry\n");
                                        rc = LDAP_OPERATIONS_ERROR;
                                    };

                                    // OpenLDAP does not support setting SLAPI_CONN_DN and SLAPI_CONN_AUTHMETHOD

                                    /*
                                                                        if (slapi_pblock_set(pb, SLAPI_CONN_DN, slapi_ch_strdup(dn)) != 0 ||
                                                                                slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_SIMPLE) != 0) {
                                                                            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Failed to set DN and auth method for connection\n", dn);
                                                                            rc = LDAP_OPERATIONS_ERROR;
                                                                        }
                                    */

                                    goto free_tpb;

                                }

                            } else {
                                // HOTP error
                                slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: HOTP error for token %s\n", token.serial);
                                break;
                            }

                        }

                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Token %s did not match\n", token.serial);
                    oath_token_free(&token);

                }

                // No token matched

                handled = 0;
                goto free_tpb;

            } else { // no tokens associated

                slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: DN %s has got no token(s) associated, rc = %d\n", dn, rc);
                handled = 0;
                goto free_upb;

            }


        } else {

            // entry not found; don't fail because this can be root (directory manager) DN

            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: DN %s not found\n", dn);

            if (rc == LDAP_SUCCESS)
                rc = LDAP_OPERATIONS_ERROR;
            else
                handled = 0;

            goto free_upb;

        }

        break;

    case LDAP_AUTH_NONE:
    case LDAP_AUTH_SASL:
    default:
        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_bind_preop: Authentication type not supported: %d", method);
        return 0;

    }

free_tpb:
    oath_token_free(&token);
    slapi_free_search_results_internal(tpb);
    slapi_pblock_destroy(tpb);

free_upb:
    slapi_free_search_results_internal(upb);
    slapi_pblock_destroy(upb);

    slapi_value_free(&sv_creds);

    if (handled) {
        slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
        return 1;
    } else
        return 0;

}
Example #17
0
/*
  return the value(s) of the given attribute in the entry that
  matches the given criteria.  The criteria must match one
  and only one entry.
  Returns:
  -1 - problem doing internal search
  LDAP_UNWILLING_TO_PERFORM - more than one matching entry
  LDAP_NO_SUCH_OBJECT - no entry found that matched
  0 and attrval == NULL - entry found but no attribute
  other ldap error - error doing search for given basedn
*/
static int
internal_find_entry_get_attr_val(const Slapi_DN *basedn, int scope,
                                 const char *filter, const char *attrname,
                                 Slapi_ValueSet **svs, char **attrval)
{
    Slapi_Entry **entries = NULL;
    Slapi_PBlock *pb = NULL;
    const char *search_basedn = slapi_sdn_get_dn(basedn);
    int search_scope = scope;
    int ret = LDAP_SUCCESS;
    const char *attrs[2] = {attrname, NULL};

    if (svs) {
        *svs = NULL;
    }
    if (attrval) {
        *attrval = NULL;
    }
    pb = slapi_pblock_new();
    slapi_search_internal_set_pb(pb, search_basedn, search_scope, filter,
                                 (char **)attrs, 0, NULL, NULL,
                                 ipa_winsync_get_plugin_identity(), 0);
    slapi_search_internal_pb(pb);

    /* This search may return no entries, but should never
       return an error
    */
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
    if (ret != LDAP_SUCCESS) {
        LOG_FATAL("Error [%d:%s] searching for base [%s] filter [%s]"
                  " attr [%s]\n", ret, ldap_err2string(ret),
                  search_basedn, filter, attrs[0]);
        goto out1;
    }

    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
    if (entries && entries[0] && entries[1]) {
        /* error - should never be more than one matching entry */
        LOG_FATAL("Error: more than one entry matches search for "
                  "base [%s] filter [%s] attr [%s]\n",
                  search_basedn, filter, attrs[0]);
        ret = LDAP_UNWILLING_TO_PERFORM;
        goto out1;
    }

    if (entries && entries[0]) { /* found one */
        if (svs) {
            Slapi_Attr *attr = NULL;
            if (!slapi_entry_attr_find(entries[0], attrname, &attr) &&
               (NULL != attr)) {
                /* slapi_attr_get_valueset allocates svs - must be freed later */
                slapi_attr_get_valueset(attr, svs);
            }
        }
        if (attrval) {
            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;
        LOG("Did not find an entry for search "
            "base [%s] filter [%s] attr [%s]\n",
            search_basedn, filter, attrs[0]);
    }

out1:
    if (pb) {
        slapi_free_search_results_internal(pb);
        slapi_pblock_destroy(pb);
        pb = NULL;
    }

    return ret;
}