mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
allow to customize the error code in case of constraint violation
This commit is contained in:
parent
0d9e140e95
commit
18b2885f69
@ -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.
|
||||
|
||||
|
@ -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 },
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user