Ejemplo n.º 1
0
/*
 * ldap_delete_ext - initiate an ldap extended delete operation. Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the object to delete
 *	sctrls	Server Controls
 *	cctrls	Client Controls
 *	msgidp	Message Id Pointer
 *
 * Example:
 *	rc = ldap_delete( ld, dn, sctrls, cctrls, msgidp );
 */
int
ldap_delete_ext(
	LDAP *ld,
	LDAP_CONST char* dn,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	int rc;
	BerElement	*ber;

#ifdef NEW_LOGGING
	LDAP_LOG ( OPERATION, ENTRY, "ldap_delete_ext\n", 0,0,0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_delete_ext\n", 0, 0, 0 );
#endif

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( dn != NULL );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( ld->ld_errno );
	}

	if ( ber_printf( ber, "{its", /* '}' */
		++ld->ld_msgid, LDAP_REQ_DELETE, dn ) == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_DELETE, dn, ber );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}
Ejemplo n.º 2
0
/*
 * ldap_compare_ext - perform an ldap extended compare operation.  The dn
 * of the entry to compare to and the attribute and value to compare (in
 * attr and value) are supplied.  The msgid of the response is returned.
 *
 * Example:
 *	struct berval bvalue = { "secret", sizeof("secret")-1 };
 *	rc = ldap_compare( ld, "c=us@cn=bob",
 *		"userPassword", &bvalue,
 *		sctrl, cctrl, &msgid )
 */
int
ldap_compare_ext(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAP_CONST char *attr,
	struct berval *bvalue,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int	*msgidp )
{
	int rc;
	BerElement	*ber;
	ber_int_t	id;

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

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( dn != NULL );
	assert( attr != NULL );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	LDAP_NEXT_MSGID(ld, id);
	rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */
		id,
		LDAP_REQ_COMPARE, dn, attr, bvalue );
	if ( rc == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}


	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber, id );
	return ( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Ejemplo n.º 3
0
BerElement *
ldap_build_moddn_req(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAP_CONST char *newrdn,
	LDAP_CONST char *newSuperior,
	int deleteoldrdn,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	ber_int_t *msgidp )
{
	BerElement	*ber;
	int rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	LDAP_NEXT_MSGID( ld, *msgidp );
	if( newSuperior != NULL ) {
		/* must be version 3 (or greater) */
		if ( ld->ld_version < LDAP_VERSION3 ) {
			ld->ld_errno = LDAP_NOT_SUPPORTED;
			ber_free( ber, 1 );
			return( NULL );
		}
		rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */
			*msgidp, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn,
			LDAP_TAG_NEWSUPERIOR, newSuperior );

	} else {
		rc = ber_printf( ber, "{it{ssbN}", /* '}' */
			*msgidp, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn );
	}

	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	rc = ber_printf( ber, /*{*/ "N}" );
	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Ejemplo n.º 4
0
int
ldap_create_page_control_value(
    LDAP *ld,
    ber_int_t pagesize,
    struct berval	*cookie,
    struct berval	*value )
{
    BerElement	*ber = NULL;
    ber_tag_t	tag;
    struct berval	null_cookie = { 0, NULL };

    if ( ld == NULL || value == NULL ||
            pagesize < 1 || pagesize > LDAP_MAXINT )
    {
        if ( ld )
            ld->ld_errno = LDAP_PARAM_ERROR;
        return LDAP_PARAM_ERROR;
    }

    assert( LDAP_VALID( ld ) );

    value->bv_val = NULL;
    value->bv_len = 0;
    ld->ld_errno = LDAP_SUCCESS;

    if ( cookie == NULL ) {
        cookie = &null_cookie;
    }

    ber = ldap_alloc_ber_with_options( ld );
    if ( ber == NULL ) {
        ld->ld_errno = LDAP_NO_MEMORY;
        return ld->ld_errno;
    }

    tag = ber_printf( ber, "{iO}", pagesize, cookie );
    if ( tag == LBER_ERROR ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        goto done;
    }

    if ( ber_flatten2( ber, value, 1 ) == -1 ) {
        ld->ld_errno = LDAP_NO_MEMORY;
    }

done:
    ;
    if ( ber != NULL ) {
        ber_free( ber, 1 );
    }

    return ld->ld_errno;
}
Ejemplo n.º 5
0
static ber_tag_t
build_result_ber( LDAP *ld, BerElement **bp, LDAPRequest *lr )
{
	ber_len_t	len;
	ber_tag_t	tag;
	ber_int_t	along;
	BerElement *ber;

	*bp = NULL;
	ber = ldap_alloc_ber_with_options( ld );

	if( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return LBER_ERROR;
	}

	if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid,
		lr->lr_res_msgtype, lr->lr_res_errno,
		lr->lr_res_matched ? lr->lr_res_matched : "",
		lr->lr_res_error ? lr->lr_res_error : "" ) == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	ber_reset( ber, 1 );

	if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	if ( ber_get_enum( ber, &along ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	tag = ber_peek_tag( ber, &len );

	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	*bp = ber;
	return tag;
}
Ejemplo n.º 6
0
Archivo: unbind.c Proyecto: 1ack/Impala
/* FIXME: this function is called only by ldap_free_connection(),
 * which, most of the times, is called with ld_req_mutex locked */
int
ldap_send_unbind(
	LDAP *ld,
	Sockbuf *sb,
	LDAPControl **sctrls,
	LDAPControl **cctrls )
{
	BerElement	*ber;
	ber_int_t	id;

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

#ifdef LDAP_CONNECTIONLESS
	if (LDAP_IS_UDP(ld))
		return LDAP_SUCCESS;
#endif
	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( ld->ld_errno );
	}

	LDAP_NEXT_MSGID(ld, id);

	/* fill it in */
	if ( ber_printf( ber, "{itn" /*}*/, id,
	    LDAP_REQ_UNBIND ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	ld->ld_errno = LDAP_SUCCESS;
	/* send the message */
	if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) {
		ld->ld_errno = LDAP_SERVER_DOWN;
	}

	return( ld->ld_errno );
}
Ejemplo n.º 7
0
/*
 * ldap_kerberos_bind1 - initiate a bind to the ldap server using
 * kerberos authentication.  The dn is supplied.  It is assumed the user
 * already has a valid ticket granting ticket.  The msgid of the
 * request is returned on success (suitable for passing to ldap_result()),
 * -1 is returned if there's trouble.
 *
 * Example:
 *	ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
 */
int
ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn )
{
	BerElement	*ber;
	char		*cred;
	int		rc;
	ber_len_t credlen;
	ber_int_t	id;

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

	if( ld->ld_version > LDAP_VERSION2 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return -1;
	}

	if ( dn == NULL )
		dn = "";

	if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
	    &credlen )) == NULL ) {
		return( -1 );	/* ld_errno should already be set */
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		LDAP_FREE( cred );
		return( -1 );
	}

	LDAP_NEXT_MSGID( ld, id );
	/* fill it in */
	rc = ber_printf( ber, "{it{istoN}N}", id, LDAP_REQ_BIND,
	    ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );

	if ( rc == -1 ) {
		LDAP_FREE( cred );
		ber_free( ber, 1 );
		ld->ld_errno = LDAP_ENCODING_ERROR;
		return( -1 );
	}

	LDAP_FREE( cred );


	/* send the message */
	return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id ));
}
Ejemplo n.º 8
0
int
ldap_create_assertion_control_value(
	LDAP		*ld,
	char		*assertion,
	struct berval	*value )
{
	BerElement		*ber = NULL;
	int			err;

