Esempio n. 1
0
static int pack_vlv_response_control(
	Operation		*op,
	SlapReply		*rs,
	sort_op			*so,
	LDAPControl	**ctrlsp )
{
	LDAPControl			*ctrl;
	BerElementBuffer	berbuf;
	BerElement			*ber		= (BerElement *)&berbuf;
	struct berval		cookie, bv;
	int					rc;

	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	rc = ber_printf( ber, "{iie", so->so_vlv_target, so->so_nentries,
		so->so_vlv_rc );

	if ( rc != -1 && so->so_vcontext ) {
		cookie.bv_val = (char *)&so->so_vcontext;
		cookie.bv_len = sizeof(so->so_vcontext);
		rc = ber_printf( ber, "tO", LDAP_VLVCONTEXT_IDENTIFIER, &cookie );
	}

	if ( rc != -1 ) {
		rc = ber_printf( ber, "}" );
	}

	if ( rc != -1 ) {
		rc = ber_flatten2( ber, &bv, 0 );
	}

	if ( rc != -1 ) {
		ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+
			bv.bv_len, op->o_tmpmemctx );
		ctrl->ldctl_oid			= LDAP_CONTROL_VLVRESPONSE;
		ctrl->ldctl_iscritical	= 0;
		ctrl->ldctl_value.bv_val = (char *)(ctrl+1);
		ctrl->ldctl_value.bv_len = bv.bv_len;
		AC_MEMCPY( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
		ctrlsp[0] = ctrl;
	} else {
		ctrlsp[0] = NULL;
		rs->sr_err = LDAP_OTHER;
	}

	ber_free_buf( ber );

	return rs->sr_err;
}
Esempio n. 2
0
static char *cpy_addresses(
	char ***tgtio,
	char *buf,
	char **src,
	int len )
{
   	char **tgt=*tgtio;
	for( ; (*src) ; src++ ) {
		AC_MEMCPY( buf, *src, len );
		*tgt++=buf;
		buf+=len;
	}
	*tgtio=tgt;      
	return buf;
}
Esempio n. 3
0
File: idl.c Progetto: 1ack/Impala
/* Append sorted list b to sorted list a. The result is unsorted but
 * a[1] is the min of the result and a[a[0]] is the max.
 */
