Пример #1
0
Entry *
monitor_entry_stub(
	struct berval *pdn,
	struct berval *pndn,
	struct berval *rdn,
	ObjectClass *oc,
	struct berval *create,
	struct berval *modify
)
{
	monitor_info_t *mi;
	AttributeDescription *nad = NULL;
	Entry *e;
	struct berval nat;
	char *ptr;
	const char *text;
	int rc;

	mi = ( monitor_info_t * )be_monitor->be_private;

	nat = *rdn;
	ptr = strchr( nat.bv_val, '=' );
	nat.bv_len = ptr - nat.bv_val;
	rc = slap_bv2ad( &nat, &nad, &text );
	if ( rc )
		return NULL;

	e = entry_alloc();
	if ( e ) {
		struct berval nrdn;

		rdnNormalize( 0, NULL, NULL, rdn, &nrdn, NULL );
		build_new_dn( &e->e_name, pdn, rdn, NULL );
		build_new_dn( &e->e_nname, pndn, &nrdn, NULL );
		ber_memfree( nrdn.bv_val );
		nat.bv_val = ptr + 1;
		nat.bv_len = rdn->bv_len - ( nat.bv_val - rdn->bv_val );
		attr_merge_normalize_one( e, slap_schema.si_ad_objectClass,
			&oc->soc_cname, NULL );
		attr_merge_normalize_one( e, slap_schema.si_ad_structuralObjectClass,
			&oc->soc_cname, NULL );
		attr_merge_normalize_one( e, nad, &nat, NULL );
		attr_merge_one( e, slap_schema.si_ad_creatorsName, &mi->mi_creatorsName,
			&mi->mi_ncreatorsName );
		attr_merge_one( e, slap_schema.si_ad_modifiersName, &mi->mi_creatorsName,
			&mi->mi_ncreatorsName );
		attr_merge_normalize_one( e, slap_schema.si_ad_createTimestamp,
			create ? create : &mi->mi_startTime, NULL );
		attr_merge_normalize_one( e, slap_schema.si_ad_modifyTimestamp,
			modify ? modify : &mi->mi_startTime, NULL );
	}
	return e;
}
Пример #2
0
int
backsql_entry_addattr(
	Entry			*e,
	AttributeDescription	*ad,
	struct berval		*val,
	void			*memctx )
{
	int			rc;

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(\"%s\"): %s=%s\n", 
		e->e_name.bv_val, ad->ad_cname.bv_val, val->bv_val );
#endif /* BACKSQL_TRACE */

	rc = attr_merge_normalize_one( e, ad, val, memctx );

	if ( rc != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(\"%s\"): "
			"failed to merge value \"%s\" for attribute \"%s\"\n",
			e->e_name.bv_val, val->bv_val, ad->ad_cname.bv_val );
		return rc;
	}

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "<==backsql_entry_addattr(\"%s\")\n",
		e->e_name.bv_val, 0, 0 );
#endif /* BACKSQL_TRACE */

	return LDAP_SUCCESS;
}
Пример #3
0
int
dnssrv_back_search(
    Operation	*op,
    SlapReply	*rs )
{
	int i;
	int rc;
	char *domain = NULL;
	char *hostlist = NULL;
	char **hosts = NULL;
	char *refdn;
	struct berval nrefdn = BER_BVNULL;
	BerVarray urls = NULL;
	int manageDSAit;

	rs->sr_ref = NULL;

	if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
		/* FIXME: need some means to determine whether the database
		 * is a glue instance; if we got here with empty DN, then
		 * we passed this same test in dnssrv_back_referrals() */
		if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) {
			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";

		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
		goto done;
	}

	manageDSAit = get_manageDSAit( op );
	/*
	 * FIXME: we may return a referral if manageDSAit is not set
	 */
	if ( !manageDSAit ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"manageDSAit must be set" );
		goto done;
	}

	if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
		rs->sr_err = LDAP_REFERRAL;
		rs->sr_ref = default_referral;
		send_ldap_result( op, rs );
		rs->sr_ref = NULL;
		goto done;
	}

	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain );

	if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) {
		Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n",
			rc );
		send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
			"no DNS SRV RR available for DN" );
		goto done;
	}

	hosts = ldap_str2charray( hostlist, " " );

	if( hosts == NULL ) {
		Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charray error\n" );
		send_ldap_error( op, rs, LDAP_OTHER,
			"problem processing DNS SRV records for DN" );
		goto done;
	}

	for( i=0; hosts[i] != NULL; i++) {
		struct berval url;

		url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]);
		url.bv_val = ch_malloc( url.bv_len + 1 );

		strcpy( url.bv_val, "ldap://" );
		strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );

		if( ber_bvarray_add( &urls, &url ) < 0 ) {
			free( url.bv_val );
			send_ldap_error( op, rs, LDAP_OTHER,
			"problem processing DNS SRV records for DN" );
			goto done;
		}
	}

	Debug( LDAP_DEBUG_STATS,
	    "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
	    op->o_log_prefix, op->o_protocol,
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val );

	Debug( LDAP_DEBUG_TRACE,
		"DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n",
		op->oq_search.rs_scope,
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
		urls[0].bv_val );

	rc = ldap_domain2dn(domain, &refdn);

	if( rc != LDAP_SUCCESS ) {
		send_ldap_error( op, rs, LDAP_OTHER,
			"DNS SRV problem processing manageDSAit control" );
		goto done;

	} else {
		struct berval bv;
		bv.bv_val = refdn;
		bv.bv_len = strlen( refdn );

		rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx );
		if( rc != LDAP_SUCCESS ) {
			send_ldap_error( op, rs, LDAP_OTHER,
				"DNS SRV problem processing manageDSAit control" );
			goto done;
		}
	}

	if( !dn_match( &nrefdn, &op->o_req_ndn ) ) {
		/* requested dn is subordinate */

		Debug( LDAP_DEBUG_TRACE,
			"DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n",
			op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
			refdn == NULL ? "" : refdn );

		rs->sr_matched = refdn;
		rs->sr_err = LDAP_NO_SUCH_OBJECT;
		send_ldap_result( op, rs );
		rs->sr_matched = NULL;

	} else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) {
		send_ldap_error( op, rs, LDAP_SUCCESS, NULL );

	} else {
		Entry e = { 0 };
		AttributeDescription *ad_objectClass
			= slap_schema.si_ad_objectClass;
		AttributeDescription *ad_ref = slap_schema.si_ad_ref;
		e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val );
		e.e_name.bv_len = op->o_req_dn.bv_len;
		e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val );
		e.e_nname.bv_len = op->o_req_ndn.bv_len;

		e.e_attrs = NULL;
		e.e_private = NULL;

		attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL );
		attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL );

		if ( ad_dc ) {
			char		*p;
			struct berval	bv;

			bv.bv_val = domain;

			p = strchr( bv.bv_val, '.' );
					
			if ( p == bv.bv_val ) {
				bv.bv_len = 1;

			} else if ( p != NULL ) {
				bv.bv_len = p - bv.bv_val;

			} else {
				bv.bv_len = strlen( bv.bv_val );
			}

			attr_merge_normalize_one( &e, ad_dc, &bv, NULL );
		}

		if ( ad_associatedDomain ) {
			struct berval	bv;

			ber_str2bv( domain, 0, 0, &bv );
			attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL );
		}

		attr_merge_normalize_one( &e, ad_ref, urls, NULL );

		rc = test_filter( op, &e, op->oq_search.rs_filter ); 

		if( rc == LDAP_COMPARE_TRUE ) {
			rs->sr_entry = &e;
			rs->sr_attrs = op->oq_search.rs_attrs;
			rs->sr_flags = REP_ENTRY_MODIFIABLE;
			send_search_entry( op, rs );
			rs->sr_entry = NULL;
			rs->sr_attrs = NULL;
			rs->sr_flags = 0;
		}

		entry_clean( &e );

		rs->sr_err = LDAP_SUCCESS;
		send_ldap_result( op, rs );
	}

	free( refdn );
	if ( nrefdn.bv_val ) free( nrefdn.bv_val );

