예제 #1
0
static int
rdnval_op_rename( Operation *op, SlapReply *rs )
{
	Modifications *ml, **mlp;
	int numvals = 0;
	BerVarray vals = NULL, nvals = NULL;
	struct berval old;
	int rc;

	dnRdn( &op->o_req_dn, &old );
	if ( dn_match( &old, &op->orr_newrdn ) ) {
		dnRdn( &op->o_req_ndn, &old );
		if ( dn_match( &old, &op->orr_nnewrdn ) ) {
			return SLAP_CB_CONTINUE;
		}
	}

	rc = rdnval_rdn2vals( op, rs, &op->orr_newrdn, &op->orr_nnewrdn,
		&vals, &nvals, &numvals );
	if ( rc != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
	}

	ml = SLAP_CALLOC( sizeof( Modifications ), 1 );
	ml->sml_values = vals;
	ml->sml_nvalues = nvals;

	ml->sml_numvals = numvals;

	ml->sml_op = LDAP_MOD_REPLACE;
	ml->sml_flags = SLAP_MOD_INTERNAL;
	ml->sml_desc = ad_rdnValue;
	ml->sml_type = ad_rdnValue->ad_cname;

	for ( mlp = &op->orr_modlist; *mlp != NULL; mlp = &(*mlp)->sml_next )
		/* goto tail */ ;

	*mlp = ml;

	return SLAP_CB_CONTINUE;
}
예제 #2
0
static int
vernum_op_modify( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *) op->o_bd->bd_info;
	vernum_t	*vn = (vernum_t *)on->on_bi.bi_private;

	Modifications *ml, **mlp;
	struct berval val = BER_BVC( "1" );
	int rc;
	unsigned got = 0;

	for ( ml = op->orm_modlist; ml != NULL; ml = ml->sml_next ) {
		if ( ml->sml_desc == vn->vn_vernum ) {
			/* already present - leave it alone
			 * (or should we increment it anyway?) */
			return SLAP_CB_CONTINUE;
		}

		if ( ml->sml_desc == vn->vn_attr ) {
			got = 1;
		}
	}

	if ( !got ) {
		return SLAP_CB_CONTINUE;
	}

	for ( mlp = &op->orm_modlist; *mlp != NULL; mlp = &(*mlp)->sml_next )
		/* goto tail */ ;

	/* ITS#6561 */
#ifdef SLAP_MOD_ADD_IF_NOT_PRESENT
	/* the initial value is only added if the vernum attr is not present */
	ml = SLAP_CALLOC( sizeof( Modifications ), 1 );
	ml->sml_values = SLAP_CALLOC( sizeof( struct berval ) , 2 );
	value_add_one( &ml->sml_values, &val_init );
	ml->sml_nvalues = NULL;
	ml->sml_numvals = 1;
	ml->sml_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
	ml->sml_flags = SLAP_MOD_INTERNAL;
	ml->sml_desc = vn->vn_vernum;
	ml->sml_type = vn->vn_vernum->ad_cname;

	*mlp = ml;
	mlp = &ml->sml_next;
