]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_overlay.c
remove redundant variable
[openldap] / servers / slapd / slapi / slapi_overlay.c
1 /* slapi_overlay.c - SLAPI overlay */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2005 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 Luke Howard 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 "slapi.h"
30
31 #ifdef LDAP_SLAPI
32
33 static slap_overinst slapi;
34
35 static Slapi_PBlock *
36 slapi_over_pblock_new ( Operation *op )
37 {
38         Slapi_PBlock            *pb;
39
40         pb = slapi_pblock_new();
41         if ( pb == NULL )
42                 return NULL;
43
44         slapi_int_pblock_set_operation( pb, op );
45
46         return pb;
47 }
48
49 static int
50 slapi_over_compute_output(
51         computed_attr_context *c,
52         Slapi_Attr *attribute,
53         Slapi_Entry *entry
54 )
55 {
56         int                     rc;
57         Attribute               **a;
58         AttributeDescription    *desc;
59         Operation               *op = c->cac_op;
60         SlapReply               *rs = (SlapReply *)c->cac_private;
61
62         if ( c == NULL || attribute == NULL || entry == NULL ) {
63                 return 0;
64         }
65
66         assert( rs->sr_entry == entry );
67
68         desc = attribute->a_desc;
69
70         if ( rs->sr_attrs == NULL ) {
71                 /* All attrs request, skip operational attributes */
72                 if ( is_at_operational( desc->ad_type ) ) {
73                         return 0;
74                 }
75         } else {
76                 /* Specific attributes requested */
77                 if ( is_at_operational( desc->ad_type ) ) {
78                         if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
79                              !ad_inlist( desc, rs->sr_attrs ) ) {
80                                 return 0;
81                         }
82                 } else {
83                         if ( !SLAP_USERATTRS( rs->sr_attr_flags ) &&
84                              !ad_inlist( desc, rs->sr_attrs ) ) {
85                                 return 0;
86                         }
87                 }
88         }
89
90         /* XXX perhaps we should check for existing attributes and merge */
91         for ( a = &rs->sr_operational_attrs; *a != NULL; a = &(*a)->a_next )
92                 ;
93
94         *a = attr_dup( attribute );
95
96         return 0;
97 }
98
99 static int
100 slapi_over_aux_operational( Operation *op, SlapReply *rs )
101 {
102         /* Support for computed attribute plugins */
103         computed_attr_context    ctx;
104         AttributeName           *anp;
105
106         ctx.cac_pb = slapi_over_pblock_new( op );
107         ctx.cac_op = op;
108         ctx.cac_private = rs;
109
110         if ( rs->sr_entry != NULL ) {
111                 /*
112                  * For each client requested attribute, call the plugins.
113                  */
114                 if ( rs->sr_attrs != NULL ) {
115                         for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) {
116                                 if ( compute_evaluator( &ctx, anp->an_name.bv_val,
117                                         rs->sr_entry, slapi_over_compute_output ) == 1 ) {
118                                         break;
119                                 }
120                         }
121                 } else {
122                         /*
123                          * Technically we shouldn't be returning operational attributes
124                          * when the user requested only user attributes. We'll let the
125                          * plugin decide whether to be naughty or not.
126                          */
127                         compute_evaluator( &ctx, "*", rs->sr_entry, slapi_over_compute_output );
128                 }
129         }
130
131         slapi_pblock_destroy( ctx.cac_pb );
132
133         return SLAP_CB_CONTINUE;
134 }
135
136 static int
137 slapi_over_search( Operation *op, SlapReply *rs, int type )
138 {
139         int                     rc;
140         Slapi_PBlock            *pb;
141
142         assert( rs->sr_type == REP_SEARCH || rs->sr_type == REP_SEARCHREF );
143
144         /* create a new pblock to not trample on result controls */
145         pb = slapi_over_pblock_new( op );
146
147         slapi_pblock_set( pb, SLAPI_RESCONTROLS,         (void *)rs->sr_ctrls );
148         slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, (void *)rs->sr_entry );
149
150         rc = slapi_int_call_plugins( op->o_bd, type, pb );
151         if ( rc >= 0 ) /* 1 means no plugins called */
152                 rc = SLAP_CB_CONTINUE;
153         else
154                 rc = LDAP_SUCCESS; /* confusing: don't abort, but don't send */
155
156         slapi_pblock_set( pb, SLAPI_RESCONTROLS, NULL ); /* don't free */
157         slapi_pblock_destroy(pb);
158
159         return rc;
160 }
161
162 static int
163 slapi_over_count_controls( LDAPControl **controls )
164 {
165         int                     i;
166
167         if ( controls == NULL )
168                 return 0;
169
170         for ( i = 0; controls[i] != NULL; i++ )
171                 ;
172
173         return i;
174 }
175
176 static int
177 slapi_over_merge_controls( Operation *op, SlapReply *rs )
178 {
179         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
180         LDAPControl             **slapiControls = NULL, **mergedControls;
181         int                     nSlapiControls = 0;
182         int                     nResControls = 0;
183         int                     i;
184
185         slapi_pblock_get( pb, SLAPI_RESCONTROLS, (void **)&slapiControls );
186         nSlapiControls = slapi_over_count_controls( slapiControls );
187
188         if ( nSlapiControls == 0 ) {
189                 /* short-circuit */
190                 return LDAP_SUCCESS;
191         }
192
193         nResControls = slapi_over_count_controls( rs->sr_ctrls );
194
195         /* XXX this is a bit tricky, rs->sr_ctrls may have been allocated on stack */
196         mergedControls = (LDAPControl **)op->o_tmpalloc( ( nResControls + nSlapiControls + 1 ) *
197                                                          sizeof( LDAPControl *), op->o_tmpmemctx );
198         if ( mergedControls == NULL ) {
199                 return LDAP_NO_MEMORY;
200         }
201
202         if ( rs->sr_ctrls != NULL ) {
203                 for ( i = 0; i < nResControls; i++ )
204                         mergedControls[i] = rs->sr_ctrls[i];
205         }
206         if ( slapiControls != NULL ) {
207                 for ( i = 0; i < nSlapiControls; i++ )
208                         mergedControls[nResControls + i] = slapiControls[i];
209         }
210         mergedControls[nResControls + nSlapiControls] = NULL;
211
212         if ( slapiControls != NULL ) {
213                 slapi_ch_free( (void **)&slapiControls );
214                 slapi_pblock_set( pb, SLAPI_RESCONTROLS, NULL ); /* don't free */
215         }
216
217         rs->sr_ctrls = mergedControls;
218
219         return LDAP_SUCCESS;
220 }
221
222 /*
223  * Call pre- and post-result plugins
224  */
225 static int
226 slapi_over_result( Operation *op, SlapReply *rs, int type )
227 {
228         int                     rc;
229         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
230
231         assert( rs->sr_type == REP_RESULT );
232
233         slapi_pblock_set( pb, SLAPI_RESULT_CODE,    (void *)rs->sr_err );
234         slapi_pblock_set( pb, SLAPI_RESULT_TEXT,    (void *)rs->sr_text );
235         slapi_pblock_set( pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
236
237         rc = slapi_int_call_plugins( op->o_bd, type, pb );
238         
239         slapi_pblock_get( pb, SLAPI_RESULT_CODE,    (void **)&rs->sr_err );
240         slapi_pblock_get( pb, SLAPI_RESULT_TEXT,    (void **)&rs->sr_text );
241         slapi_pblock_get( pb, SLAPI_RESULT_MATCHED, (void **)&rs->sr_matched );
242
243         if ( type == SLAPI_PLUGIN_PRE_RESULT_FN ) {
244                 rc = slapi_over_merge_controls( op, rs );
245         }
246
247         return SLAP_CB_CONTINUE;
248 }
249
250 static int
251 slapi_op_add_init( Operation *op, SlapReply *rs )
252 {
253         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
254
255         slapi_pblock_set( pb, SLAPI_ADD_ENTRY, (void *)op->ora_e );
256
257         return LDAP_SUCCESS;
258 }
259
260 static int
261 slapi_op_bind_preop_init( Operation *op, SlapReply *rs )
262 {
263         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
264
265         slapi_pblock_set( pb, SLAPI_BIND_TARGET,      (void *)op->o_req_dn.bv_val );
266         slapi_pblock_set( pb, SLAPI_BIND_METHOD,      (void *)op->orb_method );
267         slapi_pblock_set( pb, SLAPI_BIND_CREDENTIALS, (void *)&op->orb_cred );
268         slapi_pblock_set( pb, SLAPI_CONN_DN,          NULL );
269
270         return LDAP_SUCCESS;
271 }
272
273 static int
274 slapi_op_bind_postop_init( Operation *op, SlapReply *rs )
275 {
276         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
277         char                    *dn = NULL;
278
279         if ( rs->sr_err == LDAP_SUCCESS ) {
280                 /* fix for ITS#2971 */
281                 slapi_pblock_set( pb, SLAPI_CONN_DN, op->o_conn->c_authz.sai_dn.bv_val );
282         }
283
284         return LDAP_SUCCESS;
285 }
286
287 static int
288 slapi_op_bind_callback( Operation *op, SlapReply *rs )
289 {
290         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
291         int                     rc = rs->sr_err;
292
293         switch ( rc ) {
294         case SLAPI_BIND_SUCCESS:
295                 /* Continue with backend processing */
296                 break;
297         case SLAPI_BIND_FAIL:
298                 /* Failure, frontend (that's us) sends result */
299                 rs->sr_err = LDAP_INVALID_CREDENTIALS;
300                 send_ldap_result( op, rs );
301                 return rs->sr_err;
302                 break;
303         case SLAPI_BIND_ANONYMOUS: /* undocumented */
304         default: /* plugin sent result or no plugins called */
305                 if ( slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rs->sr_err ) != 0 ) {
306                         rs->sr_err = LDAP_OTHER;
307                 }
308
309                 BER_BVZERO( &op->orb_edn );
310
311                 if ( rs->sr_err == LDAP_SUCCESS ) {
312                         slapi_pblock_get( pb, SLAPI_CONN_DN, (void *)&op->orb_edn.bv_val );
313                         if ( BER_BVISNULL( &op->orb_edn ) ) {
314                                 if ( rc == 1 ) {
315                                         /* No plugins were called; continue processing */
316                                         return LDAP_SUCCESS;
317                                 }
318                         } else {
319                                 op->orb_edn.bv_len = strlen( op->orb_edn.bv_val );
320                         }
321                         rs->sr_err = dnPrettyNormal( NULL, &op->orb_edn,
322                                 &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
323
324                         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
325                         ber_dupbv(&op->o_conn->c_dn, &op->o_req_dn);
326                         ber_dupbv(&op->o_conn->c_ndn, &op->o_req_ndn);
327                         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
328                         BER_BVZERO( &op->o_req_dn );
329                         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
330                         BER_BVZERO( &op->o_req_ndn );
331                         if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
332                                 ber_len_t max = sockbuf_max_incoming_auth;
333                                 ber_sockbuf_ctrl( op->o_conn->c_sb,
334                                         LBER_SB_OPT_SET_MAX_INCOMING, &max );
335                         }
336
337                         /* log authorization identity */
338                         Statslog( LDAP_DEBUG_STATS,
339                                 "%s BIND dn=\"%s\" mech=%s (SLAPI) ssf=0\n",
340                                 op->o_log_prefix,
341                                 BER_BVISNULL( &op->o_conn->c_dn )
342                                         ? "<empty>" : op->o_conn->c_dn.bv_val,
343                                 op->orb_tmp_mech.bv_val, 0, 0 );
344
345                         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
346                         return -1;
347                 }
348                 break;
349         }
350
351         return rc;
352 }
353
354 static int
355 slapi_op_compare_init( Operation *op, SlapReply *rs )
356 {
357         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
358
359         slapi_pblock_set( pb, SLAPI_COMPARE_TYPE,  (void *)op->orc_ava->aa_desc->ad_cname.bv_val );
360         slapi_pblock_set( pb, SLAPI_COMPARE_VALUE, (void *)&op->orc_ava->aa_value );
361
362         return LDAP_SUCCESS;
363 }
364
365 static int
366 slapi_op_modify_init( Operation *op, SlapReply *rs )
367 {
368         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
369         LDAPMod                 **modv = NULL;
370
371         modv = slapi_int_modifications2ldapmods( &op->orm_modlist );
372         slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)modv );
373
374         return LDAP_SUCCESS;
375 }
376
377 static int
378 slapi_op_modify_callback( Operation *op, SlapReply *rs )
379 {
380         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
381         LDAPMod                 **modv = NULL;
382
383         /* check preoperation result code */
384         if ( rs->sr_err < 0 ) {
385                 slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rs->sr_err );
386                 return rs->sr_err;
387         }
388
389         /*
390          * NB: it is valid for the plugin to return no modifications
391          * (for example, a plugin might store some attributes elsewhere
392          * and remove them from the modification list; if only those
393          * attribute types were included in the modification request,
394          * then slapi_int_ldapmods2modifications() above will return
395          * NULL).
396          *
397          * However, the post-operation plugin should still be
398          * called.
399          */
400
401         slapi_pblock_get( pb, SLAPI_MODIFY_MODS, (void **)&modv );
402         op->orm_modlist = slapi_int_ldapmods2modifications( modv );
403
404         return LDAP_SUCCESS;
405 }
406
407 static int
408 slapi_op_modify_cleanup( Operation *op, SlapReply *rs )
409 {
410         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
411         LDAPMod                 **modv = NULL;
412
413         slapi_pblock_get( pb, SLAPI_MODIFY_MODS, (void **)&modv );
414
415         if ( modv != NULL )
416                 slapi_int_free_ldapmods( modv );
417
418         return LDAP_SUCCESS;
419 }
420
421 static int
422 slapi_op_modrdn_init( Operation *op, SlapReply *rs )
423 {
424         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
425
426         slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN,      (void *)op->orr_newrdn.bv_val );
427         slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)op->orr_newSup->bv_val );
428         slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN,   (void *)op->orr_deleteoldrdn );
429
430         return LDAP_SUCCESS;
431 }
432
433 static int
434 slapi_op_search_init( Operation *op, SlapReply *rs )
435 {
436         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
437         char                    **attrs;
438
439         attrs = anlist2charray_x( op->ors_attrs, 0, op->o_tmpmemctx );
440
441         slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE,     (void *)op->ors_scope );
442         slapi_pblock_set( pb, SLAPI_SEARCH_DEREF,     (void *)op->ors_deref );
443         slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)op->ors_slimit );
444         slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)op->ors_tlimit );
445         slapi_pblock_set( pb, SLAPI_SEARCH_FILTER,    (void *)op->ors_filter );
446         slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)op->ors_filterstr.bv_val );
447         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS,     (void *)attrs );
448         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)op->ors_attrsonly );
449
450         return LDAP_SUCCESS;
451 }
452
453 static int
454 slapi_op_search_callback( Operation *op, SlapReply *rs )
455 {
456         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
457
458         /* check preoperation result code */
459         if ( rs->sr_err < 0 ) {
460                 slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rs->sr_err );
461                 return rs->sr_err;
462         }
463
464         if ( slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb ) != 0 ) {
465                 return LDAP_SUCCESS;
466         }
467
468         /*
469          * The plugin can set the SLAPI_SEARCH_FILTER.
470          * SLAPI_SEARCH_STRFILER is not normative.
471          */
472         slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, (void *)&op->ors_filter );
473         op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
474         filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
475
476         slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, (void **)&op->o_req_dn.bv_val );
477         op->o_req_dn.bv_len = strlen( op->o_req_dn.bv_val );
478
479         if( !BER_BVISNULL( &op->o_req_ndn ) ) {
480                 slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );
481         }
482         rs->sr_err = dnNormalize( 0, NULL, NULL, &op->o_req_dn, &op->o_req_ndn,
483                                   op->o_tmpmemctx );
484         if ( rs->sr_err != LDAP_SUCCESS ) {
485                 send_ldap_result( op, rs );
486                 return rs->sr_err;
487         }
488
489         slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, (void **)&op->ors_scope );
490         slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, (void **)&op->ors_deref );
491
492         return LDAP_SUCCESS;
493 }
494
495 static int
496 slapi_op_search_cleanup( Operation *op, SlapReply *rs )
497 {
498         Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
499         char                    **attrs = NULL;
500
501         slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS,     (void *)&attrs );
502
503         if ( attrs != NULL )
504                 op->o_tmpfree( attrs, op->o_tmpmemctx );
505
506         return LDAP_SUCCESS;
507 }
508
509 struct slapi_op_info {
510         int soi_preop;                  /* preoperation plugin parameter */
511         int soi_postop;                 /* postoperation plugin parameter */
512         slap_response *soi_preop_init;  /* preoperation pblock init function */
513         slap_response *soi_callback;    /* preoperation result handler */
514         slap_response *soi_postop_init; /* postoperation pblock init function */
515         slap_response *soi_cleanup;     /* cleanup function */
516 } slapi_op_dispatch_table[] = {
517         {
518                 SLAPI_PLUGIN_PRE_BIND_FN,
519                 SLAPI_PLUGIN_POST_BIND_FN,
520                 slapi_op_bind_preop_init,
521                 slapi_op_bind_callback,
522                 slapi_op_bind_postop_init,
523                 NULL
524         },
525         {
526                 SLAPI_PLUGIN_PRE_UNBIND_FN, /* UNBIND */
527                 SLAPI_PLUGIN_POST_UNBIND_FN,
528                 NULL,
529                 NULL,
530                 NULL,
531                 NULL
532         },
533         {
534                 SLAPI_PLUGIN_PRE_SEARCH_FN,
535                 SLAPI_PLUGIN_POST_SEARCH_FN,
536                 slapi_op_search_init,
537                 slapi_op_search_callback,
538                 NULL,
539                 slapi_op_search_cleanup
540         },
541         {
542                 SLAPI_PLUGIN_PRE_COMPARE_FN,
543                 SLAPI_PLUGIN_POST_COMPARE_FN,
544                 slapi_op_compare_init,
545                 NULL,
546                 NULL,
547                 NULL
548         },
549         {
550                 SLAPI_PLUGIN_PRE_MODIFY_FN,
551                 SLAPI_PLUGIN_POST_MODIFY_FN,
552                 slapi_op_modify_init,
553                 slapi_op_modify_callback,
554                 NULL,
555                 slapi_op_modify_cleanup
556         },
557         {
558                 SLAPI_PLUGIN_PRE_MODRDN_FN,
559                 SLAPI_PLUGIN_POST_MODRDN_FN,
560                 slapi_op_modrdn_init,
561                 NULL,
562                 NULL,
563                 NULL
564         },
565         {
566                 SLAPI_PLUGIN_PRE_ADD_FN,
567                 SLAPI_PLUGIN_POST_ADD_FN,
568                 slapi_op_add_init,
569                 NULL,
570                 NULL,
571                 NULL
572         },
573         {
574                 SLAPI_PLUGIN_PRE_DELETE_FN,
575                 SLAPI_PLUGIN_POST_DELETE_FN,
576                 NULL,
577                 NULL,
578                 NULL,
579                 NULL
580         },
581         {
582                 SLAPI_PLUGIN_PRE_ABANDON_FN,
583                 SLAPI_PLUGIN_POST_ABANDON_FN,
584                 NULL,
585                 NULL,
586                 NULL,
587                 NULL
588         },
589         {
590                 0,
591                 0,
592                 NULL,
593                 NULL,
594                 NULL,
595                 NULL
596         }
597 };
598
599 slap_operation_t
600 slapi_tag2op( ber_tag_t tag )
601 {
602         slap_operation_t op;
603
604         switch ( tag ) {
605         case LDAP_REQ_BIND:
606                 op = op_bind;
607                 break;
608         case LDAP_REQ_ADD:
609                 op = op_add;
610                 break;
611         case LDAP_REQ_DELETE:
612                 op = op_compare;
613                 break;
614         case LDAP_REQ_MODRDN:
615                 op = op_modrdn;
616                 break;
617         case LDAP_REQ_MODIFY:
618                 op = op_modify;
619                 break;
620         case LDAP_REQ_COMPARE:
621                 op = op_compare;
622                 break;
623         case LDAP_REQ_SEARCH:
624                 op = op_search;
625                 break;
626         case LDAP_REQ_UNBIND:
627                 op = op_unbind;
628                 break;
629         default:
630                 op = op_last;
631                 break;
632         }
633
634         return op;
635 }
636
637 static int
638 slapi_over_response( Operation *op, SlapReply *rs )
639 {
640         int                     rc;
641
642         switch ( rs->sr_type ) {
643         case REP_RESULT:
644                 rc = slapi_over_result( op, rs, SLAPI_PLUGIN_PRE_RESULT_FN );
645                 break;
646         case REP_SEARCH:
647                 rc = slapi_over_search( op, rs, SLAPI_PLUGIN_PRE_ENTRY_FN );
648                 break;
649         case REP_SEARCHREF:
650                 rc = slapi_over_search( op, rs, SLAPI_PLUGIN_PRE_REFERRAL_FN );
651                 break;
652         default:
653                 rc = SLAP_CB_CONTINUE;
654                 break;
655         }
656
657         return rc;
658 }
659
660 static int
661 slapi_over_cleanup( Operation *op, SlapReply *rs )
662 {
663         int                     rc;
664
665         switch ( rs->sr_type ) {
666         case REP_RESULT:
667                 rc = slapi_over_result( op, rs, SLAPI_PLUGIN_POST_RESULT_FN );
668                 break;
669         case REP_SEARCH:
670                 rc = slapi_over_search( op, rs, SLAPI_PLUGIN_POST_ENTRY_FN );
671                 break;
672         case REP_SEARCHREF:
673                 rc = slapi_over_search( op, rs, SLAPI_PLUGIN_POST_REFERRAL_FN );
674                 break;
675         default:
676                 rc = SLAP_CB_CONTINUE;
677                 break;
678         }
679
680         return rc;
681 }
682
683 static int
684 slapi_op_func( Operation *op, SlapReply *rs )
685 {
686         Slapi_PBlock            *pb;
687         slap_operation_t        which;
688         struct slapi_op_info    *opinfo;
689         int                     rc, flags = 0;
690         slap_overinfo           *oi;
691         slap_overinst           *on;
692         slap_callback           cb;
693
694         /*
695          * We check for op->o_extensions to verify that we are not
696          * processing a SLAPI internal operation. XXX
697          */
698         if ( op->o_hdr->oh_extensions == NULL ) {
699                 return SLAP_CB_CONTINUE;
700         }
701
702         /*
703          * Find the SLAPI operation information for this LDAP
704          * operation; this will contain the preop and postop
705          * plugin types, as well as optional callbacks for
706          * setting up the SLAPI environment.
707          */
708         which = slapi_tag2op( op->o_tag );
709         if ( which >= op_last ) {
710                 /* invalid operation, but let someone else deal with it */
711                 return SLAP_CB_CONTINUE;
712         }
713
714         opinfo = &slapi_op_dispatch_table[which];
715         if ( opinfo == NULL || opinfo->soi_preop == 0 ) {
716                 /* no SLAPI plugin types for this operation */
717                 return SLAP_CB_CONTINUE;
718         }
719
720         pb = slapi_over_pblock_new( op );
721
722         /* XXX we need to fill this out for MMR support */
723         slapi_pblock_set( pb, SLAPI_TARGET_ADDRESS, NULL );
724         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, NULL );
725         slapi_pblock_set( pb, SLAPI_TARGET_DN, (void *)op->o_req_dn.bv_val );
726         
727         cb.sc_response = slapi_over_response; /* call pre-entry/result plugins */
728         cb.sc_cleanup = slapi_over_cleanup;  /* call post-entry/result plugins */
729         cb.sc_private = pb;
730         cb.sc_next = op->o_callback;
731         op->o_callback = &cb;
732
733         /*
734          * Call preoperation plugins 
735          */
736         if ( opinfo->soi_preop_init != NULL ) {
737                 rs->sr_err = (opinfo->soi_preop_init)( op, rs );
738                 if ( rs->sr_err != LDAP_SUCCESS )
739                         goto cleanup;
740         }
741
742         rs->sr_err = slapi_int_call_plugins( op->o_bd, opinfo->soi_preop, pb );
743
744         /*
745          * soi_callback is responsible for examining the result code
746          * of the preoperation plugin and determining whether to
747          * abort. This is needed because of special SLAPI behaviour
748          * with bind preoperation plugins.
749          *
750          * The soi_callback function is also used to reset any values
751          * returned from the preoperation plugin before calling the
752          * backend (for the success case).
753          */
754         if ( opinfo->soi_callback == NULL ) {
755                 /* default behaviour is preop plugin can abort operation */
756                 if ( rs->sr_err < 0 ) {
757                         slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rs->sr_err );
758                         goto cleanup;
759                 }
760         } else {
761                 rc = (opinfo->soi_callback)( op, rs );
762                 if ( rc )
763                         goto cleanup;
764         }
765
766         /*
767          * Call actual backend (or next overlay in stack). We need to
768          * do this rather than returning SLAP_CB_CONTINUE and calling
769          * postoperation plugins in a response handler to match the
770          * behaviour of SLAPI in OpenLDAP 2.2, where postoperation
771          * plugins are called after the backend has completely
772          * finished processing the operation.
773          */
774         on = (slap_overinst *)op->o_bd->bd_info;
775         oi = on->on_info;
776
777         rs->sr_err = overlay_op_walk( op, rs, which, oi, on->on_next );
778
779         /*
780          * Call postoperation plugins
781          */
782         slapi_pblock_set( pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
783
784         if ( opinfo->soi_postop_init != NULL ) {
785                 (opinfo->soi_postop_init)( op, rs );
786         }
787
788         slapi_int_call_plugins( op->o_bd, opinfo->soi_postop, pb );
789
790 cleanup:
791         if ( opinfo->soi_cleanup != NULL ) {
792                 (opinfo->soi_cleanup)( op, rs );
793         }
794
795         op->o_callback = cb.sc_next;
796         slapi_pblock_destroy(pb);
797
798         return rs->sr_err;
799 }
800
801 static int
802 slapi_over_extended( Operation *op, SlapReply *rs )
803 {
804         Slapi_PBlock    *pb;
805         SLAPI_FUNC      callback;
806         int             sentResult = 0;
807         int             rc;
808         struct berval   reqdata = BER_BVNULL;
809
810         slapi_int_get_extop_plugin( &op->ore_reqoid, &callback );
811         if ( callback == NULL ) {
812                 return SLAP_CB_CONTINUE;
813         }
814
815         pb = slapi_over_pblock_new( op );
816
817         if ( op->ore_reqdata != NULL ) {
818                 reqdata = *op->ore_reqdata;
819         }
820
821         slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_OID,   (void *)op->ore_reqoid.bv_val);
822         slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_VALUE, (void *)&reqdata);
823
824         rc = (*callback)( pb );
825         if ( rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) {
826                 slapi_pblock_destroy( pb );
827                 return rc;
828         } else if ( rc == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) {
829                 slapi_pblock_destroy( pb );
830                 return SLAP_CB_CONTINUE;
831         }
832
833         slapi_pblock_get( pb, SLAPI_EXT_OP_RET_OID,   (void **)&rs->sr_rspoid );
834         slapi_pblock_get( pb, SLAPI_EXT_OP_RET_VALUE, (void **)&rs->sr_rspdata );
835
836         rs->sr_err = rc;
837         send_ldap_extended( op, rs );
838
839         if ( rs->sr_rspoid != NULL )
840                 slapi_ch_free_string( (char **)&rs->sr_rspoid );
841
842         if ( rs->sr_rspdata != NULL )
843                 ber_bvfree( rs->sr_rspdata );
844
845         slapi_pblock_destroy( pb );
846
847         return rs->sr_err;
848 }
849
850 static int
851 slapi_over_access_allowed(
852         Operation               *op,
853         Entry                   *e,
854         AttributeDescription    *desc,
855         struct berval           *val,
856         slap_access_t           access,
857         AccessControlState      *state,
858         slap_mask_t             *maskp )
859 {
860         int                     rc;
861         Slapi_PBlock            *pb;
862         slap_callback           cb;
863
864         pb = slapi_over_pblock_new( op );
865
866         cb.sc_response = NULL;
867         cb.sc_cleanup = NULL;
868         cb.sc_private = pb;
869         cb.sc_next = op->o_callback;
870         op->o_callback = &cb;
871
872         rc = slapi_int_access_allowed( op, e, desc, val, access, state );
873         if ( rc != 0 ) {
874                 rc = SLAP_CB_CONTINUE;
875         }
876
877         op->o_callback = cb.sc_next;
878         slapi_pblock_destroy( pb );
879
880         return rc;
881 }
882
883 static int
884 slapi_over_acl_group(
885         Operation               *op,
886         Entry                   *target,
887         struct berval           *gr_ndn,
888         struct berval           *op_ndn,
889         ObjectClass             *group_oc,
890         AttributeDescription    *group_at )
891 {
892         Slapi_Entry             *e;
893         int                     rc;
894         Slapi_PBlock            *pb;
895         BackendDB               *be = op->o_bd;
896         GroupAssertion          *g;
897
898         op->o_bd = select_backend( gr_ndn, 0, 0 );
899
900         for ( g = op->o_groups; g; g = g->ga_next ) {
901                 if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
902                         g->ga_at != group_at || g->ga_len != gr_ndn->bv_len )
903                 {
904                         continue;
905                 }
906                 if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) {
907                         break;
908                 }
909         }
910         if ( g != NULL ) {
911                 rc = g->ga_res;
912                 goto done;
913         }
914
915         if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) {
916                 e = target;
917                 rc = 0;
918         } else {
919                 rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
920         }
921         if ( e != NULL ) {
922                 pb = slapi_over_pblock_new( op );
923
924                 slapi_pblock_set( pb, SLAPI_X_GROUP_ENTRY,        (void *)e );
925                 slapi_pblock_set( pb, SLAPI_X_GROUP_OPERATION_DN, (void *)op_ndn->bv_val );
926                 slapi_pblock_set( pb, SLAPI_X_GROUP_ATTRIBUTE,    (void *)group_at->ad_cname.bv_val );
927                 slapi_pblock_set( pb, SLAPI_X_GROUP_TARGET_ENTRY, (void *)target );
928
929                 rc = slapi_int_call_plugins( op->o_bd, SLAPI_X_PLUGIN_PRE_GROUP_FN, pb );
930                 if ( rc >= 0 ) /* 1 means no plugins called */
931                         rc = SLAP_CB_CONTINUE;
932                 else
933                         slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void **)&rc );
934
935                 slapi_pblock_destroy( pb );
936
937                 if ( e != target ) {
938                         be_entry_release_r( op, e );
939                 }
940         } else {
941                 rc = LDAP_NO_SUCH_OBJECT; /* return SLAP_CB_CONTINUE for correctness? */
942         }
943
944         if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache &&
945              rc != SLAP_CB_CONTINUE ) {
946                 g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len,
947                         op->o_tmpmemctx );
948                 g->ga_be = op->o_bd;
949                 g->ga_oc = group_oc;
950                 g->ga_at = group_at;
951                 g->ga_res = rc;
952                 g->ga_len = gr_ndn->bv_len;
953                 strcpy( g->ga_ndn, gr_ndn->bv_val );
954                 g->ga_next = op->o_groups;
955                 op->o_groups = g;
956         }
957         /*
958          * XXX don't call POST_GROUP_FN, I have no idea what the point of
959          * that plugin function was anyway
960          */
961 done:
962         op->o_bd = be;
963         return rc;
964 }
965
966 int
967 slapi_int_overlay_init()
968 {
969         memset( &slapi, 0, sizeof(slapi) );
970
971         slapi.on_bi.bi_type = SLAPI_OVERLAY_NAME;
972
973         slapi.on_bi.bi_op_bind          = slapi_op_func;
974         slapi.on_bi.bi_op_unbind        = slapi_op_func;
975         slapi.on_bi.bi_op_search        = slapi_op_func;
976         slapi.on_bi.bi_op_compare       = slapi_op_func;
977         slapi.on_bi.bi_op_modify        = slapi_op_func;
978         slapi.on_bi.bi_op_modrdn        = slapi_op_func;
979         slapi.on_bi.bi_op_add           = slapi_op_func;
980         slapi.on_bi.bi_op_delete        = slapi_op_func;
981         slapi.on_bi.bi_op_abandon       = slapi_op_func;
982         slapi.on_bi.bi_op_cancel        = slapi_op_func;
983
984         slapi.on_bi.bi_extended         = slapi_over_extended;
985         slapi.on_bi.bi_access_allowed   = slapi_over_access_allowed;
986         slapi.on_bi.bi_operational      = slapi_over_aux_operational;
987         slapi.on_bi.bi_acl_group        = slapi_over_acl_group;
988
989         return overlay_register( &slapi );
990 }
991
992 #endif /* LDAP_SLAPI */