done:
	if( domain != NULL ) ch_free( domain );
	if( hostlist != NULL ) ch_free( hostlist );
	if( hosts != NULL ) ldap_charray_free( hosts );
	if( urls != NULL ) ber_bvarray_free( urls );
	return 0;
}
Пример #4
0
static int
create_baseObject(
	BackendDB	*be,
	const char	*fname,
	int		lineno )
{
	backsql_info 	*bi = (backsql_info *)be->be_private;
	LDAPRDN		rdn;
	char		*p;
	int		rc, iAVA;
	char		buf[1024];

	snprintf( buf, sizeof(buf),
			"dn: %s\n"
			"objectClass: extensibleObject\n"
			"description: builtin baseObject for back-sql\n"
			"description: all entries mapped "
				"in table \"ldap_entries\" "
				"must have "
				"\"" BACKSQL_BASEOBJECT_IDSTR "\" "
				"in the \"parent\" column",
			be->be_suffix[0].bv_val );

	bi->sql_baseObject = str2entry( buf );
	if ( bi->sql_baseObject == NULL ) {
		Debug( LDAP_DEBUG_TRACE,
			"<==backsql_db_config (%s line %d): "
			"unable to parse baseObject entry\n",
			fname, lineno, 0 );
		return 1;
	}

	if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
		return 0;
	}

	rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
			LDAP_DN_FORMAT_LDAP );
	if ( rc != LDAP_SUCCESS ) {
		snprintf( buf, sizeof(buf),
			"unable to extract RDN "
			"from baseObject DN \"%s\" (%d: %s)",
			be->be_suffix[ 0 ].bv_val,
			rc, ldap_err2string( rc ) );
		Debug( LDAP_DEBUG_TRACE,
			"<==backsql_db_config (%s line %d): %s\n",
			fname, lineno, buf );
		return 1;
	}

	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
		LDAPAVA				*ava = rdn[ iAVA ];
		AttributeDescription		*ad = NULL;
		slap_syntax_transform_func	*transf = NULL;
		struct berval			bv = BER_BVNULL;
		const char			*text = NULL;

		assert( ava != NULL );

		rc = slap_bv2ad( &ava->la_attr, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( buf, sizeof(buf),
				"AttributeDescription of naming "
				"attribute #%d from baseObject "
				"DN \"%s\": %d: %s",
				iAVA, be->be_suffix[ 0 ].bv_val,
				rc, ldap_err2string( rc ) );
			Debug( LDAP_DEBUG_TRACE,
				"<==backsql_db_config (%s line %d): %s\n",
				fname, lineno, buf );
			return 1;
		}
		
		transf = ad->ad_type->sat_syntax->ssyn_pretty;
		if ( transf ) {
			/*
	 		 * transform value by pretty function
			 *	if value is empty, use empty_bv
			 */
			rc = ( *transf )( ad->ad_type->sat_syntax,
				ava->la_value.bv_len
					? &ava->la_value
					: (struct berval *) &slap_empty_bv,
				&bv, NULL );
	
			if ( rc != LDAP_SUCCESS ) {
				snprintf( buf, sizeof(buf),
					"prettying of attribute #%d "
					"from baseObject "
					"DN \"%s\" failed: %d: %s",
					iAVA, be->be_suffix[ 0 ].bv_val,
					rc, ldap_err2string( rc ) );
				Debug( LDAP_DEBUG_TRACE,
					"<==backsql_db_config (%s line %d): "
					"%s\n",
					fname, lineno, buf );
				return 1;
			}
		}

		if ( !BER_BVISNULL( &bv ) ) {
			if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
				ber_memfree( ava->la_value.bv_val );
			}
			ava->la_value = bv;
			ava->la_flags |= LDAP_AVA_FREE_VALUE;
		}

		attr_merge_normalize_one( bi->sql_baseObject,
				ad, &ava->la_value, NULL );
	}

	ldap_rdnfree( rdn );

	return 0;
}
Пример #5
0
static int
retcode_db_open( BackendDB *be, ConfigReply *cr)
{
	slap_overinst	*on = (slap_overinst *)be->bd_info;
	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;

	retcode_item_t	*rdi;

	for ( rdi = rd->rd_item; rdi; rdi = rdi->rdi_next ) {
		LDAPRDN			rdn = NULL;
		int			rc, j;
		char*			p;
		struct berval		val[ 3 ];
		char			buf[ SLAP_TEXT_BUFLEN ];

		/* DN */
		rdi->rdi_e.e_name = rdi->rdi_dn;
		rdi->rdi_e.e_nname = rdi->rdi_ndn;

		/* objectClass */
		val[ 0 ] = oc_errObject->soc_cname;
		val[ 1 ] = slap_schema.si_oc_extensibleObject->soc_cname;
		BER_BVZERO( &val[ 2 ] );

		attr_merge( &rdi->rdi_e, slap_schema.si_ad_objectClass, val, NULL );

		/* RDN avas */
		rc = ldap_bv2rdn( &rdi->rdi_dn, &rdn, (char **) &p,
				LDAP_DN_FORMAT_LDAP );

		assert( rc == LDAP_SUCCESS );

		for ( j = 0; rdn[ j ]; j++ ) {
			LDAPAVA			*ava = rdn[ j ];
			AttributeDescription	*ad = NULL;
			const char		*text;

			rc = slap_bv2ad( &ava->la_attr, &ad, &text );
			assert( rc == LDAP_SUCCESS );

			attr_merge_normalize_one( &rdi->rdi_e, ad,
					&ava->la_value, NULL );
		}

		ldap_rdnfree( rdn );

		/* error code */
		snprintf( buf, sizeof( buf ), "%d", rdi->rdi_err );
		ber_str2bv( buf, 0, 0, &val[ 0 ] );

		attr_merge_one( &rdi->rdi_e, ad_errCode, &val[ 0 ], NULL );

		if ( rdi->rdi_ref != NULL ) {
			attr_merge_normalize( &rdi->rdi_e, slap_schema.si_ad_ref,
				rdi->rdi_ref, NULL );
		}

		/* text */
		if ( !BER_BVISNULL( &rdi->rdi_text ) ) {
			val[ 0 ] = rdi->rdi_text;

			attr_merge_normalize_one( &rdi->rdi_e, ad_errText, &val[ 0 ], NULL );
		}

		/* matched */
		if ( !BER_BVISNULL( &rdi->rdi_matched ) ) {
			val[ 0 ] = rdi->rdi_matched;

			attr_merge_normalize_one( &rdi->rdi_e, ad_errMatchedDN, &val[ 0 ], NULL );
		}

		/* sleep time */
		if ( rdi->rdi_sleeptime ) {
			snprintf( buf, sizeof( buf ), "%d", rdi->rdi_sleeptime );
			ber_str2bv( buf, 0, 0, &val[ 0 ] );

			attr_merge_one( &rdi->rdi_e, ad_errSleepTime, &val[ 0 ], NULL );
		}

		/* operations */
		if ( rdi->rdi_mask & SN_DG_OP_ADD ) {
			BER_BVSTR( &val[ 0 ], "add" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_BIND ) {
			BER_BVSTR( &val[ 0 ], "bind" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_COMPARE ) {
			BER_BVSTR( &val[ 0 ], "compare" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_DELETE ) {
			BER_BVSTR( &val[ 0 ], "delete" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_EXTENDED ) {
			BER_BVSTR( &val[ 0 ], "extended" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_MODIFY ) {
			BER_BVSTR( &val[ 0 ], "modify" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_RENAME ) {
			BER_BVSTR( &val[ 0 ], "rename" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}

		if ( rdi->rdi_mask & SN_DG_OP_SEARCH ) {
			BER_BVSTR( &val[ 0 ], "search" );
			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
		}
	}

	return 0;
}
Пример #6
0
int
passwd_back_search(
    Operation	*op,
    SlapReply	*rs )
{
    struct passwd	*pw;
    time_t		stoptime = (time_t)-1;

    LDAPRDN rdn = NULL;
    struct berval parent = BER_BVNULL;

    AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;

    if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
        stoptime = op->o_time + op->ors_tlimit;
    }

    /* Handle a query for the base of this backend */
    if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
        struct berval	val;

        rs->sr_matched = op->o_req_dn.bv_val;

        if( op->ors_scope != LDAP_SCOPE_ONELEVEL ) {
            AttributeDescription	*desc = NULL;
            char			*next;
            Entry			e = { 0 };

            /* Create an entry corresponding to the base DN */
            e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val );
            e.e_name.bv_len = op->o_req_dn.bv_len;
            e.e_nname.bv_val =  ch_strdup( op->o_req_ndn.bv_val );
            e.e_nname.bv_len = op->o_req_ndn.bv_len;

            /* Use the first attribute of the DN
            * as an attribute within the entry itself.
            */
            if( ldap_bv2rdn( &op->o_req_dn, &rdn, &next,
                             LDAP_DN_FORMAT_LDAP ) )
            {
                rs->sr_err = LDAP_INVALID_DN_SYNTAX;
                goto done;
            }

            if( slap_bv2ad( &rdn[0]->la_attr, &desc, &rs->sr_text )) {
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
                ldap_rdnfree(rdn);
                goto done;
            }

            attr_merge_normalize_one( &e, desc, &rdn[0]->la_value, NULL );

            ldap_rdnfree(rdn);
            rdn = NULL;

            /* Every entry needs an objectclass. We don't really
             * know if our hardcoded choice here agrees with the
             * DN that was configured for this backend, but it's
             * better than nothing.
             *
             * should be a configuratable item
             */
            BER_BVSTR( &val, "organizationalUnit" );
            attr_merge_one( &e, ad_objectClass, &val, NULL );

            if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
                rs->sr_entry = &e;
                rs->sr_attrs = op->ors_attrs;
                rs->sr_flags = REP_ENTRY_MODIFIABLE;
                send_search_entry( op, rs );
                rs->sr_flags = 0;
                rs->sr_attrs = NULL;
            }

            entry_clean( &e );
        }

        if ( op->ors_scope != LDAP_SCOPE_BASE ) {
            /* check all our "children" */

            ldap_pvt_thread_mutex_lock( &passwd_mutex );
            pw_start( op->o_bd );
            for ( pw = getpwent(); pw != NULL; pw = getpwent() ) {
                Entry		e = { 0 };

                /* check for abandon */
                if ( op->o_abandon ) {
                    endpwent();
                    ldap_pvt_thread_mutex_unlock( &passwd_mutex );
                    return( SLAPD_ABANDON );
                }

                /* check time limit */
                if ( op->ors_tlimit != SLAP_NO_LIMIT
                        && slap_get_time() > stoptime )
                {
                    send_ldap_error( op, rs, LDAP_TIMELIMIT_EXCEEDED, NULL );
                    endpwent();
                    ldap_pvt_thread_mutex_unlock( &passwd_mutex );
                    return( 0 );
                }

                if ( pw2entry( op->o_bd, pw, &e ) ) {
                    rs->sr_err = LDAP_OTHER;
                    endpwent();
                    ldap_pvt_thread_mutex_unlock( &passwd_mutex );
                    goto done;
                }

                if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
                    /* check size limit */
                    if ( --op->ors_slimit == -1 ) {
                        send_ldap_error( op, rs, LDAP_SIZELIMIT_EXCEEDED, NULL );
                        endpwent();
                        ldap_pvt_thread_mutex_unlock( &passwd_mutex );
                        return( 0 );
                    }

                    rs->sr_entry = &e;
                    rs->sr_attrs = op->ors_attrs;
                    rs->sr_flags = REP_ENTRY_MODIFIABLE;
                    send_search_entry( op, rs );
                    rs->sr_flags = 0;
                    rs->sr_entry = NULL;
                }

                entry_clean( &e );
            }
            endpwent();
            ldap_pvt_thread_mutex_unlock( &passwd_mutex );
        }

    } else {
        char	*next;
        Entry	e = { 0 };
        int	rc;

        if (! be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
            dnParent( &op->o_req_ndn, &parent );
        }

        /* This backend is only one layer deep. Don't answer requests for
         * anything deeper than that.
         */
        if( !be_issuffix( op->o_bd, &parent ) ) {
            int i;
            for( i=0; op->o_bd->be_nsuffix[i].bv_val != NULL; i++ ) {
                if( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_nsuffix[i] ) ) {
                    rs->sr_matched = op->o_bd->be_suffix[i].bv_val;
                    break;
                }
            }
            rs->sr_err = LDAP_NO_SUCH_OBJECT;
            goto done;
        }

        if( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
            goto done;
        }

        if ( ldap_bv2rdn( &op->o_req_dn, &rdn, &next,
                          LDAP_DN_FORMAT_LDAP ))
        {
            rs->sr_err = LDAP_OTHER;
            goto done;
        }

        ldap_pvt_thread_mutex_lock( &passwd_mutex );
        pw_start( op->o_bd );
        pw = getpwnam( rdn[0]->la_value.bv_val );
        if ( pw == NULL ) {
            rs->sr_matched = parent.bv_val;
            rs->sr_err = LDAP_NO_SUCH_OBJECT;
            ldap_pvt_thread_mutex_unlock( &passwd_mutex );
            goto done;
        }

        rc = pw2entry( op->o_bd, pw, &e );
        ldap_pvt_thread_mutex_unlock( &passwd_mutex );
        if ( rc ) {
            rs->sr_err = LDAP_OTHER;
            goto done;
        }

        if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
            rs->sr_entry = &e;
            rs->sr_attrs = op->ors_attrs;
            rs->sr_flags = REP_ENTRY_MODIFIABLE;
            send_search_entry( op, rs );
            rs->sr_flags = 0;
            rs->sr_entry = NULL;
            rs->sr_attrs = NULL;
        }

        entry_clean( &e );
    }

done:
    if( rs->sr_err != LDAP_NO_SUCH_OBJECT ) rs->sr_matched = NULL;
    send_ldap_result( op, rs );

    if( rdn != NULL ) ldap_rdnfree( rdn );

    return( 0 );
}
Пример #7
0
static int
pw2entry( Backend *be, struct passwd *pw, Entry *e )
{
    size_t		pwlen;
    struct berval	val;
    struct berval	bv;

    int		rc;

    /*
     * from pw we get pw_name and make it cn
     * give it an objectclass of person.
     */

    pwlen = strlen( pw->pw_name );
    val.bv_len = STRLENOF("uid=,") + ( pwlen + be->be_suffix[0].bv_len );
    val.bv_val = ch_malloc( val.bv_len + 1 );

    /* rdn attribute type should be a configuratable item */
    sprintf( val.bv_val, "uid=%s,%s",
             pw->pw_name, be->be_suffix[0].bv_val );

    rc = dnNormalize( 0, NULL, NULL, &val, &bv, NULL );
    if( rc != LDAP_SUCCESS ) {
        free( val.bv_val );
        return( -1 );
    }

    e->e_name = val;
    e->e_nname = bv;

    e->e_attrs = NULL;

    /* objectclasses should be configurable items */
    BER_BVSTR( &val, "person" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    BER_BVSTR( &val, "uidObject" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    val.bv_val = pw->pw_name;
    val.bv_len = pwlen;
    attr_merge_normalize_one( e, slap_schema.si_ad_uid, &val, NULL );	/* required by uidObject */
    attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );	/* required by person */
    attr_merge_normalize_one( e, ad_sn, &val, NULL );	/* required by person */

#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
    /*
     * if gecos is present, add it as a cn. first process it
     * according to standard BSD usage. If the processed cn has
     * a space, use the tail as the surname.
     */
    if (pw->pw_gecos[0]) {
        char *s;

        ber_str2bv( pw->pw_gecos, 0, 0, &val );
        attr_merge_normalize_one( e, ad_desc, &val, NULL );

        s = ber_bvchr( &val, ',' );
        if ( s ) *s = '\0';

        s = ber_bvchr( &val, '&' );
        if ( s ) {
            char buf[1024];

            if( val.bv_len + pwlen < sizeof(buf) ) {
                int i = s - val.bv_val;
                strncpy( buf, val.bv_val, i );
                s = buf + i;
                strcpy( s, pw->pw_name );
                *s = TOUPPER((unsigned char)*s);
                strcat( s, val.bv_val + i + 1 );
                val.bv_val = buf;
            }
        }
        val.bv_len = strlen( val.bv_val );

        if ( val.bv_len && strcasecmp( val.bv_val, pw->pw_name ) ) {
            attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );
        }

        if ( ( s = strrchr(val.bv_val, ' ' ) ) ) {
            ber_str2bv( s + 1, 0, 0, &val );
            attr_merge_normalize_one( e, ad_sn, &val, NULL );
        }
    }
#endif /* HAVE_STRUCT_PASSWD_PW_GECOS */

    return( 0 );
}
Пример #8
0
int
monitor_subsys_listener_init(
	BackendDB		*be,
	monitor_subsys_t	*ms
)
{
	monitor_info_t	*mi;
	Entry		*e_listener, **ep;
	int		i;
	monitor_entry_t	*mp;
	Listener	**l;

	assert( be != NULL );

	if ( ( l = slapd_get_listeners() ) == NULL ) {
		if ( slapMode & SLAP_TOOL_MODE ) {
			return 0;
		}

		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_listener_init: "
			"unable to get listeners\n", 0, 0, 0 );
		return( -1 );
	}

	mi = ( monitor_info_t * )be->be_private;

	if ( monitor_cache_get( mi, &ms->mss_ndn, &e_listener ) ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_listener_init: "
			"unable to get entry \"%s\"\n",
			ms->mss_ndn.bv_val, 0, 0 );
		return( -1 );
	}

	mp = ( monitor_entry_t * )e_listener->e_private;
	mp->mp_children = NULL;
	ep = &mp->mp_children;

	for ( i = 0; l[ i ]; i++ ) {
		char 		buf[ BACKMONITOR_BUFSIZE ];
		Entry		*e;
		struct berval bv;

		bv.bv_len = snprintf( buf, sizeof( buf ),
				"cn=Listener %d", i );
		bv.bv_val = buf;
		e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
			mi->mi_oc_monitoredObject, NULL, NULL );

		if ( e == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"monitor_subsys_listener_init: "
				"unable to create entry \"cn=Listener %d,%s\"\n",
				i, ms->mss_ndn.bv_val, 0 );
			return( -1 );
		}

		attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionLocalAddress,
				&l[ i ]->sl_name, NULL );

		attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI,
				&l[ i ]->sl_url, NULL );

