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