X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fretcode.c;h=4c8af8898695bcc2e7c3cb3509c6e1f9ccb2da3f;hb=fb2e448e877a8a387084dde517362c9f7bf1b6b7;hp=3e5568552d255293069a853f594afeb010a7e4f6;hpb=3f4e196beb91b8e965746d6660d08daa6f0e172e;p=openldap diff --git a/servers/slapd/overlays/retcode.c b/servers/slapd/overlays/retcode.c index 3e5568552d..4c8af88986 100644 --- a/servers/slapd/overlays/retcode.c +++ b/servers/slapd/overlays/retcode.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2006 The OpenLDAP Foundation. + * Copyright 2005-2007 The OpenLDAP Foundation. * Portions Copyright 2005 Pierangelo Masarati * All rights reserved. * @@ -32,6 +32,7 @@ #include "slap.h" #include "lutil.h" +#include "ldif.h" static slap_overinst retcode; @@ -40,6 +41,10 @@ static AttributeDescription *ad_errText; static AttributeDescription *ad_errOp; static AttributeDescription *ad_errSleepTime; static AttributeDescription *ad_errMatchedDN; +static AttributeDescription *ad_errUnsolicitedOID; +static AttributeDescription *ad_errUnsolicitedData; +static AttributeDescription *ad_errDisconnect; + static ObjectClass *oc_errAbsObject; static ObjectClass *oc_errObject; static ObjectClass *oc_errAuxObject; @@ -70,6 +75,13 @@ typedef struct retcode_item_t { int rdi_sleeptime; Entry rdi_e; slap_mask_t rdi_mask; + struct berval rdi_unsolicited_oid; + struct berval rdi_unsolicited_data; + + unsigned rdi_flags; +#define RDI_PRE_DISCONNECT (0x1U) +#define RDI_POST_DISCONNECT (0x2U) + struct retcode_item_t *rdi_next; } retcode_item_t; @@ -143,11 +155,6 @@ retcode_send_onelevel( Operation *op, SlapReply *rs ) rs->sr_err = test_filter( op, &rdi->rdi_e, op->ors_filter ); if ( rs->sr_err == LDAP_COMPARE_TRUE ) { - if ( op->ors_slimit == rs->sr_nentries ) { - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - goto done; - } - /* safe default */ rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; @@ -407,6 +414,10 @@ retcode_op_func( Operation *op, SlapReply *rs ) rs->sr_text = "retcode not found"; } else { + if ( rdi->rdi_flags & RDI_PRE_DISCONNECT ) { + return rs->sr_err = SLAPD_DISCONNECT; + } + rs->sr_err = rdi->rdi_err; rs->sr_text = rdi->rdi_text.bv_val; rs->sr_matched = rdi->rdi_matched.bv_val; @@ -447,13 +458,45 @@ retcode_op_func( Operation *op, SlapReply *rs ) break; default: - send_ldap_result( op, rs ); + if ( rdi && !BER_BVISNULL( &rdi->rdi_unsolicited_oid ) ) { + ber_int_t msgid = op->o_msgid; + + /* RFC 4511 unsolicited response */ + + op->o_msgid = 0; + if ( strcmp( rdi->rdi_unsolicited_oid.bv_val, "0" ) == 0 ) { + send_ldap_result( op, rs ); + + } else { + ber_tag_t tag = op->o_tag; + + op->o_tag = LDAP_REQ_EXTENDED; + rs->sr_rspoid = rdi->rdi_unsolicited_oid.bv_val; + if ( !BER_BVISNULL( &rdi->rdi_unsolicited_data ) ) { + rs->sr_rspdata = &rdi->rdi_unsolicited_data; + } + send_ldap_extended( op, rs ); + rs->sr_rspoid = NULL; + rs->sr_rspdata = NULL; + op->o_tag = tag; + + } + op->o_msgid = msgid; + + } else { + send_ldap_result( op, rs ); + } + if ( rs->sr_ref != NULL ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } rs->sr_matched = NULL; rs->sr_text = NULL; + + if ( rdi && rdi->rdi_flags & RDI_POST_DISCONNECT ) { + return rs->sr_err = SLAPD_DISCONNECT; + } break; } @@ -498,6 +541,7 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e Attribute *a; int err; char *next; + int disconnect = 0; if ( get_manageDSAit( op ) ) { return SLAP_CB_CONTINUE; @@ -532,6 +576,15 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e } } + /* disconnect */ + a = attr_find( e->e_attrs, ad_errDisconnect ); + if ( a != NULL ) { + if ( bvmatch( &a->a_nvals[ 0 ], &slap_true_bv ) ) { + return rs->sr_err = SLAPD_DISCONNECT; + } + disconnect = 1; + } + /* error code */ a = attr_find( e->e_attrs, ad_errCode ); if ( a == NULL ) { @@ -553,7 +606,7 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e } } - if ( rs->sr_err != LDAP_SUCCESS ) { + if ( rs->sr_err != LDAP_SUCCESS && !LDAP_API_ERROR( rs->sr_err )) { BackendDB db = *op->o_bd, *o_bd = op->o_bd; void *o_callback = op->o_callback; @@ -596,7 +649,44 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e rs->sr_ref = NULL; } else { - send_ldap_result( op, rs ); + a = attr_find( e->e_attrs, ad_errUnsolicitedOID ); + if ( a != NULL ) { + struct berval oid = BER_BVNULL, + data = BER_BVNULL; + ber_int_t msgid = op->o_msgid; + + /* RFC 4511 unsolicited response */ + + op->o_msgid = 0; + + oid = a->a_nvals[ 0 ]; + + a = attr_find( e->e_attrs, ad_errUnsolicitedData ); + if ( a != NULL ) { + data = a->a_nvals[ 0 ]; + } + + if ( strcmp( oid.bv_val, "0" ) == 0 ) { + send_ldap_result( op, rs ); + + } else { + ber_tag_t tag = op->o_tag; + + op->o_tag = LDAP_REQ_EXTENDED; + rs->sr_rspoid = oid.bv_val; + if ( !BER_BVISNULL( &data ) ) { + rs->sr_rspdata = &data; + } + send_ldap_extended( op, rs ); + rs->sr_rspoid = NULL; + rs->sr_rspdata = NULL; + op->o_tag = tag; + } + op->o_msgid = msgid; + + } else { + send_ldap_result( op, rs ); + } } rs->sr_text = NULL; @@ -604,8 +694,12 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e op->o_bd = o_bd; op->o_callback = o_callback; } - + if ( rs->sr_err != LDAP_SUCCESS ) { + if ( disconnect ) { + return rs->sr_err = SLAPD_DISCONNECT; + } + op->o_abandon = 1; return rs->sr_err; } @@ -887,10 +981,60 @@ retcode_db_config( return 1; } + } else if ( strncasecmp( argv[ i ], "unsolicited=", STRLENOF( "unsolicited=" ) ) == 0 ) + { + char *data; + + if ( !BER_BVISNULL( &rdi.rdi_unsolicited_oid ) ) { + fprintf( stderr, "%s: line %d: retcode: " + "\"unsolicited\" already provided.\n", + fname, lineno ); + return 1; + } + + data = strchr( &argv[ i ][ STRLENOF( "unsolicited=" ) ], ':' ); + if ( data != NULL ) { + struct berval oid; + + if ( ldif_parse_line2( &argv[ i ][ STRLENOF( "unsolicited=" ) ], + &oid, &rdi.rdi_unsolicited_data, NULL ) ) + { + fprintf( stderr, "%s: line %d: retcode: " + "unable to parse \"unsolicited\".\n", + fname, lineno ); + return 1; + } + + ber_dupbv( &rdi.rdi_unsolicited_oid, &oid ); + + } else { + ber_str2bv( &argv[ i ][ STRLENOF( "unsolicited=" ) ], 0, 1, + &rdi.rdi_unsolicited_oid ); + } + + } else if ( strncasecmp( argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) + { + char *arg = &argv[ i ][ STRLENOF( "flags=" ) ]; + if ( strcasecmp( arg, "disconnect" ) == 0 ) { + rdi.rdi_flags |= RDI_PRE_DISCONNECT; + + } else if ( strcasecmp( arg, "pre-disconnect" ) == 0 ) { + rdi.rdi_flags |= RDI_PRE_DISCONNECT; + + } else if ( strcasecmp( arg, "post-disconnect" ) == 0 ) { + rdi.rdi_flags |= RDI_POST_DISCONNECT; + + } else { + fprintf( stderr, "%s: line %d: retcode: " + "unknown flag \"%s\".\n", + fname, lineno, arg ); + return 1; + } + } else { fprintf( stderr, "%s: line %d: retcode: " "unknown option \"%s\".\n", - fname, lineno, argv[ i ] ); + fname, lineno, argv[ i ] ); return 1; } } @@ -1118,7 +1262,6 @@ int retcode_initialize( void ) { int i, code; - const char *err; static struct { char *desc; @@ -1161,6 +1304,25 @@ retcode_initialize( void ) "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 " "SINGLE-VALUE )", &ad_errMatchedDN }, + { "( 1.3.6.1.4.1.4203.666.11.4.1.6 " + "NAME ( 'errUnsolicitedOID' ) " + "DESC 'OID to be returned within unsolicited response' " + "EQUALITY objectIdentifierMatch " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 " + "SINGLE-VALUE )", + &ad_errUnsolicitedOID }, + { "( 1.3.6.1.4.1.4203.666.11.4.1.7 " + "NAME ( 'errUnsolicitedData' ) " + "DESC 'Data to be returned within unsolicited response' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 " + "SINGLE-VALUE )", + &ad_errUnsolicitedData }, + { "( 1.3.6.1.4.1.4203.666.11.4.1.8 " + "NAME ( 'errDisconnect' ) " + "DESC 'Disconnect without notice' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 " + "SINGLE-VALUE )", + &ad_errDisconnect }, { NULL } }; @@ -1179,6 +1341,9 @@ retcode_initialize( void ) "$ errText " "$ errSleepTime " "$ errMatchedDN " + "$ errUnsolicitedOID " + "$ errUnsolicitedData " + "$ errDisconnect " ") )", &oc_errAbsObject }, { "( 1.3.6.1.4.1.4203.666.11.4.3.1 "