예제 #1
0
파일: bprint.c 프로젝트: openldap/openldap
void
ber_dump(
	BerElement *ber,
	int inout )
{
	char buf[132];
	ber_len_t len;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( inout == 1 ) {
		len = ber_pvt_ber_remaining(ber);
	} else {
		len = ber_pvt_ber_write(ber);
	}

	sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n",
		ber->ber_buf,
		ber->ber_ptr,
		ber->ber_end,
		(long) len );

	(void) (*ber_pvt_log_print)( buf );

	ber_bprint( ber->ber_ptr, len );
}
예제 #2
0
파일: getattr.c 프로젝트: cptaffe/openldap
/* ARGSUSED */
int
ldap_get_attribute_ber( LDAP *ld, LDAPMessage *entry, BerElement *ber,
	BerValue *attr, BerVarray *vals )
{
	ber_tag_t tag;
	int rc = LDAP_SUCCESS;

	Debug( LDAP_DEBUG_TRACE, "ldap_get_attribute_ber\n", 0, 0, 0 );

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( entry != NULL );
	assert( ber != NULL );
	assert( attr != NULL );

	attr->bv_val = NULL;
	attr->bv_len = 0;

	if ( ber_pvt_ber_remaining( ber ) ) {
		ber_len_t siz = sizeof( BerValue );

		/* skip sequence, snarf attribute type */
		tag = ber_scanf( ber, vals ? "{mM}" : "{mx}", attr, vals,
			&siz, 0 ); 
		if( tag == LBER_ERROR ) {
			rc = ld->ld_errno = LDAP_DECODING_ERROR;
		}
	}

	return rc;
}
예제 #3
0
파일: getattr.c 프로젝트: cptaffe/openldap
/* ARGSUSED */
char *
ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber )
{
	ber_tag_t tag;
	char *attr;

	Debug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 );

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( entry != NULL );
	assert( ber != NULL );

	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
		return NULL;
	}

	/* skip sequence, snarf attribute type, skip values */
	tag = ber_scanf( ber, "{ax}", &attr ); 
	if( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return NULL;
	}

	return attr;
}
예제 #4
0
char *
first_attribute(BerElement *ber )
{
	int rc;
	ber_tag_t tag;
	ber_len_t len = 0;
	char *attr;
	
	/* 
	 * Skip past the sequence, dn, sequence of sequence leaving
	 * us at the first attribute.
	 */

	tag = ber_scanf( ber, "{xl{" /*}}*/, &len );
	if( tag == LBER_ERROR ) {
		
		ber_free( ber, 0 );
		return NULL;
	}

	/* set the length to avoid overrun */
	rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len );
	if( rc != LBER_OPT_SUCCESS ) {
		printf(">>Error<< Avoid overrun failed!\n");
		ber_free( ber, 0 );
		return NULL;
	}

	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
		assert( len == 0 );
		ber_free( ber, 0 );
		return NULL;
	}
	

	/* snatch the first attribute */
	tag = ber_scanf( ber, "{ax}", &attr );
	if( tag == LBER_ERROR ) {
		printf(">>Error<< Snatch first Attr failed!\n");
		ber_free( ber, 0 );
		return NULL;
	}
	
	return attr;

}
예제 #5
0
파일: io.c 프로젝트: bagel/openldap-ga
ber_slen_t
ber_skip_data(
	BerElement *ber,
	ber_len_t len )
{
	ber_len_t	actuallen, nleft;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	nleft = ber_pvt_ber_remaining( ber );
	actuallen = nleft < len ? nleft : len;
	ber->ber_ptr += actuallen;
	ber->ber_tag = *(unsigned char *)ber->ber_ptr;

	return( (ber_slen_t) actuallen );
}
예제 #6
0
/* Parse the next attribute */
char * next_attribute( BerElement *ber )
{
	ber_tag_t tag;
	char *attr;

	
	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
		return NULL;
	}

	/* skip sequence, snarf attribute type, skip values */
	tag = ber_scanf( ber, "{ax}", &attr ); 
	if( tag == LBER_ERROR ) {
		printf("| Attribute end\n");
		return NULL;
	}

	return attr;
}	
예제 #7
0
파일: io.c 프로젝트: bagel/openldap-ga
/*
 * Read from the ber buffer.  The caller must maintain ber->ber_tag.
 * Do not use to read whole tags.  See ber_get_tag() and ber_skip_data().
 */
