123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /* $OpenLDAP$ */
- /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2022 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
- /* This notice applies to changes, created by or for Novell, Inc.,
- * to preexisting works for which notices appear elsewhere in this file.
- *
- * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
- *
- * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
- * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
- * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
- * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
- * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
- * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
- * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
- * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
- *---
- * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
- * can be found in the file "build/LICENSE-2.0.1" in this distribution
- * of OpenLDAP Software.
- */
- #include "portable.h"
- #include <ac/stdlib.h>
- #include <ac/time.h>
- #include <ac/string.h>
- #include "ldap-int.h"
- /* LDAPv3 Controls (RFC 4511)
- *
- * Controls ::= SEQUENCE OF control Control
- *
- * Control ::= SEQUENCE {
- * controlType LDAPOID,
- * criticality BOOLEAN DEFAULT FALSE,
- * controlValue OCTET STRING OPTIONAL
- * }
- */
- 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 /* only if true */
- && ( ber_printf( ber, "b",
- (ber_int_t) c->ldctl_iscritical ) == -1 ) )
- {
- return LDAP_ENCODING_ERROR;
- }
- if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a 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;
- }
- /*
- * ldap_int_put_controls
- */
- 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 ) {
- /* 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++ ) {
- 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) {
- /* no controls */
- return LDAP_SUCCESS;
- }
- if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
- if( tag == LBER_ERROR ) {
- /* decoding error */
- return LDAP_DECODING_ERROR;
- }
- /* ignore unexpected input */
- return LDAP_SUCCESS;
- }
- /* set through each element */
- nctrls = 0;
- *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
- if( *ctrls == NULL ) {
- return LDAP_NO_MEMORY;
- }
- *ctrls[nctrls] = NULL;
- for( tag = ber_first_element( ber, &len, &opaque );
- tag != LBER_ERROR;
- tag = ber_next_element( ber, &len, opaque ) )
- {
- LDAPControl *tctrl;
- LDAPControl **tctrls;
- tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
- /* allocate pointer space for current controls (nctrls)
- * + this control + extra NULL
- */
- tctrls = (tctrl == NULL) ? NULL :
- LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
- if( tctrls == NULL ) {
- /* one of the above allocation failed */
- if( tctrl != NULL ) {
- LDAP_FREE( tctrl );
- }
- ldap_controls_free(*ctrls);
- *ctrls = NULL;
- return LDAP_NO_MEMORY;
- }
- tctrls[nctrls++] = tctrl;
- tctrls[nctrls] = NULL;
- tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
- if( tag == LBER_ERROR ) {
- *ctrls = NULL;
- ldap_controls_free( tctrls );
- return LDAP_DECODING_ERROR;
- }
- tag = ber_peek_tag( ber, &len );
- if( tag == LBER_BOOLEAN ) {
- ber_int_t crit;
- tag = ber_scanf( ber, "b", &crit );
- tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
- tag = ber_peek_tag( ber, &len );
- }
- if( tag == LBER_OCTETSTRING ) {
- tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
- } else {
- BER_BVZERO( &tctrl->ldctl_value );
- }
- *ctrls = tctrls;
- }
-
- return LDAP_SUCCESS;
- }
- /*
- * Free a LDAPControl
- */
- 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 );
- }
- }
- /*
- * Free an array of LDAPControl's
- */
- 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 );
- }
- }
- /*
- * Duplicate an array of LDAPControl
- */
- LDAPControl **
- ldap_controls_dup( LDAPControl *const *controls )
- {
- LDAPControl **new;
- int i;
- if ( controls == NULL ) {
- return NULL;
- }
- /* count the controls */
- for(i=0; controls[i] != NULL; i++) /* empty */ ;
- if( i < 1 ) {
- /* no controls to duplicate */
- return NULL;
- }
- new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
- if( new == NULL ) {
- /* memory allocation failure */
- return NULL;
- }
- /* duplicate the controls */
- 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;
- }
- /*
- * Duplicate a LDAPControl
- */
- 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;
- }
- /*
- * Find a LDAPControl - deprecated
- */
- 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;
- }
- /*
- * Find a LDAPControl
- */
- 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;
- }
- /*
- * Create a LDAPControl, optionally from ber - deprecated
- */
- 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;
- }
- /*
- * Create a LDAPControl, optionally from value
- */
- 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;
- }
- /*
- * check for critical client controls and bitch if present
- * if we ever support critical controls, we'll have to
- * find a means for maintaining per API call control
- * information.
- */
- int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
- {
- LDAPControl *const *c;
- assert( ld != NULL );
- assert( LDAP_VALID( ld ) );
- if( ctrls == NULL ) {
- /* use default client controls */
- 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;
- }
|