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