X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fcontrols.c;h=b609b7bc5660cd0c180fe2df01663248bda74c69;hb=8482d2b4889b32f70c51144ac73423dd4e8ddc14;hp=bac038e3048c8e6873f3e8356b695dd280d0b02e;hpb=e4a589d99eb04f5222d6ba8cd755a8968c5c9da1;p=openldap diff --git a/libraries/libldap/controls.c b/libraries/libldap/controls.c index bac038e304..b609b7bc56 100644 --- a/libraries/libldap/controls.c +++ b/libraries/libldap/controls.c @@ -2,35 +2,237 @@ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ -/* - * LDAP controls + +/* LDAPv3 Controls (RFC2251) + * + * Controls ::= SEQUENCE OF Control + * + * Control ::= SEQUENCE { + * controlType LDAPOID, + * criticality BOOLEAN DEFAULT FALSE, + * controlValue OCTET STRING OPTIONAL + * } */ #include "portable.h" -#include +#include #include #include #include "ldap-int.h" + +/* + * ldap_int_put_controls + */ + +int ldap_int_put_controls( + LDAP *ld, + LDAPControl **ctrls, + BerElement *ber ) +{ + LDAPControl **c; + + assert( ld != NULL ); + assert( ber != NULL ); + + if( ctrls == NULL ) { + /* use default server controls */ + ctrls = ld->ld_sctrls; + } + + if( ctrls == NULL || *ctrls == NULL ) { + return LDAP_SUCCESS; + } + + if ( ld->ld_version < LDAP_VERSION3 ) { + /* LDAPv2 doesn't support controls, + * error if any control is critical + */ + for( c = ctrls ; *c != NULL; c++ ) { + if( (*c)->ldctl_iscritical ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + } + + return LDAP_SUCCESS; + } + + /* Controls are encoded as a sequence of sequences */ + 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++ ) { + if ( ber_printf( ber, "{s" /*}*/, + (*c)->ldctl_oid ) == -1 ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + if( (*c)->ldctl_iscritical /* only if true */ + && ( ber_printf( ber, "b", + (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */ + && ( ber_printf( ber, "O", + &((*c)->ldctl_value) ) == -1 ) ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + + if( ber_printf( ber, /*{*/"}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + } + + + if( ber_printf( ber, /*{*/"}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + return LDAP_SUCCESS; +} + +int ldap_int_get_controls( + BerElement *ber, + LDAPControl ***ctrls ) +{ + int nctrls; + ber_tag_t tag; + ber_len_t len; + char *opaque; + + assert( ber != NULL ); + assert( ctrls != NULL ); + + *ctrls = NULL; + + len = ber_pvt_ber_remaining(ber); + + if( len == 0) { + /* no controls */ + return LDAP_SUCCESS; + } + + if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { + if( tag == LBER_ERROR ) { + /* decoding error */ + return LDAP_DECODING_ERROR; + } + + /* ignore unexpected input */ + return LDAP_SUCCESS; + } + + /* set through each element */ + nctrls = 0; + *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) ); + + if( *ctrls == NULL ) { + return LDAP_NO_MEMORY; + } + + ctrls[nctrls] = NULL; + + for( tag = ber_first_element( ber, &len, &opaque ); + tag != LBER_ERROR; + tag = ber_next_element( ber, &len, opaque ) ) + { + LDAPControl *tctrl; + LDAPControl **tctrls; + + tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) ); + + /* allocate pointer space for current controls (nctrls) + * + this control + extra NULL + */ + tctrls = (tctrl == NULL) ? NULL : + LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *)); + + if( tctrls == NULL ) { + /* one of the above allocation failed */ + + if( tctrl != NULL ) { + LDAP_FREE( tctrl ); + } + + ldap_controls_free(*ctrls); + *ctrls = NULL; + + return LDAP_NO_MEMORY; + } + + + tctrls[nctrls++] = tctrl; + tctrls[nctrls] = NULL; + + tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid ); + + if( tag != LBER_ERROR ) { + 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; + } + + if( tag != LBER_ERROR ) { + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LBER_OCTETSTRING ) { + tag = ber_scanf( ber, "o", &tctrl->ldctl_value ); + + } else { + tctrl->ldctl_value.bv_val = NULL; + } + + if( tag == LBER_ERROR ) { + *ctrls = NULL; + ldap_controls_free( tctrls ); + return LDAP_DECODING_ERROR; + } + + *ctrls = tctrls; + } + + return LDAP_SUCCESS; +} + /* * Free a LDAPControl */ void ldap_control_free( LDAPControl *c ) { + assert( c != NULL ); + if ( c != NULL ) { if( c->ldctl_oid != NULL) { - free( c->ldctl_oid ); + LDAP_FREE( c->ldctl_oid ); } if( c->ldctl_value.bv_val != NULL ) { - free( c->ldctl_value.bv_val ); + LDAP_FREE( c->ldctl_value.bv_val ); } - free( c ); + LDAP_FREE( c ); } } @@ -40,6 +242,8 @@ ldap_control_free( LDAPControl *c ) void ldap_controls_free( LDAPControl **controls ) { + assert( controls != NULL ); + if ( controls != NULL ) { LDAPControl *c; @@ -47,7 +251,7 @@ ldap_controls_free( LDAPControl **controls ) ldap_control_free( c ); } - free( controls ); + LDAP_FREE( controls ); } } @@ -71,7 +275,7 @@ LDAPControl **ldap_controls_dup( LDAPControl **controls ) return NULL; } - new = (LDAPControl **) malloc( i * sizeof(LDAPControl *) ); + new = (LDAPControl **) LDAP_MALLOC( i * sizeof(LDAPControl *) ); if( new == NULL ) { /* memory allocation failure */ @@ -104,17 +308,17 @@ LDAPControl *ldap_control_dup( LDAPControl *c ) return NULL; } - new = (LDAPControl *) malloc( sizeof(LDAPControl) ); + new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); if( new == NULL ) { return NULL; } if( c->ldctl_oid != NULL ) { - new->ldctl_oid = strdup( c->ldctl_oid ); + new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid ); if(new->ldctl_oid == NULL) { - free( new ); + LDAP_FREE( new ); return NULL; } @@ -123,13 +327,13 @@ LDAPControl *ldap_control_dup( LDAPControl *c ) } if( c->ldctl_value.bv_len > 0 ) { - new->ldctl_value.bv_val = (char *) malloc( c->ldctl_value.bv_len ); + new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len ); if(new->ldctl_value.bv_val == NULL) { if(new->ldctl_oid != NULL) { - free( new->ldctl_oid ); + LDAP_FREE( new->ldctl_oid ); } - free( new ); + LDAP_FREE( new ); return NULL; } @@ -146,9 +350,3 @@ LDAPControl *ldap_control_dup( LDAPControl *c ) new->ldctl_iscritical = c->ldctl_iscritical; return new; } - -/* get the controls from the BerElement */ -int ldap_get_ber_controls( BerElement *be, LDAPControl ***cp) -{ - return LDAP_NOT_SUPPORTED; -}