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