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