#endif /* SLAP_MOD_ADD_IF_NOT_PRESENT */

	/* this increments by 1 the vernum attr */
	ml = SLAP_CALLOC( sizeof( Modifications ), 1 );
	ml->sml_values = SLAP_CALLOC( sizeof( struct berval ) , 2 );
	value_add_one( &ml->sml_values, &val );
	ml->sml_nvalues = NULL;
	ml->sml_numvals = 1;
	ml->sml_op = LDAP_MOD_INCREMENT;
	ml->sml_flags = SLAP_MOD_INTERNAL;
	ml->sml_desc = vn->vn_vernum;
	ml->sml_type = vn->vn_vernum->ad_cname;

	*mlp = ml;

	return SLAP_CB_CONTINUE;
}
예제 #3
0
파일: vc.c 프로젝트: Joywar/openldap
static int
vc_exop(
	Operation	*op,
	SlapReply	*rs )
{
	int rc = LDAP_SUCCESS;
	ber_tag_t tag;
	ber_len_t len = -1;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	struct berval reqdata = BER_BVNULL;

	struct berval cookie = BER_BVNULL;
	struct berval bdn = BER_BVNULL;
	ber_tag_t authtag;
	struct berval cred = BER_BVNULL;
	struct berval ndn = BER_BVNULL;
	struct berval mechanism = BER_BVNULL;

	vc_conn_t *conn = NULL;
	vc_cb_t vc = { 0 };
	slap_callback sc = { 0 };
	SlapReply rs2 = { 0 };

	if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) {
		rs->sr_text = "empty request data field in VerifyCredentials exop";
		return LDAP_PROTOCOL_ERROR;
	}

	/* optimistic */
	rs->sr_err = LDAP_SUCCESS;

	ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx );

	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
	ber_init2( ber, &reqdata, 0 );

	tag = ber_scanf( ber, "{" /*}*/ );
	if ( tag != LBER_SEQUENCE ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) {
		/*
		 * cookie: the pointer to the connection
		 * of this operation
		 */

		ber_scanf( ber, "m", &cookie );
		if ( cookie.bv_len != sizeof(Connection *) ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
	}

	/* DN, authtag */
	tag = ber_scanf( ber, "mt", &bdn, &authtag );
	if ( tag == LBER_ERROR ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx );
	if ( rc != LDAP_SUCCESS ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	switch ( authtag ) {
	case LDAP_AUTH_SIMPLE:
		/* cookie only makes sense for SASL bind (so far) */
		if ( !BER_BVISNULL( &cookie ) ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		tag = ber_scanf( ber, "m", &cred );
		if ( tag == LBER_ERROR ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
		break;

	case LDAP_AUTH_SASL:
		tag = ber_scanf( ber, "{s" /*}*/ , &mechanism );
		if ( tag == LBER_ERROR || 
			BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) )
		{
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		tag = ber_peek_tag( ber, &len );
		if ( tag == LBER_OCTETSTRING ) {
			ber_scanf( ber, "m", &cred );
		}

		tag = ber_scanf( ber, /*{*/ "}" );
		break;

	default:
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	if ( !BER_BVISNULL( &cookie ) ) {
		vc_conn_t tmp = { 0 };

		AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len );
		ldap_pvt_thread_mutex_lock( &vc_mutex );
		conn = (vc_conn_t *)avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp );
		if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) {
			conn = NULL;
			ldap_pvt_thread_mutex_unlock( &vc_mutex );
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
		conn->refcnt++;
		ldap_pvt_thread_mutex_unlock( &vc_mutex );

	} else {
		void *thrctx;

		conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) );
		conn->refcnt = 1;

		thrctx = ldap_pvt_thread_pool_context();
		connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 );
		conn->op = &conn->opbuf.ob_op;
		snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ),
			"%s VERIFYCREDENTIALS", op->o_log_prefix );
	}

	conn->op->o_tag = LDAP_REQ_BIND;
	memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) );
	conn->op->o_req_dn = ndn;
	conn->op->o_req_ndn = ndn;
	conn->op->o_protocol = LDAP_VERSION3;
	conn->op->orb_method = authtag;
	conn->op->o_callback = ≻

	/* TODO: controls */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) {
		conn->op->o_ber = ber;
		rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
		if ( rc != LDAP_SUCCESS ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
	}

	tag = ber_skip_tag( ber, &len );
	if ( len || tag != LBER_DEFAULT ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	switch ( authtag ) {
	case LDAP_AUTH_SIMPLE:
		break;

	case LDAP_AUTH_SASL:
		conn->op->orb_mech = mechanism;
		break;
	}

	conn->op->orb_cred = cred;
	sc.sc_response = vc_cb;
	sc.sc_private = &vc;

	conn->op->o_bd = frontendDB;
	rs->sr_err = frontendDB->be_bind( conn->op, &rs2 );

	if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
		rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text,
			!BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL,
			NULL,
			vc.ctrls, &rs->sr_rspdata );

	} else {
		rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text,
			NULL,
			&conn->op->o_conn->c_dn,
			vc.ctrls, &rs->sr_rspdata );
	}

	if ( rc != 0 ) {
		rs->sr_err = LDAP_OTHER;
		goto done;
	}

	if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) &&
		conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val )
		ber_memfree( conn->op->o_conn->c_dn.bv_val );
	if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) )
		ber_memfree( conn->op->o_conn->c_ndn.bv_val );

