]> git.sur5r.net Git - openldap/blob - servers/slapd/back-relay/op.c
6b4d00b3da6618195c58befc0be3146d06db8975
[openldap] / servers / slapd / back-relay / op.c
1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003-2004 The OpenLDAP Foundation.
5  * Portions Copyright 2004 Pierangelo Masarati.
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 Pierangelo Masarati for inclusion
18  * in OpenLDAP Software.
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 "back-relay.h"
30
31 static int
32 relay_back_swap_bd( struct slap_op *op, struct slap_rep *rs )
33 {
34         slap_callback   *cb = op->o_callback;
35         BackendDB       *be = op->o_bd;
36
37         op->o_bd = cb->sc_private;
38         cb->sc_private = be;
39
40         return SLAP_CB_CONTINUE;
41 }
42
43 static BackendDB *
44 relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
45 {
46         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
47         BackendDB               *bd = ri->ri_bd;
48
49         if ( bd == NULL ) {
50                 bd = select_backend( &op->o_req_ndn, 0, 1 );
51                 if ( bd == op->o_bd ) {
52                         if ( err != LDAP_SUCCESS ) {
53                                 send_ldap_error( op, rs,
54                                                 LDAP_UNWILLING_TO_PERFORM, 
55                                                 "would call self" );
56                         }
57                         return NULL;
58                 }
59         }
60
61         if ( bd == NULL ) {
62                 if ( default_referral ) {
63                         rs->sr_ref = referral_rewrite( default_referral,
64                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
65                         if ( !rs->sr_ref ) {
66                                 rs->sr_ref = default_referral;
67                         }
68
69                         rs->sr_err = LDAP_REFERRAL;
70                         send_ldap_result( op, rs );
71
72                         if ( rs->sr_ref != default_referral ) {
73                                 ber_bvarray_free( rs->sr_ref );
74                         }
75
76                 } else {
77                         /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
78                          * LDAP_NO_SUCH_OBJECT for other operations.
79                          * noSuchObject is not allowed to be returned by bind */
80                         rs->sr_err = err;
81                         send_ldap_result( op, rs );
82                 }
83         }
84
85         return bd;
86 }
87
88 int
89 relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
90 {
91         BackendDB               *bd;
92         int                     rc = 1;
93
94         bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
95         if ( bd == NULL ) {
96                 return rc;
97         }
98
99         if ( bd->be_bind ) {
100                 BackendDB       *be = op->o_bd;
101
102                 op->o_bd = bd;
103                 rc = ( bd->be_bind )( op, rs );
104                 op->o_bd = be;
105
106         } else {
107                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
108                                 "operation not supported "
109                                 "within naming context" );
110         }
111
112         return rc;
113 }
114
115 int
116 relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
117 {
118         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
119         BackendDB               *bd;
120         int                     rc = 1;
121
122         bd = ri->ri_bd;
123         if ( bd == NULL ) {
124                 bd = select_backend( &op->o_req_ndn, 0, 1 );
125         }
126
127         if ( bd && bd->be_unbind ) {
128                 BackendDB       *be = op->o_bd;
129
130                 op->o_bd = bd;
131                 rc = ( bd->be_unbind )( op, rs );
132                 op->o_bd = be;
133         }
134
135         return 0;
136
137 }
138
139 int
140 relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
141 {
142         BackendDB               *bd;
143         int                     rc = 1;
144
145         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
146         if ( bd == NULL ) {
147                 return 1;
148         }
149
150         if ( bd->be_search ) {
151                 BackendDB       *be = op->o_bd;
152                 slap_callback   cb;
153
154                 cb.sc_next = op->o_callback;
155                 cb.sc_response = relay_back_swap_bd;
156                 cb.sc_cleanup = relay_back_swap_bd;
157                 cb.sc_private = op->o_bd;
158                 op->o_callback = &cb;
159
160                 op->o_bd = bd;
161                 rc = ( bd->be_search )( op, rs );
162                 op->o_bd = be;
163
164         } else {
165                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
166                                 "operation not supported "
167                                 "within naming context" );
168         }
169
170         return rc;
171
172 }
173
174 int
175 relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
176 {
177         BackendDB               *bd;
178         int                     rc = 1;
179
180         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
181         if ( bd == NULL ) {
182                 return 1;
183         }
184
185         if ( bd->be_compare ) {
186                 BackendDB       *be = op->o_bd;
187
188                 op->o_bd = bd;
189                 rc = ( bd->be_compare )( op, rs );
190                 op->o_bd = be;
191
192         } else {
193                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
194                                 "operation not supported "
195                                 "within naming context" );
196         }
197
198         return rc;
199
200 }
201
202 int
203 relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
204 {
205         BackendDB               *bd;
206         int                     rc = 1;
207
208         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
209         if ( bd == NULL ) {
210                 return 1;
211         }
212
213         if ( bd->be_modify ) {
214                 BackendDB       *be = op->o_bd;
215
216                 op->o_bd = bd;
217                 rc = ( bd->be_modify )( op, rs );
218                 op->o_bd = be;
219
220         } else {
221                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
222                                 "operation not supported "
223                                 "within naming context" );
224         }
225
226         return rc;
227
228 }
229
230 int
231 relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
232 {
233         BackendDB               *bd;
234         int                     rc = 1;
235
236         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
237         if ( bd == NULL ) {
238                 return 1;
239         }
240
241         if ( bd->be_modrdn ) {
242                 BackendDB       *be = op->o_bd;
243
244                 op->o_bd = bd;
245                 rc = ( bd->be_modrdn )( op, rs );
246                 op->o_bd = be;
247
248         } else {
249                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
250                                 "operation not supported "
251                                 "within naming context" );
252         }
253
254         return rc;
255
256 }
257
258 int
259 relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
260 {
261         BackendDB               *bd;
262         int                     rc = 1;
263
264         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
265         if ( bd == NULL ) {
266                 return 1;
267         }
268
269         if ( bd->be_add ) {
270                 BackendDB       *be = op->o_bd;
271
272                 op->o_bd = bd;
273                 rc = ( bd->be_add )( op, rs );
274                 op->o_bd = be;
275
276         } else {
277                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
278                                 "operation not supported "
279                                 "within naming context" );
280         }
281
282         return rc;
283
284 }
285
286 int
287 relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
288 {
289         BackendDB               *bd;
290         int                     rc = 1;
291
292         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
293         if ( bd == NULL ) {
294                 return 1;
295         }
296
297         if ( bd->be_delete ) {
298                 BackendDB       *be = op->o_bd;
299
300                 op->o_bd = bd;
301                 rc = ( bd->be_delete )( op, rs );
302                 op->o_bd = be;
303         }
304
305         return rc;
306
307 }
308
309 int
310 relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
311 {
312         BackendDB               *bd;
313         int                     rc = 1;
314
315         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
316         if ( bd == NULL ) {
317                 return 1;
318         }
319
320         if ( bd->be_abandon ) {
321                 BackendDB       *be = op->o_bd;
322
323                 op->o_bd = bd;
324                 rc = ( bd->be_abandon )( op, rs );
325                 op->o_bd = be;
326
327         } else {
328                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
329                                 "operation not supported "
330                                 "within naming context" );
331         }
332
333         return rc;
334
335 }
336
337 int
338 relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
339 {
340         BackendDB               *bd;
341         int                     rc = 1;
342
343         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
344         if ( bd == NULL ) {
345                 return 1;
346         }
347
348         if ( bd->be_cancel ) {
349                 BackendDB       *be = op->o_bd;
350
351                 op->o_bd = bd;
352                 rc = ( bd->be_cancel )( op, rs );
353                 op->o_bd = be;
354
355         } else {
356                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
357                                 "operation not supported "
358                                 "within naming context" );
359         }
360
361         return rc;
362
363 }
364
365 int
366 relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
367 {
368         BackendDB               *bd;
369         int                     rc = 1;
370
371         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
372         if ( bd == NULL ) {
373                 return 1;
374         }
375
376         if ( bd->be_extended ) {
377                 BackendDB       *be = op->o_bd;
378
379                 op->o_bd = bd;
380                 rc = ( bd->be_extended )( op, rs );
381                 op->o_bd = be;
382
383         } else {
384                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
385                                 "operation not supported "
386                                 "within naming context" );
387         }
388
389         return rc;
390
391 }
392
393 int
394 relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
395 {
396         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
397         BackendDB               *bd;
398         int                     rc = 1;
399
400         bd = ri->ri_bd;
401         if ( bd == NULL) {
402                 bd = select_backend( &op->o_req_ndn, 0, 1 );
403                 if ( bd == NULL ) {
404                         return 1;
405                 }
406         }
407
408         if ( bd->be_release ) {
409                 BackendDB       *be = op->o_bd;
410
411                 op->o_bd = bd;
412                 rc = ( bd->be_release )( op, e, rw );
413                 op->o_bd = be;
414         }
415
416         return rc;
417
418 }
419
420 int
421 relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
422         ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
423 {
424         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
425         BackendDB               *bd;
426         int                     rc = 1;
427
428         bd = ri->ri_bd;
429         if ( bd == NULL) {
430                 bd = select_backend( &op->o_req_ndn, 0, 1 );
431                 if ( bd == NULL ) {
432                         return 1;
433                 }
434         }
435
436         if ( bd->be_fetch ) {
437                 BackendDB       *be = op->o_bd;
438
439                 op->o_bd = bd;
440                 rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
441                 op->o_bd = be;
442         }
443
444         return rc;
445
446 }
447
448 int
449 relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
450 {
451         BackendDB               *bd;
452         int                     rc = 0;
453
454         bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
455         if ( bd == NULL ) {
456                 return 0;
457         }
458
459         if ( bd->be_chk_referrals ) {
460                 BackendDB       *be = op->o_bd;
461
462                 op->o_bd = bd;
463                 rc = ( bd->be_chk_referrals )( op, rs );
464                 op->o_bd = be;
465         }
466
467         return rc;
468
469 }
470
471 int
472 relay_back_operational( struct slap_op *op, struct slap_rep *rs, 
473                 int opattrs, Attribute **ap )
474 {
475         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
476         BackendDB               *bd;
477         int                     rc = 1;
478
479         bd = ri->ri_bd;
480         if ( bd == NULL) {
481                 bd = select_backend( &op->o_req_ndn, 0, 1 );
482                 if ( bd == NULL ) {
483                         return 1;
484                 }
485         }
486
487         if ( bd->be_operational ) {
488                 BackendDB       *be = op->o_bd;
489
490                 op->o_bd = bd;
491                 rc = ( bd->be_operational )( op, rs, opattrs, ap );
492                 op->o_bd = be;
493         }
494
495         return rc;
496
497 }
498
499 int
500 relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
501 {
502         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
503         BackendDB               *bd;
504         int                     rc = 1;
505
506         bd = ri->ri_bd;
507         if ( bd == NULL) {
508                 bd = select_backend( &op->o_req_ndn, 0, 1 );
509                 if ( bd == NULL ) {
510                         return 1;
511                 }
512         }
513
514         if ( bd->be_has_subordinates ) {
515                 BackendDB       *be = op->o_bd;
516
517                 op->o_bd = bd;
518                 rc = ( bd->be_has_subordinates )( op, e, hasSubs );
519                 op->o_bd = be;
520         }
521
522         return rc;
523
524 }
525
526 int
527 relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
528 {
529         relay_back_info         *ri = (relay_back_info *)bd->be_private;
530
531         bd = ri->ri_bd;
532         if ( bd == NULL ) {
533                 return 0;
534         }
535
536         if ( bd->be_connection_init ) {
537                 return ( bd->be_connection_init )( bd, c );
538         }
539
540         return 0;
541 }
542
543 int
544 relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
545 {
546         relay_back_info         *ri = (relay_back_info *)bd->be_private;
547
548         bd = ri->ri_bd;
549         if ( bd == NULL) {
550                 return 0;
551         }
552
553         if ( bd->be_connection_destroy ) {
554                 return ( bd->be_connection_destroy )( bd, c );
555         }
556
557         return 0;
558
559 }
560
561 /*
562  * FIXME: must implement tools as well
563  */