diff --git a/Makefile.am b/Makefile.am index dd7965f..65977d9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -277,7 +277,6 @@ perl_DATA = ldap/admin/src/scripts/SetupLog.pm \ ldap/admin/src/scripts/DialogManager.pm \ ldap/admin/src/scripts/Dialog.pm \ ldap/admin/src/scripts/DSDialogs.pm \ - ldap/admin/src/scripts/Setup.pm \ ldap/admin/src/scripts/Migration.pm \ ldap/admin/src/scripts/DSMigration.pm \ ldap/admin/src/scripts/FileConn.pm \ @@ -942,16 +941,23 @@ libstatechange_plugin_la_LDFLAGS = -avoid-version # libsyntax-plugin #------------------------ libsyntax_plugin_la_SOURCES = ldap/servers/plugins/syntaxes/bin.c \ + ldap/servers/plugins/syntaxes/bitstring.c \ ldap/servers/plugins/syntaxes/ces.c \ ldap/servers/plugins/syntaxes/cis.c \ ldap/servers/plugins/syntaxes/debug.c \ ldap/servers/plugins/syntaxes/dn.c \ + ldap/servers/plugins/syntaxes/deliverymethod.c \ + ldap/servers/plugins/syntaxes/facsimile.c \ + ldap/servers/plugins/syntaxes/guide.c \ ldap/servers/plugins/syntaxes/int.c \ + ldap/servers/plugins/syntaxes/nameoptuid.c \ ldap/servers/plugins/syntaxes/numericstring.c \ ldap/servers/plugins/syntaxes/phonetic.c \ ldap/servers/plugins/syntaxes/sicis.c \ ldap/servers/plugins/syntaxes/string.c \ ldap/servers/plugins/syntaxes/tel.c \ + ldap/servers/plugins/syntaxes/telex.c \ + ldap/servers/plugins/syntaxes/teletex.c \ ldap/servers/plugins/syntaxes/validate.c \ ldap/servers/plugins/syntaxes/validate_task.c \ ldap/servers/plugins/syntaxes/value.c diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in index 2694f0f..d0e2927 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 2d0b6f8..be42358 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 @@ -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 0000000..91f8884 --- /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 +#endif + +/* bitstring.c - Bit String syntax routines */ + +#include +#include +#include +#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 4f1d9d7..2af300b 100644 --- a/ldap/servers/plugins/syntaxes/cis.c +++ b/ldap/servers/plugins/syntaxes/cis.c @@ -51,7 +51,7 @@ * GeneralizedTime * OID * PostalAddress - * + * PrintableString */ #include @@ -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 0000000..0edb8ce --- /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 +#endif + +/* deliverymethod.c - Delivery Method syntax routines */ + +#include +#include +#include +#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 ab6b254..fbfb49f 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 0000000..c37a360 --- /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 +#endif + +/* facsimile.c - Facsimile Telephone Number syntax routines */ + +#include +#include +#include +#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 0000000..90dd27a --- /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 +#endif + +/* guide.c - Guide and Enhanced Guide syntax routines */ + +#include +#include +#include +#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 0000000..70b760a --- /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 +#endif + +/* nameoptuid.c - Name And Optional UID syntax routines */ + +#include +#include +#include +#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 e673718..865fc8b 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 0000000..da9e7fe --- /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 +#endif + +/* teletex.c - Teletex Terminal Identifier syntax routines */ + +#include +#include +#include +#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 0000000..e51f2f7 --- /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 +#endif + +/* telex.c - Telex Number syntax routines */ + +#include +#include +#include +#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 a34830c..d0da4be 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 696d810..b4eb0c0 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 */