Esempio n. 1
0
static int
default_mr_filter_match(void *obj, Slapi_Entry *e, Slapi_Attr *attr)
{
/* returns:  0  filter matched
 *	    -1  filter did not match
 *	    >0  an LDAP error code
 */
	int rc = -1;
	struct mr_private* mrpriv = (struct mr_private*)obj;
	
	/* In case SLAPI_PLUGIN_OBJECT is not set, mrpriv may be NULL */
	if (mrpriv == NULL)
		return rc;
	
    for (; (rc == -1) && (attr != NULL); slapi_entry_next_attr(e, attr, &attr)) {
		char* type = NULL;
		if (!slapi_attr_get_type (attr, &type) && type != NULL &&
			!slapi_attr_type_cmp ((const char *)mrpriv->type, type, 2/*match subtypes*/)) {
			Slapi_Value **vals = attr_get_present_values(attr);
#ifdef SUPPORT_MR_SUBSTRING_MATCHING
			if (mrpriv->ftype == LDAP_FILTER_SUBSTRINGS) {
				rc = (*mrpriv->match_fn)(pb, mrpriv->initial, mrpriv->any, mrpriv->final, vals);
			}
#endif
			rc = (*mrpriv->match_fn)(NULL, mrpriv->value, vals, mrpriv->ftype, NULL);
		}
Esempio n. 2
0
/* Handles the parsing of the config entry for an ldbm instance.  Returns 0
 * on success. */    
static int 
parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_info *config_array)
{
    Slapi_Attr *attr = NULL;
    
    for (slapi_entry_first_attr(e, &attr); attr; 
         slapi_entry_next_attr(e, attr, &attr)) { 
        char *attr_name = NULL;
        Slapi_Value *sval = NULL;
        struct berval *bval;
        char err_buf[BUFSIZ];
        
        slapi_attr_get_type(attr, &attr_name);

        /* There are some attributes that we don't care about, 
         * like objectclass. */
        if (ldbm_config_ignored_attr(attr_name)) {
            continue;
        }

        /* We have to handle suffix attributes a little differently */
        if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) {
            Slapi_DN suffix;

            slapi_attr_first_value(attr, &sval);
            
            bval = (struct berval *) slapi_value_get_berval(sval);
            slapi_sdn_init_dn_byref(&suffix, bval->bv_val);
            if (!slapi_be_issuffix(inst->inst_be, &suffix)) {
                be_addsuffix(inst->inst_be, &suffix);
            }
            slapi_sdn_done(&suffix);
            continue;
        }

        /* We are assuming that each of these attributes are to have 
         * only one value.  If they have more than one value, like
         * the nsslapd-suffix attribute, then they need to be 
         * handled differently. */
        slapi_attr_first_value(attr, &sval);
        bval = (struct berval *) slapi_value_get_berval(sval);

        if (ldbm_config_set((void *) inst, attr_name, config_array, bval,
            err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */, LDAP_MOD_REPLACE) != LDAP_SUCCESS) {
            LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n",
                      attr_name, err_buf, 0);
            return 1;
        }
    }

    /* Read the index entries */
    read_instance_index_entries(inst);
    /* Read the attribute encryption entries */
    read_instance_attrcrypt_entries(inst);

    return 0;
}
Esempio n. 3
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);
}
Esempio n. 4
0
static int 
parse_ldbm_instance_entry(Slapi_Entry *e, char **instance_name)
{
    Slapi_Attr *attr = NULL;
    
    for (slapi_entry_first_attr(e, &attr); attr;
         slapi_entry_next_attr(e, attr, &attr)) {
        char *attr_name = NULL;

        slapi_attr_get_type(attr, &attr_name);
        if (strcasecmp(attr_name, "cn") == 0) {
            Slapi_Value *sval = NULL;
            struct berval *bval;
            slapi_attr_first_value(attr, &sval);
            bval = (struct berval *) slapi_value_get_berval(sval);
            *instance_name = slapi_ch_strdup((char *)bval->bv_val);
        }
    }
    return 0;
}
Esempio n. 5
0
static int
or_filter_match (void* obj, Slapi_Entry* entry, Slapi_Attr* attr)
/* returns:  0  filter matched
 *	    -1  filter did not match
 *	    >0  an LDAP error code
 */
{
    auto int rc = -1; /* no match */
    auto or_filter_t* or = (or_filter_t*)obj;
    for (; attr != NULL; slapi_entry_next_attr (entry, attr, &attr)) {
	auto char* type = NULL;
	auto struct berval** vals = NULL;

/*
 * XXXmcs 1-March-2001: This code would perform better if it did not make
 * a copy of the values here, but that would require re-writing the code
 * in this file to use Slapi_ValueSet's instead of struct berval **'s
 * (and that is not a small project).
 */
	if (!slapi_attr_get_type (attr, &type) && type != NULL &&
	    !slapi_attr_type_cmp (or->or_type, type, 2/*match subtypes*/) &&
	    !slapi_attr_get_bervals_copy(attr, &vals) && vals != NULL) {

	    if (or->or_op == SLAPI_OP_SUBSTRING) {
		rc = ss_filter_match (or, vals);
	    } else {
		rc = op_filter_match (or, vals);
	    }

	    ber_bvecfree( vals );
	    vals = NULL;
	    if (rc >= 0) break;
	}
    }
    return rc;
}
Esempio n. 6
0
void
_ger_get_attrs_rights (
	Slapi_PBlock *gerpb,
	Slapi_Entry *e,
	const char *subjectndn,
	char **attrs,
	char **gerstr,
	size_t *gerstrsize,
	size_t *gerstrcap,
	char **errbuf
	)
{
	int isfirstattr = 1;

	/* gerstr was initially allocated with enough space for one more line */
	_append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL);

	/* 
	 * If it's stated attribute list is given,
	 * the first attr in the list should not be empty.
	 * Otherwise, it's considered the list is not given.
	 */
	if (attrs && *attrs && (strlen(*attrs) > 0))
	{
		int i = 0;
		char **allattrs = NULL;
		char **opattrs = NULL;
		char **noexpattrs = NULL; /* attrs not to expose */
		char **myattrs = NULL;
		char **thisattr = NULL;
		int hasstar = charray_inlist(attrs, "*");
		int hasplus = charray_inlist(attrs, "+");
		Slapi_Attr *objclasses = NULL;
		Slapi_ValueSet *objclassvals = NULL;
		int isextensibleobj = 0;

		/* get all attrs available for the entry */
		slapi_entry_attr_find(e, "objectclass", &objclasses);
		if (NULL != objclasses) {
			Slapi_Value *v;
			slapi_attr_get_valueset(objclasses, &objclassvals);
			i = slapi_valueset_first_value(objclassvals, &v);
			if (-1 != i)
			{
				const char *ocname = NULL;
				allattrs = slapi_schema_list_objectclass_attributes(
							(const char *)v->bv.bv_val,
							SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED);
				/* check if this entry is an extensble object or not */
				ocname = slapi_value_get_string(v);
				if ( strcasecmp( ocname, "extensibleobject" ) == 0 )
				{
					isextensibleobj = 1;
				}
				/* add "aci" to the allattrs to adjust to do_search */
				charray_add(&allattrs, slapi_attr_syntax_normalize("aci"));
				while (-1 != i)
				{
					i = slapi_valueset_next_value(objclassvals, i, &v);
					if (-1 != i)
					{
						myattrs = slapi_schema_list_objectclass_attributes(
							(const char *)v->bv.bv_val,
							SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED);
						/* check if this entry is an extensble object or not */
						ocname = slapi_value_get_string(v);
						if ( strcasecmp( ocname, "extensibleobject" ) == 0 )
						{
							isextensibleobj = 1;
						}
						charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/);
						charray_free(myattrs);
					}
				}
			}
			slapi_valueset_free(objclassvals);
		}

		/* get operational attrs */
		opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR);
		noexpattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_NOEXPOSE);
		/* subtract no expose attrs from opattrs (e.g., unhashed pw) */
		charray_subtract(opattrs, noexpattrs, NULL);

		if (isextensibleobj)
		{
			for ( i = 0; attrs[i]; i++ )
			{
				if ('\0' == *attrs[i]) {
					continue; /* skip an empty attr */
				}
				_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, 
								gerstrsize, gerstrcap, isfirstattr, errbuf );
				isfirstattr = 0;
			}
		}
		else
		{
			if (hasstar && hasplus)
			{
				GER_GET_ATTR_RIGHTS(allattrs);
				GER_GET_ATTR_RIGHTS(opattrs);
			}
			else if (hasstar)
			{
				GER_GET_ATTR_RIGHTS(allattrs);
				GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs);
			}
			else if (hasplus)
			{
				GER_GET_ATTR_RIGHTS(opattrs);
				GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs);
			}
			else
			{
				for ( i = 0; attrs[i]; i++ )
				{
					if ('\0' == *attrs[i]) {
						continue; /* skip an empty attr */
					}
					if (charray_inlist(noexpattrs, attrs[i]))
					{
						continue;
					}
					else if (charray_inlist(allattrs, attrs[i]) ||
						charray_inlist(opattrs, attrs[i]) ||
						(0 == strcasecmp(attrs[i], "dn")) ||
						(0 == strcasecmp(attrs[i], "distinguishedName")))
					{
						_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i],
							gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
						isfirstattr = 0;
					}
					else
					{
						/* if the attr does not belong to the entry,
						   "<attr>:none" is returned */
						if (!isfirstattr)
						{
							_append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL);
						}
						_append_gerstr(gerstr, gerstrsize, gerstrcap, attrs[i], ":");
						_append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL);
						isfirstattr = 0;
					}
				}
			}
		}
		charray_free(allattrs);
		charray_free(opattrs);
	}
	else
	{
		Slapi_Attr *prevattr = NULL, *attr;
		char *type;

		while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 )
		{
			if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) )
			{
				slapi_attr_get_type ( attr, &type );
				_ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr,
								gerstrsize, gerstrcap, isfirstattr, errbuf );
				isfirstattr = 0;
			}
			prevattr = attr;
		}
	}

	if ( isfirstattr )
	{
		/* not a single attribute was retrived or specified */
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL);
	}
	return;
}
Esempio n. 7
0
/*
  Given an entry, provide the account policy in effect for that entry.
  Returns non-0 if function fails.  If account policy comes back NULL, it's
  not an error; the entry is simply not covered by a policy.
*/
int
get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id,
                acctPolicy **policy )
{
    Slapi_DN *sdn = NULL;
    Slapi_Entry *policy_entry = NULL;
    Slapi_Attr *attr;
    Slapi_Value *sval = NULL;
    int ldrc;
    char *attr_name;
    char *policy_dn = NULL;
    acctPluginCfg *cfg;
    int rc = 0;

    if( policy == NULL ) {
        /* Bad parameter */
        return( -1 );
    }

    *policy = NULL;

    config_rd_lock();
    cfg = get_config();
    /* Return success and NULL policy */
    policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name );
    if( policy_dn == NULL ) {
        slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                      "get_acctpolicy - \"%s\" is not governed by an account inactivity "
                      "policy subentry\n", slapi_entry_get_ndn( target_entry ) );
        if (cfg->inactivitylimit != ULONG_MAX) {
            goto dopolicy;
        }
        slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                      "get_acctpolicy - \"%s\" is not governed by an account inactivity "
                      "global policy\n", slapi_entry_get_ndn( target_entry ) );
        config_unlock();
        return rc;
    }

    sdn = slapi_sdn_new_dn_byref( policy_dn );
    ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry,
                                            plugin_id );
    slapi_sdn_free( &sdn );

    /* There should be a policy but it can't be retrieved; fatal error */
    if( policy_entry == NULL ) {
        if( ldrc != LDAP_NO_SUCH_OBJECT ) {
            slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME,
                          "get_acctpolicy - Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc );
        } else {
            slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                          "get_acctpolicy - Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc );
        }
        rc = -1;
        goto done;
    }