	if ( assertion == NULL || assertion[ 0 ] == '\0' ) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return ld->ld_errno;
	}

	if ( value == NULL ) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return ld->ld_errno;
	}

	BER_BVZERO( value );

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	err = ldap_pvt_put_filter( ber, assertion );
	if ( err < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	err = ber_flatten2( ber, value, 1 );
	if ( err < 0 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		goto done;
	}

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Ejemplo n.º 9
0
BerElement *
ldap_build_compare_req(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAP_CONST char *attr,
	struct berval *bvalue,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int	*msgidp )
{
	BerElement	*ber;
	int rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	LDAP_NEXT_MSGID(ld, *msgidp);
	rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */
		*msgidp,
		LDAP_REQ_COMPARE, dn, attr, bvalue );
	if ( rc == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	if( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Ejemplo n.º 10
0
Archivo: ppolicy.c Proyecto: phpor/otpc
int
ldap_create_passwordpolicy_control( LDAP *ld,
                                    LDAPControl **ctrlp )
{
	BerElement *ber;

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( ctrlp != NULL );

	if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return(LDAP_NO_MEMORY);
	}

	ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
		ber, 0, ctrlp);

	ber_free(ber, 1);
	return(ld->ld_errno);
}
Ejemplo n.º 11
0
int
ldap_create_vlv_control_value(
	LDAP *ld,
	LDAPVLVInfo *vlvinfop,
	struct berval *value )
{
	ber_tag_t tag;
	BerElement *ber;

	if ( ld == NULL || vlvinfop == NULL || value == NULL ) {
		if ( ld )
			ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	assert( LDAP_VALID( ld ) );

	value->bv_val = NULL;
	value->bv_len = 0;
	ld->ld_errno = LDAP_SUCCESS;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{ii" /*}*/,
		vlvinfop->ldvlv_before_count,
		vlvinfop->ldvlv_after_count );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( vlvinfop->ldvlv_attrvalue == NULL ) {
		tag = ber_printf( ber, "t{iiN}",
			LDAP_VLVBYINDEX_IDENTIFIER,
			vlvinfop->ldvlv_offset,
			vlvinfop->ldvlv_count );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}

	} else {
		tag = ber_printf( ber, "tO",
			LDAP_VLVBYVALUE_IDENTIFIER,
			vlvinfop->ldvlv_attrvalue );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	if ( vlvinfop->ldvlv_context ) {
		tag = ber_printf( ber, "tO",
			LDAP_VLVCONTEXT_IDENTIFIER,
			vlvinfop->ldvlv_context );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	tag = ber_printf( ber, /*{*/ "N}" ); 
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

	if ( 0 ) {
error_return:;
		ld->ld_errno = LDAP_ENCODING_ERROR;
	}

	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Ejemplo n.º 12
0
/*
 * ldap_modify_ext - initiate an ldap extended modify operation.
 *
 * Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the object to modify
 *	mods		List of modifications to make.  This is null-terminated
 *			array of struct ldapmod's, specifying the modifications
 *			to perform.
 *	sctrls	Server Controls
 *	cctrls	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*mods[] = { 
 *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_DELETE, "ou", 0 },
 *			{ LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
 *			0
 *		}
 *	rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
 */
int
ldap_modify_ext( LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **mods,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int		i, rc;
	ber_int_t	id;

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

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	LDAP_NEXT_MSGID( ld, id );
	rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn );
	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* allow mods to be NULL ("touch") */
	if ( mods ) {
		/* for each modification to be performed... */
		for ( i = 0; mods[i] != NULL; i++ ) {
			if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
				rc = ber_printf( ber, "{e{s[V]N}N}",
				    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
				    mods[i]->mod_type, mods[i]->mod_bvalues );
			} else {
				rc = ber_printf( ber, "{e{s[v]N}N}",
					(ber_int_t) mods[i]->mod_op,
				    mods[i]->mod_type, mods[i]->mod_values );
			}

			if ( rc == -1 ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				ber_free( ber, 1 );
				return( ld->ld_errno );
			}
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id );
	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Ejemplo n.º 13
0
int
ldap_create_session_tracking_value(
	LDAP		*ld,
	char		*sessionSourceIp,
	char		*sessionSourceName,
	char		*formatOID,
	struct berval	*sessionTrackingIdentifier,
	struct berval	*value )
{
	BerElement	*ber = NULL;
	ber_tag_t	tag;

	struct berval	ip, name, oid, id;

	if ( ld == NULL ||
		formatOID == NULL ||
		value == NULL )
	{
param_error:;
		if ( ld ) {
			ld->ld_errno = LDAP_PARAM_ERROR;
		}

		return LDAP_PARAM_ERROR;
	}

	assert( LDAP_VALID( ld ) );
	ld->ld_errno = LDAP_SUCCESS;

	/* check sizes according to I.D. */
	if ( sessionSourceIp == NULL ) {
		BER_BVSTR( &ip, "" );

	} else {
		ber_str2bv( sessionSourceIp, 0, 0, &ip );
		/* NOTE: we're strict because we don't want
		 * to send out bad data */
		if ( ip.bv_len > 128 ) goto param_error;
	}

	if ( sessionSourceName == NULL ) {
		BER_BVSTR( &name, "" );

	} else {
		ber_str2bv( sessionSourceName, 0, 0, &name );
		/* NOTE: we're strict because we don't want
		 * to send out bad data */
		if ( name.bv_len > 65536 ) goto param_error;
	}

	ber_str2bv( formatOID, 0, 0, &oid );
	/* NOTE: we're strict because we don't want
	 * to send out bad data */
	if ( oid.bv_len > 1024 ) goto param_error;

	if ( sessionTrackingIdentifier == NULL ||
		sessionTrackingIdentifier->bv_val == NULL )
	{
		BER_BVSTR( &id, "" );

	} else {
		id = *sessionTrackingIdentifier;
	}

	/* prepare value */
	value->bv_val = NULL;
	value->bv_len = 0;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Ejemplo n.º 14
0
int
ldap_extended_operation(
	LDAP			*ld,
	LDAP_CONST char	*reqoid,
	struct berval	*reqdata,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp )
{
	BerElement *ber;
	int rc;
	ber_int_t id;

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

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( reqoid != NULL && *reqoid != '\0' );
	assert( msgidp != NULL );

	/* must be version 3 (or greater) */
	if ( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return( ld->ld_errno );
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( ld->ld_errno );
	}

	LDAP_NEXT_MSGID( ld, id );
	if ( reqdata != NULL ) {
		rc = ber_printf( ber, "{it{tstON}", /* '}' */
			id, LDAP_REQ_EXTENDED,
			LDAP_TAG_EXOP_REQ_OID, reqoid,
			LDAP_TAG_EXOP_REQ_VALUE, reqdata );

	} else {
		rc = ber_printf( ber, "{it{tsN}", /* '}' */
			id, LDAP_REQ_EXTENDED,
			LDAP_TAG_EXOP_REQ_OID, reqoid );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id );

	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Ejemplo n.º 15
0
/*
 * ldap_modify_ext - initiate an ldap extended modify operation.
 *
 * Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the object to modify
 *	mods		List of modifications to make.  This is null-terminated
 *			array of struct ldapmod's, specifying the modifications
 *			to perform.
 *	sctrls	Server Controls
 *	cctrls	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*mods[] = { 
 *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
 *			0
 *		}
 *	rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
 */
int
ldap_modify_ext( LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **mods,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int		i, rc;

	/*
	 * A modify request looks like this:
	 *	ModifyRequet ::= SEQUENCE {
	 *		object		DistinguishedName,
	 *		modifications	SEQUENCE OF SEQUENCE {
	 *			operation	ENUMERATED {
	 *				add	(0),
	 *				delete	(1),
	 *				replace	(2)
	 *			},
	 *			modification	SEQUENCE {
	 *				type	AttributeType,
	 *				values	SET OF AttributeValue
	 *			}
	 *		}
	 *	}
	 */

#ifdef NEW_LOGGING
	LDAP_LOG ( OPERATION, ENTRY, "ldap_modify_ext\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );
#endif

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	if ( ber_printf( ber, "{it{s{" /*}}}*/, ++ld->ld_msgid, LDAP_REQ_MODIFY, dn )
	    == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* for each modification to be performed... */
	for ( i = 0; mods[i] != NULL; i++ ) {
		if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
			rc = ber_printf( ber, "{e{s[V]N}N}",
			    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
			    mods[i]->mod_type, mods[i]->mod_bvalues );
		} else {
			rc = ber_printf( ber, "{e{s[v]N}N}",
				(ber_int_t) mods[i]->mod_op,
			    mods[i]->mod_type, mods[i]->mod_values );
		}

		if ( rc == -1 ) {
			ld->ld_errno = LDAP_ENCODING_ERROR;
			ber_free( ber, 1 );
			return( ld->ld_errno );
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber );
	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Ejemplo n.º 16
0
BerElement *
ldap_build_search_req(
    LDAP *ld,
    LDAP_CONST char *base,
    ber_int_t scope,
    LDAP_CONST char *filter,
    char **attrs,
    ber_int_t attrsonly,
    LDAPControl **sctrls,
    LDAPControl **cctrls,
    ber_int_t timelimit,
    ber_int_t sizelimit,
    ber_int_t deref,
    ber_int_t *idp)
{
    BerElement	*ber;
    int		err;

    /*
     * Create the search request.  It looks like this:
     *	SearchRequest := [APPLICATION 3] SEQUENCE {
     *		baseObject	DistinguishedName,
     *		scope		ENUMERATED {
     *			baseObject	(0),
     *			singleLevel	(1),
     *			wholeSubtree	(2)
     *		},
     *		derefAliases	ENUMERATED {
     *			neverDerefaliases	(0),
     *			derefInSearching	(1),
     *			derefFindingBaseObj	(2),
     *			alwaysDerefAliases	(3)
     *		},
     *		sizelimit	INTEGER (0 .. 65535),
     *		timelimit	INTEGER (0 .. 65535),
     *		attrsOnly	BOOLEAN,
     *		filter		Filter,
     *		attributes	SEQUENCE OF AttributeType
     *	}
     * wrapped in an ldap message.
     */

    /* create a message to send */
    if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
        return( NULL );
    }

    if ( base == NULL ) {
        /* no base provided, use session default base */
        base = ld->ld_options.ldo_defbase;

        if ( base == NULL ) {
            /* no session default base, use top */
            base = "";
        }
    }

    LDAP_NEXT_MSGID( ld, *idp );
#ifdef LDAP_CONNECTIONLESS
    if ( LDAP_IS_UDP(ld) ) {
        struct sockaddr sa = {0};
        /* dummy, filled with ldo_peer in request.c */
        err = ber_write( ber, &sa, sizeof( sa ), 0 );
    }
    if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
        char *dn = ld->ld_options.ldo_cldapdn;
        if (!dn) dn = "";
        err = ber_printf( ber, "{ist{seeiib", *idp, dn,
                          LDAP_REQ_SEARCH, base, (ber_int_t) scope,
                          (deref < 0) ? ld->ld_deref : deref,
                          (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
                          (timelimit < 0) ? ld->ld_timelimit : timelimit,
                          attrsonly );
    } else
#endif
    {
        err = ber_printf( ber, "{it{seeiib", *idp,
                          LDAP_REQ_SEARCH, base, (ber_int_t) scope,
                          (deref < 0) ? ld->ld_deref : deref,
                          (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
                          (timelimit < 0) ? ld->ld_timelimit : timelimit,
                          attrsonly );
    }

    if ( err == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    if( filter == NULL ) {
        filter = "(objectclass=*)";
    }

    err = ldap_pvt_put_filter( ber, filter );

    if ( err  == -1 ) {
        ld->ld_errno = LDAP_FILTER_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

#ifdef LDAP_DEBUG
    if ( ldap_debug & LDAP_DEBUG_ARGS ) {
        char	buf[ BUFSIZ ], *ptr = " *";

        if ( attrs != NULL ) {
            int	i, len, rest = sizeof( buf );

            for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) {
                ptr = &buf[ sizeof( buf ) - rest ];
                len = snprintf( ptr, rest, " %s", attrs[ i ] );
                rest -= (len >= 0 ? len : (int) sizeof( buf ));
            }

            if ( rest <= 0 ) {
                AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ],
                           "...(truncated)", STRLENOF( "...(truncated)" ) + 1 );
            }
            ptr = buf;
        }

        Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr, 0,0 );
    }
#endif /* LDAP_DEBUG */

    if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    /* Put Server Controls */
    if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
        ber_free( ber, 1 );
        return( NULL );
    }

    if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    return( ber );
}
Ejemplo n.º 17
0
BerElement *
ldap_build_bind_req(
	LDAP			*ld,
	LDAP_CONST char	*dn,
	LDAP_CONST char	*mechanism,
	struct berval	*cred,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	ber_int_t		*msgidp )
{
	BerElement	*ber;
	int rc;

	if( mechanism == LDAP_SASL_SIMPLE ) {
		if( dn == NULL && cred != NULL && cred->bv_len ) {
			/* use default binddn */
			dn = ld->ld_defbinddn;
		}

	} else if( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return( NULL );
	}

	if ( dn == NULL ) {
		dn = "";
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	LDAP_NEXT_MSGID( ld, *msgidp );
	if( mechanism == LDAP_SASL_SIMPLE ) {
		/* simple bind */
		rc = ber_printf( ber, "{it{istON}" /*}*/,
			*msgidp, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SIMPLE,
			cred );
		
	} else if ( cred == NULL || cred->bv_val == NULL ) {
		/* SASL bind w/o credentials */
		rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/,
			*msgidp, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism );

	} else {
		/* SASL bind w/ credentials */
		rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/,
			*msgidp, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism, cred );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Ejemplo n.º 18
0
static BerElement *
re_encode_request( LDAP *ld,
	BerElement *origber,
	ber_int_t msgid,
	int sref,
	LDAPURLDesc *srv,
	int *type )
{
	/*
	 * XXX this routine knows way too much about how the lber library works!
	 */
	ber_int_t	along;
	ber_tag_t	tag;
	ber_tag_t	rtag;
	ber_int_t	ver;
	ber_int_t	scope;
	int		rc;
	BerElement	tmpber, *ber;
	struct berval		dn;

	Debug( LDAP_DEBUG_TRACE,
	    "re_encode_request: new msgid %ld, new dn <%s>\n",
	    (long) msgid,
		( srv == NULL || srv->lud_dn == NULL) ? "NONE" : srv->lud_dn, 0 );

	tmpber = *origber;

	/*
	 * all LDAP requests are sequences that start with a message id.
	 * For all except delete, this is followed by a sequence that is
	 * tagged with the operation code.  For delete, the provided DN
	 * is not wrapped by a sequence.
	 */
	rtag = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag );

	if ( rtag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return( NULL );
	}

	assert( tag != 0);
	if ( tag == LDAP_REQ_BIND ) {
		/* bind requests have a version number before the DN & other stuff */
		rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn );

	} else if ( tag == LDAP_REQ_DELETE ) {
		/* delete requests don't have a DN wrapping sequence */
		rtag = ber_scanf( &tmpber, "m", &dn );

	} else if ( tag == LDAP_REQ_SEARCH ) {
		/* search requests need to be re-scope-ed */
		rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope );

		if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
			/* use the scope provided in reference */
			scope = srv->lud_scope;

		} else if ( sref ) {
			/* use scope implied by previous operation
			 *   base -> base
			 *   one -> base
			 *   subtree -> subtree
			 *   subordinate -> subtree
			 */
			switch( scope ) {
			default:
			case LDAP_SCOPE_BASE:
			case LDAP_SCOPE_ONELEVEL:
				scope = LDAP_SCOPE_BASE;
				break;
			case LDAP_SCOPE_SUBTREE:
			case LDAP_SCOPE_SUBORDINATE:
				scope = LDAP_SCOPE_SUBTREE;
				break;
			}
		}

	} else {
		rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn );
	}

	if( rtag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return NULL;
	}

	/* restore character zero'd out by ber_scanf*/
	dn.bv_val[dn.bv_len] = tmpber.ber_tag;

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

	if ( srv->lud_dn ) {
		ber_str2bv( srv->lud_dn, 0, 0, &dn );
	}

	if ( tag == LDAP_REQ_BIND ) {
		rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn );
	} else if ( tag == LDAP_REQ_DELETE ) {
		rc = ber_printf( ber, "{itON}", msgid, tag, &dn );
	} else if ( tag == LDAP_REQ_SEARCH ) {
		rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope );
	} else {
		rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn );
	}

	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return NULL;
	}

	if ( tag != LDAP_REQ_DELETE && (
		ber_write(ber, tmpber.ber_ptr, ( tmpber.ber_end - tmpber.ber_ptr ), 0)
		!= ( tmpber.ber_end - tmpber.ber_ptr ) ||
	    ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return NULL;
	}

#ifdef LDAP_DEBUG
	if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
		Debug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n",
		    0, 0, 0 );
		ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 );
	}
