xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/schema.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: schema.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
2 
3 /* schema.c - routines to manage schema definitions */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #include <sys/cdefs.h>
20 __RCSID("$NetBSD: schema.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/ctype.h>
27 #include <ac/string.h>
28 #include <ac/socket.h>
29 
30 #include "slap.h"
31 #include "lutil.h"
32 
33 
34 int
schema_info(Entry ** entry,const char ** text)35 schema_info( Entry **entry, const char **text )
36 {
37 	AttributeDescription *ad_structuralObjectClass
38 		= slap_schema.si_ad_structuralObjectClass;
39 	AttributeDescription *ad_objectClass
40 		= slap_schema.si_ad_objectClass;
41 	AttributeDescription *ad_createTimestamp
42 		= slap_schema.si_ad_createTimestamp;
43 	AttributeDescription *ad_modifyTimestamp
44 		= slap_schema.si_ad_modifyTimestamp;
45 
46 	Entry		*e;
47 	struct berval	vals[5];
48 	struct berval	nvals[5];
49 
50 	e = entry_alloc();
51 	if( e == NULL ) {
52 		/* Out of memory, do something about it */
53 		Debug( LDAP_DEBUG_ANY,
54 			"schema_info: entry_alloc failed - out of memory.\n" );
55 		*text = "out of memory";
56 		return LDAP_OTHER;
57 	}
58 
59 	e->e_attrs = NULL;
60 	/* backend-specific schema info should be created by the
61 	 * backend itself
62 	 */
63 	ber_dupbv( &e->e_name, &frontendDB->be_schemadn );
64 	ber_dupbv( &e->e_nname, &frontendDB->be_schemandn );
65 	e->e_private = NULL;
66 
67 	BER_BVSTR( &vals[0], "subentry" );
68 	if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) {
69 		/* Out of memory, do something about it */
70 		entry_free( e );
71 		*text = "out of memory";
72 		return LDAP_OTHER;
73 	}
74 
75 	BER_BVSTR( &vals[0], "top" );
76 	BER_BVSTR( &vals[1], "subentry" );
77 	BER_BVSTR( &vals[2], "subschema" );
78 	BER_BVSTR( &vals[3], "extensibleObject" );
79 	BER_BVZERO( &vals[4] );
80 	if ( attr_merge( e, ad_objectClass, vals, NULL ) ) {
81 		/* Out of memory, do something about it */
82 		entry_free( e );
83 		*text = "out of memory";
84 		return LDAP_OTHER;
85 	}
86 
87 	{
88 		int rc;
89 		AttributeDescription *desc = NULL;
90 		struct berval rdn = frontendDB->be_schemadn;
91 		vals[0].bv_val = ber_bvchr( &rdn, '=' );
92 
93 		if( vals[0].bv_val == NULL ) {
94 			*text = "improperly configured subschema subentry";
95 			return LDAP_OTHER;
96 		}
97 
98 		vals[0].bv_val++;
99 		vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val);
100 		rdn.bv_len -= vals[0].bv_len + 1;
101 
102 		rc = slap_bv2ad( &rdn, &desc, text );
103 
104 		if( rc != LDAP_SUCCESS ) {
105 			entry_free( e );
106 			*text = "improperly configured subschema subentry";
107 			return LDAP_OTHER;
108 		}
109 
110 		nvals[0].bv_val = ber_bvchr( &frontendDB->be_schemandn, '=' );
111 		assert( nvals[0].bv_val != NULL );
112 		nvals[0].bv_val++;
113 		nvals[0].bv_len = frontendDB->be_schemandn.bv_len -
114 			(nvals[0].bv_val - frontendDB->be_schemandn.bv_val);
115 
116 		if ( attr_merge_one( e, desc, vals, nvals ) ) {
117 			/* Out of memory, do something about it */
118 			entry_free( e );
119 			*text = "out of memory";
120 			return LDAP_OTHER;
121 		}
122 	}
123 
124 	{
125 		char		timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
126 
127 		/*
128 		 * According to RFC 4512:
129 
130    Servers SHOULD maintain the 'creatorsName', 'createTimestamp',
131    'modifiersName', and 'modifyTimestamp' attributes for all entries of
132    the DIT.
133 
134 		 * to be conservative, we declare schema created
135 		 * AND modified at server startup time ...
136 		 */
137 
138 		vals[0].bv_val = timebuf;
139 		vals[0].bv_len = sizeof( timebuf );
140 
141 		slap_timestamp( &starttime, vals );
142 
143 		if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) {
144 			/* Out of memory, do something about it */
145 			entry_free( e );
146 			*text = "out of memory";
147 			return LDAP_OTHER;
148 		}
149 		if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) {
150 			/* Out of memory, do something about it */
151 			entry_free( e );
152 			*text = "out of memory";
153 			return LDAP_OTHER;
154 		}
155 	}
156 
157 	if ( syn_schema_info( e )
158 		|| mr_schema_info( e )
159 		|| mru_schema_info( e )
160 		|| at_schema_info( e )
161 		|| oc_schema_info( e )
162 		|| cr_schema_info( e ) )
163 	{
164 		/* Out of memory, do something about it */
165 		entry_free( e );
166 		*text = "out of memory";
167 		return LDAP_OTHER;
168 	}
169 
170 	*entry = e;
171 	return LDAP_SUCCESS;
172 }
173