]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
Use AC_MEMCPY instead of memcpy
[openldap] / servers / slapd / schemaparse.c
1 /* schemaparse.c - routines to parse config file objectclass definitions */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_schema.h"
18
19 int     global_schemacheck = 1; /* schemacheck on is default */
20
21 static void             oc_usage(void); 
22 static void             at_usage(void);
23
24 static char *const err2text[] = {
25         "Success",
26         "Out of memory",
27         "ObjectClass not found",
28         "ObjectClass inappropriate SUPerior",
29         "AttributeType not found",
30         "AttributeType inappropriate USAGE",
31         "Duplicate objectClass",
32         "Duplicate attributeType",
33         "Duplicate ldapSyntax",
34         "Duplicate matchingRule",
35         "OID or name required",
36         "SYNTAX or SUPerior required",
37         "MatchingRule not found",
38         "Syntax not found",
39         "Syntax required",
40         "Qualifier not supported",
41         "Invalid NAME"
42 };
43
44 char *
45 scherr2str(int code)
46 {
47         if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) {
48                 return "Unknown error";
49         } else {
50                 return err2text[code];
51         }
52 }
53
54 /* check schema descr validity */
55 int slap_valid_descr( const char *descr )
56 {
57         int i=0;
58
59         if( !DESC_LEADCHAR( descr[i] ) ) {
60                 return 0;
61         }
62
63         while( descr[++i] ) {
64                 if( !DESC_CHAR( descr[i] ) ) {
65                         return 0;
66                 }
67         }
68
69         return 1;
70 }
71
72
73 /* OID Macros */
74
75 /* String compare with delimiter check. Return 0 if not
76  * matched, otherwise return length matched.
77  */
78 int
79 dscompare(const char *s1, const char *s2, char delim)
80 {
81         const char *orig = s1;
82         while (*s1++ == *s2++)
83                 if (!s1[-1]) break;
84         --s1;
85         --s2;
86         if (!*s1 && (!*s2 || *s2 == delim))
87                 return s1 - orig;
88         return 0;
89 }
90
91 static OidMacro *om_list = NULL;
92
93 /* Replace an OID Macro invocation with its full numeric OID.
94  * If the macro is used with "macroname:suffix" append ".suffix"
95  * to the expansion.
96  */
97 static char *
98 find_oidm(char *oid)
99 {
100         OidMacro *om;
101
102         /* OID macros must start alpha */
103         if ( OID_LEADCHAR( *oid ) )     {
104                 return oid;
105         }
106
107     for (om = om_list; om; om=om->som_next) {
108                 char **names = om->som_names;
109
110                 if( names == NULL ) {
111                         continue;
112                 }
113
114                 for( ; *names != NULL ; names++ ) {
115                         int pos = dscompare(*names, oid, ':');
116
117                         if( pos ) {
118                                 int suflen = strlen(oid + pos);
119                                 char *new = ch_malloc( om->som_oid.bv_len
120                                         + suflen + 1);
121                                 strcpy(new, om->som_oid.bv_val);
122
123                                 if( suflen ) {
124                                         suflen = om->som_oid.bv_len;
125                                         new[suflen++] = '.';
126                                         strcpy(new+suflen, oid+pos+1);
127                                 }
128                                 return new;
129                         }
130                 }
131         }
132         return NULL;
133 }
134
135 void
136 oidm_destroy()
137 {
138         OidMacro *om, *n;
139
140         for (om = om_list; om; om = n) {
141                 n = om->som_next;
142                 charray_free(om->som_names);
143                 free(om->som_oid.bv_val);
144                 free(om);
145         }
146 }
147
148 int
149 parse_oidm(
150     const char  *fname,
151     int         lineno,
152     int         argc,
153     char        **argv
154 )
155 {
156         char *oid;
157         OidMacro *om;
158
159         if (argc != 3) {
160                 fprintf( stderr, "%s: line %d: too many arguments\n",
161                         fname, lineno );
162 usage:  fprintf( stderr, "\tObjectIdentifier <name> <oid>\n");
163                 return 1;
164         }
165
166         oid = find_oidm( argv[1] );
167         if( oid != NULL ) {
168                 fprintf( stderr,
169                         "%s: line %d: "
170                         "ObjectIdentifier \"%s\" previously defined \"%s\"",
171                         fname, lineno, argv[1], oid );
172                 return 1;
173         }
174
175         om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
176
177         om->som_names = NULL;
178         charray_add( &om->som_names, argv[1] );
179         om->som_oid.bv_val = find_oidm( argv[2] );
180
181         if (!om->som_oid.bv_val) {
182                 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
183                         fname, lineno, argv[2] );
184                 goto usage;
185         }
186
187         if (om->som_oid.bv_val == argv[2]) {
188                 om->som_oid.bv_val = ch_strdup( argv[2] );
189         }
190
191         om->som_oid.bv_len = strlen( om->som_oid.bv_val );
192         om->som_next = om_list;
193         om_list = om;
194
195         return 0;
196 }
197
198 int
199 parse_oc(
200     const char  *fname,
201     int         lineno,
202     char        *line,
203     char        **argv
204 )
205 {
206         LDAPObjectClass *oc;
207         int             code;
208         const char      *err;
209         char            *oid = NULL;
210
211         oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
212         if ( !oc ) {
213                 fprintf( stderr, "%s: line %d: %s before %s\n",
214                          fname, lineno, ldap_scherr2str(code), err );
215                 oc_usage();
216                 return 1;
217         }
218
219         if ( oc->oc_oid == NULL ) {
220                 fprintf( stderr,
221                         "%s: line %d: objectclass has no OID\n",
222                         fname, lineno );
223                 oc_usage();
224                 return 1;
225         }
226
227         if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
228                 /* Expand OID macros */
229                 oid = find_oidm( oc->oc_oid );
230                 if ( !oid ) {
231                         fprintf( stderr,
232                                 "%s: line %d: OID %s not recognized\n",
233                                 fname, lineno, oc->oc_oid);
234                         return 1;
235                 }
236                 if ( oid != oc->oc_oid ) {
237                         ldap_memfree( oc->oc_oid );
238                         oc->oc_oid = oid;
239                 }
240         }
241
242         code = oc_add(oc,&err);
243         if ( code ) {
244                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
245                          fname, lineno, scherr2str(code), err);
246                 return 1;
247         }
248
249         ldap_memfree(oc);
250         return 0;
251 }
252
253 static void
254 oc_usage( void )
255 {
256         fprintf( stderr,
257                 "ObjectClassDescription = \"(\" whsp\n"
258                 "  numericoid whsp                 ; ObjectClass identifier\n"
259                 "  [ \"NAME\" qdescrs ]\n"
260                 "  [ \"DESC\" qdstring ]\n"
261                 "  [ \"OBSOLETE\" whsp ]\n"
262                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
263                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
264                 "                                  ; default structural\n"
265                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
266                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
267                 "  whsp \")\"\n" );
268 }
269
270
271 static void
272 at_usage( void )
273 {
274         fprintf( stderr,
275                 "AttributeTypeDescription = \"(\" whsp\n"
276                 "  numericoid whsp      ; AttributeType identifier\n"
277                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
278                 "  [ \"DESC\" qdstring ]            ; description\n"
279                 "  [ \"OBSOLETE\" whsp ]\n"
280                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
281                 "                                   ; AttributeType\n"
282                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
283                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
284                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
285                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
286                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
287                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
288                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
289                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
290                 "                                   ; userApplications\n"
291                 "                                   ; directoryOperation\n"
292                 "                                   ; distributedOperation\n"
293                 "                                   ; dSAOperation\n"
294                 "  whsp \")\"\n");
295 }
296
297 int
298 parse_at(
299     const char  *fname,
300     int         lineno,
301     char        *line,
302     char        **argv
303 )
304 {
305         LDAPAttributeType *at;
306         int             code;
307         const char      *err;
308         char            *oid = NULL;
309
310         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
311         if ( !at ) {
312                 fprintf( stderr, "%s: line %d: %s before %s\n",
313                          fname, lineno, ldap_scherr2str(code), err );
314                 at_usage();
315                 return 1;
316         }
317
318         if ( at->at_oid == NULL ) {
319                 fprintf( stderr,
320                         "%s: line %d: attributeType has no OID\n",
321                         fname, lineno );
322                 at_usage();
323                 return 1;
324         }
325
326         if ( !OID_LEADCHAR( at->at_oid[0] )) {
327                 /* Expand OID macros */
328                 oid = find_oidm( at->at_oid );
329                 if ( !oid ) {
330                         fprintf( stderr,
331                                 "%s: line %d: OID %s not recognized\n",
332                                 fname, lineno, at->at_oid);
333                         return 1;
334                 }
335                 if ( oid != at->at_oid ) {
336                         ldap_memfree( at->at_oid );
337                         at->at_oid = oid;
338                 }
339         }
340
341         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
342                 /* Expand OID macros */
343                 oid = find_oidm( at->at_syntax_oid );
344                 if ( !oid ) {
345                         fprintf(stderr,
346                                 "%s: line %d: OID %s not recognized\n",
347                                 fname, lineno, at->at_syntax_oid);
348                         return 1;
349                 }
350                 if ( oid != at->at_syntax_oid ) {
351                         ldap_memfree( at->at_syntax_oid );
352                         at->at_syntax_oid = oid;
353                 }
354
355         }
356         code = at_add(at,&err);
357         if ( code ) {
358                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
359                          fname, lineno, scherr2str(code), err);
360                 return 1;
361         }
362         ldap_memfree(at);
363         return 0;
364 }