#endif /* LDAP_DEBUG */

	*type = tag;	/* return request type */
	return ber;
}
Ejemplo n.º 19
0
static ber_tag_t
try_read1msg(
	LDAP *ld,
	ber_int_t msgid,
	int all,
	LDAPConn **lcp,
	LDAPMessage **result )
{
	BerElement	*ber;
	LDAPMessage	*newmsg, *l, *prev;
	ber_int_t	id;
	int		idx;
	ber_tag_t	tag;
	ber_len_t	len;
	int		foundit = 0;
	LDAPRequest	*lr, *tmplr, dummy_lr = { 0 };
	LDAPConn	*lc;
	BerElement	tmpber;
	int		rc, refer_cnt, hadref, simple_request;
	ber_int_t	lderr;

#ifdef LDAP_CONNECTIONLESS
	LDAPMessage	*tmp = NULL, *chain_head = NULL;
	int		moremsgs = 0, isv2 = 0;
#endif

	assert( ld != NULL );
	assert( lcp != NULL );
	assert( *lcp != NULL );
	
#ifdef LDAP_R_COMPILE
	LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
#endif

	Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
		(void *)ld, msgid, all );

	lc = *lcp;

retry:
	if ( lc->lconn_ber == NULL ) {
		lc->lconn_ber = ldap_alloc_ber_with_options( ld );

		if ( lc->lconn_ber == NULL ) {
			return -1;
		}
	}

	ber = lc->lconn_ber;
	assert( LBER_VALID (ber) );

	/* get the next message */
	sock_errset(0);
