config.c revision 1.1.1.6
1/*	$NetBSD: config.c,v 1.1.1.6 2018/02/06 01:53:17 christos Exp $	*/
2
3/* config.c - sock backend configuration file routine */
4/* $OpenLDAP$ */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2007-2017 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/* ACKNOWLEDGEMENTS:
19 * This work was initially developed by Brian Candler for inclusion
20 * in OpenLDAP Software. Dynamic config support by Howard Chu.
21 */
22
23#include <sys/cdefs.h>
24__RCSID("$NetBSD: config.c,v 1.1.1.6 2018/02/06 01:53:17 christos Exp $");
25
26#include "portable.h"
27
28#include <stdio.h>
29
30#include <ac/string.h>
31#include <ac/socket.h>
32
33#include "slap.h"
34#include "config.h"
35#include "back-sock.h"
36
37static ConfigDriver bs_cf_gen;
38static int sock_over_setup();
39static slap_response sock_over_response;
40
41enum {
42	BS_EXT = 1,
43	BS_OPS,
44	BS_RESP
45};
46
47/* The number of overlay-only config attrs */
48#define NUM_OV_ATTRS	2
49
50static ConfigTable bscfg[] = {
51	{ "sockops", "ops", 2, 0, 0, ARG_MAGIC|BS_OPS,
52		bs_cf_gen, "( OLcfgDbAt:7.3 NAME 'olcOvSocketOps' "
53			"DESC 'Operation types to forward' "
54			"EQUALITY caseIgnoreMatch "
55			"SYNTAX OMsDirectoryString )", NULL, NULL },
56	{ "sockresps", "resps", 2, 0, 0, ARG_MAGIC|BS_RESP,
57		bs_cf_gen, "( OLcfgDbAt:7.4 NAME 'olcOvSocketResps' "
58			"DESC 'Response types to forward' "
59			"EQUALITY caseIgnoreMatch "
60			"SYNTAX OMsDirectoryString )", NULL, NULL },
61
62	{ "socketpath", "pathname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
63		(void *)offsetof(struct sockinfo, si_sockpath),
64		"( OLcfgDbAt:7.1 NAME 'olcDbSocketPath' "
65			"DESC 'Pathname for Unix domain socket' "
66			"EQUALITY caseExactMatch "
67			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
68	{ "extensions", "ext", 2, 0, 0, ARG_MAGIC|BS_EXT,
69		bs_cf_gen, "( OLcfgDbAt:7.2 NAME 'olcDbSocketExtensions' "
70			"DESC 'binddn, peername, or ssf' "
71			"EQUALITY caseIgnoreMatch "
72			"SYNTAX OMsDirectoryString )", NULL, NULL },
73	{ NULL, NULL }
74};
75
76static ConfigOCs bsocs[] = {
77	{ "( OLcfgDbOc:7.1 "
78		"NAME 'olcDbSocketConfig' "
79		"DESC 'Socket backend configuration' "
80		"SUP olcDatabaseConfig "
81		"MUST olcDbSocketPath "
82		"MAY olcDbSocketExtensions )",
83			Cft_Database, bscfg+NUM_OV_ATTRS },
84	{ NULL, 0, NULL }
85};
86
87static ConfigOCs osocs[] = {
88	{ "( OLcfgDbOc:7.2 "
89		"NAME 'olcOvSocketConfig' "
90		"DESC 'Socket overlay configuration' "
91		"SUP olcOverlayConfig "
92		"MUST olcDbSocketPath "
93		"MAY ( olcDbSocketExtensions $ "
94			" olcOvSocketOps $ olcOvSocketResps ) )",
95			Cft_Overlay, bscfg },
96	{ NULL, 0, NULL }
97};
98
99#define SOCK_OP_BIND	0x001
100#define SOCK_OP_UNBIND	0x002
101#define SOCK_OP_SEARCH	0x004
102#define SOCK_OP_COMPARE	0x008
103#define SOCK_OP_MODIFY	0x010
104#define SOCK_OP_MODRDN	0x020
105#define SOCK_OP_ADD		0x040
106#define SOCK_OP_DELETE	0x080
107
108#define SOCK_REP_RESULT	0x001
109#define SOCK_REP_SEARCH	0x002
110
111static slap_verbmasks bs_exts[] = {
112	{ BER_BVC("binddn"), SOCK_EXT_BINDDN },
113	{ BER_BVC("peername"), SOCK_EXT_PEERNAME },
114	{ BER_BVC("ssf"), SOCK_EXT_SSF },
115	{ BER_BVC("connid"), SOCK_EXT_CONNID },
116	{ BER_BVNULL, 0 }
117};
118
119static slap_verbmasks ov_ops[] = {
120	{ BER_BVC("bind"), SOCK_OP_BIND },
121	{ BER_BVC("unbind"), SOCK_OP_UNBIND },
122	{ BER_BVC("search"), SOCK_OP_SEARCH },
123	{ BER_BVC("compare"), SOCK_OP_COMPARE },
124	{ BER_BVC("modify"), SOCK_OP_MODIFY },
125	{ BER_BVC("modrdn"), SOCK_OP_MODRDN },
126	{ BER_BVC("add"), SOCK_OP_ADD },
127	{ BER_BVC("delete"), SOCK_OP_DELETE },
128	{ BER_BVNULL, 0 }
129};
130
131static slap_verbmasks ov_resps[] = {
132	{ BER_BVC("result"), SOCK_REP_RESULT },
133	{ BER_BVC("search"), SOCK_REP_SEARCH },
134	{ BER_BVNULL, 0 }
135};
136
137static int
138bs_cf_gen( ConfigArgs *c )
139{
140	struct sockinfo	*si;
141	int rc;
142
143	if ( c->be && c->table == Cft_Database )
144		si = c->be->be_private;
145	else if ( c->bi )
146		si = c->bi->bi_private;
147	else
148		return ARG_BAD_CONF;
149
150	if ( c->op == SLAP_CONFIG_EMIT ) {
151		switch( c->type ) {
152		case BS_EXT:
153			return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals );
154		case BS_OPS:
155			return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals );
156		case BS_RESP:
157			return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals );
158		}
159	} else if ( c->op == LDAP_MOD_DELETE ) {
160		switch( c->type ) {
161		case BS_EXT:
162			if ( c->valx < 0 ) {
163				si->si_extensions = 0;
164				rc = 0;
165			} else {
166				slap_mask_t dels = 0;
167				rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels );
168				if ( rc == 0 )
169					si->si_extensions ^= dels;
170			}
171			return rc;
172		case BS_OPS:
173			if ( c->valx < 0 ) {
174				si->si_ops = 0;
175				rc = 0;
176			} else {
177				slap_mask_t dels = 0;
178				rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels );
179				if ( rc == 0 )
180					si->si_ops ^= dels;
181			}
182			return rc;
183		case BS_RESP:
184			if ( c->valx < 0 ) {
185				si->si_resps = 0;
186				rc = 0;
187			} else {
188				slap_mask_t dels = 0;
189				rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels );
190				if ( rc == 0 )
191					si->si_resps ^= dels;
192			}
193			return rc;
194		}
195
196	} else {
197		switch( c->type ) {
198		case BS_EXT:
199			return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions );
200		case BS_OPS:
201			return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops );
202		case BS_RESP:
203			return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps );
204		}
205	}
206	return 1;
207}
208
209int
210sock_back_init_cf( BackendInfo *bi )
211{
212	int rc;
213	bi->bi_cf_ocs = bsocs;
214
215	rc = config_register_schema( bscfg, bsocs );
216	if ( !rc )
217		rc = sock_over_setup();
218	return rc;
219}
220
221/* sock overlay wrapper */
222static slap_overinst sockover;
223
224static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
225static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
226
227static BI_op_bind *sockfuncs[] = {
228	sock_back_bind,
229	sock_back_unbind,
230	sock_back_search,
231	sock_back_compare,
232	sock_back_modify,
233	sock_back_modrdn,
234	sock_back_add,
235	sock_back_delete
236};
237
238static const int sockopflags[] = {
239	SOCK_OP_BIND,
240	SOCK_OP_UNBIND,
241	SOCK_OP_SEARCH,
242	SOCK_OP_COMPARE,
243	SOCK_OP_MODIFY,
244	SOCK_OP_MODRDN,
245	SOCK_OP_ADD,
246	SOCK_OP_DELETE
247};
248
249static int sock_over_op(
250	Operation *op,
251	SlapReply *rs
252)
253{
254	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
255	void *private = op->o_bd->be_private;
256	slap_callback *sc;
257	struct sockinfo	*si;
258	slap_operation_t which;
259
260	switch (op->o_tag) {
261	case LDAP_REQ_BIND:	which = op_bind; break;
262	case LDAP_REQ_UNBIND:	which = op_unbind; break;
263	case LDAP_REQ_SEARCH:	which = op_search; break;
264	case LDAP_REQ_COMPARE:	which = op_compare; break;
265	case LDAP_REQ_MODIFY:	which = op_modify; break;
266	case LDAP_REQ_MODRDN:	which = op_modrdn; break;
267	case LDAP_REQ_ADD:	which = op_add; break;
268	case LDAP_REQ_DELETE:	which = op_delete; break;
269	default:
270		return SLAP_CB_CONTINUE;
271	}
272	si = on->on_bi.bi_private;
273	if ( !(si->si_ops & sockopflags[which]))
274		return SLAP_CB_CONTINUE;
275
276	op->o_bd->be_private = si;
277	sc = op->o_callback;
278	op->o_callback = NULL;
279	sockfuncs[which]( op, rs );
280	op->o_bd->be_private = private;
281	op->o_callback = sc;
282	return rs->sr_err;
283}
284
285static int
286sock_over_response( Operation *op, SlapReply *rs )
287{
288	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
289	struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
290	FILE *fp;
291
292	if ( rs->sr_type == REP_RESULT ) {
293		if ( !( si->si_resps & SOCK_REP_RESULT ))
294			return SLAP_CB_CONTINUE;
295	} else if ( rs->sr_type == REP_SEARCH ) {
296		if ( !( si->si_resps & SOCK_REP_SEARCH ))
297			return SLAP_CB_CONTINUE;
298	} else
299		return SLAP_CB_CONTINUE;
300
301	if (( fp = opensock( si->si_sockpath )) == NULL )
302		return SLAP_CB_CONTINUE;
303
304	if ( rs->sr_type == REP_RESULT ) {
305		/* write out the result */
306		fprintf( fp, "RESULT\n" );
307		fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
308		sock_print_conn( fp, op->o_conn, si );
309		fprintf( fp, "code: %d\n", rs->sr_err );
310		if ( rs->sr_matched )
311			fprintf( fp, "matched: %s\n", rs->sr_matched );
312		if (rs->sr_text )
313			fprintf( fp, "info: %s\n", rs->sr_text );
314	} else {
315		/* write out the search entry */
316		int len;
317		fprintf( fp, "ENTRY\n" );
318		fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
319		sock_print_conn( fp, op->o_conn, si );
320		ldap_pvt_thread_mutex_lock( &entry2str_mutex );
321		fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
322		ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
323	}
324	fprintf( fp, "\n" );
325	fclose( fp );
326
327	return SLAP_CB_CONTINUE;
328}
329
330static int
331sock_over_setup()
332{
333	int rc;
334
335	sockover.on_bi.bi_type = "sock";
336	sockover.on_bi.bi_db_init = sock_over_db_init;
337	sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
338
339	sockover.on_bi.bi_op_bind = sock_over_op;
340	sockover.on_bi.bi_op_unbind = sock_over_op;
341	sockover.on_bi.bi_op_search = sock_over_op;
342	sockover.on_bi.bi_op_compare = sock_over_op;
343	sockover.on_bi.bi_op_modify = sock_over_op;
344	sockover.on_bi.bi_op_modrdn = sock_over_op;
345	sockover.on_bi.bi_op_add = sock_over_op;
346	sockover.on_bi.bi_op_delete = sock_over_op;
347	sockover.on_response = sock_over_response;
348
349	sockover.on_bi.bi_cf_ocs = osocs;
350
351	rc = config_register_schema( bscfg, osocs );
352	if ( rc ) return rc;
353
354	return overlay_register( &sockover );
355}
356
357static int
358sock_over_db_init(
359    Backend	*be,
360	struct config_reply_s *cr
361)
362{
363	slap_overinst	*on = (slap_overinst *)be->bd_info;
364	void *private = be->be_private;
365	void *cf_ocs = be->be_cf_ocs;
366	int rc;
367
368	be->be_private = NULL;
369	rc = sock_back_db_init( be, cr );
370	on->on_bi.bi_private = be->be_private;
371	be->be_private = private;
372	be->be_cf_ocs = cf_ocs;
373	return rc;
374}
375
376static int
377sock_over_db_destroy(
378    Backend	*be,
379	struct config_reply_s *cr
380)
381{
382	slap_overinst	*on = (slap_overinst *)be->bd_info;
383	void *private = be->be_private;
384	int rc;
385
386	be->be_private = on->on_bi.bi_private;
387	rc = sock_back_db_destroy( be, cr );
388	on->on_bi.bi_private = be->be_private;
389	be->be_private = private;
390	return rc;
391}
392