#ifdef HAVE_TLS
		if ( l[ i ]->sl_is_tls ) {
			struct berval bv;

			BER_BVSTR( &bv, "TLS" );
			attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
					&bv, NULL );
		}
#endif /* HAVE_TLS */
#ifdef LDAP_CONNECTIONLESS
		if ( l[ i ]->sl_is_udp ) {
			struct berval bv;

			BER_BVSTR( &bv, "UDP" );
			attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
					&bv, NULL );
		}
#endif /* HAVE_TLS */

		mp = monitor_entrypriv_create();
		if ( mp == NULL ) {
			return -1;
		}
		e->e_private = ( void * )mp;
		mp->mp_info = ms;
		mp->mp_flags = ms->mss_flags
			| MONITOR_F_SUB;

		if ( monitor_cache_add( mi, e ) ) {
			Debug( LDAP_DEBUG_ANY,
				"monitor_subsys_listener_init: "
				"unable to add entry \"cn=Listener %d,%s\"\n",
				i, ms->mss_ndn.bv_val, 0 );
			return( -1 );
		}

		*ep = e;
		ep = &mp->mp_next;
	}
	
	monitor_cache_release( mi, e_listener );

	return( 0 );
}
Пример #9
0
int
monitor_subsys_time_init(
	BackendDB		*be,
	monitor_subsys_t	*ms )
{
	monitor_info_t	*mi;
	
	Entry		*e, **ep, *e_time;
	monitor_entry_t	*mp;
	struct berval	bv, value;

	assert( be != NULL );

	ms->mss_update = monitor_subsys_time_update;

	mi = ( monitor_info_t * )be->be_private;

	if ( monitor_cache_get( mi,
			&ms->mss_ndn, &e_time ) ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to get entry \"%s\"\n",
			ms->mss_ndn.bv_val, 0, 0 );
		return( -1 );
	}

	mp = ( monitor_entry_t * )e_time->e_private;
	mp->mp_children = NULL;
	ep = &mp->mp_children;

	BER_BVSTR( &bv, "cn=Start" );
	e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
		mi->mi_oc_monitoredObject, NULL, NULL );
	if ( e == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to create entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
		&mi->mi_startTime, NULL );
	
	mp = monitor_entrypriv_create();
	if ( mp == NULL ) {
		return -1;
	}
	e->e_private = ( void * )mp;
	mp->mp_info = ms;
	mp->mp_flags = ms->mss_flags \
		| MONITOR_F_SUB | MONITOR_F_PERSISTENT;

	if ( monitor_cache_add( mi, e ) ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to add entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	
	*ep = e;
	ep = &mp->mp_next;

	/*
	 * Current
	 */
	BER_BVSTR( &bv, "cn=Current" );
	e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
		mi->mi_oc_monitoredObject, NULL, NULL );
	if ( e == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to create entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	attr_merge_normalize_one( e, mi->mi_ad_monitorTimestamp,
		&mi->mi_startTime, NULL );

	mp = monitor_entrypriv_create();
	if ( mp == NULL ) {
		return -1;
	}
	e->e_private = ( void * )mp;
	mp->mp_info = ms;
	mp->mp_flags = ms->mss_flags \
		| MONITOR_F_SUB | MONITOR_F_PERSISTENT;

	if ( monitor_cache_add( mi, e ) ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to add entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	
	*ep = e;
	ep = &mp->mp_next;

	/*
	 * Uptime
	 */
	BER_BVSTR( &bv, "cn=Uptime" );
	e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
		mi->mi_oc_monitoredObject, NULL, NULL );
	if ( e == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to create entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	BER_BVSTR( &value, "0" );
	attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
		&value, NULL );

	mp = monitor_entrypriv_create();
	if ( mp == NULL ) {
		return -1;
	}
	e->e_private = ( void * )mp;
	mp->mp_info = ms;
	mp->mp_flags = ms->mss_flags \
		| MONITOR_F_SUB | MONITOR_F_PERSISTENT;

	if ( monitor_cache_add( mi, e ) ) {
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_time_init: "
			"unable to add entry \"%s,%s\"\n",
			bv.bv_val, ms->mss_ndn.bv_val, 0 );
		return( -1 );
	}
	
	*ep = e;
	ep = &mp->mp_next;

	monitor_cache_release( mi, e_time );

	return( 0 );
}
Пример #10
0
int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
{
	Operation		*op = bsi->bsi_op;
	backsql_info		*bi = (backsql_info *)op->o_bd->be_private;
	int			i;
	int			rc;

	Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );

	assert( bsi->bsi_e != NULL );

	memset( bsi->bsi_e, 0, sizeof( Entry ) );

	if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
		Entry	*e;

		e = entry_dup( bi->sql_baseObject );
		if ( e == NULL ) {
			return LDAP_NO_MEMORY;
		}
			
		*bsi->bsi_e = *e;
		free( e );
		goto done;
	}

	ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
	ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );

	bsi->bsi_e->e_attrs = NULL;
	bsi->bsi_e->e_private = NULL;

	if ( eid->eid_oc == NULL ) {
		eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
			eid->eid_oc_id );
	}
	bsi->bsi_oc = eid->eid_oc;
	bsi->bsi_c_eid = eid;

