]> git.sur5r.net Git - openldap/commitdiff
allow to customize the error code in case of constraint violation
authorPierangelo Masarati <ando@openldap.org>
Fri, 28 Dec 2007 00:38:27 +0000 (00:38 +0000)
committerPierangelo Masarati <ando@openldap.org>
Fri, 28 Dec 2007 00:38:27 +0000 (00:38 +0000)
doc/man/man5/slapo-memberof.5
servers/slapd/config.c
servers/slapd/config.h
servers/slapd/overlays/memberof.c

index b9f6e06761bb9d25ffef02873e49c2b579710115..b5cf27d4bc5e1564229457c72c51fdd1f931bd29 100644 (file)
@@ -36,59 +36,69 @@ The following
 configuration options are defined for the memberofoverlay.
 
 .TP
-.B memberof-group-oc <group-oc>
+.BI memberof-group-oc \ <group-oc>
 The value 
-.B <group-oc> 
+.I <group-oc> 
 is the name of the objectClass that triggers the reverse group membership
 update.
 It defaults to \fIgroupOfNames\fP.
 
 .TP
-.B memberof-member-ad <member-ad>
+.BI memberof-member-ad \ <member-ad>
 The value 
-.B <member-ad> 
+.I <member-ad> 
 is the name of the attribute that contains the names of the members
 in the group objects; it must be DN-valued.
 It defaults to \fImember\fP.
 
 .TP
-.B memberof-memberof-ad <memberof-ad>
+.BI memberof-memberof-ad \ <memberof-ad>
 The value 
-.B <memberof-ad> 
+.I <memberof-ad> 
 is the name of the attribute that contains the names of the groups
 an entry is member of; it must be DN-valued.  Its contents are 
 automatically updated by the overlay.
 It defaults to \fImemberOf\fP.
 
 .TP
-.B memberof-dn <dn>
+.BI memberof-dn \ <dn>
 The value 
-.B <dn> 
+.I <dn> 
 contains the DN that is used as \fImodifiersName\fP for internal 
 modifications performed to update the reverse group membership.
 It defaults to the \fIrootdn\fP of the underlying database.
 
 .TP
-.B memberof-dangling {ignore, drop, error}
+.BI "memberof-dangling {" ignore ", " drop ", " error "}"
 This option determines the behavior of the overlay when, during 
 a modification, it encounters dangling references.
 The default is
-.BR ignore ,
+.IR ignore ,
 which may leave dangling references.
 Other options are
-.BR drop ,
+.IR drop ,
 which discards those modifications that would result in dangling
 references, and
-.BR error ,
+.IR error ,
 which causes modifications that would result in dangling references
 to fail.
 
 .TP
-.B memberof-refint {true|FALSE}
+.BI memberof-dangling-error \ <error-code>
+If
+.BR memberof-dangling
+is set to
+.IR error ,
+this configuration parameter can be used to modify the response code
+returned in case of violation.  It defaults to "constraint violation",
+but other implementations are known to return "no such object" instead.
+
+.TP
+.BI "memberof-refint {" true "|" FALSE "}"
 This option determines whether the overlay will try to preserve
 referential integrity or not.
 If set to
-.BR TRUE ,
+.IR TRUE ,
 when an entry containing values of the "is member of" attribute is modified,
 the corresponding groups are modified as well.
 
index 93fdf1dc5f4ec645f666a75045283db34001fef2..6e20e6a09c28b9f734560bde3165a1a2c07de14b 100644 (file)
@@ -1007,6 +1007,92 @@ enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
        return -1;
 }
 
