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