#ifndef BACKSQL_ARBITRARY_KEY	
	/* FIXME: unused */
	bsi->bsi_e->e_id = eid->eid_id;
#endif /* ! BACKSQL_ARBITRARY_KEY */
 
	rc = attr_merge_normalize_one( bsi->bsi_e,
			slap_schema.si_ad_objectClass,
			&bsi->bsi_oc->bom_oc->soc_cname,
			bsi->bsi_op->o_tmpmemctx );
	if ( rc != LDAP_SUCCESS ) {
		backsql_entry_clean( op, bsi->bsi_e );
		return rc;
	}

	if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
	{
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"retrieving all attributes\n", 0, 0, 0 );
		avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
				bsi, 0, AVL_INORDER );

	} else {
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"custom attribute list\n", 0, 0, 0 );
		for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
			backsql_at_map_rec	**vat;
			AttributeName		*an = &bsi->bsi_attrs[ i ];
			int			j;

			/* if one of the attributes listed here is
			 * a subtype of another, it must be ignored,
			 * because subtypes are already dealt with
			 * by backsql_supad2at()
			 */
			for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
				/* skip self */
				if ( j == i ) {
					continue;
				}

				/* skip subtypes */
				if ( is_at_subtype( an->an_desc->ad_type,
							bsi->bsi_attrs[ j ].an_desc->ad_type ) )
				{
					goto next;
				}
			}

			rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
			if ( rc != 0 || vat == NULL ) {
				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
						"attribute \"%s\" is not defined "
						"for objectlass \"%s\"\n",
						an->an_name.bv_val, 
						BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
				continue;
			}

			for ( j = 0; vat[j]; j++ ) {
    				backsql_get_attr_vals( vat[j], bsi );
			}

			ch_free( vat );

