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