init.c revision 1.3
1/*	$NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $	*/
2
3/* init.c - initialize relay backend */
4/* $OpenLDAP$ */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2004-2021 The OpenLDAP Foundation.
8 * Portions Copyright 2004 Pierangelo Masarati.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19/* ACKNOWLEDGEMENTS:
20 * This work was initially developed by Pierangelo Masarati for inclusion
21 * in OpenLDAP Software.
22 */
23
24#include <sys/cdefs.h>
25__RCSID("$NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $");
26
27#include "portable.h"
28
29#include <stdio.h>
30#include <ac/string.h>
31
32#include "slap.h"
33#include "slap-config.h"
34#include "back-relay.h"
35
36static ConfigDriver relay_back_cf;
37
38static ConfigTable relaycfg[] = {
39	{ "relay", "relay", 2, 2, 0,
40		ARG_MAGIC|ARG_DN|ARG_QUOTE,
41		relay_back_cf, "( OLcfgDbAt:5.1 "
42			"NAME 'olcRelay' "
43			"DESC 'Relay DN' "
44			"EQUALITY distinguishedNameMatch "
45			"SYNTAX OMsDN "
46			"SINGLE-VALUE )",
47		NULL, NULL },
48	{ NULL }
49};
50
51static ConfigOCs relayocs[] = {
52	{ "( OLcfgDbOc:5.1 "
53		"NAME 'olcRelayConfig' "
54		"DESC 'Relay backend configuration' "
55		"SUP olcDatabaseConfig "
56		"MAY ( olcRelay "
57		") )",
58		 	Cft_Database, relaycfg},
59	{ NULL, 0, NULL }
60};
61
62static int
63relay_back_cf( ConfigArgs *c )
64{
65	relay_back_info	*ri = ( relay_back_info * )c->be->be_private;
66	int		rc = 0;
67
68	if ( c->op == SLAP_CONFIG_EMIT ) {
69		if ( ri != NULL && !BER_BVISNULL( &ri->ri_realsuffix ) ) {
70			value_add_one( &c->rvalue_vals, &ri->ri_realsuffix );
71			return 0;
72		}
73		return 1;
74
75	} else if ( c->op == LDAP_MOD_DELETE ) {
76		if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
77			ch_free( ri->ri_realsuffix.bv_val );
78			BER_BVZERO( &ri->ri_realsuffix );
79			ri->ri_bd = NULL;
80			return 0;
81		}
82		return 1;
83
84	} else {
85		BackendDB *bd;
86
87		assert( ri != NULL );
88		assert( BER_BVISNULL( &ri->ri_realsuffix ) );
89
90		if ( c->be->be_nsuffix == NULL ) {
91			snprintf( c->cr_msg, sizeof( c->cr_msg),
92				"\"relay\" directive "
93				"must appear after \"suffix\"" );
94			Log( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
95				"%s: %s.\n", c->log, c->cr_msg );
96			rc = 1;
97			goto relay_done;
98		}
99
100		if ( !BER_BVISNULL( &c->be->be_nsuffix[ 1 ] ) ) {
101			snprintf( c->cr_msg, sizeof( c->cr_msg),
102				"relaying of multiple suffix "
103				"database not supported" );
104			Log( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
105				"%s: %s.\n", c->log, c->cr_msg );
106			rc = 1;
107			goto relay_done;
108		}
109
110		bd = select_backend( &c->value_ndn, 1 );
111		if ( bd == NULL ) {
112			snprintf( c->cr_msg, sizeof( c->cr_msg),
113				"cannot find database "
114				"of relay dn \"%s\" "
115				"in \"olcRelay <dn>\"\n",
116				c->value_dn.bv_val );
117			Log( LDAP_DEBUG_CONFIG, LDAP_LEVEL_ERR,
118				"%s: %s.\n", c->log, c->cr_msg );
119
120		} else if ( bd->be_private == c->be->be_private ) {
121			snprintf( c->cr_msg, sizeof( c->cr_msg),
122				"relay dn \"%s\" would call self "
123				"in \"relay <dn>\" line\n",
124				c->value_dn.bv_val );
125			Log( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
126				"%s: %s.\n", c->log, c->cr_msg );
127			rc = 1;
128			goto relay_done;
129		}
130
131		ri->ri_realsuffix = c->value_ndn;
132		BER_BVZERO( &c->value_ndn );
133
134relay_done:;
135		ch_free( c->value_dn.bv_val );
136		ch_free( c->value_ndn.bv_val );
137	}
138
139	return rc;
140}
141
142int
143relay_back_initialize( BackendInfo *bi )
144{
145	bi->bi_init = 0;
146	bi->bi_open = 0;
147	bi->bi_config = 0;
148	bi->bi_close = 0;
149	bi->bi_destroy = 0;
150
151	bi->bi_db_init = relay_back_db_init;
152	bi->bi_db_config = config_generic_wrapper;
153	bi->bi_db_open = relay_back_db_open;
154#if 0
155	bi->bi_db_close = relay_back_db_close;
156#endif
157	bi->bi_db_destroy = relay_back_db_destroy;
158
159	bi->bi_op_bind = relay_back_op_bind;
160	bi->bi_op_search = relay_back_op_search;
161	bi->bi_op_compare = relay_back_op_compare;
162	bi->bi_op_modify = relay_back_op_modify;
163	bi->bi_op_modrdn = relay_back_op_modrdn;
164	bi->bi_op_add = relay_back_op_add;
165	bi->bi_op_delete = relay_back_op_delete;
166	bi->bi_extended = relay_back_op_extended;
167	bi->bi_entry_release_rw = relay_back_entry_release_rw;
168	bi->bi_entry_get_rw = relay_back_entry_get_rw;
169	bi->bi_operational = relay_back_operational;
170	bi->bi_has_subordinates = relay_back_has_subordinates;
171
172	bi->bi_cf_ocs = relayocs;
173
174	return config_register_schema( relaycfg, relayocs );
175}
176
177int
178relay_back_db_init( Backend *be, ConfigReply *cr)
179{
180	relay_back_info		*ri;
181
182	be->be_private = NULL;
183
184	ri = (relay_back_info *) ch_calloc( 1, RELAY_INFO_SIZE );
185	if ( ri == NULL ) {
186 		return -1;
187 	}
188
189	ri->ri_bd = NULL;
190	BER_BVZERO( &ri->ri_realsuffix );
191	ri->ri_massage = 0;
192
193	be->be_cf_ocs = be->bd_info->bi_cf_ocs;
194
195	be->be_private = (void *)ri;
196
197	return 0;
198}
199
200int
201relay_back_db_open( Backend *be, ConfigReply *cr )
202{
203	relay_back_info		*ri = (relay_back_info *)be->be_private;
204
205	assert( ri != NULL );
206
207	if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
208		ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );
209
210		/* must be there: it was during config! */
211		if ( ri->ri_bd == NULL ) {
212			snprintf( cr->msg, sizeof( cr->msg),
213				"cannot find database "
214				"of relay dn \"%s\" "
215				"in \"olcRelay <dn>\"\n",
216				ri->ri_realsuffix.bv_val );
217			Log( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
218				"relay_back_db_open: %s.\n", cr->msg );
219
220			return 1;
221		}
222
223		/* inherit controls */
224		AC_MEMCPY( be->bd_self->be_ctrls, ri->ri_bd->be_ctrls, sizeof( be->be_ctrls ) );
225
226	} else {
227		/* inherit all? */
228		AC_MEMCPY( be->bd_self->be_ctrls, frontendDB->be_ctrls, sizeof( be->be_ctrls ) );
229	}
230
231	return 0;
232}
233
234int
235relay_back_db_close( Backend *be, ConfigReply *cr )
236{
237	return 0;
238}
239
240int
241relay_back_db_destroy( Backend *be, ConfigReply *cr)
242{
243	relay_back_info		*ri = (relay_back_info *)be->be_private;
244
245	if ( ri ) {
246		if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
247			ch_free( ri->ri_realsuffix.bv_val );
248		}
249		ch_free( ri );
250	}
251
252	return 0;
253}
254
255#if SLAPD_RELAY == SLAPD_MOD_DYNAMIC
256
257/* conditionally define the init_module() function */
258SLAP_BACKEND_INIT_MODULE( relay )
259
260#endif /* SLAPD_RELAY == SLAPD_MOD_DYNAMIC */
261