next:;
		}
	}

	if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
		Attribute	*a_entryUUID,
				**ap;

		a_entryUUID = backsql_operational_entryUUID( bi, eid );
		if ( a_entryUUID != NULL ) {
			for ( ap = &bsi->bsi_e->e_attrs; 
					*ap; 
					ap = &(*ap)->a_next );

			*ap = a_entryUUID;
		}
	}

	if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
			|| an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs )
			|| an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
	{
		ObjectClass	*soc = NULL;

		if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
			Attribute	*a;
			const char	*text = NULL;
			char		textbuf[ 1024 ];
			size_t		textlen = sizeof( textbuf );
			struct berval	bv[ 2 ],
					*nvals;
			int		rc = LDAP_SUCCESS;

			a = attr_find( bsi->bsi_e->e_attrs,
					slap_schema.si_ad_objectClass );
			if ( a != NULL ) {
				nvals = a->a_nvals;

			} else {
				bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
				BER_BVZERO( &bv[ 1 ] );
				nvals = bv;
			}

			rc = structural_class( nvals, &soc, NULL, 
					&text, textbuf, textlen, op->o_tmpmemctx );
			if ( rc != LDAP_SUCCESS ) {
      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"structural_class() failed %d (%s)\n",
					bsi->bsi_e->e_name.bv_val,
					rc, text ? text : "" );
				backsql_entry_clean( op, bsi->bsi_e );
				return rc;
			}

			if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
				if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
					Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
						"computed structuralObjectClass %s "
						"does not match objectClass %s associated "
						"to entry\n",
						bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
						bsi->bsi_oc->bom_oc->soc_cname.bv_val );
					backsql_entry_clean( op, bsi->bsi_e );
					return rc;
				}

      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"computed structuralObjectClass %s "
					"is subclass of objectClass %s associated "
					"to entry\n",
					bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
					bsi->bsi_oc->bom_oc->soc_cname.bv_val );
			}

		} else {
			soc = bsi->bsi_oc->bom_oc;
		}

		rc = attr_merge_normalize_one( bsi->bsi_e,
				slap_schema.si_ad_structuralObjectClass,
				&soc->soc_cname,
				bsi->bsi_op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			backsql_entry_clean( op, bsi->bsi_e );
			return rc;
		}
	}