int bdb_idl_append( ID *a, ID *b )
{
	ID ida, idb, tmp, swap = 0;

	if ( BDB_IDL_IS_ZERO( b ) ) {
		return 0;
	}

	if ( BDB_IDL_IS_ZERO( a ) ) {
		BDB_IDL_CPY( a, b );
		return 0;
	}

	ida = BDB_IDL_LAST( a );
	idb = BDB_IDL_LAST( b );
	if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ||
		a[0] + b[0] >= BDB_IDL_UM_MAX ) {
		a[2] = IDL_MAX( ida, idb );
		a[1] = IDL_MIN( a[1], b[1] );
		a[0] = NOID;
		return 0;
	}

	if ( b[0] > 1 && ida > idb ) {
		swap = idb;
		a[a[0]] = idb;
		b[b[0]] = ida;
	}

	if ( b[1] < a[1] ) {
		tmp = a[1];
		a[1] = b[1];
	} else {
		tmp = b[1];
	}
	a[0]++;
	a[a[0]] = tmp;

	if ( b[0] > 1 ) {
		int i = b[0] - 1;
		AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID));
		a[0] += i;
	}
	if ( swap ) {
		b[b[0]] = swap;
	}
	return 0;
}
Esempio n. 4
0
static char *cpy_aliases(
	char ***tgtio,
	char *buf,
	char **src )
{
	int len;
	char **tgt=*tgtio;
	for( ; (*src) ; src++ ) {
		len = strlen( *src ) + 1;
		AC_MEMCPY( buf, *src, len );
		*tgt++=buf;
		buf+=len;
	}
	*tgtio=tgt;   
	return buf;
}
Esempio n. 5
0
int
rewrite_var_replace(
		struct rewrite_var *var,
		const char *value,
		int flags
)
{
	ber_len_t	len;

	assert( value != NULL );

	len = strlen( value );

	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
		if ( flags & REWRITE_VAR_COPY_VALUE ) {
			if ( len <= var->lv_value.bv_len ) {
				AC_MEMCPY(var->lv_value.bv_val, value, len + 1);

			} else {
				free( var->lv_value.bv_val );
				var->lv_value.bv_val = strdup( value );
			}

		} else {
			free( var->lv_value.bv_val );
			var->lv_value.bv_val = (char *)value;
			var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
		}

	} else {
		if ( flags & REWRITE_VAR_COPY_VALUE ) {
			var->lv_value.bv_val = strdup( value );
			var->lv_flags |= REWRITE_VAR_COPY_VALUE;

		} else {
			var->lv_value.bv_val = (char *)value;
		}
	}

	if ( var->lv_value.bv_val == NULL ) {
		return -1;
	}

	var->lv_value.bv_len = len;

	return 0;
}
Esempio n. 6
0
static int
dupent_response_done( Operation *op, SlapReply *rs )
{
	BerElementBuffer	berbuf;
	BerElement			*ber = (BerElement *) &berbuf;
	struct berval		ctrlval;
	LDAPControl			*ctrl, *ctrlsp[2];

	ber_init2( ber, NULL, LBER_USE_DER );

	/*

      DuplicateEntryResponseDone ::= SEQUENCE { 
         resultCode,     -- From [RFC2251] 
         errorMessage    [0] LDAPString OPTIONAL, 
         attribute       [1] AttributeDescription OPTIONAL } 

	 */

	ber_printf( ber, "{i}", rs->sr_err );
	if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
		ber_free_buf( ber );
		if ( op->o_dupent == SLAP_CONTROL_CRITICAL ) {
			return LDAP_CONSTRAINT_VIOLATION;
		}
		return SLAP_CB_CONTINUE;
	}

	ctrl = op->o_tmpcalloc( 1,
		sizeof( LDAPControl ) + ctrlval.bv_len + 1,
		op->o_tmpmemctx );
	ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
	ctrl->ldctl_oid = LDAP_CONTROL_DUPENT_RESPONSE;
	ctrl->ldctl_iscritical = 0;
	ctrl->ldctl_value.bv_len = ctrlval.bv_len;
	AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
	ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';

	ber_free_buf( ber );

	ctrlsp[0] = ctrl;
	ctrlsp[1] = NULL;
	slap_add_ctrls( op, rs, ctrlsp );

	return SLAP_CB_CONTINUE;
}
Esempio n. 7
0
static void
add_lower(ac_uint4 code)
{
    ac_uint4 i, j;

    /*
     * Always map the code to itself.
     */
    cases[1] = code;

    /*
     * If the title case character is empty, then make it the same as the
     * upper case.
     */
    if (cases[2] == 0)
      cases[2] = cases[0];

    if (lower_used == lower_size) {
        if (lower_size == 0)
          lower = (_case_t *) malloc(sizeof(_case_t) << 3);
        else
          lower = (_case_t *) realloc((char *) lower,
                                      sizeof(_case_t) * (lower_size + 8));
        lower_size += 8;
    }

    /*
     * Locate the insertion point.
     */
    for (i = 0; i < lower_used && code > lower[i].key; i++) ;

    if (i < lower_used) {
        /*
         * Shift the array up by one.
         */
        for (j = lower_used; j > i; j--)
          (void) AC_MEMCPY((char *) &lower[j], (char *) &lower[j - 1],
                        sizeof(_case_t));
    }

    lower[i].key = cases[1];    /* Lower */
    lower[i].other1 = cases[0]; /* Upper */
    lower[i].other2 = cases[2]; /* Title */

    lower_used++;
}
Esempio n. 8
0
int
bdb_dn2id_children(
	Operation *op,
	DB_TXN *txn,
	Entry *e )
{
	DBT		key, data;
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	ID		id;
	int		rc;

	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children(\"%s\")\n",
		e->e_nname.bv_val, 0, 0 );
	DBTzero( &key );
	key.size = e->e_nname.bv_len + 2;
	key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
	((char *)key.data)[0] = DN_ONE_PREFIX;
	AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );

	if ( bdb->bi_idl_cache_size ) {
		rc = bdb_idl_cache_get( bdb, db, &key, NULL );
		if ( rc != LDAP_NO_SUCH_OBJECT ) {
			op->o_tmpfree( key.data, op->o_tmpmemctx );
			return rc;
		}
	}
	/* we actually could do a empty get... */
	DBTzero( &data );
	data.data = &id;
	data.ulen = sizeof(id);
	data.flags = DB_DBT_USERMEM;
	data.doff = 0;
	data.dlen = sizeof(id);

	rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
	op->o_tmpfree( key.data, op->o_tmpmemctx );

	Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children(\"%s\"): %s (%d)\n",
		e->e_nname.bv_val,
		rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
			db_strerror(rc) ), rc );

	return rc;
}
Esempio n. 9
0
int
ldap_get_entry_controls(
	LDAP *ld,
	LDAPMessage *entry, 
	LDAPControl ***sctrls )
{
	int rc;
	BerElement be;

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

	if ( entry->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
		return LDAP_PARAM_ERROR;
	}

	/* make a local copy of the BerElement */
	AC_MEMCPY(&be, entry->lm_ber, sizeof(be));

	if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) {
		rc = LDAP_DECODING_ERROR;
		goto cleanup_and_return;
	}

	rc = ldap_pvt_get_controls( &be, sctrls );

