]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sock/config.c
d97cf3a2b1f99971c16238827592c8cd4421ab7e
[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_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
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_DNPAT:
161                         value_add_one( &c->rvalue_vals, &si->si_dnpatstr );
162                         return 0;
163                 }
164         } else if ( c->op == LDAP_MOD_DELETE ) {
165                 switch( c->type ) {
166                 case BS_EXT:
167                         if ( c->valx < 0 ) {
168                                 si->si_extensions = 0;
169                                 rc = 0;
170                         } else {
171                                 slap_mask_t dels = 0;
172                                 rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels );
173                                 if ( rc == 0 )
174                                         si->si_extensions ^= dels;
175                         }
176                         return rc;
177                 case BS_OPS:
178                         if ( c->valx < 0 ) {
179                                 si->si_ops = 0;
180                                 rc = 0;
181                         } else {
182                                 slap_mask_t dels = 0;
183                                 rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels );
184                                 if ( rc == 0 )
185                                         si->si_ops ^= dels;
186                         }
187                         return rc;
188                 case BS_RESP:
189                         if ( c->valx < 0 ) {
190                                 si->si_resps = 0;
191                                 rc = 0;
192                         } else {
193                                 slap_mask_t dels = 0;
194                                 rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels );
195                                 if ( rc == 0 )
196                                         si->si_resps ^= dels;
197                         }
198                         return rc;
199                 case BS_DNPAT:
200                         regfree( &si->si_dnpat );
201                         ch_free( si->si_dnpatstr.bv_val );
202                         BER_BVZERO( &si->si_dnpatstr );
203                         return 0;
204                 }
205
206         } else {
207                 switch( c->type ) {
208                 case BS_EXT:
209                         return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions );
210                 case BS_OPS:
211                         return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops );
212                 case BS_RESP:
213                         return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps );
214                 case BS_DNPAT:
215                         if ( !regcomp( &si->si_dnpat, c->argv[1], REG_EXTENDED|REG_ICASE|REG_NOSUB )) {
216                                 ber_str2bv( c->argv[1], 0, 1, &si->si_dnpatstr );
217                                 return 0;
218                         } else {
219                                 return 1;
220                         }
221                 }
222         }
223         return 1;
224 }
225
226 int
227 sock_back_init_cf( BackendInfo *bi )
228 {
229         int rc;
230         bi->bi_cf_ocs = bsocs;
231
232         rc = config_register_schema( bscfg, bsocs );
233         if ( !rc )
234                 rc = sock_over_setup();
235         return rc;
236 }
237
238 /* sock overlay wrapper */
239 static slap_overinst sockover;
240
241 static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
242 static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
243
244 static BI_op_bind *sockfuncs[] = {
245         sock_back_bind,
246         sock_back_unbind,
247         sock_back_search,
248         sock_back_compare,
249         sock_back_modify,
250         sock_back_modrdn,
251         sock_back_add,
252         sock_back_delete
253 };
254
255 static const int sockopflags[] = {
256         SOCK_OP_BIND,
257         SOCK_OP_UNBIND,
258         SOCK_OP_SEARCH,
259         SOCK_OP_COMPARE,
260         SOCK_OP_MODIFY,
261         SOCK_OP_MODRDN,
262         SOCK_OP_ADD,
263         SOCK_OP_DELETE
264 };
265
266 static int sock_over_op(
267         Operation *op,
268         SlapReply *rs
269 )
270 {
271         slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
272         void *private = op->o_bd->be_private;
273         slap_callback *sc;
274         struct sockinfo *si;
275         slap_operation_t which;
276
277         switch (op->o_tag) {
278         case LDAP_REQ_BIND:     which = op_bind; break;
279         case LDAP_REQ_UNBIND:   which = op_unbind; break;
280         case LDAP_REQ_SEARCH:   which = op_search; break;
281         case LDAP_REQ_COMPARE:  which = op_compare; break;
282         case LDAP_REQ_MODIFY:   which = op_modify; break;
283         case LDAP_REQ_MODRDN:   which = op_modrdn; break;
284         case LDAP_REQ_ADD:      which = op_add; break;
285         case LDAP_REQ_DELETE:   which = op_delete; break;
286         default:
287                 return SLAP_CB_CONTINUE;
288         }
289         si = on->on_bi.bi_private;
290         if ( !(si->si_ops & sockopflags[which]))
291                 return SLAP_CB_CONTINUE;
292
293         if ( !BER_BVISEMPTY( &si->si_dnpatstr ) &&
294                 regexec( &si->si_dnpat, op->o_req_ndn.bv_val, 0, NULL, 0 ))
295                 return SLAP_CB_CONTINUE;
296
297         op->o_bd->be_private = si;
298         sc = op->o_callback;
299         op->o_callback = NULL;
300         sockfuncs[which]( op, rs );
301         op->o_bd->be_private = private;
302         op->o_callback = sc;
303         return rs->sr_err;
304 }
305
306 static int
307 sock_over_response( Operation *op, SlapReply *rs )
308 {
309         slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
310         struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
311         FILE *fp;
312
313         if ( rs->sr_type == REP_RESULT ) {
314                 if ( !( si->si_resps & SOCK_REP_RESULT ))
315                         return SLAP_CB_CONTINUE;
316         } else if ( rs->sr_type == REP_SEARCH ) {
317                 if ( !( si->si_resps & SOCK_REP_SEARCH ))
318                         return SLAP_CB_CONTINUE;
319         } else
320                 return SLAP_CB_CONTINUE;
321
322         if (( fp = opensock( si->si_sockpath )) == NULL )
323                 return SLAP_CB_CONTINUE;
324
325         if ( rs->sr_type == REP_RESULT ) {
326                 /* write out the result */
327                 fprintf( fp, "RESULT\n" );
328                 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
329                 sock_print_conn( fp, op->o_conn, si );
330                 fprintf( fp, "code: %d\n", rs->sr_err );
331                 if ( rs->sr_matched )
332                         fprintf( fp, "matched: %s\n", rs->sr_matched );
333                 if (rs->sr_text )
334                         fprintf( fp, "info: %s\n", rs->sr_text );
335         } else {
336                 /* write out the search entry */
337                 int len;
338                 fprintf( fp, "ENTRY\n" );
339                 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
340                 sock_print_conn( fp, op->o_conn, si );
341                 ldap_pvt_thread_mutex_lock( &entry2str_mutex );
342                 fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
343                 ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
344         }
345         fprintf( fp, "\n" );
346         fclose( fp );
347
348         return SLAP_CB_CONTINUE;
349 }
350
351 static int
352 sock_over_setup()
353 {
354         int rc;
355
356         sockover.on_bi.bi_type = "sock";
357         sockover.on_bi.bi_db_init = sock_over_db_init;
358         sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
359
360         sockover.on_bi.bi_op_bind = sock_over_op;
361         sockover.on_bi.bi_op_unbind = sock_over_op;
362         sockover.on_bi.bi_op_search = sock_over_op;
363         sockover.on_bi.bi_op_compare = sock_over_op;
364         sockover.on_bi.bi_op_modify = sock_over_op;
365         sockover.on_bi.bi_op_modrdn = sock_over_op;
366         sockover.on_bi.bi_op_add = sock_over_op;
367         sockover.on_bi.bi_op_delete = sock_over_op;
368         sockover.on_response = sock_over_response;
369
370         sockover.on_bi.bi_cf_ocs = osocs;
371
372         rc = config_register_schema( bscfg, osocs );
373         if ( rc ) return rc;
374
375         return overlay_register( &sockover );
376 }
377
378 static int
379 sock_over_db_init(
380     Backend     *be,
381         struct config_reply_s *cr
382 )
383 {
384         slap_overinst   *on = (slap_overinst *)be->bd_info;
385         void *private = be->be_private;
386         void *cf_ocs = be->be_cf_ocs;
387         int rc;
388
389         be->be_private = NULL;
390         rc = sock_back_db_init( be, cr );
391         on->on_bi.bi_private = be->be_private;
392         be->be_private = private;
393         be->be_cf_ocs = cf_ocs;
394         return rc;
395 }
396
397 static int
398 sock_over_db_destroy(
399     Backend     *be,
400         struct config_reply_s *cr
401 )
402 {
403         slap_overinst   *on = (slap_overinst *)be->bd_info;
404         void *private = be->be_private;
405         int rc;
406
407         be->be_private = on->on_bi.bi_private;
408         rc = sock_back_db_destroy( be, cr );
409         on->on_bi.bi_private = be->be_private;
410         be->be_private = private;
411         return rc;
412 }