done:;
	Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );

	return LDAP_SUCCESS;
}
Пример #11
0
static int
entry_naming_check(
	Entry *e,
	int manage,
	int add_naming,
	const char** text,
	char *textbuf, size_t textlen )
{
	/* naming check */
	LDAPRDN		rdn = NULL;
	const char	*p = NULL;
	ber_len_t	cnt;
	int		rc = LDAP_SUCCESS;

	if ( BER_BVISEMPTY( &e->e_name )) {
		return LDAP_SUCCESS;
	}

	/*
	 * Get attribute type(s) and attribute value(s) of our RDN
	 */
	if ( ldap_bv2rdn( &e->e_name, &rdn, (char **)&p,
		LDAP_DN_FORMAT_LDAP ) )
	{
		*text = "unrecognized attribute type(s) in RDN";
		return LDAP_INVALID_DN_SYNTAX;
	}

	/* Check that each AVA of the RDN is present in the entry */
	/* FIXME: Should also check that each AVA lists a distinct type */
	for ( cnt = 0; rdn[cnt]; cnt++ ) {
		LDAPAVA *ava = rdn[cnt];
		AttributeDescription *desc = NULL;
		Attribute *attr;
		const char *errtext;
		int add = 0;

		if( ava->la_flags & LDAP_AVA_BINARY ) {
			snprintf( textbuf, textlen, 
				"value of naming attribute '%s' in unsupported BER form",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}

		rc = slap_bv2ad( &ava->la_attr, &desc, &errtext );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( textbuf, textlen, "%s (in RDN)", errtext );
			break;
		}

		if( desc->ad_type->sat_usage ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' is operational",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}
 
		if( desc->ad_type->sat_collective ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' is collective",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}

		if( !manage && desc->ad_type->sat_obsolete ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' is obsolete",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}

		if( !desc->ad_type->sat_equality ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' has no equality matching rule",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}

		if( !desc->ad_type->sat_equality->smr_match ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' has unsupported equality matching rule",
				ava->la_attr.bv_val );
			rc = LDAP_NAMING_VIOLATION;
			break;
		}

		/* find the naming attribute */
		attr = attr_find( e->e_attrs, desc );
		if ( attr == NULL ) {
			snprintf( textbuf, textlen, 
				"naming attribute '%s' is not present in entry",
				ava->la_attr.bv_val );
			if ( add_naming ) {
				add = 1;

			} else {
				rc = LDAP_NAMING_VIOLATION;
			}

		} else {
			rc = attr_valfind( attr, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX|
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
				&ava->la_value, NULL, NULL );

			if ( rc != 0 ) {
				switch( rc ) {
				case LDAP_INAPPROPRIATE_MATCHING:
					snprintf( textbuf, textlen, 
						"inappropriate matching for naming attribute '%s'",
						ava->la_attr.bv_val );
					break;
				case LDAP_INVALID_SYNTAX:
					snprintf( textbuf, textlen, 
						"value of naming attribute '%s' is invalid",
						ava->la_attr.bv_val );
					break;
				case LDAP_NO_SUCH_ATTRIBUTE:
					if ( add_naming ) {
						if ( is_at_single_value( desc->ad_type ) ) {
							snprintf( textbuf, textlen, 
								"value of single-valued naming attribute '%s' conflicts with value present in entry",
								ava->la_attr.bv_val );

						} else {
							add = 1;
							rc = LDAP_SUCCESS;
						}

					} else {
						snprintf( textbuf, textlen, 
							"value of naming attribute '%s' is not present in entry",
							ava->la_attr.bv_val );
					}
					break;
				default:
					snprintf( textbuf, textlen, 
						"naming attribute '%s' is inappropriate",
						ava->la_attr.bv_val );
				}

				if ( !add ) {
					rc = LDAP_NAMING_VIOLATION;
				}
			}
		}

		if ( add ) {
			attr_merge_normalize_one( e, desc, &ava->la_value, NULL );

		} else if ( rc != LDAP_SUCCESS ) {
			break;
		}
	}

	ldap_rdnfree( rdn );
	return rc;
}
Пример #12
0
/*
 * call from within ldap_back_db_open()
 */
int
ldap_back_monitor_db_open( BackendDB *be )
{
	ldapinfo_t		*li = (ldapinfo_t *) be->be_private;
	char			buf[ BACKMONITOR_BUFSIZE ];
	Entry			*e = NULL;
	monitor_callback_t	*cb = NULL;
	struct berval		suffix, *filter, *base;
	char			*ptr;
	time_t			now;
	char			timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	struct berval 		timestamp;
	int			rc = 0;
	BackendInfo		*mi;
	monitor_extra_t		*mbe;

	if ( !SLAP_DBMONITORING( be ) ) {
		return 0;
	}

	/* check if monitor is configured and usable */
	mi = backend_info( "monitor" );
	if ( !mi || !mi->bi_extra ) {
		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
		return 0;
 	}
 	mbe = mi->bi_extra;

	/* don't bother if monitor is not configured */
	if ( !mbe->is_configured() ) {
		static int warning = 0;

		if ( warning++ == 0 ) {
			Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: "
				"monitoring disabled; "
				"configure monitor database to enable\n",
				0, 0, 0 );
		}

		return 0;
	}

	/* set up the fake subsystem that is used to create
	 * the volatile connection entries */
	li->li_monitor_info.lmi_mss.mss_name = "back-ldap";
	li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH;
	li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create;

	li->li_monitor_info.lmi_li = li;
	li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE;
	base = &li->li_monitor_info.lmi_base;
	BER_BVSTR( base, "cn=databases,cn=monitor" );
	filter = &li->li_monitor_info.lmi_filter;
	BER_BVZERO( filter );

	suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
	if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
		suffix = be->be_nsuffix[ 0 ];

	} else {
		ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
	}
	
	filter->bv_len = STRLENOF( "(&" )
		+ li->li_monitor_info.lmi_more_filter.bv_len
		+ STRLENOF( "(monitoredInfo=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( ")(!(monitorOverlay=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( "))(namingContexts:distinguishedNameMatch:=" )
		+ suffix.bv_len + STRLENOF( "))" );
	ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
	ptr = lutil_strcopy( ptr, "(&" );
	ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val,
		li->li_monitor_info.lmi_more_filter.bv_len );
	ptr = lutil_strcopy( ptr, "(monitoredInfo=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" );
	ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
	ptr = lutil_strcopy( ptr, "))" );
	ptr[ 0 ] = '\0';
	assert( ptr == &filter->bv_val[ filter->bv_len ] );

	if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
		ch_free( suffix.bv_val );
	}

	now = slap_get_time();
	timestamp.bv_val = timebuf;
	timestamp.bv_len = sizeof( timebuf );
	slap_timestamp( &now, &timestamp );

	/* caller (e.g. an overlay based on back-ldap) may want to use
	 * a different RDN... */
	if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) {
		ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn );
	}

	ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' );
	assert( ptr != NULL );
	ptr[ 0 ] = '\0';
	ptr++;

	snprintf( buf, sizeof( buf ),
		"dn: %s=%s\n"
		"objectClass: monitorContainer\n"
		"%s: %s\n"
		"creatorsName: %s\n"
		"createTimestamp: %s\n"
		"modifiersName: %s\n"
		"modifyTimestamp: %s\n",
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val );
	e = str2entry( buf );
	if ( e == NULL ) {
		rc = -1;
		goto cleanup;
	}

	ptr[ -1 ] = '=';

	/* add labeledURI and special, modifiable URI value */
	if ( li->li_uri != NULL ) {
		struct berval	bv;
		LDAPURLDesc	*ludlist = NULL;
		int		rc;

		rc = ldap_url_parselist_ext( &ludlist,
			li->li_uri, NULL,
			LDAP_PVT_URL_PARSE_NOEMPTY_HOST
				| LDAP_PVT_URL_PARSE_DEF_PORT );
		if ( rc != LDAP_URL_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"ldap_back_monitor_db_open: "
				"unable to parse URI list (ignored)\n",
				0, 0, 0 );
		} else {
			for ( ; ludlist != NULL; ) {
				LDAPURLDesc	*next = ludlist->lud_next;

				bv.bv_val = ldap_url_desc2str( ludlist );
				assert( bv.bv_val != NULL );
				ldap_free_urldesc( ludlist );
				bv.bv_len = strlen( bv.bv_val );
				attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI,
					&bv, NULL );
				ch_free( bv.bv_val );

				ludlist = next;
			}
		}
		
		ber_str2bv( li->li_uri, 0, 0, &bv );
		attr_merge_normalize_one( e, ad_olmDbURIList,
			&bv, NULL );
	}

	ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname );

	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
	cb->mc_update = ldap_back_monitor_update;
	cb->mc_modify = ldap_back_monitor_modify;
	cb->mc_free = ldap_back_monitor_free;
	cb->mc_private = (void *)li;

	rc = mbe->register_entry_parent( e, cb,
		(monitor_subsys_t *)&li->li_monitor_info,
		MONITOR_F_VOLATILE_CH,
		base, LDAP_SCOPE_SUBORDINATE, filter );