ber_slen_t
ber_read(
	BerElement *ber,
	char *buf,
	ber_len_t len )
{
	ber_len_t	actuallen, nleft;

	assert( ber != NULL );
	assert( buf != NULL );
	assert( LBER_VALID( ber ) );

	nleft = ber_pvt_ber_remaining( ber );
	actuallen = nleft < len ? nleft : len;

	AC_MEMCPY( buf, ber->ber_ptr, actuallen );

	ber->ber_ptr += actuallen;

	return( (ber_slen_t) actuallen );
}
예제 #8
0
파일: getattr.c 프로젝트: cptaffe/openldap
char *
ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berout )
{
	int rc;
	ber_tag_t tag;
	ber_len_t len = 0;
	char *attr;
	BerElement *ber;

	Debug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 );

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( entry != NULL );
	assert( berout != NULL );

	*berout = NULL;

	ber = ldap_alloc_ber_with_options( ld );
	if( ber == NULL ) {
		return NULL;
	}

	*ber = *entry->lm_ber;

	/* 
	 * Skip past the sequence, dn, sequence of sequence leaving
	 * us at the first attribute.
	 */

	tag = ber_scanf( ber, "{xl{" /*}}*/, &len );
	if( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 0 );
		return NULL;
	}

	/* set the length to avoid overrun */
	rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len );
	if( rc != LBER_OPT_SUCCESS ) {
		ld->ld_errno = LDAP_LOCAL_ERROR;
		ber_free( ber, 0 );
		return NULL;
	}

	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
		assert( len == 0 );
		ber_free( ber, 0 );
		return NULL;
	}
	assert( len != 0 );

	/* snatch the first attribute */
	tag = ber_scanf( ber, "{ax}", &attr );
	if( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 0 );
		return NULL;
	}

	*berout = ber;
	return attr;
}
예제 #9
0
static int
asyncmeta_send_entry(
	Operation 	*op,
	SlapReply	*rs,
	a_metaconn_t	*mc,
	int 		target,
	LDAPMessage 	*e )
{
	a_metainfo_t 		*mi = mc->mc_info;
	struct berval		a, mapped = BER_BVNULL;
	int			check_sorted_attrs = 0;
	Entry 			ent = {0};
	BerElement 		ber = *ldap_get_message_ber( e );
	Attribute 		*attr, **attrp;
	struct berval 		bdn,
				dn = BER_BVNULL;
	const char 		*text;
	a_dncookie		dc;
	ber_len_t		len;
	int			rc;
	void	*mem_mark;

	mem_mark = slap_sl_mark( op->o_tmpmemctx );
	ber_set_option( &ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) {
		return LDAP_DECODING_ERROR;
	}

	if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) {
		return LDAP_OTHER;
	}

	if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) {
		return LDAP_DECODING_ERROR;
	}

	/*
	 * Rewrite the dn of the result, if needed
	 */
	dc.op = op;
	dc.target = mi->mi_targets[ target ];
	dc.memctx = op->o_tmpmemctx;
	dc.to_from = MASSAGE_REP;
	asyncmeta_dn_massage( &dc, &bdn, &dn );

	/*
	 * Note: this may fail if the target host(s) schema differs
	 * from the one known to the meta, and a DN with unknown
	 * attributes is returned.
	 *
	 * FIXME: should we log anything, or delegate to dnNormalize?
	 */
	rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,
		op->o_tmpmemctx );
	if ( dn.bv_val != bdn.bv_val ) {
			op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
	}
	BER_BVZERO( &dn );

	if ( rc != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY,
			"%s asyncmeta_send_entry(\"%s\"): "
			"invalid DN syntax\n",
			op->o_log_prefix, ent.e_name.bv_val );
		rc = LDAP_INVALID_DN_SYNTAX;
		goto done;
	}

	/*
	 * cache dn
	 */
	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
		( void )asyncmeta_dncache_update_entry( &mi->mi_cache,
				&ent.e_nname, target );
	}

	attrp = &ent.e_attrs;

	while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
		int				last = 0;
		slap_syntax_validate_func	*validate;
		slap_syntax_transform_func	*pretty;

		if ( ber_pvt_ber_remaining( &ber ) < 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"%s asyncmeta_send_entry(\"%s\"): "
				"unable to parse attr \"%s\".\n",
				op->o_log_prefix, ent.e_name.bv_val, a.bv_val );

			rc = LDAP_OTHER;
			goto done;
		}

		if ( ber_pvt_ber_remaining( &ber ) == 0 ) {
			break;
		}

		attr = op->o_tmpcalloc( 1, sizeof(Attribute), op->o_tmpmemctx );
		if ( slap_bv2ad( &a, &attr->a_desc, &text )
				!= LDAP_SUCCESS) {
			if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
			{
				Debug(LDAP_DEBUG_ANY,
				      "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n",
				      op->o_log_prefix, ent.e_name.bv_val,
				      mapped.bv_val, text );
				( void )ber_scanf( &ber, "x" /* [W] */ );
				op->o_tmpfree( attr, op->o_tmpmemctx );
				continue;
			}
		}

		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
			check_sorted_attrs = 1;

		/* no subschemaSubentry */
		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
			|| attr->a_desc == slap_schema.si_ad_entryDN )
		{

			/*
			 * We eat target's subschemaSubentry because
			 * a search for this value is likely not
			 * to resolve to the appropriate backend;
			 * later, the local subschemaSubentry is
			 * added.
			 *
			 * We also eat entryDN because the frontend
			 * will reattach it without checking if already
			 * present...
			 */
			( void )ber_scanf( &ber, "x" /* [W] */ );
			op->o_tmpfree( attr, op->o_tmpmemctx );
			continue;
		}

		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
				|| attr->a_vals == NULL )
		{
			attr->a_vals = (struct berval *)&slap_dummy_bv;

		} else {
			for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
				;
		}
		attr->a_numvals = last;

		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;

		if ( !validate && !pretty ) {
			ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx );
			op->o_tmpfree( attr, op->o_tmpmemctx );
			goto next_attr;
		}

		/*
		 * It is necessary to try to rewrite attributes with
		 * dn syntax because they might be used in ACLs as
		 * members of groups; since ACLs are applied to the
		 * rewritten stuff, no dn-based subecj clause could
		 * be used at the ldap backend side (see
		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
		 * The problem can be overcome by moving the dn-based
		 * ACLs to the target directory server, and letting
		 * everything pass thru the ldap backend.
		 */
		{
			int	i;

			if ( attr->a_desc->ad_type->sat_syntax ==
				slap_schema.si_syn_distinguishedName )
			{
				asyncmeta_dnattr_result_rewrite( &dc, attr->a_vals );

			} else if ( attr->a_desc == slap_schema.si_ad_ref ) {
				asyncmeta_referral_result_rewrite( &dc, attr->a_vals );

			}

			for ( i = 0; i < last; i++ ) {
				struct berval	pval;
				int		rc;

				if ( pretty ) {
					rc = ordered_value_pretty( attr->a_desc,
						&attr->a_vals[i], &pval, op->o_tmpmemctx );

				} else {
					rc = ordered_value_validate( attr->a_desc,
						&attr->a_vals[i], 0 );
				}

				if ( rc ) {
					ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[ i ] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
					continue;
				}

				if ( pretty ) {
					ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx );
					attr->a_vals[i] = pval;
				}
			}

			if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
				ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx );
				op->o_tmpfree( attr, op->o_tmpmemctx );
				goto next_attr;
			}
		}

		if ( last && attr->a_desc->ad_type->sat_equality &&
			attr->a_desc->ad_type->sat_equality->smr_normalize )
		{
			int i;

			attr->a_nvals = op->o_tmpalloc( ( last + 1 ) * sizeof( struct berval ), op->o_tmpmemctx );
			for ( i = 0; i<last; i++ ) {
				/* if normalizer fails, drop this value */
				if ( ordered_value_normalize(
					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
					attr->a_desc,
					attr->a_desc->ad_type->sat_equality,
					&attr->a_vals[i], &attr->a_nvals[i],
					op->o_tmpmemctx )) {
					ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[ i ] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
				}
			}
			BER_BVZERO( &attr->a_nvals[i] );
			if ( last == 0 ) {
				ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx );
				ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx );
				op->o_tmpfree( attr, op->o_tmpmemctx );
				goto next_attr;
			}

		} else {
			attr->a_nvals = attr->a_vals;
		}

		attr->a_numvals = last;
		*attrp = attr;
		attrp = &attr->a_next;