cleanup_and_return:
	if( rc != LDAP_SUCCESS ) {
		ld->ld_errno = rc;

		if( ld->ld_matched != NULL ) {
			LDAP_FREE( ld->ld_matched );
			ld->ld_matched = NULL;
		}

		if( ld->ld_error != NULL ) {
			LDAP_FREE( ld->ld_error );
			ld->ld_error = NULL;
		}
	}

	return rc;
}
Esempio n. 10
0
int
bdb_dn2id(
	Operation *op,
	struct berval	*dn,
	EntryInfo *ei,
	DB_TXN *txn,
	DBC **cursor )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	int		rc;
	DBT		key, data;
	ID		nid;

	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id(\"%s\")\n", dn->bv_val, 0, 0 );

	DBTzero( &key );
	key.size = dn->bv_len + 2;
	key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
	((char *)key.data)[0] = DN_BASE_PREFIX;
	AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );

	/* store the ID */
	DBTzero( &data );
	data.data = &nid;
	data.ulen = sizeof(ID);
	data.flags = DB_DBT_USERMEM;

	rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );

	/* fetch it */
	if ( !rc )
		rc = (*cursor)->c_get( *cursor, &key, &data, DB_SET );

	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
			db_strerror( rc ), rc, 0 );
	} else {
		BDB_DISK2ID( &nid, &ei->bei_id );
		Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%lx\n",
			ei->bei_id, 0, 0 );
	}
	op->o_tmpfree( key.data, op->o_tmpmemctx );
	return rc;
}
Esempio n. 11
0
static Datum
ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
{
	kvpair	out;
	kvpair	in;
	Datum	ret;
	size_t	sz = MDBM_PAGE_SIZE(ldbm);
#ifdef NO_NULL_KEY
	int	delta = 1;
#else
	int	delta = 0;
#endif

	/* LDBM_RLOCK; */

	in.key.dsize = sz;	/* Assume first key in one pg */
	in.key.dptr = malloc(sz);
	
	in.val.dptr = NULL;	/* Don't need data just key */ 
	in.val.dsize = 0;

	ret.dptr = NULL;
	ret.dsize = NULL;

	out = fptr( ldbm, in );

	if (out.key.dsize > 0) {
		ret.dsize = out.key.dsize - delta;

		if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
			ret.dsize = 0;
			ret.dptr = NULL;

		} else {
			AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta),
				ret.dsize );
	    }
	}

	/* LDBM_RUNLOCK; */
	
	free(in.key.dptr);
	return ret;
}
Esempio n. 12
0
File: result.c Progetto: 1ack/Impala
static char *v2ref( BerVarray ref, const char *text )
{
	size_t len = 0, i = 0;
	char *v2;

	if(ref == NULL) {
		if (text) {
			return ch_strdup(text);
		} else {
			return NULL;
		}
	}
	
	if ( text != NULL ) {
		len = strlen( text );
		if (text[len-1] != '\n') {
		    i = 1;
		}
	}

	v2 = ch_malloc( len+i+sizeof("Referral:") );

	if( text != NULL ) {
		strcpy(v2, text);
		if( i ) {
			v2[len++] = '\n';
		}
	}
	strcpy( v2+len, "Referral:" );
	len += sizeof("Referral:");

	for( i=0; ref[i].bv_val != NULL; i++ ) {
		v2 = ch_realloc( v2, len + ref[i].bv_len + 1 );
		v2[len-1] = '\n';
		AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
		len += ref[i].bv_len;
		if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
			++len;
		}
	}

	v2[len-1] = '\0';
	return v2;
}
Esempio n. 13
0
static int
parse_paged_cookie( Operation *op, SlapReply *rs )
{
	int		rc = LDAP_SUCCESS;
	PagedResultsState *ps = op->o_pagedresults_state;

	/* this function must be invoked only if the pagedResults
	 * control has been detected, parsed and partially checked
	 * by the frontend */
	assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );

	/* cookie decoding/checks deferred to backend... */
	if ( ps->ps_cookieval.bv_len ) {
		PagedResultsCookie reqcookie;
		if( ps->ps_cookieval.bv_len != sizeof( reqcookie ) ) {
			/* bad cookie */
			rs->sr_text = "paged results cookie is invalid";
			rc = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));

		if ( reqcookie > ps->ps_cookie ) {
			/* bad cookie */
			rs->sr_text = "paged results cookie is invalid";
			rc = LDAP_PROTOCOL_ERROR;
			goto done;

		} else if ( reqcookie < ps->ps_cookie ) {
			rs->sr_text = "paged results cookie is invalid or old";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

	} else {
		/* we're going to use ps_cookie */
		op->o_conn->c_pagedresults_state.ps_cookie = 0;
	}

done:;

	return rc;
}
Esempio n. 14
0
static int
ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
{
	int x;
	int i = bdb_attr_slot( bdb, a->ai_desc, &x );

	/* Is it a dup? */
	if ( i >= 0 )
		return -1;

	bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) * 
		sizeof( AttrInfo * ));
	if ( x < bdb->bi_nattrs )
		AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
			( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
	bdb->bi_attrs[x] = a;
	bdb->bi_nattrs++;
	return 0;
}
Esempio n. 15
0
static int
ainfo_insert( struct mdb_info *mdb, AttrInfo *a )
{
	int x;
	int i = mdb_attr_slot( mdb, a->ai_desc, &x );

	/* Is it a dup? */
	if ( i >= 0 )
		return -1;

	mdb->mi_attrs = ch_realloc( mdb->mi_attrs, ( mdb->mi_nattrs+1 ) * 
		sizeof( AttrInfo * ));
	if ( x < mdb->mi_nattrs )
		AC_MEMCPY( &mdb->mi_attrs[x+1], &mdb->mi_attrs[x],
			( mdb->mi_nattrs - x ) * sizeof( AttrInfo *));
	mdb->mi_attrs[x] = a;
	mdb->mi_nattrs++;
	return 0;
}
Esempio n. 16
0
		/* insert id */
		AC_MEMCPY( &ids[x+1], &ids[x], (ids[0]-x) * sizeof(ID) );
		ids[x] = id;
	}

#if IDL_DEBUG > 1
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	return 0;
}