cleanup:;
	if ( rc != 0 ) {
		if ( cb != NULL ) {
			ch_free( cb );
			cb = NULL;
		}

		if ( e != NULL ) {
			entry_free( e );
			e = NULL;
		}

		if ( !BER_BVISNULL( filter ) ) {
			ch_free( filter->bv_val );
			BER_BVZERO( filter );
		}
	}

	/* store for cleanup */
	li->li_monitor_info.lmi_cb = (void *)cb;

	if ( e != NULL ) {
		entry_free( e );
	}

	return rc;
}
Пример #13
0
static int
ldap_back_monitor_modify(
	Operation	*op,
	SlapReply	*rs,
	Entry		*e,
	void		*priv )
{
	ldapinfo_t		*li = (ldapinfo_t *) priv;
	
	Attribute		*save_attrs = NULL;
	Modifications		*ml,
				*ml_olmDbURIList = NULL;
	struct berval		ul = BER_BVNULL;
	int			got = 0;

	for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
		if ( ml->sml_desc == ad_olmDbURIList ) {
			if ( ml_olmDbURIList != NULL ) {
				rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
				rs->sr_text = "conflicting modifications";
				goto done;
			}

			if ( ml->sml_op != LDAP_MOD_REPLACE ) {
				rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
				rs->sr_text = "modification not allowed";
				goto done;
			}

			ml_olmDbURIList = ml;
			got++;
			continue;
		}
	}

	if ( got == 0 ) {
		return SLAP_CB_CONTINUE;
	}

	save_attrs = attrs_dup( e->e_attrs );

	if ( ml_olmDbURIList != NULL ) {
		Attribute	*a = NULL;
		LDAPURLDesc	*ludlist = NULL;
		int		rc;

		ml = ml_olmDbURIList;
		assert( ml->sml_nvalues != NULL );

		if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) {
			rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
			rs->sr_text = "no value provided";
			goto done;
		}

		if ( !BER_BVISNULL( &ml->sml_nvalues[ 1 ] ) ) {
			rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
			rs->sr_text = "multiple values provided";
			goto done;
		}

		rc = ldap_url_parselist_ext( &ludlist,
			ml->sml_nvalues[ 0 ].bv_val, NULL,
			LDAP_PVT_URL_PARSE_NOEMPTY_HOST
				| LDAP_PVT_URL_PARSE_DEF_PORT );
		if ( rc != LDAP_URL_SUCCESS ) {
			rs->sr_err = LDAP_INVALID_SYNTAX;
			rs->sr_text = "unable to parse URI list";
			goto done;
		}

		ul.bv_val = ldap_url_list2urls( ludlist );
		ldap_free_urllist( ludlist );
		if ( ul.bv_val == NULL ) {
			rs->sr_err = LDAP_OTHER;
			goto done;
		}
		ul.bv_len = strlen( ul.bv_val );
		
		a = attr_find( e->e_attrs, ad_olmDbURIList );
		if ( a != NULL ) {
			if ( a->a_nvals == a->a_vals ) {
				a->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
			}

			ber_bvreplace( &a->a_vals[ 0 ], &ul );
			ber_bvreplace( &a->a_nvals[ 0 ], &ul );

		} else {
			attr_merge_normalize_one( e, ad_olmDbURIList, &ul, NULL );
		}
	}

	/* apply changes */
	if ( !BER_BVISNULL( &ul ) ) {
		ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
		if ( li->li_uri ) {
			ch_free( li->li_uri );
		}
		li->li_uri = ul.bv_val;
		ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );

		BER_BVZERO( &ul );
	}