next_attr:;
	}

	/* Check for sorted attributes */
	if ( check_sorted_attrs ) {
		for ( attr = ent.e_attrs; attr; attr = attr->a_next ) {
			if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
				while ( attr->a_numvals > 1 ) {
					int i;
					int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
					if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
						break;

					/* Strip duplicate values */
					if ( attr->a_nvals != attr->a_vals )
						ber_memfree_x( attr->a_nvals[i].bv_val, op->o_tmpmemctx );
					ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx );
					attr->a_numvals--;
					if ( (unsigned)i < attr->a_numvals ) {
						attr->a_vals[i] = attr->a_vals[attr->a_numvals];
						if ( attr->a_nvals != attr->a_vals )
							attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
					}
					BER_BVZERO(&attr->a_vals[attr->a_numvals]);
					if ( attr->a_nvals != attr->a_vals )
						BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
				}
				attr->a_flags |= SLAP_ATTR_SORTED_VALS;
			}
		}
	}
	Debug( LDAP_DEBUG_TRACE,
	       "%s asyncmeta_send_entry(\"%s\"): "
	       ".\n",
	       op->o_log_prefix, ent.e_name.bv_val );
	ldap_get_entry_controls( mc->mc_conns[target].msc_ldr,
		e, &rs->sr_ctrls );
	rs->sr_entry = &ent;
	rs->sr_attrs = op->ors_attrs;
	rs->sr_operational_attrs = NULL;
	rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags;
	rs->sr_err = LDAP_SUCCESS;
	rc = send_search_entry( op, rs );
	switch ( rc ) {
	case LDAP_UNAVAILABLE:
		rc = LDAP_OTHER;
		break;
	}