#ifdef LDAP_CONNECTIONLESS
	if ( LDAP_IS_UDP(ld) ) {
		struct sockaddr from;
		ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr) );
		if ( ld->ld_options.ldo_version == LDAP_VERSION2 ) isv2 = 1;
	}
nextresp3:
#endif
	tag = ber_get_next( lc->lconn_sb, &len, ber );
	switch ( tag ) {
	case LDAP_TAG_MESSAGE:
		/*
	 	 * We read a complete message.
	 	 * The connection should no longer need this ber.
	 	 */
		lc->lconn_ber = NULL;
		break;

	case LBER_DEFAULT:
#ifdef LDAP_DEBUG		   
		Debug( LDAP_DEBUG_CONNS,
			"ber_get_next failed.\n", 0, 0, 0 );
#endif		   
#ifdef EWOULDBLOCK			
		if ( sock_errno() == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
#ifdef EAGAIN
		if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
		ld->ld_errno = LDAP_SERVER_DOWN;
#ifdef LDAP_R_COMPILE
		ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
		ldap_free_connection( ld, lc, 1, 0 );
#ifdef LDAP_R_COMPILE
		ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
		lc = *lcp = NULL;
		return -1;

	default:
		ld->ld_errno = LDAP_LOCAL_ERROR;
		return -1;
	}

	/* message id */
	if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
		ber_free( ber, 1 );
		ld->ld_errno = LDAP_DECODING_ERROR;
		return( -1 );
	}

	/* id == 0 iff unsolicited notification message (RFC 4511) */

	/* if it's been abandoned, toss it */
	if ( id > 0 ) {
		if ( ldap_abandoned( ld, id, &idx ) ) {
			/* the message type */
			tag = ber_peek_tag( ber, &len );
			switch ( tag ) {
			case LDAP_RES_SEARCH_ENTRY:
			case LDAP_RES_SEARCH_REFERENCE:
			case LDAP_RES_INTERMEDIATE:
			case LBER_ERROR:
				break;

			default:
				/* there's no need to keep the id
				 * in the abandoned list any longer */
				ldap_mark_abandoned( ld, id, idx );
				break;
			}

			Debug( LDAP_DEBUG_ANY,
				"abandoned/discarded ld %p msgid %ld message type %s\n",
				(void *)ld, (long)id, ldap_int_msgtype2str( tag ) );

retry_ber:
			ber_free( ber, 1 );
			if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
				goto retry;
			}
			return( LDAP_MSG_X_KEEP_LOOKING );	/* continue looking */
		}

		lr = ldap_find_request_by_msgid( ld, id );
		if ( lr == NULL ) {
			const char	*msg = "unknown";

			/* the message type */
			tag = ber_peek_tag( ber, &len );
			switch ( tag ) {
			case LBER_ERROR:
				break;

			default:
				msg = ldap_int_msgtype2str( tag );
				break;
			}

			Debug( LDAP_DEBUG_ANY,
				"no request for response on ld %p msgid %ld message type %s (tossing)\n",
				(void *)ld, (long)id, msg );

			goto retry_ber;
		}

#ifdef LDAP_CONNECTIONLESS
		if ( LDAP_IS_UDP(ld) && isv2 ) {
			ber_scanf(ber, "x{");
		}
