From 25d46e7578842557738d3f48d7f102be11a09ac6 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 22 Aug 2007 22:35:14 +0000 Subject: [PATCH] rework controls API --- doc/man/man3/ldap_controls.3 | 61 ++++++++++++++---- doc/man/man3/ldap_controls.3.links | 6 +- include/ldap.h | 28 ++++++++- libraries/libldap/controls.c | 99 +++++++++++++++++++++++++----- libraries/libldap/pagectrl.c | 17 ++--- libraries/libldap/ppolicy.c | 11 ++-- libraries/libldap/sortctrl.c | 20 +++--- libraries/libldap/stctrl.c | 10 +-- libraries/libldap/vlvctrl.c | 14 +---- servers/slapd/syncrepl.c | 11 +++- 10 files changed, 194 insertions(+), 83 deletions(-) diff --git a/doc/man/man3/ldap_controls.3 b/doc/man/man3/ldap_controls.3 index 7cb7d21ddd..413ce0817e 100644 --- a/doc/man/man3/ldap_controls.3 +++ b/doc/man/man3/ldap_controls.3 @@ -3,45 +3,80 @@ .\" Copyright 1998-2007 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME -ldap_create_control, ldap_find_control, ldap_control_free, ldap_controls_free \- LDAP control manipulation routines +ldap_control_create, ldap_control_find, ldap_control_dup, +ldap_controls_dup, ldap_control_free, ldap_controls_free +\- LDAP control manipulation routines .SH LIBRARY OpenLDAP LDAP (libldap, -lldap) .SH SYNOPSIS .B #include .LP -.BI "int ldap_create_control(LDAP_CONST char *" OID ", BerElement *" ber ", int " iscritical ", LDAPControl **" ctrlp ");" +.BI "int ldap_control_create(const char *" oid ", int " iscritical ", struct berval *" value ", int " dupval ", LDAPControl **" ctrlp ");" .LP -.BI "LDAPControl *ldap_find_control(LDAP_CONST char *" OID ", LDAPControl **" ctrls ");" +.BI "LDAPControl *ldap_control_find( const char *" oid ", LDAPControl **" ctrls ", LDAPControl ***" nextctrlp ");" +.LP +.BI "LDAPControl *ldap_control_dup(LDAPControl *" ctrl ");" +.LP +.BI "LDAPControl **ldap_controls_dup(LDAPControl **" ctrls ");" .LP .BI "void ldap_control_free(LDAPControl *" ctrl ");" .LP .BI "void ldap_controls_free(LDAPControl **" ctrls ");" .SH DESCRIPTION These routines are used to manipulate structures used for LDAP controls. -.BR ldap_create_control () + +.BR ldap_control_create () creates a control with the specified .I OID using the contents of the -.I ber -parameter for the control value, if any. The +.I value +parameter for the control value, if any. The content of +.I value +is duplicated if +.I dupval +is non-zero. The .I iscritical -parameter should be non-zero for a critical control. The created control +parameter must be non-zero for a critical control. The created control is returned in the .I ctrlp -parameter. The routine returns +parameter. The routine returns .B LDAP_SUCCESS on success or some other error code on failure. -.BR ldap_find_control () -searches the +The content of +.IR value , +for supported control types, can be prepared using helpers provided +by this implementation of libldap, usually in the form +.BR "ldap_create__control_value" (). +Otherwise, it can be BER-encoded using the functionalities of liblber. + +.BR ldap_control_find () +searches the NULL-terminated .I ctrls array for a control whose OID matches the -.I OID -parameter. The routine returns a pointer to the control if found, +.I oid +parameter. The routine returns a pointer to the control if found, NULL otherwise. +If the parameter +.I nextctrlp +is not NULL, on return it will point to the next control +in the array, and can be passed to the +.BR ldap_control_find () +routine for subsequent calls, to find further occurrences of the same +control type. +The use of this function is discouraged; the recommended way of handling +controls in responses consists in going through the array of controls, +dealing with each of them in the returned order, since it could matter. + +.BR ldap_control_dup () +duplicates an individual control structure, and +.BR ldap_controls_dup () +duplicates a NULL-terminated array of controls. + .BR ldap_control_free () frees an individual control structure, and .BR ldap_controls_free () -frees an array of controls. +frees a NULL-terminated array of controls. + .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) diff --git a/doc/man/man3/ldap_controls.3.links b/doc/man/man3/ldap_controls.3.links index 03cd358cc8..6c5248f641 100644 --- a/doc/man/man3/ldap_controls.3.links +++ b/doc/man/man3/ldap_controls.3.links @@ -1,4 +1,6 @@ -ldap_create_control.3 -ldap_find_control.3 +ldap_control_create.3 +ldap_control_find.3 +ldap_control_dup.3 +ldap_controls_dup.3 ldap_control_free.3 ldap_controls_free.3 diff --git a/include/ldap.h b/include/ldap.h index 2f217523d9..2e55abd007 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -941,17 +941,33 @@ ldap_set_urllist_proc LDAP_P(( /* * in controls.c: */ +#if LDAP_DEPRECATED LDAP_F( int ) -ldap_create_control LDAP_P(( +ldap_create_control LDAP_P(( /* deprecated, use ldap_control_create */ LDAP_CONST char *requestOID, BerElement *ber, int iscritical, LDAPControl **ctrlp )); LDAP_F( LDAPControl * ) -ldap_find_control LDAP_P(( +ldap_find_control LDAP_P(( /* deprecated, use ldap_control_find */ LDAP_CONST char *oid, LDAPControl **ctrls )); +#endif + +LDAP_F( int ) +ldap_control_create LDAP_P(( + LDAP_CONST char *requestOID, + int iscritical, + struct berval *value, + int dupval, + LDAPControl **ctrlp )); + +LDAP_F( LDAPControl * ) +ldap_control_find LDAP_P(( + LDAP_CONST char *oid, + LDAPControl **ctrls, + LDAPControl ***nextctrlp )); LDAP_F( void ) ldap_control_free LDAP_P(( @@ -961,6 +977,14 @@ LDAP_F( void ) ldap_controls_free LDAP_P(( LDAPControl **ctrls )); +LDAP_F( LDAPControl ** ) +ldap_controls_dup LDAP_P(( + LDAPControl *LDAP_CONST *controls )); + +LDAP_F( LDAPControl * ) +ldap_control_dup LDAP_P(( + LDAP_CONST LDAPControl *c )); + /* * in dnssrv.c: */ diff --git a/libraries/libldap/controls.c b/libraries/libldap/controls.c index c9847a3b7d..ab5ae46da9 100644 --- a/libraries/libldap/controls.c +++ b/libraries/libldap/controls.c @@ -382,7 +382,9 @@ ldap_control_dup( const LDAPControl *c ) return new; } - +/* + * Find a LDAPControl - deprecated + */ LDAPControl * ldap_find_control( LDAP_CONST char *oid, @@ -402,21 +404,38 @@ ldap_find_control( } /* - ldap_create_control - - Internal function to create an LDAP control from the encoded BerElement. - - requestOID (IN) The OID to use in creating the control. - - ber (IN) The encoded BerElement to use in creating the control. - - iscritical (IN) 0 - Indicates the control is not critical to the operation. - non-zero - The control is critical to the operation. - - ctrlp (OUT) Returns a pointer to the LDAPControl created. This control - SHOULD be freed by calling ldap_control_free() when done. ----*/ + * 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, @@ -434,7 +453,7 @@ ldap_create_control( return LDAP_NO_MEMORY; } - BER_BVZERO(&ctrl->ldctl_value); + BER_BVZERO(&ctrl->ldctl_value); if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) { LDAP_FREE( ctrl ); return LDAP_NO_MEMORY; @@ -452,6 +471,54 @@ ldap_create_control( 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 diff --git a/libraries/libldap/pagectrl.c b/libraries/libldap/pagectrl.c index df4978705d..93222406b1 100644 --- a/libraries/libldap/pagectrl.c +++ b/libraries/libldap/pagectrl.c @@ -139,7 +139,6 @@ ldap_create_page_control( LDAPControl **ctrlp ) { struct berval value; - BerElement *ber; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; @@ -149,19 +148,11 @@ ldap_create_page_control( ld->ld_errno = ldap_create_page_control_value( ld, pagesize, cookie, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { - if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) { - ld->ld_errno = LDAP_NO_MEMORY; - return LDAP_NO_MEMORY; - } - - ld->ld_errno = ldap_create_control( LDAP_CONTROL_PAGEDRESULTS, - ber, iscritical, ctrlp ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - (*ctrlp)->ldctl_value = value; - } else { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS, + iscritical, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } - ber_free(ber, 1); } return ld->ld_errno; @@ -256,7 +247,7 @@ ldap_parse_page_control( return ld->ld_errno; } - c = ldap_find_control( LDAP_CONTROL_PAGEDRESULTS, ctrls ); + c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( c == NULL ) { /* No page control was found. */ ld->ld_errno = LDAP_CONTROL_NOT_FOUND; diff --git a/libraries/libldap/ppolicy.c b/libraries/libldap/ppolicy.c index b82208fe76..ad7153406f 100644 --- a/libraries/libldap/ppolicy.c +++ b/libraries/libldap/ppolicy.c @@ -65,10 +65,10 @@ ldap_create_passwordpolicy_control( LDAP *ld, assert( LDAP_VALID( ld ) ); assert( ctrlp != NULL ); - ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST, - NULL, 0, ctrlp); + ld->ld_errno = ldap_control_create( LDAP_CONTROL_PASSWORDPOLICYREQUEST, + 0, NULL, 0, ctrlp ); - return(ld->ld_errno); + return ld->ld_errno; } @@ -80,8 +80,9 @@ ldap_create_passwordpolicy_control( LDAP *ld, ld (IN) An LDAP session handle. ctrl (IN) The address of an - LDAPControl structure, typically obtained - by a call to ldap_find_control(). + LDAPControl structure, either obtained + by running thorugh the list of response controls or + by a call to ldap_control_find(). exptimep (OUT) This result parameter is filled in with the number of seconds before the password will expire, if expiration is imminent diff --git a/libraries/libldap/sortctrl.c b/libraries/libldap/sortctrl.c index 0200e01dac..05c66eec09 100644 --- a/libraries/libldap/sortctrl.c +++ b/libraries/libldap/sortctrl.c @@ -408,12 +408,14 @@ ldap_create_sort_control( LDAPControl **ctrlp ) { struct berval value; - BerElement *ber; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); - if ( ld == NULL ) return LDAP_PARAM_ERROR; + if ( ld == NULL ) { + return LDAP_PARAM_ERROR; + } + if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; @@ -421,19 +423,11 @@ ldap_create_sort_control( ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { - if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) { - ld->ld_errno = LDAP_NO_MEMORY; - return LDAP_NO_MEMORY; - } - - ld->ld_errno = ldap_create_control( LDAP_CONTROL_SORTREQUEST, - ber, isCritical, ctrlp ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - (*ctrlp)->ldctl_value = value; - } else { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST, + isCritical, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } - ber_free(ber, 1); } return ld->ld_errno; diff --git a/libraries/libldap/stctrl.c b/libraries/libldap/stctrl.c index bfec5c44e7..4dc197cb6c 100644 --- a/libraries/libldap/stctrl.c +++ b/libraries/libldap/stctrl.c @@ -137,7 +137,6 @@ ldap_create_session_tracking_control( LDAPControl **ctrlp ) { struct berval value; - BerElement *ber; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; @@ -148,12 +147,9 @@ ldap_create_session_tracking_control( sessionSourceIp, sessionSourceName, formatOID, sessionTrackingIdentifier, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { - ld->ld_errno = ldap_create_control( LDAP_CONTROL_X_SESSION_TRACKING, - NULL, 0, ctrlp ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - (*ctrlp)->ldctl_value = value; - - } else { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING, + 0, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } diff --git a/libraries/libldap/vlvctrl.c b/libraries/libldap/vlvctrl.c index f301a2e641..f0c4cb446e 100644 --- a/libraries/libldap/vlvctrl.c +++ b/libraries/libldap/vlvctrl.c @@ -210,7 +210,6 @@ ldap_create_vlv_control( LDAPControl **ctrlp ) { struct berval value; - BerElement *ber; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; @@ -219,19 +218,12 @@ ldap_create_vlv_control( ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { - if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) { - ld->ld_errno = LDAP_NO_MEMORY; - return LDAP_NO_MEMORY; - } - ld->ld_errno = ldap_create_control( LDAP_CONTROL_VLVREQUEST, - ber, 1, ctrlp ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - (*ctrlp)->ldctl_value = value; - } else { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST, + 1, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } - ber_free(ber, 1); } return ld->ld_errno; diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index f4a9c39531..cad1a1a218 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -742,10 +742,19 @@ do_syncrep2( /* we can't work without the control */ rctrlp = NULL; if ( rctrls ) { + LDAPControl **next; /* NOTE: make sure we use the right one; * a better approach would be to run thru * the whole list and take care of all */ - rctrlp = ldap_find_control( LDAP_CONTROL_SYNC_STATE, rctrls ); + rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_STATE, rctrls, &next ); + if ( next && ldap_control_find( LDAP_CONTROL_SYNC_STATE, next, NULL ) ) + { + Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " + "got search entry with multiple " + "Sync State control\n", si->si_ridtxt, 0, 0 ); + rc = -1; + goto done; + } } if ( rctrlp == NULL ) { Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " -- 2.39.5