Back to index

openldap  2.4.31
controls.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* This notice applies to changes, created by or for Novell, Inc.,
00016  * to preexisting works for which notices appear elsewhere in this file.
00017  *
00018  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
00019  *
00020  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
00021  * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
00022  * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
00023  * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
00024  * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
00025  * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
00026  * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
00027  * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
00028  *---
00029  * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
00030  * can be found in the file "build/LICENSE-2.0.1" in this distribution
00031  * of OpenLDAP Software.
00032  */
00033 
00034 #include "portable.h"
00035 
00036 #include <ac/stdlib.h>
00037 
00038 #include <ac/time.h>
00039 #include <ac/string.h>
00040 
00041 #include "ldap-int.h"
00042 
00043 /* LDAPv3 Controls (RFC 4511)
00044  *
00045  *     Controls ::= SEQUENCE OF control Control  
00046  *
00047  *     Control ::= SEQUENCE { 
00048  *            controlType          LDAPOID,
00049  *            criticality          BOOLEAN DEFAULT FALSE,
00050  *            controlValue  OCTET STRING OPTIONAL
00051  *     }
00052  */
00053 
00054 int
00055 ldap_pvt_put_control(
00056        const LDAPControl *c,
00057        BerElement *ber )
00058 {
00059        if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) {
00060               return LDAP_ENCODING_ERROR;
00061        }
00062 
00063        if ( c->ldctl_iscritical /* only if true */
00064               &&  ( ber_printf( ber, "b",
00065                      (ber_int_t) c->ldctl_iscritical ) == -1 ) )
00066        {
00067               return LDAP_ENCODING_ERROR;
00068        }
00069 
00070        if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */
00071               &&  ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
00072        {
00073               return LDAP_ENCODING_ERROR;
00074        }
00075 
00076        if ( ber_printf( ber, /*{*/"N}" ) == -1 ) {
00077               return LDAP_ENCODING_ERROR;
00078        }
00079 
00080        return LDAP_SUCCESS;
00081 }
00082 
00083 
00084 /*
00085  * ldap_int_put_controls
00086  */
00087 
00088 int
00089 ldap_int_put_controls(
00090        LDAP *ld,
00091        LDAPControl *const *ctrls,
00092        BerElement *ber )
00093 {
00094        LDAPControl *const *c;
00095 
00096        assert( ld != NULL );
00097        assert( LDAP_VALID( ld ) );
00098        assert( ber != NULL );
00099 
00100        if( ctrls == NULL ) {
00101               /* use default server controls */
00102               ctrls = ld->ld_sctrls;
00103        }
00104 
00105        if( ctrls == NULL || *ctrls == NULL ) {
00106               return LDAP_SUCCESS;
00107        }
00108 
00109        if ( ld->ld_version < LDAP_VERSION3 ) {
00110               /* LDAPv2 doesn't support controls,
00111                * error if any control is critical
00112                */
00113               for( c = ctrls ; *c != NULL; c++ ) {
00114                      if( (*c)->ldctl_iscritical ) {
00115                             ld->ld_errno = LDAP_NOT_SUPPORTED;
00116                             return ld->ld_errno;
00117                      }
00118               }
00119 
00120               return LDAP_SUCCESS;
00121        }
00122 
00123        /* Controls are encoded as a sequence of sequences */
00124        if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
00125               ld->ld_errno = LDAP_ENCODING_ERROR;
00126               return ld->ld_errno;
00127        }
00128 
00129        for( c = ctrls ; *c != NULL; c++ ) {
00130               ld->ld_errno = ldap_pvt_put_control( *c, ber );
00131               if ( ld->ld_errno != LDAP_SUCCESS ) {
00132                      return ld->ld_errno;
00133               }
00134        }
00135 
00136 
00137        if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
00138               ld->ld_errno = LDAP_ENCODING_ERROR;
00139               return ld->ld_errno;
00140        }
00141 
00142        return LDAP_SUCCESS;
00143 }
00144 
00145 int ldap_pvt_get_controls(
00146        BerElement *ber,
00147        LDAPControl ***ctrls )
00148 {
00149        int nctrls;
00150        ber_tag_t tag;
00151        ber_len_t len;
00152        char *opaque;
00153 
00154        assert( ber != NULL );
00155 
00156        if( ctrls == NULL ) {
00157               return LDAP_SUCCESS;
00158        }
00159        *ctrls = NULL;
00160 
00161        len = ber_pvt_ber_remaining( ber );
00162 
00163        if( len == 0) {
00164               /* no controls */
00165               return LDAP_SUCCESS;
00166        }
00167 
00168        if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
00169               if( tag == LBER_ERROR ) {
00170                      /* decoding error */
00171                      return LDAP_DECODING_ERROR;
00172               }
00173 
00174               /* ignore unexpected input */
00175               return LDAP_SUCCESS;
00176        }
00177 
00178        /* set through each element */
00179        nctrls = 0;
00180        *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
00181 
00182        if( *ctrls == NULL ) {
00183               return LDAP_NO_MEMORY;
00184        }
00185 
00186        *ctrls[nctrls] = NULL;
00187 
00188        for( tag = ber_first_element( ber, &len, &opaque );
00189               tag != LBER_ERROR;
00190               tag = ber_next_element( ber, &len, opaque ) )
00191        {
00192               LDAPControl *tctrl;
00193               LDAPControl **tctrls;
00194 
00195               tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
00196 
00197               /* allocate pointer space for current controls (nctrls)
00198                * + this control + extra NULL
00199                */
00200               tctrls = (tctrl == NULL) ? NULL :
00201                      LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
00202 
00203               if( tctrls == NULL ) {
00204                      /* one of the above allocation failed */
00205 
00206                      if( tctrl != NULL ) {
00207                             LDAP_FREE( tctrl );
00208                      }
00209 
00210                      ldap_controls_free(*ctrls);
00211                      *ctrls = NULL;
00212 
00213                      return LDAP_NO_MEMORY;
00214               }
00215 
00216 
00217               tctrls[nctrls++] = tctrl;
00218               tctrls[nctrls] = NULL;
00219 
00220               tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
00221 
00222               if( tag == LBER_ERROR ) {
00223                      *ctrls = NULL;
00224                      ldap_controls_free( tctrls );
00225                      return LDAP_DECODING_ERROR;
00226               }
00227 
00228               tag = ber_peek_tag( ber, &len );
00229 
00230               if( tag == LBER_BOOLEAN ) {
00231                      ber_int_t crit;
00232                      tag = ber_scanf( ber, "b", &crit );
00233                      tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
00234                      tag = ber_peek_tag( ber, &len );
00235               }
00236 
00237               if( tag == LBER_OCTETSTRING ) {
00238                      tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
00239               } else {
00240                      BER_BVZERO( &tctrl->ldctl_value );
00241               }
00242 
00243               *ctrls = tctrls;
00244        }
00245               
00246        return LDAP_SUCCESS;
00247 }
00248 
00249 /*
00250  * Free a LDAPControl
00251  */
00252 void
00253 ldap_control_free( LDAPControl *c )
00254 {
00255        LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
00256 
00257        if ( c != NULL ) {
00258               if( c->ldctl_oid != NULL) {
00259                      LDAP_FREE( c->ldctl_oid );
00260               }
00261 
00262               if( c->ldctl_value.bv_val != NULL ) {
00263                      LDAP_FREE( c->ldctl_value.bv_val );
00264               }
00265 
00266               LDAP_FREE( c );
00267        }
00268 }
00269 
00270 /*
00271  * Free an array of LDAPControl's
00272  */
00273 void
00274 ldap_controls_free( LDAPControl **controls )
00275 {
00276        LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
00277 
00278        if ( controls != NULL ) {
00279               int i;
00280 
00281               for( i=0; controls[i] != NULL; i++) {
00282                      ldap_control_free( controls[i] );
00283               }
00284 
00285               LDAP_FREE( controls );
00286        }
00287 }
00288 
00289 /*
00290  * Duplicate an array of LDAPControl
00291  */
00292 LDAPControl **
00293 ldap_controls_dup( LDAPControl *const *controls )
00294 {
00295        LDAPControl **new;
00296        int i;
00297 
00298        if ( controls == NULL ) {
00299               return NULL;
00300        }
00301 
00302        /* count the controls */
00303        for(i=0; controls[i] != NULL; i++) /* empty */ ;
00304 
00305        if( i < 1 ) {
00306               /* no controls to duplicate */
00307               return NULL;
00308        }
00309 
00310        new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
00311 
00312        if( new == NULL ) {
00313               /* memory allocation failure */
00314               return NULL;
00315        }
00316 
00317        /* duplicate the controls */
00318        for(i=0; controls[i] != NULL; i++) {
00319               new[i] = ldap_control_dup( controls[i] );
00320 
00321               if( new[i] == NULL ) {
00322                      ldap_controls_free( new );
00323                      return NULL;
00324               }
00325        }
00326 
00327        new[i] = NULL;
00328 
00329        return new;
00330 }
00331 
00332 /*
00333  * Duplicate a LDAPControl
00334  */
00335 LDAPControl *
00336 ldap_control_dup( const LDAPControl *c )
00337 {
00338        LDAPControl *new;
00339 
00340        if ( c == NULL || c->ldctl_oid == NULL ) {
00341               return NULL;
00342        }
00343 
00344        new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
00345 
00346        if( new == NULL ) {
00347               return NULL;
00348        }
00349 
00350        new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
00351 
00352        if(new->ldctl_oid == NULL) {
00353               LDAP_FREE( new );
00354               return NULL;
00355        }
00356 
00357        if( c->ldctl_value.bv_val != NULL ) {
00358               new->ldctl_value.bv_val =
00359                      (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
00360 
00361               if(new->ldctl_value.bv_val == NULL) {
00362                      if(new->ldctl_oid != NULL) {
00363                             LDAP_FREE( new->ldctl_oid );
00364                      }
00365                      LDAP_FREE( new );
00366                      return NULL;
00367               }
00368               
00369               new->ldctl_value.bv_len = c->ldctl_value.bv_len;
00370 
00371               AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
00372                      c->ldctl_value.bv_len );
00373 
00374               new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
00375 
00376        } else {
00377               new->ldctl_value.bv_len = 0;
00378               new->ldctl_value.bv_val = NULL;
00379        }
00380 
00381        new->ldctl_iscritical = c->ldctl_iscritical;
00382        return new;
00383 }
00384 
00385 /*
00386  * Find a LDAPControl - deprecated
00387  */
00388 LDAPControl *
00389 ldap_find_control(
00390        LDAP_CONST char *oid,
00391        LDAPControl **ctrls )
00392 {
00393        if( ctrls == NULL || *ctrls == NULL ) {
00394               return NULL;
00395        }
00396 
00397        for( ; *ctrls != NULL; ctrls++ ) {
00398               if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
00399                      return *ctrls;
00400               }
00401        }
00402 
00403        return NULL;
00404 }
00405 
00406 /*
00407  * Find a LDAPControl
00408  */
00409 LDAPControl *
00410 ldap_control_find(
00411        LDAP_CONST char *oid,
00412        LDAPControl **ctrls,
00413        LDAPControl ***nextctrlp )
00414 {
00415        if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
00416               return NULL;
00417        }
00418 
00419        for( ; *ctrls != NULL; ctrls++ ) {
00420               if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
00421                      if ( nextctrlp != NULL ) {
00422                             *nextctrlp = ctrls + 1;
00423                      }
00424 
00425                      return *ctrls;
00426               }
00427        }
00428 
00429        if ( nextctrlp != NULL ) {
00430               *nextctrlp = NULL;
00431        }
00432 
00433        return NULL;
00434 }
00435 
00436 /*
00437  * Create a LDAPControl, optionally from ber - deprecated
00438  */
00439 int
00440 ldap_create_control(
00441        LDAP_CONST char *requestOID,
00442        BerElement *ber,
00443        int iscritical,
00444        LDAPControl **ctrlp )
00445 {
00446        LDAPControl *ctrl;
00447 
00448        assert( requestOID != NULL );
00449        assert( ctrlp != NULL );
00450 
00451        ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
00452        if ( ctrl == NULL ) {
00453               return LDAP_NO_MEMORY;
00454        }
00455 
00456        BER_BVZERO(&ctrl->ldctl_value);
00457        if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
00458               LDAP_FREE( ctrl );
00459               return LDAP_NO_MEMORY;
00460        }
00461 
00462        ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
00463        ctrl->ldctl_iscritical = iscritical;
00464 
00465        if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
00466               ldap_control_free( ctrl );
00467               return LDAP_NO_MEMORY;
00468        }
00469 
00470        *ctrlp = ctrl;
00471        return LDAP_SUCCESS;
00472 }
00473 
00474 /*
00475  * Create a LDAPControl, optionally from value
00476  */
00477 int
00478 ldap_control_create(
00479        LDAP_CONST char *requestOID,
00480        int iscritical,
00481        struct berval *value,
00482        int dupval,
00483        LDAPControl **ctrlp )
00484 {
00485        LDAPControl *ctrl;
00486 
00487        assert( requestOID != NULL );
00488        assert( ctrlp != NULL );
00489 
00490        ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
00491        if ( ctrl == NULL ) {
00492               return LDAP_NO_MEMORY;
00493        }
00494 
00495        ctrl->ldctl_iscritical = iscritical;
00496        if ( requestOID != NULL ) {
00497               ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
00498               if ( ctrl->ldctl_oid == NULL ) {
00499                      ldap_control_free( ctrl );
00500                      return LDAP_NO_MEMORY;
00501               }
00502        }
00503 
00504        if ( value && !BER_BVISNULL( value ) ) {
00505               if ( dupval ) {
00506                      ber_dupbv( &ctrl->ldctl_value, value );
00507                      if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
00508                             ldap_control_free( ctrl );
00509                             return LDAP_NO_MEMORY;
00510                      }
00511 
00512               } else {
00513                      ctrl->ldctl_value = *value;
00514               }
00515        }
00516 
00517        *ctrlp = ctrl;
00518 
00519        return LDAP_SUCCESS;
00520 }
00521 
00522 /*
00523  * check for critical client controls and bitch if present
00524  * if we ever support critical controls, we'll have to
00525  * find a means for maintaining per API call control
00526  * information.
00527  */
00528 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
00529 {
00530        LDAPControl *const *c;
00531 
00532        assert( ld != NULL );
00533        assert( LDAP_VALID( ld ) );
00534 
00535        if( ctrls == NULL ) {
00536               /* use default client controls */
00537               ctrls = ld->ld_cctrls;
00538        }
00539 
00540        if( ctrls == NULL || *ctrls == NULL ) {
00541               return LDAP_SUCCESS;
00542        }
00543 
00544        for( c = ctrls ; *c != NULL; c++ ) {
00545               if( (*c)->ldctl_iscritical ) {
00546                      ld->ld_errno = LDAP_NOT_SUPPORTED;
00547                      return ld->ld_errno;
00548               }
00549        }
00550 
00551        return LDAP_SUCCESS;
00552 }