#if 0	/* unused */
static int idl_delete( ID *ids, ID id )
{
	unsigned x = bdb_idl_search( ids, id );

#if IDL_DEBUG > 1
#ifdef NEW_LOGGING
	LDAP_LOG( INDEX, DETAIL1, "delete: %04lx at %d\n", (long) id, x, 0 );
#else
	Debug( LDAP_DEBUG_ANY, "delete: %04lx at %d\n", (long) id, x, 0 );
	idl_dump( ids );
#endif
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	assert( x > 0 );

	if( x <= 0 ) {
		/* internal error */
		return -2;
	}

	if( x > ids[0] || ids[x] != id ) {
		/* not found */
		return -1;

	} else if ( --ids[0] == 0 ) {
		if( x != 1 ) {
			return -3;
		}

	} else {
		AC_MEMCPY( &ids[x], &ids[x+1], (1+ids[0]-x) * sizeof(ID) );
	}

#if IDL_DEBUG > 1
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	return 0;
}
Esempio n. 17
0
int
ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
{
	int	rc;
	Datum	int_key;	/* Internal key */

#ifdef MDBM_DEBUG
	fprintf( stdout,
		 "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
		 ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
	fflush( stdout );
#endif

	/* LDBM_WLOCK; */

#ifdef NO_NULL_KEY
	int_key.dsize = key.dsize + 1;
	int_key.dptr = malloc( int_key.dsize );
	*(int_key.dptr) = 'l';	/* Must not be NULL !*/
	AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
#else
	int_key = key;
#endif

	rc = mdbm_store( ldbm, int_key, data, flags );
	if ( flags & LDBM_SYNC ) {
		mdbm_sync( ldbm );
	}

	/* LDBM_WUNLOCK; */

#ifdef MDBM_DEBUG
	fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
	fflush( stdout );
#endif

#ifdef NO_NULL_KEY
	free(int_key.dptr);
#endif

	return( rc );
}
Esempio n. 18
0
static int 
OpenLDAPaciNormalizeRights(
	struct berval	*actions,
	struct berval	*nactions,
	void		*ctx )

{
	struct berval	bv = BER_BVNULL;
	int		i;

	BER_BVZERO( nactions );
	for ( i = 0; acl_get_part( actions, i, '$', &bv ) >= 0; i++ ) {
		int		rc;
		struct berval	nbv;

		rc = OpenLDAPaciNormalizeRight( &bv, &nbv, ctx );
		if ( rc != LDAP_SUCCESS ) {
			ber_memfree_x( nactions->bv_val, ctx );
			BER_BVZERO( nactions );
			return LDAP_INVALID_SYNTAX;
		}

		if ( i == 0 ) {
			*nactions = nbv;

		} else {
			nactions->bv_val = ber_memrealloc_x( nactions->bv_val,
				nactions->bv_len + STRLENOF( "$" )
				+ nbv.bv_len + 1,
				ctx );
			nactions->bv_val[ nactions->bv_len ] = '$';
			AC_MEMCPY( &nactions->bv_val[ nactions->bv_len + 1 ],
				nbv.bv_val, nbv.bv_len + 1 );
			ber_memfree_x( nbv.bv_val, ctx );
			nactions->bv_len += STRLENOF( "$" ) + nbv.bv_len;
		}
		BER_BVZERO( &nbv );
	}

	return LDAP_SUCCESS;
}
Esempio n. 19
0
/* Drop a processed packet from the input buffer */
static void
sb_sasl_generic_drop_packet (
	struct sb_sasl_generic_data *p,
	int debuglevel )
{
	ber_slen_t			len;

	len = p->sec_buf_in.buf_ptr - p->sec_buf_in.buf_end;
	if ( len > 0 )
		AC_MEMCPY( p->sec_buf_in.buf_base, p->sec_buf_in.buf_base +
			p->sec_buf_in.buf_end, len );

	if ( len >= 4 ) {
		p->sec_buf_in.buf_end = sb_sasl_generic_pkt_length(p,
			(unsigned char *) p->sec_buf_in.buf_base, debuglevel);
	}
	else {
		p->sec_buf_in.buf_end = 0;
	}
	p->sec_buf_in.buf_ptr = len;
}
Esempio n. 20
0
Datum
ldbm_datum_dup( LDBM ldbm, Datum data )
{
	Datum	dup;

	ldbm_datum_init( dup );

	if ( data.dsize == 0 ) {
		dup.dsize = 0;
		dup.dptr = NULL;

		return( dup );
	}
	dup.dsize = data.dsize;

	if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) {
		AC_MEMCPY( dup.dptr, data.dptr, data.dsize );
	}

	return( dup );
}
Esempio n. 21
0
/*
 * 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 );
}
Esempio n. 22
0
static void
add_title(ac_uint4 code)
{
    ac_uint4 i, j;

    /*
     * Always map the code to itself.
     */
    cases[2] = code;

    if (title_used == title_size) {
        if (title_size == 0)
          title = (_case_t *) malloc(sizeof(_case_t) << 3);
        else
          title = (_case_t *) realloc((char *) title,
                                      sizeof(_case_t) * (title_size + 8));
        title_size += 8;
    }

    /*
     * Locate the insertion point.
     */
    for (i = 0; i < title_used && code > title[i].key; i++) ;

    if (i < title_used) {
        /*
         * Shift the array up by one.
         */
        for (j = title_used; j > i; j--)
          (void) AC_MEMCPY((char *) &title[j], (char *) &title[j - 1],
                        sizeof(_case_t));
    }

    title[i].key = cases[2];    /* Title */
    title[i].other1 = cases[0]; /* Upper */
    title[i].other2 = cases[1]; /* Lower */

    title_used++;
}
Esempio n. 23
0
char *ldap_pvt_ctime( const time_t *tp, char *buf )
{
#ifdef USE_CTIME_R
# if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2)
#	error "CTIME_R_NARGS should be 2 or 3"
# elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT)
    return( ctime_r(tp,buf,26) < 0 ? 0 : buf );
# elif CTIME_R_NARGS > 2
    return ctime_r(tp,buf,26);
# else
    return ctime_r(tp,buf);
# endif

#else

    LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex );
    AC_MEMCPY( buf, ctime(tp), 26 );
    LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex );

    return buf;