done:;
	if ( conn ) {
		if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
			if ( conn->conn == NULL ) {
				conn->conn = conn;
				conn->refcnt--;
				ldap_pvt_thread_mutex_lock( &vc_mutex );
				rc = avl_insert( &vc_tree, (caddr_t)conn,
					vc_conn_cmp, vc_conn_dup );
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
				assert( rc == 0 );

			} else {
				ldap_pvt_thread_mutex_lock( &vc_mutex );
				conn->refcnt--;
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
			}

		} else {
			if ( conn->conn != NULL ) {
				vc_conn_t *tmp;

				ldap_pvt_thread_mutex_lock( &vc_mutex );
				tmp = avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp );
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
			}
			SLAP_FREE( conn );
		}
	}

	if ( vc.ctrls ) {
		ldap_controls_free( vc.ctrls );
		vc.ctrls = NULL;
	}

	if ( !BER_BVISNULL( &ndn ) ) {
		op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &ndn );
	}

	op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx );
	BER_BVZERO( &reqdata );

        return rs->sr_err;
}
예제 #4
0
int
modify_delete_values(
	Entry	*e,
	Modification	*mod,
	int	permissive,
	const char	**text,
	char *textbuf, size_t textlen
)
{
	int		i, j, k, rc = LDAP_SUCCESS;
	Attribute	*a;
	MatchingRule 	*mr = mod->sm_desc->ad_type->sat_equality;
	BerVarray	nvals = NULL;
	char		dummy = '\0';

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

	/* delete the entire attribute */
	if ( mod->sm_bvalues == 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;
	}

	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 );
		return LDAP_INAPPROPRIATE_MATCHING;
	}

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

	/* find each value to delete */
	for ( j = 0; a->a_vals[ j ].bv_val != NULL; j++ )
		/* count existing values */ ;

	nvals = (BerVarray)SLAP_CALLOC( j + 1, sizeof ( struct berval ) );
	if( nvals == NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, ERR,
			"modify_delete_values: SLAP_CALLOC failed", 0, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, 
			"modify_delete_values: SLAP_CALLOC failed", 0, 0, 0 );
#endif
				goto return_results;
	}

	/* normalize existing values */
	for ( j = 0; a->a_vals[ j ].bv_val != NULL; j++ ) {
		rc = value_normalize( a->a_desc, SLAP_MR_EQUALITY,
			&a->a_vals[ j ], &nvals[ j ], text );

		if ( rc != LDAP_SUCCESS ) {
			nvals[ j ].bv_val = NULL;
			goto return_results;
		}
	}

	for ( i = 0; mod->sm_bvalues[ i ].bv_val != NULL; i++ ) {
		struct	berval asserted;
		int	found = 0;

		/* normalize the value to be deleted */
		rc = value_normalize( mod->sm_desc, SLAP_MR_EQUALITY,
			&mod->sm_bvalues[ i ], &asserted, text );

		if( rc != LDAP_SUCCESS ) {
			goto return_results;
		}

		/* search it */
		for ( j = 0; nvals[ j ].bv_val != NULL; j++ ) {
			int match;

			if ( nvals[ j ].bv_val == &dummy ) {
				continue;
			}

			rc = (*mr->smr_match)( &match,
				SLAP_MR_VALUE_SYNTAX_MATCH,
				a->a_desc->ad_type->sat_syntax,
				mr, &nvals[ j ], &asserted );

			if ( rc != LDAP_SUCCESS ) {
				free( asserted.bv_val );
				*text = textbuf;
				snprintf( textbuf, textlen,
					"%s: matching rule failed",
					mod->sm_desc->ad_cname.bv_val );
				goto return_results;
			}

			if ( match != 0 ) {
				continue;
			}

			found = 1;

			/* delete value and mark it as dummy */
			free( nvals[ j ].bv_val );
			nvals[ j ].bv_val = &dummy;

			break;
		}

		free( asserted.bv_val );

		if ( found == 0 ) {
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such value",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
			goto return_results;
		}
	}

	/* compact array skipping dummies */
	for ( k = 0, j = 0; nvals[ k ].bv_val != NULL; j++, k++ ) {

		/* delete and skip dummies */ ;
		for ( ; nvals[ k ].bv_val == &dummy; k++ ) {
			free( a->a_vals[ k ].bv_val );
		}

		if ( j != k ) {
			a->a_vals[ j ] = a->a_vals[ k ];
		}

		if ( a->a_vals[ k ].bv_val == NULL ) {
			break;
		}
	}
	a->a_vals[ j ].bv_val = NULL;

	assert( i == k - j );

	/* if no values remain, delete the entire attribute */
	if ( a->a_vals[0].bv_val == NULL ) {
		if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such attribute",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
	}

