]> git.sur5r.net Git - openldap/blob - servers/slapd/bconfig.c
Fix compiler error and warnings.
[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         BackendInfo *ce_bi;
36         BackendDB *ce_be;
37 } CfEntryInfo;
38
39 typedef struct {
40         ConfigFile *cb_config;
41         CfEntryInfo *cb_root;
42 } CfBackInfo;
43
44 static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
45         *cfAd_include;
46
47 static ObjectClass *cfOc_global, *cfOc_backend, *cfOc_database,
48         *cfOc_include, *cfOc_overlay;
49
50 static struct oc_info {
51         char *def;
52         ObjectClass **oc;
53 } cf_ocs[] = {
54         { "( OLcfgOc:1 "
55                 "NAME 'olcConfig' "
56                 "DESC 'OpenLDAP configuration object' "
57                 "ABSTRACT SUP top "
58                 "MAY ( cn $ olcConfigFile ) )", NULL },
59         { "( OLcfgOc:3 "
60                 "NAME 'olcGlobal' "
61                 "DESC 'OpenLDAP Global configuration options' "
62                 "SUP olcConfig STRUCTURAL "
63                 "MAY ( olcAccess $ olcAllows $ olcArgsFile $ olcAttributeOptions $ "
64                  "olcAuthRewrite $ olcAuthzPolicy $ olcAuthzRegexp $ "
65                  "olcConcurrency $ olcConnMaxPending $ olcConnMaxPendingAuth $ "
66                  "olcDefaultSearchBase $ olcDisallows $ olcGentleHUP $ "
67                  "olcIdleTimeout $ olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
68                  "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
69                  "olcLogLevel $ olcModuleLoad $ olcModulePath $ olcObjectIdentifier $ "
70                  "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
71                  "olcPlugin $ olcPluginLogFile $ olcReadOnly $ olcReferral $ "
72                  "olcReplicaPidFile $ olcReplicaArgsFile $ olcReplicationInterval $ "
73                  "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
74                  "olcRootDSE $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
75                  "olcSchemaCheck $ olcSchemaDN $ olcSecurity $ olcSizeLimit $ "
76                  "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ "
77                  "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
78                  "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
79                  "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
80                  "olcTLSRandFile $ olcTLSVerifyClient ) )", &cfOc_global },
81         { "( OLcfgOc:4 "
82                 "NAME 'olcBackendConfig' "
83                 "DESC 'OpenLDAP Backend-specific options' "
84                 "SUP olcConfig STRUCTURAL "
85                 "MAY ( olcBackend ) )", &cfOc_backend },
86         { "( OLcfgOc:5 "
87                 "NAME 'olcDatabaseConfig' "
88                 "DESC 'OpenLDAP Database-specific options' "
89                 "SUP olcConfig STRUCTURAL "
90                 "MAY ( olcAccess $ olcDatabase $ olcLastMod $ olcLimits $ "
91                  "olcMaxDerefDepth $ olcReadOnly $ olcReplica $ olcReplogFile $ "
92                  "olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ olcSchemaDN $ "
93                  "olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ "
94                  "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )", &cfOc_database },
95         { "( OLcfgOc:6 "
96                 "NAME 'olcIncludeFile' "
97                 "DESC 'OpenLDAP configuration include file' "
98                 "SUP olcConfig STRUCTURAL "
99                 "MAY ( olcInclude $ olcModuleLoad $ olcModulePath $ olcRootDSE ) )",
100                 &cfOc_include },
101         { "( OLcfgOc:7 "
102                 "NAME 'olcOverlayConfig' "
103                 "DESC 'OpenLDAP Overlay-specific options' "
104                 "SUP olcConfig STRUCTURAL "
105                 "MAY ( olcOverlay ) )", &cfOc_overlay },
106         { NULL, NULL }
107 };
108
109 static int
110 config_back_bind( Operation *op, SlapReply *rs )
111 {
112         if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
113                 ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
114                 /* frontend sends result */
115                 return LDAP_SUCCESS;
116         }
117
118         rs->sr_err = LDAP_INVALID_CREDENTIALS;
119         send_ldap_result( op, rs );
120
121         return rs->sr_err;
122 }
123
124 static CfEntryInfo *
125 config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
126 {
127         struct berval cdn;
128         char *c;
129
130         if ( dn_match( &root->ce_entry->e_nname, dn ))
131                 return root;
132
133         c = dn->bv_val+dn->bv_len;
134         for (;*c != ',';c--);
135
136         while(root) {
137                 *last = root;
138                 for (--c;c>dn->bv_val && *c != ',';c--);
139                 if ( *c == ',' )
140                         c++;
141                 cdn.bv_val = c;
142                 cdn.bv_len = dn->bv_len - (c-dn->bv_val);
143
144                 root = root->ce_kids;
145
146                 for (;root;root=root->ce_sibs) {
147                         if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
148                                 if ( cdn.bv_val == dn->bv_val ) {
149                                         return root;
150                                 }
151                                 break;
152                         }
153                 }
154         }
155         return root;
156 }
157
158 static int
159 config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
160 {
161         int rc = 0;
162
163         if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
164         {
165                 rs->sr_attrs = op->ors_attrs;
166                 rs->sr_entry = ce->ce_entry;
167                 rc = send_search_entry( op, rs );
168         }
169         if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
170                 if ( ce->ce_kids ) {
171                         rc = config_send( op, rs, ce->ce_kids, 1 );
172                         if ( rc ) return rc;
173                 }
174                 if ( depth ) {
175                         for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
176                                 rc = config_send( op, rs, ce, 0 );
177                                 if ( rc ) break;
178                         }
179                 }
180         }
181         return rc;
182 }
183
184 static int
185 config_back_search( Operation *op, SlapReply *rs )
186 {
187         CfBackInfo *cfb;
188         CfEntryInfo *ce, *last;
189         int rc;
190
191         if ( !be_isroot( op ) ) {
192                 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
193                 send_ldap_result( op, rs );
194         }
195
196         cfb = (CfBackInfo *)op->o_bd->be_private;
197
198         ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
199         if ( !ce ) {
200                 if ( last )
201                         rs->sr_matched = last->ce_entry->e_name.bv_val;
202                 rs->sr_err = LDAP_NO_SUCH_OBJECT;
203                 goto out;
204         }
205         switch ( op->ors_scope ) {
206         case LDAP_SCOPE_BASE:
207         case LDAP_SCOPE_SUBTREE:
208                 config_send( op, rs, ce, 0 );
209                 break;
210                 
211         case LDAP_SCOPE_ONELEVEL:
212                 for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
213                         config_send( op, rs, ce, 1 );
214                 }
215                 break;
216         }
217                 
218         rs->sr_err = LDAP_SUCCESS;
219 out:
220         send_ldap_result( op, rs );
221         return 0;
222 }
223
224 static Entry *
225 config_alloc_entry( struct berval *pdn, struct berval *rdn )
226 {
227         Entry *e = ch_calloc( 1, sizeof(Entry) );
228         CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
229         e->e_private = ce;
230         ce->ce_entry = e;
231         build_new_dn( &e->e_name, pdn, rdn, NULL );
232         ber_dupbv( &e->e_nname, &e->e_name );
233         return e;
234 }
235
236 #define NO_TABLE        0
237 #define BI_TABLE        1
238 #define BE_TABLE        2
239
240 static int
241 config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
242          struct berval *rdn, ConfigTable *ct, int table )
243 {
244         struct berval vals[2];
245         struct berval ad_name;
246         AttributeDescription *ad = NULL;
247         int rc, i;
248         char *ptr;
249         const char *text;
250         AttributeType **at;
251
252         BER_BVZERO( &vals[1] );
253
254         vals[0] = oc->soc_cname;
255         attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
256         ptr = strchr(rdn->bv_val, '=');
257         ad_name.bv_val = rdn->bv_val;
258         ad_name.bv_len = ptr - rdn->bv_val;
259         rc = slap_bv2ad( &ad_name, &ad, &text );
260         if ( rc ) {
261                 return rc;
262         }
263         vals[0].bv_val = ptr+1;
264         vals[0].bv_len = rdn->bv_len - (vals[0].bv_val - rdn->bv_val);
265         attr_merge(e, ad, vals, NULL );
266
267         for (at=oc->soc_allowed;*at;at++) {
268                 /* Skip the naming attr */
269                 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
270                         continue;
271                 for (i=0;ct[i].name;i++) {
272                         if (ct[i].ad == (*at)->sat_ad)
273                                 break;
274                 }
275                 rc = config_get_vals(&ct[i], c);
276                 if (rc == LDAP_SUCCESS) {
277                         attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
278                         ber_bvarray_free( c->rvalue_nvals );
279                         ber_bvarray_free( c->rvalue_vals );
280                 }
281         }
282
283         if ( table ) {
284                 if ( table == BI_TABLE )
285                         ct = c->bi->bi_cf_table;
286                 else
287                         ct = c->be->be_cf_table;
288                 for (;ct && ct->name;ct++) {
289                         if (!ct->ad) continue;
290                         rc = config_get_vals(ct, c);
291                         if (rc == LDAP_SUCCESS) {
292                                 attr_merge(e, ct->ad, c->rvalue_vals, c->rvalue_nvals);
293                         }
294                 }
295         }
296
297         return 0;
298 }
299
300 static CfEntryInfo *
301 config_build_includes( ConfigArgs *c, Entry *parent )
302 {
303         Entry *e;
304         int i;
305         ConfigFile *cf = (ConfigFile *)c->line;
306         CfEntryInfo *ce, *ceparent, *ceprev;
307
308         ceparent = parent->e_private;
309
310         for (i=0; cf; cf=cf->c_sibs, i++) {
311                 c->value_dn.bv_val = c->log;
312                 c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include{%d}", i);
313                 e = config_alloc_entry( &parent->e_nname, &c->value_dn );
314                 c->line = (char *)cf;
315                 config_build_entry( c, e, cfOc_include, &c->value_dn,
316                         c->bi->bi_cf_table, NO_TABLE );
317                 ce = e->e_private;
318                 if ( !ceparent->ce_kids ) {
319                         ceparent->ce_kids = ce;
320                 } else {
321                         ceprev->ce_sibs = ce;
322                 }
323                 ceprev = ce;
324                 if ( cf->c_kids ) {
325                         c->line = (char *)cf->c_kids;
326                         config_build_includes( c, e );
327                 }
328         }
329         return ce;
330 }
331
332 static int
333 config_back_db_open( BackendDB *be )
334 {
335         CfBackInfo *cfb = be->be_private;
336         struct berval rdn;
337         Entry *e, *parent;
338         CfEntryInfo *ce, *ceparent, *ceprev;
339         int i, rc;
340         BackendInfo *bi;
341         BackendDB *bptr;
342         ConfigArgs c;
343         ConfigTable *ct;
344
345         /* create root of tree */
346         ber_str2bv( CONFIG_DN, STRLENOF( CONFIG_DN ), 0, &rdn );
347         e = config_alloc_entry( NULL, &rdn );
348         ce = e->e_private;
349         cfb->cb_root = ce;
350         c.be = be;
351         c.bi = be->bd_info;
352         c.line = (char *)cfb->cb_config;
353         ct = c.bi->bi_cf_table;
354         config_build_entry( &c, e, cfOc_global, &rdn, ct, NO_TABLE );
355
356         parent = e;
357         ceparent = ce;
358
359         /* Create includeFile nodes... */
360         if ( cfb->cb_config->c_kids ) {
361                 c.line = (char *)cfb->cb_config->c_kids;
362                 ceprev = config_build_includes( &c, parent );
363         }
364
365         /* Create backend nodes. Skip if they don't provide a cf_table.
366          * There usually aren't any of these.
367          */
368         
369         c.line = 0;
370         bi = backendInfo;
371         for (i=0; i<nBackendInfo; i++, bi++) {
372                 if (!bi->bi_cf_table) continue;
373                 if (!bi->bi_private) continue;
374
375                 rdn.bv_val = c.log;
376                 rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type);
377                 e = config_alloc_entry( &parent->e_nname, &rdn );
378                 ce = e->e_private;
379                 ce->ce_bi = bi;
380                 c.bi = bi;
381                 config_build_entry( &c, e, cfOc_backend, &rdn, ct, BI_TABLE );
382                 if ( !ceparent->ce_kids ) {
383                         ceparent->ce_kids = ce;
384                 } else {
385                         ceprev->ce_sibs = ce;
386                 }
387                 ceprev = ce;
388         }
389
390         /* Create database nodes... */
391         for (i=0; i<nBackendDB; i++) {
392                 slap_overinfo *oi = NULL;
393                 if ( i == 0 ) {
394                         bptr = frontendDB;
395                 } else {
396                         bptr = &backendDB[i];
397                 }
398                 if ( overlay_is_over( bptr )) {
399                         oi = bptr->bd_info->bi_private;
400                         bi = oi->oi_orig;
401                 } else {
402                         bi = bptr->bd_info;
403                 }
404                 rdn.bv_val = c.log;
405                 rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s", cfAd_database->ad_cname.bv_val,
406                         i, bi->bi_type);
407                 e = config_alloc_entry( &parent->e_nname, &rdn );
408                 ce = e->e_private;
409                 c.be = bptr;
410                 c.bi = bi;
411                 ce->ce_be = c.be;
412                 ce->ce_bi = c.bi;
413                 config_build_entry( &c, e, cfOc_database, &rdn, ct, BE_TABLE );
414                 if ( !ceparent->ce_kids ) {
415                         ceparent->ce_kids = ce;
416                 } else {
417                         ceprev->ce_sibs = ce;
418                 }
419                 ceprev = ce;
420                 /* Iterate through overlays */
421                 if ( oi ) {
422                         slap_overinst *on;
423                         Entry *oe;
424                         CfEntryInfo *opar = ce, *oprev = NULL;
425                         int j;
426
427                         for (j=0,on=oi->oi_list; on; j++,on=on->on_next) {
428                                 rdn.bv_val = c.log;
429                                 rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s",
430                                         cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type );
431                                 oe = config_alloc_entry( &e->e_nname, &rdn );
432                                 ce = oe->e_private;
433                                 c.be = bptr;
434                                 c.bi = &on->on_bi;
435                                 ce->ce_be = c.be;
436                                 ce->ce_bi = c.bi;
437                                 config_build_entry( &c, oe, cfOc_overlay, &rdn, ct, BI_TABLE );
438                                 if ( !opar->ce_kids ) {
439                                         opar->ce_kids = ce;
440                                 } else {
441                                         oprev->ce_sibs = ce;
442                                 }
443                                 oprev = ce;
444                         }
445                 }
446         }
447
448         return 0;
449 }
450
451 static int
452 config_back_db_destroy( Backend *be )
453 {
454         free( be->be_private );
455         return 0;
456 }
457
458 int
459 config_back_initialize( BackendInfo *bi )
460 {
461         bi->bi_open = 0;
462         bi->bi_close = 0;
463         bi->bi_config = 0;
464         bi->bi_destroy = 0;
465
466         bi->bi_db_init = 0;
467         bi->bi_db_config = 0;
468         bi->bi_db_open = config_back_db_open;
469         bi->bi_db_close = 0;
470         bi->bi_db_destroy = config_back_db_destroy;
471
472         bi->bi_op_bind = config_back_bind;
473         bi->bi_op_unbind = 0;
474         bi->bi_op_search = config_back_search;
475         bi->bi_op_compare = 0;
476         bi->bi_op_modify = 0;
477         bi->bi_op_modrdn = 0;
478         bi->bi_op_add = 0;
479         bi->bi_op_delete = 0;
480         bi->bi_op_abandon = 0;
481
482         bi->bi_extended = 0;
483
484         bi->bi_chk_referrals = 0;
485
486         bi->bi_connection_init = 0;
487         bi->bi_connection_destroy = 0;
488
489         return 0;
490 }
491
492 static struct {
493         char *name;
494         AttributeDescription **desc;
495         AttributeDescription *sub;
496 } ads[] = {
497         { "attribute", NULL, NULL },
498         { "backend", &cfAd_backend, NULL },
499         { "database", &cfAd_database, NULL },
500         { "ditcontentrule", NULL, NULL },
501         { "include", &cfAd_include, NULL },
502         { "objectclass", NULL, NULL },
503         { "overlay", &cfAd_overlay, NULL },
504         { NULL, NULL, NULL }
505 };
506
507 int config_back_init( ConfigFile *cfp, ConfigTable *ct )
508 {
509         BackendInfo bi = {0};
510         BackendDB *be;
511         struct berval dn;
512         CfBackInfo *cfb;
513         int i;
514
515         bi.bi_type = "config";
516         bi.bi_init = config_back_initialize;
517         bi.bi_cf_table = ct;
518         backend_add( &bi );
519         be = backend_db_init( bi.bi_type );
520         ber_str2bv( CONFIG_DN, 0, 1, &be->be_rootdn );
521         ber_dupbv( &be->be_rootndn, &be->be_rootdn );
522         ber_dupbv( &dn, &be->be_rootdn );
523         ber_bvarray_add( &be->be_suffix, &dn );
524         ber_dupbv( &dn, &be->be_rootdn );
525         ber_bvarray_add( &be->be_nsuffix, &dn );
526         cfb = ch_calloc( 1, sizeof(CfBackInfo));
527         cfb->cb_config = cfp;
528         be->be_private = cfb;
529
530         /* set up the notable AttributeDescriptions */
531         ads[0].sub = slap_schema.si_ad_attributeTypes;
532         ads[3].sub = slap_schema.si_ad_ditContentRules;
533         ads[5].sub = slap_schema.si_ad_objectClasses;
534
535         i = 0;
536         for (;ct->name;ct++) {
537                 if (strcmp(ct->name, ads[i].name)) continue;
538                 if (ads[i].sub) {
539                         ct->ad = ads[i].sub;
540                 } else {
541                         *ads[i].desc = ct->ad;
542                 }
543                 i++;
544                 if (!ads[i].name) break;
545         }
546
547         /* set up the objectclasses */
548         for (i=0;cf_ocs[i].def;i++) {
549                 LDAPObjectClass *oc;
550                 int code;
551                 const char *err;
552
553                 oc = ldap_str2objectclass( cf_ocs[i].def, &code, &err,
554                         LDAP_SCHEMA_ALLOW_ALL );
555                 if ( !oc ) {
556                         fprintf( stderr, "config_back_init: objectclass \"%s\": %s, %s\n",
557                                 cf_ocs[i].def, ldap_scherr2str(code), err );
558                         return code;
559                 }
560                 code = oc_add(oc,0,&err);
561                 if ( code ) {
562                         fprintf( stderr, "config_back_init: objectclass \"%s\": %s, %s\n",
563                                 cf_ocs[i].def, scherr2str(code), err );
564                         return code;
565                 }
566                 if ( cf_ocs[i].oc ) {
567                         *cf_ocs[i].oc = oc_find(oc->oc_names[0]);
568                 }
569                 ldap_memfree(oc);
570         }
571         return 0;
572 }