]> git.sur5r.net Git - openldap/commitdiff
add matchedDN; fix and clarify behavior when searching in-directory entries
authorPierangelo Masarati <ando@openldap.org>
Sun, 6 Nov 2005 23:26:42 +0000 (23:26 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 6 Nov 2005 23:26:42 +0000 (23:26 +0000)
doc/man/man5/slapo-retcode.5
servers/slapd/overlays/retcode.c
tests/data/retcode.conf

index 78cef21866a532243e05bad8769f08bfe56282aa..031094829c91af9c24d15b256d649df9cf07fb9b 100644 (file)
@@ -21,8 +21,8 @@ The error responses are generated according to different strategies.
 In the first case, all operations targeted at a specific configurable
 subtree cause the object related to the request DN to be looked up
 and checked for return code data: a response code, plus an optional
-textual message, an optional configurable delay, and, when the response code
-is referral, a (list of) referral(s).
+textual message, an optional configurable delay, an optional matched DN
+field, and, when the response code is "referral", a (list of) referral(s).
 .LP
 Well-known response codes from standard track documents are provided
 in \fBretcode.conf\fP, which can be included after instantiating
@@ -57,13 +57,15 @@ If not defined, the suffix of the database is used.
 .HP
 .hy 0
 .B retcode\-item <RDN> <errCode> [op=<oplist>] [text=<message>]
-.B [ref=<referral>] [sleeptime=<sec>]
+.B [ref=<referral>] [sleeptime=<sec>] [matched=<DN>]
 .RS
 A dynamically generated entry, located below \fBretcode\-parent\fP.
 The \fB<errCode>\fP is the number of the response code;
 it can be in any format supported by strtol.
 The optional \fB<oplist>\fP is a list of operations that cause
 response code generation; if absent, all operations are affected.
+The \fBmatched\fP field is the matched DN that is returned
+along with the error.
 The \fBref\fP field is only allowed for the \fBreferral\fP 
 response code.
 .RE
@@ -130,13 +132,24 @@ The sleep time before the response is actually returned to the client:
     SINGLE-VALUE )
 .RE
 .LP
+The matched DN returned to the client:
+.RS 4
+( 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 )
+.RE
+.LP
 The abstract class that triggers the overlay:
 .RS 4
 ( 1.3.6.1.4.1.4203.666.11.4.3.0
     NAME ( 'errAbsObject' )
     SUP top ABSTRACT
     MUST ( errCode )
-    MAY ( cn $ description $ errOp $ errText $ errSleepTime ) )
+    MAY ( cn $ description $ errOp $ errText $ errSleepTime
+        $ errMatchedDN ) )
 .RE
 .LP
 The standalone structural objectclass for specifically created data:
index 25e12d366fe1f1e24eee27f03dcedefac0b62515..5041c25f10e8192a709dfc882929233aebd5daa1 100644 (file)
@@ -39,6 +39,7 @@ static AttributeDescription   *ad_errCode;
 static AttributeDescription    *ad_errText;
 static AttributeDescription    *ad_errOp;
 static AttributeDescription    *ad_errSleepTime;
+static AttributeDescription    *ad_errMatchedDN;
 static ObjectClass             *oc_errAbsObject;
 static ObjectClass             *oc_errObject;
 static ObjectClass             *oc_errAuxObject;
@@ -63,6 +64,7 @@ typedef struct retcode_item_t {
        struct berval           rdi_dn;
        struct berval           rdi_ndn;
        struct berval           rdi_text;
+       struct berval           rdi_matched;
        int                     rdi_err;
        BerVarray               rdi_ref;
        int                     rdi_sleeptime;
@@ -188,7 +190,9 @@ retcode_cb_response( Operation *op, SlapReply *rs )
        }
 
        if ( rs->sr_err == LDAP_SUCCESS ) {
-               rdc->rdc_flags = SLAP_CB_CONTINUE;
+               if ( !op->o_abandon ) {
+                       rdc->rdc_flags = SLAP_CB_CONTINUE;
+               }
                return 0;
        }
 
@@ -264,16 +268,27 @@ retcode_op_func( Operation *op, SlapReply *rs )
                                return retcode_op_add( op, rs );
 
                        case LDAP_REQ_BIND:
+                               /* skip if rootdn */
                                if ( be_isroot_pw( op ) ) {
                                        return SLAP_CB_CONTINUE;
                                }
-                               /* fallthru */
+                               return retcode_op_internal( op, rs );
+
+                       case LDAP_REQ_SEARCH:
+                               if ( op->ors_scope == LDAP_SCOPE_BASE ) {
+                                       rs->sr_err = retcode_op_internal( op, rs );
+                                       if ( rs->sr_err == SLAP_CB_CONTINUE ) {
+                                               rs->sr_err = LDAP_SUCCESS;
+                                       }
+                                       send_ldap_result( op, rs );
+                                       return rs->sr_err;
+                               }
+                               break;
 
                        case LDAP_REQ_MODIFY:
                        case LDAP_REQ_DELETE:
                        case LDAP_REQ_MODRDN:
                        case LDAP_REQ_COMPARE:
-                       case LDAP_REQ_SEARCH:
                                return retcode_op_internal( op, rs );
                        }
                }
@@ -362,6 +377,7 @@ retcode_op_func( Operation *op, SlapReply *rs )
        } else {
                rs->sr_err = rdi->rdi_err;
                rs->sr_text = rdi->rdi_text.bv_val;
+               rs->sr_matched = rdi->rdi_matched.bv_val;
 
                /* FIXME: we only honor the rdi_ref field in case rdi_err
                 * is LDAP_REFERRAL otherwise send_ldap_result() bails out */
@@ -520,6 +536,12 @@ retcode_entry_response( Operation *op, SlapReply *rs, Entry *e )
                        rs->sr_text = a->a_vals[ 0 ].bv_val;
                }
 
