]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sock/config.c
46c05c643894af0e06b51d5221e3bdba2ff5a334
[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-2014 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_SUFFIX
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         { "socksuffix", "DN", 2, 0, 0, ARG_DN|ARG_QUOTE|ARG_MAGIC|BS_SUFFIX,
58                 bs_cf_gen, "( OLcfgDbAt:7.5 NAME 'olcOvSocketSuffix' "
59                         "DESC 'DN suffixes to match' "
60                         "EQUALITY distinguishedNameMatch "
61                         "SYNTAX OMsDN )", 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                         " olcOvSocketSuffix ) )",
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
110 #define SOCK_REP_RESULT 0x001
111 #define SOCK_REP_SEARCH 0x002
112
113 static slap_verbmasks bs_exts[] = {
114         { BER_BVC("binddn"), SOCK_EXT_BINDDN },
115         { BER_BVC("peername"), SOCK_EXT_PEERNAME },
116         { BER_BVC("ssf"), SOCK_EXT_SSF },
117         { BER_BVC("connid"), SOCK_EXT_CONNID },
118         { BER_BVNULL, 0 }
119 };
120
121 static slap_verbmasks ov_ops[] = {
122         { BER_BVC("bind"), SOCK_OP_BIND },
123         { BER_BVC("unbind"), SOCK_OP_UNBIND },
124         { BER_BVC("search"), SOCK_OP_SEARCH },
125         { BER_BVC("compare"), SOCK_OP_COMPARE },
126         { BER_BVC("modify"), SOCK_OP_MODIFY },
127         { BER_BVC("modrdn"), SOCK_OP_MODRDN },
128         { BER_BVC("add"), SOCK_OP_ADD },
129         { BER_BVC("delete"), SOCK_OP_DELETE },
130         { BER_BVNULL, 0 }
131 };
132
133 static slap_verbmasks ov_resps[] = {
134         { BER_BVC("result"), SOCK_REP_RESULT },
135         { BER_BVC("search"), SOCK_REP_SEARCH },
136         { BER_BVNULL, 0 }
137 };
138
139 static int
140 bs_cf_gen( ConfigArgs *c )
141 {
142         struct sockinfo *si;
143         int rc;
144
145         if ( c->be && c->table == Cft_Database )
146                 si = c->be->be_private;
147         else if ( c->bi )
148                 si = c->bi->bi_private;
149         else
150                 return ARG_BAD_CONF;
151
152         if ( c->op == SLAP_CONFIG_EMIT ) {
153                 switch( c->type ) {
154                 case BS_EXT:
155                         return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals );
156                 case BS_OPS:
157                         return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals );
158                 case BS_RESP:
159                         return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals );
160                 case BS_SUFFIX:
161                         value_add( &c->rvalue_vals, si->si_suffix );
162                         value_add( &c->rvalue_nvals, si->si_nsuffix );
163                         return 0;
164                 }
165         } else if ( c->op == LDAP_MOD_DELETE ) {
166                 switch( c->type ) {
167                 case BS_EXT:
168                         if ( c->valx < 0 ) {
169                                 si->si_extensions = 0;
170                                 rc = 0;
171                         } else {
172                                 slap_mask_t dels = 0;
173                                 rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels );
174                                 if ( rc == 0 )
175                                         si->si_extensions ^= dels;
176                         }
177                         return rc;
178                 case BS_OPS:
179                         if ( c->valx < 0 ) {
180                                 si->si_ops = 0;
181                                 rc = 0;
182                         } else {
183                                 slap_mask_t dels = 0;
184                                 rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels );
185                                 if ( rc == 0 )
186                                         si->si_ops ^= dels;
187                         }
188                         return rc;
189                 case BS_RESP:
190                         if ( c->valx < 0 ) {
191                                 si->si_resps = 0;
192                                 rc = 0;
193                         } else {
194                                 slap_mask_t dels = 0;
195                                 rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels );
196                                 if ( rc == 0 )
197                                         si->si_resps ^= dels;
198                         }
199                         return rc;
200                 case BS_SUFFIX:
201                         if ( c->valx < 0 ) {
202                                 ber_bvarray_free( si->si_suffix );
203                                 ber_bvarray_free( si->si_nsuffix );
204                                 si->si_suffix = NULL;
205                                 si->si_nsuffix = NULL;
206                         } else {
207                                 int i = c->valx;
208                                 ch_free( si->si_suffix[i].bv_val );
209                                 ch_free( si->si_nsuffix[i].bv_val );
210                                 do {
211                                         si->si_suffix[i] = si->si_suffix[i+1];
212                                         si->si_nsuffix[i] = si->si_nsuffix[i+1];
213                                         i++;
214                                 } while ( !BER_BVISNULL( &si->si_suffix[i] ));
215                         }
216                         return 0;
217                 }
218
219         } else {
220                 switch( c->type ) {
221                 case BS_EXT:
222                         return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions );
223                 case BS_OPS:
224                         return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops );
225                 case BS_RESP:
226                         return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps );
227                 case BS_SUFFIX:
228                         ber_bvarray_add( &si->si_suffix, &c->value_dn );
229                         ber_bvarray_add( &si->si_nsuffix, &c->value_ndn );
230                         return 0;
231                 }
232         }
233         return 1;
234 }
235
236 int
237 sock_back_init_cf( BackendInfo *bi )
238 {
239         int rc;
240         bi->bi_cf_ocs = bsocs;
241
242         rc = config_register_schema( bscfg, bsocs );
243         if ( !rc )
244                 rc = sock_over_setup();
245         return rc;
246 }
247
248 /* sock overlay wrapper */
249 static slap_overinst sockover;
250
251 static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
252 static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
253
254 static BI_op_bind *sockfuncs[] = {
255         sock_back_bind,
256         sock_back_unbind,
257         sock_back_search,
258         sock_back_compare,
259         sock_back_modify,
260         sock_back_modrdn,
261         sock_back_add,
262         sock_back_delete
263 };
264
265 static const int sockopflags[] = {
266         SOCK_OP_BIND,
267         SOCK_OP_UNBIND,
268         SOCK_OP_SEARCH,
269         SOCK_OP_COMPARE,
270         SOCK_OP_MODIFY,
271         SOCK_OP_MODRDN,
272         SOCK_OP_ADD,
273         SOCK_OP_DELETE
274 };
275
276 static int sock_over_op(
277         Operation *op,
278         SlapReply *rs
279 )
280 {
281         slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
282         void *private = op->o_bd->be_private;
283         slap_callback *sc;
284         struct sockinfo *si;
285         slap_operation_t which;
286
287         switch (op->o_tag) {
288         case LDAP_REQ_BIND:     which = op_bind; break;
289         case LDAP_REQ_UNBIND:   which = op_unbind; break;
290         case LDAP_REQ_SEARCH:   which = op_search; break;
291         case LDAP_REQ_COMPARE:  which = op_compare; break;
292         case LDAP_REQ_MODIFY:   which = op_modify; break;
293         case LDAP_REQ_MODRDN:   which = op_modrdn; break;
294         case LDAP_REQ_ADD:      which = op_add; break;
295         case LDAP_REQ_DELETE:   which = op_delete; break;
296         default:
297                 return SLAP_CB_CONTINUE;
298         }
299         si = on->on_bi.bi_private;
300         if ( !(si->si_ops & sockopflags[which]))
301                 return SLAP_CB_CONTINUE;
302
303         if ( si->si_nsuffix ) {
304                 int i, ok = 0;
305                 for ( i=0; !BER_BVISNULL( &si->si_nsuffix[i] ); i++ ) {
306                         if ( dnIsSuffix( &op->o_req_ndn, &si->si_nsuffix[i] )) {
307                                 ok = 1;
308                                 break;
309                         }
310                 }
311                 if ( !ok )
312                         return SLAP_CB_CONTINUE;
313         }
314
315         op->o_bd->be_private = si;
316         sc = op->o_callback;
317         op->o_callback = NULL;
318         sockfuncs[which]( op, rs );
319         op->o_bd->be_private = private;
320         op->o_callback = sc;
321         return rs->sr_err;
322 }
323
324 static int
325 sock_over_response( Operation *op, SlapReply *rs )
326 {
327         slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
328         struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
329         FILE *fp;
330
331         if ( rs->sr_type == REP_RESULT ) {
332                 if ( !( si->si_resps & SOCK_REP_RESULT ))
333                         return SLAP_CB_CONTINUE;
334         } else if ( rs->sr_type == REP_SEARCH ) {
335                 if ( !( si->si_resps & SOCK_REP_SEARCH ))
336                         return SLAP_CB_CONTINUE;
337         } else
338                 return SLAP_CB_CONTINUE;
339
340         if (( fp = opensock( si->si_sockpath )) == NULL )
341                 return SLAP_CB_CONTINUE;
342
343         if ( rs->sr_type == REP_RESULT ) {
344                 /* write out the result */
345                 fprintf( fp, "RESULT\n" );
346                 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
347                 sock_print_conn( fp, op->o_conn, si );
348                 fprintf( fp, "code: %d\n", rs->sr_err );
349                 if ( rs->sr_matched )
350                         fprintf( fp, "matched: %s\n", rs->sr_matched );
351                 if (rs->sr_text )
352                         fprintf( fp, "info: %s\n", rs->sr_text );
353         } else {
354                 /* write out the search entry */
355                 int len;
356                 fprintf( fp, "ENTRY\n" );
357                 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
358                 sock_print_conn( fp, op->o_conn, si );
359                 ldap_pvt_thread_mutex_lock( &entry2str_mutex );
360                 fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
361                 ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
362         }
363         fprintf( fp, "\n" );
364         fclose( fp );
365
366         return SLAP_CB_CONTINUE;
367 }
368
369 static int
370 sock_over_setup()
371 {
372         int rc;
373
374         sockover.on_bi.bi_type = "sock";
375         sockover.on_bi.bi_db_init = sock_over_db_init;
376         sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
377
378         sockover.on_bi.bi_op_bind = sock_over_op;
379         sockover.on_bi.bi_op_unbind = sock_over_op;
380         sockover.on_bi.bi_op_search = sock_over_op;
381         sockover.on_bi.bi_op_compare = sock_over_op;
382         sockover.on_bi.bi_op_modify = sock_over_op;
383         sockover.on_bi.bi_op_modrdn = sock_over_op;
384         sockover.on_bi.bi_op_add = sock_over_op;
385         sockover.on_bi.bi_op_delete = sock_over_op;
386         sockover.on_response = sock_over_response;
387
388         sockover.on_bi.bi_cf_ocs = osocs;
389
390         rc = config_register_schema( bscfg, osocs );
391         if ( rc ) return rc;
392
393         return overlay_register( &sockover );
394 }
395
396 static int
397 sock_over_db_init(
398     Backend     *be,
399         struct config_reply_s *cr
400 )
401 {
402         slap_overinst   *on = (slap_overinst *)be->bd_info;
403         void *private = be->be_private;
404         void *cf_ocs = be->be_cf_ocs;
405         int rc;
406
407         be->be_private = NULL;
408         rc = sock_back_db_init( be, cr );
409         on->on_bi.bi_private = be->be_private;
410         be->be_private = private;
411         be->be_cf_ocs = cf_ocs;
412         return rc;
413 }
414
415 static int
416 sock_over_db_destroy(
417     Backend     *be,
418         struct config_reply_s *cr
419 )
420 {
421         slap_overinst   *on = (slap_overinst *)be->bd_info;
422         void *private = be->be_private;
423         int rc;
424
425         be->be_private = on->on_bi.bi_private;
426         rc = sock_back_db_destroy( be, cr );
427         on->on_bi.bi_private = be->be_private;
428         be->be_private = private;
429         return rc;
430 }