Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions
control.c File Reference
#include "ldap-int.h"

Go to the source code of this file.

Defines

#define CONTROL_GRABSIZE   5

Functions

static LDAPControlldap_control_dup (LDAPControl *ctrl)
static int ldap_control_copy_contents (LDAPControl *ctrl_dst, LDAPControl *ctrl_src)
int nsldapi_put_controls (LDAP *ld, LDAPControl **ctrls, int closeseq, BerElement *ber)
int nsldapi_get_controls (BerElement *ber, LDAPControl ***controlsp)
void LDAP_CALL ldap_control_free (LDAPControl *ctrl)
void LDAP_CALL ldap_controls_free (LDAPControl **ctrls)
int nsldapi_dup_controls (LDAP *ld, LDAPControl ***ldctrls, LDAPControl **newctrls)
int nsldapi_build_control (char *oid, BerElement *ber, int freeber, char iscritical, LDAPControl **ctrlp)

Define Documentation


Function Documentation

static int ldap_control_copy_contents ( LDAPControl ctrl_dst,
LDAPControl ctrl_src 
) [static]

Definition at line 421 of file control.c.

{
       size_t len;

       if ( NULL == ctrl_dst || NULL == ctrl_src ) {
              return( LDAP_PARAM_ERROR );
       }

       ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical;

       /* fill in the fields of this new control */
       if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid ))
           == NULL ) {
              return( LDAP_NO_MEMORY );
       }

       len = (size_t)(ctrl_src->ldctl_value).bv_len;
       if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) {
              ctrl_dst->ldctl_value.bv_len = 0;
              ctrl_dst->ldctl_value.bv_val = NULL;
       } else {
              ctrl_dst->ldctl_value.bv_len = len;
              if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len ))
                  == NULL ) {
                     NSLDAPI_FREE( ctrl_dst->ldctl_oid );
                     return( LDAP_NO_MEMORY );
              }
              SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val,
                  ctrl_src->ldctl_value.bv_val, len );
       }

       return ( LDAP_SUCCESS );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static LDAPControl * ldap_control_dup ( LDAPControl ctrl) [static]

Definition at line 398 of file control.c.

{
       LDAPControl   *rctrl;

       if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl )))
           == NULL ) {
              return( NULL );
       }

       if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) {
              NSLDAPI_FREE( rctrl );
              return( NULL );
       }

       return( rctrl );
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 277 of file control.c.

{
       if ( ctrl != NULL ) {
              if ( ctrl->ldctl_oid != NULL ) {
                     NSLDAPI_FREE( ctrl->ldctl_oid );
              }
              if ( ctrl->ldctl_value.bv_val != NULL ) {
                     NSLDAPI_FREE( ctrl->ldctl_value.bv_val );
              }
              NSLDAPI_FREE( (char *)ctrl );
       }
}

Here is the caller graph for this function:

Definition at line 293 of file control.c.

{
       int    i;

       if ( ctrls != NULL ) {
              for ( i = 0; ctrls[i] != NULL; i++ ) {
                     ldap_control_free( ctrls[i] );
              }
              NSLDAPI_FREE( (char *)ctrls );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsldapi_build_control ( char *  oid,
BerElement *  ber,
int  freeber,
char  iscritical,
LDAPControl **  ctrlp 
)

Definition at line 461 of file control.c.

{
       int           rc;
       struct berval *bvp;

       if ( ber == NULL ) {
              bvp = NULL;
       } else {
              /* allocate struct berval with contents of the BER encoding */
              rc = ber_flatten( ber, &bvp );
              if ( freeber ) {
                     ber_free( ber, 1 );
              }
              if ( rc == -1 ) {
                     return( LDAP_NO_MEMORY );
              }
       }

       /* allocate the new control structure */
       if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl)))
           == NULL ) {
              if ( bvp != NULL ) {
                     ber_bvfree( bvp );
              }
              return( LDAP_NO_MEMORY );
       }

       /* fill in the fields of this new control */
       (*ctrlp)->ldctl_iscritical = iscritical;  
       if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) {
              NSLDAPI_FREE( *ctrlp ); 
              if ( bvp != NULL ) {
                     ber_bvfree( bvp );
              }
              return( LDAP_NO_MEMORY );
       }                           

       if ( bvp == NULL ) {
              (*ctrlp)->ldctl_value.bv_len = 0;
              (*ctrlp)->ldctl_value.bv_val = NULL;
       } else {
              (*ctrlp)->ldctl_value = *bvp;      /* struct copy */
              NSLDAPI_FREE( bvp ); /* free container, not contents! */
       }

       return( LDAP_SUCCESS );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsldapi_dup_controls ( LDAP *  ld,
LDAPControl ***  ldctrls,
LDAPControl **  newctrls 
)

