summaryrefslogtreecommitdiffstats
path: root/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'ldap')
-rw-r--r--ldap/ldif/template-dse.ldif.in100
-rw-r--r--ldap/servers/plugins/syntaxes/bin.c32
-rw-r--r--ldap/servers/plugins/syntaxes/bitstring.c195
-rw-r--r--ldap/servers/plugins/syntaxes/cis.c46
-rw-r--r--ldap/servers/plugins/syntaxes/deliverymethod.c318
-rw-r--r--ldap/servers/plugins/syntaxes/dn.c222
-rw-r--r--ldap/servers/plugins/syntaxes/facsimile.c324
-rw-r--r--ldap/servers/plugins/syntaxes/guide.c734
-rw-r--r--ldap/servers/plugins/syntaxes/nameoptuid.c232
-rw-r--r--ldap/servers/plugins/syntaxes/syntax.h12
-rw-r--r--ldap/servers/plugins/syntaxes/teletex.c342
-rw-r--r--ldap/servers/plugins/syntaxes/telex.c257
-rw-r--r--ldap/servers/plugins/syntaxes/validate.c259
-rw-r--r--ldap/servers/slapd/slap.h10
14 files changed, 2857 insertions, 226 deletions
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index 2694f0f1..d0e29278 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -244,6 +244,16 @@ nsslapd-plugininitfunc: bin_init
nsslapd-plugintype: syntax
nsslapd-pluginenabled: on
+dn: cn=Bit String Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Bit String
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: bitstring_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
dn: cn=Octet String Syntax,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
@@ -284,6 +294,76 @@ nsslapd-plugininitfunc: tel_init
nsslapd-plugintype: syntax
nsslapd-pluginenabled: on
+dn: cn=Telex Number Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Telex Number Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: telex_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Teletex Terminal Identifier Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Teletex Terminal Identifier Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: teletex_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Enhanced Guide Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Enhanced Guide Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: enhancedguide_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Facsimile Telephone Number Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Facsimile Telephone Number Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: facsimile_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Fax Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Fax Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: fax_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Guide Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Guide Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: guide_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
+dn: cn=Delivery Method Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Delivery Method Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: delivery_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
dn: cn=Integer Syntax,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
@@ -304,6 +384,16 @@ nsslapd-plugininitfunc: dn_init
nsslapd-plugintype: syntax
nsslapd-pluginenabled: on
+dn: cn=Name And Optional UID Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Name And Optional UID Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: nameoptuid_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
dn: cn=OID Syntax,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
@@ -364,6 +454,16 @@ nsslapd-plugininitfunc: numstr_init
nsslapd-plugintype: syntax
nsslapd-pluginenabled: on
+dn: cn=Printable String Syntax,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Printable String Syntax
+nsslapd-pluginpath: libsyntax-plugin
+nsslapd-plugininitfunc: printable_init
+nsslapd-plugintype: syntax
+nsslapd-pluginenabled: on
+
dn: cn=State Change Plugin,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
diff --git a/ldap/servers/plugins/syntaxes/bin.c b/ldap/servers/plugins/syntaxes/bin.c
index 2d0b6f8a..be423582 100644
--- a/ldap/servers/plugins/syntaxes/bin.c
+++ b/ldap/servers/plugins/syntaxes/bin.c
@@ -43,7 +43,8 @@
/* bin.c - bin syntax routines */
/*
- * This file actually implements three syntax plugins: OctetString, JPEG, and Binary.
+ * This file actually implements four syntax plugins: OctetString, JPEG,
+ * Fax, and Binary.
*/
#include <stdio.h>
@@ -59,11 +60,11 @@ static int bin_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *bval,
Slapi_Value ***ivals, int ftype );
/*
- * Attribute syntaxes. We treat all of these the same for now, even though
- * the specifications (e.g., RFC 2252) impose various constraints on the
- * the format for each of these.
- *
- * Note: the first name is the official one from RFC 2252.
+ * Attribute syntaxes. We treat all of these the same since the
+ * LDAP-specific encoding for all of them are simply strings of octets
+ * with no real content restrictions (even though the content is supposed
+ * to represent something specific). For this reason, we do no
+ * validation of the values for these syntaxes.
*/
static char *bin_names[] = { "Binary", "bin", BINARY_SYNTAX_OID, 0 };
@@ -71,6 +72,8 @@ static char *octetstring_names[] = { "OctetString", OCTETSTRING_SYNTAX_OID, 0 };
static char *jpeg_names[] = { "JPEG", JPEG_SYNTAX_OID, 0 };
+static char *fax_names[] = { "FAX", FAX_SYNTAX_OID, 0 };
+
/* This syntax has "gone away" in RFC 4517, however we still use it for
* a number of attributes in our default schema. We should try to eliminate
@@ -90,6 +93,10 @@ static Slapi_PluginDesc jpeg_pdesc = {
"JPEG attribute syntax plugin"
};
+static Slapi_PluginDesc fax_pdesc = {
+ "fax-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Fax attribute syntax plugin"
+};
/*
* register_bin_like_plugin(): register all items for a bin-like plugin.
@@ -158,6 +165,19 @@ jpeg_init( Slapi_PBlock *pb )
}
+int
+fax_init( Slapi_PBlock *pb )
+{
+ int rc;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> fax_init\n", 0, 0, 0 );
+ rc = register_bin_like_plugin( pb, &fax_pdesc, fax_names,
+ FAX_SYNTAX_OID );
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= fax_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+
static int
bin_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
Slapi_Value **bvals, int ftype, Slapi_Value **retVal )
diff --git a/ldap/servers/plugins/syntaxes/bitstring.c b/ldap/servers/plugins/syntaxes/bitstring.c
new file mode 100644
index 00000000..91f88846
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/bitstring.c
@@ -0,0 +1,195 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* bitstring.c - Bit String syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int bitstring_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int bitstring_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int bitstring_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int bitstring_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int bitstring_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int bitstring_compare(struct berval *v1, struct berval *v2);
+static int bitstring_validate(struct berval *val);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Bit String", "bitstring", BITSTRING_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "bitstring-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Bit String attribute syntax plugin" };
+
+int
+bitstring_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> bitstring_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) bitstring_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) bitstring_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) bitstring_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) bitstring_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) bitstring_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) BITSTRING_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) bitstring_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) bitstring_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= bitstring_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+bitstring_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CES,
+ ftype, retVal ) );
+}
+
+
+static int
+bitstring_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CES ) );
+}
+
+static int
+bitstring_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CES,
+ ftype ) );
+}
+
+static int
+bitstring_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CES, ftype ));
+}
+
+static int
+bitstring_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CES ) );
+}
+
+static int bitstring_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CES, 3 /* Normalise both values */);
+}
+
+static int
+bitstring_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ rc = bitstring_validate_internal(val->bv_val, &(val->bv_val[val->bv_len - 1]));
+
+exit:
+ return rc;
+}
+
diff --git a/ldap/servers/plugins/syntaxes/cis.c b/ldap/servers/plugins/syntaxes/cis.c
index 4f1d9d71..2af300ba 100644
--- a/ldap/servers/plugins/syntaxes/cis.c
+++ b/ldap/servers/plugins/syntaxes/cis.c
@@ -51,7 +51,7 @@
* GeneralizedTime
* OID
* PostalAddress
- *
+ * PrintableString
*/
#include <stdio.h>
@@ -76,6 +76,7 @@ static int time_validate(struct berval *val);
static int country_validate(struct berval *val);
static int postal_validate(struct berval *val);
static int oid_validate(struct berval *val);
+static int printable_validate(struct berval *val);
/*
* Attribute syntaxes. We treat all of these the same for now, even though
@@ -114,6 +115,9 @@ static char *postal_names[] = { "Postal Address",
static char *oid_names[] = { "OID",
OID_SYNTAX_OID, 0};
+static char *printable_names[] = { "Printable String",
+ PRINTABLESTRING_SYNTAX_OID, 0};
+
/*
TBD (XXX)
@@ -172,6 +176,10 @@ static Slapi_PluginDesc oid_pdesc = { "oid-syntax",
PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
"OID attribute syntax plugin" };
+static Slapi_PluginDesc printable_pdesc = { "printablestring-syntax",
+ PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Printable String attribtue syntax plugin" };
+
/*
* register_cis_like_plugin(): register all items for a cis-like plugin.
@@ -289,7 +297,17 @@ oid_init( Slapi_PBlock *pb )
return( rc );
}
+int
+printable_init( Slapi_PBlock *pb )
+{
+ int rc;
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> printable_init\n", 0, 0, 0 );
+ rc = register_cis_like_plugin( pb, &printable_pdesc, printable_names,
+ PRINTABLESTRING_SYNTAX_OID, printable_validate );
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= printable_init %d\n", rc, 0, 0 );
+ return( rc );
+}
static int
cis_filter_ava(
@@ -805,3 +823,29 @@ exit:
return( rc );
}
+static int printable_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ int i = 0;
+
+ /* Per RFC4517:
+ *
+ * PrintableString = 1*PrintableCharacter
+ */
+ if ((val != NULL) && (val->bv_len > 0)) {
+ /* Make sure all chars are a PrintableCharacter */
+ for (i=0; i < val->bv_len; i++) {
+ if (!IS_PRINTABLE(val->bv_val[i])) {
+ rc = 1;
+ goto exit;
+ }
+ }
+ } else {
+ rc = 1;
+ }
+
+exit:
+ return( rc );
+}
diff --git a/ldap/servers/plugins/syntaxes/deliverymethod.c b/ldap/servers/plugins/syntaxes/deliverymethod.c
new file mode 100644
index 00000000..0edb8ceb
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/deliverymethod.c
@@ -0,0 +1,318 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* deliverymethod.c - Delivery Method syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int delivery_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int delivery_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int delivery_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int delivery_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int delivery_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int delivery_compare(struct berval *v1, struct berval *v2);
+static int delivery_validate(struct berval *val);
+static int pdm_validate(const char *start, const char *end);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Delivery Method", "delivery", DELIVERYMETHOD_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "delivery-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Delivery Method attribute syntax plugin" };
+
+int
+delivery_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> delivery_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) delivery_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) delivery_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) delivery_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) delivery_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) delivery_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) DELIVERYMETHOD_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) delivery_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) delivery_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= delivery_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+delivery_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+delivery_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+delivery_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+delivery_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+delivery_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int delivery_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+delivery_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *start = NULL;
+ const char *end = NULL;
+ const char *p = NULL;
+
+ /* Per RFC4517:
+ *
+ * DeliveryMethod = pdm *( WSP DOLLAR WSP pdm )
+ * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
+ * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Loop through each delivery method. */
+ for (p = start; p <= end; p++) {
+ if (p == end) {
+ /* Validate start through p */
+ rc = pdm_validate(start, p);
+ goto exit;
+ } else if (IS_SPACE(*p) || IS_DOLLAR(*p)) {
+ /* Validate start through p-1. Advance
+ * pointer to next start char. */
+ if ((rc = pdm_validate(start, p - 1)) != 0) {
+ goto exit;
+ } else {
+ int got_separator = 0;
+
+ /* Advance until we find the
+ * start of the next pdm. */
+ for (p++; p <= end; p++) {
+ /* If we hit the end before encountering
+ * another pdm, fail. We can do this check
+ * without looking at what the actual char
+ * is first since no single char is a valid
+ * pdm. */
+ if (p == end) {
+ rc = 1;
+ goto exit;
+ } else if (IS_DOLLAR(*p)) {
+ /* Only allow one '$' between pdm's. */
+ if (got_separator) {
+ rc = 1;
+ goto exit;
+ } else {
+ got_separator = 1;
+ }
+ } else if (!IS_SPACE(*p)) {
+ /* Set start to point to what
+ * should be the start of the
+ * next pdm. */
+ start = p;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+exit:
+ return rc;
+}
+
+/*
+ * pdm_validate()
+ *
+ * Returns 0 if the string from start to end is a valid
+ * pdm, otherwise returns 1.
+ */
+static int
+pdm_validate(const char *start, const char *end)
+{
+ int rc = 0; /* Assume string is valid */
+ size_t length = 0;
+ const char *p = NULL;
+
+ if ((start == NULL) || (end == NULL)) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Per RFC4517:
+ *
+ * DeliveryMethod = pdm *( WSP DOLLAR WSP pdm )
+ * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
+ * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
+ */
+
+ /* Check length first for efficiency. */
+ length = end - start + 1;
+ switch (length) {
+ case 3:
+ if ((strncmp(start, "any", length) != 0) &&
+ (strncmp(start, "mhs", length) != 0) &&
+ (strncmp(start, "ia5", length) != 0)) {
+ rc = 1;
+ }
+ break;
+ case 5:
+ if ((strncmp(start, "telex", length) != 0) &&
+ (strncmp(start, "g3fax", length) != 0) &&
+ (strncmp(start, "g4fax", length) != 0)) {
+ rc = 1;
+ }
+ break;
+ case 7:
+ if (strncmp(start, "teletex", length) != 0) {
+ rc = 1;
+ }
+ break;
+ case 8:
+ if ((strncmp(start, "physical", length) != 0) &&
+ (strncmp(start, "videotex", length) != 0)) {
+ rc = 1;
+ }
+ break;
+ case 9:
+ if (strncmp(start, "telephone", length) != 0) {
+ rc = 1;
+ }
+ break;
+ default:
+ rc = 1;
+ break;
+ }
+
+exit:
+ return rc;
+}
diff --git a/ldap/servers/plugins/syntaxes/dn.c b/ldap/servers/plugins/syntaxes/dn.c
index ab6b254d..fbfb49f3 100644
--- a/ldap/servers/plugins/syntaxes/dn.c
+++ b/ldap/servers/plugins/syntaxes/dn.c
@@ -58,7 +58,6 @@ static int dn_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
static int dn_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
char *final, Slapi_Value ***ivals );
static int dn_validate( struct berval *val );
-static int rdn_validate( const char *begin, const char *end, const char **last );
/* the first name is the official one from RFC 2252 */
static char *names[] = { "DN", DN_SYNTAX_OID, 0 };
@@ -143,224 +142,13 @@ static int dn_validate( struct berval *val )
int rc = 0; /* Assume value is valid */
char *val_copy = NULL;
- if (val != NULL) {
- /* Per RFC 4514:
- *
- * distinguishedName = [ relativeDistinguishedName
- * *( COMMA relativeDistinguishedName ) ]
- * relativeDistinguishedName = attributeTypeAndValue
- * *( PLUS attributeTypeAndValue )
- * attributeTypeAndValue = attribyteType EQUALS attributeValue
- * attributeType = descr / numericoid
- * attributeValue = string / hexstring
- */
- if (val->bv_len > 0) {
- int strict = 0;
- const char *p = val->bv_val;
- const char *end = &(val->bv_val[val->bv_len - 1]);
- const char *last = NULL;
-
- /* Check if we should be performing strict validation. */
- strict = config_get_dn_validate_strict();
- if (!strict) {
- /* Create a normalized copy of the value to use
- * for validation. The original value will be
- * stored in the backend unmodified. */
- val_copy = PL_strndup(val->bv_val, val->bv_len);
- p = val_copy;
- end = slapi_dn_normalize_to_end(val_copy, NULL) - 1;
- }
-
- /* Validate one RDN at a time in a loop. */
- while (p <= end) {
- if ((rc = rdn_validate(p, end, &last)) != 0) {
- goto exit;
- }
- p = last + 1;
-
- /* p should be pointing at a comma, or one past
- * the end of the entire dn value. If we have
- * not reached the end, ensure that the next
- * character is a comma and that there is at
- * least another character after the comma. */
- if ((p <= end) && ((p == end) || (*p != ','))) {
- rc = 1;
- goto exit;
- }
-
- /* Advance the pointer past the comma so it
- * points at the beginning of the next RDN
- * (if there is one). */
- p++;
- }
- }
- } else {
- rc = 1;
- goto exit;
- }
-exit:
- if (val_copy) {
- slapi_ch_free_string(&val_copy);
- }
- return rc;
-}
-
-/*
- * Helper function for validating a DN. This function will validate
- * a single RDN. If the RDN is valid, 0 will be returned, otherwise
- * non-zero will be returned. A pointer to the last character processed
- * will be set in the "last parameter. This will be the end of the RDN
- * in the valid case, and the illegal character in the invalid case.
- */
-static int rdn_validate( const char *begin, const char *end, const char **last )
-{
- int rc = 0; /* Assume RDN is valid */
- int numericform = 0;
- char *separator = NULL;
- const char *p = begin;
-
- /* Find the '=', then use the helpers for descr and numericoid */
- if ((separator = PL_strnchr(p, '=', end - begin + 1)) == NULL) {
- rc = 1;
- goto exit;
- }
-
- /* Process an attribute type. The 'descr'
- * form must start with a 'leadkeychar'. */
- if (IS_LEADKEYCHAR(*p)) {
- if ((rc = keystring_validate(p, separator - 1))) {
- goto exit;
- }
- /* See if the 'numericoid' form is being used */
- } else if (isdigit(*p)) {
- numericform = 1;
- if ((rc = numericoid_validate(p, separator - 1))) {
- goto exit;
- }
- } else {
- rc = 1;
- goto exit;
- }
-
- /* Advance the pointer past the '=' and make sure
- * we're not past the end of the string. */
- p = separator + 1;
- if (p > end) {
+ /* A 0 length value is valid for the DN syntax. */
+ if (val == NULL) {
rc = 1;
- goto exit;
- }
-
- /* The value must be a 'hexstring' if the 'numericoid'
- * form of 'attributeType' is used. Per RFC 4514:
- *
- * hexstring = SHARP 1*hexpair
- * hexpair = HEX HEX
- */
- if (numericform) {
- if ((p == end) || !IS_SHARP(*p)) {
- rc = 1;
- goto exit;
- }
- p++;
- /* The value must be a 'string' when the 'descr' form
- * of 'attributeType' is used. Per RFC 4514:
- *
- * string = [ ( leadchar / pair ) [ *( stringchar / pair )
- * ( trailchar / pair ) ] ]
- *
- * leadchar = LUTF1 / UTFMB
- * trailchar = TUTF1 / UTFMB
- * stringchar = SUTF1 / UTFMB
- *
- * pair = ESC (ESC / special / hexpair )
- * special = escaped / SPACE / SHARP / EQUALS
- * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
- * hexpair = HEX HEX
- */
- } else {
- /* Check the leadchar to see if anything illegal
- * is there. We need to allow a 'pair' to get
- * through, so we'll assume that a '\' is the
- * start of a 'pair' for now. */
- if (IS_UTF1(*p) && !IS_ESC(*p) && !IS_LUTF1(*p)) {
- rc = 1;
- goto exit;
- }
- }
-
- /* Loop through string until we find the ',' separator, a '+'
- * char indicating a multi-value RDN, or we reach the end. */
- while ((p <= end) && (*p != ',') && (*p != '+')) {
- if (numericform) {
- /* Process a single 'hexpair' */
- if ((p == end) || !isxdigit(*p) || !isxdigit(*p + 1)) {
- rc = 1;
- goto exit;
- }
- p = p + 2;
- } else {
- /* Check for a valid 'stringchar'. We handle
- * multi-byte characters separately. */
- if (IS_UTF1(*p)) {
- /* If we're at the end, check if we have
- * a valid 'trailchar'. */
- if ((p == end) && !IS_TUTF1(*p)) {
- rc = 1;
- goto exit;
- /* Check for a 'pair'. */
- } else if (IS_ESC(*p)) {
- /* We're guaranteed to still have at
- * least one more character, so lets
- * take a look at it. */
- p++;
- if (!IS_ESC(*p) && !IS_SPECIAL(*p)) {
- /* The only thing valid now
- * is a 'hexpair'. */
- if ((p == end) || !isxdigit(*p) ||!isxdigit(*p + 1)) {
- rc = 1;
- goto exit;
- }
- p++;
- }
- p++;
- /* Only allow 'SUTF1' chars now. */
- } else if (!IS_SUTF1(*p)) {
- rc = 1;
- goto exit;
- }
-
- p++;
- } else {
- /* Validate a single 'UTFMB' (multi-byte) character. */
- if (utf8char_validate(p, end, &p ) != 0) {
- rc = 1;
- goto exit;
- }
-
- /* Advance the pointer past the multi-byte char. */
- p++;
- }
- }
+ } else if (val->bv_len > 0) {
+ rc = distinguishedname_validate(val->bv_val, &(val->bv_val[val->bv_len - 1]));
}
- /* We'll end up either at the comma, a '+', or one past end.
- * If we are processing a multi-valued RDN, we recurse to
- * process the next 'attributeTypeAndValue'. */
- if ((p <= end) && (*p == '+')) {
- /* Make sure that there is something after the '+'. */
- if (p == end) {
- rc = 1;
- goto exit;
- }
- p++;
-
- /* Recurse to process the next value. We need to reset p to
- * ensure that last is set correctly for the original caller. */
- rc = rdn_validate( p, end, last );
- p = *last + 1;
- }
-
-exit:
- *last = p - 1;
return rc;
}
+
diff --git a/ldap/servers/plugins/syntaxes/facsimile.c b/ldap/servers/plugins/syntaxes/facsimile.c
new file mode 100644
index 00000000..c37a3604
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/facsimile.c
@@ -0,0 +1,324 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* facsimile.c - Facsimile Telephone Number syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int facsimile_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int facsimile_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int facsimile_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int facsimile_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int facsimile_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int facsimile_compare(struct berval *v1, struct berval *v2);
+static int facsimile_validate(struct berval *val);
+static int fax_parameter_validate(const char *start, const char *end);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Facsimile Telephone Number", "facsimile", FACSIMILE_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "facsimile-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Facsimile Telephone Number attribute syntax plugin" };
+
+int
+facsimile_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> facsimile_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) facsimile_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) facsimile_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) facsimile_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) facsimile_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) facsimile_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) FACSIMILE_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) facsimile_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) facsimile_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= facsimile_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+facsimile_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+facsimile_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+facsimile_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+facsimile_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+facsimile_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int facsimile_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+facsimile_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ int i = 0;
+
+ /* Per RFC4517:
+ *
+ * fax-number = telephone-number *( DOLLAR fax-parameter )
+ * telephone-number = PrintableString
+ * fax-parameter = "twoDimensional" /
+ * "fineResolution" /
+ * "unlimitedLength" /
+ * "b4Length" /
+ * "a3Width" /
+ * "b4Width" /
+ * "uncompressed"
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Make sure all chars are a PrintableCharacter */
+ for (i=0; i < val->bv_len; i++) {
+ if (!IS_PRINTABLE(val->bv_val[i])) {
+ if (!IS_DOLLAR(val->bv_val[i])) {
+ rc = 1;
+ goto exit;
+ } else {
+ /* Process the fax-parameters */
+ const char *start = NULL;
+ const char *end = &(val->bv_val[val->bv_len - 1]);
+ const char *p = &(val->bv_val[i]);
+
+ /* The value must have a printable string first,
+ * so we can't allow it to start with a '$'. We
+ * also need to ensure that the string does not
+ * end with this '$'. */
+ if ((i == 0) || (p == end)) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* We're guaranteed to have at least one character
+ * past p. This is where the fax-paramter should
+ * start. */
+ start = p + 1;
+
+ for (p = start; p <= end; p++) {
+ if (p == end) {
+ /* Ensure start to p is a valid fax-parameter, then
+ * exit since we're at the end. */
+ rc = fax_parameter_validate(start, p);
+ goto exit;
+ } else if (*p == '$') {
+ /* Ensure start to p-1 is a valid fax-parameter */
+ if ((rc = fax_parameter_validate(start, p - 1)) != 0) {
+ goto exit;
+ }
+
+ /* We're guaranteed to have another character, which
+ * should be the beginning of the next fax-paramter.
+ * Adjust the start pointer to point to the beginning
+ * of this fax-paramter. */
+ start = p + 1;
+ }
+ }
+ }
+ }
+ }
+
+exit:
+ return rc;
+}
+
+/*
+ * fax_parameter_validate()
+ *
+ * Returns 0 if the string from start to end is a valid
+ * fax-parameter, otherwise returns 1.
+ */
+static int
+fax_parameter_validate(const char *start, const char *end)
+{
+ int rc = 0; /* Assume string is valid */
+ size_t length = 0;
+ const char *p = NULL;
+
+ if ((start == NULL) || (end == NULL)) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Per RFC4517:
+ *
+ * fax-parameter = "twoDimensional" /
+ * "fineResolution" /
+ * "unlimitedLength" /
+ * "b4Length" /
+ * "a3Width" /
+ * "b4Width" /
+ * "uncompressed"
+ */
+
+ /* Check length first for efficiency. */
+ length = end - start + 1;
+ switch (length) {
+ case 7:
+ if ((strncmp(start, "a3Width", length) != 0) &&
+ (strncmp(start, "b4Width", length) != 0)) {
+ rc = 1;
+ }
+ break;
+ case 8:
+ if (strncmp(start, "b4Length", length) != 0) {
+ rc = 1;
+ }
+ break;
+ case 12:
+ if (strncmp(start, "uncompressed", length) != 0) {
+ rc = 1;
+ }
+ break;
+ case 14:
+ if ((strncmp(start, "twoDimensional", length) != 0) &&
+ (strncmp(start, "fineResolution", length) != 0)) {
+ rc = 1;
+ }
+ break;
+ case 15:
+ if (strncmp(start, "unlimitedLength", length) != 0) {
+ rc = 1;
+ }
+ break;
+ default:
+ rc = 1;
+ break;
+ }
+
+exit:
+ return rc;
+}
diff --git a/ldap/servers/plugins/syntaxes/guide.c b/ldap/servers/plugins/syntaxes/guide.c
new file mode 100644
index 00000000..90dd27a4
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/guide.c
@@ -0,0 +1,734 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* guide.c - Guide and Enhanced Guide syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int guide_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int guide_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int guide_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int guide_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int guide_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int guide_compare(struct berval *v1, struct berval *v2);
+static int enhancedguide_validate(struct berval *val);
+static int guide_validate(struct berval *val);
+static int criteria_validate(const char *start, const char *end);
+static int andterm_validate(const char *start, const char *end, const char **last);
+static int term_validate(const char *start, const char *end, const char **last);
+
+/* the first name is the official one from RFC 4517 */
+static char *guide_names[] = { "Guide", "guide", GUIDE_SYNTAX_OID, 0 };
+
+static char *enhancedguide_names[] = { "Enhanced Guide", "enhancedguide",
+ ENHANCEDGUIDE_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc guide_pdesc = { "guide-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Guide attribute syntax plugin" };
+
+static Slapi_PluginDesc enhancedguide_pdesc = { "enhancedguide-syntax",
+ PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Enhanced Guide attribute syntax plugin" };
+
+int
+guide_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> guide_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&guide_pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) guide_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) guide_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) guide_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) guide_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) guide_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) guide_names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) GUIDE_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) guide_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) guide_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= guide_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+int
+enhancedguide_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> guide_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&enhancedguide_pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) guide_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) guide_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) guide_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) guide_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) guide_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) enhancedguide_names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) ENHANCEDGUIDE_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) guide_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) enhancedguide_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= guide_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+guide_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+guide_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+guide_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+guide_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+guide_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int guide_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+enhancedguide_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *start = NULL;
+ const char *end = NULL;
+ const char *p = NULL;
+ const char *sharp = NULL;
+
+ /* Per RFC4517:
+ *
+ * EnhancedGuide = object-class SHARP WSP criteria WSP
+ * SHARP WSP subset
+ * subset = "baseobject" / "oneLevel" / "wholeSubtree"
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Find the first SHARP. */
+ for (p = start; p <= end; p++) {
+ if (IS_SHARP(*p)) {
+ sharp = p;
+ break;
+ }
+ }
+
+ /* Fail if we didn't find a SHARP, or if SHARP
+ * is at the start or end of the value. */
+ if ((sharp == NULL) || (sharp == start) || (sharp == end)){
+ rc = 1;
+ goto exit;
+ }
+
+ /* Reset p and end to validate the object-class. */
+ p = start;
+ end = sharp - 1;
+
+ /* Skip any leading spaces. */
+ while ((p < sharp) && IS_SPACE(*p)) {
+ p++;
+ }
+
+ /* Skip any trailing spaces. */
+ while ((end > p) && IS_SPACE(*end)) {
+ end--;
+ }
+
+ /* See if we only found spaces before the SHARP. */
+ if (end < p) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Validate p to end as object-class. This is the same
+ * as an oid, which is either a keystring or a numericoid. */
+ if (IS_LEADKEYCHAR(*p)) {
+ rc = keystring_validate(p, end);
+ /* check if the value matches the numericoid form */
+ } else if (isdigit(*p)) {
+ rc = numericoid_validate(p, end);
+ } else {
+ rc = 1;
+ }
+
+ /* We're done if the object-class failed to validate. */
+ if (rc != 0) {
+ goto exit;
+ }
+
+ /* Reset start and end to validate the criteria. */
+ start = sharp + 1;
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Find the next SHARP. */
+ for (p = start; p <= end; p++) {
+ if (IS_SHARP(*p)) {
+ sharp = p;
+ break;
+ }
+ }
+
+ /* Fail if we didn't find a SHARP, or if SHARP
+ * is at the start or end of the value. */
+ if ((sharp == NULL) || (sharp == start) || (sharp == end)){
+ rc = 1;
+ goto exit;
+ }
+
+ /* Reset p and end to validate the criteria. */
+ p = start;
+ end = sharp - 1;
+
+ /* Skip any leading spaces. */
+ while ((p < sharp) && IS_SPACE(*p)) {
+ p++;
+ }
+
+ /* Skip any trailing spaces. */
+ while ((end > p) && IS_SPACE(*end)) {
+ end--;
+ }
+
+ /* See if we only found spaces before the SHARP. */
+ if (end < p) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Validate p to end as criteria. */
+ if ((rc = criteria_validate(p, end)) != 0) {
+ goto exit;
+ }
+
+ /* Reset start and end to validate the subset. We're
+ * guaranteed to have a character after sharp. */
+ p = start = sharp + 1;
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Skip any leading spaces. */
+ while ((p < end) && IS_SPACE(*p)) {
+ p ++;
+ }
+
+ /* Validate the subset. */
+ switch (end - p + 1) {
+ case 8:
+ if (strncmp(p, "oneLevel", 8) != 0) {
+ rc = 1;
+ }
+ break;
+ case 10:
+ if (strncmp(p, "baseobject", 10) != 0) {
+ rc = 1;
+ }
+ break;
+ case 12:
+ if (strncmp(p, "wholeSubtree", 12) != 0) {
+ rc = 1;
+ }
+ break;
+ default:
+ rc = 1;
+ }
+
+exit:
+ return rc;
+}
+
+static int
+guide_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *start = NULL;
+ const char *end = NULL;
+ const char *p = NULL;
+ const char *sharp = NULL;
+
+ /* Per RFC4517:
+ *
+ * Guide = [ object-class SHARP ] criteria
+ * object-class = WSP oid WSP
+ * criteria = and-term *( BAR and-term )
+ * and-term = term *( AMPERSAND term )
+ * term = EXCLAIM term /
+ * attributetype DOLLAR match-type /
+ * LPAREN criteria RPAREN /
+ * true /
+ * false
+ * match-type = "EQ" / "SUBSTR" / "GE" / "LE" / "APPROX"
+ * true = "?true"
+ * false = "?false"
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Look for a SHARP. If we have one, the value should
+ * begin with the optional object-class. */
+ for (p = start; p <= end; p++) {
+ if (IS_SHARP(*p)) {
+ sharp = p;
+ break;
+ }
+ }
+
+ if (sharp) {
+ /* "criteria" must exist, so the SHARP
+ * can't be at the end of the value. */
+ if (sharp == end) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* An optional object-class should be present. Reset
+ * p to the beginning of the value and end to just
+ * before the SHARP to validate the object-class.
+ * We'll reset end later. */
+ p = start;
+ end = sharp - 1;
+
+ /* This can happen if the value begins with SHARP. */
+ if (end < start) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Skip any leading spaces. */
+ while ((p < sharp) && IS_SPACE(*p)) {
+ p++;
+ }
+
+ /* Skip any trailing spaces. */
+ while ((end > p) && IS_SPACE(*end)) {
+ end--;
+ }
+
+ /* See if we only found spaces before the SHARP. */
+ if (end < p) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Validate p to end as object-class. This is the same
+ * as an oid, which is either a keystring or a numericoid. */
+ if (IS_LEADKEYCHAR(*p)) {
+ rc = keystring_validate(p, end);
+ /* check if the value matches the numericoid form */
+ } else if (isdigit(*p)) {
+ rc = numericoid_validate(p, end);
+ } else {
+ rc = 1;
+ }
+
+ /* If the object-class failed to validate, we're done. */
+ if (rc != 0) {
+ goto exit;
+ }
+
+ /* Reset p and end to point to the criteria. */
+ p = sharp + 1;
+ end = &(val->bv_val[val->bv_len - 1]);
+ } else {
+ /* Reset p. */
+ p = start;
+ }
+
+ /* Validate the criteria. */
+ rc = criteria_validate(p, end);
+
+exit:
+ return rc;
+}
+
+/* criteria_validate()
+ *
+ * Helper to validate criteria element.
+ */
+static int
+criteria_validate(const char *start, const char *end)
+{
+ const char *p = start;
+ const char *last = NULL;
+ int rc = 0;
+
+ /* Validate the criteria, which is just made up of a number
+ * of and-term elements. Validate one and-term at a time. */
+ while (p <= end) {
+ if ((rc = andterm_validate(p, end, &last)) != 0) {
+ goto exit;
+ }
+ p = last + 1;
+
+ /* p should be pointing at a BAR, or one past
+ * the end of the entire value. If we have
+ * not reached the end, ensure that the next
+ * character is a BAR and that there is at
+ * least another character after the BAR. */
+ if ((p <= end) && ((p == end) || (*p != '|'))) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Advance the pointer past the BAR so
+ * it points at the beginning of the
+ * next and-term (if there is one). */
+ p++;
+ }
+
+exit:
+ return rc;
+}
+
+/*
+ * andterm_validate()
+ *
+ * This function will validate a single and-term. If the and-term
+ * is valid, 0 will be returned, otherwise non-zero will be returned.
+ * A pointer to the last character of the and-term will be set in the
+ * "last" parameter in the valid case.
+ */
+static int
+andterm_validate(const char *start, const char *end, const char **last)
+{
+ const char *p = start;
+ int rc = 0;
+
+ if ((start == NULL) || (end == NULL)) {
+ rc = 1;
+ goto exit;
+ }
+
+ while (p <= end) {
+ if ((rc = term_validate(p, end, last)) != 0) {
+ goto exit;
+ }
+ p = *last + 1;
+
+ /* p should be pointing at an ampersand, a bar, or
+ * one past the end of the entire value. If we have
+ * not reached the end, ensure that the next
+ * character is an ampersand or a bar and that
+ * there is at least another character afterwards. */
+ if ((p <= end) && ((p == end) || ((*p != '&') && (*p != '|')))) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* If p is a bar, we're done. */
+ if (*p == '|') {
+ break;
+ }
+
+ /* Advance the pointer past the ampersand
+ * or bar so it points at the beginning of
+ * the next term or and-term (if there is
+ * one). */
+ p++;
+ }
+
+exit:
+ return rc;
+}
+
+static int
+term_validate(const char *start, const char *end, const char **last)
+{
+ int rc = 0;
+ const char *p = start;
+
+ /* Per RFC 4517:
+ *
+ * term = EXCLAIM term /
+ * attributetype DOLLAR match-type /
+ * LPAREN criteria RPAREN /
+ * true /
+ * false
+ * match-type = "EQ" / "SUBSTR" / "GE" / "LE" / "APPROX"
+ * true = "?true"
+ * false = "?false"
+ */
+
+ /* See if the term is prefixed by an EXCLAIM. */
+ if (*p == '!') {
+ p++;
+ /* Ensure the value doesn't end with an EXCLAIM. */
+ if (p > end) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+ /* Check for valid terms. */
+ switch (*p) {
+ case '?':
+ {
+ /* true or false */
+ int length = 0;
+
+ p++;
+ length = end - p + 1;
+
+ if ((length >= 5) && (strncmp(p, "false", 5) == 0)) {
+ /* Found false. We're done. */
+ *last = p + 4;
+ goto exit;
+ }
+
+ if ((length >= 4) && (strncmp(p, "true", 4) == 0)) {
+ /* Found true. We're done. */
+ *last = p + 3;
+ goto exit;
+ }
+
+ /* We didn't find true or false. Fail. */
+ rc = 1;
+ goto exit;
+ }
+ case '(':
+ {
+ /* LPAREN criteria RPAREN */
+ const char *lparen = p;
+
+ while ((p <= end) && !IS_RPAREN(*p)) {
+ p++;
+ }
+
+ if (p > end) {
+ /* We didn't find a RPAREN. Fail. */
+ rc = 1;
+ goto exit;
+ } else {
+ /* p is pointing at the RPAREN. Validate
+ * everything between the parens as criteria. */
+ rc = criteria_validate(lparen + 1, p - 1);
+ *last = p;
+ }
+ break;
+ }
+ default:
+ {
+ /* attributetype DOLLAR match-type */
+ const char *attrtype = p;
+
+ while ((p <= end) && !IS_DOLLAR(*p)) {
+ p++;
+ }
+
+ if (p > end) {
+ /* We didn't find a DOLLAR. Fail. */
+ rc = 1;
+ goto exit;
+ } else {
+ /* p is pointing at the DOLLAR. Validate
+ * the attributetype before the DOLLAR. */
+ if (IS_LEADKEYCHAR(*attrtype)) {
+ rc = keystring_validate(attrtype, p - 1);
+ /* check if the value matches the numericoid form */
+ } else if (isdigit(*attrtype)) {
+ rc = numericoid_validate(attrtype, p - 1);
+ } else {
+ rc = 1;
+ }
+
+ /* If the attributetype was invalid, we're done. */
+ if (rc != 0) {
+ goto exit;
+ }
+
+ /* Validate that a valid match-type
+ * is after the DOLLAR. */
+ if (p == end) {
+ rc = 1;
+ goto exit;
+ } else {
+ int length = 0;
+
+ p++;
+ length = end - p + 1;
+
+ if (length >= 6) {
+ /* APPROX, SUBSTR */
+ if ((strncmp(p, "APPROX", 6) == 0) ||
+ (strncmp(p, "SUBSTR", 6) == 0)) {
+ /* We found a valid match-type.
+ * We're done. */
+ *last = p + 5;
+ goto exit;
+ }
+ }
+
+ if (length >= 2) {
+ /* EQ, GE, LE */
+ if ((strncmp(p, "EQ", 2) == 0) ||
+ (strncmp(p, "GE", 2) == 0) ||
+ (strncmp(p, "LE", 2) == 0)) {
+ /* We found a valid match-type.
+ * We're done. */
+ *last = p + 1;
+ goto exit;
+ }
+ }
+
+ /* We failed to find a valid match-type. */
+ rc = 1;
+ goto exit;
+ }
+ }
+ }
+ }
+
+exit:
+ return rc;
+}
diff --git a/ldap/servers/plugins/syntaxes/nameoptuid.c b/ldap/servers/plugins/syntaxes/nameoptuid.c
new file mode 100644
index 00000000..70b760ab
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/nameoptuid.c
@@ -0,0 +1,232 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* nameoptuid.c - Name And Optional UID syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int nameoptuid_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int nameoptuid_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int nameoptuid_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int nameoptuid_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int nameoptuid_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int nameoptuid_compare(struct berval *v1, struct berval *v2);
+static int nameoptuid_validate(struct berval *val);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Name And Optional UID", "nameoptuid", NAMEANDOPTIONALUID_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "nameoptuid-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Name And Optional UID attribute syntax plugin" };
+
+int
+nameoptuid_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> nameoptuid_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) nameoptuid_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) nameoptuid_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) nameoptuid_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) nameoptuid_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) nameoptuid_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) NAMEANDOPTIONALUID_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) nameoptuid_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) nameoptuid_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= nameoptuid_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+nameoptuid_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+nameoptuid_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+nameoptuid_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+nameoptuid_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+nameoptuid_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int nameoptuid_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+nameoptuid_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ int got_sharp = 0;
+ const char *p = NULL;
+ const char *start = NULL;
+ const char *end = NULL;
+
+ /* Per RFC4517:
+ *
+ * NameAndOptionalUID = distinguishedName [ SHARP BitString ]
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Find the last SHARP in the value that may be separating
+ * the distinguishedName from the optional BitString. */
+ for (p = end; p >= start + 1; p--) {
+ if (IS_SHARP(*p)) {
+ got_sharp = 1;
+ break;
+ }
+ }
+
+ if (got_sharp) {
+ /* Try to validate everything after the sharp as
+ * a BitString. If this fails, we may still have
+ * a valid value since a sharp is allowed in a
+ * distinguishedName. If we don't find a valid
+ * BitString, just validate the entire value as
+ * a distinguishedName. */
+ if ((rc = bitstring_validate_internal(p + 1, end)) != 0) {
+ rc = distinguishedname_validate(start, end);
+ } else {
+ rc = distinguishedname_validate(start, p - 1);
+ }
+ } else {
+ /* No optional BitString is present, so validate
+ * the entire value as a distinguishedName. */
+ rc = distinguishedname_validate(start, end);
+ }
+
+exit:
+ return rc;
+}
+
diff --git a/ldap/servers/plugins/syntaxes/syntax.h b/ldap/servers/plugins/syntaxes/syntax.h
index e673718f..865fc8b7 100644
--- a/ldap/servers/plugins/syntaxes/syntax.h
+++ b/ldap/servers/plugins/syntaxes/syntax.h
@@ -74,7 +74,12 @@
#define IS_SPACE(c) ( (c == ' ') )
#define IS_LDIGIT(c) ( (c != '0') && isdigit(c) )
#define IS_SHARP(c) ( (c == '#') )
+#define IS_DOLLAR(c) ( (c == '$') )
+#define IS_SQUOTE(c) ( (c == '\'') )
#define IS_ESC(c) ( (c == '\\') )
+#define IS_LPAREN(c) ( (c == '(') )
+#define IS_RPAREN(c) ( (c == ')') )
+#define IS_COLON(c) ( (c == ':') )
#define IS_UTF0(c) ( ((unsigned char)(c) >= (unsigned char)'\x80') && ((unsigned char)(c) <= (unsigned char)'\xBF') )
#define IS_UTF1(c) ( !((unsigned char)(c) & 128) )
/* These are only checking the first byte of the multibyte character. They
@@ -102,8 +107,8 @@
* PLUS / COMMA / HYPHEN / DOT / EQUALS /
* SLASH / COLON / QUESTION / SPACE
*/
-#define IS_PRINTABLE(c) ( isalnum(c) || (c == '\'') || (c == '(') || \
- (c == ')') || (c == '+') || (c == ',') || (c == '-') || (c == '.') || \
+#define IS_PRINTABLE(c) ( isalnum(c) || (c == '\'') || IS_LPAREN(c) || \
+ IS_RPAREN(c) || (c == '+') || (c == ',') || (c == '-') || (c == '.') || \
(c == '=') || (c == '/') || (c == ':') || (c == '?') || IS_SPACE(c) )
int string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,Slapi_Value **bvals, int syntax );
@@ -123,5 +128,8 @@ int keystring_validate( const char *begin, const char *end );
int numericoid_validate( const char *begin, const char *end );
int utf8char_validate( const char *begin, const char *end, const char **last );
int utf8string_validate( const char *begin, const char *end, const char **last );
+int distinguishedname_validate( const char *begin, const char *end );
+int rdn_validate( const char *begin, const char *end, const char **last );
+int bitstring_validate_internal(const char *begin, const char *end);
#endif
diff --git a/ldap/servers/plugins/syntaxes/teletex.c b/ldap/servers/plugins/syntaxes/teletex.c
new file mode 100644
index 00000000..da9e7fe2
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/teletex.c
@@ -0,0 +1,342 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* teletex.c - Teletex Terminal Identifier syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int teletex_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int teletex_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int teletex_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int teletex_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int teletex_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int teletex_compare(struct berval *v1, struct berval *v2);
+static int teletex_validate(struct berval *val);
+static int ttx_param_validate(const char *start, const char *end);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Teletex Terminal Identifier", "teletextermid", TELETEXTERMID_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "teletextermid-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Teletex Terminal Identifier attribute syntax plugin" };
+
+int
+teletex_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> teletex_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) teletex_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) teletex_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) teletex_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) teletex_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) teletex_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) TELETEXTERMID_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) teletex_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) teletex_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= teletex_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+teletex_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+teletex_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+teletex_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+teletex_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+teletex_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int teletex_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+teletex_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *start = NULL;
+ const char *end = NULL;
+ const char *p = NULL;
+ int got_ttx_term = 0;
+
+ /* Per RFC4517:
+ *
+ * teletex-id = ttx-term *(DOLLAR ttx-param)
+ * ttx-term = PrintableString
+ * ttx-param = ttx-key COLON ttx-value
+ * tty-key = "graphic" / "control" / "misc" / "page" / "private"
+ * ttx-value = *ttx-value-octet
+ *
+ * ttx-value-octet = %x00-23
+ * / (%x5C "24") ; escaped "$"
+ * / %x25-5B
+ * / (%x5C "5C") ; escaped "\"
+ * / %x5D-FF
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Look for a DOLLAR separator. */
+ for (p = start; p <= end; p++) {
+ if (IS_DOLLAR(*p)) {
+ /* Ensure we don't have an empty element. */
+ if ((p == start) || (p == end)) {
+ rc = 1;
+ goto exit;
+ }
+
+ if (!got_ttx_term) {
+ /* Validate the ttx-term. */
+ while (start < p) {
+ if (!IS_PRINTABLE(*start)) {
+ rc = 1;
+ goto exit;
+ }
+ start++;
+ }
+
+ got_ttx_term = 1;
+ } else {
+ /* Validate the ttx-param. */
+ if ((rc = ttx_param_validate(start, p - 1)) != 0) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+ /* Reset start to point at the
+ * next ttx-param. We're
+ * guaranteed to have at least
+ * one more char after p. */
+ start = p + 1;
+ }
+ }
+
+ /* If we didn't find the ttx-term, validate
+ * the whole value as the ttx-term. */
+ if (!got_ttx_term) {
+ for (p = start; p <= end; p++) {
+ if (!IS_PRINTABLE(*p)) {
+ rc = 1;
+ goto exit;
+ }
+ }
+ } else {
+ /* Validate the final ttx-param. */
+ rc = ttx_param_validate(start, end);
+ }
+
+exit:
+ return rc;
+}
+
+static int
+ttx_param_validate(
+ const char *start,
+ const char *end)
+{
+ int rc = 0;
+ const char *p = NULL;
+ int found_colon = 0;
+
+ for (p = start; p <= end; p++) {
+ if (IS_COLON(*p)) {
+ found_colon = 1;
+
+ /* Validate the ttx-key before the COLON. */
+ switch (p - start) {
+ case 4:
+ /* "misc" / "page" */
+ if ((strncmp(start, "misc", 4) != 0) &&
+ (strncmp(start, "page", 4) != 0)) {
+ rc = 1;
+ goto exit;
+ }
+ break;
+ case 7:
+ /* "graphic" / "control" / "private" */
+ if ((strncmp(start, "graphic", 7) != 0) &&
+ (strncmp(start, "control", 7) != 0) &&
+ (strncmp(start, "private", 7) != 0)) {
+ rc = 1;
+ goto exit;
+ }
+ break;
+ default:
+ rc = 1;
+ goto exit;
+ }
+
+ /* Validate the ttx-value after the COLON.
+ * It is allowed to be 0 length. */
+ if (p != end) {
+ for (++p; p <= end; p++) {
+ /* Ensure that '\' is only used
+ * to escape a '$' or a '\'. */
+ if (*p == '\\') {
+ p++;
+ /* Ensure that we're not at the end of the value */
+ if ((p > end) || ((strncmp(p, "24", 2) != 0)
+ && (strncasecmp(p, "5C", 2) != 0))) {
+ rc = 1;
+ goto exit;
+ } else {
+ /* advance the pointer to point to the end
+ * of the hex code for the escaped character */
+ p++;
+ }
+ } else if (*p == '$') {
+ /* This should be escaped. Fail. */
+ rc = 1;
+ goto exit;
+ }
+ }
+ }
+
+ /* We're done. */
+ break;
+ }
+ }
+
+ /* If we didn't find a COLON, fail. */
+ if (!found_colon) {
+ rc = 1;
+ }
+
+exit:
+ return rc;
+}
diff --git a/ldap/servers/plugins/syntaxes/telex.c b/ldap/servers/plugins/syntaxes/telex.c
new file mode 100644
index 00000000..e51f2f73
--- /dev/null
+++ b/ldap/servers/plugins/syntaxes/telex.c
@@ -0,0 +1,257 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* telex.c - Telex Number syntax routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "syntax.h"
+
+static int telex_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
+ Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
+static int telex_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value **bvals );
+static int telex_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
+ Slapi_Value ***ivals, int ftype );
+static int telex_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
+ Slapi_Value ***ivals, int ftype );
+static int telex_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
+ char *final, Slapi_Value ***ivals );
+static int telex_compare(struct berval *v1, struct berval *v2);
+static int telex_validate(struct berval *val);
+
+/* the first name is the official one from RFC 4517 */
+static char *names[] = { "Telex Number", "telexnumber", TELEXNUMBER_SYNTAX_OID, 0 };
+
+static Slapi_PluginDesc pdesc = { "telex-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "Telex Number attribute syntax plugin" };
+
+int
+telex_init( Slapi_PBlock *pb )
+{
+ int rc, flags;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "=> telex_init\n", 0, 0, 0 );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
+ (void *) telex_filter_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
+ (void *) telex_filter_sub );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
+ (void *) telex_values2keys );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
+ (void *) telex_assertion2keys_ava );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
+ (void *) telex_assertion2keys_sub );
+ flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
+ (void *) &flags );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
+ (void *) names );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
+ (void *) TELEXNUMBER_SYNTAX_OID );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
+ (void *) telex_compare );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
+ (void *) telex_validate );
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<= telex_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+static int
+telex_filter_ava(
+ Slapi_PBlock *pb,
+ struct berval *bvfilter,
+ Slapi_Value **bvals,
+ int ftype,
+ Slapi_Value **retVal
+)
+{
+ return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS,
+ ftype, retVal ) );
+}
+
+
+static int
+telex_filter_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value **bvals
+)
+{
+ return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
+}
+
+static int
+telex_values2keys(
+ Slapi_PBlock *pb,
+ Slapi_Value **vals,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return( string_values2keys( pb, vals, ivals, SYNTAX_CIS,
+ ftype ) );
+}
+
+static int
+telex_assertion2keys_ava(
+ Slapi_PBlock *pb,
+ Slapi_Value *val,
+ Slapi_Value ***ivals,
+ int ftype
+)
+{
+ return(string_assertion2keys_ava( pb, val, ivals,
+ SYNTAX_CIS, ftype ));
+}
+
+static int
+telex_assertion2keys_sub(
+ Slapi_PBlock *pb,
+ char *initial,
+ char **any,
+ char *final,
+ Slapi_Value ***ivals
+)
+{
+ return( string_assertion2keys_sub( pb, initial, any, final, ivals,
+ SYNTAX_CIS ) );
+}
+
+static int telex_compare(
+ struct berval *v1,
+ struct berval *v2
+)
+{
+ return value_cmp(v1, v2, SYNTAX_CIS, 3 /* Normalise both values */);
+}
+
+static int
+telex_validate(
+ struct berval *val
+)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *start = NULL;
+ const char *end = NULL;
+ const char *p = NULL;
+ const char *p2 = NULL;
+ int num_dollars = 0;
+
+ /* Per RFC4517:
+ *
+ * telex-number = actual-number DOLLAR country-code
+ * DOLLAR answerback
+ * actual-number = PrintableString
+ * country-code = PrintableString
+ * answerback = PrintableString
+ */
+
+ /* Don't allow a 0 length string */
+ if ((val == NULL) || (val->bv_len == 0)) {
+ rc = 1;
+ goto exit;
+ }
+
+ start = &(val->bv_val[0]);
+ end = &(val->bv_val[val->bv_len - 1]);
+
+ /* Look for the DOLLAR separators. */
+ for (p = start; p <= end; p++) {
+ if (IS_DOLLAR(*p)) {
+ num_dollars++;
+
+ /* Ensure we don't have an empty element. */
+ if ((p == start) || (p == end)) {
+ rc = 1;
+ goto exit;
+ }
+
+ for (p2 = start; p2 < p; p2++) {
+ if (!IS_PRINTABLE(*p2)) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+ /* Reset start to the beginning
+ * of the next element. We're
+ * guaranteed to have another
+ * char after p. */
+ start = p + 1;
+
+ if (num_dollars == 2) {
+ /* Validate the answerback element
+ * and exit. */
+ for (p2 = start; p2 <= end; p2++) {
+ if (!IS_PRINTABLE(*p2)) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+ /* We've hit the end and it's
+ * all valid. We're done. */
+ goto exit;
+ }
+ }
+ }
+
+ /* Make sure we found all three elements. */
+ if (num_dollars != 2) {
+ rc = 1;
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
diff --git a/ldap/servers/plugins/syntaxes/validate.c b/ldap/servers/plugins/syntaxes/validate.c
index a34830cd..d0da4be0 100644
--- a/ldap/servers/plugins/syntaxes/validate.c
+++ b/ldap/servers/plugins/syntaxes/validate.c
@@ -350,3 +350,262 @@ exit:
return(rc);
}
+/*
+ * Validates a distinguishedName as degined in RFC 4514. Returns
+ * 0 if the value from begin to end is a valid distinguishedName.
+ * Returns 1 otherwise.
+ */
+int distinguishedname_validate(
+ const char *begin,
+ const char *end
+)
+{
+ int rc = 0; /* Assume value is valid */
+ char *val_copy = NULL;
+ int strict = 0;
+ const char *p = begin;
+ const char *last = NULL;
+
+ /* Per RFC 4514:
+ *
+ * distinguishedName = [ relativeDistinguishedName
+ * *( COMMA relativeDistinguishedName ) ]
+ * relativeDistinguishedName = attributeTypeAndValue
+ * *( PLUS attributeTypeAndValue )
+ * attributeTypeAndValue = attribyteType EQUALS attributeValue
+ * attributeType = descr / numericoid
+ * attributeValue = string / hexstring
+ */
+
+ /* Check if we should be performing strict validation. */
+ strict = config_get_dn_validate_strict();
+ if (!strict) {
+ /* Create a normalized copy of the value to use
+ * for validation. The original value will be
+ * stored in the backend unmodified. */
+ val_copy = PL_strndup(begin, end - begin + 1);
+ p = val_copy;
+ end = slapi_dn_normalize_to_end(val_copy, NULL) - 1;
+ }
+
+ /* Validate one RDN at a time in a loop. */
+ while (p <= end) {
+ if ((rc = rdn_validate(p, end, &last)) != 0) {
+ goto exit;
+ }
+ p = last + 1;
+
+ /* p should be pointing at a comma, or one past
+ * the end of the entire dn value. If we have
+ * not reached the end, ensure that the next
+ * character is a comma and that there is at
+ * least another character after the comma. */
+ if ((p <= end) && ((p == end) || (*p != ','))) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Advance the pointer past the comma so it
+ * points at the beginning of the next RDN
+ * (if there is one). */
+ p++;
+ }
+
+exit:
+ if (val_copy) {
+ slapi_ch_free_string(&val_copy);
+ }
+ return rc;
+}
+
+/*
+ * Helper function for validating a DN. This function will validate
+ * a single RDN. If the RDN is valid, 0 will be returned, otherwise
+ * non-zero will be returned. A pointer to the last character processed
+ * will be set in the "last parameter. This will be the end of the RDN
+ * in the valid case, and the illegal character in the invalid case.
+ */
+int rdn_validate( const char *begin, const char *end, const char **last )
+{
+ int rc = 0; /* Assume RDN is valid */
+ int numericform = 0;
+ char *separator = NULL;
+ const char *p = begin;
+
+ /* Find the '=', then use the helpers for descr and numericoid */
+ if ((separator = PL_strnchr(p, '=', end - begin + 1)) == NULL) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Process an attribute type. The 'descr'
+ * form must start with a 'leadkeychar'. */
+ if (IS_LEADKEYCHAR(*p)) {
+ if ((rc = keystring_validate(p, separator - 1))) {
+ goto exit;
+ }
+ /* See if the 'numericoid' form is being used */
+ } else if (isdigit(*p)) {
+ numericform = 1;
+ if ((rc = numericoid_validate(p, separator - 1))) {
+ goto exit;
+ }
+ } else {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Advance the pointer past the '=' and make sure
+ * we're not past the end of the string. */
+ p = separator + 1;
+ if (p > end) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* The value must be a 'hexstring' if the 'numericoid'
+ * form of 'attributeType' is used. Per RFC 4514:
+ *
+ * hexstring = SHARP 1*hexpair
+ * hexpair = HEX HEX
+ */
+ if (numericform) {
+ if ((p == end) || !IS_SHARP(*p)) {
+ rc = 1;
+ goto exit;
+ }
+ p++;
+ /* The value must be a 'string' when the 'descr' form
+ * of 'attributeType' is used. Per RFC 4514:
+ *
+ * string = [ ( leadchar / pair ) [ *( stringchar / pair )
+ * ( trailchar / pair ) ] ]
+ *
+ * leadchar = LUTF1 / UTFMB
+ * trailchar = TUTF1 / UTFMB
+ * stringchar = SUTF1 / UTFMB
+ *
+ * pair = ESC (ESC / special / hexpair )
+ * special = escaped / SPACE / SHARP / EQUALS
+ * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
+ * hexpair = HEX HEX
+ */
+ } else {
+ /* Check the leadchar to see if anything illegal
+ * is there. We need to allow a 'pair' to get
+ * through, so we'll assume that a '\' is the
+ * start of a 'pair' for now. */
+ if (IS_UTF1(*p) && !IS_ESC(*p) && !IS_LUTF1(*p)) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+ /* Loop through string until we find the ',' separator, a '+'
+ * char indicating a multi-value RDN, or we reach the end. */
+ while ((p <= end) && (*p != ',') && (*p != '+')) {
+ if (numericform) {
+ /* Process a single 'hexpair' */
+ if ((p == end) || !isxdigit(*p) || !isxdigit(*p + 1)) {
+ rc = 1;
+ goto exit;
+ }
+ p = p + 2;
+ } else {
+ /* Check for a valid 'stringchar'. We handle
+ * multi-byte characters separately. */
+ if (IS_UTF1(*p)) {
+ /* If we're at the end, check if we have
+ * a valid 'trailchar'. */
+ if ((p == end) && !IS_TUTF1(*p)) {
+ rc = 1;
+ goto exit;
+ /* Check for a 'pair'. */
+ } else if (IS_ESC(*p)) {
+ /* We're guaranteed to still have at
+ * least one more character, so lets
+ * take a look at it. */
+ p++;
+ if (!IS_ESC(*p) && !IS_SPECIAL(*p)) {
+ /* The only thing valid now
+ * is a 'hexpair'. */
+ if ((p == end) || !isxdigit(*p) ||!isxdigit(*p + 1)) {
+ rc = 1;
+ goto exit;
+ }
+ p++;
+ }
+ p++;
+ /* Only allow 'SUTF1' chars now. */
+ } else if (!IS_SUTF1(*p)) {
+ rc = 1;
+ goto exit;
+ }
+
+ p++;
+ } else {
+ /* Validate a single 'UTFMB' (multi-byte) character. */
+ if (utf8char_validate(p, end, &p ) != 0) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Advance the pointer past the multi-byte char. */
+ p++;
+ }
+ }
+ }
+
+ /* We'll end up either at the comma, a '+', or one past end.
+ * If we are processing a multi-valued RDN, we recurse to
+ * process the next 'attributeTypeAndValue'. */
+ if ((p <= end) && (*p == '+')) {
+ /* Make sure that there is something after the '+'. */
+ if (p == end) {
+ rc = 1;
+ goto exit;
+ }
+ p++;
+
+ /* Recurse to process the next value. We need to reset p to
+ * ensure that last is set correctly for the original caller. */
+ rc = rdn_validate( p, end, last );
+ p = *last + 1;
+ }
+
+exit:
+ *last = p - 1;
+ return rc;
+}
+
+int
+bitstring_validate_internal(const char *begin, const char *end)
+{
+ int rc = 0; /* assume the value is valid */
+ const char *p = NULL;
+
+ /* Per RFC4517:
+ *
+ * BitString = SQUOTE *binary-digit SQUOTE "B"
+ * binary-digit = "0" / "1"
+ */
+
+ /* Check that the value starts with a SQUOTE and
+ * ends with SQUOTE "B". */
+ if (!IS_SQUOTE(*begin) || (*end != 'B') ||
+ !IS_SQUOTE(*(end - 1))) {
+ rc = 1;
+ goto exit;
+ }
+
+ /* Ensure that only '0' and '1' are between the SQUOTE chars. */
+ for (p = begin + 1; p <= end - 2; p++) {
+ if ((*p != '0') && (*p != '1')) {
+ rc = 1;
+ goto exit;
+ }
+ }
+
+exit:
+ return rc;
+}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 696d8103..b4eb0c03 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -507,19 +507,29 @@ 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 BITSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.6"
#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 DELIVERYMETHOD_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.14"
#define DIRSTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.15"
+#define ENHANCEDGUIDE_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.21"
+#define FACSIMILE_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.22"
+#define FAX_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.23"
#define GENERALIZEDTIME_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.24"
+#define GUIDE_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.25"
#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 NAMEANDOPTIONALUID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.34"
#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 POSTALADDRESS_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.41"
+#define PRINTABLESTRING_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.44"
#define TELEPHONE_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.50"
+#define TELETEXTERMID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.51"
+#define TELEXNUMBER_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.52"
#define SPACE_INSENSITIVE_STRING_SYNTAX_OID "2.16.840.1.113730.3.7.1"
/* OIDs for some commonly used matching rules */