1 /*        $NetBSD: slapi_ops.c,v 1.3 2021/08/14 16:15:02 christos Exp $         */
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2002-2021 The OpenLDAP Foundation.
7  * Portions Copyright 1997,2002-2003 IBM Corporation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by IBM Corporation for use in
20  * IBM products and subsequently ported to OpenLDAP Software by
21  * Steve Omrani.  Additional significant contributors include:
22  *   Luke Howard
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: slapi_ops.c,v 1.3 2021/08/14 16:15:02 christos Exp $");
27 
28 #include "portable.h"
29 
30 #include <ac/string.h>
31 #include <ac/stdarg.h>
32 #include <ac/ctype.h>
33 #include <ac/unistd.h>
34 
35 #include <slap.h>
36 #include <lber_pvt.h>
37 #include <slapi.h>
38 
39 #ifdef LDAP_SLAPI
40 
41 static struct Listener slapi_listener = {
42           BER_BVC("slapi://"),
43           BER_BVC("slapi://")
44 };
45 
46 static LDAPControl **
slapi_int_dup_controls(LDAPControl ** controls)47 slapi_int_dup_controls( LDAPControl **controls )
48 {
49           LDAPControl **c;
50           size_t i;
51 
52           if ( controls == NULL )
53                     return NULL;
54 
55           for ( i = 0; controls[i] != NULL; i++ )
56                     ;
57 
58           c = (LDAPControl **) slapi_ch_calloc( i + 1, sizeof(LDAPControl *) );
59 
60           for ( i = 0; controls[i] != NULL; i++ ) {
61                     c[i] = slapi_dup_control( controls[i] );
62           }
63 
64           return c;
65 }
66 
67 static int
slapi_int_result(Operation * op,SlapReply * rs)68 slapi_int_result(
69           Operation *op,
70           SlapReply *rs )
71 {
72           Slapi_PBlock                  *pb = SLAPI_OPERATION_PBLOCK( op );
73           plugin_result_callback        prc = NULL;
74           void                          *callback_data = NULL;
75           LDAPControl                   **ctrls = NULL;
76 
77           assert( pb != NULL );
78 
79           slapi_pblock_get( pb, SLAPI_X_INTOP_RESULT_CALLBACK, (void **)&prc );
80           slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,   &callback_data );
81 
82           /* we need to duplicate controls because they might go out of scope */
83           ctrls = slapi_int_dup_controls( rs->sr_ctrls );
84           slapi_pblock_set( pb, SLAPI_RESCONTROLS, ctrls );
85 
86           if ( prc != NULL ) {
87                     (*prc)( rs->sr_err, callback_data );
88           }
89 
90           return rs->sr_err;
91 }
92 
93 static int
slapi_int_search_entry(Operation * op,SlapReply * rs)94 slapi_int_search_entry(
95           Operation *op,
96           SlapReply *rs )
97 {
98           Slapi_PBlock                            *pb = SLAPI_OPERATION_PBLOCK( op );
99           plugin_search_entry_callback  psec = NULL;
100           void                                    *callback_data = NULL;
101           int                                     rc = LDAP_SUCCESS;
102 
103           assert( pb != NULL );
104 
105           slapi_pblock_get( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK, (void **)&psec );
106           slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,         &callback_data );
107 
108           if ( psec != NULL ) {
109                     rc = (*psec)( rs->sr_entry, callback_data );
110           }
111 
112           return rc;
113 }
114 
115 static int
slapi_int_search_reference(Operation * op,SlapReply * rs)116 slapi_int_search_reference(
117           Operation *op,
118           SlapReply *rs )
119 {
120           int                                     i, rc = LDAP_SUCCESS;
121           plugin_referral_entry_callback          prec = NULL;
122           void                                    *callback_data = NULL;
123           Slapi_PBlock                            *pb = SLAPI_OPERATION_PBLOCK( op );
124 
125           assert( pb != NULL );
126 
127           slapi_pblock_get( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void **)&prec );
128           slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,           &callback_data );
129 
130           if ( prec != NULL ) {
131                     for ( i = 0; rs->sr_ref[i].bv_val != NULL; i++ ) {
132                               rc = (*prec)( rs->sr_ref[i].bv_val, callback_data );
133                               if ( rc != LDAP_SUCCESS ) {
134                                         break;
135                               }
136                     }
137           }
138 
139           return rc;
140 }
141 
142 int
slapi_int_response(Slapi_Operation * op,SlapReply * rs)143 slapi_int_response( Slapi_Operation *op, SlapReply *rs )
144 {
145           int                                     rc;
146 
147           switch ( rs->sr_type ) {
148           case REP_RESULT:
149                     rc = slapi_int_result( op, rs );
150                     break;
151           case REP_SEARCH:
152                     rc = slapi_int_search_entry( op, rs );
153                     break;
154           case REP_SEARCHREF:
155                     rc = slapi_int_search_reference( op, rs );
156                     break;
157           default:
158                     rc = LDAP_OTHER;
159                     break;
160           }
161 
162           assert( rc != SLAP_CB_CONTINUE ); /* never try to send a wire response */
163 
164           return rc;
165 }
166 
167 static int
slapi_int_get_ctrls(Slapi_PBlock * pb)168 slapi_int_get_ctrls( Slapi_PBlock *pb )
169 {
170           LDAPControl                   **c;
171           int                           rc = LDAP_SUCCESS;
172 
173           if ( pb->pb_op->o_ctrls != NULL ) {
174                     for ( c = pb->pb_op->o_ctrls; *c != NULL; c++ ) {
175                               rc = slap_parse_ctrl( pb->pb_op, pb->pb_rs, *c, &pb->pb_rs->sr_text );
176                               if ( rc != LDAP_SUCCESS )
177                                         break;
178                     }
179           }
180 
181           return rc;
182 }
183 
184 void
slapi_int_connection_init_pb(Slapi_PBlock * pb,ber_tag_t tag)185 slapi_int_connection_init_pb( Slapi_PBlock *pb, ber_tag_t tag )
186 {
187           Connection                    *conn;
188           Operation           *op;
189           ber_len_t           max = sockbuf_max_incoming;
190 
191           conn = (Connection *) slapi_ch_calloc( 1, sizeof(Connection) );
192 
193           LDAP_STAILQ_INIT( &conn->c_pending_ops );
194 
195           op = (Operation *) slapi_ch_calloc( 1, sizeof(OperationBuffer) );
196           op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
197           op->o_controls = ((OperationBuffer *) op)->ob_controls;
198 
199           op->o_callback = (slap_callback *) slapi_ch_calloc( 1, sizeof(slap_callback) );
200           op->o_callback->sc_response = slapi_int_response;
201           op->o_callback->sc_cleanup = NULL;
202           op->o_callback->sc_private = pb;
203           op->o_callback->sc_next = NULL;
204 
205           conn->c_pending_ops.stqh_first = op;
206 
207           /* connection object authorization information */
208           conn->c_authtype = LDAP_AUTH_NONE;
209           BER_BVZERO( &conn->c_authmech );
210           BER_BVZERO( &conn->c_dn );
211           BER_BVZERO( &conn->c_ndn );
212 
213           conn->c_listener = &slapi_listener;
214           ber_dupbv( &conn->c_peer_domain, (struct berval *)&slap_unknown_bv );
215           ber_dupbv( &conn->c_peer_name, (struct berval *)&slap_unknown_bv );
216 
217           LDAP_STAILQ_INIT( &conn->c_ops );
218 
219           BER_BVZERO( &conn->c_sasl_bind_mech );
220           conn->c_sasl_authctx = NULL;
221           conn->c_sasl_sockctx = NULL;
222           conn->c_sasl_extra = NULL;
223 
224           conn->c_sb = ber_sockbuf_alloc();
225 
226           ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
227 
228           conn->c_currentber = NULL;
229 
230           /* should check status of thread calls */
231           ldap_pvt_thread_mutex_init( &conn->c_mutex );
232           ldap_pvt_thread_mutex_init( &conn->c_write1_mutex );
233           ldap_pvt_thread_cond_init( &conn->c_write1_cv );
234 
235           ldap_pvt_thread_mutex_lock( &conn->c_mutex );
236 
237           conn->c_n_ops_received = 0;
238           conn->c_n_ops_executing = 0;
239           conn->c_n_ops_pending = 0;
240           conn->c_n_ops_completed = 0;
241 
242           conn->c_n_get = 0;
243           conn->c_n_read = 0;
244           conn->c_n_write = 0;
245 
246           conn->c_protocol = LDAP_VERSION3;
247 
248           conn->c_activitytime = conn->c_starttime = slap_get_time();
249 
250           /*
251            * A real connection ID is required, because syncrepl associates
252            * pending CSNs with unique ( connection, operation ) tuples.
253            * Setting a fake connection ID will cause slap_get_commit_csn()
254            * to return a stale value.
255            */
256           connection_assign_nextid( conn );
257 
258           conn->c_conn_state  = SLAP_C_ACTIVE;
259 
260           conn->c_ssf = conn->c_transport_ssf = local_ssf;
261           conn->c_tls_ssf = 0;
262 
263           backend_connection_init( conn );
264 
265           conn->c_send_ldap_result = slap_send_ldap_result;
266           conn->c_send_search_entry = slap_send_search_entry;
267           conn->c_send_ldap_extended = slap_send_ldap_extended;
268           conn->c_send_search_reference = slap_send_search_reference;
269 
270           /* operation object */
271           op->o_tag = tag;
272           op->o_protocol = LDAP_VERSION3;
273           BER_BVZERO( &op->o_authmech );
274           op->o_time = slap_get_time();
275           op->o_do_not_cache = 1;
276           op->o_threadctx = ldap_pvt_thread_pool_context();
277           op->o_tmpmemctx = NULL;
278           op->o_tmpmfuncs = &ch_mfuncs;
279           op->o_conn = conn;
280           op->o_connid = conn->c_connid;
281           op->o_bd = frontendDB;
282 
283           /* extensions */
284           slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op );
285           slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
286 
287           pb->pb_rs = (SlapReply *)slapi_ch_calloc( 1, sizeof(SlapReply) );
288           pb->pb_op = op;
289           pb->pb_conn = conn;
290           pb->pb_intop = 1;
291 
292           ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
293 }
294 
295 static void
slapi_int_set_operation_dn(Slapi_PBlock * pb)296 slapi_int_set_operation_dn( Slapi_PBlock *pb )
297 {
298           Backend                       *be;
299           Operation           *op = pb->pb_op;
300 
301           if ( BER_BVISNULL( &op->o_ndn ) ) {
302                     /* set to root DN */
303                     be = select_backend( &op->o_req_ndn, 1 );
304                     if ( be != NULL ) {
305                               ber_dupbv( &op->o_dn, &be->be_rootdn );
306                               ber_dupbv( &op->o_ndn, &be->be_rootndn );
307                     }
308           }
309 }
310 
311 void
slapi_int_connection_done_pb(Slapi_PBlock * pb)312 slapi_int_connection_done_pb( Slapi_PBlock *pb )
313 {
314           Connection                    *conn;
315           Operation           *op;
316 
317           PBLOCK_ASSERT_INTOP( pb, 0 );
318 
319           conn = pb->pb_conn;
320           op = pb->pb_op;
321 
322           /* free allocated DNs */
323           if ( !BER_BVISNULL( &op->o_dn ) )
324                     op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx );
325           if ( !BER_BVISNULL( &op->o_ndn ) )
326                     op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx );
327 
328           if ( !BER_BVISNULL( &op->o_req_dn ) )
329                     op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
330           if ( !BER_BVISNULL( &op->o_req_ndn ) )
331                     op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
332 
333           switch ( op->o_tag ) {
334           case LDAP_REQ_MODRDN:
335                     if ( !BER_BVISNULL( &op->orr_newrdn ))
336                               op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );
337                     if ( !BER_BVISNULL( &op->orr_nnewrdn ))
338                               op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );
339                     if ( op->orr_newSup != NULL ) {
340                               assert( !BER_BVISNULL( op->orr_newSup ) );
341                               op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
342                               op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
343                     }
344                     if ( op->orr_nnewSup != NULL ) {
345                               assert( !BER_BVISNULL( op->orr_nnewSup ) );
346                               op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
347                               op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
348                     }
349                     slap_mods_free( op->orr_modlist, 1 );
350                     break;
351           case LDAP_REQ_ADD:
352                     slap_mods_free( op->ora_modlist, 0 );
353                     break;
354           case LDAP_REQ_MODIFY:
355                     slap_mods_free( op->orm_modlist, 1 );
356                     break;
357           case LDAP_REQ_SEARCH:
358                     if ( op->ors_attrs != NULL ) {
359                               op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
360                               op->ors_attrs = NULL;
361                     }
362                     break;
363           default:
364                     break;
365           }
366 
367           slapi_ch_free_string( &conn->c_authmech.bv_val );
368           slapi_ch_free_string( &conn->c_dn.bv_val );
369           slapi_ch_free_string( &conn->c_ndn.bv_val );
370           slapi_ch_free_string( &conn->c_peer_domain.bv_val );
371           slapi_ch_free_string( &conn->c_peer_name.bv_val );
372 
373           if ( conn->c_sb != NULL ) {
374                     ber_sockbuf_free( conn->c_sb );
375           }
376 
377           slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op );
378           slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
379 
380           slapi_ch_free( (void **)&pb->pb_op->o_callback );
381           slapi_ch_free( (void **)&pb->pb_op );
382           slapi_ch_free( (void **)&pb->pb_conn );
383           slapi_ch_free( (void **)&pb->pb_rs );
384 }
385 
386 static int
slapi_int_func_internal_pb(Slapi_PBlock * pb,slap_operation_t which)387 slapi_int_func_internal_pb( Slapi_PBlock *pb, slap_operation_t which )
388 {
389           SlapReply           *rs = pb->pb_rs;
390           int                           rc;
391 
392           PBLOCK_ASSERT_INTOP( pb, 0 );
393 
394           rc = slapi_int_get_ctrls( pb );
395           if ( rc != LDAP_SUCCESS ) {
396                     rs->sr_err = rc;
397                     return rc;
398           }
399 
400           pb->pb_op->o_bd = frontendDB;
401           return (&frontendDB->be_bind)[which]( pb->pb_op, pb->pb_rs );
402 }
403 
404 int
slapi_delete_internal_pb(Slapi_PBlock * pb)405 slapi_delete_internal_pb( Slapi_PBlock *pb )
406 {
407           if ( pb == NULL ) {
408                     return -1;
409           }
410 
411           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_DELETE );
412 
413           slapi_int_func_internal_pb( pb, op_delete );
414 
415           return 0;
416 }
417 
418 int
slapi_add_internal_pb(Slapi_PBlock * pb)419 slapi_add_internal_pb( Slapi_PBlock *pb )
420 {
421           SlapReply           *rs;
422           Slapi_Entry                   *entry_orig = NULL;
423           OpExtraDB oex;
424           int rc;
425 
426           if ( pb == NULL ) {
427                     return -1;
428           }
429 
430           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD );
431 
432           rs = pb->pb_rs;
433 
434           entry_orig = pb->pb_op->ora_e;
435           pb->pb_op->ora_e = NULL;
436 
437           /*
438            * The caller can specify a new entry, or a target DN and set
439            * of modifications, but not both.
440            */
441           if ( entry_orig != NULL ) {
442                     if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
443                               rs->sr_err = LDAP_PARAM_ERROR;
444                               goto cleanup;
445                     }
446 
447                     assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */
448                     ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name );
449                     ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname );
450           } else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
451                     rs->sr_err = LDAP_PARAM_ERROR;
452                     goto cleanup;
453           }
454 
455           pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
456           ber_dupbv( &pb->pb_op->ora_e->e_name,  &pb->pb_op->o_req_dn );
457           ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );
458 
459           if ( entry_orig != NULL ) {
460                     assert( pb->pb_op->ora_modlist == NULL );
461 
462                     rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist,
463                               &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
464                     if ( rs->sr_err != LDAP_SUCCESS ) {
465                               goto cleanup;
466                     }
467           } else {
468                     assert( pb->pb_op->ora_modlist != NULL );
469           }
470 
471           rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text,
472                     pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
473           if ( rs->sr_err != LDAP_SUCCESS ) {
474                 goto cleanup;
475         }
476 
477           /* Duplicate the values, because we may call slapi_entry_free() */
478           rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
479                     1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
480           if ( rs->sr_err != LDAP_SUCCESS ) {
481                     goto cleanup;
482           }
483 
484           oex.oe.oe_key = (void *)do_add;
485           oex.oe_db = NULL;
486           LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next);
487           rc = slapi_int_func_internal_pb( pb, op_add );
488           LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next);
489 
490           if ( !rc ) {
491                     if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) {
492                               BackendDB *bd = pb->pb_op->o_bd;
493 
494                               pb->pb_op->o_bd = oex.oe_db;
495                               be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
496                               pb->pb_op->ora_e = NULL;
497                               pb->pb_op->o_bd = bd;
498                     }
499           }
500 
501 cleanup:
502 
503           if ( pb->pb_op->ora_e != NULL ) {
504                     slapi_entry_free( pb->pb_op->ora_e );
505                     pb->pb_op->ora_e = NULL;
506           }
507           if ( entry_orig != NULL ) {
508                     pb->pb_op->ora_e = entry_orig;
509                     slap_mods_free( pb->pb_op->ora_modlist, 1 );
510                     pb->pb_op->ora_modlist = NULL;
511           }
512 
513           return 0;
514 }
515 
516 int
slapi_modrdn_internal_pb(Slapi_PBlock * pb)517 slapi_modrdn_internal_pb( Slapi_PBlock *pb )
518 {
519           if ( pb == NULL ) {
520                     return -1;
521           }
522 
523           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODRDN );
524 
525           if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
526                     pb->pb_rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
527                     goto cleanup;
528           }
529 
530           slapi_int_func_internal_pb( pb, op_modrdn );
531 
532 cleanup:
533 
534           return 0;
535 }
536 
537 int
slapi_modify_internal_pb(Slapi_PBlock * pb)538 slapi_modify_internal_pb( Slapi_PBlock *pb )
539 {
540           SlapReply           *rs;
541 
542           if ( pb == NULL ) {
543                     return -1;
544           }
545 
546           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODIFY );
547 
548           rs = pb->pb_rs;
549 
550           if ( pb->pb_op->orm_modlist == NULL ) {
551                     rs->sr_err = LDAP_PARAM_ERROR;
552                     goto cleanup;
553           }
554 
555           if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
556                     rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
557                     goto cleanup;
558           }
559 
560           rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->orm_modlist,
561                     &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
562           if ( rs->sr_err != LDAP_SUCCESS ) {
563                 goto cleanup;
564         }
565 
566           slapi_int_func_internal_pb( pb, op_modify );
567 
568 cleanup:
569 
570           return 0;
571 }
572 
573 static int
slapi_int_search_entry_callback(Slapi_Entry * entry,void * callback_data)574 slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data )
575 {
576           int                 nentries = 0, i = 0;
577           Slapi_Entry         **head = NULL, **tp;
578           Slapi_PBlock        *pb = (Slapi_PBlock *)callback_data;
579 
580           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
581 
582           entry = slapi_entry_dup( entry );
583           if ( entry == NULL ) {
584                     return LDAP_NO_MEMORY;
585           }
586 
587           slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
588           slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
589 
590           i = nentries + 1;
591           if ( nentries == 0 ) {
592                     tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
593                     if ( tp == NULL ) {
594                               slapi_entry_free( entry );
595                               return LDAP_NO_MEMORY;
596                     }
597 
598                     tp[0] = entry;
599           } else {
600                     tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
601                                         sizeof(Slapi_Entry *) * ( i + 1 ) );
602                     if ( tp == NULL ) {
603                               slapi_entry_free( entry );
604                               return LDAP_NO_MEMORY;
605                     }
606                     tp[i - 1] = entry;
607           }
608           tp[i] = NULL;
609 
610           slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
611           slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)&i );
612 
613           return LDAP_SUCCESS;
614 }
615 
616 int
slapi_search_internal_pb(Slapi_PBlock * pb)617 slapi_search_internal_pb( Slapi_PBlock *pb )
618 {
619           return slapi_search_internal_callback_pb( pb,
620                     (void *)pb,
621                     NULL,
622                     slapi_int_search_entry_callback,
623                     NULL );
624 }
625 
626 int
slapi_search_internal_callback_pb(Slapi_PBlock * pb,void * callback_data,plugin_result_callback prc,plugin_search_entry_callback psec,plugin_referral_entry_callback prec)627 slapi_search_internal_callback_pb( Slapi_PBlock *pb,
628           void *callback_data,
629           plugin_result_callback prc,
630           plugin_search_entry_callback psec,
631           plugin_referral_entry_callback prec )
632 {
633           int                           free_filter = 0;
634           SlapReply           *rs;
635 
636           if ( pb == NULL ) {
637                     return -1;
638           }
639 
640           PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
641 
642           rs = pb->pb_rs;
643 
644           /* search callback and arguments */
645           slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK,         (void *)prc );
646           slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK,   (void *)psec );
647           slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void *)prec );
648           slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA,           (void *)callback_data );
649 
650           if ( BER_BVISEMPTY( &pb->pb_op->ors_filterstr )) {
651                     rs->sr_err = LDAP_PARAM_ERROR;
652                     goto cleanup;
653           }
654 
655           if ( pb->pb_op->ors_filter == NULL ) {
656                     pb->pb_op->ors_filter = slapi_str2filter( pb->pb_op->ors_filterstr.bv_val );
657                     if ( pb->pb_op->ors_filter == NULL ) {
658                               rs->sr_err = LDAP_PROTOCOL_ERROR;
659                               goto cleanup;
660                     }
661 
662                     free_filter = 1;
663           }
664 
665           slapi_int_func_internal_pb( pb, op_search );
666 
667 cleanup:
668           if ( free_filter ) {
669                     slapi_filter_free( pb->pb_op->ors_filter, 1 );
670                     pb->pb_op->ors_filter = NULL;
671           }
672 
673           slapi_pblock_delete_param( pb, SLAPI_X_INTOP_RESULT_CALLBACK );
674           slapi_pblock_delete_param( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK );
675           slapi_pblock_delete_param( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK );
676           slapi_pblock_delete_param( pb, SLAPI_X_INTOP_CALLBACK_DATA );
677 
678           return 0;
679 }
680 
681 /* Wrappers for old API */
682 
683 void
slapi_search_internal_set_pb(Slapi_PBlock * pb,const char * base,int scope,const char * filter,char ** attrs,int attrsonly,LDAPControl ** controls,const char * uniqueid,Slapi_ComponentId * plugin_identity,int operation_flags)684 slapi_search_internal_set_pb( Slapi_PBlock *pb,
685           const char *base,
686           int scope,
687           const char *filter,
688           char **attrs,
689           int attrsonly,
690           LDAPControl **controls,
691           const char *uniqueid,
692           Slapi_ComponentId *plugin_identity,
693           int operation_flags )
694 {
695           int no_limit = SLAP_NO_LIMIT;
696           int deref = LDAP_DEREF_NEVER;
697 
698           slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
699           slapi_pblock_set( pb, SLAPI_SEARCH_TARGET,    (void *)base );
700           slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE,     (void *)&scope );
701           slapi_pblock_set( pb, SLAPI_SEARCH_FILTER,    (void *)0 );
702           slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
703           slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS,     (void *)attrs );
704           slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)&attrsonly );
705           slapi_pblock_set( pb, SLAPI_REQCONTROLS,      (void *)controls );
706           slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,  (void *)uniqueid );
707           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,  (void *)plugin_identity );
708           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,    (void *)&operation_flags );
709           slapi_pblock_set( pb, SLAPI_SEARCH_DEREF,     (void *)&deref );
710           slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)&no_limit );
711           slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)&no_limit );
712 
713           slapi_int_set_operation_dn( pb );
714 }
715 
716 Slapi_PBlock *
slapi_search_internal(char * ldn,int scope,char * filStr,LDAPControl ** controls,char ** attrs,int attrsonly)717 slapi_search_internal(
718           char *ldn,
719           int scope,
720           char *filStr,
721           LDAPControl **controls,
722           char **attrs,
723           int attrsonly )
724 {
725           Slapi_PBlock *pb;
726 
727           pb = slapi_pblock_new();
728 
729           slapi_search_internal_set_pb( pb, ldn, scope, filStr,
730                     attrs, attrsonly,
731                     controls, NULL, NULL, 0 );
732 
733           slapi_search_internal_pb( pb );
734 
735           return pb;
736 }
737 
738 void
slapi_modify_internal_set_pb(Slapi_PBlock * pb,const char * dn,LDAPMod ** mods,LDAPControl ** controls,const char * uniqueid,Slapi_ComponentId * plugin_identity,int operation_flags)739 slapi_modify_internal_set_pb( Slapi_PBlock *pb,
740           const char *dn,
741           LDAPMod **mods,
742           LDAPControl **controls,
743           const char *uniqueid,
744           Slapi_ComponentId *plugin_identity,
745           int operation_flags )
746 {
747           slapi_int_connection_init_pb( pb, LDAP_REQ_MODIFY );
748           slapi_pblock_set( pb, SLAPI_MODIFY_TARGET,   (void *)dn );
749           slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)mods );
750           slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
751           slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
752           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
753           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
754           slapi_int_set_operation_dn( pb );
755 }
756 
757 /* Function : slapi_modify_internal
758  *
759  * Description:     Plugin functions call this routine to modify an entry
760  *                                      in the backend directly
761  * Return values : LDAP_SUCCESS
762  *                 LDAP_PARAM_ERROR
763  *                 LDAP_NO_MEMORY
764  *                 LDAP_OTHER
765  *                 LDAP_UNWILLING_TO_PERFORM
766 */
767 Slapi_PBlock *
slapi_modify_internal(char * ldn,LDAPMod ** mods,LDAPControl ** controls,int log_change)768 slapi_modify_internal(
769           char *ldn,
770           LDAPMod **mods,
771           LDAPControl **controls,
772           int log_change )
773 {
774           Slapi_PBlock *pb;
775 
776           pb = slapi_pblock_new();
777 
778           slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL, 0 );
779           slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
780           slapi_modify_internal_pb( pb );
781 
782           return pb;
783 }
784 
785 int
slapi_add_internal_set_pb(Slapi_PBlock * pb,const char * dn,LDAPMod ** attrs,LDAPControl ** controls,Slapi_ComponentId * plugin_identity,int operation_flags)786 slapi_add_internal_set_pb( Slapi_PBlock *pb,
787           const char *dn,
788           LDAPMod **attrs,
789           LDAPControl **controls,
790           Slapi_ComponentId *plugin_identity,
791           int operation_flags )
792 {
793           slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
794           slapi_pblock_set( pb, SLAPI_ADD_TARGET,      (void *)dn );
795           slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)attrs );
796           slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
797           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
798           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
799           slapi_int_set_operation_dn( pb );
800 
801           return 0;
802 }
803 
804 Slapi_PBlock *
slapi_add_internal(char * dn,LDAPMod ** attrs,LDAPControl ** controls,int log_change)805 slapi_add_internal(
806           char * dn,
807           LDAPMod **attrs,
808           LDAPControl **controls,
809           int log_change )
810 {
811           Slapi_PBlock *pb;
812 
813           pb = slapi_pblock_new();
814 
815           slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL, 0);
816           slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
817           slapi_add_internal_pb( pb );
818 
819           return pb;
820 }
821 
822 void
slapi_add_entry_internal_set_pb(Slapi_PBlock * pb,Slapi_Entry * e,LDAPControl ** controls,Slapi_ComponentId * plugin_identity,int operation_flags)823 slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
824           Slapi_Entry *e,
825           LDAPControl **controls,
826           Slapi_ComponentId *plugin_identity,
827           int operation_flags )
828 {
829           slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
830           slapi_pblock_set( pb, SLAPI_ADD_ENTRY,       (void *)e );
831           slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
832           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
833           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
834           slapi_int_set_operation_dn( pb );
835 }
836 
837 Slapi_PBlock *
slapi_add_entry_internal(Slapi_Entry * e,LDAPControl ** controls,int log_change)838 slapi_add_entry_internal(
839           Slapi_Entry *e,
840           LDAPControl **controls,
841           int log_change )
842 {
843           Slapi_PBlock *pb;
844 
845           pb = slapi_pblock_new();
846 
847           slapi_add_entry_internal_set_pb( pb, e, controls, NULL, 0 );
848           slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
849           slapi_add_internal_pb( pb );
850 
851           return pb;
852 }
853 
854 void
slapi_rename_internal_set_pb(Slapi_PBlock * pb,const char * olddn,const char * newrdn,const char * newsuperior,int deloldrdn,LDAPControl ** controls,const char * uniqueid,Slapi_ComponentId * plugin_identity,int operation_flags)855 slapi_rename_internal_set_pb( Slapi_PBlock *pb,
856           const char *olddn,
857           const char *newrdn,
858           const char *newsuperior,
859           int deloldrdn,
860           LDAPControl **controls,
861           const char *uniqueid,
862           Slapi_ComponentId *plugin_identity,
863           int operation_flags )
864 {
865           slapi_int_connection_init_pb( pb, LDAP_REQ_MODRDN );
866           slapi_pblock_set( pb, SLAPI_MODRDN_TARGET,      (void *)olddn );
867           slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN,      (void *)newrdn );
868           slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
869           slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN,   (void *)&deloldrdn );
870           slapi_pblock_set( pb, SLAPI_REQCONTROLS,        (void *)controls );
871           slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,    (void *)uniqueid );
872           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,    (void *)plugin_identity );
873           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,      (void *)&operation_flags );
874           slap_modrdn2mods( pb->pb_op, pb->pb_rs );
875           slapi_int_set_operation_dn( pb );
876 }
877 
878 /* Function : slapi_modrdn_internal
879  *
880  * Description : Plugin functions call this routine to modify the rdn
881  *                                       of an entry in the backend directly
882  * Return values : LDAP_SUCCESS
883  *                 LDAP_PARAM_ERROR
884  *                 LDAP_NO_MEMORY
885  *                 LDAP_OTHER
886  *                 LDAP_UNWILLING_TO_PERFORM
887  *
888  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
889  */
890 Slapi_PBlock *
slapi_modrdn_internal(char * olddn,char * lnewrdn,int deloldrdn,LDAPControl ** controls,int log_change)891 slapi_modrdn_internal(
892           char *olddn,
893           char *lnewrdn,
894           int deloldrdn,
895           LDAPControl **controls,
896           int log_change )
897 {
898           Slapi_PBlock *pb;
899 
900           pb = slapi_pblock_new ();
901 
902           slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
903                     deloldrdn, controls, NULL, NULL, 0 );
904           slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
905           slapi_modrdn_internal_pb( pb );
906 
907           return pb;
908 }
909 
910 void
slapi_delete_internal_set_pb(Slapi_PBlock * pb,const char * dn,LDAPControl ** controls,const char * uniqueid,Slapi_ComponentId * plugin_identity,int operation_flags)911 slapi_delete_internal_set_pb( Slapi_PBlock *pb,
912           const char *dn,
913           LDAPControl **controls,
914           const char *uniqueid,
915           Slapi_ComponentId *plugin_identity,
916           int operation_flags )
917 {
918           slapi_int_connection_init_pb( pb, LDAP_REQ_DELETE );
919           slapi_pblock_set( pb, SLAPI_TARGET_DN,       (void *)dn );
920           slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
921           slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
922           slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
923           slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
924           slapi_int_set_operation_dn( pb );
925 }
926 
927 /* Function : slapi_delete_internal
928  *
929  * Description : Plugin functions call this routine to delete an entry
930  *               in the backend directly
931  * Return values : LDAP_SUCCESS
932  *                 LDAP_PARAM_ERROR
933  *                 LDAP_NO_MEMORY
934  *                 LDAP_OTHER
935  *                 LDAP_UNWILLING_TO_PERFORM
936 */
937 Slapi_PBlock *
slapi_delete_internal(char * ldn,LDAPControl ** controls,int log_change)938 slapi_delete_internal(
939           char *ldn,
940           LDAPControl **controls,
941           int log_change )
942 {
943           Slapi_PBlock *pb;
944 
945           pb = slapi_pblock_new();
946 
947           slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL, 0 );
948           slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
949           slapi_delete_internal_pb( pb );
950 
951           return pb;
952 }
953 
954 #endif /* LDAP_SLAPI */
955