nextresp2:
#endif
	}

	/* the message type */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( -1 );
	}

	Debug( LDAP_DEBUG_TRACE,
		"read1msg: ld %p msgid %ld message type %s\n",
		(void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) );

	if ( id == 0 ) {
		/* unsolicited notification message (RFC 4511) */
		if ( tag != LDAP_RES_EXTENDED ) {
			/* toss it */
			goto retry_ber;

			/* strictly speaking, it's an error; from RFC 4511:

4.4.  Unsolicited Notification

   An unsolicited notification is an LDAPMessage sent from the server to
   the client that is not in response to any LDAPMessage received by the
   server.  It is used to signal an extraordinary condition in the
   server or in the LDAP session between the client and the server.  The
   notification is of an advisory nature, and the server will not expect
   any response to be returned from the client.

   The unsolicited notification is structured as an LDAPMessage in which
   the messageID is zero and protocolOp is set to the extendedResp
   choice using the ExtendedResponse type (See Section 4.12).  The
   responseName field of the ExtendedResponse always contains an LDAPOID
   that is unique for this notification.

			 * however, since unsolicited responses
			 * are of advisory nature, better
			 * toss it, right now
			 */

#if 0
			ld->ld_errno = LDAP_DECODING_ERROR;
			ber_free( ber, 1 );
			return( -1 );
#endif
		}

		lr = &dummy_lr;
	}

	id = lr->lr_origid;
	refer_cnt = 0;
	hadref = simple_request = 0;
	rc = LDAP_MSG_X_KEEP_LOOKING;	/* default is to keep looking (no response found) */
	lr->lr_res_msgtype = tag;

	/*
	 * Check for V3 search reference
	 */
	if ( tag == LDAP_RES_SEARCH_REFERENCE ) {
		if ( ld->ld_version > LDAP_VERSION2 ) {
			/* This is a V3 search reference */
			if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
					lr->lr_parent != NULL )
			{
				char **refs = NULL;
				tmpber = *ber;

				/* Get the referral list */
				if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
					rc = LDAP_DECODING_ERROR;

				} else {
					/* Note: refs array is freed by ldap_chase_v3referrals */
					refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
						1, &lr->lr_res_error, &hadref );
					if ( refer_cnt > 0 ) {
						/* successfully chased reference */
						/* If haven't got end search, set chasing referrals */
						if ( lr->lr_status != LDAP_REQST_COMPLETED ) {
							lr->lr_status = LDAP_REQST_CHASINGREFS;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg:  search ref chased, "
								"mark request chasing refs, "
								"id = %d\n",
								lr->lr_msgid, 0, 0 );
						}
					}
				}
			}
		}

	} else if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) {
		/* All results that just return a status, i.e. don't return data
		 * go through the following code.  This code also chases V2 referrals
		 * and checks if all referrals have been chased.
		 */
		char		*lr_res_error = NULL;

		tmpber = *ber; 	/* struct copy */
		if ( ber_scanf( &tmpber, "{eAA", &lderr,
				&lr->lr_res_matched, &lr_res_error )
				!= LBER_ERROR )
		{
			if ( lr_res_error != NULL ) {
				if ( lr->lr_res_error != NULL ) {
					(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
					LDAP_FREE( (char *)lr_res_error );

				} else {
					lr->lr_res_error = lr_res_error;
				}
				lr_res_error = NULL;
			}

			/* Do we need to check for referrals? */
			if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
					lr->lr_parent != NULL )
			{
				char		**refs = NULL;
				ber_len_t	len;

				/* Check if V3 referral */
				if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) {
					if ( ld->ld_version > LDAP_VERSION2 ) {
						/* Get the referral list */
						if ( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) {
							rc = LDAP_DECODING_ERROR;
							lr->lr_status = LDAP_REQST_COMPLETED;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg: referral decode error, "
								"mark request completed, ld %p msgid %d\n",
								(void *)ld, lr->lr_msgid, 0 );

						} else {
							/* Chase the referral 
							 * refs array is freed by ldap_chase_v3referrals
							 */
							refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
								0, &lr->lr_res_error, &hadref );
							lr->lr_status = LDAP_REQST_COMPLETED;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg: referral %s chased, "
								"mark request completed, ld %p msgid %d\n",
								refer_cnt > 0 ? "" : "not",
								(void *)ld, lr->lr_msgid);
							if ( refer_cnt < 0 ) {
								refer_cnt = 0;
							}
						}
					}
				} else {
					switch ( lderr ) {
					case LDAP_SUCCESS:
					case LDAP_COMPARE_TRUE:
					case LDAP_COMPARE_FALSE:
						break;

					default:
						if ( lr->lr_res_error == NULL ) {
							break;
						}

						/* pedantic, should never happen */
						if ( lr->lr_res_error[ 0 ] == '\0' ) {
							LDAP_FREE( lr->lr_res_error );
							lr->lr_res_error = NULL;
							break;	
						}

						/* V2 referrals are in error string */
						refer_cnt = ldap_chase_referrals( ld, lr,
							&lr->lr_res_error, -1, &hadref );
						lr->lr_status = LDAP_REQST_COMPLETED;
						Debug( LDAP_DEBUG_TRACE,
							"read1msg:  V2 referral chased, "
							"mark request completed, id = %d\n",
							lr->lr_msgid, 0, 0 );
						break;
					}
				}
			}

			/* save errno, message, and matched string */
			if ( !hadref || lr->lr_res_error == NULL ) {
				lr->lr_res_errno =
					lderr == LDAP_PARTIAL_RESULTS
					? LDAP_SUCCESS : lderr;

			} else if ( ld->ld_errno != LDAP_SUCCESS ) {
				lr->lr_res_errno = ld->ld_errno;

			} else {
				lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
			}
		}

		/* in any case, don't leave any lr_res_error 'round */
		if ( lr_res_error ) {
			LDAP_FREE( lr_res_error );
		}

		Debug( LDAP_DEBUG_TRACE,
			"read1msg: ld %p %d new referrals\n",
			(void *)ld, refer_cnt, 0 );

		if ( refer_cnt != 0 ) {	/* chasing referrals */
			ber_free( ber, 1 );
			ber = NULL;
			if ( refer_cnt < 0 ) {
				ldap_return_request( ld, lr, 0 );
				return( -1 );	/* fatal error */
			}
			lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */

		} else {
			if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
				/* request without any referrals */
				simple_request = ( hadref ? 0 : 1 );

			} else {
				/* request with referrals or child request */
				ber_free( ber, 1 );
				ber = NULL;
			}

			lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */
			Debug( LDAP_DEBUG_TRACE,
				"read1msg:  mark request completed, ld %p msgid %d\n",
				(void *)ld, lr->lr_msgid, 0);
			while ( lr->lr_parent != NULL ) {
				merge_error_info( ld, lr->lr_parent, lr );

				lr = lr->lr_parent;
				if ( --lr->lr_outrefcnt > 0 ) {
					break;	/* not completely done yet */
				}
			}

			/* Check if all requests are finished, lr is now parent */
			tmplr = lr;
			if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) {
				for ( tmplr = lr->lr_child;
					tmplr != NULL;
					tmplr = tmplr->lr_refnext )
				{
					if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break;
				}
			}

			/* This is the parent request if the request has referrals */
			if ( lr->lr_outrefcnt <= 0 &&
				lr->lr_parent == NULL &&
				tmplr == NULL )
			{
				id = lr->lr_msgid;
				tag = lr->lr_res_msgtype;
				Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %ld\n",
					(void *)ld, (long) id, 0 );
				Debug( LDAP_DEBUG_TRACE,
					"res_errno: %d, res_error: <%s>, "
					"res_matched: <%s>\n",
					lr->lr_res_errno,
					lr->lr_res_error ? lr->lr_res_error : "",
					lr->lr_res_matched ? lr->lr_res_matched : "" );
				if ( !simple_request ) {
					ber_free( ber, 1 );
					ber = NULL;
					if ( build_result_ber( ld, &ber, lr )
					    == LBER_ERROR )
					{
						rc = -1; /* fatal error */
					}
				}

				if ( lr != &dummy_lr ) {
					ldap_return_request( ld, lr, 1 );
				}
				lr = NULL;
			}

			/*
			 * RF 4511 unsolicited (id == 0) responses
			 * shouldn't necessarily end the connection
			 */
			if ( lc != NULL && id != 0 ) {
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
				ldap_free_connection( ld, lc, 0, 1 );
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
				lc = *lcp = NULL;
			}
		}
	}

	if ( lr != NULL ) {
		if ( lr != &dummy_lr ) {
			ldap_return_request( ld, lr, 0 );
		}
		lr = NULL;
	}

	if ( ber == NULL ) {
		return( rc );
	}

	/* try to handle unsolicited responses as appropriate */
	if ( id == 0 && msgid > LDAP_RES_UNSOLICITED ) {
		int	is_nod = 0;

		tag = ber_peek_tag( &tmpber, &len );

		/* we have a res oid */
		if ( tag == LDAP_TAG_EXOP_RES_OID ) {
			static struct berval	bv_nod = BER_BVC( LDAP_NOTICE_OF_DISCONNECTION );
			struct berval		resoid = BER_BVNULL;

			if ( ber_scanf( &tmpber, "m", &resoid ) == LBER_ERROR ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 1 );
				return -1;
			}

			assert( !BER_BVISEMPTY( &resoid ) );

			is_nod = ber_bvcmp( &resoid, &bv_nod ) == 0;

			tag = ber_peek_tag( &tmpber, &len );
		}

#if 0 /* don't need right now */
		/* we have res data */
		if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
			struct berval resdata;

			if ( ber_scanf( &tmpber, "m", &resdata ) == LBER_ERROR ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 0 );
				return ld->ld_errno;
			}

			/* use it... */
		}
#endif

		/* handle RFC 4511 "Notice of Disconnection" locally */

		if ( is_nod ) {
			if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 1 );
				return -1;
			}

			/* get rid of the connection... */
			if ( lc != NULL ) {
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
				ldap_free_connection( ld, lc, 0, 1 );
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
				lc = *lcp = NULL;
			}

			/* need to return -1, because otherwise
			 * a valid result is expected */
			return -1;
		}
	}

	/* make a new ldap message */
	newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) );
	if ( newmsg == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( -1 );
	}
	newmsg->lm_msgid = (int)id;
	newmsg->lm_msgtype = tag;
	newmsg->lm_ber = ber;
	newmsg->lm_chain_tail = newmsg;

#ifdef LDAP_CONNECTIONLESS
	/* CLDAP replies all fit in a single datagram. In LDAPv2 RFC1798
	 * the responses are all a sequence wrapped in one message. In
	 * LDAPv3 each response is in its own message. The datagram must
	 * end with a SearchResult. We can't just parse each response in
	 * separate calls to try_read1msg because the header info is only
	 * present at the beginning of the datagram, not at the beginning
	 * of each response. So parse all the responses at once and queue
	 * them up, then pull off the first response to return to the
	 * caller when all parsing is complete.
	 */
	if ( LDAP_IS_UDP(ld) ) {
		/* If not a result, look for more */
		if ( tag != LDAP_RES_SEARCH_RESULT ) {
			int ok = 0;
			moremsgs = 1;
			if (isv2) {
				/* LDAPv2: dup the current ber, skip past the current
				 * response, and see if there are any more after it.
				 */
				ber = ber_dup( ber );
				ber_scanf( ber, "x" );
				if ( ber_peek_tag( ber, &len ) != LBER_DEFAULT ) {
					/* There's more - dup the ber buffer so they can all be
					 * individually freed by ldap_msgfree.
					 */
					struct berval bv;
					ber_get_option( ber, LBER_OPT_BER_REMAINING_BYTES, &len );
					bv.bv_val = LDAP_MALLOC( len );
					if ( bv.bv_val ) {
						ok = 1;
						ber_read( ber, bv.bv_val, len );
						bv.bv_len = len;
						ber_init2( ber, &bv, ld->ld_lberoptions );
					}
				}
			} else {
				/* LDAPv3: Just allocate a new ber. Since this is a buffered
				 * datagram, if the sockbuf is readable we still have data
				 * to parse.
				 */
				ber = ldap_alloc_ber_with_options( ld );
				if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) ok = 1;
			}
			/* set up response chain */
			if ( tmp == NULL ) {
				newmsg->lm_next = ld->ld_responses;
				ld->ld_responses = newmsg;
				chain_head = newmsg;
			} else {
				tmp->lm_chain = newmsg;
			}
			chain_head->lm_chain_tail = newmsg;
			tmp = newmsg;
			/* "ok" means there's more to parse */
			if ( ok ) {
				if ( isv2 ) {
					goto nextresp2;

				} else {
					goto nextresp3;
				}
			} else {
				/* got to end of datagram without a SearchResult. Free
				 * our dup'd ber, but leave any buffer alone. For v2 case,
				 * the previous response is still using this buffer. For v3,
				 * the new ber has no buffer to free yet.
				 */
				ber_free( ber, 0 );
				return -1;
			}
		} else if ( moremsgs ) {
		/* got search result, and we had multiple responses in 1 datagram.
		 * stick the result onto the end of the chain, and then pull the
		 * first response off the head of the chain.
		 */
			tmp->lm_chain = newmsg;
			chain_head->lm_chain_tail = newmsg;
			*result = chkResponseList( ld, msgid, all );
			ld->ld_errno = LDAP_SUCCESS;
			return( (*result)->lm_msgtype );
		}
	}
