]> git.sur5r.net Git - openldap/blob - servers/slapd/schema.c
Changed FD_SETSIZE checks for consistency. Added checks where needed.
[openldap] / servers / slapd / schema.c
1 /* schema.c - routines to enforce schema definitions */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include "slap.h"
8
9 extern Attribute        *attr_find();
10 extern char             **str2charray();
11 extern void             charray_merge();
12
13 extern struct objclass  *global_oc;
14 extern int              global_schemacheck;
15
16 static struct objclass  *oc_find();
17 static int              oc_check_required();
18 static int              oc_check_allowed();
19
20 /*
21  * oc_check - check that entry e conforms to the schema required by
22  * its object class(es). returns 0 if so, non-zero otherwise.
23  */
24
25 int
26 oc_schema_check( Entry *e )
27 {
28         Attribute       *a, *aoc;
29         struct objclass *oc;
30         int             i;
31         int             ret = 0;
32
33         /* find the object class attribute - could error out here */
34         if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) {
35                 Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n",
36                     e->e_dn, 0, 0 );
37                 return( 0 );
38         }
39
40         /* check that the entry has required attrs for each oc */
41         for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
42                 if ( oc_check_required( e, aoc->a_vals[i]->bv_val ) != 0 ) {
43                         Debug( LDAP_DEBUG_ANY,
44                             "Entry (%s), required attr (%s) missing\n",
45                             e->e_dn, aoc->a_vals[i]->bv_val, 0 );
46                         ret = 1;
47                 }
48         }
49
50         if ( ret != 0 ) {
51             return( ret );
52         }
53
54         /* check that each attr in the entry is allowed by some oc */
55         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
56                 if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) {
57                         Debug( LDAP_DEBUG_ANY,
58                             "Entry (%s), attr (%s) not allowed\n",
59                             e->e_dn, a->a_type, 0 );
60                         ret = 1;
61                 }
62         }
63
64         return( ret );
65 }
66
67 static int
68 oc_check_required( Entry *e, char *ocname )
69 {
70         struct objclass *oc;
71         int             i;
72         Attribute       *a;
73
74         /* find global oc defn. it we don't know about it assume it's ok */
75         if ( (oc = oc_find( ocname )) == NULL ) {
76                 return( 0 );
77         }
78
79         /* check for empty oc_required */
80         if(oc->oc_required == NULL) {
81                 return( 0 );
82         }
83
84         /* for each required attribute */
85         for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
86                 /* see if it's in the entry */
87                 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
88                         if ( strcasecmp( a->a_type, oc->oc_required[i] )
89                             == 0 ) {
90                                 break;
91                         }
92                 }
93
94                 /* not there => schema violation */
95                 if ( a == NULL ) {
96                         return( 1 );
97                 }
98         }
99
100         return( 0 );
101 }
102
103 static int
104 oc_check_allowed( char *type, struct berval **ocl )
105 {
106         struct objclass *oc;
107         int             i, j;
108
109         /* always allow objectclass attribute */
110         if ( strcasecmp( type, "objectclass" ) == 0 ) {
111                 return( 0 );
112         }
113
114         /* check that the type appears as req or opt in at least one oc */
115         for ( i = 0; ocl[i] != NULL; i++ ) {
116                 /* if we know about the oc */
117                 if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
118                         /* does it require the type? */
119                         for ( j = 0; oc->oc_required != NULL && 
120                                 oc->oc_required[j] != NULL; j++ ) {
121                                 if ( strcasecmp( oc->oc_required[j], type )
122                                     == 0 ) {
123                                         return( 0 );
124                                 }
125                         }
126                         /* does it allow the type? */
127                         for ( j = 0; oc->oc_allowed != NULL && 
128                                 oc->oc_allowed[j] != NULL; j++ ) {
129                                 if ( strcasecmp( oc->oc_allowed[j], type )
130                                     == 0 || strcmp( oc->oc_allowed[j], "*" )
131                                     == 0 )
132                                 {
133                                         return( 0 );
134                                 }
135                         }
136                         /* maybe the next oc allows it */
137
138                 /* we don't know about the oc. assume it allows it */
139                 } else {
140                         return( 0 );
141                 }
142         }
143
144         /* not allowed by any oc */
145         return( 1 );
146 }
147
148 static struct objclass *
149 oc_find( char *ocname )
150 {
151         struct objclass *oc;
152
153         for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
154                 if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
155                         return( oc );
156                 }
157         }
158
159         return( NULL );
160 }
161
162 #ifdef LDAP_DEBUG
163
164 static
165 oc_print( struct objclass *oc )
166 {
167         int     i;
168
169         printf( "objectclass %s\n", oc->oc_name );
170         if ( oc->oc_required != NULL ) {
171                 printf( "\trequires %s", oc->oc_required[0] );
172                 for ( i = 1; oc->oc_required[i] != NULL; i++ ) {
173                         printf( ",%s", oc->oc_required[i] );
174                 }
175                 printf( "\n" );
176         }
177         if ( oc->oc_allowed != NULL ) {
178                 printf( "\tallows %s", oc->oc_allowed[0] );
179                 for ( i = 1; oc->oc_allowed[i] != NULL; i++ ) {
180                         printf( ",%s", oc->oc_allowed[i] );
181                 }
182                 printf( "\n" );
183         }
184 }
185
186 #endif