#endif
}
Esempio n. 24
0
ber_len_t
ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
{
	ber_len_t		max;

	assert( buf != NULL );
	assert( sbb != NULL );
#if 0
	assert( sbb->buf_size > 0 );
#endif

	max = sbb->buf_end - sbb->buf_ptr;
	max = ( max < len) ? max : len;
	if ( max ) {
		AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
		sbb->buf_ptr += max;
		if ( sbb->buf_ptr >= sbb->buf_end ) {
			sbb->buf_ptr = sbb->buf_end = 0;
		}
   }
	return max;
}
Esempio n. 25
0
static int pack_sss_response_control(
	Operation		*op,
	SlapReply		*rs,
	LDAPControl	**ctrlsp )
{
	LDAPControl			*ctrl;
	BerElementBuffer	berbuf;
	BerElement			*ber		= (BerElement *)&berbuf;
	struct berval		bv;
	int					rc;

	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	/* Pack error code */
	rc = ber_printf(ber, "{e}", rs->sr_err);

	if ( rc != -1)
		rc = ber_flatten2( ber, &bv, 0 );

	if ( rc != -1 ) {
		ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+
			bv.bv_len, op->o_tmpmemctx );
		ctrl->ldctl_oid			= LDAP_CONTROL_SORTRESPONSE;
		ctrl->ldctl_iscritical	= 0;
		ctrl->ldctl_value.bv_val = (char *)(ctrl+1);
		ctrl->ldctl_value.bv_len = bv.bv_len;
		AC_MEMCPY( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
		ctrlsp[0] = ctrl;
	} else {
		ctrlsp[0] = NULL;
		rs->sr_err = LDAP_OTHER;
	}

	ber_free_buf( ber );

	return rs->sr_err;
}
Esempio n. 26
0
/* Duplicate a set.  If SLAP_SET_REFARR, is not set, the original array
 * with the original values is returned, otherwise the array is duplicated;
 * if SLAP_SET_REFVAL is set, also the values are duplicated.
 */
static BerVarray
set_dup( SetCookie *cp, BerVarray set, unsigned flags )
{
	BerVarray	newset = NULL;

	if ( set == NULL ) {
		return NULL;
	}

	if ( flags & SLAP_SET_REFARR ) {
		int	i;

		for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ )
			;
		newset = cp->set_op->o_tmpcalloc( i + 1,
				sizeof( struct berval ), 
				cp->set_op->o_tmpmemctx );
		if ( newset == NULL ) {
			return NULL;
		}

		if ( flags & SLAP_SET_REFVAL ) {
			for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
				ber_dupbv_x( &newset[ i ], &set[ i ],
						cp->set_op->o_tmpmemctx );
			}

		} else {
			AC_MEMCPY( newset, set, ( i + 1 ) * sizeof( struct berval ) );
		}
		
	} else {
		newset = set;
	}

	return newset;
}
Esempio n. 27
0
/*
 * Compiles a substitution pattern
 */