#endif /* LDAP_CONNECTIONLESS */

	/* is this the one we're looking for? */
	if ( msgid == LDAP_RES_ANY || id == msgid ) {
		if ( all == LDAP_MSG_ONE
			|| ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT
			    	&& newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY
			  	&& newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) )
		{
			*result = newmsg;
			ld->ld_errno = LDAP_SUCCESS;
			return( tag );

		} else if ( newmsg->lm_msgtype == LDAP_RES_SEARCH_RESULT) {
			foundit = 1;	/* return the chain later */
		}
	}

	/* 
	 * if not, we must add it to the list of responses.  if
	 * the msgid is already there, it must be part of an existing
	 * search response.
	 */

	prev = NULL;
	for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {
		if ( l->lm_msgid == newmsg->lm_msgid ) {
			break;
		}
		prev = l;
	}

	/* not part of an existing search response */
	if ( l == NULL ) {
		if ( foundit ) {
			*result = newmsg;
			goto exit;
		}

		newmsg->lm_next = ld->ld_responses;
		ld->ld_responses = newmsg;
		goto exit;
	}

	Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %ld type %ld:\n",
		(void *)ld, (long) newmsg->lm_msgid, (long) newmsg->lm_msgtype );

	/* part of a search response - add to end of list of entries */
	l->lm_chain_tail->lm_chain = newmsg;
	l->lm_chain_tail = newmsg;

	/* return the whole chain if that's what we were looking for */
	if ( foundit ) {
		if ( prev == NULL ) {
			ld->ld_responses = l->lm_next;
		} else {
			prev->lm_next = l->lm_next;
		}
		*result = l;
	}

exit:
	if ( foundit ) {
		ld->ld_errno = LDAP_SUCCESS;
		return( tag );
	}
	if ( lc && ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
		goto retry;
	}
	return( LDAP_MSG_X_KEEP_LOOKING );	/* continue looking */
}


static ber_tag_t
build_result_ber( LDAP *ld, BerElement **bp, LDAPRequest *lr )
{
	ber_len_t	len;
	ber_tag_t	tag;
	ber_int_t	along;
	BerElement *ber;

	*bp = NULL;
	ber = ldap_alloc_ber_with_options( ld );

	if( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return LBER_ERROR;
	}

	if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid,
		lr->lr_res_msgtype, lr->lr_res_errno,
		lr->lr_res_matched ? lr->lr_res_matched : "",
		lr->lr_res_error ? lr->lr_res_error : "" ) == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	ber_reset( ber, 1 );

	if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	if ( ber_get_enum( ber, &along ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	tag = ber_peek_tag( ber, &len );

	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	*bp = ber;
	return tag;
}
Ejemplo n.º 20
0
BerElement *
ldap_build_modify_req(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **mods,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	ber_int_t *msgidp )
{
	BerElement	*ber;
	int		i, rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	LDAP_NEXT_MSGID( ld, *msgidp );
	rc = ber_printf( ber, "{it{s{" /*}}}*/, *msgidp, LDAP_REQ_MODIFY, dn );
	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* allow mods to be NULL ("touch") */
	if ( mods ) {
		/* for each modification to be performed... */
		for ( i = 0; mods[i] != NULL; i++ ) {
			if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
				rc = ber_printf( ber, "{e{s[V]N}N}",
				    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
				    mods[i]->mod_type, mods[i]->mod_bvalues );
			} else {
				rc = ber_printf( ber, "{e{s[v]N}N}",
					(ber_int_t) mods[i]->mod_op,
				    mods[i]->mod_type, mods[i]->mod_values );
			}

			if ( rc == -1 ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				ber_free( ber, 1 );
				return( NULL );
			}
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Ejemplo n.º 21
0
int
ldap_create_sort_control (
	LDAP *ld,
	LDAPSortKey **keyList,
	int isCritical,
	LDAPControl **ctrlp )
{
	int         i;
	BerElement  *ber;
	ber_tag_t tag;


	if ( (ld == NULL) || (keyList == NULL) || (ctrlp == NULL) ) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return(ld->ld_errno);
	}

	if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( ld->ld_errno );
	}

	tag = ber_printf(ber, "{" /*}*/);
	if (tag == LBER_ERROR) goto exit;

	for (i = 0; keyList[i] != NULL; i++) {
		tag = ber_printf(ber, "{s" /*}*/, (keyList[i])->attributeType);
		if (tag == LBER_ERROR) goto exit;

		if ((keyList[i])->orderingRule != NULL) {
			tag = ber_printf( ber, "ts",
				LDAP_MATCHRULE_IDENTIFIER,
				(keyList[i])->orderingRule );

			if( tag == LBER_ERROR ) goto exit;
		}

		if ((keyList[i])->reverseOrder) {
			tag = ber_printf(ber, "tb",
				LDAP_REVERSEORDER_IDENTIFIER,
				(keyList[i])->reverseOrder );

			if( tag == LBER_ERROR ) goto exit;
		}

		tag = ber_printf(ber, /*{*/ "N}");
		if( tag == LBER_ERROR ) goto exit;
	}

	tag = ber_printf(ber, /*{*/ "N}");
	if( tag == LBER_ERROR ) goto exit;

	ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST,
		ber, isCritical, ctrlp);

	ber_free(ber, 1);

	return(ld->ld_errno);

exit:
	ber_free(ber, 1);
	ld->ld_errno =  LDAP_ENCODING_ERROR;
	return(ld->ld_errno);
}
Ejemplo n.º 22
0
BerElement *
ldap_build_search_req(
	LDAP *ld,
	LDAP_CONST char *base,
	ber_int_t scope,
	LDAP_CONST char *filter,
	char **attrs,
	ber_int_t attrsonly,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	ber_int_t timelimit,
	ber_int_t sizelimit )
{
	BerElement	*ber;
	int		err;

	/*
	 * Create the search request.  It looks like this:
	 *	SearchRequest := [APPLICATION 3] SEQUENCE {
	 *		baseObject	DistinguishedName,
	 *		scope		ENUMERATED {
	 *			baseObject	(0),
	 *			singleLevel	(1),
	 *			wholeSubtree	(2)
	 *		},
	 *		derefAliases	ENUMERATED {
	 *			neverDerefaliases	(0),
	 *			derefInSearching	(1),
	 *			derefFindingBaseObj	(2),
	 *			alwaysDerefAliases	(3)
	 *		},
	 *		sizelimit	INTEGER (0 .. 65535),
	 *		timelimit	INTEGER (0 .. 65535),
	 *		attrsOnly	BOOLEAN,
	 *		filter		Filter,
	 *		attributes	SEQUENCE OF AttributeType
	 *	}
	 * wrapped in an ldap message.
	 */

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	if ( base == NULL ) {
		/* no base provided, use session default base */
		base = ld->ld_options.ldo_defbase;

		if ( base == NULL ) {
			/* no session default base, use top */
			base = "";
		}
	}

#ifdef LDAP_CONNECTIONLESS
	if ( LDAP_IS_UDP(ld) ) {
	    err = ber_write( ber, ld->ld_options.ldo_peer,
		    sizeof(struct sockaddr), 0);
	}
	if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
	    char *dn = ld->ld_options.ldo_cldapdn;
	    if (!dn) dn = "";
	    err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, dn,
		LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
		(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
		(timelimit < 0) ? ld->ld_timelimit : timelimit,
		attrsonly );
	} else
