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