Definition at line 355 of file control.c.

{
       int    count;

       if ( *ldctrls != NULL ) {
              ldap_controls_free( *ldctrls );
       }

       if ( newctrls == NULL || newctrls[0] == NULL ) {
              *ldctrls = NULL;
              return( 0 );
       }

       for ( count = 0; newctrls[ count ] != NULL; ++count ) {
              ;
       }

       if (( *ldctrls = (LDAPControl **)NSLDAPI_MALLOC(( count + 1 ) *
           sizeof( LDAPControl *))) == NULL ) {
              LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
              return( -1 );
       }
       (*ldctrls)[ count ] = NULL;

       for ( count = 0; newctrls[ count ] != NULL; ++count ) {
              if (( (*ldctrls)[ count ] =
                  ldap_control_dup( newctrls[ count ] )) == NULL ) {
                     ldap_controls_free( *ldctrls );
                     *ldctrls = NULL;
                     LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
                     return( -1 );
              }
       }

       return( 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsldapi_get_controls ( BerElement *  ber,
LDAPControl ***  controlsp 
)

Definition at line 145 of file control.c.

{
       LDAPControl          *newctrl;
       unsigned long        tag, len;
       int                  rc, maxcontrols, curcontrols;
       char                 *last;

       /*
        * Each LDAPMessage can have a set of controls appended
        * to it. Controls are used to extend the functionality
        * of an LDAP operation (e.g., add an attribute size limit
        * to the search operation). These controls look like this:
        *
        *     Controls ::= SEQUENCE OF Control
        *
        *     Control ::= SEQUENCE {
        *            controlType   LDAPOID,
        *            criticality   BOOLEAN DEFAULT FALSE,
        *            controlValue  OCTET STRING
        *     }
        */
       LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 );

       *controlsp = NULL;

       /*
         * check to see if controls were included
        */
       if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) {
              return( LDAP_DECODING_ERROR );     /* unexpected error */
       }
       if ( len == 0 ) {
              LDAPDebug( LDAP_DEBUG_TRACE,
                  "<= nsldapi_get_controls no controls\n", 0, 0, 0 );
              return( LDAP_SUCCESS );                   /* no controls */
       }
       if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
              if ( tag == LBER_ERROR ) {
                     LDAPDebug( LDAP_DEBUG_TRACE,
                         "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n",
                         0, 0, 0 );
                     return( LDAP_DECODING_ERROR );     /* decoding error */
              }
              /*
               * We found something other than controls.  This should never
               * happen in LDAPv3, but we don't treat this is a hard error --
               * we just ignore the extra stuff.
               */
              LDAPDebug( LDAP_DEBUG_TRACE,
                  "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n",
                  tag, 0, 0 );
              return( LDAP_SUCCESS );
       }

       maxcontrols = curcontrols = 0;
       for ( tag = ber_first_element( ber, &len, &last );
           tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
           tag = ber_next_element( ber, &len, last ) ) {
              if ( curcontrols >= maxcontrols - 1 ) {
#define CONTROL_GRABSIZE    5
                     maxcontrols += CONTROL_GRABSIZE;
                     *controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC(
                         (char *)*controlsp, maxcontrols *
                         sizeof(struct ldapcontrol *) );
                     if ( *controlsp == NULL ) {
                         rc = LDAP_NO_MEMORY;
                         goto free_and_return;
                     }
              }
              if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1,
                  sizeof(LDAPControl))) == NULL ) {
                     rc = LDAP_NO_MEMORY;
                     goto free_and_return;
              }
              
              (*controlsp)[curcontrols++] = newctrl;
              (*controlsp)[curcontrols] = NULL;

              if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid )
                  == LBER_ERROR ) {
                     rc = LDAP_DECODING_ERROR;
                     goto free_and_return;
              }

              /* the criticality is optional */
              if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) {
                     int           aint;

                     if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) {
                            rc = LDAP_DECODING_ERROR;
                            goto free_and_return;
                     }
                     newctrl->ldctl_iscritical = (char)aint;   /* XXX lossy cast */
              } else {
                     /* absent is synonomous with FALSE */
                     newctrl->ldctl_iscritical = 0;
              }

              /* the control value is optional */
              if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) {
                     if ( ber_scanf( ber, "o", &newctrl->ldctl_value )
                         == LBER_ERROR ) {
                            rc = LDAP_DECODING_ERROR;
                            goto free_and_return;
                     }
              } else {
                     (newctrl->ldctl_value).bv_val = NULL;
                     (newctrl->ldctl_value).bv_len = 0;
              }

       }

       if ( tag == LBER_ERROR ) {
              rc = LDAP_DECODING_ERROR;
              goto free_and_return;
       }

       LDAPDebug( LDAP_DEBUG_TRACE,
           "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 );
       return( LDAP_SUCCESS );

free_and_return:;
       ldap_controls_free( *controlsp );
       *controlsp = NULL;
       LDAPDebug( LDAP_DEBUG_TRACE,
           "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 );
       return( rc );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsldapi_put_controls ( LDAP *  ld,
LDAPControl **  ctrls,
int  closeseq,
BerElement *  ber 
)

Definition at line 52 of file control.c.

{
       LDAPControl   *c;
       int           rc, i;

       rc = LDAP_ENCODING_ERROR;   /* the most popular error */

       /* if no controls were passed in, use global list from LDAP * */
       LDAP_MUTEX_LOCK( ld, LDAP_CTRL_LOCK );
       if ( ctrls == NULL ) {
              ctrls = ld->ld_servercontrols;
       }

       /* if there are no controls then we are done */
       if ( ctrls == NULL || ctrls[ 0 ] == NULL ) {
              goto clean_exit;
       }

       /*
        * If we're using LDAPv2 or earlier we can't send any controls, so
        * we just ignore them unless one is marked critical, in which case
        * we return an error.
        */
       if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
              for ( i = 0; ctrls != NULL && ctrls[i] != NULL; i++ ) {
                     if ( ctrls[i]->ldctl_iscritical ) {
                            rc = LDAP_NOT_SUPPORTED;
                            goto error_exit;
                     }
              }
              goto clean_exit;
       }

       /*
        * encode the controls as a Sequence of Sequence
        */
       if ( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) {
              goto error_exit;
       }

       for ( i = 0; ctrls[i] != NULL; i++ ) {
              c = ctrls[i];

              if ( ber_printf( ber, "{s", c->ldctl_oid ) == -1 ) {
                     goto error_exit;
              }

              /* criticality is "BOOLEAN DEFAULT FALSE" */
              /* therefore, it should only be encoded if it exists AND is TRUE */
              if ( c->ldctl_iscritical ) {
                     if ( ber_printf( ber, "b", (int)c->ldctl_iscritical )
                         == -1 ) {
                            goto error_exit;
                     }
              }

              if ( c->ldctl_value.bv_val != NULL ) {
                     if ( ber_printf( ber, "o", c->ldctl_value.bv_val,
                         (int)c->ldctl_value.bv_len /* XXX lossy cast */ )
                         == -1 ) {
                            goto error_exit;
                     }
              }

              if ( ber_put_seq( ber ) == -1 ) {
                     goto error_exit;
              }
       }

       if ( ber_put_seq( ber ) == -1 ) {
              goto error_exit;
       }

clean_exit:
       LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
       if ( closeseq && ber_put_seq( ber ) == -1 ) {
              goto error_exit;
       }
       return( LDAP_SUCCESS );

error_exit:
       LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
       LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
       return( rc );
}

Here is the call graph for this function:

Here is the caller graph for this function: