summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd
diff options
context:
space:
mode:
authorNathan Kinder <nkinder@redhat.com>2009-05-08 09:14:42 -0700
committerNathan Kinder <nkinder@redhat.com>2009-05-08 09:14:42 -0700
commitd19eafcd211d89cffdac1b2c3432087443e7d122 (patch)
tree26d2b7f956c2ceaa3f605a42552a113e156b5b30 /ldap/servers/slapd
parent5d3d883251dd15cf719181e33fb6954454869822 (diff)
downloadds-d19eafcd211d89cffdac1b2c3432087443e7d122.tar.gz
ds-d19eafcd211d89cffdac1b2c3432087443e7d122.tar.xz
ds-d19eafcd211d89cffdac1b2c3432087443e7d122.zip
Added capability to validate syntax of values being added to the database. Also added numericstring syntax support.
For more details, see the design doc at http://directory.fedoraproject.org/wiki/Syntax_Validation_Design
Diffstat (limited to 'ldap/servers/slapd')
-rw-r--r--ldap/servers/slapd/add.c10
-rw-r--r--ldap/servers/slapd/back-ldbm/import-threads.c22
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_add.c9
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_modify.c14
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_modrdn.c11
-rw-r--r--ldap/servers/slapd/back-ldif/add.c7
-rw-r--r--ldap/servers/slapd/back-ldif/modify.c7
-rw-r--r--ldap/servers/slapd/config.c34
-rw-r--r--ldap/servers/slapd/dse.c23
-rw-r--r--ldap/servers/slapd/fedse.c11
-rw-r--r--ldap/servers/slapd/libglobs.c59
-rw-r--r--ldap/servers/slapd/pblock.c12
-rw-r--r--ldap/servers/slapd/plugin.c16
-rw-r--r--ldap/servers/slapd/plugin_syntax.c177
-rw-r--r--ldap/servers/slapd/proto-slap.h4
-rw-r--r--ldap/servers/slapd/schema.c4
-rw-r--r--ldap/servers/slapd/slap.h22
-rw-r--r--ldap/servers/slapd/slapi-plugin.h6
18 files changed, 416 insertions, 32 deletions
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index b69da2e5..6607eff9 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -800,6 +800,16 @@ static void handle_fast_add(Slapi_PBlock *pb, Slapi_Entry *entry)
return;
}
+ /* syntax check */
+ if (slapi_entry_syntax_check(pb, entry, 0) != 0) {
+ char *errtext;
+ LDAPDebug(LDAP_DEBUG_TRACE, "entry failed syntax check\n", 0, 0, 0);
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
+ send_ldap_result(pb, LDAP_INVALID_SYNTAX, NULL, errtext, 0, NULL);
+ slapi_entry_free(entry);
+ return;
+ }
+
/* Check if the entry being added is a Tombstone. Could be if we are
* doing a replica init. */
if (slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS,
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 7a1bcba1..7cde2bfc 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -534,9 +534,27 @@ void import_producer(void *param)
"violates schema, ending line %d of file "
"\"%s\"", escape_string(slapi_entry_get_dn(e), ebuf),
curr_lineno, curr_filename);
- if (e)
+ if (e) {
+ slapi_entry_free(e);
+ }
+
+ job->skipped++;
+ continue;
+ }
+
+ /* Check attribute syntax */
+ if (slapi_entry_syntax_check(NULL, e, 0) != 0)
+ {
+ char ebuf[BUFSIZ];
+ import_log_notice(job, "WARNING: skipping entry \"%s\" which "
+ "violates attribute syntax, ending line %d of "
+ "file \"%s\"", escape_string(slapi_entry_get_dn(e), ebuf),
+ curr_lineno, curr_filename);
+ if (e) {
slapi_entry_free(e);
- job->skipped++;
+ }
+
+ job->skipped++;
continue;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 764cff99..b9f573a7 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -305,6 +305,15 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
+ /* Check attribute syntax */
+ if (slapi_entry_syntax_check(pb, e, 0) != 0)
+ {
+ LDAPDebug(LDAP_DEBUG_TRACE, "entry failed syntax check\n", 0, 0, 0);
+ ldap_result_code = LDAP_INVALID_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+
opcsn = operation_get_csn (operation);
if(is_resurect_operation)
{
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index c169e9ed..1cbe92de 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -188,6 +188,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
struct backentry *e, *ec = NULL;
Slapi_Entry *postentry = NULL;
LDAPMod **mods;
+ Slapi_Mods smods;
back_txn txn;
back_txnid parent_txn;
int retval = -1;
@@ -279,11 +280,10 @@ ldbm_back_modify( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
/* The Plugin may have messed about with some of the PBlock parameters... ie. mods */
slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
+ slapi_mods_init_byref(&smods,mods);
{
- Slapi_Mods smods;
CSN *csn = operation_get_csn(operation);
- slapi_mods_init_byref(&smods,mods);
if ( (change_entry = mods_have_effect (ec->ep_entry, &smods)) ) {
ldap_result_code = entry_apply_mods_wsi(ec->ep_entry, &smods, csn, operation_is_flag_set(operation,OP_FLAG_REPLICATED));
/*
@@ -301,7 +301,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
slapi_pblock_set ( pb, SLAPI_ENTRY_POST_OP, postentry );
postentry = NULL; /* avoid removal/free in error_return code */
}
- slapi_mods_done(&smods);
if ( !change_entry || ldap_result_code != 0 ) {
/* change_entry == 0 is not an error, but we need to free lock etc */
goto error_return;
@@ -340,6 +339,14 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
+ /* check attribute syntax for the new values */
+ if (slapi_mods_syntax_check(pb, mods, 0) != 0)
+ {
+ ldap_result_code = LDAP_INVALID_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+
/*
* make sure the entry contains all values in the RDN.
* if not, the modification must have removed them.
@@ -506,6 +513,7 @@ error_return:
common_return:
+ slapi_mods_done(&smods);
if (ec_in_cache)
{
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 1cb35ab8..c71dd8ee 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -530,6 +530,17 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ /* Check attribute syntax if any new values are being added for the new RDN */
+ if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
+ {
+ if (slapi_mods_syntax_check(pb, smods_generated_wsi.mods, 0) != 0)
+ {
+ ldap_result_code = LDAP_INVALID_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+ }
+
/*
* Update the DN CSN of the entry.
*/
diff --git a/ldap/servers/slapd/back-ldif/add.c b/ldap/servers/slapd/back-ldif/add.c
index 231f5483..27799973 100644
--- a/ldap/servers/slapd/back-ldif/add.c
+++ b/ldap/servers/slapd/back-ldif/add.c
@@ -92,6 +92,13 @@ ldif_back_add( Slapi_PBlock *pb )
return( -1 );
}
+ /* Check if the attribute values in the entry obey the syntaxes */
+ if ( slapi_entry_syntax_check( pb, e, 0 ) != 0 ) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "entry failed syntax_check\n", 0, 0, 0 );
+ slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, NULL, 0, NULL );
+ return( -1 );
+ }
+
prev = NULL;
/*Lock the database*/
diff --git a/ldap/servers/slapd/back-ldif/modify.c b/ldap/servers/slapd/back-ldif/modify.c
index 58229ecc..7fff0670 100644
--- a/ldap/servers/slapd/back-ldif/modify.c
+++ b/ldap/servers/slapd/back-ldif/modify.c
@@ -140,6 +140,13 @@ ldif_back_modify( Slapi_PBlock *pb )
PR_Unlock( db->ldif_lock );
goto error_return;
}
+
+ /* Check if the attribute values in the mods obey the syntaxes */
+ if ( slapi_mods_syntax_check( pb, mods, 0 ) != 0 ) {
+ slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, NULL, 0, NULL );
+ PR_Unlock( db->ldif_lock );
+ goto error_return;
+ }
/* Check for abandon again */
if ( slapi_op_abandoned( pb ) ) {
diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c
index 9cf56ddd..1af1b77b 100644
--- a/ldap/servers/slapd/config.c
+++ b/ldap/servers/slapd/config.c
@@ -239,11 +239,13 @@ slapd_bootstrap_config(const char *configdir)
char _localuser[BUFSIZ];
char logenabled[BUFSIZ];
char schemacheck[BUFSIZ];
+ char syntaxcheck[BUFSIZ];
+ char syntaxlogging[BUFSIZ];
Slapi_DN plug_dn;
workpath[0] = loglevel[0] = maxdescriptors[0] = '\0';
- val[0] = logenabled[0] = schemacheck[0] = '\0';
- _localuser[0] = '\0';
+ val[0] = logenabled[0] = schemacheck[0] = syntaxcheck[0] = '\0';
+ syntaxlogging[0] = _localuser[0] = '\0';
/* Convert LDIF to entry structures */
slapi_sdn_init_dn_byref(&plug_dn, PLUGIN_BASE_DN);
@@ -460,6 +462,34 @@ slapd_bootstrap_config(const char *configdir)
}
}
+ /* see if we need to enable syntax checking */
+ if (!syntaxcheck[0] &&
+ entry_has_attr_and_value(e, CONFIG_SYNTAXCHECK_ATTRIBUTE,
+ syntaxcheck, sizeof(syntaxcheck)))
+ {
+ if (config_set_syntaxcheck(CONFIG_SYNTAXCHECK_ATTRIBUTE,
+ syntaxcheck, errorbuf, CONFIG_APPLY)
+ != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_SYNTAXCHECK_ATTRIBUTE, errorbuf);
+ }
+ }
+
+ /* see if we need to enable syntax warnings */
+ if (!syntaxlogging[0] &&
+ entry_has_attr_and_value(e, CONFIG_SYNTAXLOGGING_ATTRIBUTE,
+ syntaxlogging, sizeof(syntaxlogging)))
+ {
+ if (config_set_syntaxlogging(CONFIG_SYNTAXLOGGING_ATTRIBUTE,
+ syntaxlogging, errorbuf, CONFIG_APPLY)
+ != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_SYNTAXLOGGING_ATTRIBUTE, errorbuf);
+ }
+ }
+
/* see if we need to expect quoted schema values */
if (entry_has_attr_and_value(e, CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE,
val, sizeof(val)))
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 4d593500..956c29d4 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -1864,6 +1864,17 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
return dse_modify_return( -1, ec, ecc );
}
+ /* Check if the attribute values in the mods obey the syntaxes */
+ if ( slapi_mods_syntax_check( pb, mods, 0 ) != 0 )
+ {
+ char *errtext;
+
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
+ slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errtext, 0, NULL );
+ slapi_sdn_done(&sdn);
+ return dse_modify_return( -1, ec, ecc );
+ }
+
/* Change the entry itself both on disk and in the AVL tree */
/* dse_replace_entry free's the existing entry. */
if (dse_replace_entry( pdse, ecc, !dont_write_file, DSE_USE_LOCK )!=0 )
@@ -1941,6 +1952,18 @@ dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this f
return error;
}
+ /* Check if the attribute values in the entry obey the syntaxes */
+ if ( slapi_entry_syntax_check( pb, e, 0 ) != 0 )
+ {
+ char *errtext;
+ LDAPDebug( SLAPI_DSE_TRACELEVEL,
+ "dse_add: entry failed syntax check\n", 0, 0, 0 );
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
+ slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errtext, 0, NULL );
+ slapi_sdn_done(&sdn);
+ return error;
+ }
+
/*
* Attempt to find this dn.
*/
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
index f71b7fdd..beec7d5c 100644
--- a/ldap/servers/slapd/fedse.c
+++ b/ldap/servers/slapd/fedse.c
@@ -143,14 +143,7 @@ static const char *internal_entries[] =
"objectclass:top\n"
"objectclass:nsSNMP\n"
"cn:SNMP\n"
- "nsSNMPEnabled:on\n"
- "nsSNMPName:\n"
- "nsSNMPOrganization:\n"
- "nsSNMPLocation:\n"
- "nsSNMPContact:\n"
- "nsSNMPDescription:\n"
- "nsSNMPMasterHost:\n"
- "nsSNMPMasterPort:\n"
+ "nsSNMPEnabled: on\n"
"aci:(target=\"ldap:///cn=SNMP,cn=config\")(targetattr !=\"aci\")(version 3.0;acl \"snmp\";allow (read, search, compare)(userdn = \"ldap:///anyone\");)\n",
};
@@ -161,7 +154,7 @@ static char *easter_egg_entry=
"1E14405A150F47341F0E09191B0A1F5A3E13081F190E1508035A2E1F1B1756191447171514"
"130E1508701518101F190E39161B0909405A0E150A701518101F190E39161B0909405A1508"
"1D1B1413001B0E1315141B162F14130E701518101F190E39161B0909405A1E13081F190E15"
-"0803040E1F1B17041F020E1F14091318161F041518101F190E70150F405A341F0E09191B0A"
+"0803570E1F1B17571F020E1F14091318161F571518101F190E70150F405A341F0E09191B0A"
"1F5A291F190F08130E035A2915160F0E1315140970150F405A341F0E09191B0A1F5A3E1308"
"1F190E1508035A2E1F1B17701E1F091908130A0E131514405A3E1B0C131E5A3815081F121B"
"17565A301B190B0F1F1613141F5A3815081F121B17565A3B140E121514035A3C15020D1508"
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index e473663c..30ad5f3a 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -321,6 +321,12 @@ static struct config_get_and_set {
{CONFIG_SCHEMACHECK_ATTRIBUTE, config_set_schemacheck,
NULL, 0,
(void**)&global_slapdFrontendConfig.schemacheck, CONFIG_ON_OFF, NULL},
+ {CONFIG_SYNTAXCHECK_ATTRIBUTE, config_set_syntaxcheck,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.syntaxcheck, CONFIG_ON_OFF, NULL},
+ {CONFIG_SYNTAXLOGGING_ATTRIBUTE, config_set_syntaxlogging,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.syntaxlogging, CONFIG_ON_OFF, NULL},
{CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE, config_set_ds4_compatible_schema,
NULL, 0,
(void**)&global_slapdFrontendConfig.ds4_compatible_schema,
@@ -891,6 +897,8 @@ FrontendConfig_init () {
cfg->sizelimit = SLAPD_DEFAULT_SIZELIMIT;
cfg->timelimit = SLAPD_DEFAULT_TIMELIMIT;
cfg->schemacheck = LDAP_ON;
+ cfg->syntaxcheck = LDAP_OFF;
+ cfg->syntaxlogging = LDAP_OFF;
cfg->ds4_compatible_schema = LDAP_OFF;
cfg->enquote_sup_oc = LDAP_OFF;
cfg->lastmod = LDAP_ON;
@@ -2422,6 +2430,33 @@ config_set_schemacheck( const char *attrname, char *value, char *errorbuf, int a
return retVal;
}
+int
+config_set_syntaxcheck( const char *attrname, char *value, char *errorbuf, int apply ) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+ &(slapdFrontendConfig->syntaxcheck),
+ errorbuf,
+ apply);
+
+ return retVal;
+}
+
+int
+config_set_syntaxlogging( const char *attrname, char *value, char *errorbuf, int apply ) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+ &(slapdFrontendConfig->syntaxlogging),
+ errorbuf,
+ apply);
+
+ return retVal;
+}
int
config_set_ds4_compatible_schema( const char *attrname, char *value, char *errorbuf, int apply ) {
@@ -4034,6 +4069,30 @@ config_get_schemacheck() {
}
int
+config_get_syntaxcheck() {
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->syntaxcheck;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_get_syntaxlogging() {
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->syntaxlogging;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
config_get_ds4_compatible_schema() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
int retVal;
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 6ac6aa8e..062a87f8 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1072,6 +1072,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
case SLAPI_SYNTAX_SUBSTRLENS:
(*(int **)value) = pblock->pb_substrlens;
break;
+ case SLAPI_PLUGIN_SYNTAX_VALIDATE:
+ if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_SYNTAX ) {
+ return( -1 );
+ }
+ (*(int *)value) = pblock->pb_plugin->plg_syntax_validate;
+ break;
/* controls we know about */
case SLAPI_MANAGEDSAIT:
@@ -2314,6 +2320,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
case SLAPI_SYNTAX_SUBSTRLENS:
pblock->pb_substrlens = (int *) value;
break;
+ case SLAPI_PLUGIN_SYNTAX_VALIDATE:
+ if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_SYNTAX ) {
+ return( -1 );
+ }
+ pblock->pb_plugin->plg_syntax_validate = (IFP) value;
+ break;
case SLAPI_ENTRY_PRE_OP:
pblock->pb_pre_op_entry = (Slapi_Entry *) value;
break;
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index a7ad7dff..5ae63564 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -1878,35 +1878,37 @@ plugin_add_descriptive_attributes( Slapi_Entry *e, struct slapdplugin *plugin )
if ( NULL == plugin )
{
+ /* This can happen for things such as disabled syntax plug-ins. We
+ * just treat this as a warning to allow the description attributes
+ * to be set to a default value to avoid an objectclass violation. */
LDAPDebug(LDAP_DEBUG_PLUGIN,
- "Error: failed to add descriptive values for plugin %s"
- " (could not find plugin entry)\n",
+ "Warning: couldn't find plugin %s in global list. "
+ "Adding default descriptive values.\n",
slapi_entry_get_dn_const(e), 0, 0 );
- return 1; /* failure */
}
}
if (add_plugin_description(e, ATTR_PLUGIN_PLUGINID,
- plugin->plg_desc.spd_id))
+ plugin ? plugin->plg_desc.spd_id : NULL))
{
status = 1;
}
if (add_plugin_description(e, ATTR_PLUGIN_VERSION,
- plugin->plg_desc.spd_version))
+ plugin ? plugin->plg_desc.spd_version : NULL))
{
status = 1;
}
if (add_plugin_description(e, ATTR_PLUGIN_VENDOR,
- plugin->plg_desc.spd_vendor))
+ plugin ? plugin->plg_desc.spd_vendor: NULL))
{
status = 1;
}
if (add_plugin_description(e, ATTR_PLUGIN_DESC,
- plugin->plg_desc.spd_description))
+ plugin ? plugin->plg_desc.spd_description : NULL))
{
status = 1;
}
diff --git a/ldap/servers/slapd/plugin_syntax.c b/ldap/servers/slapd/plugin_syntax.c
index cb3cde9f..3290a954 100644
--- a/ldap/servers/slapd/plugin_syntax.c
+++ b/ldap/servers/slapd/plugin_syntax.c
@@ -261,6 +261,183 @@ plugin_call_syntax_filter_sub_sv(
return( rc );
}
+/* Checks if the values of all attributes in an entry are valid for the
+ * syntax specified for the attribute in question. Setting override to
+ * 1 will force syntax checking to be performed, even if syntax checking
+ * is disabled in the config. Setting override to 0 will obey the config
+ * settings.
+ *
+ * Returns 1 if there is a syntax violation and sets the error message
+ * appropriately. Returns 0 if everything checks out fine.
+ */
+int
+slapi_entry_syntax_check(
+ Slapi_PBlock *pb, Slapi_Entry *e, int override
+)
+{
+ int ret = 0;
+ int i = 0;
+ int is_replicated_operation = 0;
+ int badval = 0;
+ int syntaxcheck = config_get_syntaxcheck();
+ int syntaxlogging = config_get_syntaxlogging();
+ Slapi_Attr *prevattr = NULL;
+ Slapi_Attr *a = NULL;
+ char errtext[ BUFSIZ ];
+ char *errp = &errtext[0];
+ size_t err_remaining = sizeof(errtext);
+
+ if (pb != NULL) {
+ slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation);
+ }
+
+ /* If syntax checking and logging are off, or if this is a
+ * replicated operation, just return that the syntax is OK. */
+ if (((syntaxcheck == 0) && (syntaxlogging == 0) && (override == 0)) ||
+ is_replicated_operation) {
+ goto exit;
+ }
+
+ i = slapi_entry_first_attr(e, &a);
+
+ while ((-1 != i) && a && (a->a_plugin != NULL)) {
+ /* If no validate function is available for this type, just
+ * assume that the value is valid. */
+ if ( a->a_plugin->plg_syntax_validate != NULL ) {
+ int numvals = 0;
+
+ slapi_attr_get_numvalues(a, &numvals);
+ if ( numvals > 0 ) {
+ Slapi_Value *val = NULL;
+ const struct berval *bval = NULL;
+ int hint = slapi_attr_first_value(a, &val);
+
+ /* iterate through each value to check if it's valid */
+ while (val != NULL) {
+ bval = slapi_value_get_berval(val);
+ if ((a->a_plugin->plg_syntax_validate( bval )) != 0) {
+ if (syntaxlogging) {
+ slapi_log_error( SLAPI_LOG_FATAL, "Syntax Check",
+ "\"%s\": (%s) value #%d invalid per syntax\n",
+ slapi_entry_get_dn(e), a->a_type, hint );
+ }
+
+ if (syntaxcheck || override) {
+ if (pb) {
+ /* Append new text to any existing text. */
+ errp += PR_snprintf( errp, err_remaining,
+ "%s: value #%d invalid per syntax\n", a->a_type, hint );
+ err_remaining -= errp - &errtext[0];
+ }
+ ret = 1;
+ }
+ }
+
+ hint = slapi_attr_next_value(a, hint, &val);
+ }
+ }
+ }
+
+ prevattr = a;
+ i = slapi_entry_next_attr(e, prevattr, &a);
+ }
+
+ /* See if we need to set the error text in the pblock. */
+ if (errp != &errtext[0]) {
+ slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
+ }
+
+exit:
+ return( ret );
+}
+
+/* Checks if the values of all attributes being added in a Slapi_Mods
+ * are valid for the syntax specified for the attribute in question.
+ * The new values in an add or replace modify operation and the newrdn
+ * value for a modrdn operation will be checked.
+ * Returns 1 if there is a syntax violation and sets the error message
+ * appropriately. Returns 0 if everything checks out fine.
+ */
+int
+slapi_mods_syntax_check(
+ Slapi_PBlock *pb, LDAPMod **mods, int override
+)
+{
+ int ret = 0;
+ int i, j = 0;
+ int is_replicated_operation = 0;
+ int badval = 0;
+ int syntaxcheck = config_get_syntaxcheck();
+ int syntaxlogging = config_get_syntaxlogging();
+ char errtext[ BUFSIZ ];
+ char *errp = &errtext[0];
+ size_t err_remaining = sizeof(errtext);
+ char *dn = NULL;
+ LDAPMod *mod = NULL;
+
+ if (mods == NULL) {
+ ret = 1;
+ goto exit;
+ }
+
+ if (pb != NULL) {
+ slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation);
+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
+ }
+
+ /* If syntax checking and logging are off, or if this is a
+ * replicated operation, just return that the syntax is OK. */
+ if (((syntaxcheck == 0) && (syntaxlogging == 0) && (override == 0)) ||
+ is_replicated_operation) {
+ goto exit;
+ }
+
+ /* Loop through mods */
+ for (i = 0; mods[i] != NULL; i++) {
+ mod = mods[i];
+
+ /* We only care about replace and add modify operations that
+ * are truly adding new values to the entry. */
+ if ((SLAPI_IS_MOD_REPLACE(mod->mod_op) || SLAPI_IS_MOD_ADD(mod->mod_op)) &&
+ (mod->mod_bvalues != NULL)) {
+ struct slapdplugin *syntax_plugin = NULL;
+
+ /* Find the plug-in for this type, then call it's
+ * validate function.*/
+ slapi_attr_type2plugin(mod->mod_type, (void **)&syntax_plugin);
+ if ((syntax_plugin != NULL) && (syntax_plugin->plg_syntax_validate != NULL)) {
+ /* Loop through the values and validate each one */
+ for (j = 0; mod->mod_bvalues[j] != NULL; j++) {
+ if (syntax_plugin->plg_syntax_validate(mod->mod_bvalues[j]) != 0) {
+ if (syntaxlogging) {
+ slapi_log_error( SLAPI_LOG_FATAL, "Syntax Check", "\"%s\": (%s) value #%d invalid per syntax\n",
+ dn ? dn : "NULL", mod->mod_type, j );
+ }
+
+ if (syntaxcheck || override) {
+ if (pb) {
+ /* Append new text to any existing text. */
+ errp += PR_snprintf( errp, err_remaining,
+ "%s: value #%d invalid per syntax\n", mod->mod_type, j );
+ err_remaining -= errp - &errtext[0];
+ }
+ ret = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* See if we need to set the error text in the pblock. */
+ if (errp != &errtext[0]) {
+ slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
+ }
+
+exit:
+ return( ret );
+}
+
SLAPI_DEPRECATED int
slapi_call_syntax_values2keys( /* JCM SLOW FUNCTION */
void *vpi,
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 7c25b18d..c561196d 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -264,6 +264,8 @@ int config_set_accesscontrol( const char *attrname, char *value, char *errorbuf,
int config_set_security( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_readonly( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_schemacheck( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_syntaxcheck( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_syntaxlogging( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_ds4_compatible_schema( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_schema_ignore_trailing_spaces( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_rootdn( const char *attrname, char *value, char *errorbuf, int apply );
@@ -406,6 +408,8 @@ int config_get_return_exact_case();
int config_get_result_tweak();
int config_get_security();
int config_get_schemacheck();
+int config_get_syntaxcheck();
+int config_get_syntaxlogging();
int config_get_ds4_compatible_schema();
int config_get_schema_ignore_trailing_spaces();
char *config_get_rootdn();
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 04b13d09..e331a946 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -3415,7 +3415,9 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
schema_errprefix_at, first_attr_name,
"Missing parent attribute syntax OID");
status = invalid_syntax_error;
- } else {
+ /* We only want to use the parent syntax if a SYNTAX
+ * wasn't explicitly specified for this attribute. */
+ } else if (NULL == pSyntax) {
char *pso = plugin_syntax2oid(asi_parent->asi_plugin);
if (pso) {
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index ceeb11e9..cec186f9 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -287,8 +287,8 @@ typedef void (*VFP0)();
#define SLAPD_SCHEMA_DN "cn=schema"
#define SLAPD_CONFIG_DN "cn=config"
-#define EGG_OBJECT_CLASS "directory~team~extensible~object"
-#define EGG_FILTER "(objectclass=directory~team~extensible~object)"
+#define EGG_OBJECT_CLASS "directory-team-extensible-object"
+#define EGG_FILTER "(objectclass=directory-team-extensible-object)"
#define BE_LIST_SIZE 100 /* used by mapping tree code to hold be_list stuff */
@@ -501,16 +501,17 @@ typedef int (*SyntaxEnumFunc)(char **names, Slapi_PluginDesc *plugindesc,
/* OIDs for some commonly used syntaxes */
#define BINARY_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.5"
-#define BOOLEAN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.7"
+#define BOOLEAN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.7"
#define COUNTRYSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.11"
#define DN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.12"
#define DIRSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.15"
#define GENERALIZEDTIME_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.24"
#define IA5STRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.26"
#define INTEGER_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.27"
-#define JPEG_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.28"
+#define JPEG_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.28"
+#define NUMERICSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.36"
+#define OID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.38"
#define OCTETSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.40"
-#define OID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.38"
#define POSTALADDRESS_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.41"
#define TELEPHONE_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.50"
#define SPACE_INSENSITIVE_STRING_SYNTAX_OID "2.16.840.1.113730.3.7.1"
@@ -967,6 +968,7 @@ struct slapdplugin {
char **plg_un_syntax_names;
char *plg_un_syntax_oid;
IFP plg_un_syntax_compare;
+ IFP plg_un_syntax_validate;
} plg_un_syntax;
#define plg_syntax_filter_ava plg_un.plg_un_syntax.plg_un_syntax_filter_ava
#define plg_syntax_filter_sub plg_un.plg_un_syntax.plg_un_syntax_filter_sub
@@ -976,7 +978,8 @@ struct slapdplugin {
#define plg_syntax_flags plg_un.plg_un_syntax.plg_un_syntax_flags
#define plg_syntax_names plg_un.plg_un_syntax.plg_un_syntax_names
#define plg_syntax_oid plg_un.plg_un_syntax.plg_un_syntax_oid
-#define plg_syntax_compare plg_un.plg_un_syntax.plg_un_syntax_compare
+#define plg_syntax_compare plg_un.plg_un_syntax.plg_un_syntax_compare
+#define plg_syntax_validate plg_un.plg_un_syntax.plg_un_syntax_validate
struct plg_un_acl_struct {
IFP plg_un_acl_init;
@@ -1519,6 +1522,9 @@ typedef struct daemon_ports_s {
/* Definition for plugin syntax compare routine */
typedef int (*value_compare_fn_type)(const struct berval *,const struct berval *);
+/* Definition for plugin syntax validate routine */
+typedef int (*value_validate_fn_type)(const struct berval *);
+
#include "pw.h"
#include "proto-slap.h"
@@ -1631,6 +1637,8 @@ typedef struct _slapdEntryPoints {
#define CONFIG_OBJECTCLASS_ATTRIBUTE "nsslapd-objectclass"
#define CONFIG_ATTRIBUTE_ATTRIBUTE "nsslapd-attribute"
#define CONFIG_SCHEMACHECK_ATTRIBUTE "nsslapd-schemacheck"
+#define CONFIG_SYNTAXCHECK_ATTRIBUTE "nsslapd-syntaxcheck"
+#define CONFIG_SYNTAXLOGGING_ATTRIBUTE "nsslapd-syntaxlogging"
#define CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE "nsslapd-ds4-compatible-schema"
#define CONFIG_SCHEMA_IGNORE_TRAILING_SPACES "nsslapd-schema-ignore-trailing-spaces"
#define CONFIG_SCHEMAREPLACE_ATTRIBUTE "nsslapd-schemareplace"
@@ -1846,6 +1854,8 @@ typedef struct _slapdFrontendConfig {
int readonly;
int reservedescriptors;
int schemacheck;
+ int syntaxcheck;
+ int syntaxlogging;
int ds4_compatible_schema;
int schema_ignore_trailing_spaces;
int secureport;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 3c0cf72d..70556e98 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -280,6 +280,8 @@ int slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Att
const char *slapi_entry_get_uniqueid( const Slapi_Entry *e );
void slapi_entry_set_uniqueid( Slapi_Entry *e, char *uniqueid );
int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e );
+int slapi_entry_syntax_check( Slapi_PBlock *pb, Slapi_Entry *e, int override );
+int slapi_mods_syntax_check( Slapi_PBlock *pb, LDAPMod **mods, int override );
int slapi_entry_rdn_values_present( const Slapi_Entry *e );
int slapi_entry_add_rdn_values( Slapi_Entry *e );
int slapi_entry_attr_delete( Slapi_Entry *e, const char *type );
@@ -1702,9 +1704,9 @@ typedef struct slapi_plugindesc {
#define SLAPI_PLUGIN_SYNTAX_OID 706
#define SLAPI_PLUGIN_SYNTAX_FLAGS 707
#define SLAPI_PLUGIN_SYNTAX_COMPARE 708
-
/* user defined substrlen; not stored in slapdplugin, but pblock itself */
-#define SLAPI_SYNTAX_SUBSTRLENS 709
+#define SLAPI_SYNTAX_SUBSTRLENS 709
+#define SLAPI_PLUGIN_SYNTAX_VALIDATE 710
/* ACL plugin functions and arguments */
#define SLAPI_PLUGIN_ACL_INIT 730