struct rewrite_subst *
rewrite_subst_compile(
		struct rewrite_info *info,
		const char *str
)
{
	size_t subs_len;
	struct berval *subs = NULL, *tmps;
	struct rewrite_submatch *submatch = NULL;

	struct rewrite_subst *s = NULL;

	char *result, *begin, *p;
	int nsub = 0, l;

	assert( info != NULL );
	assert( str != NULL );

	result = strdup( str );
	if ( result == NULL ) {
		return NULL;
	}

	/*
	 * Take care of substitution string
	 */
	for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) {

		/*
		 * Keep only single escapes '%'
		 */
		if (  !IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
			continue;
		} 

		if (  IS_REWRITE_SUBMATCH_ESCAPE( p[ 1 ] ) ) {
			/* Pull &p[1] over p, including the trailing '\0' */
			AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) );
			continue;
		}

		tmps = ( struct berval * )realloc( subs,
				sizeof( struct berval )*( nsub + 1 ) );
		if ( tmps == NULL ) {
			goto cleanup;
		}
		subs = tmps;
		
		/*
		 * I think an `if l > 0' at runtime is better outside than
		 * inside a function call ...
		 */
		l = p - begin;
		if ( l > 0 ) {
			subs_len += l;
			subs[ nsub ].bv_len = l;
			subs[ nsub ].bv_val = malloc( l + 1 );
			if ( subs[ nsub ].bv_val == NULL ) {
				goto cleanup;
			}
			AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
			subs[ nsub ].bv_val[ l ] = '\0';
		} else {
			subs[ nsub ].bv_val = NULL;
			subs[ nsub ].bv_len = 0;
		}
		
		/*
		 * Substitution pattern
		 */
		if ( isdigit( (unsigned char) p[ 1 ] ) ) {
			struct rewrite_submatch *tmpsm;
			int d = p[ 1 ] - '0';

			/*
			 * Add a new value substitution scheme
			 */

			tmpsm = ( struct rewrite_submatch * )realloc( submatch,
					sizeof( struct rewrite_submatch )*( nsub + 1 ) );
			if ( tmpsm == NULL ) {
				goto cleanup;
			}
			submatch = tmpsm;
			submatch[ nsub ].ls_submatch = d;

			/*
			 * If there is no argument, use default
			 * (substitute substring as is)
			 */
			if ( p[ 2 ] != '{' ) {
				submatch[ nsub ].ls_type = 
					REWRITE_SUBMATCH_ASIS;
				submatch[ nsub ].ls_map = NULL;
				begin = ++p + 1;

			} else {
				struct rewrite_map *map;

				submatch[ nsub ].ls_type =
					REWRITE_SUBMATCH_XMAP;

				map = rewrite_xmap_parse( info,
						p + 3, (const char **)&begin );
				if ( map == NULL ) {
					goto cleanup;
				}
				submatch[ nsub ].ls_map = map;
				p = begin - 1;
			}

		/*
		 * Map with args ...
		 */
		} else if ( p[ 1 ] == '{' ) {
			struct rewrite_map *map;
			struct rewrite_submatch *tmpsm;

			map = rewrite_map_parse( info, p + 2,
					(const char **)&begin );
			if ( map == NULL ) {
				goto cleanup;
			}
			p = begin - 1;

			/*
			 * Add a new value substitution scheme
			 */
			tmpsm = ( struct rewrite_submatch * )realloc( submatch,
					sizeof( struct rewrite_submatch )*( nsub + 1 ) );
			if ( tmpsm == NULL ) {
				goto cleanup;
			}
			submatch = tmpsm;
			submatch[ nsub ].ls_type =
				REWRITE_SUBMATCH_MAP_W_ARG;
			submatch[ nsub ].ls_map = map;

		/*
		 * Escape '%' ...
		 */
		} else if ( p[ 1 ] == '%' ) {
			AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) );
			continue;

		} else {
			goto cleanup;
		}

		nsub++;
	}
	
	/*
	 * Last part of string
	 */
	tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
	if ( tmps == NULL ) {
		/*
		 * XXX need to free the value subst stuff!
		 */
		free( subs );
		goto cleanup;
	}
	subs = tmps;
	l = p - begin;
	if ( l > 0 ) {
		subs_len += l;
		subs[ nsub ].bv_len = l;
		subs[ nsub ].bv_val = malloc( l + 1 );
		if ( subs[ nsub ].bv_val == NULL ) {
			free( subs );
			goto cleanup;
		}
		AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
		subs[ nsub ].bv_val[ l ] = '\0';
	} else {
		subs[ nsub ].bv_val = NULL;
		subs[ nsub ].bv_len = 0;
	}

	s = calloc( sizeof( struct rewrite_subst ), 1 );
	if ( s == NULL ) {
		goto cleanup;
	}

	s->lt_subs_len = subs_len;
        s->lt_subs = subs;
        s->lt_num_submatch = nsub;
        s->lt_submatch = submatch;

cleanup:;
	free( result );

	return s;
}
Esempio n. 28
0
/*
 * Substitutes a portion of rewritten string according to substitution
 * pattern using submatches
 */
int
rewrite_subst_apply(
		struct rewrite_info *info,
		struct rewrite_op *op,
		struct rewrite_subst *subst,
		const char *string,
		const regmatch_t *match,
		struct berval *val
)
{
	struct berval *submatch = NULL;
	char *res = NULL;
	int n = 0, l, cl;
	int rc = REWRITE_REGEXEC_OK;

	assert( info != NULL );
	assert( op != NULL );
	assert( subst != NULL );
	assert( string != NULL );
	assert( match != NULL );
	assert( val != NULL );

	assert( val->bv_val == NULL );

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

	/*
	 * Prepare room for submatch expansion
	 */
	if ( subst->lt_num_submatch > 0 ) {
		submatch = calloc( sizeof( struct berval ),
				subst->lt_num_submatch );
		if ( submatch == NULL ) {
			return REWRITE_REGEXEC_ERR;
		}
	}
	
	/*
	 * Resolve submatches (simple subst, map expansion and so).
	 */
	for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
		struct berval	key = { 0, NULL };

		submatch[ n ].bv_val = NULL;
		
		/*
		 * Get key
		 */
		switch ( subst->lt_submatch[ n ].ls_type ) {
		case REWRITE_SUBMATCH_ASIS:
		case REWRITE_SUBMATCH_XMAP:
			rc = submatch_copy( &subst->lt_submatch[ n ],
					string, match, &key );
			if ( rc != REWRITE_SUCCESS ) {
				rc = REWRITE_REGEXEC_ERR;
				goto cleanup;
			}
			break;
			
		case REWRITE_SUBMATCH_MAP_W_ARG:
			switch ( subst->lt_submatch[ n ].ls_map->lm_type ) {
			case REWRITE_MAP_GET_OP_VAR:
			case REWRITE_MAP_GET_SESN_VAR:
			case REWRITE_MAP_GET_PARAM:
				rc = REWRITE_SUCCESS;
				break;

			default:
				rc = rewrite_subst_apply( info, op, 
					subst->lt_submatch[ n ].ls_map->lm_subst,
					string, match, &key);
			}
			
			if ( rc != REWRITE_SUCCESS ) {
				goto cleanup;
			}
			break;

		default:
			Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 );
			rc = REWRITE_ERR;
			break;
		}
		
		if ( rc != REWRITE_SUCCESS ) {
			rc = REWRITE_REGEXEC_ERR;
			goto cleanup;
		}

		/*
		 * Resolve key
		 */
		switch ( subst->lt_submatch[ n ].ls_type ) {
		case REWRITE_SUBMATCH_ASIS:
			submatch[ n ] = key;
			rc = REWRITE_SUCCESS;
			break;
			
		case REWRITE_SUBMATCH_XMAP:
			rc = rewrite_xmap_apply( info, op,
					subst->lt_submatch[ n ].ls_map,
					&key, &submatch[ n ] );
			free( key.bv_val );
			key.bv_val = NULL;
			break;
			
		case REWRITE_SUBMATCH_MAP_W_ARG:
			rc = rewrite_map_apply( info, op,
					subst->lt_submatch[ n ].ls_map,
					&key, &submatch[ n ] );
			free( key.bv_val );
			key.bv_val = NULL;
			break;

		default:
			/*
			 * When implemented, this might return the
                         * exit status of a rewrite context,
                         * which may include a stop, or an
                         * unwilling to perform
                         */
			rc = REWRITE_ERR;
			break;
		}

		if ( rc != REWRITE_SUCCESS ) {
			rc = REWRITE_REGEXEC_ERR;
			goto cleanup;
		}
		
		/*
                 * Increment the length of the resulting string
                 */
		l += submatch[ n ].bv_len;
	}
	
	/*
         * Alloc result buffer
         */
	l += subst->lt_subs_len;
	res = malloc( l + 1 );
	if ( res == NULL ) {
		rc = REWRITE_REGEXEC_ERR;
		goto cleanup;
	}

	/*
	 * Apply submatches (possibly resolved thru maps)
	 */
        for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
		if ( subst->lt_subs[ n ].bv_val != NULL ) {
                	AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
					subst->lt_subs[ n ].bv_len );
			cl += subst->lt_subs[ n ].bv_len;
		}
		AC_MEMCPY( res + cl, submatch[ n ].bv_val, 
				submatch[ n ].bv_len );
		cl += submatch[ n ].bv_len;
	}
	if ( subst->lt_subs[ n ].bv_val != NULL ) {
		AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
				subst->lt_subs[ n ].bv_len );
		cl += subst->lt_subs[ n ].bv_len;
	}
	res[ cl ] = '\0';

	val->bv_val = res;
	val->bv_len = l;