return_results:;
	if ( nvals ) {
		/* delete the remaining normalized values */
		for ( j = 0; nvals[ j ].bv_val != NULL; j++ ) {
			if ( nvals[ j ].bv_val != &dummy ) {
				ber_memfree( nvals[ j ].bv_val );
			}
		}
		ber_memfree( nvals );
	}

	return rc;
}
예제 #5
0
int
modify_check_duplicates(
	AttributeDescription	*ad,
	MatchingRule		*mr,
	BerVarray		vals,
	BerVarray		mods,
	int			permissive,
	const char	**text,
	char *textbuf, size_t textlen )
{
	int		i, j, numvals = 0, nummods,
			rc = LDAP_SUCCESS, matched;
	BerVarray	nvals = NULL, nmods = NULL;

	/*
	 * FIXME: better do the following
	 * 
	 *   - count the existing values
	 *   - count the new values
	 *   
	 *   - if the existing values are less than the new ones {
	 *       - normalize all the existing values
	 *       - for each new value {
	 *           - normalize
	 *           - check with existing
	 *           - cross-check with already normalized new vals
	 *       }
	 *   } else {
	 *       - for each new value {
	 *           - normalize
	 *           - cross-check with already normalized new vals
	 *       }
	 *       - for each existing value {
	 *           - normalize
	 *           - check with already normalized new values
	 *       }
	 *   }
	 *
	 * The first case is good when adding a lot of new values,
	 * and significantly at first import of values (e.g. adding
	 * a new group); the latter case seems to be quite important
	 * as well, because it is likely to be the most frequently
	 * used when administering the entry.  The current 
	 * implementation will always normalize all the existing
	 * values before checking.  If there's no duplicate, the
	 * performances should not change; they will in case of error.
	 */

	for ( nummods = 0; mods[ nummods ].bv_val != NULL; nummods++ )
		/* count new values */ ;

	if ( vals ) {
		for ( numvals = 0; vals[ numvals ].bv_val != NULL; numvals++ )
			/* count existing values */ ;

		if ( numvals < nummods ) {
			nvals = SLAP_CALLOC( numvals + 1, sizeof( struct berval ) );
			if( nvals == NULL ) {
#ifdef NEW_LOGGING
				LDAP_LOG( OPERATION, ERR,
					"modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
#else
				Debug( LDAP_DEBUG_ANY, 
					"modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
#endif
				goto return_results;
			}

			/* normalize the existing values first */
			for ( j = 0; vals[ j ].bv_val != NULL; j++ ) {
				rc = value_normalize( ad, SLAP_MR_EQUALITY,
					&vals[ j ], &nvals[ j ], text );

				/* existing attribute values must normalize */
				assert( rc == LDAP_SUCCESS );

				if ( rc != LDAP_SUCCESS ) {
					nvals[ j ].bv_val = NULL;
					goto return_results;
				}
			}
			nvals[ j ].bv_val = NULL;
		}
	}

	/*
	 * If the existing values are less than the new values,
	 * it is more convenient to normalize all the existing
	 * values and test each new value against them first,
	 * then to other already normalized values
	 */
	nmods = SLAP_CALLOC( nummods + 1, sizeof( struct berval ) );
	if ( nmods == NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, ERR,
			"modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, 
			"modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
#endif
		goto return_results;
	}

	for ( i = 0; mods[ i ].bv_val != NULL; i++ ) {
		rc = value_normalize( ad, SLAP_MR_EQUALITY,
			&mods[ i ], &nmods[ i ], text );

		if ( rc != LDAP_SUCCESS ) {
			nmods[ i ].bv_val = NULL;
			goto return_results;
		}

		if ( numvals > 0 && numvals < nummods ) {
			for ( matched = 0, j = 0; nvals[ j ].bv_val; j++ ) {
				int match;

				rc = (*mr->smr_match)( &match,
					SLAP_MR_VALUE_SYNTAX_MATCH,
					ad->ad_type->sat_syntax,
					mr, &nmods[ i ], &nvals[ j ] );
				if ( rc != LDAP_SUCCESS ) {
					nmods[ i + 1 ].bv_val = NULL;
					*text = textbuf;
					snprintf( textbuf, textlen,
						"%s: matching rule failed",
						ad->ad_cname.bv_val );
					goto return_results;
				}

				if ( match == 0 ) {
					if ( permissive ) {
						matched++;
						continue;
					}
					*text = textbuf;
					snprintf( textbuf, textlen,
						"%s: value #%d provided more than once",
						ad->ad_cname.bv_val, i );
					rc = LDAP_TYPE_OR_VALUE_EXISTS;
					nmods[ i + 1 ].bv_val = NULL;
					goto return_results;
				}
			}

			if ( permissive && matched == j ) {
				nmods[ i + 1 ].bv_val = NULL;
				rc = LDAP_TYPE_OR_VALUE_EXISTS;
				goto return_results;
			}
		}
	
		for ( matched = 0, j = 0; j < i; j++ ) {
			int match;

			rc = (*mr->smr_match)( &match,
				SLAP_MR_VALUE_SYNTAX_MATCH,
				ad->ad_type->sat_syntax,
				mr, &nmods[ i ], &nmods[ j ] );
			if ( rc != LDAP_SUCCESS ) {
				nmods[ i + 1 ].bv_val = NULL;
				*text = textbuf;
				snprintf( textbuf, textlen,
					"%s: matching rule failed",
					ad->ad_cname.bv_val );
				goto return_results;
			}

			if ( match == 0 ) {
				if ( permissive ) {
					matched++;
					continue;
				}
				*text = textbuf;
				snprintf( textbuf, textlen,
					"%s: value #%d provided more than once",
					ad->ad_cname.bv_val, j );
				rc = LDAP_TYPE_OR_VALUE_EXISTS;
				nmods[ i + 1 ].bv_val = NULL;
				goto return_results;
			}
		}

		if ( permissive && matched == j ) {
			nmods[ i + 1 ].bv_val = NULL;
			rc = LDAP_TYPE_OR_VALUE_EXISTS;
			goto return_results;
		}
	}
	nmods[ i ].bv_val = NULL;

	/*
	 * if new values are more than existing values, it is more
	 * convenient to normalize and check all new values first,
	 * then check each new value against existing values, which 
	 * can be normalized in place
	 */

	if ( numvals >= nummods ) {
		for ( j = 0; vals[ j ].bv_val; j++ ) {
			struct berval	asserted;

			rc = value_normalize( ad, SLAP_MR_EQUALITY,
				&vals[ j ], &asserted, text );

			if ( rc != LDAP_SUCCESS ) {
				goto return_results;
			}

			for ( matched = 0, i = 0; nmods[ i ].bv_val; i++ ) {
				int match;

				rc = (*mr->smr_match)( &match,
					SLAP_MR_VALUE_SYNTAX_MATCH,
					ad->ad_type->sat_syntax,
					mr, &nmods[ i ], &asserted );
				if ( rc != LDAP_SUCCESS ) {
					*text = textbuf;
					snprintf( textbuf, textlen,
						"%s: matching rule failed",
						ad->ad_cname.bv_val );
					free( asserted.bv_val );
					goto return_results;
				}

				if ( match == 0 ) {
					if ( permissive ) {
						matched++;
						continue;
					}
					*text = textbuf;
					snprintf( textbuf, textlen,
						"%s: value #%d provided more than once",
						ad->ad_cname.bv_val, j );
					rc = LDAP_TYPE_OR_VALUE_EXISTS;
					free( asserted.bv_val );
					goto return_results;
				}
			}
			free( asserted.bv_val );

			if ( permissive && matched == i ) {
				rc = LDAP_TYPE_OR_VALUE_EXISTS;
				goto return_results;
			}
		}
	}

return_results:;
	if ( nvals ) {
		ber_bvarray_free( nvals );
	}
	if ( nmods ) {
		ber_bvarray_free( nmods );
	}

	return rc;
}
예제 #6
0
파일: cloak.c 프로젝트: cptaffe/openldap
static int
cloak_cfgen( ConfigArgs *c )
{
	slap_overinst	*on = (slap_overinst *)c->bi;
	cloak_info_t	*ci = (cloak_info_t *)on->on_bi.bi_private;

	int		rc = 0, i;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch( c->type ) {
		case CLOAK_ATTR:
			for ( i = 0; ci; i++, ci = ci->ci_next ) {
				struct berval	bv;
				int len;

				assert( ci->ci_ad != NULL );

				if ( ci->ci_oc != NULL )
					len = snprintf( c->cr_msg, 
					sizeof( c->cr_msg ),
					SLAP_X_ORDERED_FMT "%s %s", i,
					ci->ci_ad->ad_cname.bv_val,
					ci->ci_oc->soc_cname.bv_val );
				else
					len = snprintf( c->cr_msg, 
					sizeof( c->cr_msg ),
					SLAP_X_ORDERED_FMT "%s", i,
					ci->ci_ad->ad_cname.bv_val );

				bv.bv_val = c->cr_msg;
				bv.bv_len = len;
				value_add_one( &c->rvalue_vals, &bv );
			}
			break;

		default:
			rc = 1;
			break;
		}

		return rc;

	} else if ( c->op == LDAP_MOD_DELETE ) {
		cloak_info_t	*ci_next;

		switch( c->type ) {
		case CLOAK_ATTR:
			for ( ci_next = ci, i = 0; 
			      ci_next, c->valx < 0 || i < c->valx; 
			      ci = ci_next, i++ ){

				ci_next = ci->ci_next;

				ch_free ( ci->ci_ad );
				if ( ci->ci_oc != NULL )
					ch_free ( ci->ci_oc );

				ch_free( ci );
			}
			ci = (cloak_info_t *)on->on_bi.bi_private;
			break;

		default:
			rc = 1;
			break;
		}

		return rc;
	}

	switch( c->type ) {
	case CLOAK_ATTR: {
		ObjectClass		*oc = NULL;
		AttributeDescription	*ad = NULL;
		const char		*text;
		cloak_info_t 	       **cip = NULL;
		cloak_info_t 	        *ci_next = NULL;

		if ( c->argc == 3 ) {
			oc = oc_find( c->argv[ 2 ] );
			if ( oc == NULL ) {
				snprintf( c->cr_msg, 
					  sizeof( c->cr_msg ), 
					  CLOAK_USAGE
					  "unable to find ObjectClass \"%s\"",
					  c->argv[ 2 ] );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				       c->log, c->cr_msg, 0 );
				return 1;
			}
		}

		rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), CLOAK_USAGE
				"unable to find AttributeDescription \"%s\"",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		for ( i = 0, cip = (cloak_info_t **)&on->on_bi.bi_private;
		      c->valx < 0 || i < c->valx, *cip;
		      i++, cip = &(*cip)->ci_next ) {
			if ( c->valx >= 0 && *cip == NULL ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					CLOAK_USAGE
					"invalid index {%d}\n",
					c->valx );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );
				return 1;
			}
			ci_next = *cip;
		}

		*cip = (cloak_info_t *)SLAP_CALLOC( 1, sizeof( cloak_info_t ) );
		(*cip)->ci_oc = oc;
		(*cip)->ci_ad = ad;
		(*cip)->ci_next = ci_next;

		rc = 0;
		break;
	}

	default:
		rc = 1;
		break;
	}

	return rc;
}
예제 #7
0
static int
rdnval_rdn2vals(
	Operation *op,
	SlapReply *rs,
	struct berval *dn,
	struct berval *ndn,
	BerVarray *valsp,
	BerVarray *nvalsp,
	int *numvalsp )
{
	LDAPRDN rdn = NULL, nrdn = NULL;
	int nAVA, i;

	assert( *valsp == NULL );
	assert( *nvalsp == NULL );

	*numvalsp = 0;

	if ( ldap_bv2rdn_x( dn, &rdn, (char **)&rs->sr_text,
		LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
	{
		Debug( LDAP_DEBUG_TRACE,
			"%s rdnval: can't figure out "
			"type(s)/value(s) of rdn DN=\"%s\"\n",
			op->o_log_prefix, dn->bv_val, 0 );
		rs->sr_err = LDAP_INVALID_DN_SYNTAX;
		rs->sr_text = "unknown type(s) used in RDN";

		goto done;
	}

	if ( ldap_bv2rdn_x( ndn, &nrdn,
		(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
	{
		Debug( LDAP_DEBUG_TRACE,
			"%s rdnval: can't figure out "
			"type(s)/value(s) of normalized rdn DN=\"%s\"\n",
			op->o_log_prefix, ndn->bv_val, 0 );
		rs->sr_err = LDAP_INVALID_DN_SYNTAX;
		rs->sr_text = "unknown type(s) used in RDN";

		goto done;
	}

	for ( nAVA = 0; rdn[ nAVA ]; nAVA++ )
		/* count'em */ ;

	/* NOTE: we assume rdn and nrdn contain the same AVAs! */

	*valsp = SLAP_CALLOC( sizeof( struct berval ), nAVA + 1 );
	*nvalsp = SLAP_CALLOC( sizeof( struct berval ), nAVA + 1 );

	/* Add new attribute values to the entry */
	for ( i = 0; rdn[ i ]; i++ ) {
		AttributeDescription	*desc = NULL;

		rs->sr_err = slap_bv2ad( &rdn[ i ]->la_attr,
			&desc, &rs->sr_text );

		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE,
				"%s rdnval: %s: %s\n",
				op->o_log_prefix,
				rs->sr_text, 
				rdn[ i ]->la_attr.bv_val );
			goto done;
		}

		if ( !rdnval_is_valid( desc, &rdn[ i ]->la_value ) ) {
			Debug( LDAP_DEBUG_TRACE,
				"%s rdnval: syntax of naming attribute '%s' "
				"not compatible with directoryString",
				op->o_log_prefix, rdn[ i ]->la_attr.bv_val, 0 );
			continue;
		}

		if ( value_find_ex( desc,
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
				*nvalsp,
				&nrdn[ i ]->la_value,
				op->o_tmpmemctx )
			== LDAP_NO_SUCH_ATTRIBUTE )
		{
			ber_dupbv( &(*valsp)[ *numvalsp ], &rdn[ i ]->la_value );
			ber_dupbv( &(*nvalsp)[ *numvalsp ], &nrdn[ i ]->la_value );

			(*numvalsp)++;
		}
	}

	if ( rdnval_unique_check( op, *valsp ) != LDAP_SUCCESS ) {
		rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
		rs->sr_text = "rdnValue not unique within siblings";
		goto done;
	}

done:;
	if ( rdn != NULL ) {
		ldap_rdnfree_x( rdn, op->o_tmpmemctx );
	}

	if ( nrdn != NULL ) {
		ldap_rdnfree_x( nrdn, op->o_tmpmemctx );
	}

	if ( rs->sr_err != LDAP_SUCCESS ) {
		if ( *valsp != NULL ) {
			ber_bvarray_free( *valsp );
			ber_bvarray_free( *nvalsp );
			*valsp = NULL;
			*nvalsp = NULL;
			*numvalsp = 0;
		}
	}

	return rs->sr_err;
}