done:;
	if ( rs->sr_ctrls != NULL ) {
		ldap_controls_free( rs->sr_ctrls );
		rs->sr_ctrls = NULL;
	}
#if 0
	while ( ent.e_attrs ) {
		attr = ent.e_attrs;
		ent.e_attrs = attr->a_next;
		if ( attr->a_nvals != attr->a_vals )
			ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx );
		ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx );
		op->o_tmpfree( attr, op->o_tmpmemctx );
	}
	if (ent.e_name.bv_val != NULL) {
		op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
	}

	if (ent.e_nname.bv_val != NULL) {
		op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );
	}
	if (rs->sr_entry && rs->sr_entry != &ent) {
		entry_free( rs->sr_entry );
	}
#endif
	slap_sl_release( mem_mark, op->o_tmpmemctx );
	rs->sr_entry = NULL;
	rs->sr_attrs = NULL;
	return rc;
}
예제 #10
0
파일: options.c 프로젝트: cptaffe/openldap
int
ber_get_option(
	void	*item,
	int		option,
	void	*outvalue)
{
	const BerElement *ber;
	const Sockbuf *sb;

	if(outvalue == NULL) {
		/* no place to get to */
		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	if(item == NULL) {
		switch ( option ) {
		case LBER_OPT_BER_DEBUG:
			* (int *) outvalue = ber_int_debug;
			return LBER_OPT_SUCCESS;

		case LBER_OPT_MEMORY_INUSE:
			/* The memory inuse is a global variable on kernal implementations.
			 * This means that memory debug is shared by all LDAP processes
			 * so for this variable to have much meaning, only one LDAP process
			 * should be running and memory inuse should be initialized to zero
			 * using the lber_set_option() function during startup.
			 * The counter is not accurate for multithreaded ldap applications.
			 */
#ifdef LDAP_MEMORY_DEBUG
			* (int *) outvalue = ber_int_meminuse;
			return LBER_OPT_SUCCESS;
#else
			return LBER_OPT_ERROR;
#endif

		case LBER_OPT_LOG_PRINT_FILE:
			*((FILE**)outvalue) = (FILE*)ber_pvt_err_file;
			return LBER_OPT_SUCCESS;
		}

		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	ber = item;
	sb = item;

	switch(option) {
	case LBER_OPT_BER_OPTIONS:
		assert( LBER_VALID( ber ) );
		* (int *) outvalue = ber->ber_options;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_DEBUG:
		assert( LBER_VALID( ber ) );
		* (int *) outvalue = ber->ber_debug;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_REMAINING_BYTES:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_TOTAL_BYTES:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_total(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_BYTES_TO_WRITE:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_write(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_MEMCTX:
		assert( LBER_VALID( ber ) );
		*((void **) outvalue) = ber->ber_memctx;
		return LBER_OPT_SUCCESS;
	
	default:
		/* bad param */
		ber_errno = LBER_ERROR_PARAM;
		break;
	}

	return LBER_OPT_ERROR;
}
예제 #11
0
int ldap_pvt_get_controls(
	BerElement *ber,
	LDAPControl ***ctrls )
{
	int nctrls;
	ber_tag_t tag;
	ber_len_t len;
	char *opaque;

	assert( ber != NULL );

	if( ctrls == NULL ) {
		return LDAP_SUCCESS;
	}
	*ctrls = NULL;

	len = ber_pvt_ber_remaining( ber );

	if( len == 0) {
		/* no controls */
		return LDAP_SUCCESS;
	}

	if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
		if( tag == LBER_ERROR ) {
			/* decoding error */
			return LDAP_DECODING_ERROR;
		}

		/* ignore unexpected input */
		return LDAP_SUCCESS;
	}

	/* set through each element */
	nctrls = 0;
	*ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );

	if( *ctrls == NULL ) {
		return LDAP_NO_MEMORY;
	}

	*ctrls[nctrls] = NULL;

	for( tag = ber_first_element( ber, &len, &opaque );
		tag != LBER_ERROR;
		tag = ber_next_element( ber, &len, opaque ) )
	{
		LDAPControl *tctrl;
		LDAPControl **tctrls;

		tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );

		/* allocate pointer space for current controls (nctrls)
		 * + this control + extra NULL
		 */
		tctrls = (tctrl == NULL) ? NULL :
			LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));

		if( tctrls == NULL ) {
			/* one of the above allocation failed */

			if( tctrl != NULL ) {
				LDAP_FREE( tctrl );
			}

			ldap_controls_free(*ctrls);
			*ctrls = NULL;

			return LDAP_NO_MEMORY;
		}


		tctrls[nctrls++] = tctrl;
		tctrls[nctrls] = NULL;

		tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );

		if( tag == LBER_ERROR ) {
			*ctrls = NULL;
			ldap_controls_free( tctrls );
			return LDAP_DECODING_ERROR;
		}

		tag = ber_peek_tag( ber, &len );

		if( tag == LBER_BOOLEAN ) {
			ber_int_t crit;
			tag = ber_scanf( ber, "b", &crit );
			tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
			tag = ber_peek_tag( ber, &len );
		}

		if( tag == LBER_OCTETSTRING ) {
			tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
		} else {
			BER_BVZERO( &tctrl->ldctl_value );
		}

		*ctrls = tctrls;
	}
		
	return LDAP_SUCCESS;
}
예제 #12
0
파일: controls.c 프로젝트: vmware/lightwave
int
ParseRequestControls(
   VDIR_OPERATION *    op,
   VDIR_LDAP_RESULT *  lr
   )
{
    int                     retVal = LDAP_SUCCESS;
    ber_tag_t               tag = LBER_ERROR;
    ber_len_t               len = 0;
    char *                  endOfCtrlsMarker = NULL;
    VDIR_LDAP_CONTROL **    control = &(op->reqControls);
    BerValue                lberBervType = {0};
    BerValue                lberBervCtlValue = {0};
    PSTR                    pszLocalErrorMsg = NULL;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: Begin." );

    *control = NULL;

#ifndef _WIN32
    if (ber_pvt_ber_remaining(op->ber) != 0)
#else
    if (LBER_DEFAULT != ber_peek_tag (op->ber, &len))
#endif
    {
        if (ber_peek_tag( op->ber, &len ) != LDAP_TAG_CONTROLS )
        {
            lr->errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                           "ParseRequestControls: Request controls expected, but something else is there in the PDU.");
        }

        // Get controls. ber_first_element => skip the sequence header, set the cursor at the 1st control in the SEQ of SEQ
        for( tag = ber_first_element( op->ber, &len, &endOfCtrlsMarker ); tag != LBER_ERROR;
             tag = ber_next_element( op->ber, &len, endOfCtrlsMarker ) )
        {
            // m => in-place
            if (ber_scanf( op->ber, "{m", &lberBervType ) == LBER_ERROR)
            {
                lr->errCode = LDAP_PROTOCOL_ERROR;
                retVal = LDAP_NOTICE_OF_DISCONNECT;
                BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                              "ParseRequestControls Error in reading control type from the PDU.");
            }
            if ( VmDirLogGetMask() & LDAP_DEBUG_ARGS)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "    Request Control: %s", lberBervType.bv_val );
            }
            if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL), (PVOID *)control ) != 0)
            {
                retVal = lr->errCode = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "ParseRequestControls: VmDirAllocateMemory failed");
            }
            // type points into in-place ber and does NOT own its content
            (*control)->type = lberBervType.bv_val;
            (*control)->criticality = FALSE;
            tag = ber_peek_tag( op->ber, &len );

            if (tag == LBER_BOOLEAN)
            {
                ber_int_t criticality;
                if (ber_scanf( op->ber, "b", &criticality) == LBER_ERROR)
                {
                    lr->errCode = LDAP_PROTOCOL_ERROR;
                    retVal = LDAP_NOTICE_OF_DISCONNECT;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                            "ParseRequestControls: Error in reading control criticality from the PDU.");
                }
                if (criticality)
                {
                    (*control)->criticality = TRUE;
                }
                tag = ber_peek_tag( op->ber, &len );
            }

            if (tag == LBER_OCTETSTRING)
            {
                if (ber_scanf( op->ber, "m", &lberBervCtlValue) == LBER_ERROR)
                {
                    lr->errCode = LDAP_PROTOCOL_ERROR;
                    retVal = LDAP_NOTICE_OF_DISCONNECT;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                             "ParseRequestControls: ber_scanf failed while parsing the control value.");
                }
            }

            // SJ-TBD: Make sure that the control appears only once in the request, and it is present only in a search
            // request
            if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_SYNC, TRUE ) == 0)
            {
                if (VmDirdGetRunMode() != VMDIR_RUNMODE_NORMAL)
                {
                    // Why block out-bound replication when catching up during restore mode?
                    //
                    // Reason: Partners have high-water-mark (lastLocalUsn) corresponding to this replica that is being
                    // restored. If out-bound replication is not blocked while restore/catching-up is going on, originating
                    // or replicated updates (if this replica is the only partner) made between the current-local-usn and
                    // high-water-marks, that partners remember, will not get replicated out (even if the invocationId
                    // has been fixed/changed).

                    retVal = lr->errCode = LDAP_UNWILLING_TO_PERFORM;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                 "ParseRequestControls: Server not in normal mode, not allowing outward replication.");
                }

                if ((retVal = ParseSyncRequestControlVal( op, &lberBervCtlValue, &((*control)->value.syncReqCtrlVal),
                                                          lr)) != LDAP_SUCCESS)
                {
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                                  "ParseRequestControls: ParseSyncRequestControlVal failed.");
                }
                op->syncReqCtrl = *control;
            }
            if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_DELETED_OBJECTS, TRUE ) == 0)
            {
                op->showDeletedObjectsCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_MASTER_KEY, TRUE ) == 0)
            {
                op->showMasterKeyCtrl = *control;
            }

            if (VmDirStringCompareA((*control)->type, LDAP_CONTROL_CONSISTENT_WRITE, TRUE ) == 0)
            {
                op->strongConsistencyWriteCtrl = *control;
            }

            if (VmDirStringCompareA((*control)->type, VDIR_LDAP_CONTROL_MANAGEDDSAIT, TRUE ) == 0)
            {
                op->manageDsaITCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_PAGEDRESULTS, TRUE ) == 0)
            {
                retVal = _ParsePagedResultControlVal( op,
                                                &lberBervCtlValue,
                                                &((*control)->value.pagedResultCtrlVal),
                                                lr);
                if (retVal != LDAP_SUCCESS)
                {
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                                  "ParseRequestControls: _ParsePagedResultControlVal failed.");
                }
                op->showPagedResultsCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_CONDITIONAL_WRITE, TRUE ) == 0)
            {
                retVal = _ParseCondWriteControlVal(
                            op,
                            &lberBervCtlValue,
                            &((*control)->value.condWriteCtrlVal),
                            lr);
                if (retVal != LDAP_SUCCESS)
                {
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                                  "ParseRequestControls: _ParseConditionalWriteControlVal failed.");
                }
                op->pCondWriteCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, LDAP_APPEND_ENTRIES_CONTROL, TRUE ) == 0)
            {
                retVal = _ParseAppendEntriesControlVal( op,
                                                &lberBervCtlValue,
                                                &((*control)->value.appendEntriesCtrlVal),
                                                lr);
                if (retVal != LDAP_SUCCESS)
                {
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                                  "ParseRequestControls: _ParseAppendEntriesControlVal failed.");
                }
                op->appendEntriesCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, LDAP_REQUEST_VOTE_CONTROL, TRUE ) == 0)
            {
                retVal = _ParseRequestVoteControlVal( op,
                                                &lberBervCtlValue,
                                                &((*control)->value.requestVoteCtrlVal),
                                                lr);
                if (retVal != LDAP_SUCCESS)
                {
                    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                                  "ParseRequestControls: _ParseRequestVoteControlVal failed.");
                }
                op->requestVoteCtrl = *control;
            }

            if (VmDirStringCompareA( (*control)->type, VMDIR_LDAP_CONTROL_TXN_SPEC, TRUE ) == 0)
            {
                retVal = VmDirAllocateMemory(lberBervCtlValue.bv_len+1, (PVOID*)&((*control)->value.txnSpecCtrlVal).pszTxnId);
                BAIL_ON_VMDIR_ERROR(retVal);
                VmDirStringNCpyA(((*control)->value.txnSpecCtrlVal).pszTxnId, lberBervCtlValue.bv_len+1,
                                 lberBervCtlValue.bv_val, lberBervCtlValue.bv_len);
                op->txnSpecCtrl = *control;
                op->pBECtx->pszTxnId = (op->txnSpecCtrl->value.txnSpecCtrlVal).pszTxnId;
            }

            if ( ber_scanf( op->ber, "}") == LBER_ERROR ) // end of control
            {
                lr->errCode = LDAP_PROTOCOL_ERROR;
                retVal = LDAP_NOTICE_OF_DISCONNECT;
                BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                                              "ParseRequestControls: ber_scanf failed while parsing the end of control");

            }
            control = &((*control)->next);
        }

        retVal = LDAP_SUCCESS;
    }

cleanup:
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: End." );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:
    DeleteControls(&(op->reqControls));

    if (pszLocalErrorMsg)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, pszLocalErrorMsg);
        VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg);
    }

    goto cleanup;
}