cleanup:;
	if ( submatch ) {
        	for ( ; --n >= 0; ) {
			if ( submatch[ n ].bv_val ) {
				free( submatch[ n ].bv_val );
			}
		}
		free( submatch );
	}

	return rc;
}
Esempio n. 29
0
/* Return values: -1: error, 0: no operation performed or the answer is false,
 * 1: successful operation or the answer is true
 */
int
ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
{
	Sockbuf_IO_Desc		*p;
	int			ret = 0;

	assert( sb != NULL );
	assert( SOCKBUF_VALID( sb ) );

	switch ( opt ) {
		case LBER_SB_OPT_HAS_IO:
			p = sb->sb_iod;
			while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
				p = p->sbiod_next;
			}
   
			if ( p ) {
				ret = 1;
			}
			break;

		case LBER_SB_OPT_GET_FD:
			if ( arg != NULL ) {
				*((ber_socket_t *)arg) = sb->sb_fd;
			}
			ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
			break;

		case LBER_SB_OPT_SET_FD:
			sb->sb_fd = *((ber_socket_t *)arg);
			ret = 1;
			break;

		case LBER_SB_OPT_SET_NONBLOCK:
			ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
				? -1 : 1;
			break;

		case LBER_SB_OPT_DRAIN: {
				/* Drain the data source to enable possible errors (e.g.
				 * TLS) to be propagated to the upper layers
				 */
				char buf[LBER_MIN_BUFF_SIZE];

				do {
					ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
				} while ( ret == sizeof( buf ) );

				ret = 1;
			} break;

		case LBER_SB_OPT_NEEDS_READ:
			ret = ( sb->sb_trans_needs_read ? 1 : 0 );
			break;

		case LBER_SB_OPT_NEEDS_WRITE:
			ret = ( sb->sb_trans_needs_write ? 1 : 0 );
			break;

		case LBER_SB_OPT_GET_MAX_INCOMING:
			if ( arg != NULL ) {
				*((ber_len_t *)arg) = sb->sb_max_incoming;
			}
			ret = 1;
			break;

		case LBER_SB_OPT_SET_MAX_INCOMING:
			sb->sb_max_incoming = *((ber_len_t *)arg);
			ret = 1;
			break;

		case LBER_SB_OPT_UNGET_BUF:
#ifdef LDAP_PF_LOCAL_SENDMSG
			sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
			if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
				AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
					sb->sb_ungetlen );
				ret = 1;
			} else {
				sb->sb_ungetlen = 0;
				ret = -1;
			}
#endif
			break;

		default:
			ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
			break;
   }

	return ret;
}
Esempio n. 30
0
File: idl.c Progetto: 1ack/Impala
int
bdb_idl_fetch_key(
	BackendDB	*be,
	DB			*db,
	DB_TXN		*txn,
	DBT			*key,
	ID			*ids,
	DBC                     **saved_cursor,
	int                     get_flag )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	int rc;
	DBT data, key2, *kptr;
	DBC *cursor;
	ID *i;
	void *ptr;
	size_t len;
	int rc2;
	int flags = bdb->bi_db_opflags | DB_MULTIPLE;
	int opflag;

	/* If using BerkeleyDB 4.0, the buf must be large enough to
	 * grab the entire IDL in one get(), otherwise BDB will leak
	 * resources on subsequent get's.  We can safely call get()
	 * twice - once for the data, and once to get the DB_NOTFOUND
	 * result meaning there's no more data. See ITS#2040 for details.
	 * This bug is fixed in BDB 4.1 so a smaller buffer will work if
	 * stack space is too limited.
	 *
	 * configure now requires Berkeley DB 4.1.
	 */