+static slap_verbmasks slap_ldap_response_code_[] = {
+       { BER_BVC("success"),                           LDAP_SUCCESS },
+
+       { BER_BVC("operationsError"),                   LDAP_OPERATIONS_ERROR },
+       { BER_BVC("protocolError"),                     LDAP_PROTOCOL_ERROR },
+       { BER_BVC("timelimitExceeded"),                 LDAP_TIMELIMIT_EXCEEDED },
+       { BER_BVC("sizelimitExceeded"),                 LDAP_SIZELIMIT_EXCEEDED },
+       { BER_BVC("compareFalse"),                      LDAP_COMPARE_FALSE },
+       { BER_BVC("compareTrue"),                       LDAP_COMPARE_TRUE },
+
+       { BER_BVC("authMethodNotSupported"),            LDAP_AUTH_METHOD_NOT_SUPPORTED },
+       { BER_BVC("strongAuthNotSupported"),            LDAP_STRONG_AUTH_NOT_SUPPORTED },
+       { BER_BVC("strongAuthRequired"),                LDAP_STRONG_AUTH_REQUIRED },
+       { BER_BVC("strongerAuthRequired"),              LDAP_STRONGER_AUTH_REQUIRED },
+#if 0 /* not LDAPv3 */
+       { BER_BVC("partialResults"),                    LDAP_PARTIAL_RESULTS },
+#endif
+
+       { BER_BVC("referral"),                          LDAP_REFERRAL },
+       { BER_BVC("adminlimitExceeded"),                LDAP_ADMINLIMIT_EXCEEDED },
+       { BER_BVC("unavailableCriticalExtension"),      LDAP_UNAVAILABLE_CRITICAL_EXTENSION },
+       { BER_BVC("confidentialityRequired"),           LDAP_CONFIDENTIALITY_REQUIRED },
+       { BER_BVC("saslBindInProgress"),                LDAP_SASL_BIND_IN_PROGRESS },
+
+       { BER_BVC("noSuchAttribute"),                   LDAP_NO_SUCH_ATTRIBUTE },
+       { BER_BVC("undefinedType"),                     LDAP_UNDEFINED_TYPE },
+       { BER_BVC("inappropriateMatching"),             LDAP_INAPPROPRIATE_MATCHING },
+       { BER_BVC("constraintViolation"),               LDAP_CONSTRAINT_VIOLATION },
+       { BER_BVC("typeOrValueExists"),                 LDAP_TYPE_OR_VALUE_EXISTS },
+       { BER_BVC("invalidSyntax"),                     LDAP_INVALID_SYNTAX },
+
+       { BER_BVC("noSuchObject"),                      LDAP_NO_SUCH_OBJECT },
+       { BER_BVC("aliasProblem"),                      LDAP_ALIAS_PROBLEM },
+       { BER_BVC("invalidDnSyntax"),                   LDAP_INVALID_DN_SYNTAX },
+#if 0 /* not LDAPv3 */
+       { BER_BVC("isLeaf"),                            LDAP_IS_LEAF },
+#endif
+       { BER_BVC("aliasDerefProblem"),                 LDAP_ALIAS_DEREF_PROBLEM },
+
+       { BER_BVC("proxyAuthzFailure"),                 LDAP_X_PROXY_AUTHZ_FAILURE },
+       { BER_BVC("inappropriateAuth"),                 LDAP_INAPPROPRIATE_AUTH },
+       { BER_BVC("invalidCredentials"),                LDAP_INVALID_CREDENTIALS },
+       { BER_BVC("insufficientAccess"),                LDAP_INSUFFICIENT_ACCESS },
+
+       { BER_BVC("busy"),                              LDAP_BUSY },
+       { BER_BVC("unavailable"),                       LDAP_UNAVAILABLE },
+       { BER_BVC("unwillingToPerform"),                LDAP_UNWILLING_TO_PERFORM },
+       { BER_BVC("loopDetect"),                        LDAP_LOOP_DETECT },
+
+       { BER_BVC("namingViolation"),                   LDAP_NAMING_VIOLATION },
+       { BER_BVC("objectClassViolation"),              LDAP_OBJECT_CLASS_VIOLATION },
+       { BER_BVC("notAllowedOnNonleaf"),               LDAP_NOT_ALLOWED_ON_NONLEAF },
+       { BER_BVC("notAllowedOnRdn"),                   LDAP_NOT_ALLOWED_ON_RDN },
+       { BER_BVC("alreadyExists"),                     LDAP_ALREADY_EXISTS },
+       { BER_BVC("noObjectClassMods"),                 LDAP_NO_OBJECT_CLASS_MODS },
+       { BER_BVC("resultsTooLarge"),                   LDAP_RESULTS_TOO_LARGE },
+       { BER_BVC("affectsMultipleDsas"),               LDAP_AFFECTS_MULTIPLE_DSAS },
+
+       { BER_BVC("other"),                             LDAP_OTHER },
+
+       /* extension-specific */
+
+       { BER_BVC("cupResourcesExhausted"),             LDAP_CUP_RESOURCES_EXHAUSTED },
+       { BER_BVC("cupSecurityViolation"),              LDAP_CUP_SECURITY_VIOLATION },
+       { BER_BVC("cupInvalidData"),                    LDAP_CUP_INVALID_DATA },
+       { BER_BVC("cupUnsupportedScheme"),              LDAP_CUP_UNSUPPORTED_SCHEME },
+       { BER_BVC("cupReloadRequired"),                 LDAP_CUP_RELOAD_REQUIRED },
+
+       { BER_BVC("cancelled"),                         LDAP_CANCELLED },
+       { BER_BVC("noSuchOperation"),                   LDAP_NO_SUCH_OPERATION },
+       { BER_BVC("tooLate"),                           LDAP_TOO_LATE },
+       { BER_BVC("cannotCancel"),                      LDAP_CANNOT_CANCEL },
+
+       { BER_BVC("assertionFailed"),                   LDAP_ASSERTION_FAILED },
+
+       { BER_BVC("proxiedAuthorizationDenied"),        LDAP_PROXIED_AUTHORIZATION_DENIED },
+
+       { BER_BVC("syncRefreshRequired"),               LDAP_SYNC_REFRESH_REQUIRED },
+
+       { BER_BVC("noOperation"),                       LDAP_X_NO_OPERATION },
+
+       { BER_BVNULL,                           0 }
+};
+
+slap_verbmasks *slap_ldap_response_code = slap_ldap_response_code_;
+
 #ifdef HAVE_TLS
 static slap_verbmasks tlskey[] = {
        { BER_BVC("no"),        SB_TLS_OFF },
index 5964b8df9af548346aa018c753552080a286db73..c6b97945650862025c0dd8a0ae92623e8f5faff1 100644 (file)
@@ -196,4 +196,6 @@ int config_shadow( ConfigArgs *c, int flag );
 
 #define        SLAP_X_ORDERED_FMT      "{%d}"
 
+extern slap_verbmasks *slap_ldap_response_code;
+
 #endif /* CONFIG_H */
index 45c388650d4f8ac67dae28b47df751bd651709f6..df834c88b007a24598d1a3cedabddd1ed8cbbdc8 100644 (file)
@@ -155,6 +155,8 @@ typedef struct memberof_t {
 #define        MEMBEROF_FREFINT        0x04U
 #define        MEMBEROF_FREVERSE       0x08U
 
+       ber_int_t               mo_dangling_err;
+
 #define MEMBEROF_CHK(mo,f) \
        (((mo)->mo_flags & (f)) == (f))
 #define MEMBEROF_DANGLING_CHECK(mo) \
@@ -571,7 +573,7 @@ memberof_op_add( Operation *op, SlapReply *rs )
                                }
 
                                if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
-                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                       rc = rs->sr_err = mo->mo_dangling_err;
                                        rs->sr_text = "adding non-existing object "
                                                "as group member";
                                        send_ldap_result( op, rs );
@@ -649,7 +651,7 @@ memberof_op_add( Operation *op, SlapReply *rs )
                                }
 
                                if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
