mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-18 11:05:48 +08:00
add support for (experimental) dereference control (ITS#5768); need to re-run autoconf (and autoheader?)
This commit is contained in:
parent
382bb4de11
commit
91e14ca638
@ -135,6 +135,9 @@ static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
|
|||||||
static int print_ppolicy( LDAP *ld, LDAPControl *ctrl );
|
static int print_ppolicy( LDAP *ld, LDAPControl *ctrl );
|
||||||
#endif
|
#endif
|
||||||
static int print_sss( LDAP *ld, LDAPControl *ctrl );
|
static int print_sss( LDAP *ld, LDAPControl *ctrl );
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
static int print_deref( LDAP *ld, LDAPControl *ctrl );
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct tool_ctrls_t {
|
static struct tool_ctrls_t {
|
||||||
const char *oid;
|
const char *oid;
|
||||||
@ -148,6 +151,9 @@ static struct tool_ctrls_t {
|
|||||||
{ LDAP_CONTROL_PASSWORDPOLICYRESPONSE, TOOL_ALL, print_ppolicy },
|
{ LDAP_CONTROL_PASSWORDPOLICYRESPONSE, TOOL_ALL, print_ppolicy },
|
||||||
#endif
|
#endif
|
||||||
{ LDAP_CONTROL_SORTRESPONSE, TOOL_SEARCH, print_sss },
|
{ LDAP_CONTROL_SORTRESPONSE, TOOL_SEARCH, print_sss },
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
{ LDAP_CONTROL_X_DEREF, TOOL_SEARCH, print_deref },
|
||||||
|
#endif
|
||||||
{ NULL, 0, NULL }
|
{ NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1890,6 +1896,76 @@ print_sss( LDAP *ld, LDAPControl *ctrl )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
static int
|
||||||
|
print_deref( LDAP *ld, LDAPControl *ctrl )
|
||||||
|
{
|
||||||
|
LDAPDerefRes *drhead = NULL, *dr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ldap_parse_derefresponse_control( ld, ctrl, &drhead );
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( dr = drhead; dr != NULL; dr = dr->next ) {
|
||||||
|
LDAPDerefVal *dv;
|
||||||
|
ber_len_t len;
|
||||||
|
char *buf, *ptr;
|
||||||
|
|
||||||
|
len = strlen( dr->derefAttr ) + STRLENOF(": ");
|
||||||
|
|
||||||
|
for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
|
||||||
|
if ( dv->vals != NULL ) {
|
||||||
|
int j;
|
||||||
|
ber_len_t tlen = strlen(dv->type);
|
||||||
|
|
||||||
|
for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
|
||||||
|
len += STRLENOF("<=>;") + tlen + dv->vals[ j ].bv_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len += dr->derefVal.bv_len;
|
||||||
|
buf = ldap_memalloc( len + 1 );
|
||||||
|
if ( buf == NULL ) {
|
||||||
|
rc = LDAP_NO_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = buf;
|
||||||
|
ptr = lutil_strcopy( ptr, dr->derefAttr );
|
||||||
|
*ptr++ = ':';
|
||||||
|
*ptr++ = ' ';
|
||||||
|
for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
|
||||||
|
if ( dv->vals != NULL ) {
|
||||||
|
int j;
|
||||||
|
for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
|
||||||
|
*ptr++ = '<';
|
||||||
|
ptr = lutil_strcopy( ptr, dv->type );
|
||||||
|
*ptr++ = '=';
|
||||||
|
ptr = lutil_strncopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
|
||||||
|
*ptr++ = '>';
|
||||||
|
*ptr++ = ';';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len );
|
||||||
|
*ptr++ = '\0';
|
||||||
|
|
||||||
|
tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, len );
|
||||||
|
|
||||||
|
ldap_memfree( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
done:;
|
||||||
|
ldap_derefresponse_free( drhead );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
|
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
|
||||||
static int
|
static int
|
||||||
print_ppolicy( LDAP *ld, LDAPControl *ctrl )
|
print_ppolicy( LDAP *ld, LDAPControl *ctrl )
|
||||||
|
@ -223,6 +223,12 @@ static LDAPControl *c = NULL;
|
|||||||
static int nctrls = 0;
|
static int nctrls = 0;
|
||||||
static int save_nctrls = 0;
|
static int save_nctrls = 0;
|
||||||
|
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
static int derefcrit;
|
||||||
|
static LDAPDerefSpec *ds;
|
||||||
|
static struct berval derefval;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ctrl_add( void )
|
ctrl_add( void )
|
||||||
{
|
{
|
||||||
@ -491,6 +497,43 @@ handle_private_option( int i )
|
|||||||
}
|
}
|
||||||
if ( crit ) ldapsync *= -1;
|
if ( crit ) ldapsync *= -1;
|
||||||
|
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
} else if ( strcasecmp( control, "deref" ) == 0 ) {
|
||||||
|
int ispecs;
|
||||||
|
char **specs;
|
||||||
|
|
||||||
|
/* cvalue is something like
|
||||||
|
*
|
||||||
|
* derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]"
|
||||||
|
*/
|
||||||
|
|
||||||
|
specs = ldap_str2charray( cvalue, ";" );
|
||||||
|
for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
|
||||||
|
/* count'em */
|
||||||
|
|
||||||
|
ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
|
||||||
|
if ( ds == NULL ) {
|
||||||
|
/* error */
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr = strchr( specs[ ispecs ], ':' );
|
||||||
|
if ( ptr == NULL ) {
|
||||||
|
/* error */
|
||||||
|
}
|
||||||
|
|
||||||
|
ds[ ispecs ].derefAttr = specs[ ispecs ];
|
||||||
|
*ptr++ = '\0';
|
||||||
|
ds[ ispecs ].attributes = ldap_str2charray( ptr, "," );
|
||||||
|
}
|
||||||
|
|
||||||
|
derefcrit = 1 + crit;
|
||||||
|
|
||||||
|
ldap_memfree( specs );
|
||||||
|
#endif /* LDAP_CONTROL_X_DEREF */
|
||||||
|
|
||||||
} else if ( tool_is_oid( control ) ) {
|
} else if ( tool_is_oid( control ) ) {
|
||||||
if ( ctrl_add() ) {
|
if ( ctrl_add() ) {
|
||||||
exit( EXIT_FAILURE );
|
exit( EXIT_FAILURE );
|
||||||
@ -780,6 +823,9 @@ getNextPage:
|
|||||||
if ( nctrls > 0
|
if ( nctrls > 0
|
||||||
#ifdef LDAP_CONTROL_DONTUSECOPY
|
#ifdef LDAP_CONTROL_DONTUSECOPY
|
||||||
|| dontUseCopy
|
|| dontUseCopy
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
|| derefcrit
|
||||||
#endif
|
#endif
|
||||||
|| domainScope
|
|| domainScope
|
||||||
|| pagedResults
|
|| pagedResults
|
||||||
@ -933,6 +979,32 @@ getNextPage:
|
|||||||
c[i].ldctl_iscritical = sss > 1;
|
c[i].ldctl_iscritical = sss > 1;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
if ( ds ) {
|
||||||
|
if ( derefval.bv_val == NULL ) {
|
||||||
|
int i;
|
||||||
|
if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) {
|
||||||
|
ldap_memfree( ds[ i ].derefAttr );
|
||||||
|
ldap_charray_free( ds[ i ].attributes );
|
||||||
|
}
|
||||||
|
ldap_memfree( ds );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ctrl_add() ) {
|
||||||
|
exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
c[ i ].ldctl_iscritical = derefcrit > 1;
|
||||||
|
c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF;
|
||||||
|
c[ i ].ldctl_value = derefval;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif /* LDAP_CONTROL_X_DEREF */
|
||||||
}
|
}
|
||||||
|
|
||||||
tool_server_controls( ld, c, i );
|
tool_server_controls( ld, c, i );
|
||||||
@ -1019,6 +1091,12 @@ getNextPage:
|
|||||||
printf(_("\n# with server side sorting %scontrol"),
|
printf(_("\n# with server side sorting %scontrol"),
|
||||||
sss > 1 ? _("critical ") : "" );
|
sss > 1 ? _("critical ") : "" );
|
||||||
}
|
}
|
||||||
|
#ifdef LDAP_CONTROL_X_DEREF
|
||||||
|
if ( sss ) {
|
||||||
|
printf(_("\n# with dereference %scontrol"),
|
||||||
|
sss > 1 ? _("critical ") : "" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
printf( _("\n#\n\n") );
|
printf( _("\n#\n\n") );
|
||||||
|
|
||||||
|
15
configure.in
15
configure.in
@ -338,6 +338,7 @@ Overlays="accesslog \
|
|||||||
collect \
|
collect \
|
||||||
constraint \
|
constraint \
|
||||||
dds \
|
dds \
|
||||||
|
deref \
|
||||||
dyngroup \
|
dyngroup \
|
||||||
dynlist \
|
dynlist \
|
||||||
memberof \
|
memberof \
|
||||||
@ -367,6 +368,8 @@ OL_ARG_ENABLE(constraint,[ --enable-constraint Attribute Constraint overlay
|
|||||||
no, [no yes mod], ol_enable_overlays)
|
no, [no yes mod], ol_enable_overlays)
|
||||||
OL_ARG_ENABLE(dds,[ --enable-dds Dynamic Directory Services overlay],
|
OL_ARG_ENABLE(dds,[ --enable-dds Dynamic Directory Services overlay],
|
||||||
no, [no yes mod], ol_enable_overlays)
|
no, [no yes mod], ol_enable_overlays)
|
||||||
|
OL_ARG_ENABLE(deref,[ --enable-deref Dereference overlay],
|
||||||
|
no, [no yes mod], ol_enable_overlays)
|
||||||
OL_ARG_ENABLE(dyngroup,[ --enable-dyngroup Dynamic Group overlay],
|
OL_ARG_ENABLE(dyngroup,[ --enable-dyngroup Dynamic Group overlay],
|
||||||
no, [no yes mod], ol_enable_overlays)
|
no, [no yes mod], ol_enable_overlays)
|
||||||
OL_ARG_ENABLE(dynlist,[ --enable-dynlist Dynamic List overlay],
|
OL_ARG_ENABLE(dynlist,[ --enable-dynlist Dynamic List overlay],
|
||||||
@ -2846,6 +2849,18 @@ if test "$ol_enable_dds" != no ; then
|
|||||||
AC_DEFINE_UNQUOTED(SLAPD_OVER_DDS,$MFLAG,[define for Dynamic Directory Services overlay])
|
AC_DEFINE_UNQUOTED(SLAPD_OVER_DDS,$MFLAG,[define for Dynamic Directory Services overlay])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$ol_enable_deref" != no ; then
|
||||||
|
BUILD_DDS=$ol_enable_deref
|
||||||
|
if test "$ol_enable_deref" = mod ; then
|
||||||
|
MFLAG=SLAPD_MOD_DYNAMIC
|
||||||
|
SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS deref.la"
|
||||||
|
else
|
||||||
|
MFLAG=SLAPD_MOD_STATIC
|
||||||
|
SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS deref.o"
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED(SLAPD_OVER_DEREF,$MFLAG,[define for Dynamic Directory Services overlay])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$ol_enable_dyngroup" != no ; then
|
if test "$ol_enable_dyngroup" != no ; then
|
||||||
BUILD_DYNGROUP=$ol_enable_dyngroup
|
BUILD_DYNGROUP=$ol_enable_dyngroup
|
||||||
if test "$ol_enable_dyngroup" = mod ; then
|
if test "$ol_enable_dyngroup" = mod ; then
|
||||||
|
@ -321,6 +321,8 @@ typedef struct ldapcontrol {
|
|||||||
LDAP_CONTROL_X_SESSION_TRACKING ".2"
|
LDAP_CONTROL_X_SESSION_TRACKING ".2"
|
||||||
#define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \
|
#define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \
|
||||||
LDAP_CONTROL_X_SESSION_TRACKING ".3"
|
LDAP_CONTROL_X_SESSION_TRACKING ".3"
|
||||||
|
/* Dereference Control (work in progress) */
|
||||||
|
#define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16"
|
||||||
#endif /* LDAP_DEVEL */
|
#endif /* LDAP_DEVEL */
|
||||||
|
|
||||||
/* various expired works */
|
/* various expired works */
|
||||||
@ -2400,5 +2402,56 @@ ldap_create_assertion_control LDAP_P((
|
|||||||
int iscritical,
|
int iscritical,
|
||||||
LDAPControl **ctrlp ));
|
LDAPControl **ctrlp ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in deref.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct LDAPDerefSpec {
|
||||||
|
char *derefAttr;
|
||||||
|
char **attributes;
|
||||||
|
} LDAPDerefSpec;
|
||||||
|
|
||||||
|
typedef struct LDAPDerefVal {
|
||||||
|
char *type;
|
||||||
|
BerVarray vals;
|
||||||
|
struct LDAPDerefVal *next;
|
||||||
|
} LDAPDerefVal;
|
||||||
|
|
||||||
|
typedef struct LDAPDerefRes {
|
||||||
|
char *derefAttr;
|
||||||
|
struct berval derefVal;
|
||||||
|
LDAPDerefVal *attrVals;
|
||||||
|
struct LDAPDerefRes *next;
|
||||||
|
} LDAPDerefRes;
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_create_deref_control_value LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPDerefSpec *ds,
|
||||||
|
struct berval *value ));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_create_deref_control LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPDerefSpec *ds,
|
||||||
|
int iscritical,
|
||||||
|
LDAPControl **ctrlp ));
|
||||||
|
|
||||||
|
LDAP_F( void )
|
||||||
|
ldap_derefresponse_free LDAP_P((
|
||||||
|
LDAPDerefRes *dr ));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_parse_derefresponse_control LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl *ctrl,
|
||||||
|
LDAPDerefRes **drp ));
|
||||||
|
|
||||||
|
LDAP_F( int )
|
||||||
|
ldap_parse_deref_control LDAP_P((
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl **ctrls,
|
||||||
|
LDAPDerefRes **drp ));
|
||||||
|
|
||||||
LDAP_END_DECL
|
LDAP_END_DECL
|
||||||
#endif /* _LDAP_H */
|
#endif /* _LDAP_H */
|
||||||
|
@ -978,6 +978,9 @@
|
|||||||
/* define for Dynamic Directory Services overlay */
|
/* define for Dynamic Directory Services overlay */
|
||||||
#undef SLAPD_OVER_DDS
|
#undef SLAPD_OVER_DDS
|
||||||
|
|
||||||
|
/* define for Dynamic Directory Services overlay */
|
||||||
|
#undef SLAPD_OVER_DEREF
|
||||||
|
|
||||||
/* define for Dynamic Group overlay */
|
/* define for Dynamic Group overlay */
|
||||||
#undef SLAPD_OVER_DYNGROUP
|
#undef SLAPD_OVER_DYNGROUP
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \
|
|||||||
init.c options.c print.c string.c util-int.c schema.c \
|
init.c options.c print.c string.c util-int.c schema.c \
|
||||||
charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
|
charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
|
||||||
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
|
||||||
assertion.c
|
assertion.c deref.c
|
||||||
|
|
||||||
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
||||||
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
||||||
@ -39,7 +39,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
|||||||
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
|
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
|
||||||
charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
|
charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
|
||||||
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
|
||||||
assertion.lo
|
assertion.lo deref.lo
|
||||||
|
|
||||||
LDAP_INCDIR= ../../include
|
LDAP_INCDIR= ../../include
|
||||||
LDAP_LIBDIR= ../../libraries
|
LDAP_LIBDIR= ../../libraries
|
||||||
|
279
libraries/libldap/deref.c
Normal file
279
libraries/libldap/deref.c
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 1998-2008 The OpenLDAP Foundation.
|
||||||
|
* Portions Copyright 2008 Pierangelo Masarati.
|
||||||
|
* 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Pierangelo Masarati
|
||||||
|
* for inclusion in OpenLDAP Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/stdlib.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/time.h>
|
||||||
|
|
||||||
|
#include "ldap-int.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_create_deref_control_value(
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPDerefSpec *ds,
|
||||||
|
struct berval *value )
|
||||||
|
{
|
||||||
|
BerElement *ber = NULL;
|
||||||
|
ber_tag_t tag;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( ld == NULL || value == NULL || ds == NULL )
|
||||||
|
{
|
||||||
|
if ( ld )
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( LDAP_VALID( ld ) );
|
||||||
|
|
||||||
|
value->bv_val = NULL;
|
||||||
|
value->bv_len = 0;
|
||||||
|
ld->ld_errno = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
ber = ldap_alloc_ber_with_options( ld );
|
||||||
|
if ( ber == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ber_printf( ber, "{" /*}*/ );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; ds[i].derefAttr != NULL; i++ ) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
tag = ber_printf( ber, "{s{" /*}}*/ , ds[i].derefAttr );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( j = 0; ds[i].attributes[j] != NULL; j++ ) {
|
||||||
|
tag = ber_printf( ber, "s", ds[i].attributes[ j ] );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ber_printf( ber, /*{{*/ "}N}" );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ber_printf( ber, /*{*/ "}" );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ber_flatten2( ber, value, 1 ) == -1 ) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:;
|
||||||
|
if ( ber != NULL ) {
|
||||||
|
ber_free( ber, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_create_deref_control(
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPDerefSpec *ds,
|
||||||
|
int iscritical,
|
||||||
|
LDAPControl **ctrlp )
|
||||||
|
{
|
||||||
|
struct berval value;
|
||||||
|
|
||||||
|
if ( ctrlp == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ld->ld_errno = ldap_create_deref_control_value( ld, ds, &value );
|
||||||
|
if ( ld->ld_errno == LDAP_SUCCESS ) {
|
||||||
|
ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
|
||||||
|
iscritical, &value, 0, ctrlp );
|
||||||
|
if ( ld->ld_errno != LDAP_SUCCESS ) {
|
||||||
|
LDAP_FREE( value.bv_val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldap_derefresponse_free( LDAPDerefRes *dr )
|
||||||
|
{
|
||||||
|
for ( ; dr; ) {
|
||||||
|
LDAPDerefRes *drnext = dr->next;
|
||||||
|
LDAPDerefVal *dv;
|
||||||
|
|
||||||
|
LDAP_FREE( dr->derefAttr );
|
||||||
|
LDAP_FREE( dr->derefVal.bv_val );
|
||||||
|
|
||||||
|
for ( dv = dr->attrVals; dv; ) {
|
||||||
|
LDAPDerefVal *dvnext = dv->next;
|
||||||
|
LDAP_FREE( dv->type );
|
||||||
|
ber_bvarray_free( dv->vals );
|
||||||
|
LDAP_FREE( dv );
|
||||||
|
dv = dvnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
LDAP_FREE( dr );
|
||||||
|
|
||||||
|
dr = drnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_parse_derefresponse_control(
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl *ctrl,
|
||||||
|
LDAPDerefRes **drp2 )
|
||||||
|
{
|
||||||
|
BerElement *ber;
|
||||||
|
ber_tag_t tag;
|
||||||
|
ber_len_t len;
|
||||||
|
char *last;
|
||||||
|
LDAPDerefRes *drhead = NULL, **drp;
|
||||||
|
|
||||||
|
if ( ld == NULL || ctrl == NULL || drp2 == NULL ) {
|
||||||
|
if ( ld )
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return LDAP_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a BerElement from the berval returned in the control. */
|
||||||
|
ber = ber_init( &ctrl->ldctl_value );
|
||||||
|
|
||||||
|
if ( ber == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_NO_MEMORY;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the count and cookie from the control. */
|
||||||
|
drp = &drhead;
|
||||||
|
for ( tag = ber_first_element( ber, &len, &last );
|
||||||
|
tag != LBER_DEFAULT;
|
||||||
|
tag = ber_next_element( ber, &len, last ) )
|
||||||
|
{
|
||||||
|
LDAPDerefRes *dr;
|
||||||
|
LDAPDerefVal **dvp;
|
||||||
|
char *last2;
|
||||||
|
|
||||||
|
dr = LDAP_CALLOC( 1, sizeof(LDAPDerefRes) );
|
||||||
|
dvp = &dr->attrVals;
|
||||||
|
|
||||||
|
tag = ber_scanf( ber, "{ao", &dr->derefAttr, &dr->derefVal );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( tag = ber_first_element( ber, &len, &last2 );
|
||||||
|
tag != LBER_DEFAULT;
|
||||||
|
tag = ber_next_element( ber, &len, last2 ) )
|
||||||
|
{
|
||||||
|
LDAPDerefVal *dv;
|
||||||
|
|
||||||
|
dv = LDAP_CALLOC( 1, sizeof(LDAPDerefVal) );
|
||||||
|
|
||||||
|
tag = ber_scanf( ber, "{a[W]}", &dv->type, &dv->vals );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dvp = dv;
|
||||||
|
dvp = &dv->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ber_scanf( ber, "}" );
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
*drp = dr;
|
||||||
|
drp = &dr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = 0;
|
||||||
|
|
||||||
|
done:;
|
||||||
|
ber_free( ber, 1 );
|
||||||
|
|
||||||
|
if ( tag == LBER_ERROR ) {
|
||||||
|
if ( drhead != NULL ) {
|
||||||
|
ldap_derefresponse_free( drhead );
|
||||||
|
}
|
||||||
|
|
||||||
|
*drp2 = NULL;
|
||||||
|
ld->ld_errno = LDAP_DECODING_ERROR;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*drp2 = drhead;
|
||||||
|
ld->ld_errno = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_parse_deref_control(
|
||||||
|
LDAP *ld,
|
||||||
|
LDAPControl **ctrls,
|
||||||
|
LDAPDerefRes **drp )
|
||||||
|
{
|
||||||
|
LDAPControl *c;
|
||||||
|
|
||||||
|
if ( drp == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
*drp = NULL;
|
||||||
|
|
||||||
|
if ( ctrls == NULL ) {
|
||||||
|
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = ldap_control_find( LDAP_CONTROL_X_DEREF, ctrls, NULL );
|
||||||
|
if ( c == NULL ) {
|
||||||
|
/* No deref control was found. */
|
||||||
|
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ld->ld_errno = ldap_parse_derefresponse_control( ld, c, drp );
|
||||||
|
|
||||||
|
return ld->ld_errno;
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ SRCS = overlays.c \
|
|||||||
auditlog.c \
|
auditlog.c \
|
||||||
constraint.c \
|
constraint.c \
|
||||||
dds.c \
|
dds.c \
|
||||||
|
deref.c \
|
||||||
dyngroup.c \
|
dyngroup.c \
|
||||||
dynlist.c \
|
dynlist.c \
|
||||||
memberof.c \
|
memberof.c \
|
||||||
@ -72,6 +73,9 @@ constraint.la : constraint.lo
|
|||||||
dds.la : dds.lo
|
dds.la : dds.lo
|
||||||
$(LTLINK_MOD) -module -o $@ dds.lo version.lo $(LINK_LIBS)
|
$(LTLINK_MOD) -module -o $@ dds.lo version.lo $(LINK_LIBS)
|
||||||
|
|
||||||
|
deref.la : deref.lo
|
||||||
|
$(LTLINK_MOD) -module -o $@ deref.lo version.lo $(LINK_LIBS)
|
||||||
|
|
||||||
dyngroup.la : dyngroup.lo
|
dyngroup.la : dyngroup.lo
|
||||||
$(LTLINK_MOD) -module -o $@ dyngroup.lo version.lo $(LINK_LIBS)
|
$(LTLINK_MOD) -module -o $@ dyngroup.lo version.lo $(LINK_LIBS)
|
||||||
|
|
||||||
|
517
servers/slapd/overlays/deref.c
Normal file
517
servers/slapd/overlays/deref.c
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
/* deref.c - dereference overlay */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 1998-2008 The OpenLDAP Foundation.
|
||||||
|
* Portions Copyright 2008 Pierangelo Masarati.
|
||||||
|
* 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Pierangelo Masarati
|
||||||
|
* for inclusion in OpenLDAP Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#ifdef SLAPD_OVER_DEREF
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ac/string.h"
|
||||||
|
#include "ac/socket.h"
|
||||||
|
|
||||||
|
#include "slap.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "lutil.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Specification
|
||||||
|
*
|
||||||
|
* 1.1. Request
|
||||||
|
*
|
||||||
|
* controlValue ::= SEQUENCE OF derefSpec DerefSpec
|
||||||
|
*
|
||||||
|
* DerefSpec ::= SEQUENCE {
|
||||||
|
* derefAttr attributeDescription, ; DN-valued
|
||||||
|
* attributes AttributeList }
|
||||||
|
*
|
||||||
|
* AttributeList ::= SEQUENCE OF attr AttributeDescription
|
||||||
|
*
|
||||||
|
* derefAttr MUST be unique within controlValue
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 1.2. Response
|
||||||
|
*
|
||||||
|
* controlValue ::= SEQUENCE OF DerefRes
|
||||||
|
*
|
||||||
|
* From RFC 4511:
|
||||||
|
* PartialAttribute ::= SEQUENCE {
|
||||||
|
* type AttributeDescription,
|
||||||
|
* vals SET OF value AttributeValue }
|
||||||
|
*
|
||||||
|
* PartialAttributeList ::= SEQUENCE OF
|
||||||
|
* partialAttribute PartialAttribute
|
||||||
|
*
|
||||||
|
* DerefRes ::= SEQUENCE {
|
||||||
|
* derefAttr AttributeDescription,
|
||||||
|
* derefVal LDAPDN,
|
||||||
|
* attrVals PartialAttributeList OPTIONAL }
|
||||||
|
*
|
||||||
|
* If vals is empty, partialAttribute is omitted.
|
||||||
|
* If all vals in attrVals are empty, attrVals is omitted.
|
||||||
|
*
|
||||||
|
* 2. Examples
|
||||||
|
*
|
||||||
|
* 2.1. Example
|
||||||
|
*
|
||||||
|
* 2.1.1. Request
|
||||||
|
*
|
||||||
|
* { { member, { GUID, SID } }, { memberOf, { GUID, SID } } }
|
||||||
|
*
|
||||||
|
* 2.1.2. Response
|
||||||
|
*
|
||||||
|
* { { memberOf, "cn=abartlet,cn=users,dc=abartlet,dc=net",
|
||||||
|
* { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fa" ],
|
||||||
|
* SID, [ "S-1-2-3-2345" ] } },
|
||||||
|
* { memberOf, "cn=ando,cn=users,dc=sys-net,dc=it",
|
||||||
|
* { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fb" ],
|
||||||
|
* SID, [ "S-1-2-3-2346" ] } } }
|
||||||
|
*
|
||||||
|
* 2.2. Example
|
||||||
|
*
|
||||||
|
* 2.2.1. Request
|
||||||
|
*
|
||||||
|
* { { member, { cn, uid, drink } } }
|
||||||
|
*
|
||||||
|
* 2.2.2. Response
|
||||||
|
*
|
||||||
|
* { { member, "cn=ando,cn=users,dc=sys-net,dc=it",
|
||||||
|
* { cn, [ "ando", "Pierangelo Masarati" ],
|
||||||
|
* uid, [ "ando" ] } } }
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define o_deref o_ctrlflag[deref_cid]
|
||||||
|
#define o_ctrlderef o_controls[deref_cid]
|
||||||
|
|
||||||
|
typedef struct DerefSpec {
|
||||||
|
AttributeDescription *ds_derefAttr;
|
||||||
|
AttributeDescription **ds_attributes;
|
||||||
|
int ds_nattrs;
|
||||||
|
struct DerefSpec *ds_next;
|
||||||
|
} DerefSpec;
|
||||||
|
|
||||||
|
typedef struct DerefVal {
|
||||||
|
struct berval dv_derefSpecVal;
|
||||||
|
BerVarray *dv_attrVals;
|
||||||
|
} DerefVal;
|
||||||
|
|
||||||
|
typedef struct DerefRes {
|
||||||
|
DerefSpec dr_spec;
|
||||||
|
DerefVal *dr_vals;
|
||||||
|
struct DerefRes *dr_next;
|
||||||
|
} DerefRes;
|
||||||
|
|
||||||
|
typedef struct deref_cb_t {
|
||||||
|
slap_overinst *dc_on;
|
||||||
|
DerefSpec *dc_ds;
|
||||||
|
} deref_cb_t;
|
||||||
|
|
||||||
|
static int deref_cid;
|
||||||
|
static slap_overinst deref;
|
||||||
|
|
||||||
|
static int
|
||||||
|
deref_parseCtrl (
|
||||||
|
Operation *op,
|
||||||
|
SlapReply *rs,
|
||||||
|
LDAPControl *ctrl )
|
||||||
|
{
|
||||||
|
ber_tag_t tag;
|
||||||
|
BerElementBuffer berbuf;
|
||||||
|
BerElement *ber = (BerElement *)&berbuf;
|
||||||
|
ber_len_t len;
|
||||||
|
char *last;
|
||||||
|
DerefSpec *dshead = NULL, **dsp = &dshead;
|
||||||
|
BerVarray attributes = NULL;
|
||||||
|
|
||||||
|
if ( op->o_deref != SLAP_CONTROL_NONE ) {
|
||||||
|
rs->sr_text = "Dereference control specified multiple times";
|
||||||
|
return LDAP_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
|
||||||
|
rs->sr_text = "Dereference control value is absent";
|
||||||
|
return LDAP_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
|
||||||
|
rs->sr_text = "Dereference control value is empty";
|
||||||
|
return LDAP_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ber_init2( ber, &ctrl->ldctl_value, 0 );
|
||||||
|
|
||||||
|
for ( tag = ber_first_element( ber, &len, &last );
|
||||||
|
tag != LBER_DEFAULT;
|
||||||
|
tag = ber_next_element( ber, &len, last ) )
|
||||||
|
{
|
||||||
|
struct berval derefAttr;
|
||||||
|
DerefSpec *ds, *dstmp;
|
||||||
|
const char *text;
|
||||||
|
int rc;
|
||||||
|
ber_len_t cnt = sizeof(struct berval);
|
||||||
|
ber_len_t off = 0;
|
||||||
|
|
||||||
|
if ( ber_scanf( ber, "{m{M}}", &derefAttr, &attributes, &cnt, off ) == LBER_ERROR )
|
||||||
|
{
|
||||||
|
rs->sr_text = "Dereference control: derefSpec decoding error";
|
||||||
|
rs->sr_err = LDAP_PROTOCOL_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ds = (DerefSpec *)op->o_tmpcalloc( 1,
|
||||||
|
sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1),
|
||||||
|
op->o_tmpmemctx );
|
||||||
|
ds->ds_attributes = (AttributeDescription **)&ds[1];
|
||||||
|
ds->ds_nattrs = cnt;
|
||||||
|
|
||||||
|
rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text );
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
rs->sr_text = "Dereference control: derefAttr decoding error";
|
||||||
|
rs->sr_err = LDAP_PROTOCOL_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( dstmp = dshead; dstmp && dstmp != ds; dstmp = dstmp->ds_next ) {
|
||||||
|
if ( dstmp->ds_derefAttr == ds->ds_derefAttr ) {
|
||||||
|
rs->sr_text = "Dereference control: derefAttr must be unique within control";
|
||||||
|
rs->sr_err = LDAP_PROTOCOL_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ds->ds_derefAttr->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
|
||||||
|
if ( ctrl->ldctl_iscritical ) {
|
||||||
|
rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName";
|
||||||
|
rs->sr_err = LDAP_PROTOCOL_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
goto justcleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( cnt = 0; !BER_BVISNULL( &attributes[ cnt ] ); cnt++ ) {
|
||||||
|
rc = slap_bv2ad( &attributes[ cnt ], &ds->ds_attributes[ cnt ], &text );
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
rs->sr_text = "Dereference control: attribute decoding error";
|
||||||
|
rs->sr_err = LDAP_PROTOCOL_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ber_memfree_x( attributes, op->o_tmpmemctx );
|
||||||
|
attributes = NULL;
|
||||||
|
|
||||||
|
*dsp = ds;
|
||||||
|
dsp = &ds->ds_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
op->o_ctrlderef = (void *)dshead;
|
||||||
|
|
||||||
|
op->o_deref = ctrl->ldctl_iscritical
|
||||||
|
? SLAP_CONTROL_CRITICAL
|
||||||
|
: SLAP_CONTROL_NONCRITICAL;
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
done:;
|
||||||
|
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
justcleanup:;
|
||||||
|
for ( ; dshead; ) {
|
||||||
|
DerefSpec *dsnext = dshead->ds_next;
|
||||||
|
op->o_tmpfree( dshead, op->o_tmpmemctx );
|
||||||
|
dshead = dsnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( attributes != NULL ) {
|
||||||
|
ber_memfree_x( attributes, op->o_tmpmemctx );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
deref_response( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
int rc = SLAP_CB_CONTINUE;
|
||||||
|
|
||||||
|
if ( rs->sr_type == REP_SEARCH ) {
|
||||||
|
BerElementBuffer berbuf;
|
||||||
|
BerElement *ber = (BerElement *) &berbuf;
|
||||||
|
deref_cb_t *dc = (deref_cb_t *)op->o_callback->sc_private;
|
||||||
|
DerefSpec *ds;
|
||||||
|
DerefRes *dr, *drhead = NULL, **drp = &drhead;
|
||||||
|
BackendInfo *bi = op->o_bd->bd_info;
|
||||||
|
struct berval bv = BER_BVNULL;
|
||||||
|
int nDerefRes = 0, nDerefVals = 0, nAttrs = 0, nVals = 0;
|
||||||
|
struct berval ctrlval;
|
||||||
|
LDAPControl *ctrl, **ctrlsp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
op->o_bd->bd_info = (BackendInfo *)dc->dc_on->on_info;
|
||||||
|
for ( ds = dc->dc_ds; ds; ds = ds->ds_next ) {
|
||||||
|
Attribute *a = attr_find( rs->sr_entry->e_attrs, ds->ds_derefAttr );
|
||||||
|
|
||||||
|
if ( a != NULL ) {
|
||||||
|
DerefVal *dv;
|
||||||
|
BerVarray *bva;
|
||||||
|
|
||||||
|
dr = op->o_tmpcalloc( 1,
|
||||||
|
sizeof( DerefRes ) + ( sizeof( DerefVal ) + sizeof( BerVarray * ) * ds->ds_nattrs ) * ( a->a_numvals + 1 ),
|
||||||
|
op->o_tmpmemctx );
|
||||||
|
dr->dr_spec = *ds;
|
||||||
|
dv = dr->dr_vals = (DerefVal *)&dr[ 1 ];
|
||||||
|
bva = (BerVarray *)&dv[ a->a_numvals + 1 ];
|
||||||
|
|
||||||
|
bv.bv_len += ds->ds_derefAttr->ad_cname.bv_len;
|
||||||
|
nAttrs++;
|
||||||
|
nDerefRes++;
|
||||||
|
|
||||||
|
for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
|
||||||
|
Entry *e = NULL;
|
||||||
|
|
||||||
|
dv[ i ].dv_attrVals = bva;
|
||||||
|
bva += ds->ds_nattrs;
|
||||||
|
|
||||||
|
dv[i].dv_derefSpecVal = a->a_vals[ i ];
|
||||||
|
bv.bv_len += dv[i].dv_derefSpecVal.bv_len;
|
||||||
|
nVals++;
|
||||||
|
nDerefVals++;
|
||||||
|
|
||||||
|
rc = overlay_entry_get_ov( op, &a->a_nvals[ i ], NULL, NULL, 0, &e, dc->dc_on );
|
||||||
|
if ( rc == LDAP_SUCCESS && e != NULL ) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for ( j = 0; j < ds->ds_nattrs; j++ ) {
|
||||||
|
Attribute *aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] );
|
||||||
|
if ( aa != NULL ) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
dv[i].dv_attrVals[ j ] = aa->a_vals;
|
||||||
|
|
||||||
|
bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len;
|
||||||
|
for ( k = 0; !BER_BVISNULL( &aa->a_vals[ k ] ); k++ ) {
|
||||||
|
bv.bv_len += aa->a_vals[ k ].bv_len;
|
||||||
|
nVals++;
|
||||||
|
}
|
||||||
|
nAttrs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay_entry_release_ov( op, e, 0, dc->dc_on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*drp = dr;
|
||||||
|
drp = &dr->dr_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op->o_bd->bd_info = bi;
|
||||||
|
|
||||||
|
if ( drhead == NULL ) {
|
||||||
|
return SLAP_CB_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cook the control value */
|
||||||
|
bv.bv_len += nVals * sizeof(struct berval)
|
||||||
|
+ nAttrs * sizeof(struct berval)
|
||||||
|
+ nDerefVals * sizeof(DerefVal)
|
||||||
|
+ nDerefRes * sizeof(DerefRes);
|
||||||
|
bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
|
||||||
|
|
||||||
|
ber_init2( ber, &bv, LBER_USE_DER );
|
||||||
|
ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
rc = ber_printf( ber, "{" /*}*/ );
|
||||||
|
for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
|
||||||
|
rc = ber_printf( ber, "{{O{" /*}}}*/,
|
||||||
|
&dr->dr_spec.ds_derefAttr->ad_cname );
|
||||||
|
for ( i = 0; i < dr->dr_spec.ds_nattrs; i++ ) {
|
||||||
|
rc = ber_printf( ber, "O",
|
||||||
|
&dr->dr_spec.ds_attributes[ i ]->ad_cname );
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{{*/ "}}{" /*}*/ );
|
||||||
|
for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
rc = ber_printf( ber, "{O{" /*}}*/ ,
|
||||||
|
&dr->dr_vals[ i ].dv_derefSpecVal );
|
||||||
|
for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) {
|
||||||
|
if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) {
|
||||||
|
rc = ber_printf( ber, "[W]", dr->dr_vals[ i ].dv_attrVals[ j ] );
|
||||||
|
} else {
|
||||||
|
rc = ber_printf( ber, "b", 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{{*/ "}}" );
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{{*/ "}}" );
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{*/ "}" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = ber_printf( ber, "{" /*}*/ );
|
||||||
|
for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
|
||||||
|
for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
rc = ber_printf( ber, "{OO{" /*}*/,
|
||||||
|
&dr->dr_spec.ds_derefAttr->ad_cname,
|
||||||
|
&dr->dr_vals[ i ].dv_derefSpecVal );
|
||||||
|
for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) {
|
||||||
|
if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) {
|
||||||
|
rc = ber_printf( ber, "{O[W]}",
|
||||||
|
&dr->dr_spec.ds_attributes[ j ]->ad_cname,
|
||||||
|
dr->dr_vals[ i ].dv_attrVals[ j ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{*/ "}N}" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ber_printf( ber, /*{*/ "}" );
|
||||||
|
if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
|
||||||
|
if ( op->o_deref == SLAP_CONTROL_CRITICAL ) {
|
||||||
|
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rc = SLAP_CB_CONTINUE;
|
||||||
|
}
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl = op->o_tmpcalloc( 1,
|
||||||
|
sizeof( LDAPControl ) + ctrlval.bv_len + 1,
|
||||||
|
op->o_tmpmemctx );
|
||||||
|
ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
|
||||||
|
ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF;
|
||||||
|
ctrl->ldctl_iscritical = 0;
|
||||||
|
ctrl->ldctl_value.bv_len = ctrlval.bv_len;
|
||||||
|
lutil_strncopy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
|
||||||
|
ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';
|
||||||
|
|
||||||
|
ber_free_buf( ber );
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if ( rs->sr_ctrls ) {
|
||||||
|
for ( ; rs->sr_ctrls[ i ] != NULL; i++ )
|
||||||
|
/* count'em */ ;
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
ctrlsp = op->o_tmpcalloc( i, sizeof(LDAPControl *), op->o_tmpmemctx );
|
||||||
|
i = 0;
|
||||||
|
if ( rs->sr_ctrls != NULL ) {
|
||||||
|
for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) {
|
||||||
|
ctrlsp[ i ] = rs->sr_ctrls[ i ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctrlsp[ i++ ] = ctrl;
|
||||||
|
ctrlsp[ i++ ] = NULL;
|
||||||
|
if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
|
||||||
|
op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
|
||||||
|
}
|
||||||
|
rs->sr_ctrls = ctrlsp;
|
||||||
|
rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
|
||||||
|
|
||||||
|
rc = SLAP_CB_CONTINUE;
|
||||||
|
|
||||||
|
cleanup:;
|
||||||
|
/* release all */
|
||||||
|
for ( ; drhead != NULL; ) {
|
||||||
|
DerefRes *drnext = drhead->dr_next;
|
||||||
|
op->o_tmpfree( drhead, op->o_tmpmemctx );
|
||||||
|
drhead = drnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
deref_cleanup( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
if ( rs->sr_type == REP_RESULT || rs->sr_err == SLAPD_ABANDON ) {
|
||||||
|
op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
|
||||||
|
op->o_callback = NULL;
|
||||||
|
|
||||||
|
op->o_tmpfree( op->o_ctrlderef, op->o_tmpmemctx );
|
||||||
|
op->o_ctrlderef = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SLAP_CB_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
deref_op_search( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
if ( op->o_deref ) {
|
||||||
|
slap_callback *sc;
|
||||||
|
deref_cb_t *dc;
|
||||||
|
|
||||||
|
sc = op->o_tmpcalloc( 1, sizeof( slap_callback ) + sizeof( deref_cb_t ), op->o_tmpmemctx );
|
||||||
|
|
||||||
|
dc = (deref_cb_t *)&sc[ 1 ];
|
||||||
|
dc->dc_on = (slap_overinst *)op->o_bd->bd_info;
|
||||||
|
dc->dc_ds = (DerefSpec *)op->o_ctrlderef;
|
||||||
|
|
||||||
|
sc->sc_response = deref_response;
|
||||||
|
sc->sc_cleanup = deref_cleanup;
|
||||||
|
sc->sc_private = (void *)dc;
|
||||||
|
|
||||||
|
sc->sc_next = op->o_callback->sc_next;
|
||||||
|
op->o_callback->sc_next = sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SLAP_CB_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
deref_initialize()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = register_supported_control( LDAP_CONTROL_X_DEREF,
|
||||||
|
SLAP_CTRL_SEARCH, NULL,
|
||||||
|
deref_parseCtrl, &deref_cid );
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"deref_init: Failed to register control (%d)\n",
|
||||||
|
rc, 0, 0 );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
deref.on_bi.bi_type = "deref";
|
||||||
|
deref.on_bi.bi_op_search = deref_op_search;
|
||||||
|
|
||||||
|
return overlay_register( &deref );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SLAPD_OVER_DEREF == SLAPD_MOD_DYNAMIC
|
||||||
|
int
|
||||||
|
init_module( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
return deref_initialize();
|
||||||
|
}
|
||||||
|
#endif /* SLAPD_OVER_DEREF == SLAPD_MOD_DYNAMIC */
|
||||||
|
|
||||||
|
#endif /* SLAPD_OVER_DEREF */
|
Loading…
Reference in New Issue
Block a user