Esempio n. 1
0
static int
delete_values( Operation *op, Entry *e, Modification *mod, int *newlevel )
{
	int             i, j, k, found, rc, nl = 0;
	Attribute       *a;
	MatchingRule 	*mr = mod->sm_desc->ad_type->sat_equality;

	/* delete the entire attribute */
	if ( mod->sm_values == NULL ) {
		int rc = attr_delete( &e->e_attrs, mod->sm_desc );

		if ( rc ) {
			rc = LDAP_NO_SUCH_ATTRIBUTE;

		} else {
			*newlevel = 0;
			rc = LDAP_SUCCESS;
		}
		return rc;
	}

	rc = check_constraints( mod, &nl );
	if ( rc != LDAP_SUCCESS ) {
		return rc;
	}

	*newlevel &= ~nl;

	if ( mr == NULL || !mr->smr_match ) {
		/* disallow specific attributes from being deleted if
		 * no equality rule */
		return LDAP_INAPPROPRIATE_MATCHING;
	}

	/* delete specific values - find the attribute first */
	if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
		return( LDAP_NO_SUCH_ATTRIBUTE );
	}

	/* find each value to delete */
	for ( i = 0; !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) {
		int rc;
		const char *text = NULL;

		struct berval asserted;

		rc = asserted_value_validate_normalize(
				mod->sm_desc, mr, SLAP_MR_EQUALITY,
				&mod->sm_values[ i ], &asserted, &text,
				op->o_tmpmemctx );

		if( rc != LDAP_SUCCESS ) return rc;

		found = 0;
		for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
			int match;
			int rc = value_match( &match, mod->sm_desc, mr,
				0, &a->a_nvals[ j ], &asserted, &text );

			if( rc == LDAP_SUCCESS && match != 0 ) {
				continue;
			}

			/* found a matching value */
			found = 1;

			/* delete it */
			if ( a->a_nvals != a->a_vals ) {
				free( a->a_nvals[ j ].bv_val );
				for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) {
					a->a_nvals[ k - 1 ] = a->a_nvals[ k ];
				}
				BER_BVZERO( &a->a_nvals[ k - 1 ] );
			}

			free( a->a_vals[ j ].bv_val );
			for ( k = j + 1; !BER_BVISNULL( &a->a_vals[ k ] ); k++ ) {
				a->a_vals[ k - 1 ] = a->a_vals[ k ];
			}
			BER_BVZERO( &a->a_vals[ k - 1 ] );
			a->a_numvals--;

			break;
		}

		free( asserted.bv_val );

		/* looked through them all w/o finding it */
		if ( ! found ) {
			return LDAP_NO_SUCH_ATTRIBUTE;
		}
	}

	/* if no values remain, delete the entire attribute */
	if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
		assert( a->a_numvals == 0 );

		/* should already be zero */
		*newlevel = 0;
		
		if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
			return LDAP_NO_SUCH_ATTRIBUTE;
		}
	}

	return LDAP_SUCCESS;
}
Esempio n. 2
0
/* This is a copy from slapd/mods.c, but with compaction tweaked
 * to swap values from the tail into deleted slots, to reduce the
 * overall update traffic.
 */
