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