done:;
	if ( !BER_BVISNULL( &ul ) ) {
		ldap_memfree( ul.bv_val );
	}

	if ( rs->sr_err == LDAP_SUCCESS ) {
		attrs_free( save_attrs );
		return SLAP_CB_CONTINUE;
	}

	attrs_free( e->e_attrs );
	e->e_attrs = save_attrs;

	return rs->sr_err;
}
Пример #14
0
int
slapadd( int argc, char **argv )
{
	char *buf = NULL;
	const char *text;
	char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
	size_t textlen = sizeof textbuf;
	const char *progname = "slapadd";

	struct berval csn;
	struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ];
	unsigned long sid;
	struct berval bvtext;
	Attribute *attr;
	Entry *ctxcsn_e;
	ID	ctxcsn_id, id;
	OperationBuffer opbuf;
	Operation *op;

	int match;
	int checkvals;
	int lineno, nextline;
	int lmax;
	int rc = EXIT_SUCCESS;
	int manage = 0;	

	/* default "000" */
	csnsid = 0;

	slap_tool_init( progname, SLAPADD, argc, argv );

	memset( &opbuf, 0, sizeof(opbuf) );
	op = &opbuf.ob_op;
	op->o_hdr = &opbuf.ob_hdr;

	if( !be->be_entry_open ||
		!be->be_entry_close ||
		!be->be_entry_put ||
		(update_ctxcsn &&
		 (!be->be_dn2id_get ||
		  !be->be_entry_get ||
		  !be->be_entry_modify)) )
	{
		fprintf( stderr, "%s: database doesn't support necessary operations.\n",
			progname );
		if ( dryrun ) {
			fprintf( stderr, "\t(dry) continuing...\n" );

		} else {
			exit( EXIT_FAILURE );
		}
	}

	checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1;

	lmax = 0;
	nextline = 0;

	/* enforce schema checking unless not disabled */
	if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
		SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
	}

	if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
		fprintf( stderr, "%s: could not open database.\n",
			progname );
		exit( EXIT_FAILURE );
	}

	if ( update_ctxcsn ) {
		maxcsn[ 0 ].bv_val = maxcsnbuf;
		for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
			maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE;
			maxcsn[ sid ].bv_len = 0;
		}
	}

	/* nextline is the line number of the end of the current entry */
	for( lineno=1; ldif_read_record( ldiffp, &nextline, &buf, &lmax );
		lineno=nextline+1 ) {
		Entry *e;

		if ( lineno < jumpline )
			continue;

		e = str2entry2( buf, checkvals );

		/*
		 * Initialize text buffer
		 */
		bvtext.bv_len = textlen;
		bvtext.bv_val = textbuf;
		bvtext.bv_val[0] = '\0';

		if( e == NULL ) {
			fprintf( stderr, "%s: could not parse entry (line=%d)\n",
				progname, lineno );
			rc = EXIT_FAILURE;
			if( continuemode ) continue;
			break;
		}

		/* make sure the DN is not empty */
		if( BER_BVISEMPTY( &e->e_nname ) &&
			!BER_BVISEMPTY( be->be_nsuffix )) {
			fprintf( stderr, "%s: empty dn=\"%s\" (line=%d)\n",
				progname, e->e_dn, lineno );
			rc = EXIT_FAILURE;
			entry_free( e );
			if( continuemode ) continue;
			break;
		}

		/* check backend */
		if( select_backend( &e->e_nname, nosubordinates )
			!= be )
		{
			fprintf( stderr, "%s: line %d: "
				"database (%s) not configured to hold \"%s\"\n",
				progname, lineno,
				be ? be->be_suffix[0].bv_val : "<none>",
				e->e_dn );
			fprintf( stderr, "%s: line %d: "
				"database (%s) not configured to hold \"%s\"\n",
				progname, lineno,
				be ? be->be_nsuffix[0].bv_val : "<none>",
				e->e_ndn );
			rc = EXIT_FAILURE;
			entry_free( e );
			if( continuemode ) continue;
			break;
		}

		{
			Attribute *oc = attr_find( e->e_attrs,
				slap_schema.si_ad_objectClass );

			if( oc == NULL ) {
				fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n",
					progname, e->e_dn, lineno,
					"no objectClass attribute");
				rc = EXIT_FAILURE;
				entry_free( e );
				if( continuemode ) continue;
				break;
			}

			/* check schema */
			op->o_bd = be;

			if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
				rc = entry_schema_check( op, e, NULL, manage, 1,
					&text, textbuf, textlen );

				if( rc != LDAP_SUCCESS ) {
					fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n",
						progname, e->e_dn, lineno, rc, text );
					rc = EXIT_FAILURE;
					entry_free( e );
					if( continuemode ) continue;
					break;
				}
				textbuf[ 0 ] = '\0';
			}
		}

		if ( SLAP_LASTMOD(be) ) {
			time_t now = slap_get_time();
			char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
			struct berval vals[ 2 ];

			struct berval name, timestamp;

			struct berval nvals[ 2 ];
			struct berval nname;
			char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];

			vals[1].bv_len = 0;
			vals[1].bv_val = NULL;

			nvals[1].bv_len = 0;
			nvals[1].bv_val = NULL;

			csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 );
			csn.bv_val = csnbuf;

			timestamp.bv_val = timebuf;
			timestamp.bv_len = sizeof(timebuf);

			slap_timestamp( &now, &timestamp );

			if ( BER_BVISEMPTY( &be->be_rootndn ) ) {
				BER_BVSTR( &name, SLAPD_ANONYMOUS );
				nname = name;
			} else {
				name = be->be_rootdn;
				nname = be->be_rootndn;
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )
				== NULL )
			{
				vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
				vals[0].bv_val = uuidbuf;
				attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, vals, NULL );
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName )
				== NULL )
			{
				vals[0] = name;
				nvals[0] = nname;
				attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals );
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp )
				== NULL )
			{
				vals[0] = timestamp;
				attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL );
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN )
				== NULL )
			{
				vals[0] = csn;
				attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName )
				== NULL )
			{
				vals[0] = name;
				nvals[0] = nname;
				attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals );
			}

			if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp )
				== NULL )
			{
				vals[0] = timestamp;
				attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL );
			}

			if ( update_ctxcsn ) {
				int rc_sid;

				attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
				assert( attr != NULL );

				rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] );
				if ( rc_sid < 0 ) {
					Debug( LDAP_DEBUG_ANY, "%s: could not "
						"extract SID from entryCSN=%s\n",
						progname, attr->a_nvals[ 0 ].bv_val, 0 );

				} else {
					assert( rc_sid <= SLAP_SYNC_SID_MAX );

					sid = (unsigned)rc_sid;
					if ( maxcsn[ sid ].bv_len != 0 ) {
						match = 0;
						value_match( &match, slap_schema.si_ad_entryCSN,
							slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
							SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
							&maxcsn[ sid ], &attr->a_nvals[0], &text );
					} else {
						match = -1;
					}
					if ( match < 0 ) {
						strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val );
						maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len;
					}
				}
			}
		}

		if ( !dryrun ) {
			id = be->be_entry_put( be, e, &bvtext );
			if( id == NOID ) {
				fprintf( stderr, "%s: could not add entry dn=\"%s\" "
								 "(line=%d): %s\n", progname, e->e_dn,
								 lineno, bvtext.bv_val );
				rc = EXIT_FAILURE;
				entry_free( e );
				if( continuemode ) continue;
				break;
			}
			if ( verbose )
				fprintf( stderr, "added: \"%s\" (%08lx)\n",
					e->e_dn, (long) id );
		} else {
			if ( verbose )
				fprintf( stderr, "added: \"%s\"\n",
					e->e_dn );
		}

		entry_free( e );
	}

	bvtext.bv_len = textlen;
	bvtext.bv_val = textbuf;
	bvtext.bv_val[0] = '\0';

	if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
		ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
		if ( ctxcsn_id == NOID ) {
			fprintf( stderr, "%s: context entry is missing\n", progname );
			rc = EXIT_FAILURE;
		} else {
			ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
			if ( ctxcsn_e != NULL ) {
				Entry *e = entry_dup( ctxcsn_e );
				int change;
				attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
				if ( attr ) {
					int		i;

					change = 0;

					for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) {
						int rc_sid;

						rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] );
						if ( rc_sid < 0 ) {
							Debug( LDAP_DEBUG_ANY,
								"%s: unable to extract SID "
								"from #%d contextCSN=%s\n",
								progname, i,
								attr->a_nvals[ i ].bv_val );
							continue;
						}

						assert( rc_sid <= SLAP_SYNC_SID_MAX );

						sid = (unsigned)rc_sid;

						if ( maxcsn[ sid ].bv_len == 0 ) {
							match = -1;

						} else {
							value_match( &match, slap_schema.si_ad_entryCSN,
								slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
								SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
								&maxcsn[ sid ], &attr->a_nvals[i], &text );
						}

						if ( match > 0 ) {
							change = 1;
						} else {
							AC_MEMCPY( maxcsn[ sid ].bv_val,
								attr->a_nvals[ i ].bv_val,
								attr->a_nvals[ i ].bv_len );
							maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0';
							maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len;
						}
					}

					if ( change ) {
						if ( attr->a_nvals != attr->a_vals ) {
							ber_bvarray_free( attr->a_nvals );
						}
						attr->a_nvals = NULL;
						ber_bvarray_free( attr->a_vals );
						attr->a_vals = NULL;
						attr->a_numvals = 0;
					}
				} else {
					change = 1;
				}

				if ( change ) {
					for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
						if ( maxcsn[ sid ].bv_len ) {
							attr_merge_one( e, slap_schema.si_ad_contextCSN,
								&maxcsn[ sid], NULL );
						}
					}

					ctxcsn_id = be->be_entry_modify( be, e, &bvtext );
					if( ctxcsn_id == NOID ) {
						fprintf( stderr, "%s: could not modify ctxcsn\n",
							progname);
						rc = EXIT_FAILURE;
					} else if ( verbose ) {
						fprintf( stderr, "modified: \"%s\" (%08lx)\n",
							e->e_dn, (long) ctxcsn_id );
					}
				}
				entry_free( e );
			}
		} 
	}

	ch_free( buf );

	if ( !dryrun ) {
		if( be->be_entry_close( be ) ) {
			rc = EXIT_FAILURE;
		}

		if( be->be_sync ) {
			be->be_sync( be );
		}
	}

	slap_tool_destroy();

	return rc;
}