mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-18 11:05:48 +08:00
add "What Failed?" LDAP control (ITS#5784)
This commit is contained in:
parent
d023222ee4
commit
7ad03166b6
@ -138,6 +138,9 @@ static int print_sss( LDAP *ld, LDAPControl *ctrl );
|
||||
#ifdef LDAP_CONTROL_X_DEREF
|
||||
static int print_deref( LDAP *ld, LDAPControl *ctrl );
|
||||
#endif
|
||||
#ifdef LDAP_CONTROL_X_WHATFAILED
|
||||
static int print_whatfailed( LDAP *ld, LDAPControl *ctrl );
|
||||
#endif
|
||||
|
||||
static struct tool_ctrls_t {
|
||||
const char *oid;
|
||||
@ -153,6 +156,9 @@ static struct tool_ctrls_t {
|
||||
{ LDAP_CONTROL_SORTRESPONSE, TOOL_SEARCH, print_sss },
|
||||
#ifdef LDAP_CONTROL_X_DEREF
|
||||
{ LDAP_CONTROL_X_DEREF, TOOL_SEARCH, print_deref },
|
||||
#endif
|
||||
#ifdef LDAP_CONTROL_X_WHATFAILED
|
||||
{ LDAP_CONTROL_X_WHATFAILED, TOOL_ALL, print_whatfailed },
|
||||
#endif
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
@ -1966,6 +1972,43 @@ done:;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_CONTROL_X_WHATFAILED
|
||||
static int
|
||||
print_whatfailed( LDAP *ld, LDAPControl *ctrl )
|
||||
{
|
||||
BerElement *ber;
|
||||
ber_tag_t tag;
|
||||
ber_len_t siz;
|
||||
BerVarray bva = NULL;
|
||||
|
||||
/* Create a BerElement from the berval returned in the control. */
|
||||
ber = ber_init( &ctrl->ldctl_value );
|
||||
|
||||
if ( ber == NULL ) {
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
|
||||
siz = sizeof(struct berval);
|
||||
tag = ber_scanf( ber, "[M]", &bva, &siz, 0 );
|
||||
if ( tag != LBER_ERROR ) {
|
||||
int i;
|
||||
|
||||
tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 );
|
||||
|
||||
for ( i = 0; bva[i].bv_val != NULL; i++ ) {
|
||||
tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len );
|
||||
}
|
||||
|
||||
ldap_memfree( bva );
|
||||
}
|
||||
|
||||
ber_free( ber, 1 );
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
|
||||
static int
|
||||
print_ppolicy( LDAP *ld, LDAPControl *ctrl )
|
||||
|
@ -323,6 +323,8 @@ typedef struct ldapcontrol {
|
||||
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"
|
||||
/* "What Failed?" Control (work in progress) */
|
||||
#define LDAP_CONTROL_X_WHATFAILED "1.3.6.1.4.1.4203.666.5.17"
|
||||
#endif /* LDAP_DEVEL */
|
||||
|
||||
/* various expired works */
|
||||
|
@ -946,6 +946,12 @@ backend_check_controls(
|
||||
|
||||
case LDAP_COMPARE_FALSE:
|
||||
if ( !op->o_bd->be_ctrls[cid] && (*ctrls)->ldctl_iscritical ) {
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
if ( get_whatFailed( op ) ) {
|
||||
char *oids[ 2 ] = { (*ctrls)->ldctl_oid, NULL };
|
||||
slap_ctrl_whatFailed_add( op, rs, oids );
|
||||
}
|
||||
#endif
|
||||
/* RFC 4511 allows unavailableCriticalExtension to be
|
||||
* returned when the server is unwilling to perform
|
||||
* an operation extended by a recognized critical
|
||||
|
@ -48,6 +48,9 @@ static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
|
||||
#ifdef SLAP_CONTROL_X_SESSION_TRACKING
|
||||
static SLAP_CTRL_PARSE_FN parseSessionTracking;
|
||||
#endif
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
static SLAP_CTRL_PARSE_FN parseWhatFailed;
|
||||
#endif
|
||||
|
||||
#undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
|
||||
|
||||
@ -217,6 +220,14 @@ static struct slap_control control_defs[] = {
|
||||
session_tracking_extops, NULL,
|
||||
parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
|
||||
#endif
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
{ LDAP_CONTROL_X_WHATFAILED,
|
||||
(int)offsetof(struct slap_control_ids, sc_whatFailed),
|
||||
SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
|
||||
NULL, NULL,
|
||||
parseWhatFailed, LDAP_SLIST_ENTRY_INITIALIZER(next) },
|
||||
#endif
|
||||
|
||||
{ NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
|
||||
};
|
||||
|
||||
@ -536,6 +547,7 @@ int slap_parse_ctrl(
|
||||
const char **text )
|
||||
{
|
||||
struct slap_control *sc;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
sc = find_ctrl( control->ldctl_oid );
|
||||
if( sc != NULL ) {
|
||||
@ -591,31 +603,29 @@ int slap_parse_ctrl(
|
||||
|
||||
if (( sc->sc_mask & tagmask ) == tagmask ) {
|
||||
/* available extension */
|
||||
int rc;
|
||||
|
||||
if( !sc->sc_parse ) {
|
||||
*text = "not yet implemented";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
rc = sc->sc_parse( op, rs, control );
|
||||
if ( rc ) {
|
||||
if ( sc->sc_parse ) {
|
||||
rc = sc->sc_parse( op, rs, control );
|
||||
assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION );
|
||||
return rc;
|
||||
|
||||
} else if ( control->ldctl_iscritical ) {
|
||||
*text = "not yet implemented";
|
||||
rc = LDAP_OTHER;
|
||||
}
|
||||
|
||||
} else if( control->ldctl_iscritical ) {
|
||||
|
||||
} else if ( control->ldctl_iscritical ) {
|
||||
/* unavailable CRITICAL control */
|
||||
*text = "critical extension is unavailable";
|
||||
return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
|
||||
rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
|
||||
}
|
||||
} else if( control->ldctl_iscritical ) {
|
||||
|
||||
} else if ( control->ldctl_iscritical ) {
|
||||
/* unrecognized CRITICAL control */
|
||||
*text = "critical extension is not recognized";
|
||||
return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
|
||||
rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int get_ctrls(
|
||||
@ -629,6 +639,15 @@ int get_ctrls(
|
||||
char *opaque;
|
||||
BerElement *ber = op->o_ber;
|
||||
struct berval bv;
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
/* NOTE: right now, slapd checks the validity of each control
|
||||
* while parsing. As a consequence, it can only detect one
|
||||
* cause of failure at a time. This results in returning
|
||||
* exactly one OID with the whatFailed control, or no control
|
||||
* at all.
|
||||
*/
|
||||
char *failed_oid = NULL;
|
||||
#endif
|
||||
|
||||
len = ber_pvt_ber_remaining(ber);
|
||||
|
||||
@ -769,6 +788,9 @@ int get_ctrls(
|
||||
|
||||
rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
failed_oid = c->ldctl_oid;
|
||||
#endif
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
@ -784,6 +806,69 @@ return_results:
|
||||
send_ldap_disconnect( op, rs );
|
||||
rs->sr_err = SLAPD_DISCONNECT;
|
||||
} else {
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
/* might have not been parsed yet? */
|
||||
if ( failed_oid != NULL ) {
|
||||
if ( !get_whatFailed( op ) ) {
|
||||
/* look it up */
|
||||
|
||||
/* step through each remaining element */
|
||||
for ( ; tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) )
|
||||
{
|
||||
LDAPControl c = { 0 };
|
||||
|
||||
tag = ber_scanf( ber, "{m" /*}*/, &bv );
|
||||
c.ldctl_oid = bv.bv_val;
|
||||
|
||||
if ( tag == LBER_ERROR ) {
|
||||
slap_free_ctrls( op, op->o_ctrls );
|
||||
op->o_ctrls = NULL;
|
||||
break;
|
||||
|
||||
} else if ( c.ldctl_oid == NULL ) {
|
||||
slap_free_ctrls( op, op->o_ctrls );
|
||||
op->o_ctrls = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
if ( tag == LBER_BOOLEAN ) {
|
||||
ber_int_t crit;
|
||||
tag = ber_scanf( ber, "b", &crit );
|
||||
if( tag == LBER_ERROR ) {
|
||||
slap_free_ctrls( op, op->o_ctrls );
|
||||
op->o_ctrls = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
}
|
||||
|
||||
if ( tag == LBER_OCTETSTRING ) {
|
||||
tag = ber_scanf( ber, "m", &c.ldctl_value );
|
||||
|
||||
if( tag == LBER_ERROR ) {
|
||||
slap_free_ctrls( op, op->o_ctrls );
|
||||
op->o_ctrls = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( strcmp( c.ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) == 0 ) {
|
||||
const char *text;
|
||||
slap_parse_ctrl( op, rs, &c, &text );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_whatFailed( op ) ) {
|
||||
char *oids[ 2 ] = { failed_oid, NULL };
|
||||
slap_ctrl_whatFailed_add( op, rs, oids );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
}
|
||||
@ -1865,3 +1950,87 @@ slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPContro
|
||||
return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
static int parseWhatFailed(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
LDAPControl *ctrl )
|
||||
{
|
||||
if ( op->o_whatFailed != SLAP_CONTROL_NONE ) {
|
||||
rs->sr_text = "\"WHat Failed?\" control specified multiple times";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
|
||||
rs->sr_text = "\"What Failed?\" control value not absent";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
op->o_whatFailed = ctrl->ldctl_iscritical
|
||||
? SLAP_CONTROL_CRITICAL
|
||||
: SLAP_CONTROL_NONCRITICAL;
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
slap_ctrl_whatFailed_add(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
char **oids )
|
||||
{
|
||||
BerElementBuffer berbuf;
|
||||
BerElement *ber = (BerElement *) &berbuf;
|
||||
LDAPControl **ctrls = NULL;
|
||||
struct berval ctrlval;
|
||||
int i, rc = LDAP_SUCCESS;
|
||||
|
||||
ber_init2( ber, NULL, LBER_USE_DER );
|
||||
ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
|
||||
ber_printf( ber, "[" /*]*/ );
|
||||
for ( i = 0; oids[ i ] != NULL; i++ ) {
|
||||
ber_printf( ber, "s", oids[ i ] );
|
||||
}
|
||||
ber_printf( ber, /*[*/ "]" );
|
||||
|
||||
if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if ( rs->sr_ctrls != NULL ) {
|
||||
for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) {
|
||||
if ( strcmp( rs->sr_ctrls[ i ]->ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) != 0 ) {
|
||||
/* TODO: add */
|
||||
assert( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrls = op->o_tmprealloc( rs->sr_ctrls,
|
||||
sizeof(LDAPControl *)*( i + 2 )
|
||||
+ sizeof(LDAPControl)
|
||||
+ ctrlval.bv_len + 1,
|
||||
op->o_tmpmemctx );
|
||||
if ( ctrls == NULL ) {
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
ctrls[ i + 1 ] = NULL;
|
||||
ctrls[ i ] = (LDAPControl *)&ctrls[ i + 2 ];
|
||||
ctrls[ i ]->ldctl_oid = LDAP_CONTROL_X_WHATFAILED;
|
||||
ctrls[ i ]->ldctl_iscritical = 0;
|
||||
ctrls[ i ]->ldctl_value.bv_val = (char *)&ctrls[ i ][ 1 ];
|
||||
AC_MEMCPY( ctrls[ i ]->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len + 1 );
|
||||
ctrls[ i ]->ldctl_value.bv_len = ctrlval.bv_len;
|
||||
|
||||
ber_free_buf( ber );
|
||||
|
||||
rs->sr_ctrls = ctrls;
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
@ -660,6 +660,13 @@ LDAP_SLAPD_F (int)
|
||||
slap_ctrl_session_tracking_request_add LDAP_P((
|
||||
Operation *op, SlapReply *rs, LDAPControl *ctrl ));
|
||||
#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
LDAP_SLAPD_F (int)
|
||||
slap_ctrl_whatFailed_add LDAP_P((
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
char **oids ));
|
||||
#endif /* SLAP_CONTROL_X_WHATFAILED */
|
||||
|
||||
/*
|
||||
* config.c
|
||||
|
@ -64,6 +64,7 @@ LDAP_BEGIN_DECL
|
||||
#define LDAP_SYNC_TIMESTAMP
|
||||
#define SLAP_CONTROL_X_SORTEDRESULTS
|
||||
#define SLAP_CONTROL_X_SESSION_TRACKING
|
||||
#define SLAP_CONTROL_X_WHATFAILED
|
||||
#define SLAP_CONFIG_DELETE
|
||||
#endif
|
||||
|
||||
@ -2406,6 +2407,9 @@ struct slap_control_ids {
|
||||
int sc_sessionTracking;
|
||||
#endif
|
||||
int sc_valuesReturnFilter;
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
int sc_whatFailed;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2675,6 +2679,11 @@ struct Operation {
|
||||
#define get_sessionTracking(op) ((int)(op)->o_session_tracking)
|
||||
#endif
|
||||
|
||||
#ifdef SLAP_CONTROL_X_WHATFAILED
|
||||
#define o_whatFailed o_ctrlflag[slap_cids.sc_whatFailed]
|
||||
#define get_whatFailed(op) _SCM((op)->o_whatFailed)
|
||||
#endif
|
||||
|
||||
#define o_sync o_ctrlflag[slap_cids.sc_LDAPsync]
|
||||
|
||||
AuthorizationInformation o_authz;
|
||||
|
Loading…
Reference in New Issue
Block a user