]> git.sur5r.net Git - openldap/blob - servers/slapd/bconfig.c
a1af4a4c9855f3d238c017eb616a691b512acd5b
[openldap] / servers / slapd / bconfig.c
1 /* bconfig.c - the config backend */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was originally developed by Howard Chu for inclusion
18  * in OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #include <stdio.h>
24 #include <ac/string.h>
25
26 #include "slap.h"
27 #include "config.h"
28
29 #define CONFIG_DN       "cn=config"
30
31 typedef struct CfEntryInfo {
32         struct CfEntryInfo *ce_sibs;
33         struct CfEntryInfo *ce_kids;
34         Entry *ce_entry;
35         ConfigTable *ce_table;
36 } CfEntryInfo;
37
38 typedef struct {
39         ConfigFile *cb_config;
40         CfEntryInfo *cb_root;
41 } CfBackInfo;
42
43 static int
44 config_back_bind( Operation *op, SlapReply *rs )
45 {
46         if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
47                 ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
48                 /* frontend sends result */
49                 return LDAP_SUCCESS;
50         }
51
52         rs->sr_err = LDAP_INVALID_CREDENTIALS;
53         send_ldap_result( op, rs );
54
55         return rs->sr_err;
56 }
57
58 static CfEntryInfo *
59 config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
60 {
61         struct berval cdn;
62         char *c;
63
64         if ( dn_match( &root->ce_entry->e_nname, dn ))
65                 return root;
66
67         c = dn->bv_val+dn->bv_len;
68         for (;*c != ',';c--);
69
70         while(root) {
71                 *last = root;
72                 for (--c;c>dn->bv_val && *c != ',';c--);
73                 if ( *c == ',' )
74                         c++;
75                 cdn.bv_val = c;
76                 cdn.bv_len = dn->bv_len - (c-dn->bv_val);
77
78                 root = root->ce_kids;
79
80                 for (;root;root=root->ce_sibs) {
81                         if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
82                                 if ( cdn.bv_val == dn->bv_val ) {
83                                         return root;
84                                 }
85                                 break;
86                         }
87                 }
88         }
89         return root;
90 }
91
92 static int
93 config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
94 {
95         int rc = 0;
96
97         if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
98         {
99                 rs->sr_attrs = op->ors_attrs;
100                 rs->sr_entry = ce->ce_entry;
101                 rc = send_search_entry( op, rs );
102         }
103         if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
104                 if ( ce->ce_kids ) {
105                         rc = config_send( op, rs, ce->ce_kids, 1 );
106                         if ( rc ) return rc;
107                 }
108                 if ( depth ) {
109                         for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
110                                 rc = config_send( op, rs, ce, 0 );
111                                 if ( rc ) break;
112                         }
113                 }
114         }
115         return rc;
116 }
117
118 static int
119 config_back_search( Operation *op, SlapReply *rs )
120 {
121         CfBackInfo *cfb;
122         CfEntryInfo *ce, *last;
123         int rc;
124
125         if ( !be_isroot( op ) ) {
126                 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
127                 send_ldap_result( op, rs );
128         }
129
130         cfb = (CfBackInfo *)op->o_bd->be_private;
131
132         ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
133         if ( !ce ) {
134                 if ( last )
135                         rs->sr_matched = last->ce_entry->e_name.bv_val;
136                 rs->sr_err = LDAP_NO_SUCH_OBJECT;
137                 goto out;
138         }
139         switch ( op->ors_scope ) {
140         case LDAP_SCOPE_BASE:
141         case LDAP_SCOPE_SUBTREE:
142                 config_send( op, rs, ce, 0 );
143                 break;
144                 
145         case LDAP_SCOPE_ONELEVEL:
146                 for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
147                         config_send( op, rs, ce, 1 );
148                 }
149                 break;
150         }
151                 
152         rs->sr_err = LDAP_SUCCESS;
153 out:
154         send_ldap_result( op, rs );
155         return 0;
156 }
157
158 static Entry *
159 config_alloc_entry( struct berval *pdn, struct berval *rdn )
160 {
161         Entry *e = ch_calloc( 1, sizeof(Entry) );
162         CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
163         e->e_private = ce;
164         ce->ce_entry = e;
165         build_new_dn( &e->e_name, pdn, rdn, NULL );
166         ber_dupbv( &e->e_nname, &e->e_name );
167         return e;
168 }
169
170 static int
171 config_build_entry( Entry *e, void *private, char *oc, struct berval *rdn )
172 {
173         struct berval vals[2];
174         struct berval ad_name;
175         AttributeDescription *ad = NULL;
176         int rc;
177         char *ptr;
178         const char *text;
179
180         BER_BVZERO( &vals[1] );
181
182         ber_str2bv( oc, 0, 0, &vals[0] );
183         attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
184         ptr = strchr(rdn->bv_val, '=');
185         ad_name.bv_val = rdn->bv_val;
186         ad_name.bv_len = ptr - rdn->bv_val;
187         rc = slap_bv2ad( &ad_name, &ad, &text );
188         if ( rc ) {
189                 return rc;
190         }
191         vals[0].bv_val = ptr+1;
192         vals[0].bv_len = rdn->bv_len - (vals[0].bv_val - rdn->bv_val);
193         attr_merge(e, ad, vals, NULL );
194         return 0;
195 }
196
197 static int
198 config_back_db_open( BackendDB *be )
199 {
200         CfBackInfo *cfb = be->be_private;
201         struct berval rdn;
202         Entry *e, *parent;
203         CfEntryInfo *ce, *ceparent, *ceprev;
204         int i, buflen = 0;
205         char *buf = NULL;
206         BackendInfo *bi;
207         BackendDB *bptr;
208
209         /* create root of tree */
210         ber_str2bv( CONFIG_DN, STRLENOF( CONFIG_DN ), 0, &rdn );
211         e = config_alloc_entry( NULL, &rdn );
212         ce = e->e_private;
213         ce->ce_table = be->bd_info->bi_cf_table;
214         cfb->cb_root = ce;
215
216         config_build_entry( e, be->be_private, "olcGlobal", &rdn );
217
218         parent = e;
219         ceparent = ce;
220
221         /* Create backend nodes. Skip if they don't provide a cf_table.
222          * There usually aren't any of these.
223          */
224         bi = backendInfo;
225         for (i=0; i<nBackendInfo; i++, bi++) {
226                 if (!bi->bi_cf_table) continue;
227                 if (!bi->bi_private) continue;
228
229                 if ( buflen < STRLENOF("olcbackend=")+strlen(bi->bi_type)+1) {
230                         buflen = STRLENOF("olcbackend=") + strlen(bi->bi_type)+1;
231                         buf = realloc(buf, buflen);
232                 }
233                 rdn.bv_val = buf;
234                 rdn.bv_len = sprintf(buf, "olcBackend=%s", bi->bi_type);
235                 e = config_alloc_entry( &parent->e_nname, &rdn );
236                 ce = e->e_private;
237                 ce->ce_table = bi->bi_cf_table;
238                 config_build_entry( e, bi->bi_private, "olcBackendConfig",
239                         &rdn );
240                 if ( !ceparent->ce_kids ) {
241                         ceparent->ce_kids = ce;
242                 } else {
243                         ceprev->ce_sibs = ce;
244                 }
245                 ceprev = ce;
246         }
247
248         /* Create database nodes... */
249         for (i=0; i<nBackendDB; i++) {
250                 if ( i == 0 ) {
251                         bptr = frontendDB;
252                 } else {
253                         bptr = &backendDB[i];
254                 }
255                 bi = bptr->bd_info;
256                 if ( buflen < STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1) {
257                         buflen = STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1;
258                         buf = realloc(buf, buflen);
259                 }
260                 rdn.bv_val = buf;
261                 rdn.bv_len = sprintf(buf, "olcDatabase={%0x}%s", i, bi->bi_type);
262                 e = config_alloc_entry( &parent->e_nname, &rdn );
263                 ce = e->e_private;
264                 ce->ce_table = bptr->be_cf_table;
265                 config_build_entry( e, bptr->be_private, "olcDatabaseConfig",
266                         &rdn );
267                 if ( !ceparent->ce_kids ) {
268                         ceparent->ce_kids = ce;
269                 } else {
270                         ceprev->ce_sibs = ce;
271                 }
272                 ceprev = ce;
273                 /* Iterate through overlays */
274                 
275         }
276         /* Create includeFile nodes... */
277
278         return 0;
279 }
280
281 static int
282 config_back_db_destroy( Backend *be )
283 {
284         free( be->be_private );
285         return 0;
286 }
287
288 int
289 config_back_initialize( BackendInfo *bi )
290 {
291         bi->bi_open = 0;
292         bi->bi_close = 0;
293         bi->bi_config = 0;
294         bi->bi_destroy = 0;
295
296         bi->bi_db_init = 0;
297         bi->bi_db_config = 0;
298         bi->bi_db_open = config_back_db_open;
299         bi->bi_db_close = 0;
300         bi->bi_db_destroy = config_back_db_destroy;
301
302         bi->bi_op_bind = config_back_bind;
303         bi->bi_op_unbind = 0;
304         bi->bi_op_search = config_back_search;
305         bi->bi_op_compare = 0;
306         bi->bi_op_modify = 0;
307         bi->bi_op_modrdn = 0;
308         bi->bi_op_add = 0;
309         bi->bi_op_delete = 0;
310         bi->bi_op_abandon = 0;
311
312         bi->bi_extended = 0;
313
314         bi->bi_chk_referrals = 0;
315
316         bi->bi_connection_init = 0;
317         bi->bi_connection_destroy = 0;
318
319         return 0;
320 }
321
322 void config_back_init( ConfigFile *cfp, ConfigTable *ct )
323 {
324         BackendInfo bi = {0};
325         BackendDB *be;
326         struct berval dn;
327         CfBackInfo *cfb;
328
329         bi.bi_type = "config";
330         bi.bi_init = config_back_initialize;
331         bi.bi_cf_table = ct;
332         backend_add( &bi );
333         be = backend_db_init( bi.bi_type );
334         ber_str2bv( CONFIG_DN, 0, 1, &be->be_rootdn );
335         ber_dupbv( &be->be_rootndn, &be->be_rootdn );
336         ber_dupbv( &dn, &be->be_rootdn );
337         ber_bvarray_add( &be->be_suffix, &dn );
338         ber_dupbv( &dn, &be->be_rootdn );
339         ber_bvarray_add( &be->be_nsuffix, &dn );
340         cfb = ch_calloc( 1, sizeof(CfBackInfo));
341         cfb->cb_config = cfp;
342         be->be_private = cfb;
343 }