#include "portable.h"
#include <ac/stdlib.h>
#include <ac/time.h>
#include <ac/string.h>
#include "ldap-int.h"
int
ldap_pvt_put_control(
const LDAPControl *c,
BerElement *ber )
{
if ( ber_printf( ber, "{s" , c->ldctl_oid ) == -1 ) {
return LDAP_ENCODING_ERROR;
}
if ( c->ldctl_iscritical
&& ( ber_printf( ber, "b",
(ber_int_t) c->ldctl_iscritical ) == -1 ) )
{
return LDAP_ENCODING_ERROR;
}
if ( !BER_BVISNULL( &c->ldctl_value )
&& ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
{
return LDAP_ENCODING_ERROR;
}
if ( ber_printf( ber, "N}" ) == -1 ) {
return LDAP_ENCODING_ERROR;
}
return LDAP_SUCCESS;
}
int
ldap_int_put_controls(
LDAP *ld,
LDAPControl *const *ctrls,
BerElement *ber )
{
LDAPControl *const *c;
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
assert( ber != NULL );
if( ctrls == NULL ) {
ctrls = ld->ld_sctrls;
}
if( ctrls == NULL || *ctrls == NULL ) {
return LDAP_SUCCESS;
}
if ( ld->ld_version < LDAP_VERSION3 ) {
for( c = ctrls ; *c != NULL; c++ ) {
if( (*c)->ldctl_iscritical ) {
ld->ld_errno = LDAP_NOT_SUPPORTED;
return ld->ld_errno;
}
}
return LDAP_SUCCESS;
}
if( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
return ld->ld_errno;
}
for( c = ctrls ; *c != NULL; c++ ) {
ld->ld_errno = ldap_pvt_put_control( *c, ber );
if ( ld->ld_errno != LDAP_SUCCESS ) {
return ld->ld_errno;
}
}
if( ber_printf( ber, "}" ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
return ld->ld_errno;
}
return LDAP_SUCCESS;
}
int ldap_pvt_get_controls(
BerElement *ber,
LDAPControl ***ctrls )
{
int nctrls;
ber_tag_t tag;
ber_len_t len;
char *opaque;
assert( ber != NULL );
if( ctrls == NULL ) {
return LDAP_SUCCESS;
}
*ctrls = NULL;
len = ber_pvt_ber_remaining( ber );
if( len == 0) {
return LDAP_SUCCESS;
}
if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
if( tag == LBER_ERROR ) {
return LDAP_DECODING_ERROR;
}
return LDAP_SUCCESS;
}
nctrls = 0;
*ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
if( *ctrls == NULL ) {
return LDAP_NO_MEMORY;
}
*ctrls[nctrls] = NULL;
for( tag = ber_first_element( ber, &len, &opaque );
tag != LBER_ERROR;
tag = ber_next_element( ber, &len, opaque ) )
{
LDAPControl *tctrl;
LDAPControl **tctrls;
tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
tctrls = (tctrl == NULL) ? NULL :
LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
if( tctrls == NULL ) {
if( tctrl != NULL ) {
LDAP_FREE( tctrl );
}
ldap_controls_free(*ctrls);
*ctrls = NULL;
return LDAP_NO_MEMORY;
}
tctrls[nctrls++] = tctrl;
tctrls[nctrls] = NULL;
tag = ber_scanf( ber, "{a" , &tctrl->ldctl_oid );
if( tag == LBER_ERROR ) {
*ctrls = NULL;
ldap_controls_free( tctrls );
return LDAP_DECODING_ERROR;
}
tag = ber_peek_tag( ber, &len );
if( tag == LBER_BOOLEAN ) {
ber_int_t crit;
tag = ber_scanf( ber, "b", &crit );
tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
tag = ber_peek_tag( ber, &len );
}
if( tag == LBER_OCTETSTRING ) {
tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
} else {
BER_BVZERO( &tctrl->ldctl_value );
}
*ctrls = tctrls;
}
return LDAP_SUCCESS;
}
void
ldap_control_free( LDAPControl *c )
{
LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
if ( c != NULL ) {
if( c->ldctl_oid != NULL) {
LDAP_FREE( c->ldctl_oid );
}
if( c->ldctl_value.bv_val != NULL ) {
LDAP_FREE( c->ldctl_value.bv_val );
}
LDAP_FREE( c );
}
}
void
ldap_controls_free( LDAPControl **controls )
{
LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
if ( controls != NULL ) {
int i;
for( i=0; controls[i] != NULL; i++) {
ldap_control_free( controls[i] );
}
LDAP_FREE( controls );
}
}
LDAPControl **
ldap_controls_dup( LDAPControl *const *controls )
{
LDAPControl **new;
int i;
if ( controls == NULL ) {
return NULL;
}
for(i=0; controls[i] != NULL; i++) ;
if( i < 1 ) {
return NULL;
}
new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
if( new == NULL ) {
return NULL;
}
for(i=0; controls[i] != NULL; i++) {
new[i] = ldap_control_dup( controls[i] );
if( new[i] == NULL ) {
ldap_controls_free( new );
return NULL;
}
}
new[i] = NULL;
return new;
}
LDAPControl *
ldap_control_dup( const LDAPControl *c )
{
LDAPControl *new;
if ( c == NULL || c->ldctl_oid == NULL ) {
return NULL;
}
new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
if( new == NULL ) {
return NULL;
}
new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
if(new->ldctl_oid == NULL) {
LDAP_FREE( new );
return NULL;
}
if( c->ldctl_value.bv_val != NULL ) {
new->ldctl_value.bv_val =
(char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
if(new->ldctl_value.bv_val == NULL) {
if(new->ldctl_oid != NULL) {
LDAP_FREE( new->ldctl_oid );
}
LDAP_FREE( new );
return NULL;
}
new->ldctl_value.bv_len = c->ldctl_value.bv_len;
AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
c->ldctl_value.bv_len );
new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
} else {
new->ldctl_value.bv_len = 0;
new->ldctl_value.bv_val = NULL;
}
new->ldctl_iscritical = c->ldctl_iscritical;
return new;
}
LDAPControl *
ldap_find_control(
LDAP_CONST char *oid,
LDAPControl **ctrls )
{
if( ctrls == NULL || *ctrls == NULL ) {
return NULL;
}
for( ; *ctrls != NULL; ctrls++ ) {
if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
return *ctrls;
}
}
return NULL;
}
LDAPControl *
ldap_control_find(
LDAP_CONST char *oid,
LDAPControl **ctrls,
LDAPControl ***nextctrlp )
{
if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
return NULL;
}
for( ; *ctrls != NULL; ctrls++ ) {
if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
if ( nextctrlp != NULL ) {
*nextctrlp = ctrls + 1;
}
return *ctrls;
}
}
if ( nextctrlp != NULL ) {
*nextctrlp = NULL;
}
return NULL;
}
int
ldap_create_control(
LDAP_CONST char *requestOID,
BerElement *ber,
int iscritical,
LDAPControl **ctrlp )
{
LDAPControl *ctrl;
assert( requestOID != NULL );
assert( ctrlp != NULL );
ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
if ( ctrl == NULL ) {
return LDAP_NO_MEMORY;
}
BER_BVZERO(&ctrl->ldctl_value);
if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
LDAP_FREE( ctrl );
return LDAP_NO_MEMORY;
}
ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
ctrl->ldctl_iscritical = iscritical;
if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
ldap_control_free( ctrl );
return LDAP_NO_MEMORY;
}
*ctrlp = ctrl;
return LDAP_SUCCESS;
}
int
ldap_control_create(
LDAP_CONST char *requestOID,
int iscritical,
struct berval *value,
int dupval,
LDAPControl **ctrlp )
{
LDAPControl *ctrl;
assert( requestOID != NULL );
assert( ctrlp != NULL );
ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
if ( ctrl == NULL ) {
return LDAP_NO_MEMORY;
}
ctrl->ldctl_iscritical = iscritical;
if ( requestOID != NULL ) {
ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
if ( ctrl->ldctl_oid == NULL ) {
ldap_control_free( ctrl );
return LDAP_NO_MEMORY;
}
}
if ( value && !BER_BVISNULL( value ) ) {
if ( dupval ) {
ber_dupbv( &ctrl->ldctl_value, value );
if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
ldap_control_free( ctrl );
return LDAP_NO_MEMORY;
}
} else {
ctrl->ldctl_value = *value;
}
}
*ctrlp = ctrl;
return LDAP_SUCCESS;
}
int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
{
LDAPControl *const *c;
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
if( ctrls == NULL ) {
ctrls = ld->ld_cctrls;
}
if( ctrls == NULL || *ctrls == NULL ) {
return LDAP_SUCCESS;
}
for( c = ctrls ; *c != NULL; c++ ) {
if( (*c)->ldctl_iscritical ) {
ld->ld_errno = LDAP_NOT_SUPPORTED;
return ld->ld_errno;
}
}
return LDAP_SUCCESS;
}