]> git.sur5r.net Git - openldap/blob - servers/slapd/schema.c
charray fix from HEAD
[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         /* for each required attribute */
80         for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
81                 /* see if it's in the entry */
82                 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
83                         if ( strcasecmp( a->a_type, oc->oc_required[i] )
84                             == 0 ) {
85                                 break;
86                         }
87                 }
88
89                 /* not there => schema violation */
90                 if ( a == NULL ) {
91                         return( 1 );
92                 }
93         }
94
95         return( 0 );
96 }
97
98 static int
99 oc_check_allowed( char *type, struct berval **ocl )
100 {
101         struct objclass *oc;
102         int             i, j;
103
104         /* always allow objectclass attribute */
105         if ( strcasecmp( type, "objectclass" ) == 0 ) {
106                 return( 0 );
107         }
108
109         /* check that the type appears as req or opt in at least one oc */
110         for ( i = 0; ocl[i] != NULL; i++ ) {
111                 /* if we know about the oc */
112                 if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
113                         /* does it require the type? */
114                         for ( j = 0; oc->oc_required[j] != NULL; j++ ) {
115                                 if ( strcasecmp( oc->oc_required[j], type )
116                                     == 0 ) {
117                                         return( 0 );
118                                 }
119                         }
120                         /* does it allow the type? */
121                         for ( j = 0; oc->oc_allowed[j] != NULL; j++ ) {
122                                 if ( strcasecmp( oc->oc_allowed[j], type )
123                                     == 0 || strcmp( oc->oc_allowed[j], "*" )
124                                     == 0 )
125                                 {
126                                         return( 0 );
127                                 }
128                         }
129                         /* maybe the next oc allows it */
130
131                 /* we don't know about the oc. assume it allows it */
132                 } else {
133                         return( 0 );
134                 }
135         }
136
137         /* not allowed by any oc */
138         return( 1 );
139 }
140
141 static struct objclass *
142 oc_find( char *ocname )
143 {
144         struct objclass *oc;
145
146         for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
147                 if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
148                         return( oc );
149                 }
150         }
151
152         return( NULL );
153 }
154
155 #ifdef LDAP_DEBUG
156
157 static
158 oc_print( struct objclass *oc )
159 {
160         int     i;
161
162         printf( "objectclass %s\n", oc->oc_name );
163         if ( oc->oc_required != NULL ) {
164                 printf( "\trequires %s", oc->oc_required[0] );
165                 for ( i = 1; oc->oc_required[i] != NULL; i++ ) {
166                         printf( ",%s", oc->oc_required[i] );
167                 }
168                 printf( "\n" );
169         }
170         if ( oc->oc_allowed != NULL ) {
171                 printf( "\tallows %s", oc->oc_allowed[0] );
172                 for ( i = 1; oc->oc_allowed[i] != NULL; i++ ) {
173                         printf( ",%s", oc->oc_allowed[i] );
174                 }
175                 printf( "\n" );
176         }
177 }
178
179 #endif