depend on these parameters and recreating them with
.BR slapindex (8).
+.HP
+.hy 0
+.B ldapsyntax "(\ <oid>\
+ [DESC\ <description>]\
+ [X-SUBST <substitute\-syntax>]\ )"
+.RS
+Specify an LDAP syntax using the LDAPv3 syntax defined in RFC 4512.
+The slapd parser extends the RFC 4512 definition by allowing string
+forms as well as numeric OIDs to be used for the syntax OID.
+(See the
+.B objectidentifier
+description.)
+The slapd parser also honors the
+.B X-SUBST
+extension (an OpenLDAP-specific extension), which allows to use the
+.B ldapsyntax
+statement to define a non-implemented syntax along with another syntax,
+the extension value
+.IR substitute\-syntax ,
+as its temporary replacement.
+The
+.I substitute\-syntax
+must be defined.
+This allows to define attribute types that make use of non-implemented syntaxes
+using the correct syntax OID.
+Unless
+.B X-SUBST
+is used, this configuration statement would result in an error,
+since no handlers would be associated to the resulting syntax structure.
+.RE
+
.TP
.B localSSF <SSF>
Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
ContentRule *c_cr_head, *c_cr_tail;
ObjectClass *c_oc_head, *c_oc_tail;
OidMacro *c_om_head, *c_om_tail;
+ Syntax *c_syn_head, *c_syn_tail;
BerVarray c_dseFiles;
} ConfigFile;
/* Private state */
static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
- *cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om;
+ *cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om, *cfAd_syntax;
static ConfigFile *cfn;
extern AttributeType *at_sys_tail; /* at.c */
extern ObjectClass *oc_sys_tail; /* oc.c */
extern OidMacro *om_sys_tail; /* oidm.c */
+extern Syntax *syn_sys_tail; /* syntax.c */
static AttributeType *cf_at_tail;
static ObjectClass *cf_oc_tail;
static OidMacro *cf_om_tail;
+static Syntax *cf_syn_tail;
static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
SlapReply *rs, int *renumber, Operation *op );
CFG_SERVERID,
CFG_SORTVALS,
CFG_IX_INTLEN,
+ CFG_SYNTAX,
CFG_LAST
};
{ "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
&config_generic, "( OLcfgDbAt:0.4 NAME 'olcLastMod' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { "ldapsyntax", "syntax", 2, 0, 0,
+ ARG_PAREN|ARG_MAGIC|CFG_SYNTAX,
+ &config_generic, "( OLcfgGlAt:85 NAME 'olcLdapSyntaxes' "
+ "DESC 'OpenLDAP ldapSyntax' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
+ NULL, NULL },
{ "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
&config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
"EQUALITY caseIgnoreMatch "
"olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
"olcTLSCRLFile $ olcToolThreads $ "
"olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
- "olcDitContentRules ) )", Cft_Global },
+ "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
{ "( OLcfgGlOc:2 "
"NAME 'olcSchemaConfig' "
"DESC 'OpenLDAP schema object' "
"SUP olcConfig STRUCTURAL "
"MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ "
- "olcObjectClasses $ olcDitContentRules ) )",
+ "olcObjectClasses $ olcDitContentRules $ olcLdapSyntaxes ) )",
Cft_Schema, NULL, cfAddSchema },
{ "( OLcfgGlOc:3 "
"NAME 'olcBackendConfig' "
rc = 1;
}
break;
+ case CFG_SYNTAX: {
+ ConfigFile *cf = c->ca_private;
+ if ( !cf )
+ syn_unparse( &c->rvalue_vals, NULL, NULL, 1 );
+ else if ( cf->c_syn_head )
+ syn_unparse( &c->rvalue_vals, cf->c_syn_head,
+ cf->c_syn_tail, 0 );
+ if ( !c->rvalue_vals )
+ rc = 1;
+ }
+ break;
case CFG_DIT: {
ConfigFile *cf = c->ca_private;
if ( !cf )
}
}
break;
+
+ case CFG_SYNTAX: {
+ CfEntryInfo *ce;
+ /* Can be NULL when undoing a failed add */
+ if ( c->ca_entry ) {
+ ce = c->ca_entry->e_private;
+ /* can't modify the hardcoded schema */
+ if ( ce->ce_parent->ce_type == Cft_Global )
+ return 1;
+ }
+ }
+ cfn = c->ca_private;
+ if ( c->valx < 0 ) {
+ Syntax *syn;
+
+ for( syn = cfn->c_syn_head; syn; syn_next( &syn )) {
+ syn_delete( syn );
+ if ( syn == cfn->c_syn_tail )
+ break;
+ }
+ cfn->c_syn_head = cfn->c_syn_tail = NULL;
+ } else {
+ Syntax *syn, *prev = NULL;
+
+ for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++) {
+ prev = syn;
+ syn_next( &syn );
+ }
+ syn_delete( syn );
+ if ( cfn->c_syn_tail == syn ) {
+ cfn->c_syn_tail = prev;
+ }
+ if ( cfn->c_syn_head == syn ) {
+ syn_next( &syn );
+ cfn->c_syn_head = syn;
+ }
+ }
+ break;
case CFG_SORTVALS:
if ( c->valx < 0 ) {
ADlist *sv;
}
break;
+ case CFG_SYNTAX: {
+ Syntax *syn, *prev;
+
+ if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+ cfn = c->ca_private;
+ if ( c->valx < 0 ) {
+ prev = cfn->c_syn_tail;
+ } else {
+ prev = NULL;
+ /* If adding anything after the first, prev is easy */
+ if ( c->valx ) {
+ int i;
+ for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++ ) {
+ prev = syn;
+ syn_next( &syn );
+ }
+ } else
+ /* If adding the first, and head exists, find its prev */
+ if (cfn->c_syn_head) {
+ for ( syn_start( &syn ); syn != cfn->c_syn_head; ) {
+ prev = syn;
+ syn_next( &syn );
+ }
+ }
+ /* else prev is NULL, append to end of global list */
+ }
+ if ( parse_syn( c, &syn, prev ) ) return(1);
+ if ( !cfn->c_syn_head ) cfn->c_syn_head = syn;
+ if ( cfn->c_syn_tail == prev ) cfn->c_syn_tail = syn;
+ }
+ break;
+
case CFG_DIT: {
ContentRule *cr;
ct = config_find_table( colst, nocs, ad, ca );
config_del_vals( ct, ca );
}
+ if ( cfn->c_syn_head ) {
+ struct berval bv = BER_BVC("olcLdapSyntaxes");
+ ad = NULL;
+ slap_bv2ad( &bv, &ad, &text );
+ ct = config_find_table( colst, nocs, ad, ca );
+ config_del_vals( ct, ca );
+ }
if ( cfn->c_om_head ) {
struct berval bv = BER_BVC("olcObjectIdentifier");
ad = NULL;
for (; cf; cf=cf->c_sibs, c->depth++) {
if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head &&
- !cf->c_om_head ) continue;
+ !cf->c_om_head && !cf->c_syn_head ) continue;
c->value_dn.bv_val = c->log;
LUTIL_SLASHPATH( cf->c_file.bv_val );
bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]);
ber_bvarray_free( bv );
cf_oc_tail = oc_sys_tail;
}
+ if ( cf_syn_tail != syn_sys_tail ) {
+ a = attr_find( e->e_attrs, cfAd_syntax );
+ if ( a ) {
+ if ( a->a_nvals != a->a_vals )
+ ber_bvarray_free( a->a_nvals );
+ ber_bvarray_free( a->a_vals );
+ a->a_vals = NULL;
+ a->a_nvals = NULL;
+ a->a_numvals = 0;
+ }
+ syn_unparse( &bv, NULL, NULL, 1 );
+ attr_merge_normalize( e, cfAd_syntax, bv, NULL );
+ ber_bvarray_free( bv );
+ cf_syn_tail = syn_sys_tail;
+ }
} else {
SlapReply rs = {REP_RESULT};
c.ca_private = NULL;
cf_at_tail = at_sys_tail;
cf_oc_tail = oc_sys_tail;
cf_om_tail = om_sys_tail;
+ cf_syn_tail = syn_sys_tail;
}
return 0;
}
cf_at_tail = at_sys_tail;
cf_oc_tail = oc_sys_tail;
cf_om_tail = om_sys_tail;
+ cf_syn_tail = syn_sys_tail;
/* Create schema nodes for included schema... */
if ( cfb->cb_config->c_kids ) {
{ "backend", &cfAd_backend },
{ "database", &cfAd_database },
{ "include", &cfAd_include },
+ { "ldapsyntax", &cfAd_syntax },
{ "objectclass", &cfAd_oc },
{ "objectidentifier", &cfAd_om },
{ "overlay", &cfAd_overlay },
LDAP_SLAPD_F (char *) scherr2str LDAP_P((int code)) LDAP_GCCATTR((const));
LDAP_SLAPD_F (int) dscompare LDAP_P(( const char *s1, const char *s2del,
char delim ));
+LDAP_SLAPD_F (int) parse_syn LDAP_P((
+ struct config_args_s *ca, Syntax **sat, Syntax *prev ));
/*
* sessionlog.c
const char *syndesc, int *slen ));
LDAP_SLAPD_F (int) syn_add LDAP_P((
LDAPSyntax *syn,
+ int user,
slap_syntax_defs_rec *def,
+ Syntax **ssyn,
+ Syntax *prev,
const char **err ));
LDAP_SLAPD_F (void) syn_destroy LDAP_P(( void ));
LDAP_SLAPD_F (int) syn_schema_info( Entry *e );
+LDAP_SLAPD_F (int) syn_start LDAP_P(( Syntax **at ));
+LDAP_SLAPD_F (int) syn_next LDAP_P(( Syntax **at ));
+LDAP_SLAPD_F (void) syn_delete LDAP_P(( Syntax *at ));
+
+LDAP_SLAPD_F (void) syn_unparse LDAP_P((
+ BerVarray *bva, Syntax *start, Syntax *end, int system ));
+
/*
* user.c
*/
return code;
}
+
+static void
+syn_usage( void )
+{
+ fprintf( stderr, "%s",
+ "SyntaxDescription = \"(\" whsp\n"
+ " numericoid whsp ; object identifier\n"
+ " [ whsp \"DESC\" whsp qdstring ] ; description\n"
+ " extensions whsp \")\" ; extensions\n"
+ " whsp \")\"\n");
+}
+
+int
+parse_syn(
+ struct config_args_s *c,
+ Syntax **ssyn,
+ Syntax *prev )
+{
+ LDAPSyntax *syn;
+ slap_syntax_defs_rec def = { 0 };
+ int code;
+ const char *err;
+ char *line = strchr( c->line, '(' );
+
+ syn = ldap_str2syntax( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
+ if ( !syn ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
+ c->argv[0], ldap_scherr2str(code), err );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s %s\n", c->log, c->cr_msg, 0 );
+ syn_usage();
+ return 1;
+ }
+
+ if ( syn->syn_oid == NULL ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
+ c->argv[0] );
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s %s\n", c->log, c->cr_msg, 0 );
+ syn_usage();
+ code = 1;
+ goto done;
+ }
+
+ code = syn_add( syn, 1, &def, ssyn, prev, &err );
+ if ( code ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
+ c->argv[0], scherr2str(code), err);
+ Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+ "%s %s\n", c->log, c->cr_msg, 0 );
+ code = 1;
+ goto done;
+ }
+
+done:;
+ if ( code ) {
+ ldap_syntax_free( syn );
+
+ } else {
+ ldap_memfree( syn );
+ }
+
+ return code;
+}
+
#else
#define SLAP_SYNTAX_HIDE 0x8000U /* hide (do not publish) */
#endif
+#define SLAP_SYNTAX_HARDCODE 0x10000U /* This is hardcoded schema */
Syntax **ssyn_sups;
struct ComponentDesc* ssync_comp_syntax;
#endif
- LDAP_SLIST_ENTRY(Syntax) ssyn_next;
+ LDAP_STAILQ_ENTRY(Syntax) ssyn_next;
};
#define slap_syntax_is_flag(s,flag) ((int)((s)->ssyn_flags & (flag)) ? 1 : 0)
};
static Avlnode *syn_index = NULL;
-static LDAP_SLIST_HEAD(SyntaxList, Syntax) syn_list
- = LDAP_SLIST_HEAD_INITIALIZER(&syn_list);
+static LDAP_STAILQ_HEAD(SyntaxList, Syntax) syn_list
+ = LDAP_STAILQ_HEAD_INITIALIZER(syn_list);
+
+/* Last hardcoded attribute registered */
+Syntax *syn_sys_tail;
static int
syn_index_cmp(
{
Syntax *synp;
- LDAP_SLIST_FOREACH(synp, &syn_list, ssyn_next) {
+ LDAP_STAILQ_FOREACH(synp, &syn_list, ssyn_next) {
if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{' /*'}'*/ ))) {
return synp;
}
Syntax *s;
avl_free( syn_index, ldap_memfree );
- while( !LDAP_SLIST_EMPTY( &syn_list ) ) {
- s = LDAP_SLIST_FIRST( &syn_list );
- LDAP_SLIST_REMOVE_HEAD( &syn_list, ssyn_next );
+ while( !LDAP_STAILQ_EMPTY( &syn_list ) ) {
+ s = LDAP_STAILQ_FIRST( &syn_list );
+ LDAP_STAILQ_REMOVE_HEAD( &syn_list, ssyn_next );
if ( s->ssyn_sups ) {
SLAP_FREE( s->ssyn_sups );
}
static int
syn_insert(
- Syntax *ssyn,
- const char **err
-)
+ Syntax *ssyn,
+ Syntax *prev,
+ const char **err )
{
struct sindexrec *sir;
- LDAP_SLIST_NEXT( ssyn, ssyn_next ) = NULL;
- LDAP_SLIST_INSERT_HEAD( &syn_list, ssyn, ssyn_next );
+ LDAP_STAILQ_NEXT( ssyn, ssyn_next ) = NULL;
if ( ssyn->ssyn_oid ) {
sir = (struct sindexrec *)
/* FIX: temporal consistency check */
syn_find(sir->sir_name);
}
+
+ if ( ssyn->ssyn_flags & SLAP_AT_HARDCODE ) {
+ prev = syn_sys_tail;
+ syn_sys_tail = ssyn;
+ }
+
+ if ( prev ) {
+ LDAP_STAILQ_INSERT_AFTER( &syn_list, prev, ssyn, ssyn_next );
+ } else {
+ LDAP_STAILQ_INSERT_TAIL( &syn_list, ssyn, ssyn_next );
+ }
return 0;
}
int
syn_add(
- LDAPSyntax *syn,
- slap_syntax_defs_rec *def,
- const char **err
-)
+ LDAPSyntax *syn,
+ int user,
+ slap_syntax_defs_rec *def,
+ Syntax **ssynp,
+ Syntax *prev,
+ const char **err )
{
Syntax *ssyn;
int code = 0;
+ if ( ssynp != NULL ) {
+ *ssynp = NULL;
+ }
+
ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) );
if ( ssyn == NULL ) {
Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
- LDAP_SLIST_NEXT(ssyn,ssyn_next) = NULL;
+ LDAP_STAILQ_NEXT(ssyn,ssyn_next) = NULL;
/*
* note: ssyn_bvoid uses the same memory of ssyn_syn.syn_oid;
}
}
- if ( code == 0 ) {
- code = syn_insert( ssyn, err );
+ if ( !user )
+ ssyn->ssyn_flags |= SLAP_SYNTAX_HARDCODE;
+ if ( code == 0 ) {
+ code = syn_insert( ssyn, prev, err );
}
if ( code != 0 && ssyn != NULL ) {
SLAP_FREE( ssyn->ssyn_sups );
}
SLAP_FREE( ssyn );
+ ssyn = NULL;
+ }
+
+ if (ssynp ) {
+ *ssynp = ssyn;
}
return code;
return( -1 );
}
- code = syn_add( syn, def, &err );
+ code = syn_add( syn, 0, def, NULL, NULL, &err );
if ( code ) {
Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
struct berval val;
struct berval nval;
- LDAP_SLIST_FOREACH(syn, &syn_list, ssyn_next ) {
+ LDAP_STAILQ_FOREACH(syn, &syn_list, ssyn_next ) {
if ( ! syn->ssyn_validate ) {
/* skip syntaxes without validators */
continue;
return 0;
}
+void
+syn_delete( Syntax *syn )
+{
+ LDAP_STAILQ_REMOVE(&syn_list, syn, Syntax, ssyn_next);
+}
+
+int
+syn_start( Syntax **syn )
+{
+ assert( syn != NULL );
+
+ *syn = LDAP_STAILQ_FIRST(&syn_list);
+
+ return (*syn != NULL);
+}
+
+int
+syn_next( Syntax **syn )
+{
+ assert( syn != NULL );
+
+#if 0 /* pedantic check: don't use this */
+ {
+ Syntax *tmp = NULL;
+
+ LDAP_STAILQ_FOREACH(tmp,&syn_list,ssyn_next) {
+ if ( tmp == *syn ) {
+ break;
+ }
+ }
+
+ assert( tmp != NULL );
+ }
+#endif
+
+ *syn = LDAP_STAILQ_NEXT(*syn,ssyn_next);
+
+ return (*syn != NULL);
+}
+
+void
+syn_unparse( BerVarray *res, Syntax *start, Syntax *end, int sys )
+{
+ Syntax *syn;
+ int i, num;
+ struct berval bv, *bva = NULL, idx;
+ char ibuf[32];
+
+ if ( !start )
+ start = LDAP_STAILQ_FIRST( &syn_list );
+
+ /* count the result size */
+ i = 0;
+ for ( syn = start; syn; syn = LDAP_STAILQ_NEXT( syn, ssyn_next ) ) {
+ if ( sys && !( syn->ssyn_flags & SLAP_SYNTAX_HARDCODE ) ) break;
+ i++;
+ if ( syn == end ) break;
+ }
+ if ( !i ) return;
+
+ num = i;
+ bva = ch_malloc( (num+1) * sizeof(struct berval) );
+ BER_BVZERO( bva );
+ idx.bv_val = ibuf;
+ if ( sys ) {
+ idx.bv_len = 0;
+ ibuf[0] = '\0';
+ }
+ i = 0;
+ for ( syn = start; syn; syn = LDAP_STAILQ_NEXT( syn, ssyn_next ) ) {
+ if ( sys && !( syn->ssyn_flags & SLAP_SYNTAX_HARDCODE ) ) break;
+ if ( ldap_syntax2bv( &syn->ssyn_syn, &bv ) == NULL ) {
+ ber_bvarray_free( bva );
+ }
+ if ( !sys ) {
+ idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
+ }
+ bva[i].bv_len = idx.bv_len + bv.bv_len;
+ bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
+ strcpy( bva[i].bv_val, ibuf );
+ strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
+ i++;
+ bva[i].bv_val = NULL;
+ ldap_memfree( bv.bv_val );
+ if ( syn == end ) break;
+ }
+ *res = bva;
+}
+