]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
attribute & objectclass mapping rules
[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)     LDAP_GCCATTR((noreturn));
22 static void             at_usage(void)     LDAP_GCCATTR((noreturn));
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 };
41
42 char *
43 scherr2str(int code)
44 {
45         if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) {
46                 return "Unknown error";
47         } else {
48                 return err2text[code];
49         }
50 }
51
52
53 /* OID Macros */
54
55 /* String compare with delimiter check. Return 0 if not
56  * matched, otherwise return length matched.
57  */
58 int
59 dscompare(const char *s1, const char *s2, char delim)
60 {
61         const char *orig = s1;
62         while (*s1++ == *s2++)
63                 if (!s1[-1]) break;
64         --s1;
65         --s2;
66         if (!*s1 && (!*s2 || *s2 == delim))
67                 return s1 - orig;
68         return 0;
69 }
70
71 static OidMacro *om_list = NULL;
72
73 /* Replace an OID Macro invocation with its full numeric OID.
74  * If the macro is used with "macroname:suffix" append ".suffix"
75  * to the expansion.
76  */
77 static char *
78 find_oidm(char *oid)
79 {
80         OidMacro *om;
81
82         /* OID macros must start alpha */
83         if ( OID_LEADCHAR( *oid ) )     {
84                 return oid;
85         }
86
87     for (om = om_list; om; om=om->som_next) {
88                 char **names = om->som_names;
89
90                 if( names == NULL ) {
91                         continue;
92                 }
93
94                 for( ; *names != NULL ; names++ ) {
95                         int pos = dscompare(*names, oid, ':');
96
97                         if( pos ) {
98                                 int suflen = strlen(oid + pos);
99                                 char *new = ch_calloc(1,
100                                         om->som_oid.bv_len + suflen + 1);
101                                 strcpy(new, om->som_oid.bv_val);
102
103                                 if( suflen ) {
104                                         suflen = om->som_oid.bv_len;
105                                         new[suflen++] = '.';
106                                         strcpy(new+suflen, oid+pos+1);
107                                 }
108                                 return new;
109                         }
110                 }
111         }
112         return NULL;
113 }
114
115 void
116 parse_oidm(
117     const char  *fname,
118     int         lineno,
119     int         argc,
120     char        **argv
121 )
122 {
123         char *oid;
124         OidMacro *om;
125
126         if (argc != 3) {
127                 fprintf( stderr, "%s: line %d: too many arguments\n",
128                         fname, lineno );
129 usage:  fprintf( stderr, "\tObjectIdentifier <name> <oid>\n");
130                 exit( EXIT_FAILURE );
131         }
132
133         oid = find_oidm( argv[1] );
134         if( oid != NULL ) {
135                 fprintf( stderr,
136                         "%s: line %d: "
137                         "ObjectIdentifier \"%s\" previously defined \"%s\"",
138                         fname, lineno, argv[1], oid );
139                 exit( EXIT_FAILURE );
140         }
141
142         om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
143
144         om->som_names = NULL;
145         charray_add( &om->som_names, argv[1] );
146         om->som_oid.bv_val = find_oidm( argv[2] );
147
148         if (!om->som_oid.bv_val) {
149                 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
150                         fname, lineno, argv[2] );
151                 goto usage;
152         }
153
154         if (om->som_oid.bv_val == argv[2]) {
155                 om->som_oid.bv_val = ch_strdup( argv[2] );
156         }
157
158         om->som_oid.bv_len = strlen( om->som_oid.bv_val );
159         om->som_next = om_list;
160         om_list = om;
161 }
162
163 void
164 parse_oc(
165     const char  *fname,
166     int         lineno,
167     char        *line,
168     char        **argv
169 )
170 {
171         LDAPObjectClass *oc;
172         int             code;
173         const char      *err;
174         char            *oid = NULL;
175
176         oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
177         if ( !oc ) {
178                 fprintf( stderr, "%s: line %d: %s before %s\n",
179                          fname, lineno, ldap_scherr2str(code), err );
180                 oc_usage();
181         }
182         if ( oc->oc_oid ) {
183                 if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
184                         /* Expand OID macros */
185                         oid = find_oidm( oc->oc_oid );
186                         if ( !oid ) {
187                                 fprintf(stderr,
188                                         "%s: line %d: OID %s not recognized\n",
189                                         fname, lineno, oc->oc_oid);
190                                 exit( EXIT_FAILURE );
191                         }
192                         if ( oid != oc->oc_oid ) {
193                                 ldap_memfree( oc->oc_oid );
194                                 oc->oc_oid = oid;
195                         }
196                 }
197         }
198         /* oc->oc_oid == NULL will be an error someday */
199         code = oc_add(oc,&err);
200         if ( code ) {
201                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
202                          fname, lineno, scherr2str(code), err);
203                 exit( EXIT_FAILURE );
204         }
205         ldap_memfree(oc);
206 }
207
208 static void
209 oc_usage( void )
210 {
211         fprintf( stderr,
212                 "ObjectClassDescription = \"(\" whsp\n"
213                 "  numericoid whsp                 ; ObjectClass identifier\n"
214                 "  [ \"NAME\" qdescrs ]\n"
215                 "  [ \"DESC\" qdstring ]\n"
216                 "  [ \"OBSOLETE\" whsp ]\n"
217                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
218                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
219                 "                                  ; default structural\n"
220                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
221                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
222                 "  whsp \")\"\n" );
223         exit( EXIT_FAILURE );
224 }
225
226
227 static void
228 at_usage( void )
229 {
230         fprintf( stderr,
231                 "AttributeTypeDescription = \"(\" whsp\n"
232                 "  numericoid whsp      ; AttributeType identifier\n"
233                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
234                 "  [ \"DESC\" qdstring ]            ; description\n"
235                 "  [ \"OBSOLETE\" whsp ]\n"
236                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
237                 "                                   ; AttributeType\n"
238                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
239                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
240                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
241                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
242                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
243                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
244                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
245                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
246                 "                                   ; userApplications\n"
247                 "                                   ; directoryOperation\n"
248                 "                                   ; distributedOperation\n"
249                 "                                   ; dSAOperation\n"
250                 "  whsp \")\"\n");
251         exit( EXIT_FAILURE );
252 }
253
254 void
255 parse_at(
256     const char  *fname,
257     int         lineno,
258     char        *line,
259     char        **argv
260 )
261 {
262         LDAPAttributeType *at;
263         int             code;
264         const char      *err;
265         char            *oid = NULL;
266         char            *soid = NULL;
267
268         /* Kludge for OIDmacros for syntaxes. If the syntax field starts
269          * nonnumeric, look for and expand a macro. The macro's place in
270          * the input line will be replaced with a field of '0's to keep
271          * ldap_str2attributetype happy. The actual oid will be swapped
272          * into place afterwards.
273          */
274         for (; argv[3]; argv++)
275         {
276                 if (!strcasecmp(argv[3], "syntax") &&
277                     !OID_LEADCHAR(*argv[4]))
278                 {
279                         int slen;
280                         Syntax *syn;
281                         syn = syn_find_desc(argv[4], &slen);
282                         if (!syn)
283                         {
284                             fprintf(stderr, "%s: line %d: OID %s not found\n",
285                                 fname, lineno, argv[4]);
286                             exit( EXIT_FAILURE );
287                         }
288                         memset(strstr(line, argv[4]), '0', slen);
289                         soid = ch_strdup(syn->ssyn_syn.syn_oid );
290                         break;
291                 }
292         }
293         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
294         if ( !at ) {
295                 fprintf( stderr, "%s: line %d: %s before %s\n",
296                          fname, lineno, ldap_scherr2str(code), err );
297                 at_usage();
298         }
299         if ( at->at_oid ) {
300                 if ( !OID_LEADCHAR( at->at_oid[0] )) {
301                         /* Expand OID macros */
302                         oid = find_oidm( at->at_oid );
303                         if ( !oid ) {
304                                 fprintf(stderr,
305                                         "%s: line %d: OID %s not recognized\n",
306                                         fname, lineno, at->at_oid);
307                                 exit( EXIT_FAILURE );
308                         }
309                         if ( oid != at->at_oid ) {
310                                 ldap_memfree( at->at_oid );
311                                 at->at_oid = oid;
312                         }
313                 }
314         }
315         /* at->at_oid == NULL will be an error someday */
316         if (soid) {
317                 ldap_memfree(at->at_syntax_oid);
318                 at->at_syntax_oid = soid;
319         }
320         code = at_add(at,&err);
321         if ( code ) {
322                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
323                          fname, lineno, scherr2str(code), err);
324                 exit( EXIT_FAILURE );
325         }
326         ldap_memfree(at);
327 }