dopolicy:
    *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) );

    if ( !policy_entry ) { /* global policy */
        (*policy)->inactivitylimit = cfg->inactivitylimit;
        goto done;
    }

    for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL;
            slapi_entry_next_attr( policy_entry, attr, &attr ) ) {
        slapi_attr_get_type(attr, &attr_name);
        if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) {
            if( slapi_attr_first_value( attr, &sval ) == 0 ) {
                (*policy)->inactivitylimit = slapi_value_get_ulong( sval );
            }
        }
    }
done:
    config_unlock();
    slapi_ch_free_string( &policy_dn );
    slapi_entry_free( policy_entry );
    return( rc );
}
Esempio n. 8
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);
}
Esempio n. 9
0
/*
 * Get a Slapi_Entry ready to send over the wire as part of
 * a total update protocol stream. Convert the entry and all
 * of its state information to a BerElement which will be the
 * payload of an extended LDAP operation.
 *
 * Entries consist of:
 * - An entry DN
 * - A uniqueID
 * - A set of present attributes, each of which consists of:
 *   - A set of present values, each of which consists of:
 *     - A value
 *     - A set of CSNs
 *   - A set of deleted values, each of which consists of:
 *     - A value
 *     - A set of CSNs
 * - A set of deleted attibutes, each of which consists of:
 *   - An attribute type
 *   - A set of CSNs. Note that this list of CSNs will always contain exactly one CSN.
 * 
 * This all gets mashed into one BerElement, ready to be blasted over the wire to
 * a replica.
 *
 */