#endif
	{
	    err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
		LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
		(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
		(timelimit < 0) ? ld->ld_timelimit : timelimit,
		attrsonly );
	}

	if ( err == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	if( filter == NULL ) {
		filter = "(objectclass=*)";
	}

	err = ldap_pvt_put_filter( ber, filter );

	if ( err  == -1 ) {
		ld->ld_errno = LDAP_FILTER_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Ejemplo n.º 23
0
int
ldap_rename(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAP_CONST char *newrdn,
	LDAP_CONST char *newSuperior,
	int deleteoldrdn,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int rc;
	ber_int_t id;

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

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	LDAP_NEXT_MSGID( ld, id );
	if( newSuperior != NULL ) {
		/* must be version 3 (or greater) */
		if ( ld->ld_version < LDAP_VERSION3 ) {
			ld->ld_errno = LDAP_NOT_SUPPORTED;
			ber_free( ber, 1 );
			return( ld->ld_errno );
		}
		rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ 
			id, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn,
			LDAP_TAG_NEWSUPERIOR, newSuperior );

	} else {
		rc = ber_printf( ber, "{it{ssbN}", /* '}' */ 
			id, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn );
	}

	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	rc = ber_printf( ber, /*{*/ "N}" );
	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id );
	
	if( *msgidp < 0 ) {
		return( ld->ld_errno );
	}

	return LDAP_SUCCESS;
}
Ejemplo n.º 24
0
static int
do_abandon(
	LDAP *ld,
	ber_int_t origid,
	ber_int_t msgid,
	LDAPControl **sctrls,
	LDAPControl **cctrls)
{
	BerElement	*ber;
	int		i, err, sendabandon;
	ber_int_t *old_abandon;
	Sockbuf		*sb;
	LDAPRequest	*lr;

#ifdef NEW_LOGGING
	LDAP_LOG ( OPERATION, ARGS, "do_abandon %d, msgid %d\n", origid, msgid, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
		origid, msgid, 0 );
#endif

	sendabandon = 1;

	/* find the request that we are abandoning */
	for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
		if ( lr->lr_msgid == msgid ) {	/* this message */
			break;
		}
		if ( lr->lr_origid == msgid ) {/* child:  abandon it */
			(void) do_abandon( ld,
				msgid, lr->lr_msgid, sctrls, cctrls );
		}
	}

	if ( lr != NULL ) {
		if ( origid == msgid && lr->lr_parent != NULL ) {
			/* don't let caller abandon child requests! */
			ld->ld_errno = LDAP_PARAM_ERROR;
			return( LDAP_PARAM_ERROR );
		}
		if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
			/* no need to send abandon message */
			sendabandon = 0;
		}
	}

	if ( ldap_msgdelete( ld, msgid ) == 0 ) {
		ld->ld_errno = LDAP_SUCCESS;
		return LDAP_SUCCESS;
	}

	err = 0;
	if ( sendabandon ) {
		if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
			/* not connected */
			err = -1;
			ld->ld_errno = LDAP_SERVER_DOWN;

		} else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
			/* BER element alocation failed */
			err = -1;
			ld->ld_errno = LDAP_NO_MEMORY;

		} else {
#ifdef LDAP_CONNECTIONLESS
			if ( LDAP_IS_UDP(ld) ) {
			    err = ber_write( ber, ld->ld_options.ldo_peer,
				sizeof(struct sockaddr), 0);
			}
			if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
				LDAP_VERSION2) {
			    char *dn = ld->ld_options.ldo_cldapdn;
			    if (!dn) dn = "";
			    err = ber_printf( ber, "{isti",  /* '}' */
				++ld->ld_msgid, dn,
				LDAP_REQ_ABANDON, msgid );
			} else
#endif
			{
			    /* create a message to send */
			    err = ber_printf( ber, "{iti",  /* '}' */
				++ld->ld_msgid,
				LDAP_REQ_ABANDON, msgid );
			}

			if( err == -1 ) {
				/* encoding error */
				ld->ld_errno = LDAP_ENCODING_ERROR;

			} else {
				/* Put Server Controls */
				if ( ldap_int_put_controls( ld, sctrls, ber )
					!= LDAP_SUCCESS )
				{
					err = -1;

				} else {
					/* close '{' */
					err = ber_printf( ber, /*{*/ "N}" );

					if( err == -1 ) {
						/* encoding error */
						ld->ld_errno = LDAP_ENCODING_ERROR;
					}
				}
			}

			if ( err == -1 ) {
				ber_free( ber, 1 );

			} else {
				/* send the message */
				if ( lr != NULL ) {
					sb = lr->lr_conn->lconn_sb;
				} else {
					sb = ld->ld_sb;
				}

				if ( ber_flush( sb, ber, 1 ) != 0 ) {
					ld->ld_errno = LDAP_SERVER_DOWN;
					err = -1;
				} else {
					err = 0;
				}
			}
		}
	}

	if ( lr != NULL ) {
		if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
			ldap_free_connection( ld, lr->lr_conn, 0, 1 );
		}
		if ( origid == msgid ) {
			ldap_free_request( ld, lr );
		}
	}

	i = 0;
	if ( ld->ld_abandoned != NULL ) {
		for ( ; ld->ld_abandoned[i] != -1; i++ )
			;	/* NULL */
	}

	old_abandon = ld->ld_abandoned;

	ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)
		ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) );
		
	if ( ld->ld_abandoned == NULL ) {
		ld->ld_abandoned = old_abandon;
		ld->ld_errno = LDAP_NO_MEMORY;
		return( ld->ld_errno );
	}

	ld->ld_abandoned[i] = msgid;
	ld->ld_abandoned[i + 1] = -1;

	if ( err != -1 ) {
		ld->ld_errno = LDAP_SUCCESS;
	}

	return( ld->ld_errno );
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
Archivo: add.c Proyecto: dago/openldap
/*
 * ldap_add_ext - initiate an ldap extended add operation.  Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the entry to add
 *	mods		List of attributes for the entry.  This is a null-
 *			terminated array of pointers to LDAPMod structures.
 *			only the type and values in the structures need be
 *			filled in.
 *	sctrl	Server Controls
 *	cctrl	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*attrs[] = { 
 *			{ 0, "cn", { "babs jensen", "babs", 0 } },
 *			{ 0, "sn", { "jensen", 0 } },
 *			{ 0, "objectClass", { "person", 0 } },
 *			0
 *		}
 *	rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );
 */
int
ldap_add_ext(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **attrs,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int	*msgidp )
{
	BerElement	*ber;
	int		i, rc;
	ber_int_t	id;

	Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 );
	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( dn != NULL );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	LDAP_NEXT_MSGID(ld, id);
	rc = ber_printf( ber, "{it{s{", /* '}}}' */
		id, LDAP_REQ_ADD, dn );

	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* allow attrs to be NULL ("touch"; should fail...) */
	if ( attrs ) {
		/* for each attribute in the entry... */
		for ( i = 0; attrs[i] != NULL; i++ ) {
			if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
				int j;

				if ( attrs[i]->mod_bvalues == NULL ) {
					ld->ld_errno = LDAP_PARAM_ERROR;
					ber_free( ber, 1 );
					return ld->ld_errno;
				}

				for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) {
					if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) {
						ld->ld_errno = LDAP_PARAM_ERROR;
						ber_free( ber, 1 );
						return ld->ld_errno;
					}
				}

				rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type,
				    attrs[i]->mod_bvalues );

			} else {
				if ( attrs[i]->mod_values == NULL ) {
					ld->ld_errno = LDAP_PARAM_ERROR;
					ber_free( ber, 1 );
					return ld->ld_errno;
				}

				rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type,
				    attrs[i]->mod_values );
			}
			if ( rc == -1 ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				ber_free( ber, 1 );
				return ld->ld_errno;
			}
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}
Ejemplo n.º 27
0
int
ldap_create_sort_control_value(
	LDAP *ld,
	LDAPSortKey **keyList,
	struct berval *value )
{
	int		i;
	BerElement	*ber = NULL;
	ber_tag_t	tag;

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

