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