]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_check.c
433cabae194c1cb15ab2e06fdc3fa3e858d5b6f3
[openldap] / servers / slapd / schema_check.c
1 /* schema_check.c - routines to enforce schema definitions */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 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_pvt.h"
18
19 #ifdef SLAPD_SCHEMA_NOT_COMPAT
20 static int oc_check_allowed(
21         AttributeType *type,
22         struct berval **oclist );
23 #else
24 static int              oc_check_allowed(char *type, struct berval **oclist);
25 #endif
26 static char *   oc_check_required(Entry *e, struct berval *ocname);
27
28 /*
29  * entry_schema_check - check that entry e conforms to the schema required
30  * by its object class(es).
31  *
32  * returns 0 if so, non-zero otherwise.
33  */
34
35 int
36 schema_check_entry( Entry *e )
37 {
38         Attribute       *a, *aoc;
39         ObjectClass *oc;
40         int             i;
41         int             ret = 0;
42
43         if( !global_schemacheck ) return 0;
44
45         /* find the object class attribute - could error out here */
46         if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) {
47                 Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n",
48                     e->e_dn, 0, 0 );
49                 return( 1 );
50         }
51
52         /* check that the entry has required attrs for each oc */
53         for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
54                 if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) {
55                         Debug( LDAP_DEBUG_ANY,
56                                 "Objectclass \"%s\" not defined\n",
57                                 aoc->a_vals[i]->bv_val, 0, 0 );
58                 }
59                 else
60                 {
61                         char *s = oc_check_required( e, aoc->a_vals[i] );
62
63                         if (s != NULL) {
64                                 Debug( LDAP_DEBUG_ANY,
65                                         "Entry (%s), oc \"%s\" requires attr \"%s\"\n",
66                                         e->e_dn, aoc->a_vals[i]->bv_val, s );
67                                 ret = 1;
68                         }
69                 }
70         }
71
72         if ( ret != 0 ) {
73             return( ret );
74         }
75
76         /* check that each attr in the entry is allowed by some oc */
77         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
78 #ifdef SLAPD_SCHEMA_NOT_COMPAT
79                 if ( oc_check_allowed( a->a_desc.ad_type, aoc->a_vals ) != 0 ) {
80                         Debug( LDAP_DEBUG_ANY,
81                             "Entry (%s), attr \"%s\" not allowed\n",
82                             e->e_dn, a->a_desc.ad_cname->bv_val, 0 );
83                         ret = 1;
84                 }
85 #else
86                 if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) {
87                         Debug( LDAP_DEBUG_ANY,
88                             "Entry (%s), attr \"%s\" not allowed\n",
89                             e->e_dn, a->a_type, 0 );
90                         ret = 1;
91                 }
92 #endif
93         }
94
95         return( ret );
96 }
97
98 static char *
99 oc_check_required( Entry *e, struct berval *ocname )
100 {
101         ObjectClass     *oc;
102         AttributeType   *at;
103         int             i;
104         Attribute       *a;
105
106         Debug( LDAP_DEBUG_TRACE,
107                "oc_check_required entry (%s), objectclass \"%s\"\n",
108                e->e_dn, ocname, 0 );
109
110         /* find global oc defn. it we don't know about it assume it's ok */
111         if ( (oc = oc_find( ocname->bv_val )) == NULL ) {
112                 return( 0 );
113         }
114
115         /* check for empty oc_required */
116         if(oc->soc_required == NULL) {
117                 return( 0 );
118         }
119
120         /* for each required attribute */
121         for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
122                 at = oc->soc_required[i];
123                 /* see if it's in the entry */
124                 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
125 #ifdef SLAPD_SCHEMA_NOT_COMPAT
126                         if( a->a_desc.ad_type == at ) {
127                                 break;
128                         }
129 #else
130                         char            **pp;
131
132                         if ( at->sat_oid &&
133                              strcmp( a->a_type, at->sat_oid ) == 0 ) {
134                                 break;
135                         }
136                         pp = at->sat_names;
137                         if ( pp  == NULL ) {
138                                 /* Empty name list => not found */
139                                 a = NULL;
140                                 break;
141                         }
142                         while ( *pp ) {
143                                 if ( strcasecmp( a->a_type, *pp ) == 0 ) {
144                                         break;
145                                 }
146                                 pp++;
147                         }
148                         if ( *pp ) {
149                                 break;
150                         }
151 #endif
152                 }
153                 /* not there => schema violation */
154                 if ( a == NULL ) {
155 #ifdef SLAPD_SCHEMA_NOT_COMPAT
156                         return at->sat_cname;
157 #else
158                         if ( at->sat_names && at->sat_names[0] ) {
159                                 return at->sat_names[0];
160                         } else {
161                                 return at->sat_oid;
162                         }
163 #endif
164                 }
165         }
166
167         return( NULL );
168 }
169
170 static int
171 oc_check_allowed(
172 #ifdef SLAPD_SCHEMA_NOT_COMPAT
173         AttributeType *at,
174 #else
175         char *type,
176 #endif
177         struct berval **ocl )
178 {
179         ObjectClass     *oc;
180         int             i, j;
181
182 #ifdef SLAPD_SCHEMA_NOT_COMPAT
183         Debug( LDAP_DEBUG_TRACE,
184                 "oc_check_allowed type \"%s\"\n",
185                 at->sat_cname, 0, 0 );
186
187         /* always allow objectclass attribute */
188         if ( strcasecmp( at->sat_cname, "objectclass" ) == 0 ) {
189                 return( 0 );
190         }
191
192 #else
193         AttributeType   *at;
194         char            **pp;
195         char            *p;
196         char            *t;
197
198         Debug( LDAP_DEBUG_TRACE,
199                "oc_check_allowed type \"%s\"\n", type, 0, 0 );
200
201         /* always allow objectclass attribute */
202         if ( strcasecmp( type, "objectclass" ) == 0 ) {
203                 return( 0 );
204         }
205 #endif
206
207 #ifdef SLAPD_SCHEMA_NOT_COMPAT
208         if( is_at_operational(at) ) {
209                 return 0;
210         }
211 #else
212         /*
213          * The "type" we have received is actually an AttributeDescription.
214          * Let's find out the corresponding type.
215          */
216         p = strchr( type, ';' );
217         if ( p ) {
218                 t = ch_malloc( p-type+1 );
219                 strncpy( t, type, p-type );
220                 t[p-type] = '\0';
221                 Debug( LDAP_DEBUG_TRACE,
222                        "oc_check_allowed type \"%s\" from \"%s\"\n",
223                        t, type, 0 );
224
225         } else
226         {
227                 t = type;
228         }
229
230         /*
231          * All operational attributions are allowed by schema rules.
232          */
233         if ( oc_check_op_attr( t ) ) {
234                 return( 0 );
235         }
236 #endif
237
238         /* check that the type appears as req or opt in at least one oc */
239         for ( i = 0; ocl[i] != NULL; i++ ) {
240                 /* if we know about the oc */
241                 if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
242                         /* does it require the type? */
243                         for ( j = 0; oc->soc_required != NULL && 
244                                 oc->soc_required[j] != NULL; j++ )
245                         {
246 #ifdef SLAPD_SCHEMA_NOT_COMPAT
247                                 if( at == oc->soc_required[j] ) {
248                                         return 0;
249                                 }
250 #else
251                                 at = oc->soc_required[j];
252                                 if ( at->sat_oid &&
253                                      strcmp(at->sat_oid, t ) == 0 ) {
254                                         if ( t != type )
255                                                 ldap_memfree( t );
256                                         return( 0 );
257                                 }
258                                 pp = at->sat_names;
259                                 if ( pp == NULL )
260                                         continue;
261                                 while ( *pp ) {
262                                         if ( strcasecmp( *pp, t ) == 0 ) {
263                                                 if ( t != type )
264                                                         ldap_memfree( t );
265                                                 return( 0 );
266                                         }
267                                         pp++;
268                                 }
269 #endif
270                         }
271                         /* does it allow the type? */
272                         for ( j = 0; oc->soc_allowed != NULL && 
273                                 oc->soc_allowed[j] != NULL; j++ )
274                         {
275 #ifdef SLAPD_SCHEMA_NOT_COMPAT
276                                 if( at == oc->soc_allowed[j] ) {
277                                         return 0;
278                                 }
279 #else
280                                 at = oc->soc_allowed[j];
281                                 if ( at->sat_oid &&
282                                      strcmp( at->sat_oid, t ) == 0 ) {
283                                         if ( t != type )
284                                                 ldap_memfree( t );
285                                         return( 0 );
286                                 }
287                                 pp = at->sat_names;
288                                 if ( pp == NULL )
289                                         continue;
290                                 while ( *pp ) {
291                                         if ( strcasecmp( *pp, t ) == 0 ||
292                                              strcmp( *pp, "*" ) == 0 ) {
293                                                 if ( t != type )
294                                                         ldap_memfree( t );
295                                                 return( 0 );
296                                         }
297                                         pp++;
298                                 }
299 #endif
300                         }
301                         /* maybe the next oc allows it */
302
303 #ifdef OC_UNDEFINED_IMPLES_EXTENSIBLE
304                 /* we don't know about the oc. assume it allows it */
305                 } else {
306                         if ( t != type )
307                                 ldap_memfree( t );
308                         return( 0 );
309 #endif
310                 }
311         }
312
313 #ifndef SLAPD_SCHEMA_NOT_COMPAT
314         if ( t != type )
315                 ldap_memfree( t );
316 #endif
317
318         /* not allowed by any oc */
319         return( 1 );
320 }