]> git.sur5r.net Git - openldap/blob - servers/slapd/bconfig.c
Simple values retrievable
[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, rc, buflen = 0;
205         char *buf = NULL;
206         BackendInfo *bi;
207         BackendDB *bptr;
208         ConfigArgs c;
209         ConfigTable *ct;
210
211         /* create root of tree */
212         ber_str2bv( CONFIG_DN, STRLENOF( CONFIG_DN ), 0, &rdn );
213         e = config_alloc_entry( NULL, &rdn );
214         ce = e->e_private;
215         ce->ce_table = be->bd_info->bi_cf_table;
216         cfb->cb_root = ce;
217
218         config_build_entry( e, be->be_private, "olcGlobal", &rdn );
219         c.be = be;
220         c.bi = be->bd_info;
221         ct = ce->ce_table;
222         for (ct=ce->ce_table; ct->name; ct++) {
223                 if (!ct->ad) continue;
224                 if (ct->arg_type & ARG_DB) continue;
225                 rc = config_get_vals(ct, &c);
226                 if (rc == LDAP_SUCCESS) {
227                         attr_merge(e, ct->ad, c.rvalue_vals, c.rvalue_nvals);
228                 }
229         }
230
231         parent = e;
232         ceparent = ce;
233
234         /* Create backend nodes. Skip if they don't provide a cf_table.
235          * There usually aren't any of these.
236          */
237         bi = backendInfo;
238         for (i=0; i<nBackendInfo; i++, bi++) {
239                 if (!bi->bi_cf_table) continue;
240                 if (!bi->bi_private) continue;
241
242                 if ( buflen < STRLENOF("olcbackend=")+strlen(bi->bi_type)+1) {
243                         buflen = STRLENOF("olcbackend=") + strlen(bi->bi_type)+1;
244                         buf = realloc(buf, buflen);
245                 }
246                 rdn.bv_val = buf;
247                 rdn.bv_len = sprintf(buf, "olcBackend=%s", bi->bi_type);
248                 e = config_alloc_entry( &parent->e_nname, &rdn );
249                 ce = e->e_private;
250                 ce->ce_table = bi->bi_cf_table;
251                 config_build_entry( e, bi->bi_private, "olcBackendConfig",
252                         &rdn );
253                 if ( !ceparent->ce_kids ) {
254                         ceparent->ce_kids = ce;
255                 } else {
256                         ceprev->ce_sibs = ce;
257                 }
258                 ceprev = ce;
259         }
260
261         /* Create database nodes... */
262         for (i=0; i<nBackendDB; i++) {
263                 if ( i == 0 ) {
264                         bptr = frontendDB;
265                 } else {
266                         bptr = &backendDB[i];
267                 }
268                 bi = bptr->bd_info;
269                 if ( buflen < STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1) {
270                         buflen = STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1;
271                         buf = realloc(buf, buflen);
272                 }
273                 rdn.bv_val = buf;
274                 rdn.bv_len = sprintf(buf, "olcDatabase={%0x}%s", i, bi->bi_type);
275                 e = config_alloc_entry( &parent->e_nname, &rdn );
276                 ce = e->e_private;
277                 ce->ce_table = bptr->be_cf_table;
278                 config_build_entry( e, bptr->be_private, "olcDatabaseConfig",
279                         &rdn );
280                 c.be = bptr;
281                 c.bi = bi;
282                 ct = be->bd_info->bi_cf_table;
283                 for (; ct->name; ct++) {
284                         if (!ct->ad) continue;
285                         if (!(ct->arg_type & (ARG_DB|ARG_MAY_DB))) continue;
286                         rc = config_get_vals(ct, &c);
287                         if (rc == LDAP_SUCCESS) {
288                                 attr_merge(e, ct->ad, c.rvalue_vals, c.rvalue_nvals);
289                         }
290                 }
291
292                 if ( !ceparent->ce_kids ) {
293                         ceparent->ce_kids = ce;
294                 } else {
295                         ceprev->ce_sibs = ce;
296                 }
297                 ceprev = ce;
298                 /* Iterate through overlays */
299                 
300         }
301         /* Create includeFile nodes... */
302
303         return 0;
304 }
305
306 static int
307 config_back_db_destroy( Backend *be )
308 {
309         free( be->be_private );
310         return 0;
311 }
312
313 int
314 config_back_initialize( BackendInfo *bi )
315 {
316         bi->bi_open = 0;
317         bi->bi_close = 0;
318         bi->bi_config = 0;
319         bi->bi_destroy = 0;
320
321         bi->bi_db_init = 0;
322         bi->bi_db_config = 0;
323         bi->bi_db_open = config_back_db_open;
324         bi->bi_db_close = 0;
325         bi->bi_db_destroy = config_back_db_destroy;
326
327         bi->bi_op_bind = config_back_bind;
328         bi->bi_op_unbind = 0;
329         bi->bi_op_search = config_back_search;
330         bi->bi_op_compare = 0;
331         bi->bi_op_modify = 0;
332         bi->bi_op_modrdn = 0;
333         bi->bi_op_add = 0;
334         bi->bi_op_delete = 0;
335         bi->bi_op_abandon = 0;
336
337         bi->bi_extended = 0;
338
339         bi->bi_chk_referrals = 0;
340
341         bi->bi_connection_init = 0;
342         bi->bi_connection_destroy = 0;
343
344         return 0;
345 }
346
347 void config_back_init( ConfigFile *cfp, ConfigTable *ct )
348 {
349         BackendInfo bi = {0};
350         BackendDB *be;
351         struct berval dn;
352         CfBackInfo *cfb;
353
354         bi.bi_type = "config";
355         bi.bi_init = config_back_initialize;
356         bi.bi_cf_table = ct;
357         backend_add( &bi );
358         be = backend_db_init( bi.bi_type );
359         ber_str2bv( CONFIG_DN, 0, 1, &be->be_rootdn );
360         ber_dupbv( &be->be_rootndn, &be->be_rootdn );
361         ber_dupbv( &dn, &be->be_rootdn );
362         ber_bvarray_add( &be->be_suffix, &dn );
363         ber_dupbv( &dn, &be->be_rootdn );
364         ber_bvarray_add( &be->be_nsuffix, &dn );
365         cfb = ch_calloc( 1, sizeof(CfBackInfo));
366         cfb->cb_config = cfp;
367         be->be_private = cfb;
368 }