	if ( ld == NULL ) return LDAP_PARAM_ERROR;
	if ( keyList == NULL || value == NULL ) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	value->bv_val = NULL;
	value->bv_len = 0;
	ld->ld_errno = LDAP_SUCCESS;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{" /*}*/ );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	for ( i = 0; keyList[i] != NULL; i++ ) {
		tag = ber_printf( ber, "{s" /*}*/, keyList[i]->attributeType );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}

		if ( keyList[i]->orderingRule != NULL ) {
			tag = ber_printf( ber, "ts",
				LDAP_MATCHRULE_IDENTIFIER,
				keyList[i]->orderingRule );

			if ( tag == LBER_ERROR ) {
				goto error_return;
			}
		}

		if ( keyList[i]->reverseOrder ) {
			tag = ber_printf( ber, "tb",
				LDAP_REVERSEORDER_IDENTIFIER,
				keyList[i]->reverseOrder );

			if ( tag == LBER_ERROR ) {
				goto error_return;
			}
		}

		tag = ber_printf( ber, /*{*/ "N}" );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	tag = ber_printf( ber, /*{*/ "N}" );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

	if ( 0 ) {
error_return:;
		ld->ld_errno =  LDAP_ENCODING_ERROR;
	}

	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Ejemplo n.º 28
0
int
ldap_sasl_bind(
	LDAP			*ld,
	LDAP_CONST char	*dn,
	LDAP_CONST char	*mechanism,
	struct berval	*cred,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp )
{
	BerElement	*ber;
	int rc;

#ifdef NEW_LOGGING
	LDAP_LOG ( TRANSPORT, ENTRY, "ldap_sasl_bind\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
#endif

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	if( mechanism == LDAP_SASL_SIMPLE ) {
		if( dn == NULL && cred != NULL && cred->bv_len ) {
			/* use default binddn */
			dn = ld->ld_defbinddn;
		}

	} else if( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return ld->ld_errno;
	}

	if ( dn == NULL ) {
		dn = "";
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	assert( LBER_VALID( ber ) );

	if( mechanism == LDAP_SASL_SIMPLE ) {
		/* simple bind */
		rc = ber_printf( ber, "{it{istON}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SIMPLE,
			cred );
		
	} else if ( cred == NULL || cred->bv_val == NULL ) {
		/* SASL bind w/o creditials */
		rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism );

	} else {
		/* SASL bind w/ creditials */
		rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism, cred );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( -1 );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}


	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}
Ejemplo n.º 29
0
static int
do_abandon(
	LDAP *ld,
	ber_int_t origid,
	ber_int_t msgid,
	LDAPControl **sctrls,
	int sendabandon )
{
	BerElement	*ber;
	int		i, err;
	Sockbuf		*sb;
	LDAPRequest	*lr;

	Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
		origid, msgid, 0 );

	/* find the request that we are abandoning */
start_again:;
	lr = ld->ld_requests;
	while ( lr != NULL ) {
		/* this message */
		if ( lr->lr_msgid == msgid ) {
			break;
		}

		/* child: abandon it */
		if ( lr->lr_origid == msgid && !lr->lr_abandoned ) {
			(void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
				sctrls, sendabandon );

			/* restart, as lr may now be dangling... */
			goto start_again;
		}

		lr = lr->lr_next;
	}

	if ( lr != NULL ) {
		if ( origid == msgid && lr->lr_parent != NULL ) {
			/* don't let caller abandon child requests! */
			ld->ld_errno = LDAP_PARAM_ERROR;
			return( LDAP_PARAM_ERROR );
		}
		if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
			/* no need to send abandon message */
			sendabandon = 0;
		}
	}

	/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
	 * while we're in there.
	 */
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
	err = ldap_msgdelete( ld, msgid );
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
	if ( err == 0 ) {
		ld->ld_errno = LDAP_SUCCESS;
		return LDAP_SUCCESS;
	}

	/* fetch again the request that we are abandoning */
	if ( lr != NULL ) {
		for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
			/* this message */
			if ( lr->lr_msgid == msgid ) {
				break;
			}
		}
	}

	err = 0;
	if ( sendabandon ) {
		if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
			/* not connected */
			err = -1;
			ld->ld_errno = LDAP_SERVER_DOWN;

		} else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
			/* BER element allocation failed */
			err = -1;
			ld->ld_errno = LDAP_NO_MEMORY;

		} else {
			/*
			 * We already have the mutex in LDAP_R_COMPILE, so
			 * don't try to get it again.
			 *		LDAP_NEXT_MSGID(ld, i);
			 */

			i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
			if ( LDAP_IS_UDP(ld) ) {
				struct sockaddr sa = {0};
				/* dummy, filled with ldo_peer in request.c */
				err = ber_write( ber, &sa, sizeof(sa), 0 );
			}
			if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
				LDAP_VERSION2 )
			{
				char *dn = ld->ld_options.ldo_cldapdn;
				if (!dn) dn = "";
				err = ber_printf( ber, "{isti",  /* '}' */
					i, dn,
					LDAP_REQ_ABANDON, msgid );
			} else
#endif
			{
				/* create a message to send */
				err = ber_printf( ber, "{iti",  /* '}' */
					i,
					LDAP_REQ_ABANDON, msgid );
			}

			if ( err == -1 ) {
				/* encoding error */
				ld->ld_errno = LDAP_ENCODING_ERROR;

			} else {
				/* Put Server Controls */
				if ( ldap_int_put_controls( ld, sctrls, ber )
					!= LDAP_SUCCESS )
				{
					err = -1;

				} else {
					/* close '{' */
					err = ber_printf( ber, /*{*/ "N}" );

					if ( err == -1 ) {
						/* encoding error */
						ld->ld_errno = LDAP_ENCODING_ERROR;
					}
				}
			}

			if ( err == -1 ) {
				ber_free( ber, 1 );

			} else {
				/* send the message */
				if ( lr != NULL ) {
					assert( lr->lr_conn != NULL );
					sb = lr->lr_conn->lconn_sb;
				} else {
					sb = ld->ld_sb;
				}

				if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
					ld->ld_errno = LDAP_SERVER_DOWN;
					err = -1;
				} else {
					err = 0;
				}
			}
		}
	}

	if ( lr != NULL ) {
		if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
			ldap_free_connection( ld, lr->lr_conn, 0, 1 );
		}

		if ( origid == msgid ) {
			ldap_free_request( ld, lr );

		} else {
			lr->lr_abandoned = 1;
		}
	}

#ifdef LDAP_R_COMPILE
	/* ld_abandoned is actually protected by the ld_res_mutex;
	 * give up the ld_req_mutex and get the other */
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
	ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif

	/* use bisection */
	i = 0;
	if ( ld->ld_nabandoned == 0 ||
		ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 )
	{
		ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i );
	}

	if ( err != -1 ) {
		ld->ld_errno = LDAP_SUCCESS;
	}

#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
	return( ld->ld_errno );
}
Ejemplo n.º 30
0
int
ldap_create_deref_control_value(
	LDAP		*ld,
	LDAPDerefSpec	*ds,
	struct berval	*value )
{
	BerElement	*ber = NULL;
	ber_tag_t	tag;
	int		i;

	if ( ld == NULL || value == NULL || ds == NULL )
	{
		if ( ld )
			ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	assert( LDAP_VALID( ld ) );

	value->bv_val = NULL;
	value->bv_len = 0;
	ld->ld_errno = LDAP_SUCCESS;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{" /*}*/ );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	for ( i = 0; ds[i].derefAttr != NULL; i++ ) {
		int j;

		tag = ber_printf( ber, "{s{" /*}}*/ , ds[i].derefAttr );
		if ( tag == LBER_ERROR ) {
			ld->ld_errno = LDAP_ENCODING_ERROR;
			goto done;
		}

		for ( j = 0; ds[i].attributes[j] != NULL; j++ ) {
			tag = ber_printf( ber, "s", ds[i].attributes[ j ] );
			if ( tag == LBER_ERROR ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				goto done;
			}
		}

		tag = ber_printf( ber, /*{{*/ "}N}" );
		if ( tag == LBER_ERROR ) {
			ld->ld_errno = LDAP_ENCODING_ERROR;
			goto done;
		}
	}

	tag = ber_printf( ber, /*{*/ "}" );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}