--- /dev/null
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2013 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+/* This is a simple overlay to perform the syntax checks usually
+ performed before the request is passed to the frontend.
+ This is necessary so the overlays above could handle errors and
+ return required non-standard error codes */
+
+#include "portable.h"
+
+#ifdef SLAPD_OVER_SYNTAXCHECKS
+
+#include <stdio.h>
+
+#include "ac/string.h"
+#include "ac/socket.h"
+
+#include "slap.h"
+#include "config.h"
+
+#include "lutil.h"
+#include "ldap_rq.h"
+
+static slap_overinst syntax_checks;
+
+
+static int syntax_checks_do_check( Operation *op, SlapReply *rs )
+{
+ char textbuf[ SLAP_TEXT_BUFLEN ];
+ size_t textlen = sizeof( textbuf );
+ if (SLAP_DB_DELAY_CHECKS(op->o_bd)) {
+ rs->sr_err = slap_mods_final_check( op, op->ora_modlist,
+ textbuf, textlen, NULL );
+ if (rs->sr_err != LDAP_SUCCESS) {
+ send_ldap_error( op, rs, rs->sr_err, textbuf );
+ return rs->sr_err;
+ }
+ }
+ return SLAP_CB_CONTINUE;
+}
+
+int syntax_checks_initialize(void)
+{
+ syntax_checks.on_bi.bi_type = "syntax_checks";
+ syntax_checks.on_bi.bi_op_add = syntax_checks_do_check;
+ syntax_checks.on_bi.bi_op_modify = syntax_checks_do_check;
+ Debug(LDAP_DEBUG_TRACE, ("syntax_checks_initialize\n"),0,0,0);
+ return overlay_register(&syntax_checks);
+}
+
+
+#if SLAPD_OVER_SYNTAXCHECKS == SLAPD_MOD_DYNAMIC
+int init_module( int argc, char *argv[] )
+{
+ return syntax_checks_initialize();
+}
+#endif /* SLAPD_OVER_SYNTAXCHECKS == SLAPD_MOD_DYNAMIC */
+
+#endif /*SLAPD_OVER_SYNTAXCHECKS*/
CFG_DISABLED,
CFG_THREADQS,
CFG_TLS_ECNAME,
+ CFG_DELAY_CHECKS,
CFG_LAST
};
{ "writetimeout", "timeout", 2, 2, 0, ARG_INT,
&global_writetimeout, "( OLcfgGlAt:88 NAME 'olcWriteTimeout' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "delay-checks", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_DELAY_CHECKS,
+ &config_generic, "( OLcfgDbAt:0.22 NAME 'olcDelayChecks' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
};
"olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
"olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ "
"olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ "
- "olcMonitoring $ olcExtraAttrs ) )",
+ "olcMonitoring $ olcExtraAttrs $ olcDelayChecks ) )",
Cft_Database, NULL, cfAddDatabase },
{ "( OLcfgGlOc:5 "
"NAME 'olcOverlayConfig' "
if ( !c->rvalue_vals ) rc = 1;
break;
#endif
+ case CFG_DELAY_CHECKS:
+ if ( SLAP_DB_DELAY_CHECKS( c->be )) {
+ c->value_int = 1;
+ } else {
+ rc = 1;
+ }
+ break;
default:
rc = 1;
}
}
break;
+ case CFG_DELAY_CHECKS:
+ c->be->be_flags &= ~SLAP_DBFLAG_DELAYCHECKS;
+ break;
case CFG_ATOPT:
/* FIXME: there is no ad_option_free function */
case CFG_ROOTDSE:
}
#endif
-
+ case CFG_DELAY_CHECKS:
+ if (c->value_int)
+ SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_DELAYCHECKS;
+ else
+ SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_DELAYCHECKS;
+ break;
default:
Debug( LDAP_DEBUG_ANY,
"%s: unknown CFG_TYPE %d.\n",
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
-
#include "portable.h"
#include <stdio.h>
}
}
#endif /* LDAP_DEBUG */
-
+ if (!SLAP_DB_DELAY_CHECKS(frontendDB)) {
rs->sr_err = slap_mods_check( op, op->orm_modlist,
- &rs->sr_text, textbuf, textlen, NULL );
-
+ &rs->sr_text, textbuf, textlen, NULL );
+ } else {
+ rs->sr_err = slap_mods_initial_check( op, op->orm_modlist,
+ &rs->sr_text, textbuf, textlen, NULL );
+ }
if ( rs->sr_err != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
void *ctx )
{
int rc;
-
for( ; ml != NULL; ml = ml->sml_next ) {
AttributeDescription *ad = NULL;
return LDAP_SUCCESS;
}
+/* slap_mods_check divided in two parts,
+ * the checks that should return non-standard or module-specific error codes
+ * will be moved ot slap_mods_final_check and invoked in an overlay at the bottom of the stack
+ */
+int slap_mods_initial_check(
+ Operation *op,
+ Modifications *ml,
+ const char **text,
+ char *textbuf,
+ size_t textlen,
+ void *ctx )
+{
+ int rc;
+ for( ; ml != NULL; ml = ml->sml_next ) {
+ AttributeDescription *ad = NULL;
+
+ /* convert to attribute description */
+ if ( ml->sml_desc == NULL ) {
+ rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
+ if( rc != LDAP_SUCCESS ) {
+ if ( get_no_schema_check( op )) {
+ rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc,
+ text, 0 );
+ }
+ }
+ if( rc != LDAP_SUCCESS ) {
+ snprintf( textbuf, textlen, "%s: %s",
+ ml->sml_type.bv_val, *text );
+ *text = textbuf;
+ return rc;
+ }
+ }
+
+ ad = ml->sml_desc;
+
+ if( slap_syntax_is_binary( ad->ad_type->sat_syntax )
+ && !slap_ad_is_binary( ad ))
+ {
+ /* attribute requires binary transfer */
+ snprintf( textbuf, textlen,
+ "%s: requires ;binary transfer",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_UNDEFINED_TYPE;
+ }
+
+ if( !slap_syntax_is_binary( ad->ad_type->sat_syntax )
+ && slap_ad_is_binary( ad ))
+ {
+ /* attribute does not require binary transfer */
+ snprintf( textbuf, textlen,
+ "%s: disallows ;binary transfer",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_UNDEFINED_TYPE;
+ }
+
+ if( slap_ad_is_tag_range( ad )) {
+ /* attribute requires binary transfer */
+ snprintf( textbuf, textlen,
+ "%s: inappropriate use of tag range option",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_UNDEFINED_TYPE;
+ }
+
+ if ( ml->sml_op == LDAP_MOD_INCREMENT &&
+#ifdef SLAPD_REAL_SYNTAX
+ !is_at_syntax( ad->ad_type, SLAPD_REAL_SYNTAX ) &&
+#endif
+ !is_at_syntax( ad->ad_type, SLAPD_INTEGER_SYNTAX ) )
+ {
+ /*
+ * attribute values must be INTEGER or REAL
+ */
+ snprintf( textbuf, textlen,
+ "%s: attribute syntax inappropriate for increment",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_CONSTRAINT_VIOLATION;
+ }
+
+ /*
+ * check values
+ */
+ if( ml->sml_values != NULL ) {
+ ber_len_t nvals;
+ slap_syntax_validate_func *validate =
+ ad->ad_type->sat_syntax->ssyn_validate;
+ slap_syntax_transform_func *pretty =
+ ad->ad_type->sat_syntax->ssyn_pretty;
+
+ if( !pretty && !validate ) {
+ *text = "no validator for syntax";
+ snprintf( textbuf, textlen,
+ "%s: no validator for syntax %s",
+ ml->sml_type.bv_val,
+ ad->ad_type->sat_syntax->ssyn_oid );
+ *text = textbuf;
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * check that each value is valid per syntax
+ * and pretty if appropriate
+ */
+ for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
+ struct berval pval;
+
+ if ( pretty ) {
+ rc = ordered_value_pretty( ad,
+ &ml->sml_values[nvals], &pval, ctx );
+ } else {
+ rc = ordered_value_validate( ad,
+ &ml->sml_values[nvals], ml->sml_op );
+ }
+
+ if( rc != 0 ) {
+ snprintf( textbuf, textlen,
+ "%s: value #%ld invalid per syntax",
+ ml->sml_type.bv_val, (long) nvals );
+ *text = textbuf;
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if( pretty ) {
+ ber_memfree_x( ml->sml_values[nvals].bv_val, ctx );
+ ml->sml_values[nvals] = pval;
+ }
+ }
+ ml->sml_values[nvals].bv_len = 0;
+ ml->sml_numvals = nvals;
+
+
+ /* if the type has a normalizer, generate the
+ * normalized values. otherwise leave them NULL.
+ *
+ * this is different from the rule for attributes
+ * in an entry - in an attribute list, the normalized
+ * value is set equal to the non-normalized value
+ * when there is no normalizer.
+ */
+ if( nvals && ad->ad_type->sat_equality &&
+ ad->ad_type->sat_equality->smr_normalize )
+ {
+ ml->sml_nvalues = ber_memalloc_x(
+ (nvals+1)*sizeof(struct berval), ctx );
+
+ for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
+ rc = ordered_value_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ ad,
+ ad->ad_type->sat_equality,
+ &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
+ if ( rc ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= str2entry NULL (ssyn_normalize %d)\n",
+ rc, 0, 0 );
+ snprintf( textbuf, textlen,
+ "%s: value #%ld normalization failed",
+ ml->sml_type.bv_val, (long) nvals );
+ *text = textbuf;
+ BER_BVZERO( &ml->sml_nvalues[nvals] );
+ return rc;
+ }
+ }
+
+ BER_BVZERO( &ml->sml_nvalues[nvals] );
+ }
+
+ /* check for duplicates, but ignore Deletes.
+ */
+ if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) {
+ int i;
+ rc = slap_sort_vals( ml, text, &i, ctx );
+ if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
+ /* value exists already */
+ snprintf( textbuf, textlen,
+ "%s: value #%d provided more than once",
+ ml->sml_desc->ad_cname.bv_val, i );
+ *text = textbuf;
+ }
+ if ( rc )
+ return rc;
+ }
+ } else {
+ ml->sml_numvals = 0;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int slap_mods_final_check(
+ Operation *op,
+ Modifications *ml,
+ char *textbuf,
+ size_t textlen,
+ void *ctx )
+{
+ for( ; ml != NULL; ml = ml->sml_next ) {
+/*
+ * a rough single value check... an additional check is needed
+ * to catch add of single value to existing single valued attribute
+ */
+ if ( ml->sml_values != NULL ) {
+ ber_len_t nvals = 0;
+ while (!BER_BVISNULL( &ml->sml_values[nvals])) {
+ nvals++;
+ }
+ if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE)
+ && nvals > 1 && is_at_single_value( ml->sml_desc->ad_type ))
+ {
+ snprintf( textbuf, textlen,
+ "%s: multiple values provided",
+ ml->sml_type.bv_val );
+ return LDAP_CONSTRAINT_VIOLATION;
+ }
+ }
+ }
+ return LDAP_SUCCESS;
+}
+
+
/* Sort a set of values. An (Attribute *) may be used interchangeably here
* instead of a (Modifications *) structure.
*