BerElement *
entry2bere(const Slapi_Entry *e, char **excluded_attrs)
{
	BerElement *ber = NULL;
	const char *str = NULL;
	const char *dnstr = NULL;
    char *type;
	Slapi_DN *sdn = NULL;
	Slapi_Attr *attr = NULL, *prev_attr;
    int rc;

	PR_ASSERT(NULL != e);

	if ((ber = ber_alloc()) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("{");
	if (ber_printf(ber, "{") == -1) /* Begin outer sequence */
	{
		goto loser;
	}

	/* Get the entry's uniqueid */
	if ((str = slapi_entry_get_uniqueid(e)) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("s(uniqueid)");
	if (ber_printf(ber, "s", str) == -1)
	{
		goto loser;
	}

	/* Get the entry's DN */
	if ((sdn = slapi_entry_get_sdn((Slapi_Entry *)e)) == NULL) /* XXXggood had to cast away const */
	{
		goto loser;
	}
	if ((dnstr = slapi_sdn_get_dn(sdn)) == NULL)
	{
		goto loser;
	}
	BER_DEBUG("s(dn)");
	if (ber_printf(ber, "s", dnstr) == -1)
	{
		goto loser;
	}

	/* Next comes the annoted list of the entry's attributes */
	BER_DEBUG("[");
	if (ber_printf(ber, "[") == -1) /* Begin set of attributes */
	{
		goto loser;
	}
	/*
	 * We iterate over all of the non-deleted attributes first.
	 */ 
	slapi_entry_first_attr(e, &attr);
	while (NULL != attr)
	{
        /* ONREPL - skip uniqueid attribute since we already sent uniqueid 
           This is a hack; need to figure a better way of storing uniqueid
           in an entry */
        slapi_attr_get_type (attr, &type);
        if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
        {
			/* Check to see if this attribute is excluded by the fractional list */
			if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type)) 
			{
				/* Process this attribute */
				rc = my_ber_printf_attr (ber, attr, PR_FALSE);
				if (rc != 0)
				{
					goto loser;
				}
			}
        }
		
		prev_attr = attr;
		slapi_entry_next_attr(e, prev_attr, &attr);
	}

	/*
	 * Now iterate over the deleted attributes.
	 */ 
	entry_first_deleted_attribute(e, &attr);
	while (attr != NULL)
	{
		slapi_attr_get_type (attr, &type);
		/* Check to see if this attribute is excluded by the fractional list */
		if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type)) 
		{
			/* Process this attribute */
			rc = my_ber_printf_attr (ber, attr, PR_TRUE);
			if (rc != 0)
			{
				goto loser;
			}
		}
		entry_next_deleted_attribute(e, &attr);
	}
	BER_DEBUG("]");
	if (ber_printf(ber, "]") == -1) /* End set for attributes */
	{
		goto loser;
	}
	BER_DEBUG("}");
	if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
	{
		goto loser;
	}
	
	/* If we get here, everything went ok */
	BER_DEBUG("\n");
	goto free_and_return;
loser:
	if (NULL != ber)
	{
		ber_free(ber, 1);
		ber = NULL;
	}

free_and_return:
	return ber;
}