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. configuration options are defined for the memberofoverlay.
.TP .TP
.B memberof-group-oc <group-oc> .BI memberof-group-oc \ <group-oc>
The value The value
.B <group-oc> .I <group-oc>
is the name of the objectClass that triggers the reverse group membership is the name of the objectClass that triggers the reverse group membership
update. update.
It defaults to \fIgroupOfNames\fP. It defaults to \fIgroupOfNames\fP.
.TP .TP
.B memberof-member-ad <member-ad> .BI memberof-member-ad \ <member-ad>
The value The value
.B <member-ad> .I <member-ad>
is the name of the attribute that contains the names of the members is the name of the attribute that contains the names of the members
in the group objects; it must be DN-valued. in the group objects; it must be DN-valued.
It defaults to \fImember\fP. It defaults to \fImember\fP.
.TP .TP
.B memberof-memberof-ad <memberof-ad> .BI memberof-memberof-ad \ <memberof-ad>
The value The value
.B <memberof-ad> .I <memberof-ad>
is the name of the attribute that contains the names of the groups 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 an entry is member of; it must be DN-valued. Its contents are
automatically updated by the overlay. automatically updated by the overlay.
It defaults to \fImemberOf\fP. It defaults to \fImemberOf\fP.
.TP .TP
.B memberof-dn <dn> .BI memberof-dn \ <dn>
The value The value
.B <dn> .I <dn>
contains the DN that is used as \fImodifiersName\fP for internal contains the DN that is used as \fImodifiersName\fP for internal
modifications performed to update the reverse group membership. modifications performed to update the reverse group membership.
It defaults to the \fIrootdn\fP of the underlying database. It defaults to the \fIrootdn\fP of the underlying database.
.TP .TP
.B memberof-dangling {ignore, drop, error} .BI "memberof-dangling {" ignore ", " drop ", " error "}"
This option determines the behavior of the overlay when, during This option determines the behavior of the overlay when, during
a modification, it encounters dangling references. a modification, it encounters dangling references.
The default is The default is
.BR ignore , .IR ignore ,
which may leave dangling references. which may leave dangling references.
Other options are Other options are
.BR drop , .IR drop ,
which discards those modifications that would result in dangling which discards those modifications that would result in dangling
references, and references, and
.BR error , .IR error ,
which causes modifications that would result in dangling references which causes modifications that would result in dangling references
to fail. to fail.
.TP .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 This option determines whether the overlay will try to preserve
referential integrity or not. referential integrity or not.
If set to If set to
.BR TRUE , .IR TRUE ,
when an entry containing values of the "is member of" attribute is modified, when an entry containing values of the "is member of" attribute is modified,
the corresponding groups are modified as well. 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; 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 #ifdef HAVE_TLS
static slap_verbmasks tlskey[] = { static slap_verbmasks tlskey[] = {
{ BER_BVC("no"), SB_TLS_OFF }, { 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}" #define SLAP_X_ORDERED_FMT "{%d}"
extern slap_verbmasks *slap_ldap_response_code;
#endif /* CONFIG_H */ #endif /* CONFIG_H */

View File

@ -155,6 +155,8 @@ typedef struct memberof_t {
#define MEMBEROF_FREFINT 0x04U #define MEMBEROF_FREFINT 0x04U
#define MEMBEROF_FREVERSE 0x08U #define MEMBEROF_FREVERSE 0x08U
ber_int_t mo_dangling_err;
#define MEMBEROF_CHK(mo,f) \ #define MEMBEROF_CHK(mo,f) \
(((mo)->mo_flags & (f)) == (f)) (((mo)->mo_flags & (f)) == (f))
#define MEMBEROF_DANGLING_CHECK(mo) \ #define MEMBEROF_DANGLING_CHECK(mo) \
@ -571,7 +573,7 @@ memberof_op_add( Operation *op, SlapReply *rs )
} }
if ( MEMBEROF_DANGLING_ERROR( mo ) ) { 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 " rs->sr_text = "adding non-existing object "
"as group member"; "as group member";
send_ldap_result( op, rs ); send_ldap_result( op, rs );
@ -649,7 +651,7 @@ memberof_op_add( Operation *op, SlapReply *rs )
} }
if ( MEMBEROF_DANGLING_ERROR( mo ) ) { 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 " rs->sr_text = "adding non-existing object "
"as memberof"; "as memberof";
send_ldap_result( op, rs ); send_ldap_result( op, rs );
@ -836,7 +838,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
} }
if ( MEMBEROF_DANGLING_ERROR( mo ) ) { 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 " rs->sr_text = "adding non-existing object "
"as group member"; "as group member";
send_ldap_result( op, rs ); send_ldap_result( op, rs );
@ -933,7 +935,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
} }
if ( MEMBEROF_DANGLING_ERROR( mo ) ) { 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 " rs->sr_text = "deleting non-existing object "
"as memberof"; "as memberof";
send_ldap_result( op, rs ); send_ldap_result( op, rs );
@ -1044,7 +1046,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
op->o_bd->bd_info = (BackendInfo *)on; op->o_bd->bd_info = (BackendInfo *)on;
if ( rc != LDAP_SUCCESS ) { if ( rc != LDAP_SUCCESS ) {
if ( MEMBEROF_DANGLING_ERROR( mo ) ) { 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 " rs->sr_text = "adding non-existing object "
"as memberof"; "as memberof";
send_ldap_result( op, rs ); send_ldap_result( op, rs );
@ -1490,6 +1492,10 @@ memberof_db_init(
memberof_t tmp_mo = { 0 }, *mo; memberof_t tmp_mo = { 0 }, *mo;
mo = (memberof_t *)ch_calloc( 1, sizeof( memberof_t ) ); 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; on->on_bi.bi_private = (void *)mo;
return 0; return 0;
@ -1499,12 +1505,16 @@ enum {
MO_DN = 1, MO_DN = 1,
MO_DANGLING, MO_DANGLING,
MO_REFINT, MO_REFINT,
MO_GROUP_OC,
MO_MEMBER_AD,
MO_MEMBER_OF_AD,
#if 0 #if 0
MO_REVERSE, MO_REVERSE,
#endif #endif
MO_GROUP_OC,
MO_MEMBER_AD, MO_DANGLING_ERROR,
MO_MEMBER_OF_AD
MO_LAST
}; };
static ConfigDriver mo_cf_gen; static ConfigDriver mo_cf_gen;
@ -1570,6 +1580,13 @@ static ConfigTable mo_cfg[] = {
NULL, NULL }, NULL, NULL },
#endif #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 } { NULL, NULL, 0, 0, 0, ARG_IGNORED }
}; };
@ -1581,6 +1598,7 @@ static ConfigOCs mo_ocs[] = {
"MAY ( " "MAY ( "
"olcMemberOfDN " "olcMemberOfDN "
"$ olcMemberOfDangling " "$ olcMemberOfDangling "
"$ olcMemberOfDanglingError"
"$ olcMemberOfRefInt " "$ olcMemberOfRefInt "
"$ olcMemberOfGroupOC " "$ olcMemberOfGroupOC "
"$ olcMemberOfMemberAD " "$ olcMemberOfMemberAD "
@ -1683,6 +1701,25 @@ mo_cf_gen( ConfigArgs *c )
} }
break; 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: case MO_REFINT:
c->value_int = MEMBEROF_REFINT( mo ); c->value_int = MEMBEROF_REFINT( mo );
break; break;
@ -1742,6 +1779,15 @@ mo_cf_gen( ConfigArgs *c )
mo->mo_flags |= dangling_mode[ i ].mask; mo->mo_flags |= dangling_mode[ i ].mask;
break; 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: case MO_REFINT:
if ( c->value_int ) { if ( c->value_int ) {
mo->mo_flags |= MEMBEROF_FREFINT; mo->mo_flags |= MEMBEROF_FREFINT;