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