Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/libldap/schema.c
4394 views
1
/* $OpenLDAP$ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
*
4
* Copyright 1998-2024 The OpenLDAP Foundation.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
9
* Public License.
10
*
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>.
14
*/
15
16
/*
17
* schema.c: parsing routines used by servers and clients to process
18
* schema definitions
19
*/
20
21
#include "portable.h"
22
23
#include <stdio.h>
24
#include <ac/stdlib.h>
25
26
#include <ac/string.h>
27
#include <ac/time.h>
28
29
#include "ldap-int.h"
30
31
#include <ldap_schema.h>
32
33
static const char EndOfInput[] = "end of input";
34
35
static const char *
36
choose_name( char *names[], const char *fallback )
37
{
38
return (names != NULL && names[0] != NULL) ? names[0] : fallback;
39
}
40
41
LDAP_CONST char *
42
ldap_syntax2name( LDAPSyntax * syn )
43
{
44
if (!syn) return NULL;
45
return( syn->syn_oid );
46
}
47
48
LDAP_CONST char *
49
ldap_matchingrule2name( LDAPMatchingRule * mr )
50
{
51
if (!mr) return NULL;
52
return( choose_name( mr->mr_names, mr->mr_oid ) );
53
}
54
55
LDAP_CONST char *
56
ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
57
{
58
if (!mru) return NULL;
59
return( choose_name( mru->mru_names, mru->mru_oid ) );
60
}
61
62
LDAP_CONST char *
63
ldap_attributetype2name( LDAPAttributeType * at )
64
{
65
if (!at) return NULL;
66
return( choose_name( at->at_names, at->at_oid ) );
67
}
68
69
LDAP_CONST char *
70
ldap_objectclass2name( LDAPObjectClass * oc )
71
{
72
if (!oc) return NULL;
73
return( choose_name( oc->oc_names, oc->oc_oid ) );
74
}
75
76
LDAP_CONST char *
77
ldap_contentrule2name( LDAPContentRule * cr )
78
{
79
if (!cr) return NULL;
80
return( choose_name( cr->cr_names, cr->cr_oid ) );
81
}
82
83
LDAP_CONST char *
84
ldap_nameform2name( LDAPNameForm * nf )
85
{
86
if (!nf) return NULL;
87
return( choose_name( nf->nf_names, nf->nf_oid ) );
88
}
89
90
LDAP_CONST char *
91
ldap_structurerule2name( LDAPStructureRule * sr )
92
{
93
if (!sr) return NULL;
94
return( choose_name( sr->sr_names, NULL ) );
95
}
96
97
/*
98
* When pretty printing the entities we will be appending to a buffer.
99
* Since checking for overflow, realloc'ing and checking if no error
100
* is extremely boring, we will use a protection layer that will let
101
* us blissfully ignore the error until the end. This layer is
102
* implemented with the help of the next type.
103
*/
104
105
typedef struct safe_string {
106
char * val;
107
ber_len_t size;
108
ber_len_t pos;
109
int at_whsp;
110
} safe_string;
111
112
static safe_string *
113
new_safe_string(int size)
114
{
115
safe_string * ss;
116
117
ss = LDAP_MALLOC(sizeof(safe_string));
118
if ( !ss )
119
return(NULL);
120
121
ss->val = LDAP_MALLOC(size);
122
if ( !ss->val ) {
123
LDAP_FREE(ss);
124
return(NULL);
125
}
126
127
ss->size = size;
128
ss->pos = 0;
129
ss->at_whsp = 0;
130
131
return ss;
132
}
133
134
static void
135
safe_string_free(safe_string * ss)
136
{
137
if ( !ss )
138
return;
139
LDAP_FREE(ss->val);
140
LDAP_FREE(ss);
141
}
142
143
#if 0 /* unused */
144
static char *
145
safe_string_val(safe_string * ss)
146
{
147
ss->val[ss->pos] = '\0';
148
return(ss->val);
149
}
150
#endif
151
152
static char *
153
safe_strdup(safe_string * ss)
154
{
155
char *ret = LDAP_MALLOC(ss->pos+1);
156
if (!ret)
157
return NULL;
158
AC_MEMCPY(ret, ss->val, ss->pos);
159
ret[ss->pos] = '\0';
160
return ret;
161
}
162
163
static int
164
append_to_safe_string(safe_string * ss, char * s)
165
{
166
int l = strlen(s);
167
char * temp;
168
169
/*
170
* Some runaway process is trying to append to a string that
171
* overflowed and we could not extend.
172
*/
173
if ( !ss->val )
174
return -1;
175
176
/* We always make sure there is at least one position available */
177
if ( ss->pos + l >= ss->size-1 ) {
178
ss->size *= 2;
179
if ( ss->pos + l >= ss->size-1 ) {
180
ss->size = ss->pos + l + 1;
181
}
182
183
temp = LDAP_REALLOC(ss->val, ss->size);
184
if ( !temp ) {
185
/* Trouble, out of memory */
186
LDAP_FREE(ss->val);
187
return -1;
188
}
189
ss->val = temp;
190
}
191
strncpy(&ss->val[ss->pos], s, l);
192
ss->pos += l;
193
if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
194
ss->at_whsp = 1;
195
else
196
ss->at_whsp = 0;
197
198
return 0;
199
}
200
201
static int
202
print_literal(safe_string *ss, char *s)
203
{
204
return(append_to_safe_string(ss,s));
205
}
206
207
static int
208
print_whsp(safe_string *ss)
209
{
210
if ( ss->at_whsp )
211
return(append_to_safe_string(ss,""));
212
else
213
return(append_to_safe_string(ss," "));
214
}
215
216
static int
217
print_numericoid(safe_string *ss, char *s)
218
{
219
if ( s )
220
return(append_to_safe_string(ss,s));
221
else
222
return(append_to_safe_string(ss,""));
223
}
224
225
/* This one is identical to print_qdescr */
226
static int
227
print_qdstring(safe_string *ss, char *s)
228
{
229
print_whsp(ss);
230
print_literal(ss,"'");
231
append_to_safe_string(ss,s);
232
print_literal(ss,"'");
233
return(print_whsp(ss));
234
}
235
236
static int
237
print_qdescr(safe_string *ss, char *s)
238
{
239
print_whsp(ss);
240
print_literal(ss,"'");
241
append_to_safe_string(ss,s);
242
print_literal(ss,"'");
243
return(print_whsp(ss));
244
}
245
246
static int
247
print_qdescrlist(safe_string *ss, char **sa)
248
{
249
char **sp;
250
int ret = 0;
251
252
for (sp=sa; *sp; sp++) {
253
ret = print_qdescr(ss,*sp);
254
}
255
/* If the list was empty, we return zero that is potentially
256
* incorrect, but since we will be still appending things, the
257
* overflow will be detected later. Maybe FIX.
258
*/
259
return(ret);
260
}
261
262
static int
263
print_qdescrs(safe_string *ss, char **sa)
264
{
265
/* The only way to represent an empty list is as a qdescrlist
266
* so, if the list is empty we treat it as a long list.
267
* Really, this is what the syntax mandates. We should not
268
* be here if the list was empty, but if it happens, a label
269
* has already been output and we cannot undo it.
270
*/
271
if ( !sa[0] || ( sa[0] && sa[1] ) ) {
272
print_whsp(ss);
273
print_literal(ss,"("/*)*/);
274
print_qdescrlist(ss,sa);
275
print_literal(ss,/*(*/")");
276
return(print_whsp(ss));
277
} else {
278
return(print_qdescr(ss,*sa));
279
}
280
}
281
282
static int
283
print_woid(safe_string *ss, char *s)
284
{
285
print_whsp(ss);
286
append_to_safe_string(ss,s);
287
return print_whsp(ss);
288
}
289
290
static int
291
print_oidlist(safe_string *ss, char **sa)
292
{
293
char **sp;
294
295
for (sp=sa; *(sp+1); sp++) {
296
print_woid(ss,*sp);
297
print_literal(ss,"$");
298
}
299
return(print_woid(ss,*sp));
300
}
301
302
static int
303
print_oids(safe_string *ss, char **sa)
304
{
305
if ( sa[0] && sa[1] ) {
306
print_literal(ss,"("/*)*/);
307
print_oidlist(ss,sa);
308
print_whsp(ss);
309
return(print_literal(ss,/*(*/")"));
310
} else {
311
return(print_woid(ss,*sa));
312
}
313
}
314
315
static int
316
print_noidlen(safe_string *ss, char *s, int l)
317
{
318
char buf[64];
319
int ret;
320
321
ret = print_numericoid(ss,s);
322
if ( l ) {
323
snprintf(buf, sizeof buf, "{%d}",l);
324
ret = print_literal(ss,buf);
325
}
326
return(ret);
327
}
328
329
static int
330
print_ruleid(safe_string *ss, int rid)
331
{
332
char buf[64];
333
snprintf(buf, sizeof buf, "%d", rid);
334
return print_literal(ss,buf);
335
}
336
337
static int
338
print_ruleids(safe_string *ss, int n, int *rids)
339
{
340
int i;
341
342
if( n == 1 ) {
343
print_ruleid(ss,rids[0]);
344
return print_whsp(ss);
345
} else {
346
print_literal(ss,"("/*)*/);
347
for( i=0; i<n; i++ ) {
348
print_whsp(ss);
349
print_ruleid(ss,rids[i]);
350
}
351
print_whsp(ss);
352
return print_literal(ss,/*(*/")");
353
}
354
}
355
356
357
static int
358
print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
359
{
360
LDAPSchemaExtensionItem **ext;
361
362
if ( extensions ) {
363
print_whsp(ss);
364
for ( ext = extensions; *ext != NULL; ext++ ) {
365
print_literal(ss, (*ext)->lsei_name);
366
print_whsp(ss);
367
/* Should be print_qdstrings */
368
print_qdescrs(ss, (*ext)->lsei_values);
369
print_whsp(ss);
370
}
371
}
372
373
return 0;
374
}
375
376
char *
377
ldap_syntax2str( LDAPSyntax * syn )
378
{
379
struct berval bv;
380
if (ldap_syntax2bv( syn, &bv ))
381
return(bv.bv_val);
382
else
383
return NULL;
384
}
385
386
struct berval *
387
ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
388
{
389
safe_string * ss;
390
391
if ( !syn || !bv )
392
return NULL;
393
394
ss = new_safe_string(256);
395
if ( !ss )
396
return NULL;
397
398
print_literal(ss,"("/*)*/);
399
print_whsp(ss);
400
401
print_numericoid(ss, syn->syn_oid);
402
print_whsp(ss);
403
404
if ( syn->syn_desc ) {
405
print_literal(ss,"DESC");
406
print_qdstring(ss,syn->syn_desc);
407
}
408
409
print_whsp(ss);
410
411
print_extensions(ss, syn->syn_extensions);
412
413
print_literal(ss,/*(*/ ")");
414
415
bv->bv_val = safe_strdup(ss);
416
bv->bv_len = ss->pos;
417
safe_string_free(ss);
418
return(bv);
419
}
420
421
char *
422
ldap_matchingrule2str( LDAPMatchingRule * mr )
423
{
424
struct berval bv;
425
if (ldap_matchingrule2bv( mr, &bv ))
426
return(bv.bv_val);
427
else
428
return NULL;
429
}
430
431
struct berval *
432
ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
433
{
434
safe_string * ss;
435
436
if ( !mr || !bv )
437
return NULL;
438
439
ss = new_safe_string(256);
440
if ( !ss )
441
return NULL;
442
443
print_literal(ss,"(" /*)*/);
444
print_whsp(ss);
445
446
print_numericoid(ss, mr->mr_oid);
447
print_whsp(ss);
448
449
if ( mr->mr_names ) {
450
print_literal(ss,"NAME");
451
print_qdescrs(ss,mr->mr_names);
452
}
453
454
if ( mr->mr_desc ) {
455
print_literal(ss,"DESC");
456
print_qdstring(ss,mr->mr_desc);
457
}
458
459
if ( mr->mr_obsolete ) {
460
print_literal(ss, "OBSOLETE");
461
print_whsp(ss);
462
}
463
464
if ( mr->mr_syntax_oid ) {
465
print_literal(ss,"SYNTAX");
466
print_whsp(ss);
467
print_literal(ss, mr->mr_syntax_oid);
468
print_whsp(ss);
469
}
470
471
print_whsp(ss);
472
473
print_extensions(ss, mr->mr_extensions);
474
475
print_literal(ss,/*(*/")");
476
477
bv->bv_val = safe_strdup(ss);
478
bv->bv_len = ss->pos;
479
safe_string_free(ss);
480
return(bv);
481
}
482
483
char *
484
ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
485
{
486
struct berval bv;
487
if (ldap_matchingruleuse2bv( mru, &bv ))
488
return(bv.bv_val);
489
else
490
return NULL;
491
}
492
493
struct berval *
494
ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
495
{
496
safe_string * ss;
497
498
if ( !mru || !bv )
499
return NULL;
500
501
ss = new_safe_string(256);
502
if ( !ss )
503
return NULL;
504
505
print_literal(ss,"(" /*)*/);
506
print_whsp(ss);
507
508
print_numericoid(ss, mru->mru_oid);
509
print_whsp(ss);
510
511
if ( mru->mru_names ) {
512
print_literal(ss,"NAME");
513
print_qdescrs(ss,mru->mru_names);
514
}
515
516
if ( mru->mru_desc ) {
517
print_literal(ss,"DESC");
518
print_qdstring(ss,mru->mru_desc);
519
}
520
521
if ( mru->mru_obsolete ) {
522
print_literal(ss, "OBSOLETE");
523
print_whsp(ss);
524
}
525
526
if ( mru->mru_applies_oids ) {
527
print_literal(ss,"APPLIES");
528
print_whsp(ss);
529
print_oids(ss, mru->mru_applies_oids);
530
print_whsp(ss);
531
}
532
533
print_whsp(ss);
534
535
print_extensions(ss, mru->mru_extensions);
536
537
print_literal(ss,/*(*/")");
538
539
bv->bv_val = safe_strdup(ss);
540
bv->bv_len = ss->pos;
541
safe_string_free(ss);
542
return(bv);
543
}
544
545
char *
546
ldap_objectclass2str( LDAPObjectClass * oc )
547
{
548
struct berval bv;
549
if (ldap_objectclass2bv( oc, &bv ))
550
return(bv.bv_val);
551
else
552
return NULL;
553
}
554
555
struct berval *
556
ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
557
{
558
safe_string * ss;
559
560
if ( !oc || !bv )
561
return NULL;
562
563
ss = new_safe_string(256);
564
if ( !ss )
565
return NULL;
566
567
print_literal(ss,"("/*)*/);
568
print_whsp(ss);
569
570
print_numericoid(ss, oc->oc_oid);
571
print_whsp(ss);
572
573
if ( oc->oc_names ) {
574
print_literal(ss,"NAME");
575
print_qdescrs(ss,oc->oc_names);
576
}
577
578
if ( oc->oc_desc ) {
579
print_literal(ss,"DESC");
580
print_qdstring(ss,oc->oc_desc);
581
}
582
583
if ( oc->oc_obsolete ) {
584
print_literal(ss, "OBSOLETE");
585
print_whsp(ss);
586
}
587
588
if ( oc->oc_sup_oids ) {
589
print_literal(ss,"SUP");
590
print_whsp(ss);
591
print_oids(ss,oc->oc_sup_oids);
592
print_whsp(ss);
593
}
594
595
switch (oc->oc_kind) {
596
case LDAP_SCHEMA_ABSTRACT:
597
print_literal(ss,"ABSTRACT");
598
break;
599
case LDAP_SCHEMA_STRUCTURAL:
600
print_literal(ss,"STRUCTURAL");
601
break;
602
case LDAP_SCHEMA_AUXILIARY:
603
print_literal(ss,"AUXILIARY");
604
break;
605
default:
606
print_literal(ss,"KIND-UNKNOWN");
607
break;
608
}
609
print_whsp(ss);
610
611
if ( oc->oc_at_oids_must ) {
612
print_literal(ss,"MUST");
613
print_whsp(ss);
614
print_oids(ss,oc->oc_at_oids_must);
615
print_whsp(ss);
616
}
617
618
if ( oc->oc_at_oids_may ) {
619
print_literal(ss,"MAY");
620
print_whsp(ss);
621
print_oids(ss,oc->oc_at_oids_may);
622
print_whsp(ss);
623
}
624
625
print_whsp(ss);
626
627
print_extensions(ss, oc->oc_extensions);
628
629
print_literal(ss, /*(*/")");
630
631
bv->bv_val = safe_strdup(ss);
632
bv->bv_len = ss->pos;
633
safe_string_free(ss);
634
return(bv);
635
}
636
637
char *
638
ldap_contentrule2str( LDAPContentRule * cr )
639
{
640
struct berval bv;
641
if (ldap_contentrule2bv( cr, &bv ))
642
return(bv.bv_val);
643
else
644
return NULL;
645
}
646
647
struct berval *
648
ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
649
{
650
safe_string * ss;
651
652
if ( !cr || !bv )
653
return NULL;
654
655
ss = new_safe_string(256);
656
if ( !ss )
657
return NULL;
658
659
print_literal(ss,"("/*)*/);
660
print_whsp(ss);
661
662
print_numericoid(ss, cr->cr_oid);
663
print_whsp(ss);
664
665
if ( cr->cr_names ) {
666
print_literal(ss,"NAME");
667
print_qdescrs(ss,cr->cr_names);
668
}
669
670
if ( cr->cr_desc ) {
671
print_literal(ss,"DESC");
672
print_qdstring(ss,cr->cr_desc);
673
}
674
675
if ( cr->cr_obsolete ) {
676
print_literal(ss, "OBSOLETE");
677
print_whsp(ss);
678
}
679
680
if ( cr->cr_oc_oids_aux ) {
681
print_literal(ss,"AUX");
682
print_whsp(ss);
683
print_oids(ss,cr->cr_oc_oids_aux);
684
print_whsp(ss);
685
}
686
687
if ( cr->cr_at_oids_must ) {
688
print_literal(ss,"MUST");
689
print_whsp(ss);
690
print_oids(ss,cr->cr_at_oids_must);
691
print_whsp(ss);
692
}
693
694
if ( cr->cr_at_oids_may ) {
695
print_literal(ss,"MAY");
696
print_whsp(ss);
697
print_oids(ss,cr->cr_at_oids_may);
698
print_whsp(ss);
699
}
700
701
if ( cr->cr_at_oids_not ) {
702
print_literal(ss,"NOT");
703
print_whsp(ss);
704
print_oids(ss,cr->cr_at_oids_not);
705
print_whsp(ss);
706
}
707
708
print_whsp(ss);
709
print_extensions(ss, cr->cr_extensions);
710
711
print_literal(ss, /*(*/")");
712
713
bv->bv_val = safe_strdup(ss);
714
bv->bv_len = ss->pos;
715
safe_string_free(ss);
716
return(bv);
717
}
718
719
char *
720
ldap_structurerule2str( LDAPStructureRule * sr )
721
{
722
struct berval bv;
723
if (ldap_structurerule2bv( sr, &bv ))
724
return(bv.bv_val);
725
else
726
return NULL;
727
}
728
729
struct berval *
730
ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
731
{
732
safe_string * ss;
733
734
if ( !sr || !bv )
735
return NULL;
736
737
ss = new_safe_string(256);
738
if ( !ss )
739
return NULL;
740
741
print_literal(ss,"("/*)*/);
742
print_whsp(ss);
743
744
print_ruleid(ss, sr->sr_ruleid);
745
print_whsp(ss);
746
747
if ( sr->sr_names ) {
748
print_literal(ss,"NAME");
749
print_qdescrs(ss,sr->sr_names);
750
}
751
752
if ( sr->sr_desc ) {
753
print_literal(ss,"DESC");
754
print_qdstring(ss,sr->sr_desc);
755
}
756
757
if ( sr->sr_obsolete ) {
758
print_literal(ss, "OBSOLETE");
759
print_whsp(ss);
760
}
761
762
print_literal(ss,"FORM");
763
print_whsp(ss);
764
print_woid(ss,sr->sr_nameform);
765
print_whsp(ss);
766
767
if ( sr->sr_nsup_ruleids ) {
768
print_literal(ss,"SUP");
769
print_whsp(ss);
770
print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
771
print_whsp(ss);
772
}
773
774
print_whsp(ss);
775
print_extensions(ss, sr->sr_extensions);
776
777
print_literal(ss, /*(*/")");
778
779
bv->bv_val = safe_strdup(ss);
780
bv->bv_len = ss->pos;
781
safe_string_free(ss);
782
return(bv);
783
}
784
785
786
char *
787
ldap_nameform2str( LDAPNameForm * nf )
788
{
789
struct berval bv;
790
if (ldap_nameform2bv( nf, &bv ))
791
return(bv.bv_val);
792
else
793
return NULL;
794
}
795
796
struct berval *
797
ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
798
{
799
safe_string * ss;
800
801
if ( !nf || !bv )
802
return NULL;
803
804
ss = new_safe_string(256);
805
if ( !ss )
806
return NULL;
807
808
print_literal(ss,"("/*)*/);
809
print_whsp(ss);
810
811
print_numericoid(ss, nf->nf_oid);
812
print_whsp(ss);
813
814
if ( nf->nf_names ) {
815
print_literal(ss,"NAME");
816
print_qdescrs(ss,nf->nf_names);
817
}
818
819
if ( nf->nf_desc ) {
820
print_literal(ss,"DESC");
821
print_qdstring(ss,nf->nf_desc);
822
}
823
824
if ( nf->nf_obsolete ) {
825
print_literal(ss, "OBSOLETE");
826
print_whsp(ss);
827
}
828
829
print_literal(ss,"OC");
830
print_whsp(ss);
831
print_woid(ss,nf->nf_objectclass);
832
print_whsp(ss);
833
834
print_literal(ss,"MUST");
835
print_whsp(ss);
836
print_oids(ss,nf->nf_at_oids_must);
837
print_whsp(ss);
838
839
840
if ( nf->nf_at_oids_may ) {
841
print_literal(ss,"MAY");
842
print_whsp(ss);
843
print_oids(ss,nf->nf_at_oids_may);
844
print_whsp(ss);
845
}
846
847
print_whsp(ss);
848
print_extensions(ss, nf->nf_extensions);
849
850
print_literal(ss, /*(*/")");
851
852
bv->bv_val = safe_strdup(ss);
853
bv->bv_len = ss->pos;
854
safe_string_free(ss);
855
return(bv);
856
}
857
858
char *
859
ldap_attributetype2str( LDAPAttributeType * at )
860
{
861
struct berval bv;
862
if (ldap_attributetype2bv( at, &bv ))
863
return(bv.bv_val);
864
else
865
return NULL;
866
}
867
868
struct berval *
869
ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
870
{
871
safe_string * ss;
872
873
if ( !at || !bv )
874
return NULL;
875
876
ss = new_safe_string(256);
877
if ( !ss )
878
return NULL;
879
880
print_literal(ss,"("/*)*/);
881
print_whsp(ss);
882
883
print_numericoid(ss, at->at_oid);
884
print_whsp(ss);
885
886
if ( at->at_names ) {
887
print_literal(ss,"NAME");
888
print_qdescrs(ss,at->at_names);
889
}
890
891
if ( at->at_desc ) {
892
print_literal(ss,"DESC");
893
print_qdstring(ss,at->at_desc);
894
}
895
896
if ( at->at_obsolete ) {
897
print_literal(ss, "OBSOLETE");
898
print_whsp(ss);
899
}
900
901
if ( at->at_sup_oid ) {
902
print_literal(ss,"SUP");
903
print_woid(ss,at->at_sup_oid);
904
}
905
906
if ( at->at_equality_oid ) {
907
print_literal(ss,"EQUALITY");
908
print_woid(ss,at->at_equality_oid);
909
}
910
911
if ( at->at_ordering_oid ) {
912
print_literal(ss,"ORDERING");
913
print_woid(ss,at->at_ordering_oid);
914
}
915
916
if ( at->at_substr_oid ) {
917
print_literal(ss,"SUBSTR");
918
print_woid(ss,at->at_substr_oid);
919
}
920
921
if ( at->at_syntax_oid ) {
922
print_literal(ss,"SYNTAX");
923
print_whsp(ss);
924
print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
925
print_whsp(ss);
926
}
927
928
if ( at->at_single_value == LDAP_SCHEMA_YES ) {
929
print_literal(ss,"SINGLE-VALUE");
930
print_whsp(ss);
931
}
932
933
if ( at->at_collective == LDAP_SCHEMA_YES ) {
934
print_literal(ss,"COLLECTIVE");
935
print_whsp(ss);
936
}
937
938
if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
939
print_literal(ss,"NO-USER-MODIFICATION");
940
print_whsp(ss);
941
}
942
943
if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
944
print_literal(ss,"USAGE");
945
print_whsp(ss);
946
switch (at->at_usage) {
947
case LDAP_SCHEMA_DIRECTORY_OPERATION:
948
print_literal(ss,"directoryOperation");
949
break;
950
case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
951
print_literal(ss,"distributedOperation");
952
break;
953
case LDAP_SCHEMA_DSA_OPERATION:
954
print_literal(ss,"dSAOperation");
955
break;
956
default:
957
print_literal(ss,"UNKNOWN");
958
break;
959
}
960
}
961
962
print_whsp(ss);
963
964
print_extensions(ss, at->at_extensions);
965
966
print_literal(ss,/*(*/")");
967
968
bv->bv_val = safe_strdup(ss);
969
bv->bv_len = ss->pos;
970
safe_string_free(ss);
971
return(bv);
972
}
973
974
/*
975
* Now come the parsers. There is one parser for each entity type:
976
* objectclasses, attributetypes, etc.
977
*
978
* Each of them is written as a recursive-descent parser, except that
979
* none of them is really recursive. But the idea is kept: there
980
* is one routine per non-terminal that either gobbles lexical tokens
981
* or calls lower-level routines, etc.
982
*
983
* The scanner is implemented in the routine get_token. Actually,
984
* get_token is more than a scanner and will return tokens that are
985
* in fact non-terminals in the grammar. So you can see the whole
986
* approach as the combination of a low-level bottom-up recognizer
987
* combined with a scanner and a number of top-down parsers. Or just
988
* consider that the real grammars recognized by the parsers are not
989
* those of the standards. As a matter of fact, our parsers are more
990
* liberal than the spec when there is no ambiguity.
991
*
992
* The difference is pretty academic (modulo bugs or incorrect
993
* interpretation of the specs).
994
*/
995
996
typedef enum tk_t {
997
TK_NOENDQUOTE = -2,
998
TK_OUTOFMEM = -1,
999
TK_EOS = 0,
1000
TK_UNEXPCHAR = 1,
1001
TK_BAREWORD = 2,
1002
TK_QDSTRING = 3,
1003
TK_LEFTPAREN = 4,
1004
TK_RIGHTPAREN = 5,
1005
TK_DOLLAR = 6,
1006
TK_QDESCR = TK_QDSTRING
1007
} tk_t;
1008
1009
static tk_t
1010
get_token( const char ** sp, char ** token_val )
1011
{
1012
tk_t kind;
1013
const char * p;
1014
const char * q;
1015
char * res;
1016
1017
*token_val = NULL;
1018
switch (**sp) {
1019
case '\0':
1020
kind = TK_EOS;
1021
(*sp)++;
1022
break;
1023
case '(':
1024
kind = TK_LEFTPAREN;
1025
(*sp)++;
1026
break;
1027
case ')':
1028
kind = TK_RIGHTPAREN;
1029
(*sp)++;
1030
break;
1031
case '$':
1032
kind = TK_DOLLAR;
1033
(*sp)++;
1034
break;
1035
case '\'':
1036
kind = TK_QDSTRING;
1037
(*sp)++;
1038
p = *sp;
1039
while ( **sp != '\'' && **sp != '\0' )
1040
(*sp)++;
1041
if ( **sp == '\'' ) {
1042
q = *sp;
1043
res = LDAP_MALLOC(q-p+1);
1044
if ( !res ) {
1045
kind = TK_OUTOFMEM;
1046
} else {
1047
strncpy(res,p,q-p);
1048
res[q-p] = '\0';
1049
*token_val = res;
1050
}
1051
(*sp)++;
1052
} else {
1053
kind = TK_NOENDQUOTE;
1054
}
1055
break;
1056
default:
1057
kind = TK_BAREWORD;
1058
p = *sp;
1059
while ( !LDAP_SPACE(**sp) &&
1060
**sp != '(' &&
1061
**sp != ')' &&
1062
**sp != '$' &&
1063
**sp != '\'' &&
1064
/* for suggested minimum upper bound on the number
1065
* of characters (RFC 4517) */
1066
**sp != '{' &&
1067
**sp != '\0' )
1068
(*sp)++;
1069
q = *sp;
1070
res = LDAP_MALLOC(q-p+1);
1071
if ( !res ) {
1072
kind = TK_OUTOFMEM;
1073
} else {
1074
strncpy(res,p,q-p);
1075
res[q-p] = '\0';
1076
*token_val = res;
1077
}
1078
break;
1079
/* kind = TK_UNEXPCHAR; */
1080
/* break; */
1081
}
1082
1083
return kind;
1084
}
1085
1086
/* Gobble optional whitespace */
1087
static void
1088
parse_whsp(const char **sp)
1089
{
1090
while (LDAP_SPACE(**sp))
1091
(*sp)++;
1092
}
1093
1094
/* TBC:!!
1095
* General note for all parsers: to guarantee the algorithm halts they
1096
* must always advance the pointer even when an error is found. For
1097
* this one is not that important since an error here is fatal at the
1098
* upper layers, but it is a simple strategy that will not get in
1099
* endless loops.
1100
*/
1101
1102
/* Parse a sequence of dot-separated decimal strings */
1103
char *
1104
ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1105
{
1106
char * res = NULL;
1107
const char * start = *sp;
1108
int len;
1109
int quoted = 0;
1110
1111
/* Netscape puts the SYNTAX value in quotes (incorrectly) */
1112
if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1113
quoted = 1;
1114
(*sp)++;
1115
start++;
1116
}
1117
/* Each iteration of this loop gets one decimal string */
1118
while (**sp) {
1119
if ( !LDAP_DIGIT(**sp) ) {
1120
/*
1121
* Initial char is not a digit or char after dot is
1122
* not a digit
1123
*/
1124
*code = LDAP_SCHERR_NODIGIT;
1125
return NULL;
1126
}
1127
(*sp)++;
1128
while ( LDAP_DIGIT(**sp) )
1129
(*sp)++;
1130
if ( **sp != '.' )
1131
break;
1132
/* Otherwise, gobble the dot and loop again */
1133
(*sp)++;
1134
}
1135
/* Now *sp points at the char past the numericoid. Perfect. */
1136
len = *sp - start;
1137
if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1138
if ( **sp == '\'' ) {
1139
(*sp)++;
1140
} else {
1141
*code = LDAP_SCHERR_UNEXPTOKEN;
1142
return NULL;
1143
}
1144
}
1145
if (flags & LDAP_SCHEMA_SKIP) {
1146
res = (char *)start;
1147
} else {
1148
res = LDAP_MALLOC(len+1);
1149
if (!res) {
1150
*code = LDAP_SCHERR_OUTOFMEM;
1151
return(NULL);
1152
}
1153
strncpy(res,start,len);
1154
res[len] = '\0';
1155
}
1156
return(res);
1157
}
1158
1159
/* Parse a sequence of dot-separated decimal strings */
1160
int
1161
ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1162
{
1163
*ruleid=0;
1164
1165
if ( !LDAP_DIGIT(**sp) ) {
1166
*code = LDAP_SCHERR_NODIGIT;
1167
return -1;
1168
}
1169
*ruleid = (**sp) - '0';
1170
(*sp)++;
1171
1172
while ( LDAP_DIGIT(**sp) ) {
1173
*ruleid *= 10;
1174
*ruleid += (**sp) - '0';
1175
(*sp)++;
1176
}
1177
1178
return 0;
1179
}
1180
1181
/* Parse a qdescr or a list of them enclosed in () */
1182
static char **
1183
parse_qdescrs(const char **sp, int *code)
1184
{
1185
char ** res;
1186
char ** res1;
1187
tk_t kind;
1188
char * sval;
1189
int size;
1190
int pos;
1191
1192
parse_whsp(sp);
1193
kind = get_token(sp,&sval);
1194
if ( kind == TK_LEFTPAREN ) {
1195
/* Let's presume there will be at least 2 entries */
1196
size = 3;
1197
res = LDAP_CALLOC(3,sizeof(char *));
1198
if ( !res ) {
1199
*code = LDAP_SCHERR_OUTOFMEM;
1200
return NULL;
1201
}
1202
pos = 0;
1203
while (1) {
1204
parse_whsp(sp);
1205
kind = get_token(sp,&sval);
1206
if ( kind == TK_RIGHTPAREN )
1207
break;
1208
if ( kind == TK_QDESCR ) {
1209
if ( pos == size-2 ) {
1210
size++;
1211
res1 = LDAP_REALLOC(res,size*sizeof(char *));
1212
if ( !res1 ) {
1213
LDAP_VFREE(res);
1214
LDAP_FREE(sval);
1215
*code = LDAP_SCHERR_OUTOFMEM;
1216
return(NULL);
1217
}
1218
res = res1;
1219
}
1220
res[pos++] = sval;
1221
res[pos] = NULL;
1222
parse_whsp(sp);
1223
} else {
1224
LDAP_VFREE(res);
1225
LDAP_FREE(sval);
1226
*code = LDAP_SCHERR_UNEXPTOKEN;
1227
return(NULL);
1228
}
1229
}
1230
parse_whsp(sp);
1231
return(res);
1232
} else if ( kind == TK_QDESCR ) {
1233
res = LDAP_CALLOC(2,sizeof(char *));
1234
if ( !res ) {
1235
*code = LDAP_SCHERR_OUTOFMEM;
1236
return NULL;
1237
}
1238
res[0] = sval;
1239
res[1] = NULL;
1240
parse_whsp(sp);
1241
return res;
1242
} else {
1243
LDAP_FREE(sval);
1244
*code = LDAP_SCHERR_BADNAME;
1245
return NULL;
1246
}
1247
}
1248
1249
/* Parse a woid */
1250
static char *
1251
parse_woid(const char **sp, int *code)
1252
{
1253
char * sval;
1254
tk_t kind;
1255
1256
parse_whsp(sp);
1257
kind = get_token(sp, &sval);
1258
if ( kind != TK_BAREWORD ) {
1259
LDAP_FREE(sval);
1260
*code = LDAP_SCHERR_UNEXPTOKEN;
1261
return NULL;
1262
}
1263
parse_whsp(sp);
1264
return sval;
1265
}
1266
1267
/* Parse a noidlen */
1268
static char *
1269
parse_noidlen(const char **sp, int *code, int *len, int flags)
1270
{
1271
char * sval;
1272
const char *savepos;
1273
int quoted = 0;
1274
int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED );
1275
int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO );
1276
1277
*len = 0;
1278
/* Netscape puts the SYNTAX value in quotes (incorrectly) */
1279
if ( allow_quoted && **sp == '\'' ) {
1280
quoted = 1;
1281
(*sp)++;
1282
}
1283
savepos = *sp;
1284
sval = ldap_int_parse_numericoid(sp, code, 0);
1285
if ( !sval ) {
1286
if ( allow_oidmacro
1287
&& *sp == savepos
1288
&& *code == LDAP_SCHERR_NODIGIT )
1289
{
1290
if ( get_token(sp, &sval) != TK_BAREWORD ) {
1291
if ( sval != NULL ) {
1292
LDAP_FREE(sval);
1293
}
1294
return NULL;
1295
}
1296
} else {
1297
return NULL;
1298
}
1299
}
1300
if ( **sp == '{' /*}*/ ) {
1301
(*sp)++;
1302
*len = atoi(*sp);
1303
while ( LDAP_DIGIT(**sp) )
1304
(*sp)++;
1305
if ( **sp != /*{*/ '}' ) {
1306
*code = LDAP_SCHERR_UNEXPTOKEN;
1307
LDAP_FREE(sval);
1308
return NULL;
1309
}
1310
(*sp)++;
1311
}
1312
if ( allow_quoted && quoted ) {
1313
if ( **sp == '\'' ) {
1314
(*sp)++;
1315
} else {
1316
*code = LDAP_SCHERR_UNEXPTOKEN;
1317
LDAP_FREE(sval);
1318
return NULL;
1319
}
1320
}
1321
return sval;
1322
}
1323
1324
/*
1325
* Next routine will accept a qdstring in place of an oid if
1326
* allow_quoted is set. This is necessary to interoperate with
1327
* Netscape Directory server that will improperly quote each oid (at
1328
* least those of the descr kind) in the SUP clause.
1329
*/
1330
1331
/* Parse a woid or a $-separated list of them enclosed in () */
1332
static char **
1333
parse_oids(const char **sp, int *code, const int allow_quoted)
1334
{
1335
char ** res;
1336
char ** res1;
1337
tk_t kind;
1338
char * sval;
1339
int size;
1340
int pos;
1341
1342
/*
1343
* Strictly speaking, doing this here accepts whsp before the
1344
* ( at the beginning of an oidlist, but this is harmless. Also,
1345
* we are very liberal in what we accept as an OID. Maybe
1346
* refine later.
1347
*/
1348
parse_whsp(sp);
1349
kind = get_token(sp,&sval);
1350
if ( kind == TK_LEFTPAREN ) {
1351
/* Let's presume there will be at least 2 entries */
1352
size = 3;
1353
res = LDAP_CALLOC(3,sizeof(char *));
1354
if ( !res ) {
1355
*code = LDAP_SCHERR_OUTOFMEM;
1356
return NULL;
1357
}
1358
pos = 0;
1359
parse_whsp(sp);
1360
kind = get_token(sp,&sval);
1361
if ( kind == TK_BAREWORD ||
1362
( allow_quoted && kind == TK_QDSTRING ) ) {
1363
res[pos++] = sval;
1364
res[pos] = NULL;
1365
} else if ( kind == TK_RIGHTPAREN ) {
1366
/* FIXME: be liberal in what we accept... */
1367
parse_whsp(sp);
1368
LDAP_FREE(res);
1369
return NULL;
1370
} else {
1371
*code = LDAP_SCHERR_UNEXPTOKEN;
1372
LDAP_FREE(sval);
1373
LDAP_VFREE(res);
1374
return NULL;
1375
}
1376
parse_whsp(sp);
1377
while (1) {
1378
kind = get_token(sp,&sval);
1379
if ( kind == TK_RIGHTPAREN )
1380
break;
1381
if ( kind == TK_DOLLAR ) {
1382
parse_whsp(sp);
1383
kind = get_token(sp,&sval);
1384
if ( kind == TK_BAREWORD ||
1385
( allow_quoted &&
1386
kind == TK_QDSTRING ) ) {
1387
if ( pos == size-2 ) {
1388
size++;
1389
res1 = LDAP_REALLOC(res,size*sizeof(char *));
1390
if ( !res1 ) {
1391
LDAP_FREE(sval);
1392
LDAP_VFREE(res);
1393
*code = LDAP_SCHERR_OUTOFMEM;
1394
return(NULL);
1395
}
1396
res = res1;
1397
}
1398
res[pos++] = sval;
1399
res[pos] = NULL;
1400
} else {
1401
*code = LDAP_SCHERR_UNEXPTOKEN;
1402
LDAP_FREE(sval);
1403
LDAP_VFREE(res);
1404
return NULL;
1405
}
1406
parse_whsp(sp);
1407
} else {
1408
*code = LDAP_SCHERR_UNEXPTOKEN;
1409
LDAP_FREE(sval);
1410
LDAP_VFREE(res);
1411
return NULL;
1412
}
1413
}
1414
parse_whsp(sp);
1415
return(res);
1416
} else if ( kind == TK_BAREWORD ||
1417
( allow_quoted && kind == TK_QDSTRING ) ) {
1418
res = LDAP_CALLOC(2,sizeof(char *));
1419
if ( !res ) {
1420
LDAP_FREE(sval);
1421
*code = LDAP_SCHERR_OUTOFMEM;
1422
return NULL;
1423
}
1424
res[0] = sval;
1425
res[1] = NULL;
1426
parse_whsp(sp);
1427
return res;
1428
} else {
1429
LDAP_FREE(sval);
1430
*code = LDAP_SCHERR_BADNAME;
1431
return NULL;
1432
}
1433
}
1434
1435
static int
1436
add_extension(LDAPSchemaExtensionItem ***extensions,
1437
char * name, char ** values)
1438
{
1439
int n;
1440
LDAPSchemaExtensionItem **tmp, *ext;
1441
1442
ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1443
if ( !ext )
1444
return 1;
1445
ext->lsei_name = name;
1446
ext->lsei_values = values;
1447
1448
if ( !*extensions ) {
1449
*extensions =
1450
LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1451
if ( !*extensions ) {
1452
LDAP_FREE( ext );
1453
return 1;
1454
}
1455
n = 0;
1456
} else {
1457
for ( n=0; (*extensions)[n] != NULL; n++ )
1458
;
1459
tmp = LDAP_REALLOC(*extensions,
1460
(n+2)*sizeof(LDAPSchemaExtensionItem *));
1461
if ( !tmp ) {
1462
LDAP_FREE( ext );
1463
return 1;
1464
}
1465
*extensions = tmp;
1466
}
1467
(*extensions)[n] = ext;
1468
(*extensions)[n+1] = NULL;
1469
return 0;
1470
}
1471
1472
static void
1473
free_extensions(LDAPSchemaExtensionItem **extensions)
1474
{
1475
LDAPSchemaExtensionItem **ext;
1476
1477
if ( extensions ) {
1478
for ( ext = extensions; *ext != NULL; ext++ ) {
1479
LDAP_FREE((*ext)->lsei_name);
1480
LDAP_VFREE((*ext)->lsei_values);
1481
LDAP_FREE(*ext);
1482
}
1483
LDAP_FREE(extensions);
1484
}
1485
}
1486
1487
void
1488
ldap_syntax_free( LDAPSyntax * syn )
1489
{
1490
if ( !syn ) return;
1491
LDAP_FREE(syn->syn_oid);
1492
if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1493
if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1494
free_extensions(syn->syn_extensions);
1495
LDAP_FREE(syn);
1496
}
1497
1498
LDAPSyntax *
1499
ldap_str2syntax( LDAP_CONST char * s,
1500
int * code,
1501
LDAP_CONST char ** errp,
1502
LDAP_CONST unsigned flags )
1503
{
1504
tk_t kind;
1505
const char * ss = s;
1506
char * sval;
1507
int seen_name = 0;
1508
int seen_desc = 0;
1509
LDAPSyntax * syn;
1510
char ** ext_vals;
1511
1512
if ( !s ) {
1513
*code = LDAP_SCHERR_EMPTY;
1514
*errp = "";
1515
return NULL;
1516
}
1517
1518
*errp = s;
1519
syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1520
1521
if ( !syn ) {
1522
*code = LDAP_SCHERR_OUTOFMEM;
1523
return NULL;
1524
}
1525
1526
kind = get_token(&ss,&sval);
1527
if ( kind != TK_LEFTPAREN ) {
1528
LDAP_FREE(sval);
1529
*code = LDAP_SCHERR_NOLEFTPAREN;
1530
ldap_syntax_free(syn);
1531
return NULL;
1532
}
1533
1534
parse_whsp(&ss);
1535
syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1536
if ( !syn->syn_oid ) {
1537
*errp = ss;
1538
ldap_syntax_free(syn);
1539
return NULL;
1540
}
1541
parse_whsp(&ss);
1542
1543
/*
1544
* Beyond this point we will be liberal and accept the items
1545
* in any order.
1546
*/
1547
while (1) {
1548
kind = get_token(&ss,&sval);
1549
switch (kind) {
1550
case TK_EOS:
1551
*code = LDAP_SCHERR_NORIGHTPAREN;
1552
*errp = EndOfInput;
1553
ldap_syntax_free(syn);
1554
return NULL;
1555
case TK_RIGHTPAREN:
1556
return syn;
1557
case TK_BAREWORD:
1558
if ( !strcasecmp(sval,"NAME") ) {
1559
LDAP_FREE(sval);
1560
if ( seen_name ) {
1561
*code = LDAP_SCHERR_DUPOPT;
1562
*errp = ss;
1563
ldap_syntax_free(syn);
1564
return(NULL);
1565
}
1566
seen_name = 1;
1567
syn->syn_names = parse_qdescrs(&ss,code);
1568
if ( !syn->syn_names ) {
1569
if ( *code != LDAP_SCHERR_OUTOFMEM )
1570
*code = LDAP_SCHERR_BADNAME;
1571
*errp = ss;
1572
ldap_syntax_free(syn);
1573
return NULL;
1574
}
1575
} else if ( !strcasecmp(sval,"DESC") ) {
1576
LDAP_FREE(sval);
1577
if ( seen_desc ) {
1578
*code = LDAP_SCHERR_DUPOPT;
1579
*errp = ss;
1580
ldap_syntax_free(syn);
1581
return(NULL);
1582
}
1583
seen_desc = 1;
1584
parse_whsp(&ss);
1585
kind = get_token(&ss,&sval);
1586
if ( kind != TK_QDSTRING ) {
1587
*code = LDAP_SCHERR_UNEXPTOKEN;
1588
*errp = ss;
1589
LDAP_FREE(sval);
1590
ldap_syntax_free(syn);
1591
return NULL;
1592
}
1593
syn->syn_desc = sval;
1594
parse_whsp(&ss);
1595
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1596
/* Should be parse_qdstrings */
1597
ext_vals = parse_qdescrs(&ss, code);
1598
if ( !ext_vals ) {
1599
*errp = ss;
1600
ldap_syntax_free(syn);
1601
return NULL;
1602
}
1603
if ( add_extension(&syn->syn_extensions,
1604
sval, ext_vals) ) {
1605
*code = LDAP_SCHERR_OUTOFMEM;
1606
*errp = ss;
1607
LDAP_FREE(sval);
1608
ldap_syntax_free(syn);
1609
return NULL;
1610
}
1611
} else {
1612
*code = LDAP_SCHERR_UNEXPTOKEN;
1613
*errp = ss;
1614
LDAP_FREE(sval);
1615
ldap_syntax_free(syn);
1616
return NULL;
1617
}
1618
break;
1619
default:
1620
*code = LDAP_SCHERR_UNEXPTOKEN;
1621
*errp = ss;
1622
LDAP_FREE(sval);
1623
ldap_syntax_free(syn);
1624
return NULL;
1625
}
1626
}
1627
}
1628
1629
void
1630
ldap_matchingrule_free( LDAPMatchingRule * mr )
1631
{
1632
if (!mr) return;
1633
LDAP_FREE(mr->mr_oid);
1634
if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1635
if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1636
if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1637
free_extensions(mr->mr_extensions);
1638
LDAP_FREE(mr);
1639
}
1640
1641
LDAPMatchingRule *
1642
ldap_str2matchingrule( LDAP_CONST char * s,
1643
int * code,
1644
LDAP_CONST char ** errp,
1645
LDAP_CONST unsigned flags )
1646
{
1647
tk_t kind;
1648
const char * ss = s;
1649
char * sval;
1650
int seen_name = 0;
1651
int seen_desc = 0;
1652
int seen_obsolete = 0;
1653
int seen_syntax = 0;
1654
LDAPMatchingRule * mr;
1655
char ** ext_vals;
1656
const char * savepos;
1657
1658
if ( !s ) {
1659
*code = LDAP_SCHERR_EMPTY;
1660
*errp = "";
1661
return NULL;
1662
}
1663
1664
*errp = s;
1665
mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1666
1667
if ( !mr ) {
1668
*code = LDAP_SCHERR_OUTOFMEM;
1669
return NULL;
1670
}
1671
1672
kind = get_token(&ss,&sval);
1673
if ( kind != TK_LEFTPAREN ) {
1674
*code = LDAP_SCHERR_NOLEFTPAREN;
1675
LDAP_FREE(sval);
1676
ldap_matchingrule_free(mr);
1677
return NULL;
1678
}
1679
1680
parse_whsp(&ss);
1681
savepos = ss;
1682
mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1683
if ( !mr->mr_oid ) {
1684
if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1685
/* Backtracking */
1686
ss = savepos;
1687
kind = get_token(&ss,&sval);
1688
if ( kind == TK_BAREWORD ) {
1689
if ( !strcasecmp(sval, "NAME") ||
1690
!strcasecmp(sval, "DESC") ||
1691
!strcasecmp(sval, "OBSOLETE") ||
1692
!strcasecmp(sval, "SYNTAX") ||
1693
!strncasecmp(sval, "X-", 2) ) {
1694
/* Missing OID, backtrack */
1695
ss = savepos;
1696
} else {
1697
/* Non-numerical OID, ignore */
1698
}
1699
}
1700
LDAP_FREE(sval);
1701
} else {
1702
*errp = ss;
1703
ldap_matchingrule_free(mr);
1704
return NULL;
1705
}
1706
}
1707
parse_whsp(&ss);
1708
1709
/*
1710
* Beyond this point we will be liberal and accept the items
1711
* in any order.
1712
*/
1713
while (1) {
1714
kind = get_token(&ss,&sval);
1715
switch (kind) {
1716
case TK_EOS:
1717
*code = LDAP_SCHERR_NORIGHTPAREN;
1718
*errp = EndOfInput;
1719
ldap_matchingrule_free(mr);
1720
return NULL;
1721
case TK_RIGHTPAREN:
1722
if( !seen_syntax ) {
1723
*code = LDAP_SCHERR_MISSING;
1724
ldap_matchingrule_free(mr);
1725
return NULL;
1726
}
1727
return mr;
1728
case TK_BAREWORD:
1729
if ( !strcasecmp(sval,"NAME") ) {
1730
LDAP_FREE(sval);
1731
if ( seen_name ) {
1732
*code = LDAP_SCHERR_DUPOPT;
1733
*errp = ss;
1734
ldap_matchingrule_free(mr);
1735
return(NULL);
1736
}
1737
seen_name = 1;
1738
mr->mr_names = parse_qdescrs(&ss,code);
1739
if ( !mr->mr_names ) {
1740
if ( *code != LDAP_SCHERR_OUTOFMEM )
1741
*code = LDAP_SCHERR_BADNAME;
1742
*errp = ss;
1743
ldap_matchingrule_free(mr);
1744
return NULL;
1745
}
1746
} else if ( !strcasecmp(sval,"DESC") ) {
1747
LDAP_FREE(sval);
1748
if ( seen_desc ) {
1749
*code = LDAP_SCHERR_DUPOPT;
1750
*errp = ss;
1751
ldap_matchingrule_free(mr);
1752
return(NULL);
1753
}
1754
seen_desc = 1;
1755
parse_whsp(&ss);
1756
kind = get_token(&ss,&sval);
1757
if ( kind != TK_QDSTRING ) {
1758
*code = LDAP_SCHERR_UNEXPTOKEN;
1759
*errp = ss;
1760
LDAP_FREE(sval);
1761
ldap_matchingrule_free(mr);
1762
return NULL;
1763
}
1764
mr->mr_desc = sval;
1765
parse_whsp(&ss);
1766
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
1767
LDAP_FREE(sval);
1768
if ( seen_obsolete ) {
1769
*code = LDAP_SCHERR_DUPOPT;
1770
*errp = ss;
1771
ldap_matchingrule_free(mr);
1772
return(NULL);
1773
}
1774
seen_obsolete = 1;
1775
mr->mr_obsolete = LDAP_SCHEMA_YES;
1776
parse_whsp(&ss);
1777
} else if ( !strcasecmp(sval,"SYNTAX") ) {
1778
LDAP_FREE(sval);
1779
if ( seen_syntax ) {
1780
*code = LDAP_SCHERR_DUPOPT;
1781
*errp = ss;
1782
ldap_matchingrule_free(mr);
1783
return(NULL);
1784
}
1785
seen_syntax = 1;
1786
parse_whsp(&ss);
1787
mr->mr_syntax_oid =
1788
ldap_int_parse_numericoid(&ss,code,flags);
1789
if ( !mr->mr_syntax_oid ) {
1790
*errp = ss;
1791
ldap_matchingrule_free(mr);
1792
return NULL;
1793
}
1794
parse_whsp(&ss);
1795
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1796
/* Should be parse_qdstrings */
1797
ext_vals = parse_qdescrs(&ss, code);
1798
if ( !ext_vals ) {
1799
*errp = ss;
1800
ldap_matchingrule_free(mr);
1801
return NULL;
1802
}
1803
if ( add_extension(&mr->mr_extensions,
1804
sval, ext_vals) ) {
1805
*code = LDAP_SCHERR_OUTOFMEM;
1806
*errp = ss;
1807
LDAP_FREE(sval);
1808
ldap_matchingrule_free(mr);
1809
return NULL;
1810
}
1811
} else {
1812
*code = LDAP_SCHERR_UNEXPTOKEN;
1813
*errp = ss;
1814
LDAP_FREE(sval);
1815
ldap_matchingrule_free(mr);
1816
return NULL;
1817
}
1818
break;
1819
default:
1820
*code = LDAP_SCHERR_UNEXPTOKEN;
1821
*errp = ss;
1822
LDAP_FREE(sval);
1823
ldap_matchingrule_free(mr);
1824
return NULL;
1825
}
1826
}
1827
}
1828
1829
void
1830
ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1831
{
1832
if (!mru) return;
1833
LDAP_FREE(mru->mru_oid);
1834
if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1835
if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1836
if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1837
free_extensions(mru->mru_extensions);
1838
LDAP_FREE(mru);
1839
}
1840
1841
LDAPMatchingRuleUse *
1842
ldap_str2matchingruleuse( LDAP_CONST char * s,
1843
int * code,
1844
LDAP_CONST char ** errp,
1845
LDAP_CONST unsigned flags )
1846
{
1847
tk_t kind;
1848
const char * ss = s;
1849
char * sval;
1850
int seen_name = 0;
1851
int seen_desc = 0;
1852
int seen_obsolete = 0;
1853
int seen_applies = 0;
1854
LDAPMatchingRuleUse * mru;
1855
char ** ext_vals;
1856
const char * savepos;
1857
1858
if ( !s ) {
1859
*code = LDAP_SCHERR_EMPTY;
1860
*errp = "";
1861
return NULL;
1862
}
1863
1864
*errp = s;
1865
mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1866
1867
if ( !mru ) {
1868
*code = LDAP_SCHERR_OUTOFMEM;
1869
return NULL;
1870
}
1871
1872
kind = get_token(&ss,&sval);
1873
if ( kind != TK_LEFTPAREN ) {
1874
*code = LDAP_SCHERR_NOLEFTPAREN;
1875
LDAP_FREE(sval);
1876
ldap_matchingruleuse_free(mru);
1877
return NULL;
1878
}
1879
1880
parse_whsp(&ss);
1881
savepos = ss;
1882
mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1883
if ( !mru->mru_oid ) {
1884
if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1885
/* Backtracking */
1886
ss = savepos;
1887
kind = get_token(&ss,&sval);
1888
if ( kind == TK_BAREWORD ) {
1889
if ( !strcasecmp(sval, "NAME") ||
1890
!strcasecmp(sval, "DESC") ||
1891
!strcasecmp(sval, "OBSOLETE") ||
1892
!strcasecmp(sval, "APPLIES") ||
1893
!strncasecmp(sval, "X-", 2) ) {
1894
/* Missing OID, backtrack */
1895
ss = savepos;
1896
} else {
1897
/* Non-numerical OID, ignore */
1898
}
1899
}
1900
LDAP_FREE(sval);
1901
} else {
1902
*errp = ss;
1903
ldap_matchingruleuse_free(mru);
1904
return NULL;
1905
}
1906
}
1907
parse_whsp(&ss);
1908
1909
/*
1910
* Beyond this point we will be liberal and accept the items
1911
* in any order.
1912
*/
1913
while (1) {
1914
kind = get_token(&ss,&sval);
1915
switch (kind) {
1916
case TK_EOS:
1917
*code = LDAP_SCHERR_NORIGHTPAREN;
1918
*errp = EndOfInput;
1919
ldap_matchingruleuse_free(mru);
1920
return NULL;
1921
case TK_RIGHTPAREN:
1922
if( !seen_applies ) {
1923
*code = LDAP_SCHERR_MISSING;
1924
ldap_matchingruleuse_free(mru);
1925
return NULL;
1926
}
1927
return mru;
1928
case TK_BAREWORD:
1929
if ( !strcasecmp(sval,"NAME") ) {
1930
LDAP_FREE(sval);
1931
if ( seen_name ) {
1932
*code = LDAP_SCHERR_DUPOPT;
1933
*errp = ss;
1934
ldap_matchingruleuse_free(mru);
1935
return(NULL);
1936
}
1937
seen_name = 1;
1938
mru->mru_names = parse_qdescrs(&ss,code);
1939
if ( !mru->mru_names ) {
1940
if ( *code != LDAP_SCHERR_OUTOFMEM )
1941
*code = LDAP_SCHERR_BADNAME;
1942
*errp = ss;
1943
ldap_matchingruleuse_free(mru);
1944
return NULL;
1945
}
1946
} else if ( !strcasecmp(sval,"DESC") ) {
1947
LDAP_FREE(sval);
1948
if ( seen_desc ) {
1949
*code = LDAP_SCHERR_DUPOPT;
1950
*errp = ss;
1951
ldap_matchingruleuse_free(mru);
1952
return(NULL);
1953
}
1954
seen_desc = 1;
1955
parse_whsp(&ss);
1956
kind = get_token(&ss,&sval);
1957
if ( kind != TK_QDSTRING ) {
1958
*code = LDAP_SCHERR_UNEXPTOKEN;
1959
*errp = ss;
1960
LDAP_FREE(sval);
1961
ldap_matchingruleuse_free(mru);
1962
return NULL;
1963
}
1964
mru->mru_desc = sval;
1965
parse_whsp(&ss);
1966
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
1967
LDAP_FREE(sval);
1968
if ( seen_obsolete ) {
1969
*code = LDAP_SCHERR_DUPOPT;
1970
*errp = ss;
1971
ldap_matchingruleuse_free(mru);
1972
return(NULL);
1973
}
1974
seen_obsolete = 1;
1975
mru->mru_obsolete = LDAP_SCHEMA_YES;
1976
parse_whsp(&ss);
1977
} else if ( !strcasecmp(sval,"APPLIES") ) {
1978
LDAP_FREE(sval);
1979
if ( seen_applies ) {
1980
*code = LDAP_SCHERR_DUPOPT;
1981
*errp = ss;
1982
ldap_matchingruleuse_free(mru);
1983
return(NULL);
1984
}
1985
seen_applies = 1;
1986
mru->mru_applies_oids = parse_oids(&ss,
1987
code,
1988
flags);
1989
if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1990
*errp = ss;
1991
ldap_matchingruleuse_free(mru);
1992
return NULL;
1993
}
1994
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
1995
/* Should be parse_qdstrings */
1996
ext_vals = parse_qdescrs(&ss, code);
1997
if ( !ext_vals ) {
1998
*errp = ss;
1999
ldap_matchingruleuse_free(mru);
2000
return NULL;
2001
}
2002
if ( add_extension(&mru->mru_extensions,
2003
sval, ext_vals) ) {
2004
*code = LDAP_SCHERR_OUTOFMEM;
2005
*errp = ss;
2006
LDAP_FREE(sval);
2007
ldap_matchingruleuse_free(mru);
2008
return NULL;
2009
}
2010
} else {
2011
*code = LDAP_SCHERR_UNEXPTOKEN;
2012
*errp = ss;
2013
LDAP_FREE(sval);
2014
ldap_matchingruleuse_free(mru);
2015
return NULL;
2016
}
2017
break;
2018
default:
2019
*code = LDAP_SCHERR_UNEXPTOKEN;
2020
*errp = ss;
2021
LDAP_FREE(sval);
2022
ldap_matchingruleuse_free(mru);
2023
return NULL;
2024
}
2025
}
2026
}
2027
2028
void
2029
ldap_attributetype_free(LDAPAttributeType * at)
2030
{
2031
if (!at) return;
2032
LDAP_FREE(at->at_oid);
2033
if (at->at_names) LDAP_VFREE(at->at_names);
2034
if (at->at_desc) LDAP_FREE(at->at_desc);
2035
if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
2036
if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
2037
if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
2038
if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
2039
if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
2040
free_extensions(at->at_extensions);
2041
LDAP_FREE(at);
2042
}
2043
2044
LDAPAttributeType *
2045
ldap_str2attributetype( LDAP_CONST char * s,
2046
int * code,
2047
LDAP_CONST char ** errp,
2048
LDAP_CONST unsigned flags )
2049
{
2050
tk_t kind;
2051
const char * ss = s;
2052
char * sval;
2053
int seen_name = 0;
2054
int seen_desc = 0;
2055
int seen_obsolete = 0;
2056
int seen_sup = 0;
2057
int seen_equality = 0;
2058
int seen_ordering = 0;
2059
int seen_substr = 0;
2060
int seen_syntax = 0;
2061
int seen_usage = 0;
2062
LDAPAttributeType * at;
2063
char ** ext_vals;
2064
const char * savepos;
2065
2066
if ( !s ) {
2067
*code = LDAP_SCHERR_EMPTY;
2068
*errp = "";
2069
return NULL;
2070
}
2071
2072
*errp = s;
2073
at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2074
2075
if ( !at ) {
2076
*code = LDAP_SCHERR_OUTOFMEM;
2077
return NULL;
2078
}
2079
2080
kind = get_token(&ss,&sval);
2081
if ( kind != TK_LEFTPAREN ) {
2082
*code = LDAP_SCHERR_NOLEFTPAREN;
2083
LDAP_FREE(sval);
2084
ldap_attributetype_free(at);
2085
return NULL;
2086
}
2087
2088
/*
2089
* Definitions MUST begin with an OID in the numericoid format.
2090
* However, this routine is used by clients to parse the response
2091
* from servers and very well known servers will provide an OID
2092
* in the wrong format or even no OID at all. We do our best to
2093
* extract info from those servers.
2094
*/
2095
parse_whsp(&ss);
2096
savepos = ss;
2097
at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2098
if ( !at->at_oid ) {
2099
if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2100
| LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2101
&& (ss == savepos) )
2102
{
2103
/* Backtracking */
2104
ss = savepos;
2105
kind = get_token(&ss,&sval);
2106
if ( kind == TK_BAREWORD ) {
2107
if ( !strcasecmp(sval, "NAME") ||
2108
!strcasecmp(sval, "DESC") ||
2109
!strcasecmp(sval, "OBSOLETE") ||
2110
!strcasecmp(sval, "SUP") ||
2111
!strcasecmp(sval, "EQUALITY") ||
2112
!strcasecmp(sval, "ORDERING") ||
2113
!strcasecmp(sval, "SUBSTR") ||
2114
!strcasecmp(sval, "SYNTAX") ||
2115
!strcasecmp(sval, "SINGLE-VALUE") ||
2116
!strcasecmp(sval, "COLLECTIVE") ||
2117
!strcasecmp(sval, "NO-USER-MODIFICATION") ||
2118
!strcasecmp(sval, "USAGE") ||
2119
!strncasecmp(sval, "X-", 2) )
2120
{
2121
/* Missing OID, backtrack */
2122
ss = savepos;
2123
} else if ( flags
2124
& LDAP_SCHEMA_ALLOW_OID_MACRO)
2125
{
2126
/* Non-numerical OID ... */
2127
int len = ss-savepos;
2128
at->at_oid = LDAP_MALLOC(len+1);
2129
if ( !at->at_oid ) {
2130
ldap_attributetype_free(at);
2131
return NULL;
2132
}
2133
2134
strncpy(at->at_oid, savepos, len);
2135
at->at_oid[len] = 0;
2136
}
2137
}
2138
LDAP_FREE(sval);
2139
} else {
2140
*errp = ss;
2141
ldap_attributetype_free(at);
2142
return NULL;
2143
}
2144
}
2145
parse_whsp(&ss);
2146
2147
/*
2148
* Beyond this point we will be liberal and accept the items
2149
* in any order.
2150
*/
2151
while (1) {
2152
kind = get_token(&ss,&sval);
2153
switch (kind) {
2154
case TK_EOS:
2155
*code = LDAP_SCHERR_NORIGHTPAREN;
2156
*errp = EndOfInput;
2157
ldap_attributetype_free(at);
2158
return NULL;
2159
case TK_RIGHTPAREN:
2160
return at;
2161
case TK_BAREWORD:
2162
if ( !strcasecmp(sval,"NAME") ) {
2163
LDAP_FREE(sval);
2164
if ( seen_name ) {
2165
*code = LDAP_SCHERR_DUPOPT;
2166
*errp = ss;
2167
ldap_attributetype_free(at);
2168
return(NULL);
2169
}
2170
seen_name = 1;
2171
at->at_names = parse_qdescrs(&ss,code);
2172
if ( !at->at_names ) {
2173
if ( *code != LDAP_SCHERR_OUTOFMEM )
2174
*code = LDAP_SCHERR_BADNAME;
2175
*errp = ss;
2176
ldap_attributetype_free(at);
2177
return NULL;
2178
}
2179
} else if ( !strcasecmp(sval,"DESC") ) {
2180
LDAP_FREE(sval);
2181
if ( seen_desc ) {
2182
*code = LDAP_SCHERR_DUPOPT;
2183
*errp = ss;
2184
ldap_attributetype_free(at);
2185
return(NULL);
2186
}
2187
seen_desc = 1;
2188
parse_whsp(&ss);
2189
kind = get_token(&ss,&sval);
2190
if ( kind != TK_QDSTRING ) {
2191
*code = LDAP_SCHERR_UNEXPTOKEN;
2192
*errp = ss;
2193
LDAP_FREE(sval);
2194
ldap_attributetype_free(at);
2195
return NULL;
2196
}
2197
at->at_desc = sval;
2198
parse_whsp(&ss);
2199
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2200
LDAP_FREE(sval);
2201
if ( seen_obsolete ) {
2202
*code = LDAP_SCHERR_DUPOPT;
2203
*errp = ss;
2204
ldap_attributetype_free(at);
2205
return(NULL);
2206
}
2207
seen_obsolete = 1;
2208
at->at_obsolete = LDAP_SCHEMA_YES;
2209
parse_whsp(&ss);
2210
} else if ( !strcasecmp(sval,"SUP") ) {
2211
LDAP_FREE(sval);
2212
if ( seen_sup ) {
2213
*code = LDAP_SCHERR_DUPOPT;
2214
*errp = ss;
2215
ldap_attributetype_free(at);
2216
return(NULL);
2217
}
2218
seen_sup = 1;
2219
at->at_sup_oid = parse_woid(&ss,code);
2220
if ( !at->at_sup_oid ) {
2221
*errp = ss;
2222
ldap_attributetype_free(at);
2223
return NULL;
2224
}
2225
} else if ( !strcasecmp(sval,"EQUALITY") ) {
2226
LDAP_FREE(sval);
2227
if ( seen_equality ) {
2228
*code = LDAP_SCHERR_DUPOPT;
2229
*errp = ss;
2230
ldap_attributetype_free(at);
2231
return(NULL);
2232
}
2233
seen_equality = 1;
2234
at->at_equality_oid = parse_woid(&ss,code);
2235
if ( !at->at_equality_oid ) {
2236
*errp = ss;
2237
ldap_attributetype_free(at);
2238
return NULL;
2239
}
2240
} else if ( !strcasecmp(sval,"ORDERING") ) {
2241
LDAP_FREE(sval);
2242
if ( seen_ordering ) {
2243
*code = LDAP_SCHERR_DUPOPT;
2244
*errp = ss;
2245
ldap_attributetype_free(at);
2246
return(NULL);
2247
}
2248
seen_ordering = 1;
2249
at->at_ordering_oid = parse_woid(&ss,code);
2250
if ( !at->at_ordering_oid ) {
2251
*errp = ss;
2252
ldap_attributetype_free(at);
2253
return NULL;
2254
}
2255
} else if ( !strcasecmp(sval,"SUBSTR") ) {
2256
LDAP_FREE(sval);
2257
if ( seen_substr ) {
2258
*code = LDAP_SCHERR_DUPOPT;
2259
*errp = ss;
2260
ldap_attributetype_free(at);
2261
return(NULL);
2262
}
2263
seen_substr = 1;
2264
at->at_substr_oid = parse_woid(&ss,code);
2265
if ( !at->at_substr_oid ) {
2266
*errp = ss;
2267
ldap_attributetype_free(at);
2268
return NULL;
2269
}
2270
} else if ( !strcasecmp(sval,"SYNTAX") ) {
2271
LDAP_FREE(sval);
2272
if ( seen_syntax ) {
2273
*code = LDAP_SCHERR_DUPOPT;
2274
*errp = ss;
2275
ldap_attributetype_free(at);
2276
return(NULL);
2277
}
2278
seen_syntax = 1;
2279
parse_whsp(&ss);
2280
savepos = ss;
2281
at->at_syntax_oid =
2282
parse_noidlen(&ss,
2283
code,
2284
&at->at_syntax_len,
2285
flags);
2286
if ( !at->at_syntax_oid ) {
2287
if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2288
kind = get_token(&ss,&sval);
2289
if (kind == TK_BAREWORD)
2290
{
2291
char *sp = strchr(sval, '{');
2292
at->at_syntax_oid = sval;
2293
if (sp)
2294
{
2295
*sp++ = 0;
2296
at->at_syntax_len = atoi(sp);
2297
while ( LDAP_DIGIT(*sp) )
2298
sp++;
2299
if ( *sp != '}' ) {
2300
*code = LDAP_SCHERR_UNEXPTOKEN;
2301
*errp = ss;
2302
ldap_attributetype_free(at);
2303
return NULL;
2304
}
2305
}
2306
}
2307
} else {
2308
*errp = ss;
2309
ldap_attributetype_free(at);
2310
return NULL;
2311
}
2312
}
2313
parse_whsp(&ss);
2314
} else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2315
LDAP_FREE(sval);
2316
if ( at->at_single_value ) {
2317
*code = LDAP_SCHERR_DUPOPT;
2318
*errp = ss;
2319
ldap_attributetype_free(at);
2320
return(NULL);
2321
}
2322
at->at_single_value = LDAP_SCHEMA_YES;
2323
parse_whsp(&ss);
2324
} else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2325
LDAP_FREE(sval);
2326
if ( at->at_collective ) {
2327
*code = LDAP_SCHERR_DUPOPT;
2328
*errp = ss;
2329
ldap_attributetype_free(at);
2330
return(NULL);
2331
}
2332
at->at_collective = LDAP_SCHEMA_YES;
2333
parse_whsp(&ss);
2334
} else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2335
LDAP_FREE(sval);
2336
if ( at->at_no_user_mod ) {
2337
*code = LDAP_SCHERR_DUPOPT;
2338
*errp = ss;
2339
ldap_attributetype_free(at);
2340
return(NULL);
2341
}
2342
at->at_no_user_mod = LDAP_SCHEMA_YES;
2343
parse_whsp(&ss);
2344
} else if ( !strcasecmp(sval,"USAGE") ) {
2345
LDAP_FREE(sval);
2346
if ( seen_usage ) {
2347
*code = LDAP_SCHERR_DUPOPT;
2348
*errp = ss;
2349
ldap_attributetype_free(at);
2350
return(NULL);
2351
}
2352
seen_usage = 1;
2353
parse_whsp(&ss);
2354
kind = get_token(&ss,&sval);
2355
if ( kind != TK_BAREWORD ) {
2356
*code = LDAP_SCHERR_UNEXPTOKEN;
2357
*errp = ss;
2358
LDAP_FREE(sval);
2359
ldap_attributetype_free(at);
2360
return NULL;
2361
}
2362
if ( !strcasecmp(sval,"userApplications") )
2363
at->at_usage =
2364
LDAP_SCHEMA_USER_APPLICATIONS;
2365
else if ( !strcasecmp(sval,"directoryOperation") )
2366
at->at_usage =
2367
LDAP_SCHEMA_DIRECTORY_OPERATION;
2368
else if ( !strcasecmp(sval,"distributedOperation") )
2369
at->at_usage =
2370
LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2371
else if ( !strcasecmp(sval,"dSAOperation") )
2372
at->at_usage =
2373
LDAP_SCHEMA_DSA_OPERATION;
2374
else {
2375
*code = LDAP_SCHERR_UNEXPTOKEN;
2376
*errp = ss;
2377
LDAP_FREE(sval);
2378
ldap_attributetype_free(at);
2379
return NULL;
2380
}
2381
LDAP_FREE(sval);
2382
parse_whsp(&ss);
2383
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2384
/* Should be parse_qdstrings */
2385
ext_vals = parse_qdescrs(&ss, code);
2386
if ( !ext_vals ) {
2387
*errp = ss;
2388
ldap_attributetype_free(at);
2389
return NULL;
2390
}
2391
if ( add_extension(&at->at_extensions,
2392
sval, ext_vals) ) {
2393
*code = LDAP_SCHERR_OUTOFMEM;
2394
*errp = ss;
2395
LDAP_FREE(sval);
2396
ldap_attributetype_free(at);
2397
return NULL;
2398
}
2399
} else {
2400
*code = LDAP_SCHERR_UNEXPTOKEN;
2401
*errp = ss;
2402
LDAP_FREE(sval);
2403
ldap_attributetype_free(at);
2404
return NULL;
2405
}
2406
break;
2407
default:
2408
*code = LDAP_SCHERR_UNEXPTOKEN;
2409
*errp = ss;
2410
LDAP_FREE(sval);
2411
ldap_attributetype_free(at);
2412
return NULL;
2413
}
2414
}
2415
}
2416
2417
void
2418
ldap_objectclass_free(LDAPObjectClass * oc)
2419
{
2420
if (!oc) return;
2421
LDAP_FREE(oc->oc_oid);
2422
if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2423
if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2424
if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2425
if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2426
if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2427
free_extensions(oc->oc_extensions);
2428
LDAP_FREE(oc);
2429
}
2430
2431
LDAPObjectClass *
2432
ldap_str2objectclass( LDAP_CONST char * s,
2433
int * code,
2434
LDAP_CONST char ** errp,
2435
LDAP_CONST unsigned flags )
2436
{
2437
tk_t kind;
2438
const char * ss = s;
2439
char * sval;
2440
int seen_name = 0;
2441
int seen_desc = 0;
2442
int seen_obsolete = 0;
2443
int seen_sup = 0;
2444
int seen_kind = 0;
2445
int seen_must = 0;
2446
int seen_may = 0;
2447
LDAPObjectClass * oc;
2448
char ** ext_vals;
2449
const char * savepos;
2450
2451
if ( !s ) {
2452
*code = LDAP_SCHERR_EMPTY;
2453
*errp = "";
2454
return NULL;
2455
}
2456
2457
*errp = s;
2458
oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2459
2460
if ( !oc ) {
2461
*code = LDAP_SCHERR_OUTOFMEM;
2462
return NULL;
2463
}
2464
oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2465
2466
kind = get_token(&ss,&sval);
2467
if ( kind != TK_LEFTPAREN ) {
2468
*code = LDAP_SCHERR_NOLEFTPAREN;
2469
LDAP_FREE(sval);
2470
ldap_objectclass_free(oc);
2471
return NULL;
2472
}
2473
2474
/*
2475
* Definitions MUST begin with an OID in the numericoid format.
2476
* However, this routine is used by clients to parse the response
2477
* from servers and very well known servers will provide an OID
2478
* in the wrong format or even no OID at all. We do our best to
2479
* extract info from those servers.
2480
*/
2481
parse_whsp(&ss);
2482
savepos = ss;
2483
oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2484
if ( !oc->oc_oid ) {
2485
if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2486
/* Backtracking */
2487
ss = savepos;
2488
kind = get_token(&ss,&sval);
2489
if ( kind == TK_BAREWORD ) {
2490
if ( !strcasecmp(sval, "NAME") ||
2491
!strcasecmp(sval, "DESC") ||
2492
!strcasecmp(sval, "OBSOLETE") ||
2493
!strcasecmp(sval, "SUP") ||
2494
!strcasecmp(sval, "ABSTRACT") ||
2495
!strcasecmp(sval, "STRUCTURAL") ||
2496
!strcasecmp(sval, "AUXILIARY") ||
2497
!strcasecmp(sval, "MUST") ||
2498
!strcasecmp(sval, "MAY") ||
2499
!strncasecmp(sval, "X-", 2) ) {
2500
/* Missing OID, backtrack */
2501
ss = savepos;
2502
} else if ( flags &
2503
LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2504
/* Non-numerical OID, ignore */
2505
int len = ss-savepos;
2506
oc->oc_oid = LDAP_MALLOC(len+1);
2507
if ( !oc->oc_oid ) {
2508
ldap_objectclass_free(oc);
2509
return NULL;
2510
}
2511
2512
strncpy(oc->oc_oid, savepos, len);
2513
oc->oc_oid[len] = 0;
2514
}
2515
}
2516
LDAP_FREE(sval);
2517
*code = 0;
2518
} else {
2519
*errp = ss;
2520
ldap_objectclass_free(oc);
2521
return NULL;
2522
}
2523
}
2524
parse_whsp(&ss);
2525
2526
/*
2527
* Beyond this point we will be liberal an accept the items
2528
* in any order.
2529
*/
2530
while (1) {
2531
kind = get_token(&ss,&sval);
2532
switch (kind) {
2533
case TK_EOS:
2534
*code = LDAP_SCHERR_NORIGHTPAREN;
2535
*errp = EndOfInput;
2536
ldap_objectclass_free(oc);
2537
return NULL;
2538
case TK_RIGHTPAREN:
2539
return oc;
2540
case TK_BAREWORD:
2541
if ( !strcasecmp(sval,"NAME") ) {
2542
LDAP_FREE(sval);
2543
if ( seen_name ) {
2544
*code = LDAP_SCHERR_DUPOPT;
2545
*errp = ss;
2546
ldap_objectclass_free(oc);
2547
return(NULL);
2548
}
2549
seen_name = 1;
2550
oc->oc_names = parse_qdescrs(&ss,code);
2551
if ( !oc->oc_names ) {
2552
if ( *code != LDAP_SCHERR_OUTOFMEM )
2553
*code = LDAP_SCHERR_BADNAME;
2554
*errp = ss;
2555
ldap_objectclass_free(oc);
2556
return NULL;
2557
}
2558
} else if ( !strcasecmp(sval,"DESC") ) {
2559
LDAP_FREE(sval);
2560
if ( seen_desc ) {
2561
*code = LDAP_SCHERR_DUPOPT;
2562
*errp = ss;
2563
ldap_objectclass_free(oc);
2564
return(NULL);
2565
}
2566
seen_desc = 1;
2567
parse_whsp(&ss);
2568
kind = get_token(&ss,&sval);
2569
if ( kind != TK_QDSTRING ) {
2570
*code = LDAP_SCHERR_UNEXPTOKEN;
2571
*errp = ss;
2572
LDAP_FREE(sval);
2573
ldap_objectclass_free(oc);
2574
return NULL;
2575
}
2576
oc->oc_desc = sval;
2577
parse_whsp(&ss);
2578
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2579
LDAP_FREE(sval);
2580
if ( seen_obsolete ) {
2581
*code = LDAP_SCHERR_DUPOPT;
2582
*errp = ss;
2583
ldap_objectclass_free(oc);
2584
return(NULL);
2585
}
2586
seen_obsolete = 1;
2587
oc->oc_obsolete = LDAP_SCHEMA_YES;
2588
parse_whsp(&ss);
2589
} else if ( !strcasecmp(sval,"SUP") ) {
2590
LDAP_FREE(sval);
2591
if ( seen_sup ) {
2592
*code = LDAP_SCHERR_DUPOPT;
2593
*errp = ss;
2594
ldap_objectclass_free(oc);
2595
return(NULL);
2596
}
2597
seen_sup = 1;
2598
oc->oc_sup_oids = parse_oids(&ss,
2599
code,
2600
flags);
2601
if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2602
*errp = ss;
2603
ldap_objectclass_free(oc);
2604
return NULL;
2605
}
2606
*code = 0;
2607
} else if ( !strcasecmp(sval,"ABSTRACT") ) {
2608
LDAP_FREE(sval);
2609
if ( seen_kind ) {
2610
*code = LDAP_SCHERR_DUPOPT;
2611
*errp = ss;
2612
ldap_objectclass_free(oc);
2613
return(NULL);
2614
}
2615
seen_kind = 1;
2616
oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2617
parse_whsp(&ss);
2618
} else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2619
LDAP_FREE(sval);
2620
if ( seen_kind ) {
2621
*code = LDAP_SCHERR_DUPOPT;
2622
*errp = ss;
2623
ldap_objectclass_free(oc);
2624
return(NULL);
2625
}
2626
seen_kind = 1;
2627
oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2628
parse_whsp(&ss);
2629
} else if ( !strcasecmp(sval,"AUXILIARY") ) {
2630
LDAP_FREE(sval);
2631
if ( seen_kind ) {
2632
*code = LDAP_SCHERR_DUPOPT;
2633
*errp = ss;
2634
ldap_objectclass_free(oc);
2635
return(NULL);
2636
}
2637
seen_kind = 1;
2638
oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2639
parse_whsp(&ss);
2640
} else if ( !strcasecmp(sval,"MUST") ) {
2641
LDAP_FREE(sval);
2642
if ( seen_must ) {
2643
*code = LDAP_SCHERR_DUPOPT;
2644
*errp = ss;
2645
ldap_objectclass_free(oc);
2646
return(NULL);
2647
}
2648
seen_must = 1;
2649
oc->oc_at_oids_must = parse_oids(&ss,code,0);
2650
if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2651
*errp = ss;
2652
ldap_objectclass_free(oc);
2653
return NULL;
2654
}
2655
*code = 0;
2656
parse_whsp(&ss);
2657
} else if ( !strcasecmp(sval,"MAY") ) {
2658
LDAP_FREE(sval);
2659
if ( seen_may ) {
2660
*code = LDAP_SCHERR_DUPOPT;
2661
*errp = ss;
2662
ldap_objectclass_free(oc);
2663
return(NULL);
2664
}
2665
seen_may = 1;
2666
oc->oc_at_oids_may = parse_oids(&ss,code,0);
2667
if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2668
*errp = ss;
2669
ldap_objectclass_free(oc);
2670
return NULL;
2671
}
2672
*code = 0;
2673
parse_whsp(&ss);
2674
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2675
/* Should be parse_qdstrings */
2676
ext_vals = parse_qdescrs(&ss, code);
2677
*code = 0;
2678
if ( !ext_vals ) {
2679
*errp = ss;
2680
ldap_objectclass_free(oc);
2681
return NULL;
2682
}
2683
if ( add_extension(&oc->oc_extensions,
2684
sval, ext_vals) ) {
2685
*code = LDAP_SCHERR_OUTOFMEM;
2686
*errp = ss;
2687
LDAP_FREE(sval);
2688
ldap_objectclass_free(oc);
2689
return NULL;
2690
}
2691
} else {
2692
*code = LDAP_SCHERR_UNEXPTOKEN;
2693
*errp = ss;
2694
LDAP_FREE(sval);
2695
ldap_objectclass_free(oc);
2696
return NULL;
2697
}
2698
break;
2699
default:
2700
*code = LDAP_SCHERR_UNEXPTOKEN;
2701
*errp = ss;
2702
LDAP_FREE(sval);
2703
ldap_objectclass_free(oc);
2704
return NULL;
2705
}
2706
}
2707
}
2708
2709
void
2710
ldap_contentrule_free(LDAPContentRule * cr)
2711
{
2712
if (!cr) return;
2713
LDAP_FREE(cr->cr_oid);
2714
if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2715
if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2716
if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2717
if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2718
if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2719
if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2720
free_extensions(cr->cr_extensions);
2721
LDAP_FREE(cr);
2722
}
2723
2724
LDAPContentRule *
2725
ldap_str2contentrule( LDAP_CONST char * s,
2726
int * code,
2727
LDAP_CONST char ** errp,
2728
LDAP_CONST unsigned flags )
2729
{
2730
tk_t kind;
2731
const char * ss = s;
2732
char * sval;
2733
int seen_name = 0;
2734
int seen_desc = 0;
2735
int seen_obsolete = 0;
2736
int seen_aux = 0;
2737
int seen_must = 0;
2738
int seen_may = 0;
2739
int seen_not = 0;
2740
LDAPContentRule * cr;
2741
char ** ext_vals;
2742
const char * savepos;
2743
2744
if ( !s ) {
2745
*code = LDAP_SCHERR_EMPTY;
2746
*errp = "";
2747
return NULL;
2748
}
2749
2750
*errp = s;
2751
cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2752
2753
if ( !cr ) {
2754
*code = LDAP_SCHERR_OUTOFMEM;
2755
return NULL;
2756
}
2757
2758
kind = get_token(&ss,&sval);
2759
if ( kind != TK_LEFTPAREN ) {
2760
*code = LDAP_SCHERR_NOLEFTPAREN;
2761
LDAP_FREE(sval);
2762
ldap_contentrule_free(cr);
2763
return NULL;
2764
}
2765
2766
/*
2767
* Definitions MUST begin with an OID in the numericoid format.
2768
*/
2769
parse_whsp(&ss);
2770
savepos = ss;
2771
cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2772
if ( !cr->cr_oid ) {
2773
if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2774
/* Backtracking */
2775
ss = savepos;
2776
kind = get_token(&ss,&sval);
2777
if ( kind == TK_BAREWORD ) {
2778
if ( !strcasecmp(sval, "NAME") ||
2779
!strcasecmp(sval, "DESC") ||
2780
!strcasecmp(sval, "OBSOLETE") ||
2781
!strcasecmp(sval, "AUX") ||
2782
!strcasecmp(sval, "MUST") ||
2783
!strcasecmp(sval, "MAY") ||
2784
!strcasecmp(sval, "NOT") ||
2785
!strncasecmp(sval, "X-", 2) ) {
2786
/* Missing OID, backtrack */
2787
ss = savepos;
2788
} else if ( flags &
2789
LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2790
/* Non-numerical OID, ignore */
2791
int len = ss-savepos;
2792
cr->cr_oid = LDAP_MALLOC(len+1);
2793
if ( !cr->cr_oid ) {
2794
ldap_contentrule_free(cr);
2795
return NULL;
2796
}
2797
2798
strncpy(cr->cr_oid, savepos, len);
2799
cr->cr_oid[len] = 0;
2800
}
2801
}
2802
LDAP_FREE(sval);
2803
} else {
2804
*errp = ss;
2805
ldap_contentrule_free(cr);
2806
return NULL;
2807
}
2808
}
2809
parse_whsp(&ss);
2810
2811
/*
2812
* Beyond this point we will be liberal an accept the items
2813
* in any order.
2814
*/
2815
while (1) {
2816
kind = get_token(&ss,&sval);
2817
switch (kind) {
2818
case TK_EOS:
2819
*code = LDAP_SCHERR_NORIGHTPAREN;
2820
*errp = EndOfInput;
2821
ldap_contentrule_free(cr);
2822
return NULL;
2823
case TK_RIGHTPAREN:
2824
return cr;
2825
case TK_BAREWORD:
2826
if ( !strcasecmp(sval,"NAME") ) {
2827
LDAP_FREE(sval);
2828
if ( seen_name ) {
2829
*code = LDAP_SCHERR_DUPOPT;
2830
*errp = ss;
2831
ldap_contentrule_free(cr);
2832
return(NULL);
2833
}
2834
seen_name = 1;
2835
cr->cr_names = parse_qdescrs(&ss,code);
2836
if ( !cr->cr_names ) {
2837
if ( *code != LDAP_SCHERR_OUTOFMEM )
2838
*code = LDAP_SCHERR_BADNAME;
2839
*errp = ss;
2840
ldap_contentrule_free(cr);
2841
return NULL;
2842
}
2843
} else if ( !strcasecmp(sval,"DESC") ) {
2844
LDAP_FREE(sval);
2845
if ( seen_desc ) {
2846
*code = LDAP_SCHERR_DUPOPT;
2847
*errp = ss;
2848
ldap_contentrule_free(cr);
2849
return(NULL);
2850
}
2851
seen_desc = 1;
2852
parse_whsp(&ss);
2853
kind = get_token(&ss,&sval);
2854
if ( kind != TK_QDSTRING ) {
2855
*code = LDAP_SCHERR_UNEXPTOKEN;
2856
*errp = ss;
2857
LDAP_FREE(sval);
2858
ldap_contentrule_free(cr);
2859
return NULL;
2860
}
2861
cr->cr_desc = sval;
2862
parse_whsp(&ss);
2863
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
2864
LDAP_FREE(sval);
2865
if ( seen_obsolete ) {
2866
*code = LDAP_SCHERR_DUPOPT;
2867
*errp = ss;
2868
ldap_contentrule_free(cr);
2869
return(NULL);
2870
}
2871
seen_obsolete = 1;
2872
cr->cr_obsolete = LDAP_SCHEMA_YES;
2873
parse_whsp(&ss);
2874
} else if ( !strcasecmp(sval,"AUX") ) {
2875
LDAP_FREE(sval);
2876
if ( seen_aux ) {
2877
*code = LDAP_SCHERR_DUPOPT;
2878
*errp = ss;
2879
ldap_contentrule_free(cr);
2880
return(NULL);
2881
}
2882
seen_aux = 1;
2883
cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2884
if ( !cr->cr_oc_oids_aux ) {
2885
*errp = ss;
2886
ldap_contentrule_free(cr);
2887
return NULL;
2888
}
2889
parse_whsp(&ss);
2890
} else if ( !strcasecmp(sval,"MUST") ) {
2891
LDAP_FREE(sval);
2892
if ( seen_must ) {
2893
*code = LDAP_SCHERR_DUPOPT;
2894
*errp = ss;
2895
ldap_contentrule_free(cr);
2896
return(NULL);
2897
}
2898
seen_must = 1;
2899
cr->cr_at_oids_must = parse_oids(&ss,code,0);
2900
if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2901
*errp = ss;
2902
ldap_contentrule_free(cr);
2903
return NULL;
2904
}
2905
parse_whsp(&ss);
2906
} else if ( !strcasecmp(sval,"MAY") ) {
2907
LDAP_FREE(sval);
2908
if ( seen_may ) {
2909
*code = LDAP_SCHERR_DUPOPT;
2910
*errp = ss;
2911
ldap_contentrule_free(cr);
2912
return(NULL);
2913
}
2914
seen_may = 1;
2915
cr->cr_at_oids_may = parse_oids(&ss,code,0);
2916
if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2917
*errp = ss;
2918
ldap_contentrule_free(cr);
2919
return NULL;
2920
}
2921
parse_whsp(&ss);
2922
} else if ( !strcasecmp(sval,"NOT") ) {
2923
LDAP_FREE(sval);
2924
if ( seen_not ) {
2925
*code = LDAP_SCHERR_DUPOPT;
2926
*errp = ss;
2927
ldap_contentrule_free(cr);
2928
return(NULL);
2929
}
2930
seen_not = 1;
2931
cr->cr_at_oids_not = parse_oids(&ss,code,0);
2932
if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2933
*errp = ss;
2934
ldap_contentrule_free(cr);
2935
return NULL;
2936
}
2937
parse_whsp(&ss);
2938
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
2939
/* Should be parse_qdstrings */
2940
ext_vals = parse_qdescrs(&ss, code);
2941
if ( !ext_vals ) {
2942
*errp = ss;
2943
ldap_contentrule_free(cr);
2944
return NULL;
2945
}
2946
if ( add_extension(&cr->cr_extensions,
2947
sval, ext_vals) ) {
2948
*code = LDAP_SCHERR_OUTOFMEM;
2949
*errp = ss;
2950
LDAP_FREE(sval);
2951
ldap_contentrule_free(cr);
2952
return NULL;
2953
}
2954
} else {
2955
*code = LDAP_SCHERR_UNEXPTOKEN;
2956
*errp = ss;
2957
LDAP_FREE(sval);
2958
ldap_contentrule_free(cr);
2959
return NULL;
2960
}
2961
break;
2962
default:
2963
*code = LDAP_SCHERR_UNEXPTOKEN;
2964
*errp = ss;
2965
LDAP_FREE(sval);
2966
ldap_contentrule_free(cr);
2967
return NULL;
2968
}
2969
}
2970
}
2971
2972
void
2973
ldap_structurerule_free(LDAPStructureRule * sr)
2974
{
2975
if (!sr) return;
2976
if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2977
if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2978
if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2979
if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2980
free_extensions(sr->sr_extensions);
2981
LDAP_FREE(sr);
2982
}
2983
2984
LDAPStructureRule *
2985
ldap_str2structurerule( LDAP_CONST char * s,
2986
int * code,
2987
LDAP_CONST char ** errp,
2988
LDAP_CONST unsigned flags )
2989
{
2990
tk_t kind;
2991
int ret;
2992
const char * ss = s;
2993
char * sval;
2994
int seen_name = 0;
2995
int seen_desc = 0;
2996
int seen_obsolete = 0;
2997
int seen_nameform = 0;
2998
LDAPStructureRule * sr;
2999
char ** ext_vals;
3000
const char * savepos;
3001
3002
if ( !s ) {
3003
*code = LDAP_SCHERR_EMPTY;
3004
*errp = "";
3005
return NULL;
3006
}
3007
3008
*errp = s;
3009
sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
3010
3011
if ( !sr ) {
3012
*code = LDAP_SCHERR_OUTOFMEM;
3013
return NULL;
3014
}
3015
3016
kind = get_token(&ss,&sval);
3017
if ( kind != TK_LEFTPAREN ) {
3018
*code = LDAP_SCHERR_NOLEFTPAREN;
3019
LDAP_FREE(sval);
3020
ldap_structurerule_free(sr);
3021
return NULL;
3022
}
3023
3024
/*
3025
* Definitions MUST begin with a ruleid.
3026
*/
3027
parse_whsp(&ss);
3028
savepos = ss;
3029
ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
3030
if ( ret ) {
3031
*errp = ss;
3032
ldap_structurerule_free(sr);
3033
return NULL;
3034
}
3035
parse_whsp(&ss);
3036
3037
/*
3038
* Beyond this point we will be liberal an accept the items
3039
* in any order.
3040
*/
3041
while (1) {
3042
kind = get_token(&ss,&sval);
3043
switch (kind) {
3044
case TK_EOS:
3045
*code = LDAP_SCHERR_NORIGHTPAREN;
3046
*errp = EndOfInput;
3047
ldap_structurerule_free(sr);
3048
return NULL;
3049
case TK_RIGHTPAREN:
3050
if( !seen_nameform ) {
3051
*code = LDAP_SCHERR_MISSING;
3052
ldap_structurerule_free(sr);
3053
return NULL;
3054
}
3055
return sr;
3056
case TK_BAREWORD:
3057
if ( !strcasecmp(sval,"NAME") ) {
3058
LDAP_FREE(sval);
3059
if ( seen_name ) {
3060
*code = LDAP_SCHERR_DUPOPT;
3061
*errp = ss;
3062
ldap_structurerule_free(sr);
3063
return(NULL);
3064
}
3065
seen_name = 1;
3066
sr->sr_names = parse_qdescrs(&ss,code);
3067
if ( !sr->sr_names ) {
3068
if ( *code != LDAP_SCHERR_OUTOFMEM )
3069
*code = LDAP_SCHERR_BADNAME;
3070
*errp = ss;
3071
ldap_structurerule_free(sr);
3072
return NULL;
3073
}
3074
} else if ( !strcasecmp(sval,"DESC") ) {
3075
LDAP_FREE(sval);
3076
if ( seen_desc ) {
3077
*code = LDAP_SCHERR_DUPOPT;
3078
*errp = ss;
3079
ldap_structurerule_free(sr);
3080
return(NULL);
3081
}
3082
seen_desc = 1;
3083
parse_whsp(&ss);
3084
kind = get_token(&ss,&sval);
3085
if ( kind != TK_QDSTRING ) {
3086
*code = LDAP_SCHERR_UNEXPTOKEN;
3087
*errp = ss;
3088
LDAP_FREE(sval);
3089
ldap_structurerule_free(sr);
3090
return NULL;
3091
}
3092
sr->sr_desc = sval;
3093
parse_whsp(&ss);
3094
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
3095
LDAP_FREE(sval);
3096
if ( seen_obsolete ) {
3097
*code = LDAP_SCHERR_DUPOPT;
3098
*errp = ss;
3099
ldap_structurerule_free(sr);
3100
return(NULL);
3101
}
3102
seen_obsolete = 1;
3103
sr->sr_obsolete = LDAP_SCHEMA_YES;
3104
parse_whsp(&ss);
3105
} else if ( !strcasecmp(sval,"FORM") ) {
3106
LDAP_FREE(sval);
3107
if ( seen_nameform ) {
3108
*code = LDAP_SCHERR_DUPOPT;
3109
*errp = ss;
3110
ldap_structurerule_free(sr);
3111
return(NULL);
3112
}
3113
seen_nameform = 1;
3114
sr->sr_nameform = parse_woid(&ss,code);
3115
if ( !sr->sr_nameform ) {
3116
*errp = ss;
3117
ldap_structurerule_free(sr);
3118
return NULL;
3119
}
3120
parse_whsp(&ss);
3121
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
3122
/* Should be parse_qdstrings */
3123
ext_vals = parse_qdescrs(&ss, code);
3124
if ( !ext_vals ) {
3125
*errp = ss;
3126
ldap_structurerule_free(sr);
3127
return NULL;
3128
}
3129
if ( add_extension(&sr->sr_extensions,
3130
sval, ext_vals) ) {
3131
*code = LDAP_SCHERR_OUTOFMEM;
3132
*errp = ss;
3133
LDAP_FREE(sval);
3134
ldap_structurerule_free(sr);
3135
return NULL;
3136
}
3137
} else {
3138
*code = LDAP_SCHERR_UNEXPTOKEN;
3139
*errp = ss;
3140
LDAP_FREE(sval);
3141
ldap_structurerule_free(sr);
3142
return NULL;
3143
}
3144
break;
3145
default:
3146
*code = LDAP_SCHERR_UNEXPTOKEN;
3147
*errp = ss;
3148
LDAP_FREE(sval);
3149
ldap_structurerule_free(sr);
3150
return NULL;
3151
}
3152
}
3153
}
3154
3155
void
3156
ldap_nameform_free(LDAPNameForm * nf)
3157
{
3158
if (!nf) return;
3159
LDAP_FREE(nf->nf_oid);
3160
if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3161
if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3162
if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3163
if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3164
if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3165
free_extensions(nf->nf_extensions);
3166
LDAP_FREE(nf);
3167
}
3168
3169
LDAPNameForm *
3170
ldap_str2nameform( LDAP_CONST char * s,
3171
int * code,
3172
LDAP_CONST char ** errp,
3173
LDAP_CONST unsigned flags )
3174
{
3175
tk_t kind;
3176
const char * ss = s;
3177
char * sval;
3178
int seen_name = 0;
3179
int seen_desc = 0;
3180
int seen_obsolete = 0;
3181
int seen_class = 0;
3182
int seen_must = 0;
3183
int seen_may = 0;
3184
LDAPNameForm * nf;
3185
char ** ext_vals;
3186
const char * savepos;
3187
3188
if ( !s ) {
3189
*code = LDAP_SCHERR_EMPTY;
3190
*errp = "";
3191
return NULL;
3192
}
3193
3194
*errp = s;
3195
nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3196
3197
if ( !nf ) {
3198
*code = LDAP_SCHERR_OUTOFMEM;
3199
return NULL;
3200
}
3201
3202
kind = get_token(&ss,&sval);
3203
if ( kind != TK_LEFTPAREN ) {
3204
*code = LDAP_SCHERR_NOLEFTPAREN;
3205
LDAP_FREE(sval);
3206
ldap_nameform_free(nf);
3207
return NULL;
3208
}
3209
3210
/*
3211
* Definitions MUST begin with an OID in the numericoid format.
3212
* However, this routine is used by clients to parse the response
3213
* from servers and very well known servers will provide an OID
3214
* in the wrong format or even no OID at all. We do our best to
3215
* extract info from those servers.
3216
*/
3217
parse_whsp(&ss);
3218
savepos = ss;
3219
nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3220
if ( !nf->nf_oid ) {
3221
*errp = ss;
3222
ldap_nameform_free(nf);
3223
return NULL;
3224
}
3225
parse_whsp(&ss);
3226
3227
/*
3228
* Beyond this point we will be liberal an accept the items
3229
* in any order.
3230
*/
3231
while (1) {
3232
kind = get_token(&ss,&sval);
3233
switch (kind) {
3234
case TK_EOS:
3235
*code = LDAP_SCHERR_NORIGHTPAREN;
3236
*errp = EndOfInput;
3237
ldap_nameform_free(nf);
3238
return NULL;
3239
case TK_RIGHTPAREN:
3240
if( !seen_class || !seen_must ) {
3241
*code = LDAP_SCHERR_MISSING;
3242
ldap_nameform_free(nf);
3243
return NULL;
3244
}
3245
return nf;
3246
case TK_BAREWORD:
3247
if ( !strcasecmp(sval,"NAME") ) {
3248
LDAP_FREE(sval);
3249
if ( seen_name ) {
3250
*code = LDAP_SCHERR_DUPOPT;
3251
*errp = ss;
3252
ldap_nameform_free(nf);
3253
return(NULL);
3254
}
3255
seen_name = 1;
3256
nf->nf_names = parse_qdescrs(&ss,code);
3257
if ( !nf->nf_names ) {
3258
if ( *code != LDAP_SCHERR_OUTOFMEM )
3259
*code = LDAP_SCHERR_BADNAME;
3260
*errp = ss;
3261
ldap_nameform_free(nf);
3262
return NULL;
3263
}
3264
} else if ( !strcasecmp(sval,"DESC") ) {
3265
LDAP_FREE(sval);
3266
if ( seen_desc ) {
3267
*code = LDAP_SCHERR_DUPOPT;
3268
*errp = ss;
3269
ldap_nameform_free(nf);
3270
return(NULL);
3271
}
3272
seen_desc = 1;
3273
parse_whsp(&ss);
3274
kind = get_token(&ss,&sval);
3275
if ( kind != TK_QDSTRING ) {
3276
*code = LDAP_SCHERR_UNEXPTOKEN;
3277
*errp = ss;
3278
LDAP_FREE(sval);
3279
ldap_nameform_free(nf);
3280
return NULL;
3281
}
3282
nf->nf_desc = sval;
3283
parse_whsp(&ss);
3284
} else if ( !strcasecmp(sval,"OBSOLETE") ) {
3285
LDAP_FREE(sval);
3286
if ( seen_obsolete ) {
3287
*code = LDAP_SCHERR_DUPOPT;
3288
*errp = ss;
3289
ldap_nameform_free(nf);
3290
return(NULL);
3291
}
3292
seen_obsolete = 1;
3293
nf->nf_obsolete = LDAP_SCHEMA_YES;
3294
parse_whsp(&ss);
3295
} else if ( !strcasecmp(sval,"OC") ) {
3296
LDAP_FREE(sval);
3297
if ( seen_class ) {
3298
*code = LDAP_SCHERR_DUPOPT;
3299
*errp = ss;
3300
ldap_nameform_free(nf);
3301
return(NULL);
3302
}
3303
seen_class = 1;
3304
nf->nf_objectclass = parse_woid(&ss,code);
3305
if ( !nf->nf_objectclass ) {
3306
*errp = ss;
3307
ldap_nameform_free(nf);
3308
return NULL;
3309
}
3310
} else if ( !strcasecmp(sval,"MUST") ) {
3311
LDAP_FREE(sval);
3312
if ( seen_must ) {
3313
*code = LDAP_SCHERR_DUPOPT;
3314
*errp = ss;
3315
ldap_nameform_free(nf);
3316
return(NULL);
3317
}
3318
seen_must = 1;
3319
nf->nf_at_oids_must = parse_oids(&ss,code,0);
3320
if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3321
*errp = ss;
3322
ldap_nameform_free(nf);
3323
return NULL;
3324
}
3325
parse_whsp(&ss);
3326
} else if ( !strcasecmp(sval,"MAY") ) {
3327
LDAP_FREE(sval);
3328
if ( seen_may ) {
3329
*code = LDAP_SCHERR_DUPOPT;
3330
*errp = ss;
3331
ldap_nameform_free(nf);
3332
return(NULL);
3333
}
3334
seen_may = 1;
3335
nf->nf_at_oids_may = parse_oids(&ss,code,0);
3336
if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3337
*errp = ss;
3338
ldap_nameform_free(nf);
3339
return NULL;
3340
}
3341
parse_whsp(&ss);
3342
} else if ( sval[0] == 'X' && sval[1] == '-' ) {
3343
/* Should be parse_qdstrings */
3344
ext_vals = parse_qdescrs(&ss, code);
3345
if ( !ext_vals ) {
3346
*errp = ss;
3347
ldap_nameform_free(nf);
3348
return NULL;
3349
}
3350
if ( add_extension(&nf->nf_extensions,
3351
sval, ext_vals) ) {
3352
*code = LDAP_SCHERR_OUTOFMEM;
3353
*errp = ss;
3354
LDAP_FREE(sval);
3355
ldap_nameform_free(nf);
3356
return NULL;
3357
}
3358
} else {
3359
*code = LDAP_SCHERR_UNEXPTOKEN;
3360
*errp = ss;
3361
LDAP_FREE(sval);
3362
ldap_nameform_free(nf);
3363
return NULL;
3364
}
3365
break;
3366
default:
3367
*code = LDAP_SCHERR_UNEXPTOKEN;
3368
*errp = ss;
3369
LDAP_FREE(sval);
3370
ldap_nameform_free(nf);
3371
return NULL;
3372
}
3373
}
3374
}
3375
3376
static char *const err2text[] = {
3377
N_("Success"),
3378
N_("Out of memory"),
3379
N_("Unexpected token"),
3380
N_("Missing opening parenthesis"),
3381
N_("Missing closing parenthesis"),
3382
N_("Expecting digit"),
3383
N_("Expecting a name"),
3384
N_("Bad description"),
3385
N_("Bad superiors"),
3386
N_("Duplicate option"),
3387
N_("Unexpected end of data"),
3388
N_("Missing required field"),
3389
N_("Out of order field")
3390
};
3391
3392
char *
3393
ldap_scherr2str(int code)
3394
{
3395
if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3396
return _("Unknown error");
3397
} else {
3398
return _(err2text[code]);
3399
}
3400
}
3401
3402