#if DB_VERSION_FULL < 0x04010000
#	define BDB_ENOUGH 5
#else
	/* We sometimes test with tiny IDLs, and BDB always wants buffers
	 * that are at least one page in size.
	 */
# if BDB_IDL_DB_SIZE < 4096
#   define BDB_ENOUGH 2048
# else
#	define BDB_ENOUGH 1
# endif
#endif
	ID buf[BDB_IDL_DB_SIZE*BDB_ENOUGH];

	char keybuf[16];

	Debug( LDAP_DEBUG_ARGS,
		"bdb_idl_fetch_key: %s\n", 
		bdb_show_key( key, keybuf ), 0, 0 );

	assert( ids != NULL );

	if ( saved_cursor && *saved_cursor ) {
		opflag = DB_NEXT;
	} else if ( get_flag == LDAP_FILTER_GE ) {
		opflag = DB_SET_RANGE;
	} else if ( get_flag == LDAP_FILTER_LE ) {
		opflag = DB_FIRST;
	} else {
		opflag = DB_SET;
	}

	/* only non-range lookups can use the IDL cache */
	if ( bdb->bi_idl_cache_size && opflag == DB_SET ) {
		rc = bdb_idl_cache_get( bdb, db, key, ids );
		if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
	}

	DBTzero( &data );

	data.data = buf;
	data.ulen = sizeof(buf);
	data.flags = DB_DBT_USERMEM;

	/* If we're not reusing an existing cursor, get a new one */
	if( opflag != DB_NEXT ) {
		rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
				"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
			return rc;
		}
	} else {
		cursor = *saved_cursor;
	}
	
	/* If this is a LE lookup, save original key so we can determine
	 * when to stop. If this is a GE lookup, save the key since it
	 * will be overwritten.
	 */
	if ( get_flag == LDAP_FILTER_LE || get_flag == LDAP_FILTER_GE ) {
		DBTzero( &key2 );
		key2.flags = DB_DBT_USERMEM;
		key2.ulen = sizeof(keybuf);
		key2.data = keybuf;
		key2.size = key->size;
		AC_MEMCPY( keybuf, key->data, key->size );
		kptr = &key2;
	} else {
		kptr = key;
	}
	len = key->size;
	rc = cursor->c_get( cursor, kptr, &data, flags | opflag );

	/* skip presence key on range inequality lookups */
	while (rc == 0 && kptr->size != len) {
		rc = cursor->c_get( cursor, kptr, &data, flags | DB_NEXT_NODUP );
	}
	/* If we're doing a LE compare and the new key is greater than
	 * our search key, we're done
	 */
	if (rc == 0 && get_flag == LDAP_FILTER_LE && memcmp( kptr->data,
		key->data, key->size ) > 0 ) {
		rc = DB_NOTFOUND;
	}
	if (rc == 0) {
		i = ids;
		while (rc == 0) {
			u_int8_t *j;

			DB_MULTIPLE_INIT( ptr, &data );
			while (ptr) {
				DB_MULTIPLE_NEXT(ptr, &data, j, len);
				if (j) {
					++i;
					BDB_DISK2ID( j, i );
				}
			}
			rc = cursor->c_get( cursor, key, &data, flags | DB_NEXT_DUP );
		}
		if ( rc == DB_NOTFOUND ) rc = 0;
		ids[0] = i - ids;
		/* On disk, a range is denoted by 0 in the first element */
		if (ids[1] == 0) {
			if (ids[0] != BDB_IDL_RANGE_SIZE) {
				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
					"range size mismatch: expected %d, got %ld\n",
					BDB_IDL_RANGE_SIZE, ids[0], 0 );
				cursor->c_close( cursor );
				return -1;
			}
			BDB_IDL_RANGE( ids, ids[2], ids[3] );
		}
		data.size = BDB_IDL_SIZEOF(ids);
	}

	if ( saved_cursor && rc == 0 ) {
		if ( !*saved_cursor )
			*saved_cursor = cursor;
		rc2 = 0;
	}
	else
		rc2 = cursor->c_close( cursor );
	if (rc2) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"close failed: %s (%d)\n", db_strerror(rc2), rc2, 0 );
		return rc2;
	}

	if( rc == DB_NOTFOUND ) {
		return rc;

	} else if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"get failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
		return rc;

	} else if ( data.size == 0 || data.size % sizeof( ID ) ) {
		/* size not multiple of ID size */
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"odd size: expected %ld multiple, got %ld\n",
			(long) sizeof( ID ), (long) data.size, 0 );
		return -1;

	} else if ( data.size != BDB_IDL_SIZEOF(ids) ) {
		/* size mismatch */
		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
			"get size mismatch: expected %ld, got %ld\n",
			(long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
		return -1;
	}

	if ( bdb->bi_idl_cache_max_size ) {
		bdb_idl_cache_put( bdb, db, key, ids, rc );
	}

	return rc;
}