allow to customize the error code in case of constraint violation

This commit is contained in:
Pierangelo Masarati 2007-12-28 00:38:27 +00:00
parent 0d9e140e95
commit 18b2885f69
4 changed files with 167 additions and 23 deletions

View 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.

View 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 },

View 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 */

View 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,