1
/* $OpenLDAP: pkg/ldap/libraries/libldap/schema.c,v 1.77.2.4 2008/04/14 22:32:48 quanah Exp $ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
* Copyright 1998-2008 The OpenLDAP Foundation.
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
11
* A copy of this license is available in the file LICENSE in the
12
* top-level directory of the distribution or, alternatively, at
13
* <http://www.OpenLDAP.org/license.html>.
17
* schema.c: parsing routines used by servers and clients to process
24
#include <ac/stdlib.h>
26
#include <ac/string.h>
31
#include <ldap_schema.h>
33
static const char EndOfInput[] = "end of input";
36
choose_name( char *names[], const char *fallback )
38
return (names != NULL && names[0] != NULL) ? names[0] : fallback;
42
ldap_syntax2name( LDAPSyntax * syn )
44
return( syn->syn_oid );
48
ldap_matchingrule2name( LDAPMatchingRule * mr )
50
return( choose_name( mr->mr_names, mr->mr_oid ) );
54
ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
56
return( choose_name( mru->mru_names, mru->mru_oid ) );
60
ldap_attributetype2name( LDAPAttributeType * at )
62
return( choose_name( at->at_names, at->at_oid ) );
66
ldap_objectclass2name( LDAPObjectClass * oc )
68
return( choose_name( oc->oc_names, oc->oc_oid ) );
72
ldap_contentrule2name( LDAPContentRule * cr )
74
return( choose_name( cr->cr_names, cr->cr_oid ) );
78
ldap_nameform2name( LDAPNameForm * nf )
80
return( choose_name( nf->nf_names, nf->nf_oid ) );
84
ldap_structurerule2name( LDAPStructureRule * sr )
86
return( choose_name( sr->sr_names, NULL ) );
90
* When pretty printing the entities we will be appending to a buffer.
91
* Since checking for overflow, realloc'ing and checking if no error
92
* is extremely boring, we will use a protection layer that will let
93
* us blissfully ignore the error until the end. This layer is
94
* implemented with the help of the next type.
97
typedef struct safe_string {
105
new_safe_string(int size)
109
ss = LDAP_MALLOC(sizeof(safe_string));
113
ss->val = LDAP_MALLOC(size);
127
safe_string_free(safe_string * ss)
137
safe_string_val(safe_string * ss)
139
ss->val[ss->pos] = '\0';
145
safe_strdup(safe_string * ss)
147
char *ret = LDAP_MALLOC(ss->pos+1);
150
AC_MEMCPY(ret, ss->val, ss->pos);
156
append_to_safe_string(safe_string * ss, char * s)
162
* Some runaway process is trying to append to a string that
163
* overflowed and we could not extend.
168
/* We always make sure there is at least one position available */
169
if ( ss->pos + l >= ss->size-1 ) {
171
if ( ss->pos + l >= ss->size-1 ) {
172
ss->size = ss->pos + l + 1;
175
temp = LDAP_REALLOC(ss->val, ss->size);
177
/* Trouble, out of memory */
183
strncpy(&ss->val[ss->pos], s, l);
185
if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
194
print_literal(safe_string *ss, char *s)
196
return(append_to_safe_string(ss,s));
200
print_whsp(safe_string *ss)
203
return(append_to_safe_string(ss,""));
205
return(append_to_safe_string(ss," "));
209
print_numericoid(safe_string *ss, char *s)
212
return(append_to_safe_string(ss,s));
214
return(append_to_safe_string(ss,""));
217
/* This one is identical to print_qdescr */
219
print_qdstring(safe_string *ss, char *s)
222
print_literal(ss,"'");
223
append_to_safe_string(ss,s);
224
print_literal(ss,"'");
225
return(print_whsp(ss));
229
print_qdescr(safe_string *ss, char *s)
232
print_literal(ss,"'");
233
append_to_safe_string(ss,s);
234
print_literal(ss,"'");
235
return(print_whsp(ss));
239
print_qdescrlist(safe_string *ss, char **sa)
244
for (sp=sa; *sp; sp++) {
245
ret = print_qdescr(ss,*sp);
247
/* If the list was empty, we return zero that is potentially
248
* incorrect, but since we will be still appending things, the
249
* overflow will be detected later. Maybe FIX.
255
print_qdescrs(safe_string *ss, char **sa)
257
/* The only way to represent an empty list is as a qdescrlist
258
* so, if the list is empty we treat it as a long list.
259
* Really, this is what the syntax mandates. We should not
260
* be here if the list was empty, but if it happens, a label
261
* has already been output and we cannot undo it.
263
if ( !sa[0] || ( sa[0] && sa[1] ) ) {
265
print_literal(ss,"("/*)*/);
266
print_qdescrlist(ss,sa);
267
print_literal(ss,/*(*/")");
268
return(print_whsp(ss));
270
return(print_qdescr(ss,*sa));
275
print_woid(safe_string *ss, char *s)
278
append_to_safe_string(ss,s);
279
return print_whsp(ss);
283
print_oidlist(safe_string *ss, char **sa)
287
for (sp=sa; *(sp+1); sp++) {
289
print_literal(ss,"$");
291
return(print_woid(ss,*sp));
295
print_oids(safe_string *ss, char **sa)
297
if ( sa[0] && sa[1] ) {
298
print_literal(ss,"("/*)*/);
299
print_oidlist(ss,sa);
301
return(print_literal(ss,/*(*/")"));
303
return(print_woid(ss,*sa));
308
print_noidlen(safe_string *ss, char *s, int l)
313
ret = print_numericoid(ss,s);
315
snprintf(buf, sizeof buf, "{%d}",l);
316
ret = print_literal(ss,buf);
322
print_ruleid(safe_string *ss, int rid)
325
snprintf(buf, sizeof buf, "%d", rid);
326
return print_literal(ss,buf);
330
print_ruleids(safe_string *ss, int n, int *rids)
335
print_ruleid(ss,rids[0]);
336
return print_whsp(ss);
338
print_literal(ss,"("/*)*/);
339
for( i=0; i<n; i++ ) {
341
print_ruleid(ss,rids[i]);
344
return print_literal(ss,/*(*/")");
350
print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
352
LDAPSchemaExtensionItem **ext;
356
for ( ext = extensions; *ext != NULL; ext++ ) {
357
print_literal(ss, (*ext)->lsei_name);
359
/* Should be print_qdstrings */
360
print_qdescrs(ss, (*ext)->lsei_values);
369
ldap_syntax2str( LDAPSyntax * syn )
372
if (ldap_syntax2bv( syn, &bv ))
379
ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
383
ss = new_safe_string(256);
387
print_literal(ss,"("/*)*/);
390
print_numericoid(ss, syn->syn_oid);
393
if ( syn->syn_desc ) {
394
print_literal(ss,"DESC");
395
print_qdstring(ss,syn->syn_desc);
400
print_extensions(ss, syn->syn_extensions);
402
print_literal(ss,/*(*/ ")");
404
bv->bv_val = safe_strdup(ss);
405
bv->bv_len = ss->pos;
406
safe_string_free(ss);
411
ldap_matchingrule2str( LDAPMatchingRule * mr )
414
if (ldap_matchingrule2bv( mr, &bv ))
421
ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
425
ss = new_safe_string(256);
429
print_literal(ss,"(" /*)*/);
432
print_numericoid(ss, mr->mr_oid);
435
if ( mr->mr_names ) {
436
print_literal(ss,"NAME");
437
print_qdescrs(ss,mr->mr_names);
441
print_literal(ss,"DESC");
442
print_qdstring(ss,mr->mr_desc);
445
if ( mr->mr_obsolete ) {
446
print_literal(ss, "OBSOLETE");
450
if ( mr->mr_syntax_oid ) {
451
print_literal(ss,"SYNTAX");
453
print_literal(ss, mr->mr_syntax_oid);
459
print_extensions(ss, mr->mr_extensions);
461
print_literal(ss,/*(*/")");
463
bv->bv_val = safe_strdup(ss);
464
bv->bv_len = ss->pos;
465
safe_string_free(ss);
470
ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
473
if (ldap_matchingruleuse2bv( mru, &bv ))
480
ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
484
ss = new_safe_string(256);
488
print_literal(ss,"(" /*)*/);
491
print_numericoid(ss, mru->mru_oid);
494
if ( mru->mru_names ) {
495
print_literal(ss,"NAME");
496
print_qdescrs(ss,mru->mru_names);
499
if ( mru->mru_desc ) {
500
print_literal(ss,"DESC");
501
print_qdstring(ss,mru->mru_desc);
504
if ( mru->mru_obsolete ) {
505
print_literal(ss, "OBSOLETE");
509
if ( mru->mru_applies_oids ) {
510
print_literal(ss,"APPLIES");
512
print_oids(ss, mru->mru_applies_oids);
518
print_extensions(ss, mru->mru_extensions);
520
print_literal(ss,/*(*/")");
522
bv->bv_val = safe_strdup(ss);
523
bv->bv_len = ss->pos;
524
safe_string_free(ss);
529
ldap_objectclass2str( LDAPObjectClass * oc )
532
if (ldap_objectclass2bv( oc, &bv ))
539
ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
543
ss = new_safe_string(256);
547
print_literal(ss,"("/*)*/);
550
print_numericoid(ss, oc->oc_oid);
553
if ( oc->oc_names ) {
554
print_literal(ss,"NAME");
555
print_qdescrs(ss,oc->oc_names);
559
print_literal(ss,"DESC");
560
print_qdstring(ss,oc->oc_desc);
563
if ( oc->oc_obsolete ) {
564
print_literal(ss, "OBSOLETE");
568
if ( oc->oc_sup_oids ) {
569
print_literal(ss,"SUP");
571
print_oids(ss,oc->oc_sup_oids);
575
switch (oc->oc_kind) {
576
case LDAP_SCHEMA_ABSTRACT:
577
print_literal(ss,"ABSTRACT");
579
case LDAP_SCHEMA_STRUCTURAL:
580
print_literal(ss,"STRUCTURAL");
582
case LDAP_SCHEMA_AUXILIARY:
583
print_literal(ss,"AUXILIARY");
586
print_literal(ss,"KIND-UNKNOWN");
591
if ( oc->oc_at_oids_must ) {
592
print_literal(ss,"MUST");
594
print_oids(ss,oc->oc_at_oids_must);
598
if ( oc->oc_at_oids_may ) {
599
print_literal(ss,"MAY");
601
print_oids(ss,oc->oc_at_oids_may);
607
print_extensions(ss, oc->oc_extensions);
609
print_literal(ss, /*(*/")");
611
bv->bv_val = safe_strdup(ss);
612
bv->bv_len = ss->pos;
613
safe_string_free(ss);
618
ldap_contentrule2str( LDAPContentRule * cr )
621
if (ldap_contentrule2bv( cr, &bv ))
628
ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
632
ss = new_safe_string(256);
636
print_literal(ss,"("/*)*/);
639
print_numericoid(ss, cr->cr_oid);
642
if ( cr->cr_names ) {
643
print_literal(ss,"NAME");
644
print_qdescrs(ss,cr->cr_names);
648
print_literal(ss,"DESC");
649
print_qdstring(ss,cr->cr_desc);
652
if ( cr->cr_obsolete ) {
653
print_literal(ss, "OBSOLETE");
657
if ( cr->cr_oc_oids_aux ) {
658
print_literal(ss,"AUX");
660
print_oids(ss,cr->cr_oc_oids_aux);
664
if ( cr->cr_at_oids_must ) {
665
print_literal(ss,"MUST");
667
print_oids(ss,cr->cr_at_oids_must);
671
if ( cr->cr_at_oids_may ) {
672
print_literal(ss,"MAY");
674
print_oids(ss,cr->cr_at_oids_may);
678
if ( cr->cr_at_oids_not ) {
679
print_literal(ss,"NOT");
681
print_oids(ss,cr->cr_at_oids_not);
686
print_extensions(ss, cr->cr_extensions);
688
print_literal(ss, /*(*/")");
690
bv->bv_val = safe_strdup(ss);
691
bv->bv_len = ss->pos;
692
safe_string_free(ss);
697
ldap_structurerule2str( LDAPStructureRule * sr )
700
if (ldap_structurerule2bv( sr, &bv ))
707
ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
711
ss = new_safe_string(256);
715
print_literal(ss,"("/*)*/);
718
print_ruleid(ss, sr->sr_ruleid);
721
if ( sr->sr_names ) {
722
print_literal(ss,"NAME");
723
print_qdescrs(ss,sr->sr_names);
727
print_literal(ss,"DESC");
728
print_qdstring(ss,sr->sr_desc);
731
if ( sr->sr_obsolete ) {
732
print_literal(ss, "OBSOLETE");
736
print_literal(ss,"FORM");
738
print_woid(ss,sr->sr_nameform);
741
if ( sr->sr_nsup_ruleids ) {
742
print_literal(ss,"SUP");
744
print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
749
print_extensions(ss, sr->sr_extensions);
751
print_literal(ss, /*(*/")");
753
bv->bv_val = safe_strdup(ss);
754
bv->bv_len = ss->pos;
755
safe_string_free(ss);
761
ldap_nameform2str( LDAPNameForm * nf )
764
if (ldap_nameform2bv( nf, &bv ))
771
ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
775
ss = new_safe_string(256);
779
print_literal(ss,"("/*)*/);
782
print_numericoid(ss, nf->nf_oid);
785
if ( nf->nf_names ) {
786
print_literal(ss,"NAME");
787
print_qdescrs(ss,nf->nf_names);
791
print_literal(ss,"DESC");
792
print_qdstring(ss,nf->nf_desc);
795
if ( nf->nf_obsolete ) {
796
print_literal(ss, "OBSOLETE");
800
print_literal(ss,"OC");
802
print_woid(ss,nf->nf_objectclass);
805
print_literal(ss,"MUST");
807
print_oids(ss,nf->nf_at_oids_must);
811
if ( nf->nf_at_oids_may ) {
812
print_literal(ss,"MAY");
814
print_oids(ss,nf->nf_at_oids_may);
819
print_extensions(ss, nf->nf_extensions);
821
print_literal(ss, /*(*/")");
823
bv->bv_val = safe_strdup(ss);
824
bv->bv_len = ss->pos;
825
safe_string_free(ss);
830
ldap_attributetype2str( LDAPAttributeType * at )
833
if (ldap_attributetype2bv( at, &bv ))
840
ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
844
ss = new_safe_string(256);
848
print_literal(ss,"("/*)*/);
851
print_numericoid(ss, at->at_oid);
854
if ( at->at_names ) {
855
print_literal(ss,"NAME");
856
print_qdescrs(ss,at->at_names);
860
print_literal(ss,"DESC");
861
print_qdstring(ss,at->at_desc);
864
if ( at->at_obsolete ) {
865
print_literal(ss, "OBSOLETE");
869
if ( at->at_sup_oid ) {
870
print_literal(ss,"SUP");
871
print_woid(ss,at->at_sup_oid);
874
if ( at->at_equality_oid ) {
875
print_literal(ss,"EQUALITY");
876
print_woid(ss,at->at_equality_oid);
879
if ( at->at_ordering_oid ) {
880
print_literal(ss,"ORDERING");
881
print_woid(ss,at->at_ordering_oid);
884
if ( at->at_substr_oid ) {
885
print_literal(ss,"SUBSTR");
886
print_woid(ss,at->at_substr_oid);
889
if ( at->at_syntax_oid ) {
890
print_literal(ss,"SYNTAX");
892
print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
896
if ( at->at_single_value == LDAP_SCHEMA_YES ) {
897
print_literal(ss,"SINGLE-VALUE");
901
if ( at->at_collective == LDAP_SCHEMA_YES ) {
902
print_literal(ss,"COLLECTIVE");
906
if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
907
print_literal(ss,"NO-USER-MODIFICATION");
911
if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
912
print_literal(ss,"USAGE");
914
switch (at->at_usage) {
915
case LDAP_SCHEMA_DIRECTORY_OPERATION:
916
print_literal(ss,"directoryOperation");
918
case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
919
print_literal(ss,"distributedOperation");
921
case LDAP_SCHEMA_DSA_OPERATION:
922
print_literal(ss,"dSAOperation");
925
print_literal(ss,"UNKNOWN");
932
print_extensions(ss, at->at_extensions);
934
print_literal(ss,/*(*/")");
936
bv->bv_val = safe_strdup(ss);
937
bv->bv_len = ss->pos;
938
safe_string_free(ss);
943
* Now come the parsers. There is one parser for each entity type:
944
* objectclasses, attributetypes, etc.
946
* Each of them is written as a recursive-descent parser, except that
947
* none of them is really recursive. But the idea is kept: there
948
* is one routine per non-terminal that eithers gobbles lexical tokens
949
* or calls lower-level routines, etc.
951
* The scanner is implemented in the routine get_token. Actually,
952
* get_token is more than a scanner and will return tokens that are
953
* in fact non-terminals in the grammar. So you can see the whole
954
* approach as the combination of a low-level bottom-up recognizer
955
* combined with a scanner and a number of top-down parsers. Or just
956
* consider that the real grammars recognized by the parsers are not
957
* those of the standards. As a matter of fact, our parsers are more
958
* liberal than the spec when there is no ambiguity.
960
* The difference is pretty academic (modulo bugs or incorrect
961
* interpretation of the specs).
974
TK_QDESCR = TK_QDSTRING
978
get_token( const char ** sp, char ** token_val )
996
kind = TK_RIGHTPAREN;
1007
while ( **sp != '\'' && **sp != '\0' )
1009
if ( **sp == '\'' ) {
1011
res = LDAP_MALLOC(q-p+1);
1021
kind = TK_NOENDQUOTE;
1027
while ( !LDAP_SPACE(**sp) &&
1032
/* for suggested minimum upper bound on the number
1033
* of characters (RFC 4517) */
1038
res = LDAP_MALLOC(q-p+1);
1047
/* kind = TK_UNEXPCHAR; */
1054
/* Gobble optional whitespace */
1056
parse_whsp(const char **sp)
1058
while (LDAP_SPACE(**sp))
1063
* General note for all parsers: to guarantee the algorithm halts they
1064
* must always advance the pointer even when an error is found. For
1065
* this one is not that important since an error here is fatal at the
1066
* upper layers, but it is a simple strategy that will not get in
1070
/* Parse a sequence of dot-separated decimal strings */
1072
ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1075
const char * start = *sp;
1079
/* Netscape puts the SYNTAX value in quotes (incorrectly) */
1080
if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1085
/* Each iteration of this loop gets one decimal string */
1087
if ( !LDAP_DIGIT(**sp) ) {
1089
* Initial char is not a digit or char after dot is
1092
*code = LDAP_SCHERR_NODIGIT;
1096
while ( LDAP_DIGIT(**sp) )
1100
/* Otherwise, gobble the dot and loop again */
1103
/* Now *sp points at the char past the numericoid. Perfect. */
1105
if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1106
if ( **sp == '\'' ) {
1109
*code = LDAP_SCHERR_UNEXPTOKEN;
1113
if (flags & LDAP_SCHEMA_SKIP) {
1114
res = (char *)start;
1116
res = LDAP_MALLOC(len+1);
1118
*code = LDAP_SCHERR_OUTOFMEM;
1121
strncpy(res,start,len);
1127
/* Parse a sequence of dot-separated decimal strings */
1129
ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1133
if ( !LDAP_DIGIT(**sp) ) {
1134
*code = LDAP_SCHERR_NODIGIT;
1137
*ruleid = (**sp) - '0';
1140
while ( LDAP_DIGIT(**sp) ) {
1142
*ruleid += (**sp) - '0';
1149
/* Parse a qdescr or a list of them enclosed in () */
1151
parse_qdescrs(const char **sp, int *code)
1161
kind = get_token(sp,&sval);
1162
if ( kind == TK_LEFTPAREN ) {
1163
/* Let's presume there will be at least 2 entries */
1165
res = LDAP_CALLOC(3,sizeof(char *));
1167
*code = LDAP_SCHERR_OUTOFMEM;
1173
kind = get_token(sp,&sval);
1174
if ( kind == TK_RIGHTPAREN )
1176
if ( kind == TK_QDESCR ) {
1177
if ( pos == size-2 ) {
1179
res1 = LDAP_REALLOC(res,size*sizeof(char *));
1183
*code = LDAP_SCHERR_OUTOFMEM;
1194
*code = LDAP_SCHERR_UNEXPTOKEN;
1200
} else if ( kind == TK_QDESCR ) {
1201
res = LDAP_CALLOC(2,sizeof(char *));
1203
*code = LDAP_SCHERR_OUTOFMEM;
1212
*code = LDAP_SCHERR_BADNAME;
1219
parse_woid(const char **sp, int *code)
1225
kind = get_token(sp, &sval);
1226
if ( kind != TK_BAREWORD ) {
1228
*code = LDAP_SCHERR_UNEXPTOKEN;
1235
/* Parse a noidlen */
1237
parse_noidlen(const char **sp, int *code, int *len, int flags)
1240
const char *savepos;
1242
int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED );
1243
int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO );
1246
/* Netscape puts the SYNTAX value in quotes (incorrectly) */
1247
if ( allow_quoted && **sp == '\'' ) {
1252
sval = ldap_int_parse_numericoid(sp, code, 0);
1256
&& *code == LDAP_SCHERR_NODIGIT )
1258
if ( get_token(sp, &sval) != TK_BAREWORD ) {
1259
if ( sval != NULL ) {
1268
if ( **sp == '{' /*}*/ ) {
1271
while ( LDAP_DIGIT(**sp) )
1273
if ( **sp != /*{*/ '}' ) {
1274
*code = LDAP_SCHERR_UNEXPTOKEN;
1280
if ( allow_quoted && quoted ) {
1281
if ( **sp == '\'' ) {
1284
*code = LDAP_SCHERR_UNEXPTOKEN;
1293
* Next routine will accept a qdstring in place of an oid if
1294
* allow_quoted is set. This is necessary to interoperate with
1295
* Netscape Directory server that will improperly quote each oid (at
1296
* least those of the descr kind) in the SUP clause.
1299
/* Parse a woid or a $-separated list of them enclosed in () */
1301
parse_oids(const char **sp, int *code, const int allow_quoted)
1311
* Strictly speaking, doing this here accepts whsp before the
1312
* ( at the begining of an oidlist, but this is harmless. Also,
1313
* we are very liberal in what we accept as an OID. Maybe
1317
kind = get_token(sp,&sval);
1318
if ( kind == TK_LEFTPAREN ) {
1319
/* Let's presume there will be at least 2 entries */
1321
res = LDAP_CALLOC(3,sizeof(char *));
1323
*code = LDAP_SCHERR_OUTOFMEM;
1328
kind = get_token(sp,&sval);
1329
if ( kind == TK_BAREWORD ||
1330
( allow_quoted && kind == TK_QDSTRING ) ) {
1333
} else if ( kind == TK_RIGHTPAREN ) {
1334
/* FIXME: be liberal in what we accept... */
1339
*code = LDAP_SCHERR_UNEXPTOKEN;
1346
kind = get_token(sp,&sval);
1347
if ( kind == TK_RIGHTPAREN )
1349
if ( kind == TK_DOLLAR ) {
1351
kind = get_token(sp,&sval);
1352
if ( kind == TK_BAREWORD ||
1354
kind == TK_QDSTRING ) ) {
1355
if ( pos == size-2 ) {
1357
res1 = LDAP_REALLOC(res,size*sizeof(char *));
1361
*code = LDAP_SCHERR_OUTOFMEM;
1369
*code = LDAP_SCHERR_UNEXPTOKEN;
1376
*code = LDAP_SCHERR_UNEXPTOKEN;
1384
} else if ( kind == TK_BAREWORD ||
1385
( allow_quoted && kind == TK_QDSTRING ) ) {
1386
res = LDAP_CALLOC(2,sizeof(char *));
1389
*code = LDAP_SCHERR_OUTOFMEM;
1398
*code = LDAP_SCHERR_BADNAME;
1404
add_extension(LDAPSchemaExtensionItem ***extensions,
1405
char * name, char ** values)
1408
LDAPSchemaExtensionItem **tmp, *ext;
1410
ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1413
ext->lsei_name = name;
1414
ext->lsei_values = values;
1416
if ( !*extensions ) {
1418
LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1419
if ( !*extensions ) {
1425
for ( n=0; (*extensions)[n] != NULL; n++ )
1427
tmp = LDAP_REALLOC(*extensions,
1428
(n+2)*sizeof(LDAPSchemaExtensionItem *));
1435
(*extensions)[n] = ext;
1436
(*extensions)[n+1] = NULL;
1441
free_extensions(LDAPSchemaExtensionItem **extensions)
1443
LDAPSchemaExtensionItem **ext;
1446
for ( ext = extensions; *ext != NULL; ext++ ) {
1447
LDAP_FREE((*ext)->lsei_name);
1448
LDAP_VFREE((*ext)->lsei_values);
1451
LDAP_FREE(extensions);
1456
ldap_syntax_free( LDAPSyntax * syn )
1458
LDAP_FREE(syn->syn_oid);
1459
if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1460
if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1461
free_extensions(syn->syn_extensions);
1466
ldap_str2syntax( LDAP_CONST char * s,
1468
LDAP_CONST char ** errp,
1469
LDAP_CONST unsigned flags )
1472
const char * ss = s;
1480
*code = LDAP_SCHERR_EMPTY;
1486
syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1489
*code = LDAP_SCHERR_OUTOFMEM;
1493
kind = get_token(&ss,&sval);
1494
if ( kind != TK_LEFTPAREN ) {
1496
*code = LDAP_SCHERR_NOLEFTPAREN;
1497
ldap_syntax_free(syn);
1502
syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1503
if ( !syn->syn_oid ) {
1505
ldap_syntax_free(syn);
1511
* Beyond this point we will be liberal and accept the items
1515
kind = get_token(&ss,&sval);
1518
*code = LDAP_SCHERR_NORIGHTPAREN;
1520
ldap_syntax_free(syn);
1525
if ( !strcasecmp(sval,"NAME") ) {
1528
*code = LDAP_SCHERR_DUPOPT;
1530
ldap_syntax_free(syn);
1534
syn->syn_names = parse_qdescrs(&ss,code);
1535
if ( !syn->syn_names ) {
1536
if ( *code != LDAP_SCHERR_OUTOFMEM )
1537
*code = LDAP_SCHERR_BADNAME;
1539
ldap_syntax_free(syn);
1542
} else if ( !strcasecmp(sval,"DESC") ) {
1545
*code = LDAP_SCHERR_DUPOPT;
1547
ldap_syntax_free(syn);
1552
kind = get_token(&ss,&sval);
1553
if ( kind != TK_QDSTRING ) {
1554
*code = LDAP_SCHERR_UNEXPTOKEN;
1557
ldap_syntax_free(syn);
1560
syn->syn_desc = sval;
1562
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1563
/* Should be parse_qdstrings */
1564
ext_vals = parse_qdescrs(&ss, code);
1567
ldap_syntax_free(syn);
1570
if ( add_extension(&syn->syn_extensions,
1572
*code = LDAP_SCHERR_OUTOFMEM;
1575
ldap_syntax_free(syn);
1579
*code = LDAP_SCHERR_UNEXPTOKEN;
1582
ldap_syntax_free(syn);
1587
*code = LDAP_SCHERR_UNEXPTOKEN;
1590
ldap_syntax_free(syn);
1597
ldap_matchingrule_free( LDAPMatchingRule * mr )
1599
LDAP_FREE(mr->mr_oid);
1600
if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1601
if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1602
if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1603
free_extensions(mr->mr_extensions);
1608
ldap_str2matchingrule( LDAP_CONST char * s,
1610
LDAP_CONST char ** errp,
1611
LDAP_CONST unsigned flags )
1614
const char * ss = s;
1618
int seen_obsolete = 0;
1619
int seen_syntax = 0;
1620
LDAPMatchingRule * mr;
1622
const char * savepos;
1625
*code = LDAP_SCHERR_EMPTY;
1631
mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1634
*code = LDAP_SCHERR_OUTOFMEM;
1638
kind = get_token(&ss,&sval);
1639
if ( kind != TK_LEFTPAREN ) {
1640
*code = LDAP_SCHERR_NOLEFTPAREN;
1642
ldap_matchingrule_free(mr);
1648
mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1649
if ( !mr->mr_oid ) {
1650
if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1653
kind = get_token(&ss,&sval);
1654
if ( kind == TK_BAREWORD ) {
1655
if ( !strcasecmp(sval, "NAME") ||
1656
!strcasecmp(sval, "DESC") ||
1657
!strcasecmp(sval, "OBSOLETE") ||
1658
!strcasecmp(sval, "SYNTAX") ||
1659
!strncasecmp(sval, "X-", 2) ) {
1660
/* Missing OID, backtrack */
1663
/* Non-numerical OID, ignore */
1669
ldap_matchingrule_free(mr);
1676
* Beyond this point we will be liberal and accept the items
1680
kind = get_token(&ss,&sval);
1683
*code = LDAP_SCHERR_NORIGHTPAREN;
1685
ldap_matchingrule_free(mr);
1688
if( !seen_syntax ) {
1689
*code = LDAP_SCHERR_MISSING;
1690
ldap_matchingrule_free(mr);
1695
if ( !strcasecmp(sval,"NAME") ) {
1698
*code = LDAP_SCHERR_DUPOPT;
1700
ldap_matchingrule_free(mr);
1704
mr->mr_names = parse_qdescrs(&ss,code);
1705
if ( !mr->mr_names ) {
1706
if ( *code != LDAP_SCHERR_OUTOFMEM )
1707
*code = LDAP_SCHERR_BADNAME;
1709
ldap_matchingrule_free(mr);
1712
} else if ( !strcasecmp(sval,"DESC") ) {
1715
*code = LDAP_SCHERR_DUPOPT;
1717
ldap_matchingrule_free(mr);
1722
kind = get_token(&ss,&sval);
1723
if ( kind != TK_QDSTRING ) {
1724
*code = LDAP_SCHERR_UNEXPTOKEN;
1727
ldap_matchingrule_free(mr);
1732
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
1734
if ( seen_obsolete ) {
1735
*code = LDAP_SCHERR_DUPOPT;
1737
ldap_matchingrule_free(mr);
1741
mr->mr_obsolete = LDAP_SCHEMA_YES;
1743
} else if ( !strcasecmp(sval,"SYNTAX") ) {
1745
if ( seen_syntax ) {
1746
*code = LDAP_SCHERR_DUPOPT;
1748
ldap_matchingrule_free(mr);
1754
ldap_int_parse_numericoid(&ss,code,flags);
1755
if ( !mr->mr_syntax_oid ) {
1757
ldap_matchingrule_free(mr);
1761
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1762
/* Should be parse_qdstrings */
1763
ext_vals = parse_qdescrs(&ss, code);
1766
ldap_matchingrule_free(mr);
1769
if ( add_extension(&mr->mr_extensions,
1771
*code = LDAP_SCHERR_OUTOFMEM;
1774
ldap_matchingrule_free(mr);
1778
*code = LDAP_SCHERR_UNEXPTOKEN;
1781
ldap_matchingrule_free(mr);
1786
*code = LDAP_SCHERR_UNEXPTOKEN;
1789
ldap_matchingrule_free(mr);
1796
ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1798
LDAP_FREE(mru->mru_oid);
1799
if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1800
if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1801
if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1802
free_extensions(mru->mru_extensions);
1806
LDAPMatchingRuleUse *
1807
ldap_str2matchingruleuse( LDAP_CONST char * s,
1809
LDAP_CONST char ** errp,
1810
LDAP_CONST unsigned flags )
1813
const char * ss = s;
1817
int seen_obsolete = 0;
1818
int seen_applies = 0;
1819
LDAPMatchingRuleUse * mru;
1821
const char * savepos;
1824
*code = LDAP_SCHERR_EMPTY;
1830
mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1833
*code = LDAP_SCHERR_OUTOFMEM;
1837
kind = get_token(&ss,&sval);
1838
if ( kind != TK_LEFTPAREN ) {
1839
*code = LDAP_SCHERR_NOLEFTPAREN;
1841
ldap_matchingruleuse_free(mru);
1847
mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1848
if ( !mru->mru_oid ) {
1849
if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1852
kind = get_token(&ss,&sval);
1853
if ( kind == TK_BAREWORD ) {
1854
if ( !strcasecmp(sval, "NAME") ||
1855
!strcasecmp(sval, "DESC") ||
1856
!strcasecmp(sval, "OBSOLETE") ||
1857
!strcasecmp(sval, "APPLIES") ||
1858
!strncasecmp(sval, "X-", 2) ) {
1859
/* Missing OID, backtrack */
1862
/* Non-numerical OID, ignore */
1868
ldap_matchingruleuse_free(mru);
1875
* Beyond this point we will be liberal and accept the items
1879
kind = get_token(&ss,&sval);
1882
*code = LDAP_SCHERR_NORIGHTPAREN;
1884
ldap_matchingruleuse_free(mru);
1887
if( !seen_applies ) {
1888
*code = LDAP_SCHERR_MISSING;
1889
ldap_matchingruleuse_free(mru);
1894
if ( !strcasecmp(sval,"NAME") ) {
1897
*code = LDAP_SCHERR_DUPOPT;
1899
ldap_matchingruleuse_free(mru);
1903
mru->mru_names = parse_qdescrs(&ss,code);
1904
if ( !mru->mru_names ) {
1905
if ( *code != LDAP_SCHERR_OUTOFMEM )
1906
*code = LDAP_SCHERR_BADNAME;
1908
ldap_matchingruleuse_free(mru);
1911
} else if ( !strcasecmp(sval,"DESC") ) {
1914
*code = LDAP_SCHERR_DUPOPT;
1916
ldap_matchingruleuse_free(mru);
1921
kind = get_token(&ss,&sval);
1922
if ( kind != TK_QDSTRING ) {
1923
*code = LDAP_SCHERR_UNEXPTOKEN;
1926
ldap_matchingruleuse_free(mru);
1929
mru->mru_desc = sval;
1931
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
1933
if ( seen_obsolete ) {
1934
*code = LDAP_SCHERR_DUPOPT;
1936
ldap_matchingruleuse_free(mru);
1940
mru->mru_obsolete = LDAP_SCHEMA_YES;
1942
} else if ( !strcasecmp(sval,"APPLIES") ) {
1944
if ( seen_applies ) {
1945
*code = LDAP_SCHERR_DUPOPT;
1947
ldap_matchingruleuse_free(mru);
1951
mru->mru_applies_oids = parse_oids(&ss,
1954
if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1956
ldap_matchingruleuse_free(mru);
1959
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1960
/* Should be parse_qdstrings */
1961
ext_vals = parse_qdescrs(&ss, code);
1964
ldap_matchingruleuse_free(mru);
1967
if ( add_extension(&mru->mru_extensions,
1969
*code = LDAP_SCHERR_OUTOFMEM;
1972
ldap_matchingruleuse_free(mru);
1976
*code = LDAP_SCHERR_UNEXPTOKEN;
1979
ldap_matchingruleuse_free(mru);
1984
*code = LDAP_SCHERR_UNEXPTOKEN;
1987
ldap_matchingruleuse_free(mru);
1994
ldap_attributetype_free(LDAPAttributeType * at)
1996
LDAP_FREE(at->at_oid);
1997
if (at->at_names) LDAP_VFREE(at->at_names);
1998
if (at->at_desc) LDAP_FREE(at->at_desc);
1999
if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
2000
if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
2001
if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
2002
if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
2003
if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
2004
free_extensions(at->at_extensions);
2009
ldap_str2attributetype( LDAP_CONST char * s,
2011
LDAP_CONST char ** errp,
2012
LDAP_CONST unsigned flags )
2015
const char * ss = s;
2019
int seen_obsolete = 0;
2021
int seen_equality = 0;
2022
int seen_ordering = 0;
2023
int seen_substr = 0;
2024
int seen_syntax = 0;
2026
LDAPAttributeType * at;
2028
const char * savepos;
2031
*code = LDAP_SCHERR_EMPTY;
2037
at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2040
*code = LDAP_SCHERR_OUTOFMEM;
2044
kind = get_token(&ss,&sval);
2045
if ( kind != TK_LEFTPAREN ) {
2046
*code = LDAP_SCHERR_NOLEFTPAREN;
2048
ldap_attributetype_free(at);
2053
* Definitions MUST begin with an OID in the numericoid format.
2054
* However, this routine is used by clients to parse the response
2055
* from servers and very well known servers will provide an OID
2056
* in the wrong format or even no OID at all. We do our best to
2057
* extract info from those servers.
2061
at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2062
if ( !at->at_oid ) {
2063
if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2064
| LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2065
&& (ss == savepos) )
2069
kind = get_token(&ss,&sval);
2070
if ( kind == TK_BAREWORD ) {
2071
if ( !strcasecmp(sval, "NAME") ||
2072
!strcasecmp(sval, "DESC") ||
2073
!strcasecmp(sval, "OBSOLETE") ||
2074
!strcasecmp(sval, "SUP") ||
2075
!strcasecmp(sval, "EQUALITY") ||
2076
!strcasecmp(sval, "ORDERING") ||
2077
!strcasecmp(sval, "SUBSTR") ||
2078
!strcasecmp(sval, "SYNTAX") ||
2079
!strcasecmp(sval, "SINGLE-VALUE") ||
2080
!strcasecmp(sval, "COLLECTIVE") ||
2081
!strcasecmp(sval, "NO-USER-MODIFICATION") ||
2082
!strcasecmp(sval, "USAGE") ||
2083
!strncasecmp(sval, "X-", 2) )
2085
/* Missing OID, backtrack */
2088
& LDAP_SCHEMA_ALLOW_OID_MACRO)
2090
/* Non-numerical OID ... */
2091
int len = ss-savepos;
2092
at->at_oid = LDAP_MALLOC(len+1);
2093
strncpy(at->at_oid, savepos, len);
2094
at->at_oid[len] = 0;
2100
ldap_attributetype_free(at);
2107
* Beyond this point we will be liberal and accept the items
2111
kind = get_token(&ss,&sval);
2114
*code = LDAP_SCHERR_NORIGHTPAREN;
2116
ldap_attributetype_free(at);
2121
if ( !strcasecmp(sval,"NAME") ) {
2124
*code = LDAP_SCHERR_DUPOPT;
2126
ldap_attributetype_free(at);
2130
at->at_names = parse_qdescrs(&ss,code);
2131
if ( !at->at_names ) {
2132
if ( *code != LDAP_SCHERR_OUTOFMEM )
2133
*code = LDAP_SCHERR_BADNAME;
2135
ldap_attributetype_free(at);
2138
} else if ( !strcasecmp(sval,"DESC") ) {
2141
*code = LDAP_SCHERR_DUPOPT;
2143
ldap_attributetype_free(at);
2148
kind = get_token(&ss,&sval);
2149
if ( kind != TK_QDSTRING ) {
2150
*code = LDAP_SCHERR_UNEXPTOKEN;
2153
ldap_attributetype_free(at);
2158
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2160
if ( seen_obsolete ) {
2161
*code = LDAP_SCHERR_DUPOPT;
2163
ldap_attributetype_free(at);
2167
at->at_obsolete = LDAP_SCHEMA_YES;
2169
} else if ( !strcasecmp(sval,"SUP") ) {
2172
*code = LDAP_SCHERR_DUPOPT;
2174
ldap_attributetype_free(at);
2178
at->at_sup_oid = parse_woid(&ss,code);
2179
if ( !at->at_sup_oid ) {
2181
ldap_attributetype_free(at);
2184
} else if ( !strcasecmp(sval,"EQUALITY") ) {
2186
if ( seen_equality ) {
2187
*code = LDAP_SCHERR_DUPOPT;
2189
ldap_attributetype_free(at);
2193
at->at_equality_oid = parse_woid(&ss,code);
2194
if ( !at->at_equality_oid ) {
2196
ldap_attributetype_free(at);
2199
} else if ( !strcasecmp(sval,"ORDERING") ) {
2201
if ( seen_ordering ) {
2202
*code = LDAP_SCHERR_DUPOPT;
2204
ldap_attributetype_free(at);
2208
at->at_ordering_oid = parse_woid(&ss,code);
2209
if ( !at->at_ordering_oid ) {
2211
ldap_attributetype_free(at);
2214
} else if ( !strcasecmp(sval,"SUBSTR") ) {
2216
if ( seen_substr ) {
2217
*code = LDAP_SCHERR_DUPOPT;
2219
ldap_attributetype_free(at);
2223
at->at_substr_oid = parse_woid(&ss,code);
2224
if ( !at->at_substr_oid ) {
2226
ldap_attributetype_free(at);
2229
} else if ( !strcasecmp(sval,"SYNTAX") ) {
2231
if ( seen_syntax ) {
2232
*code = LDAP_SCHERR_DUPOPT;
2234
ldap_attributetype_free(at);
2245
if ( !at->at_syntax_oid ) {
2246
if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2247
kind = get_token(&ss,&sval);
2248
if (kind == TK_BAREWORD)
2250
char *sp = strchr(sval, '{');
2251
at->at_syntax_oid = sval;
2255
at->at_syntax_len = atoi(sp);
2256
while ( LDAP_DIGIT(*sp) )
2259
*code = LDAP_SCHERR_UNEXPTOKEN;
2261
ldap_attributetype_free(at);
2268
ldap_attributetype_free(at);
2273
} else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2275
if ( at->at_single_value ) {
2276
*code = LDAP_SCHERR_DUPOPT;
2278
ldap_attributetype_free(at);
2281
at->at_single_value = LDAP_SCHEMA_YES;
2283
} else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2285
if ( at->at_collective ) {
2286
*code = LDAP_SCHERR_DUPOPT;
2288
ldap_attributetype_free(at);
2291
at->at_collective = LDAP_SCHEMA_YES;
2293
} else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2295
if ( at->at_no_user_mod ) {
2296
*code = LDAP_SCHERR_DUPOPT;
2298
ldap_attributetype_free(at);
2301
at->at_no_user_mod = LDAP_SCHEMA_YES;
2303
} else if ( !strcasecmp(sval,"USAGE") ) {
2306
*code = LDAP_SCHERR_DUPOPT;
2308
ldap_attributetype_free(at);
2313
kind = get_token(&ss,&sval);
2314
if ( kind != TK_BAREWORD ) {
2315
*code = LDAP_SCHERR_UNEXPTOKEN;
2318
ldap_attributetype_free(at);
2321
if ( !strcasecmp(sval,"userApplications") )
2323
LDAP_SCHEMA_USER_APPLICATIONS;
2324
else if ( !strcasecmp(sval,"directoryOperation") )
2326
LDAP_SCHEMA_DIRECTORY_OPERATION;
2327
else if ( !strcasecmp(sval,"distributedOperation") )
2329
LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2330
else if ( !strcasecmp(sval,"dSAOperation") )
2332
LDAP_SCHEMA_DSA_OPERATION;
2334
*code = LDAP_SCHERR_UNEXPTOKEN;
2337
ldap_attributetype_free(at);
2342
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2343
/* Should be parse_qdstrings */
2344
ext_vals = parse_qdescrs(&ss, code);
2347
ldap_attributetype_free(at);
2350
if ( add_extension(&at->at_extensions,
2352
*code = LDAP_SCHERR_OUTOFMEM;
2355
ldap_attributetype_free(at);
2359
*code = LDAP_SCHERR_UNEXPTOKEN;
2362
ldap_attributetype_free(at);
2367
*code = LDAP_SCHERR_UNEXPTOKEN;
2370
ldap_attributetype_free(at);
2377
ldap_objectclass_free(LDAPObjectClass * oc)
2379
LDAP_FREE(oc->oc_oid);
2380
if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2381
if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2382
if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2383
if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2384
if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2385
free_extensions(oc->oc_extensions);
2390
ldap_str2objectclass( LDAP_CONST char * s,
2392
LDAP_CONST char ** errp,
2393
LDAP_CONST unsigned flags )
2396
const char * ss = s;
2400
int seen_obsolete = 0;
2405
LDAPObjectClass * oc;
2407
const char * savepos;
2410
*code = LDAP_SCHERR_EMPTY;
2416
oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2419
*code = LDAP_SCHERR_OUTOFMEM;
2422
oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2424
kind = get_token(&ss,&sval);
2425
if ( kind != TK_LEFTPAREN ) {
2426
*code = LDAP_SCHERR_NOLEFTPAREN;
2428
ldap_objectclass_free(oc);
2433
* Definitions MUST begin with an OID in the numericoid format.
2434
* However, this routine is used by clients to parse the response
2435
* from servers and very well known servers will provide an OID
2436
* in the wrong format or even no OID at all. We do our best to
2437
* extract info from those servers.
2441
oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2442
if ( !oc->oc_oid ) {
2443
if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2446
kind = get_token(&ss,&sval);
2447
if ( kind == TK_BAREWORD ) {
2448
if ( !strcasecmp(sval, "NAME") ||
2449
!strcasecmp(sval, "DESC") ||
2450
!strcasecmp(sval, "OBSOLETE") ||
2451
!strcasecmp(sval, "SUP") ||
2452
!strcasecmp(sval, "ABSTRACT") ||
2453
!strcasecmp(sval, "STRUCTURAL") ||
2454
!strcasecmp(sval, "AUXILIARY") ||
2455
!strcasecmp(sval, "MUST") ||
2456
!strcasecmp(sval, "MAY") ||
2457
!strncasecmp(sval, "X-", 2) ) {
2458
/* Missing OID, backtrack */
2461
LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2462
/* Non-numerical OID, ignore */
2463
int len = ss-savepos;
2464
oc->oc_oid = LDAP_MALLOC(len+1);
2465
strncpy(oc->oc_oid, savepos, len);
2466
oc->oc_oid[len] = 0;
2473
ldap_objectclass_free(oc);
2480
* Beyond this point we will be liberal an accept the items
2484
kind = get_token(&ss,&sval);
2487
*code = LDAP_SCHERR_NORIGHTPAREN;
2489
ldap_objectclass_free(oc);
2494
if ( !strcasecmp(sval,"NAME") ) {
2497
*code = LDAP_SCHERR_DUPOPT;
2499
ldap_objectclass_free(oc);
2503
oc->oc_names = parse_qdescrs(&ss,code);
2504
if ( !oc->oc_names ) {
2505
if ( *code != LDAP_SCHERR_OUTOFMEM )
2506
*code = LDAP_SCHERR_BADNAME;
2508
ldap_objectclass_free(oc);
2511
} else if ( !strcasecmp(sval,"DESC") ) {
2514
*code = LDAP_SCHERR_DUPOPT;
2516
ldap_objectclass_free(oc);
2521
kind = get_token(&ss,&sval);
2522
if ( kind != TK_QDSTRING ) {
2523
*code = LDAP_SCHERR_UNEXPTOKEN;
2526
ldap_objectclass_free(oc);
2531
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2533
if ( seen_obsolete ) {
2534
*code = LDAP_SCHERR_DUPOPT;
2536
ldap_objectclass_free(oc);
2540
oc->oc_obsolete = LDAP_SCHEMA_YES;
2542
} else if ( !strcasecmp(sval,"SUP") ) {
2545
*code = LDAP_SCHERR_DUPOPT;
2547
ldap_objectclass_free(oc);
2551
oc->oc_sup_oids = parse_oids(&ss,
2554
if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2556
ldap_objectclass_free(oc);
2560
} else if ( !strcasecmp(sval,"ABSTRACT") ) {
2563
*code = LDAP_SCHERR_DUPOPT;
2565
ldap_objectclass_free(oc);
2569
oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2571
} else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2574
*code = LDAP_SCHERR_DUPOPT;
2576
ldap_objectclass_free(oc);
2580
oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2582
} else if ( !strcasecmp(sval,"AUXILIARY") ) {
2585
*code = LDAP_SCHERR_DUPOPT;
2587
ldap_objectclass_free(oc);
2591
oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2593
} else if ( !strcasecmp(sval,"MUST") ) {
2596
*code = LDAP_SCHERR_DUPOPT;
2598
ldap_objectclass_free(oc);
2602
oc->oc_at_oids_must = parse_oids(&ss,code,0);
2603
if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2605
ldap_objectclass_free(oc);
2610
} else if ( !strcasecmp(sval,"MAY") ) {
2613
*code = LDAP_SCHERR_DUPOPT;
2615
ldap_objectclass_free(oc);
2619
oc->oc_at_oids_may = parse_oids(&ss,code,0);
2620
if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2622
ldap_objectclass_free(oc);
2627
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2628
/* Should be parse_qdstrings */
2629
ext_vals = parse_qdescrs(&ss, code);
2633
ldap_objectclass_free(oc);
2636
if ( add_extension(&oc->oc_extensions,
2638
*code = LDAP_SCHERR_OUTOFMEM;
2641
ldap_objectclass_free(oc);
2645
*code = LDAP_SCHERR_UNEXPTOKEN;
2648
ldap_objectclass_free(oc);
2653
*code = LDAP_SCHERR_UNEXPTOKEN;
2656
ldap_objectclass_free(oc);
2663
ldap_contentrule_free(LDAPContentRule * cr)
2665
LDAP_FREE(cr->cr_oid);
2666
if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2667
if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2668
if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2669
if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2670
if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2671
if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2672
free_extensions(cr->cr_extensions);
2677
ldap_str2contentrule( LDAP_CONST char * s,
2679
LDAP_CONST char ** errp,
2680
LDAP_CONST unsigned flags )
2683
const char * ss = s;
2687
int seen_obsolete = 0;
2692
LDAPContentRule * cr;
2694
const char * savepos;
2697
*code = LDAP_SCHERR_EMPTY;
2703
cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2706
*code = LDAP_SCHERR_OUTOFMEM;
2710
kind = get_token(&ss,&sval);
2711
if ( kind != TK_LEFTPAREN ) {
2712
*code = LDAP_SCHERR_NOLEFTPAREN;
2714
ldap_contentrule_free(cr);
2719
* Definitions MUST begin with an OID in the numericoid format.
2723
cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2724
if ( !cr->cr_oid ) {
2725
if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2728
kind = get_token(&ss,&sval);
2729
if ( kind == TK_BAREWORD ) {
2730
if ( !strcasecmp(sval, "NAME") ||
2731
!strcasecmp(sval, "DESC") ||
2732
!strcasecmp(sval, "OBSOLETE") ||
2733
!strcasecmp(sval, "AUX") ||
2734
!strcasecmp(sval, "MUST") ||
2735
!strcasecmp(sval, "MAY") ||
2736
!strcasecmp(sval, "NOT") ||
2737
!strncasecmp(sval, "X-", 2) ) {
2738
/* Missing OID, backtrack */
2741
LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2742
/* Non-numerical OID, ignore */
2743
int len = ss-savepos;
2744
cr->cr_oid = LDAP_MALLOC(len+1);
2745
strncpy(cr->cr_oid, savepos, len);
2746
cr->cr_oid[len] = 0;
2752
ldap_contentrule_free(cr);
2759
* Beyond this point we will be liberal an accept the items
2763
kind = get_token(&ss,&sval);
2766
*code = LDAP_SCHERR_NORIGHTPAREN;
2768
ldap_contentrule_free(cr);
2773
if ( !strcasecmp(sval,"NAME") ) {
2776
*code = LDAP_SCHERR_DUPOPT;
2778
ldap_contentrule_free(cr);
2782
cr->cr_names = parse_qdescrs(&ss,code);
2783
if ( !cr->cr_names ) {
2784
if ( *code != LDAP_SCHERR_OUTOFMEM )
2785
*code = LDAP_SCHERR_BADNAME;
2787
ldap_contentrule_free(cr);
2790
} else if ( !strcasecmp(sval,"DESC") ) {
2793
*code = LDAP_SCHERR_DUPOPT;
2795
ldap_contentrule_free(cr);
2800
kind = get_token(&ss,&sval);
2801
if ( kind != TK_QDSTRING ) {
2802
*code = LDAP_SCHERR_UNEXPTOKEN;
2805
ldap_contentrule_free(cr);
2810
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2812
if ( seen_obsolete ) {
2813
*code = LDAP_SCHERR_DUPOPT;
2815
ldap_contentrule_free(cr);
2819
cr->cr_obsolete = LDAP_SCHEMA_YES;
2821
} else if ( !strcasecmp(sval,"AUX") ) {
2824
*code = LDAP_SCHERR_DUPOPT;
2826
ldap_contentrule_free(cr);
2830
cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2831
if ( !cr->cr_oc_oids_aux ) {
2833
ldap_contentrule_free(cr);
2837
} else if ( !strcasecmp(sval,"MUST") ) {
2840
*code = LDAP_SCHERR_DUPOPT;
2842
ldap_contentrule_free(cr);
2846
cr->cr_at_oids_must = parse_oids(&ss,code,0);
2847
if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2849
ldap_contentrule_free(cr);
2853
} else if ( !strcasecmp(sval,"MAY") ) {
2856
*code = LDAP_SCHERR_DUPOPT;
2858
ldap_contentrule_free(cr);
2862
cr->cr_at_oids_may = parse_oids(&ss,code,0);
2863
if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2865
ldap_contentrule_free(cr);
2869
} else if ( !strcasecmp(sval,"NOT") ) {
2872
*code = LDAP_SCHERR_DUPOPT;
2874
ldap_contentrule_free(cr);
2878
cr->cr_at_oids_not = parse_oids(&ss,code,0);
2879
if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2881
ldap_contentrule_free(cr);
2885
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2886
/* Should be parse_qdstrings */
2887
ext_vals = parse_qdescrs(&ss, code);
2890
ldap_contentrule_free(cr);
2893
if ( add_extension(&cr->cr_extensions,
2895
*code = LDAP_SCHERR_OUTOFMEM;
2898
ldap_contentrule_free(cr);
2902
*code = LDAP_SCHERR_UNEXPTOKEN;
2905
ldap_contentrule_free(cr);
2910
*code = LDAP_SCHERR_UNEXPTOKEN;
2913
ldap_contentrule_free(cr);
2920
ldap_structurerule_free(LDAPStructureRule * sr)
2922
if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2923
if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2924
if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2925
if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2926
free_extensions(sr->sr_extensions);
2931
ldap_str2structurerule( LDAP_CONST char * s,
2933
LDAP_CONST char ** errp,
2934
LDAP_CONST unsigned flags )
2938
const char * ss = s;
2942
int seen_obsolete = 0;
2943
int seen_nameform = 0;
2944
LDAPStructureRule * sr;
2946
const char * savepos;
2949
*code = LDAP_SCHERR_EMPTY;
2955
sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2958
*code = LDAP_SCHERR_OUTOFMEM;
2962
kind = get_token(&ss,&sval);
2963
if ( kind != TK_LEFTPAREN ) {
2964
*code = LDAP_SCHERR_NOLEFTPAREN;
2966
ldap_structurerule_free(sr);
2971
* Definitions MUST begin with a ruleid.
2975
ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
2978
ldap_structurerule_free(sr);
2984
* Beyond this point we will be liberal an accept the items
2988
kind = get_token(&ss,&sval);
2991
*code = LDAP_SCHERR_NORIGHTPAREN;
2993
ldap_structurerule_free(sr);
2996
if( !seen_nameform ) {
2997
*code = LDAP_SCHERR_MISSING;
2998
ldap_structurerule_free(sr);
3003
if ( !strcasecmp(sval,"NAME") ) {
3006
*code = LDAP_SCHERR_DUPOPT;
3008
ldap_structurerule_free(sr);
3012
sr->sr_names = parse_qdescrs(&ss,code);
3013
if ( !sr->sr_names ) {
3014
if ( *code != LDAP_SCHERR_OUTOFMEM )
3015
*code = LDAP_SCHERR_BADNAME;
3017
ldap_structurerule_free(sr);
3020
} else if ( !strcasecmp(sval,"DESC") ) {
3023
*code = LDAP_SCHERR_DUPOPT;
3025
ldap_structurerule_free(sr);
3030
kind = get_token(&ss,&sval);
3031
if ( kind != TK_QDSTRING ) {
3032
*code = LDAP_SCHERR_UNEXPTOKEN;
3035
ldap_structurerule_free(sr);
3040
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
3042
if ( seen_obsolete ) {
3043
*code = LDAP_SCHERR_DUPOPT;
3045
ldap_structurerule_free(sr);
3049
sr->sr_obsolete = LDAP_SCHEMA_YES;
3051
} else if ( !strcasecmp(sval,"FORM") ) {
3053
if ( seen_nameform ) {
3054
*code = LDAP_SCHERR_DUPOPT;
3056
ldap_structurerule_free(sr);
3060
sr->sr_nameform = parse_woid(&ss,code);
3061
if ( !sr->sr_nameform ) {
3063
ldap_structurerule_free(sr);
3067
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
3068
/* Should be parse_qdstrings */
3069
ext_vals = parse_qdescrs(&ss, code);
3072
ldap_structurerule_free(sr);
3075
if ( add_extension(&sr->sr_extensions,
3077
*code = LDAP_SCHERR_OUTOFMEM;
3080
ldap_structurerule_free(sr);
3084
*code = LDAP_SCHERR_UNEXPTOKEN;
3087
ldap_structurerule_free(sr);
3092
*code = LDAP_SCHERR_UNEXPTOKEN;
3095
ldap_structurerule_free(sr);
3102
ldap_nameform_free(LDAPNameForm * nf)
3104
LDAP_FREE(nf->nf_oid);
3105
if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3106
if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3107
if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3108
if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3109
if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3110
free_extensions(nf->nf_extensions);
3115
ldap_str2nameform( LDAP_CONST char * s,
3117
LDAP_CONST char ** errp,
3118
LDAP_CONST unsigned flags )
3121
const char * ss = s;
3125
int seen_obsolete = 0;
3131
const char * savepos;
3134
*code = LDAP_SCHERR_EMPTY;
3140
nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3143
*code = LDAP_SCHERR_OUTOFMEM;
3147
kind = get_token(&ss,&sval);
3148
if ( kind != TK_LEFTPAREN ) {
3149
*code = LDAP_SCHERR_NOLEFTPAREN;
3151
ldap_nameform_free(nf);
3156
* Definitions MUST begin with an OID in the numericoid format.
3157
* However, this routine is used by clients to parse the response
3158
* from servers and very well known servers will provide an OID
3159
* in the wrong format or even no OID at all. We do our best to
3160
* extract info from those servers.
3164
nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3165
if ( !nf->nf_oid ) {
3167
ldap_nameform_free(nf);
3173
* Beyond this point we will be liberal an accept the items
3177
kind = get_token(&ss,&sval);
3180
*code = LDAP_SCHERR_NORIGHTPAREN;
3182
ldap_nameform_free(nf);
3185
if( !seen_class || !seen_must ) {
3186
*code = LDAP_SCHERR_MISSING;
3187
ldap_nameform_free(nf);
3192
if ( !strcasecmp(sval,"NAME") ) {
3195
*code = LDAP_SCHERR_DUPOPT;
3197
ldap_nameform_free(nf);
3201
nf->nf_names = parse_qdescrs(&ss,code);
3202
if ( !nf->nf_names ) {
3203
if ( *code != LDAP_SCHERR_OUTOFMEM )
3204
*code = LDAP_SCHERR_BADNAME;
3206
ldap_nameform_free(nf);
3209
} else if ( !strcasecmp(sval,"DESC") ) {
3212
*code = LDAP_SCHERR_DUPOPT;
3214
ldap_nameform_free(nf);
3219
kind = get_token(&ss,&sval);
3220
if ( kind != TK_QDSTRING ) {
3221
*code = LDAP_SCHERR_UNEXPTOKEN;
3224
ldap_nameform_free(nf);
3229
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
3231
if ( seen_obsolete ) {
3232
*code = LDAP_SCHERR_DUPOPT;
3234
ldap_nameform_free(nf);
3238
nf->nf_obsolete = LDAP_SCHEMA_YES;
3240
} else if ( !strcasecmp(sval,"OC") ) {
3243
*code = LDAP_SCHERR_DUPOPT;
3245
ldap_nameform_free(nf);
3249
nf->nf_objectclass = parse_woid(&ss,code);
3250
if ( !nf->nf_objectclass ) {
3252
ldap_nameform_free(nf);
3255
} else if ( !strcasecmp(sval,"MUST") ) {
3258
*code = LDAP_SCHERR_DUPOPT;
3260
ldap_nameform_free(nf);
3264
nf->nf_at_oids_must = parse_oids(&ss,code,0);
3265
if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3267
ldap_nameform_free(nf);
3271
} else if ( !strcasecmp(sval,"MAY") ) {
3274
*code = LDAP_SCHERR_DUPOPT;
3276
ldap_nameform_free(nf);
3280
nf->nf_at_oids_may = parse_oids(&ss,code,0);
3281
if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3283
ldap_nameform_free(nf);
3287
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
3288
/* Should be parse_qdstrings */
3289
ext_vals = parse_qdescrs(&ss, code);
3292
ldap_nameform_free(nf);
3295
if ( add_extension(&nf->nf_extensions,
3297
*code = LDAP_SCHERR_OUTOFMEM;
3300
ldap_nameform_free(nf);
3304
*code = LDAP_SCHERR_UNEXPTOKEN;
3307
ldap_nameform_free(nf);
3312
*code = LDAP_SCHERR_UNEXPTOKEN;
3315
ldap_nameform_free(nf);
3321
static char *const err2text[] = {
3323
N_("Out of memory"),
3324
N_("Unexpected token"),
3325
N_("Missing opening parenthesis"),
3326
N_("Missing closing parenthesis"),
3327
N_("Expecting digit"),
3328
N_("Expecting a name"),
3329
N_("Bad description"),
3330
N_("Bad superiors"),
3331
N_("Duplicate option"),
3332
N_("Unexpected end of data"),
3333
N_("Missing required field"),
3334
N_("Out of order field")
3338
ldap_scherr2str(int code)
3340
if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3341
return _("Unknown error");
3343
return _(err2text[code]);