]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/controls.c
Provide build support for sasl.c.
[openldap] / libraries / libldap / controls.c
index bac038e3048c8e6873f3e8356b695dd280d0b02e..b609b7bc5660cd0c180fe2df01663248bda74c69 100644 (file)
  * 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 <stdlib.h>
+#include <ac/stdlib.h>
 
 #include <ac/time.h>
 #include <ac/string.h>
 
 #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;
-}