]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/controls.c
silence warnings
[openldap] / libraries / libldap / controls.c
index 7416242ed274ddda193aa2608e6bc570dced263f..4ead5466d009cfa5d3302e4a5e4b00d00f376de4 100644 (file)
-/*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2009 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>.
  */
-/*
- * LDAP controls
+/* 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) {
-                       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 );
        }
 }
 
@@ -38,21 +273,24 @@ ldap_control_free( LDAPControl *c )
 void
 ldap_controls_free( LDAPControl **controls )
 {
+       LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
+
        if ( controls != NULL ) {
-               LDAPControl *c;
+               int i;
 
-               for(c = *controls; c != NULL; c++) {
-                       ldap_control_free( c );
+               for( i=0; controls[i] != NULL; i++) {
+                       ldap_control_free( controls[i] );
                }
 
-               free( controls );
+               LDAP_FREE( controls );
        }
 }
 
 /*
  * Duplicate an array of LDAPControl
  */
-LDAPControl **ldap_controls_dup( LDAPControl **controls )
+LDAPControl **
+ldap_controls_dup( LDAPControl *const *controls )
 {
        LDAPControl **new;
        int i;
@@ -69,7 +307,7 @@ LDAPControl **ldap_controls_dup( LDAPControl **controls )
                return NULL;
        }
 
-       new = (LDAPControl **) malloc( i * sizeof(LDAPControl *) );
+       new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
 
        if( new == NULL ) {
                /* memory allocation failure */
@@ -94,47 +332,46 @@ LDAPControl **ldap_controls_dup( LDAPControl **controls )
 /*
  * Duplicate a LDAPControl
  */
-LDAPControl *ldap_control_dup( LDAPControl *c )
+LDAPControl *
+ldap_control_dup( const LDAPControl *c )
 {
        LDAPControl *new;
 
-       if ( c == NULL ) {
+       if ( c == NULL || c->ldctl_oid == NULL ) {
                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 );
-
-               if(new->ldctl_oid == NULL) {
-                       free( new );
-                       return NULL;
-               }
+       new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
 
-       } else {
-               new->ldctl_oid = NULL;
+       if(new->ldctl_oid == NULL) {
+               LDAP_FREE( new );
+               return NULL;
        }
 
-       if( c->ldctl_value.bv_len > 0 ) {
-               new->ldctl_value.bv_val = (char *) malloc( c->ldctl_value.bv_len );
+       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) {
-                               free( new->ldctl_oid );
+                               LDAP_FREE( new->ldctl_oid );
                        }
-                       free( new );
+                       LDAP_FREE( new );
                        return NULL;
                }
                
-               SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
+               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_len = c->ldctl_value.bv_len;
+               new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
 
        } else {
                new->ldctl_value.bv_len = 0;
@@ -145,8 +382,171 @@ LDAPControl *ldap_control_dup( LDAPControl *c )
        return new;
 }
 
-/* get the controls from the BerElement */
-int ldap_get_ber_controls( BerElement *be, LDAPControl ***cp)
+/*
+ * 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 )
 {
-       return LDAP_NOT_SUPPORTED;
+       LDAPControl *const *c;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
+       if( ctrls == NULL ) {
+               /* use default server 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;
 }