static int
ndb_modify_delete(
	Entry	*e,
	Modification	*mod,
	int	permissive,
	const char	**text,
	char *textbuf, size_t textlen,
	int *idx )
{
	Attribute	*a;
	MatchingRule 	*mr = mod->sm_desc->ad_type->sat_equality;
	struct berval *cvals;
	int		*id2 = NULL;
	int		i, j, rc = 0, num;
	unsigned flags;
	char		dummy = '\0';

	/* For ordered vals, we have no choice but to preserve order */
	if ( mod->sm_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )
		return modify_delete_vindex( e, mod, permissive, text,
			textbuf, textlen, idx );

	/*
	 * If permissive is set, then the non-existence of an 
	 * attribute is not treated as an error.
	 */

	/* delete the entire attribute */
	if ( mod->sm_values == NULL ) {
		rc = attr_delete( &e->e_attrs, mod->sm_desc );

		if( permissive ) {
			rc = LDAP_SUCCESS;
		} else if( rc != LDAP_SUCCESS ) {
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such attribute",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
		return rc;
	}

	/* FIXME: Catch old code that doesn't set sm_numvals.
	 */
	if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
		for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
		assert( mod->sm_numvals == i );
	}
	if ( !idx ) {
		id2 = (int *)ch_malloc( mod->sm_numvals * sizeof( int ));
		idx = id2;
	}

	if( mr == NULL || !mr->smr_match ) {
		/* disallow specific attributes from being deleted if
			no equality rule */
		*text = textbuf;
		snprintf( textbuf, textlen,
			"modify/delete: %s: no equality matching rule",
			mod->sm_desc->ad_cname.bv_val );
		rc = LDAP_INAPPROPRIATE_MATCHING;
		goto return_result;
	}

	/* delete specific values - find the attribute first */
	if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
		if( permissive ) {
			rc = LDAP_SUCCESS;
			goto return_result;
		}
		*text = textbuf;
		snprintf( textbuf, textlen,
			"modify/delete: %s: no such attribute",
			mod->sm_desc->ad_cname.bv_val );
		rc = LDAP_NO_SUCH_ATTRIBUTE;
		goto return_result;
	}

	if ( mod->sm_nvalues ) {
		flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
			| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
			| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
		cvals = mod->sm_nvalues;
	} else {
		flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
		cvals = mod->sm_values;
	}

	/* Locate values to delete */
	for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
		unsigned sort;
		rc = attr_valfind( a, flags, &cvals[i], &sort, NULL );
		if ( rc == LDAP_SUCCESS ) {
			idx[i] = sort;
		} else if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
			if ( permissive ) {
				idx[i] = -1;
				continue;
			}
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such value",
				mod->sm_desc->ad_cname.bv_val );
			goto return_result;
		} else {
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: matching rule failed",
				mod->sm_desc->ad_cname.bv_val );
			goto return_result;
		}
	}

	num = a->a_numvals;

	/* Delete the values */
	for ( i = 0; i < mod->sm_numvals; i++ ) {
		/* Skip permissive values that weren't found */
		if ( idx[i] < 0 )
			continue;
		/* Skip duplicate delete specs */
		if ( a->a_vals[idx[i]].bv_val == &dummy )
			continue;
		/* delete value and mark it as gone */
		free( a->a_vals[idx[i]].bv_val );
		a->a_vals[idx[i]].bv_val = &dummy;
		if( a->a_nvals != a->a_vals ) {
			free( a->a_nvals[idx[i]].bv_val );
			a->a_nvals[idx[i]].bv_val = &dummy;
		}
		a->a_numvals--;
	}

	/* compact array */
	for ( i=0; i<num; i++ ) {
		if ( a->a_vals[i].bv_val != &dummy )
			continue;
		for ( --num; num > i && a->a_vals[num].bv_val == &dummy; num-- )
			;
		a->a_vals[i] = a->a_vals[num];
		if ( a->a_nvals != a->a_vals )
			a->a_nvals[i] = a->a_nvals[num];
	}

	BER_BVZERO( &a->a_vals[num] );
	if (a->a_nvals != a->a_vals) {
		BER_BVZERO( &a->a_nvals[num] );
	}

	/* if no values remain, delete the entire attribute */
	if ( !a->a_numvals ) {
		if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
			/* Can never happen */
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such attribute",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
	}
return_result:
	if ( id2 )
		ch_free( id2 );
	return rc;
}
Esempio n. 3
0
static int 
monitor_subsys_log_modify( 
	Operation		*op,
	SlapReply		*rs,
	Entry 			*e )
{
	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
	int		rc = LDAP_OTHER;
	int		newlevel = ldap_syslog;
	Attribute	*save_attrs;
	Modifications	*modlist = op->orm_modlist;
	Modifications	*ml;

	ldap_pvt_thread_mutex_lock( &monitor_log_mutex );

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

	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
		Modification	*mod = &ml->sml_mod;

		/*
		 * accept all operational attributes;
		 * this includes modifiersName and modifyTimestamp
		 * if lastmod is "on"
		 */
		if ( is_at_operational( mod->sm_desc->ad_type ) ) {
			( void ) attr_delete( &e->e_attrs, mod->sm_desc );
			rc = rs->sr_err = attr_merge( e, mod->sm_desc,
					mod->sm_values, mod->sm_nvalues );
			if ( rc != LDAP_SUCCESS ) {
				break;
			}
			continue;

		/*
		 * only the "managedInfo" attribute can be modified
		 */
		} else if ( mod->sm_desc != mi->mi_ad_managedInfo ) {
			rc = rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			break;
		}

		switch ( mod->sm_op ) {
		case LDAP_MOD_ADD:
			rc = add_values( op, e, mod, &newlevel );
			break;
			
		case LDAP_MOD_DELETE:
			rc = delete_values( op, e, mod, &newlevel );
			break;

		case LDAP_MOD_REPLACE:
			rc = replace_values( op, e, mod, &newlevel );
			break;

		default:
			rc = LDAP_OTHER;
			break;
		}

		if ( rc != LDAP_SUCCESS ) {
			rs->sr_err = rc;
			break;
		}
	}

	/* set the new debug level */
	if ( rc == LDAP_SUCCESS ) {
		const char	*text;
		static char	textbuf[ BACKMONITOR_BUFSIZE ];

		/* check for abandon */
		if ( op->o_abandon ) {
			rc = rs->sr_err = SLAPD_ABANDON;

			goto cleanup;
		}

		/* check that the entry still obeys the schema */
		rc = entry_schema_check( op, e, save_attrs, 0, 0, NULL,
			&text, textbuf, sizeof( textbuf ) );
		if ( rc != LDAP_SUCCESS ) {
			rs->sr_err = rc;
			goto cleanup;
		}

		/*
		 * Do we need to protect this with a mutex?
		 */
		ldap_syslog = newlevel;

#if 0	/* debug rather than log */
		slap_debug = newlevel;
		lutil_set_debug_level( "slapd", slap_debug );
		ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
		ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
		ldif_debug = slap_debug;
#endif
	}

cleanup:;
	if ( rc == LDAP_SUCCESS ) {
		attrs_free( save_attrs );

	} else {
		attrs_free( e->e_attrs );
		e->e_attrs = save_attrs;
	}
	
	ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );

	if ( rc == LDAP_SUCCESS ) {
		rc = SLAP_CB_CONTINUE;
	}

	return rc;
}