mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
add support for Chaining Behavior control (<draft-sermersheim-ldap-chaining>, a work in progress)
This commit is contained in:
parent
f6ed0b0127
commit
c6a1f24186
@ -80,6 +80,12 @@ int protocol = -1;
|
||||
int verbose = 0;
|
||||
int version = 0;
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
int chaining = 0;
|
||||
static int chainingResolve = -1;
|
||||
static int chainingContinuation = -1;
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
/* Set in main() */
|
||||
char *prog = NULL;
|
||||
|
||||
@ -107,6 +113,11 @@ N_(" [!]noop\n")
|
||||
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
|
||||
N_(" ppolicy\n")
|
||||
#endif
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
N_(" [!]chaining[=<resolveBehavior>[,<continuationBehavior>]]\n")
|
||||
N_(" one of \"chainingPreferred\", \"chainingRequired\",\n")
|
||||
N_(" \"referralsPreferred\", \"referralsRequired\"\n")
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n")
|
||||
N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n"),
|
||||
N_(" -f file read operations from `file'\n"),
|
||||
@ -286,6 +297,52 @@ tool_args( int argc, char **argv )
|
||||
postread = 1 + crit;
|
||||
postread_attrs = cvalue;
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
} else if ( strcasecmp( control, "chaining" ) == 0 ) {
|
||||
chaining = 1 + crit;
|
||||
|
||||
if ( cvalue != NULL ) {
|
||||
char *continuation;
|
||||
|
||||
continuation = strchr( cvalue, ',' );
|
||||
if ( continuation ) {
|
||||
/* FIXME: this makes sense only in searches */
|
||||
*continuation++ = '\0';
|
||||
if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
|
||||
chainingContinuation = LDAP_CHAINING_PREFERRED;
|
||||
} else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
|
||||
chainingContinuation = LDAP_CHAINING_REQUIRED;
|
||||
} else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
|
||||
chainingContinuation = LDAP_REFERRALS_PREFERRED;
|
||||
} else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
|
||||
chainingContinuation = LDAP_REFERRALS_REQUIRED;
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
"chaining behavior control "
|
||||
"continuation value \"%s\" invalid\n",
|
||||
continuation );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
|
||||
chainingResolve = LDAP_CHAINING_PREFERRED;
|
||||
} else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
|
||||
chainingResolve = LDAP_CHAINING_REQUIRED;
|
||||
} else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
|
||||
chainingResolve = LDAP_REFERRALS_PREFERRED;
|
||||
} else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
|
||||
chainingResolve = LDAP_REFERRALS_REQUIRED;
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
"chaining behavior control "
|
||||
"resolve value \"%s\" invalid\n",
|
||||
cvalue);
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
} else {
|
||||
fprintf( stderr, "Invalid general control name: %s\n",
|
||||
control );
|
||||
@ -867,7 +924,7 @@ void
|
||||
tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
|
||||
{
|
||||
int i = 0, j, crit = 0, err;
|
||||
LDAPControl c[8], **ctrls;
|
||||
LDAPControl c[9], **ctrls;
|
||||
|
||||
ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
|
||||
if ( ctrls == NULL ) {
|
||||
@ -915,8 +972,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
|
||||
|
||||
if ( manageDSAit ) {
|
||||
c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
|
||||
c[i].ldctl_value.bv_val = NULL;
|
||||
c[i].ldctl_value.bv_len = 0;
|
||||
BER_BVZERO( &c[i].ldctl_value );
|
||||
c[i].ldctl_iscritical = manageDSAit > 1;
|
||||
ctrls[i] = &c[i];
|
||||
i++;
|
||||
@ -924,8 +980,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
|
||||
|
||||
if ( noop ) {
|
||||
c[i].ldctl_oid = LDAP_CONTROL_NOOP;
|
||||
c[i].ldctl_value.bv_val = NULL;
|
||||
c[i].ldctl_value.bv_len = 0;
|
||||
BER_BVZERO( &c[i].ldctl_value );
|
||||
c[i].ldctl_iscritical = noop > 1;
|
||||
ctrls[i] = &c[i];
|
||||
i++;
|
||||
@ -991,6 +1046,52 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
|
||||
if( attrs ) ldap_charray_free( attrs );
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
if ( chaining ) {
|
||||
if ( chainingResolve > -1 ) {
|
||||
BerElementBuffer berbuf;
|
||||
BerElement *ber = (BerElement *)&berbuf;
|
||||
|
||||
ber_init2( ber, NULL, LBER_USE_DER );
|
||||
|
||||
err = ber_printf( ber, "{e" /* } */, chainingResolve );
|
||||
if ( err == -1 ) {
|
||||
ber_free( ber, 1 );
|
||||
fprintf( stderr, _("Chaining behavior control encoding error!\n") );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
if ( chainingContinuation > -1 ) {
|
||||
err = ber_printf( ber, "e", chainingContinuation );
|
||||
if ( err == -1 ) {
|
||||
ber_free( ber, 1 );
|
||||
fprintf( stderr, _("Chaining behavior control encoding error!\n") );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
|
||||
err = ber_printf( ber, /* { */ "N}" );
|
||||
if ( err == -1 ) {
|
||||
ber_free( ber, 1 );
|
||||
fprintf( stderr, _("Chaining behavior control encoding error!\n") );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
} else {
|
||||
BER_BVZERO( &c[i].ldctl_value );
|
||||
}
|
||||
|
||||
c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
|
||||
c[i].ldctl_iscritical = chaining > 1;
|
||||
ctrls[i] = &c[i];
|
||||
i++;
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
while ( count-- ) {
|
||||
ctrls[i++] = extra_c++;
|
||||
}
|
||||
|
@ -49,6 +49,9 @@ extern int manageDSAit;
|
||||
extern int noop;
|
||||
extern int ppolicy;
|
||||
extern int preread, postread;
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
extern int chaining;
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
extern int not;
|
||||
extern int want_bindpw;
|
||||
|
@ -379,7 +379,7 @@ handle_private_option( int i )
|
||||
if( crit ) subentries *= -1;
|
||||
#endif
|
||||
|
||||
} else if ( strcasecmp( control, "sync" ) == 0 ) {
|
||||
} else if ( strcasecmp( control, "sync" ) == 0 ) {
|
||||
char *cookiep;
|
||||
char *slimitp;
|
||||
if ( ldapsync ) {
|
||||
@ -664,31 +664,34 @@ getNextPage:
|
||||
#ifdef LDAP_CONTROL_PAGEDRESULTS
|
||||
|| pagedResults
|
||||
#endif
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
|| chaining
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|| ldapsync
|
||||
|| subentries || valuesReturnFilter )
|
||||
{
|
||||
int err;
|
||||
int i=0;
|
||||
LDAPControl c[6];
|
||||
LDAPControl c[10];
|
||||
|
||||
#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
|
||||
if ( domainScope ) {
|
||||
c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
|
||||
c[i].ldctl_value.bv_val = NULL;
|
||||
c[i].ldctl_value.bv_len = 0;
|
||||
c[i].ldctl_iscritical = domainScope > 1;
|
||||
i++;
|
||||
}
|
||||
if ( domainScope ) {
|
||||
c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
|
||||
c[i].ldctl_value.bv_val = NULL;
|
||||
c[i].ldctl_value.bv_len = 0;
|
||||
c[i].ldctl_iscritical = domainScope > 1;
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_CONTROL_SUBENTRIES
|
||||
if ( subentries ) {
|
||||
if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
|
||||
if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
|
||||
if ( err == -1 ) {
|
||||
if ( err == -1 ) {
|
||||
ber_free( seber, 1 );
|
||||
fprintf( stderr, _("Subentries control encoding error!\n") );
|
||||
return EXIT_FAILURE;
|
||||
|
@ -277,6 +277,18 @@ typedef struct ldapcontrol {
|
||||
#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */
|
||||
#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all NCs subordinate to base */
|
||||
|
||||
/* LDAP Chaining Behavior Control *//* work in progress */
|
||||
/* <draft-sermersheim-ldap-chaining>;
|
||||
* see also LDAP_REQUIRES_CHAINING, LDAP_CANNOT_CHAIN */
|
||||
#ifdef LDAP_DEVEL
|
||||
#define LDAP_CONTROL_X_CHAINING_BEHAVIOR "1.3.6.1.4.1.4203.666.11.3"
|
||||
|
||||
#define LDAP_CHAINING_PREFERRED 0
|
||||
#define LDAP_CHAINING_REQUIRED 1
|
||||
#define LDAP_REFERRALS_PREFERRED 2
|
||||
#define LDAP_REFERRALS_REQUIRED 3
|
||||
#endif
|
||||
|
||||
/* LDAP Unsolicited Notifications */
|
||||
#define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" /* RFC 2251 */
|
||||
#define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION
|
||||
@ -550,6 +562,13 @@ typedef struct ldapcontrol {
|
||||
/* for the Assertion control */
|
||||
#define LDAP_ASSERTION_FAILED 0x410f
|
||||
|
||||
/* for the Chaining Behavior control (consecutive result codes requested;
|
||||
* see <draft-sermersheim-ldap-chaining> ) */
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
#define LDAP_REQUIRES_CHAINING 0x4110
|
||||
#define LDAP_CANNOT_CHAIN 0x4111
|
||||
#endif
|
||||
|
||||
/* API Error Codes
|
||||
*
|
||||
* Based on draft-ietf-ldap-c-api-xx
|
||||
|
@ -29,7 +29,31 @@
|
||||
#include "slap.h"
|
||||
#include "back-ldap.h"
|
||||
|
||||
static BackendInfo *lback;
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
#define SLAP_CH_RESOLVE_SHIFT SLAP_CONTROL_SHIFT
|
||||
#define SLAP_CH_RESOLVE_MASK (0x3 << SLAP_CH_RESOLVE_SHIFT)
|
||||
#define SLAP_CH_RESOLVE_CHAINING_PREFERRED (LDAP_CHAINING_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
|
||||
#define SLAP_CH_RESOLVE_CHAINING_REQUIRED (LDAP_CHAINING_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
|
||||
#define SLAP_CH_RESOLVE_REFERRALS_PREFERRED (LDAP_REFERRALS_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
|
||||
#define SLAP_CH_RESOLVE_REFERRALS_REQUIRED (LDAP_REFERRALS_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
|
||||
#define SLAP_CH_RESOLVE_DEFAULT SLAP_CH_RESOLVE_CHAINING_PREFERRED
|
||||
#define SLAP_CH_CONTINUATION_SHIFT (SLAP_CH_RESOLVE_SHIFT + 2)
|
||||
#define SLAP_CH_CONTINUATION_MASK (0x3 << SLAP_CH_CONTINUATION_SHIFT)
|
||||
#define SLAP_CH_CONTINUATION_CHAINING_PREFERRED (LDAP_CHAINING_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
|
||||
#define SLAP_CH_CONTINUATION_CHAINING_REQUIRED (LDAP_CHAINING_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
|
||||
#define SLAP_CH_CONTINUATION_REFERRALS_PREFERRED (LDAP_REFERRALS_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
|
||||
#define SLAP_CH_CONTINUATION_REFERRALS_REQUIRED (LDAP_REFERRALS_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
|
||||
#define SLAP_CH_CONTINUATION_DEFAULT SLAP_CH_CONTINUATION_CHAINING_PREFERRED
|
||||
|
||||
#define o_chaining o_ctrlflag[sc_chainingBehavior]
|
||||
#define get_chaining(op) ((op)->o_chaining & SLAP_CONTROL_MASK)
|
||||
#define get_chainingBehavior(op) ((op)->o_chaining & (SLAP_CH_RESOLVE_MASK|SLAP_CH_CONTINUATION_MASK))
|
||||
#define get_resolveBehavior(op) ((op)->o_chaining & SLAP_CH_RESOLVE_MASK)
|
||||
#define get_continuationBehavior(op) ((op)->o_chaining & SLAP_CH_CONTINUATION_MASK)
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
static int sc_chainingBehavior;
|
||||
static BackendInfo *lback;
|
||||
|
||||
static int
|
||||
ldap_chain_operational( Operation *op, SlapReply *rs )
|
||||
@ -204,10 +228,44 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
||||
|
||||
struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
int sr_err = rs->sr_err;
|
||||
slap_reply_t sr_type = rs->sr_type;
|
||||
slap_mask_t chain_mask = 0;
|
||||
ber_len_t chain_shift = 0;
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
if ( rs->sr_err == LDAP_REFERRAL && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
|
||||
switch ( get_resolveBehavior( op ) ) {
|
||||
case SLAP_CH_RESOLVE_REFERRALS_PREFERRED:
|
||||
case SLAP_CH_RESOLVE_REFERRALS_REQUIRED:
|
||||
return SLAP_CB_CONTINUE;
|
||||
|
||||
default:
|
||||
chain_mask = SLAP_CH_RESOLVE_MASK;
|
||||
chain_shift = SLAP_CH_RESOLVE_SHIFT;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if ( rs->sr_type == REP_SEARCHREF && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
|
||||
switch ( get_continuationBehavior( op ) ) {
|
||||
case SLAP_CH_CONTINUATION_REFERRALS_PREFERRED:
|
||||
case SLAP_CH_CONTINUATION_REFERRALS_REQUIRED:
|
||||
return SLAP_CB_CONTINUE;
|
||||
|
||||
default:
|
||||
chain_mask = SLAP_CH_CONTINUATION_MASK;
|
||||
chain_shift = SLAP_CH_CONTINUATION_SHIFT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
/*
|
||||
* TODO: add checks on who/when chain operations; e.g.:
|
||||
* a) what identities are authorized
|
||||
@ -393,12 +451,33 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
switch ( ( get_chainingBehavior( op ) & chain_mask ) >> chain_shift ) {
|
||||
case LDAP_CHAINING_REQUIRED:
|
||||
op->o_callback = NULL;
|
||||
send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" );
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = SLAP_CB_CONTINUE;
|
||||
rs->sr_err = sr_err;
|
||||
rs->sr_type = sr_type;
|
||||
break;
|
||||
}
|
||||
goto dont_chain;
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
if ( sc2.sc_private == NULL ) {
|
||||
op->o_callback = NULL;
|
||||
rc = rs->sr_err = slap_map_api2result( rs );
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
dont_chain:;
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
op->o_do_not_cache = cache;
|
||||
op->o_bd->be_private = private;
|
||||
op->o_callback = sc;
|
||||
@ -476,11 +555,151 @@ ldap_chain_db_destroy(
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
static int
|
||||
ldap_chain_parse_ctrl(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
LDAPControl *ctrl )
|
||||
{
|
||||
ber_tag_t tag;
|
||||
BerElement *ber;
|
||||
ber_int_t mode,
|
||||
behavior;
|
||||
|
||||
if ( get_chaining( op ) != SLAP_CONTROL_NONE ) {
|
||||
rs->sr_text = "Chaining behavior control specified multiple times";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
|
||||
rs->sr_text = "Chaining behavior control specified with pagedResults control";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
|
||||
mode = (SLAP_CH_RESOLVE_DEFAULT|SLAP_CH_CONTINUATION_DEFAULT);
|
||||
|
||||
} else {
|
||||
ber_len_t len;
|
||||
|
||||
/* Parse the control value
|
||||
* ChainingBehavior ::= SEQUENCE {
|
||||
* resolveBehavior Behavior OPTIONAL,
|
||||
* continuationBehavior Behavior OPTIONAL }
|
||||
*
|
||||
* Behavior :: = ENUMERATED {
|
||||
* chainingPreferred (0),
|
||||
* chainingRequired (1),
|
||||
* referralsPreferred (2),
|
||||
* referralsRequired (3) }
|
||||
*/
|
||||
|
||||
ber = ber_init( &ctrl->ldctl_value );
|
||||
if( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
tag = ber_scanf( ber, "{e" /* } */, &behavior );
|
||||
/* FIXME: since the whole SEQUENCE is optional,
|
||||
* should we accept no enumerations at all? */
|
||||
if ( tag != LBER_ENUMERATED ) {
|
||||
rs->sr_text = "Chaining behavior control: resolveBehavior decoding error";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
switch ( behavior ) {
|
||||
case LDAP_CHAINING_PREFERRED:
|
||||
mode = SLAP_CH_RESOLVE_CHAINING_PREFERRED;
|
||||
break;
|
||||
|
||||
case LDAP_CHAINING_REQUIRED:
|
||||
mode = SLAP_CH_RESOLVE_CHAINING_REQUIRED;
|
||||
break;
|
||||
|
||||
case LDAP_REFERRALS_PREFERRED:
|
||||
mode = SLAP_CH_RESOLVE_REFERRALS_PREFERRED;
|
||||
break;
|
||||
|
||||
case LDAP_REFERRALS_REQUIRED:
|
||||
mode = SLAP_CH_RESOLVE_REFERRALS_REQUIRED;
|
||||
break;
|
||||
|
||||
default:
|
||||
rs->sr_text = "Chaining behavior control: unknown resolveBehavior";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
if ( tag == LBER_ENUMERATED ) {
|
||||
tag = ber_scanf( ber, "e", &behavior );
|
||||
if ( tag == LBER_ERROR ) {
|
||||
rs->sr_text = "Chaining behavior control: continuationBehavior decoding error";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tag == LBER_DEFAULT ) {
|
||||
mode |= SLAP_CH_CONTINUATION_DEFAULT;
|
||||
|
||||
} else {
|
||||
switch ( behavior ) {
|
||||
case LDAP_CHAINING_PREFERRED:
|
||||
mode |= SLAP_CH_CONTINUATION_CHAINING_PREFERRED;
|
||||
break;
|
||||
|
||||
case LDAP_CHAINING_REQUIRED:
|
||||
mode |= SLAP_CH_CONTINUATION_CHAINING_REQUIRED;
|
||||
break;
|
||||
|
||||
case LDAP_REFERRALS_PREFERRED:
|
||||
mode |= SLAP_CH_CONTINUATION_REFERRALS_PREFERRED;
|
||||
break;
|
||||
|
||||
case LDAP_REFERRALS_REQUIRED:
|
||||
mode |= SLAP_CH_CONTINUATION_REFERRALS_REQUIRED;
|
||||
break;
|
||||
|
||||
default:
|
||||
rs->sr_text = "Chaining behavior control: unknown continuationBehavior";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( ber_scanf( ber, /* { */ "}") ) == LBER_ERROR ) {
|
||||
rs->sr_text = "Chaining behavior control: decoding error";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
(void) ber_free( ber, 1 );
|
||||
}
|
||||
|
||||
op->o_chaining = mode | ( ctrl->ldctl_iscritical
|
||||
? SLAP_CONTROL_CRITICAL
|
||||
: SLAP_CONTROL_NONCRITICAL );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
static slap_overinst ldapchain;
|
||||
|
||||
int
|
||||
chain_init( void )
|
||||
{
|
||||
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
|
||||
int rc;
|
||||
|
||||
rc = register_supported_control( LDAP_CONTROL_X_CHAINING_BEHAVIOR,
|
||||
SLAP_CTRL_ACCESS, NULL,
|
||||
ldap_chain_parse_ctrl, &sc_chainingBehavior );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
fprintf( stderr, "Failed to register chaining behavior control: %d\n", rc );
|
||||
return rc;
|
||||
}
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
|
||||
ldapchain.on_bi.bi_type = "chain";
|
||||
ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
|
||||
ldapchain.on_bi.bi_db_config = ldap_chain_db_config;
|
||||
|
Loading…
Reference in New Issue
Block a user