X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fretcode.c;h=4c8af8898695bcc2e7c3cb3509c6e1f9ccb2da3f;hb=fb2e448e877a8a387084dde517362c9f7bf1b6b7;hp=b966a4b1ddec7809691953a9e5cd9ff913546a23;hpb=e1b83c881c430e13365de649b978b102287bccca;p=openldap diff --git a/servers/slapd/overlays/retcode.c b/servers/slapd/overlays/retcode.c index b966a4b1dd..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; @@ -93,20 +105,22 @@ retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e static unsigned int retcode_sleep( int s ) { + unsigned int r = 0; + /* sleep as required */ if ( s < 0 ) { #if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */ - unsigned r = rand() % (-s); + r = rand() % (-s); #endif - unsigned r = ((double)(-s))*rand()/(RAND_MAX + 1.0); - return sleep( r ); + r = ((double)(-s))*rand()/(RAND_MAX + 1.0); + } else if ( s > 0 ) { + r = (unsigned int)s; } - - if ( s > 0 ) { - return sleep( (unsigned int)s ); + if ( r ) { + sleep( r ); } - return 0; + return r; } static int @@ -141,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; @@ -405,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; @@ -445,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; } @@ -496,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; @@ -530,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 ) { @@ -551,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; @@ -594,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; @@ -602,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; } @@ -885,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; } } @@ -1116,14 +1262,12 @@ int retcode_initialize( void ) { int i, code; - const char *err; static struct { - char *name; char *desc; AttributeDescription **ad; } retcode_at[] = { - { "errCode", "( 1.3.6.1.4.1.4203.666.11.4.1.1 " + { "( 1.3.6.1.4.1.4203.666.11.4.1.1 " "NAME ( 'errCode' ) " "DESC 'LDAP error code' " "EQUALITY integerMatch " @@ -1131,14 +1275,14 @@ retcode_initialize( void ) "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " "SINGLE-VALUE )", &ad_errCode }, - { "errOp", "( 1.3.6.1.4.1.4203.666.11.4.1.2 " + { "( 1.3.6.1.4.1.4203.666.11.4.1.2 " "NAME ( 'errOp' ) " "DESC 'Operations the errObject applies to' " "EQUALITY caseIgnoreMatch " "SUBSTR caseIgnoreSubstringsMatch " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", &ad_errOp}, - { "errText", "( 1.3.6.1.4.1.4203.666.11.4.1.3 " + { "( 1.3.6.1.4.1.4203.666.11.4.1.3 " "NAME ( 'errText' ) " "DESC 'LDAP error textual description' " "EQUALITY caseIgnoreMatch " @@ -1146,29 +1290,47 @@ retcode_initialize( void ) "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " "SINGLE-VALUE )", &ad_errText }, - { "errSleepTime", "( 1.3.6.1.4.1.4203.666.11.4.1.4 " + { "( 1.3.6.1.4.1.4203.666.11.4.1.4 " "NAME ( 'errSleepTime' ) " "DESC 'Time to wait before returning the error' " "EQUALITY integerMatch " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " "SINGLE-VALUE )", &ad_errSleepTime }, - { "errMatchedDN", "( 1.3.6.1.4.1.4203.666.11.4.1.5 " + { "( 1.3.6.1.4.1.4203.666.11.4.1.5 " "NAME ( 'errMatchedDN' ) " "DESC 'Value to be returned as matched DN' " "EQUALITY distinguishedNameMatch " "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 } }; static struct { - char *name; char *desc; ObjectClass **oc; } retcode_oc[] = { - { "errAbsObject", "( 1.3.6.1.4.1.4203.666.11.4.3.0 " + { "( 1.3.6.1.4.1.4203.666.11.4.3.0 " "NAME ( 'errAbsObject' ) " "SUP top ABSTRACT " "MUST ( errCode ) " @@ -1179,14 +1341,17 @@ retcode_initialize( void ) "$ errText " "$ errSleepTime " "$ errMatchedDN " + "$ errUnsolicitedOID " + "$ errUnsolicitedData " + "$ errDisconnect " ") )", &oc_errAbsObject }, - { "errObject", "( 1.3.6.1.4.1.4203.666.11.4.3.1 " + { "( 1.3.6.1.4.1.4203.666.11.4.3.1 " "NAME ( 'errObject' ) " "SUP errAbsObject STRUCTURAL " ")", &oc_errObject }, - { "errAuxObject", "( 1.3.6.1.4.1.4203.666.11.4.3.2 " + { "( 1.3.6.1.4.1.4203.666.11.4.3.2 " "NAME ( 'errAuxObject' ) " "SUP errAbsObject AUXILIARY " ")", @@ -1195,73 +1360,22 @@ retcode_initialize( void ) }; - for ( i = 0; retcode_at[ i ].name != NULL; i++ ) { - LDAPAttributeType *at; - - at = ldap_str2attributetype( retcode_at[ i ].desc, - &code, &err, LDAP_SCHEMA_ALLOW_ALL ); - if ( !at ) { - fprintf( stderr, "retcode: " - "AttributeType load failed: %s %s\n", - ldap_scherr2str( code ), err ); - return code; - } - -#if LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR > 2 - code = at_add( at, 0, NULL, &err ); -#else - code = at_add( at, &err ); -#endif - ldap_memfree( at ); - if ( code != LDAP_SUCCESS ) { - fprintf( stderr, "retcode: " - "AttributeType load failed: %s %s\n", - scherr2str( code ), err ); + for ( i = 0; retcode_at[ i ].desc != NULL; i++ ) { + code = register_at( retcode_at[ i ].desc, retcode_at[ i ].ad, 0 ); + if ( code ) { + Debug( LDAP_DEBUG_ANY, + "retcode: register_at failed\n", 0, 0, 0 ); return code; } - - code = slap_str2ad( retcode_at[ i ].name, - retcode_at[ i ].ad, &err ); - if ( code != LDAP_SUCCESS ) { - fprintf( stderr, "retcode: unable to find " - "AttributeDescription \"%s\": %d (%s)\n", - retcode_at[ i ].name, code, err ); - return 1; - } } - for ( i = 0; retcode_oc[ i ].name != NULL; i++ ) { - LDAPObjectClass *oc; - - oc = ldap_str2objectclass( retcode_oc[ i ].desc, - &code, &err, LDAP_SCHEMA_ALLOW_ALL ); - if ( !oc ) { - fprintf( stderr, "retcode: " - "ObjectClass load failed: %s %s\n", - ldap_scherr2str( code ), err ); + for ( i = 0; retcode_oc[ i ].desc != NULL; i++ ) { + code = register_oc( retcode_oc[ i ].desc, retcode_oc[ i ].oc, 0 ); + if ( code ) { + Debug( LDAP_DEBUG_ANY, + "retcode: register_oc failed\n", 0, 0, 0 ); return code; } - -#if LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR > 2 - code = oc_add( oc, 0, NULL, &err ); -#else - code = oc_add( oc, &err ); -#endif - ldap_memfree(oc); - if ( code != LDAP_SUCCESS ) { - fprintf( stderr, "retcode: " - "ObjectClass load failed: %s %s\n", - scherr2str( code ), err ); - return code; - } - - *retcode_oc[ i ].oc = oc_find( retcode_oc[ i ].name ); - if ( *retcode_oc[ i ].oc == NULL ) { - fprintf( stderr, "retcode: unable to find " - "objectClass \"%s\"\n", - retcode_oc[ i ].name ); - return 1; - } } retcode.on_bi.bi_type = "retcode";