1 /* schema_check.c - routines to enforce schema definitions */
4 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #include <ac/string.h>
14 #include <ac/socket.h>
19 static char * oc_check_required(Entry *e, struct berval *ocname);
22 * entry_schema_check - check that entry e conforms to the schema required
23 * by its object class(es).
25 * returns 0 if so, non-zero otherwise.
30 Entry *e, Attribute *oldattrs, const char** text,
31 char *textbuf, size_t textlen )
36 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
39 /* check single-valued attrs for multiple values */
40 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
41 /* there should be at least one value */
43 assert( a->a_vals[0] != NULL );
45 /* if single value type, check for multiple values */
46 if( is_at_single_value( a->a_desc->ad_type ) &&
47 a->a_vals[1] != NULL )
49 char *type = a->a_desc->ad_cname->bv_val;
51 snprintf( textbuf, textlen,
52 "attribute '%s' cannot have multiple values",
56 LDAP_LOG(( "schema", LDAP_LEVEL_INFO,
57 "entry_schema_check: dn=\"%s\" %s\n",
60 Debug( LDAP_DEBUG_ANY,
62 e->e_dn, textbuf, 0 );
66 return LDAP_CONSTRAINT_VIOLATION;
70 if( !global_schemacheck ) return LDAP_SUCCESS;
74 /* find the object class attribute - could error out here */
75 if ( (aoc = attr_find( e->e_attrs, ad_objectClass )) == NULL ) {
77 LDAP_LOG(( "schema", LDAP_LEVEL_INFO,
78 "entry_schema_check: No objectClass for entry (%s).\n", e->e_dn ));
80 Debug( LDAP_DEBUG_ANY, "No objectClass for entry (%s)\n",
84 *text = "no objectClass attribute";
85 return LDAP_OBJECT_CLASS_VIOLATION;
88 /* check that the entry has required attrs for each oc */
89 for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
90 if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) {
91 snprintf( textbuf, textlen,
92 "unrecognized objectClass '%s'",
93 aoc->a_vals[i]->bv_val );
96 LDAP_LOG(( "schema", LDAP_LEVEL_INFO,
97 "entry_schema_check: dn (%s), %s\n",
100 Debug( LDAP_DEBUG_ANY,
101 "entry_check_schema(%s): \"%s\" not recognized\n",
102 e->e_dn, textbuf, 0 );
105 return LDAP_OBJECT_CLASS_VIOLATION;
108 char *s = oc_check_required( e, aoc->a_vals[i] );
111 snprintf( textbuf, textlen,
112 "object class '%s' requires attribute '%s'",
113 aoc->a_vals[i]->bv_val, s );
116 LDAP_LOG(( "schema", LDAP_LEVEL_INFO,
117 "entry_schema_check: dn=\"%s\" %s",
120 Debug( LDAP_DEBUG_ANY,
122 e->e_dn, textbuf, 0 );
125 return LDAP_OBJECT_CLASS_VIOLATION;
128 if( oc == slap_schema.si_oc_extensibleObject ) {
139 /* check that each attr in the entry is allowed by some oc */
140 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
141 int ret = oc_check_allowed( a->a_desc->ad_type, aoc->a_vals );
142 if ( ret != LDAP_SUCCESS ) {
143 char *type = a->a_desc->ad_cname->bv_val;
145 snprintf( textbuf, textlen,
146 "attribute '%s' not allowed",
150 LDAP_LOG(( "schema", LDAP_LEVEL_INFO,
151 "entry_schema_check: dn=\"%s\" %s\n",
154 Debug( LDAP_DEBUG_ANY,
156 e->e_dn, textbuf, 0 );
167 oc_check_required( Entry *e, struct berval *ocname )
175 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
176 "oc_check_required: dn (%s), objectClass \"%s\"\n",
177 e->e_dn, ocname->bv_val ));
179 Debug( LDAP_DEBUG_TRACE,
180 "oc_check_required entry (%s), objectClass \"%s\"\n",
181 e->e_dn, ocname->bv_val, 0 );
185 /* find global oc defn. it we don't know about it assume it's ok */
186 if ( (oc = oc_find( ocname->bv_val )) == NULL ) {
190 /* check for empty oc_required */
191 if(oc->soc_required == NULL) {
195 /* for each required attribute */
196 for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
197 at = oc->soc_required[i];
198 /* see if it's in the entry */
199 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
200 if( a->a_desc->ad_type == at ) {
204 /* not there => schema violation */
206 return at->sat_cname;
213 int oc_check_allowed(
215 struct berval **ocl )
221 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
222 "oc_check_allowed: type \"%s\"\n", at->sat_cname ));
224 Debug( LDAP_DEBUG_TRACE,
225 "oc_check_allowed type \"%s\"\n",
226 at->sat_cname, 0, 0 );
229 /* always allow objectClass attribute */
230 if ( strcasecmp( at->sat_cname, "objectClass" ) == 0 ) {
236 * All operational attributions are allowed by schema rules.
238 if( is_at_operational(at) ) {
242 /* check that the type appears as req or opt in at least one oc */
243 for ( i = 0; ocl[i] != NULL; i++ ) {
244 /* if we know about the oc */
245 if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
246 /* does it require the type? */
247 for ( j = 0; oc->soc_required != NULL &&
248 oc->soc_required[j] != NULL; j++ )
250 if( at == oc->soc_required[j] ) {
254 /* does it allow the type? */
255 for ( j = 0; oc->soc_allowed != NULL &&
256 oc->soc_allowed[j] != NULL; j++ )
258 if( at == oc->soc_allowed[j] ) {
262 /* maybe the next oc allows it */
266 /* not allowed by any oc */
267 return LDAP_OBJECT_CLASS_VIOLATION;