-                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                       rc = rs->sr_err = mo->mo_dangling_err;
                                        rs->sr_text = "adding non-existing object "
                                                "as memberof";
                                        send_ldap_result( op, rs );
@@ -836,7 +838,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                                }
                
                                                if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
-                                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                                       rc = rs->sr_err = mo->mo_dangling_err;
                                                        rs->sr_text = "adding non-existing object "
                                                                "as group member";
                                                        send_ldap_result( op, rs );
@@ -933,7 +935,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                                }
 
                                                if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
-                                                       rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                                       rc = rs->sr_err = mo->mo_dangling_err;
                                                        rs->sr_text = "deleting non-existing object "
                                                                "as memberof";
                                                        send_ldap_result( op, rs );
@@ -1044,7 +1046,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                op->o_bd->bd_info = (BackendInfo *)on;
                                if ( rc != LDAP_SUCCESS ) {
                                        if ( MEMBEROF_DANGLING_ERROR( mo ) ) {
-                                               rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                                               rc = rs->sr_err = mo->mo_dangling_err;
                                                rs->sr_text = "adding non-existing object "
                                                        "as memberof";
                                                send_ldap_result( op, rs );
@@ -1490,6 +1492,10 @@ memberof_db_init(
        memberof_t      tmp_mo = { 0 }, *mo;
 
        mo = (memberof_t *)ch_calloc( 1, sizeof( memberof_t ) );
+
+       /* safe default */
+       mo->mo_dangling_err = LDAP_CONSTRAINT_VIOLATION;
+
        on->on_bi.bi_private = (void *)mo;
 
        return 0;
@@ -1499,12 +1505,16 @@ enum {
        MO_DN = 1,
        MO_DANGLING,
        MO_REFINT,
+       MO_GROUP_OC,
+       MO_MEMBER_AD,
+       MO_MEMBER_OF_AD,
 #if 0
        MO_REVERSE,
 #endif
-       MO_GROUP_OC,
-       MO_MEMBER_AD,
-       MO_MEMBER_OF_AD
+
+       MO_DANGLING_ERROR,
+
+       MO_LAST
 };
 
 static ConfigDriver mo_cf_gen;
@@ -1570,6 +1580,13 @@ static ConfigTable mo_cfg[] = {
                NULL, NULL },
 #endif
 
+       { "memberof-dangling-error", "error code",
+               2, 2, 0, ARG_MAGIC|MO_DANGLING_ERROR, mo_cf_gen,
+               "( OLcfgOvAt:18.7 NAME 'olcMemberOfDanglingError' "
+                       "DESC 'Error code returned in case of dangling back reference' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+               NULL, NULL },
+
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
@@ -1581,6 +1598,7 @@ static ConfigOCs mo_ocs[] = {
                "MAY ( "
                        "olcMemberOfDN "
                        "$ olcMemberOfDangling "
+                       "$ olcMemberOfDanglingError"
                        "$ olcMemberOfRefInt "
                        "$ olcMemberOfGroupOC "
                        "$ olcMemberOfMemberAD "
@@ -1683,6 +1701,25 @@ mo_cf_gen( ConfigArgs *c )
                        }
                        break;
 
+               case MO_DANGLING_ERROR:
+                       if ( mo->mo_flags & MEMBEROF_FDANGLING_ERROR ) {
+                               char buf[ SLAP_TEXT_BUFLEN ];
+                               enum_to_verb( slap_ldap_response_code, mo->mo_dangling_err, &bv );
+                               if ( BER_BVISNULL( &bv ) ) {
+                                       bv.bv_len = snprintf( buf, sizeof( buf ), "0x%x", mo->mo_dangling_err );
+                                       if ( bv.bv_len < sizeof( buf ) ) {
+                                               bv.bv_val = buf;
+                                       } else {
+                                               rc = 1;
+                                               break;
+                                       }
+                               }
+                               value_add_one( &c->rvalue_vals, &bv );
+                       } else {
+                               rc = 1;
+                       }
+                       break;
+
                case MO_REFINT:
                        c->value_int = MEMBEROF_REFINT( mo );
                        break;
@@ -1742,6 +1779,15 @@ mo_cf_gen( ConfigArgs *c )
                        mo->mo_flags |= dangling_mode[ i ].mask;
                        break;
 
+               case MO_DANGLING_ERROR:
+                       i = verb_to_mask( c->argv[ 1 ], slap_ldap_response_code );
+                       if ( !BER_BVISNULL( &slap_ldap_response_code[ i ].word ) ) {
+                               mo->mo_dangling_err = slap_ldap_response_code[ i ].mask;
+                       } else if ( lutil_atoix( &mo->mo_dangling_err, c->argv[ 1 ], 0 ) ) {
+                               return 1;
+                       }
+                       break;
+
                case MO_REFINT:
                        if ( c->value_int ) {
                                mo->mo_flags |= MEMBEROF_FREFINT;
@@ -1880,7 +1926,7 @@ memberof_db_open(
                }
        }
 
-    if( ! mo->mo_oc_group ){
+       if( ! mo->mo_oc_group ){
                mo->mo_oc_group = oc_find( SLAPD_GROUP_CLASS );
                if ( mo->mo_oc_group == NULL ) {
                        Debug( LDAP_DEBUG_ANY,