+               /* matched DN */
+               a = attr_find( e->e_attrs, ad_errMatchedDN );
+               if ( a != NULL ) {
+                       rs->sr_matched = a->a_vals[ 0 ].bv_val;
+               }
+
                db.bd_info = on->on_info->oi_orig;
                op->o_bd = &db;
                op->o_callback = NULL;
@@ -544,6 +566,7 @@ retcode_entry_response( Operation *op, SlapReply *rs, Entry *e )
                }
 
                rs->sr_text = NULL;
+               rs->sr_matched = NULL;
                op->o_callback = o_callback;
        }
        
@@ -711,13 +734,15 @@ retcode_db_config(
                                                } else if ( strcasecmp( ops[ j ], "compare" ) == 0 ) {
                                                        rdi.rdi_mask |= SN_DG_OP_COMPARE;
 
-                                               } else if ( strcasecmp( ops[ j ], "add" ) == 0 ) {
+                                               } else if ( strcasecmp( ops[ j ], "delete" ) == 0 ) {
                                                        rdi.rdi_mask |= SN_DG_OP_DELETE;
 
                                                } else if ( strcasecmp( ops[ j ], "modify" ) == 0 ) {
                                                        rdi.rdi_mask |= SN_DG_OP_MODIFY;
 
-                                               } else if ( strcasecmp( ops[ j ], "rename" ) == 0 ) {
+                                               } else if ( strcasecmp( ops[ j ], "rename" ) == 0
+                                                       || strcasecmp( ops[ j ], "modrdn" ) == 0 )
+                                               {
                                                        rdi.rdi_mask |= SN_DG_OP_RENAME;
 
                                                } else if ( strcasecmp( ops[ j ], "search" ) == 0 ) {
@@ -757,6 +782,24 @@ retcode_db_config(
                                        }
                                        ber_str2bv( &argv[ i ][ STRLENOF( "text=" ) ], 0, 1, &rdi.rdi_text );
 
+                               } else if ( strncasecmp( argv[ i ], "matched=", STRLENOF( "matched=" ) ) == 0 )
+                               {
+                                       struct berval   dn;
+
+                                       if ( !BER_BVISNULL( &rdi.rdi_matched ) ) {
+                                               fprintf( stderr, "%s: line %d: retcode: "
+                                                       "\"matched\" already provided.\n",
+                                                       fname, lineno );
+                                               return 1;
+                                       }
+                                       ber_str2bv( &argv[ i ][ STRLENOF( "matched=" ) ], 0, 0, &dn );
+                                       if ( dnPretty( NULL, &dn, &rdi.rdi_matched, NULL ) != LDAP_SUCCESS ) {
+                                               fprintf( stderr, "%s: line %d: retcode: "
+                                                       "unable to prettify matched DN \"%s\".\n",
+                                                       fname, lineno, &argv[ i ][ STRLENOF( "matched=" ) ] );
+                                               return 1;
+                                       }
+
                                } else if ( strncasecmp( argv[ i ], "ref=", STRLENOF( "ref=" ) ) == 0 )
                                {
                                        char            **refs;
@@ -898,6 +941,13 @@ retcode_db_open( BackendDB *be )
                        attr_merge_normalize_one( &rdi->rdi_e, ad_errText, &val[ 0 ], NULL );
                }
 
+               /* matched */
+               if ( !BER_BVISNULL( &rdi->rdi_matched ) ) {
+                       val[ 0 ] = rdi->rdi_matched;
+
+                       attr_merge_normalize_one( &rdi->rdi_e, ad_errMatchedDN, &val[ 0 ], NULL );
+               }
+
                /* sleep time */
                if ( rdi->rdi_sleeptime > 0 ) {
                        snprintf( buf, sizeof( buf ), "%d", rdi->rdi_sleeptime );
@@ -968,6 +1018,10 @@ retcode_db_destroy( BackendDB *be )
                                ber_memfree( rdi->rdi_text.bv_val );
                        }
 
+                       if ( !BER_BVISNULL( &rdi->rdi_matched ) ) {
+                               ber_memfree( rdi->rdi_matched.bv_val );
+                       }
+
                        BER_BVZERO( &rdi->rdi_e.e_name );
                        BER_BVZERO( &rdi->rdi_e.e_nname );
 
@@ -1028,6 +1082,13 @@ retcode_init( void )
                        "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 "
+                       "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 },
                { NULL }
        };
 
@@ -1046,6 +1107,7 @@ retcode_init( void )
                                "$ errOp "
                                "$ errText "
                                "$ errSleepTime "
+                               "$ errMatchedDN "
                        ") )",
                        &oc_errAbsObject },
                { "errObject", "( 1.3.6.1.4.1.4203.666.11.4.3.1 "
index e498b0a0cba1e186f01b85ec6cb924fdebccda21..18e9dcd06db969c0515d769687d7ae902533266e 100644 (file)
@@ -29,7 +29,7 @@ retcode-item  "cn=authMethodNotSupported"             0x07
 retcode-item   "cn=strongAuthNotSupported"             0x07    text="same as authMethodNotSupported"
 retcode-item   "cn=strongAuthRequired"                 0x08
 retcode-item   "cn=strongerAuthRequired"               0x08    text="same as strongAuthRequired"
-#retcode-item  "cn=partialResults"                     0x09 "LDAPv2+ (not LDAPv3)"
+#retcode-item  "cn=partialResults"                     0x09    text="LDAPv2+ (not LDAPv3)"
 
 retcode-item   "cn=referral"                           0x0a    text="LDAPv3"   ref="ldap://:9019"
 retcode-item   "cn=adminLimitExceeded"                 0x0b    text="LDAPv3"