1 /*        $NetBSD: plugin.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: plugin.c,v 1.3 2021/08/14 16:15:02 christos Exp $");
27 
28 #include "portable.h"
29 
30 /*
31  * Note: if ltdl.h is not available, slapi should not be compiled
32  */
33 
34 #ifdef HAVE_LTDL_H
35 #include "ldap_pvt_thread.h"
36 #include "slap.h"
37 #include "slap-config.h"
38 #include "slapi.h"
39 #include "lutil.h"
40 
41 #include <ltdl.h>
42 
43 static int slapi_int_load_plugin( Slapi_PBlock *, const char *, const char *, int,
44           SLAPI_FUNC *, lt_dlhandle * );
45 
46 /* pointer to link list of extended objects */
47 static ExtendedOp *pGExtendedOps = NULL;
48 
49 /*********************************************************************
50  * Function Name:      plugin_pblock_new
51  *
52  * Description:        This routine creates a new Slapi_PBlock structure,
53  *                     loads in the plugin module and executes the init
54  *                     function provided by the module.
55  *
56  * Input:              type - type of the plugin, such as SASL, database, etc.
57  *                     path - the loadpath to load the module in
58  *                     initfunc - name of the plugin function to execute first
59  *                     argc - number of arguments
60  *                     argv[] - an array of char pointers point to
61  *                              the arguments passed in via
62  *                              the configuration file.
63  *
64  * Output:
65  *
66  * Return Values:      a pointer to a newly created Slapi_PBlock structure or
67  *                     NULL - function failed
68  *
69  * Messages:           None
70  *********************************************************************/
71 
72 static Slapi_PBlock *
plugin_pblock_new(int type,int argc,char * argv[])73 plugin_pblock_new(
74           int type,
75           int argc,
76           char *argv[] )
77 {
78           Slapi_PBlock        *pPlugin = NULL;
79           Slapi_PluginDesc *pPluginDesc = NULL;
80           lt_dlhandle         hdLoadHandle;
81           int                 rc;
82           char                **av2 = NULL, **ppPluginArgv;
83           char                *path = argv[2];
84           char                *initfunc = argv[3];
85 
86           pPlugin = slapi_pblock_new();
87           if ( pPlugin == NULL ) {
88                     rc = LDAP_NO_MEMORY;
89                     goto done;
90           }
91 
92           slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
93           slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)&argc );
94 
95           av2 = ldap_charray_dup( argv );
96           if ( av2 == NULL ) {
97                     rc = LDAP_NO_MEMORY;
98                     goto done;
99           }
100 
101           if ( argc > 0 ) {
102                     ppPluginArgv = &av2[4];
103           } else {
104                     ppPluginArgv = NULL;
105           }
106 
107           slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
108           slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
109 
110           rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle );
111           if ( rc != 0 ) {
112                     goto done;
113           }
114 
115           if ( slapi_pblock_get( pPlugin, SLAPI_PLUGIN_DESCRIPTION, (void **)&pPluginDesc ) == 0 &&
116                pPluginDesc != NULL ) {
117                     slapi_log_error(SLAPI_LOG_TRACE, "plugin_pblock_new",
118                                         "Registered plugin %s %s [%s] (%s)\n",
119                                         pPluginDesc->spd_id,
120                                         pPluginDesc->spd_version,
121                                         pPluginDesc->spd_vendor,
122                                         pPluginDesc->spd_description);
123           }
124 
125 done:
126           if ( rc != 0 && pPlugin != NULL ) {
127                     slapi_pblock_destroy( pPlugin );
128                     pPlugin = NULL;
129                     if ( av2 != NULL ) {
130                               ldap_charray_free( av2 );
131                     }
132           }
133 
134           return pPlugin;
135 }
136 
137 /*********************************************************************
138  * Function Name:      slapi_int_register_plugin
139  *
140  * Description:        insert the slapi_pblock structure to a given position the end of the plugin
141  *                     list
142  *
143  * Input:              a pointer to a plugin slapi_pblock structure to be added to
144  *                     the list
145  *
146  * Output:             none
147  *
148  * Return Values:      LDAP_SUCCESS - successfully inserted.
149  *                     LDAP_LOCAL_ERROR.
150  *
151  * Messages:           None
152  *********************************************************************/
153 int
slapi_int_register_plugin_index(Backend * be,Slapi_PBlock * pPB,int index)154 slapi_int_register_plugin_index(
155           Backend *be,
156           Slapi_PBlock *pPB,
157           int index )
158 {
159           Slapi_PBlock        *pTmpPB;
160           Slapi_PBlock        *pSavePB;
161           int                 pos = 0, rc = LDAP_SUCCESS;
162 
163           assert( be != NULL );
164 
165           pTmpPB = SLAPI_BACKEND_PBLOCK( be );
166           if ( pTmpPB == NULL || index == 0 ) {
167                     SLAPI_BACKEND_PBLOCK( be ) = pPB;
168           } else {
169                     while ( pTmpPB != NULL && rc == LDAP_SUCCESS &&
170                                         ( index < 0 || pos++ < index ) ) {
171                               pSavePB = pTmpPB;
172                               rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
173                     }
174 
175                     if ( rc == LDAP_SUCCESS ) {
176                               rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK, (void *)pPB );
177                     }
178           }
179 
180           if ( index >= 0 && rc == LDAP_SUCCESS ) {
181                     rc = slapi_pblock_set( pPB, SLAPI_IBM_PBLOCK, (void *)pTmpPB );
182           }
183 
184           return ( rc != LDAP_SUCCESS ) ? LDAP_OTHER : LDAP_SUCCESS;
185 }
186 
187 int
slapi_int_register_plugin(Backend * be,Slapi_PBlock * pPB)188 slapi_int_register_plugin(
189           Backend *be,
190           Slapi_PBlock *pPB )
191 {
192           return slapi_int_register_plugin_index( be, pPB, -1 );
193 }
194 
195 /*********************************************************************
196  * Function Name:      slapi_int_get_plugins
197  *
198  * Description:        get the desired type of function pointers defined
199  *                     in all the plugins
200  *
201  * Input:              the type of the functions to get, such as pre-operation,etc.
202  *
203  * Output:             none
204  *
205  * Return Values:      this routine returns a pointer to an array of function
206  *                     pointers containing backend-specific plugin functions
207  *                     followed by global plugin functions
208  *
209  * Messages:           None
210  *********************************************************************/
211 int
slapi_int_get_plugins(Backend * be,int functype,SLAPI_FUNC ** ppFuncPtrs)212 slapi_int_get_plugins(
213           Backend *be,
214           int functype,
215           SLAPI_FUNC **ppFuncPtrs )
216 {
217 
218           Slapi_PBlock        *pCurrentPB;
219           SLAPI_FUNC          FuncPtr;
220           SLAPI_FUNC          *pTmpFuncPtr;
221           int                 numPB = 0;
222           int                 rc = LDAP_SUCCESS;
223 
224           assert( ppFuncPtrs != NULL );
225           *ppFuncPtrs = NULL;
226 
227           if ( be == NULL ) {
228                     goto done;
229           }
230 
231           pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
232 
233           while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
234                     rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
235                     if ( rc == LDAP_SUCCESS ) {
236                               if ( FuncPtr != NULL )  {
237                                         numPB++;
238                               }
239                               rc = slapi_pblock_get( pCurrentPB,
240                                         SLAPI_IBM_PBLOCK, &pCurrentPB );
241                     }
242           }
243 
244           if ( numPB == 0 ) {
245                     rc = LDAP_SUCCESS;
246                     goto done;
247           }
248 
249           /*
250            * Now, build the function pointer array of backend-specific
251            * plugins followed by global plugins.
252            */
253           *ppFuncPtrs = pTmpFuncPtr =
254                     (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) );
255           if ( ppFuncPtrs == NULL ) {
256                     rc = LDAP_NO_MEMORY;
257                     goto done;
258           }
259 
260           pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
261 
262           while ( pCurrentPB != NULL && rc == LDAP_SUCCESS )  {
263                     rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
264                     if ( rc == LDAP_SUCCESS ) {
265                               if ( FuncPtr != NULL )  {
266                                         *pTmpFuncPtr = FuncPtr;
267                                         pTmpFuncPtr++;
268                               }
269                               rc = slapi_pblock_get( pCurrentPB,
270                                                   SLAPI_IBM_PBLOCK, &pCurrentPB );
271                     }
272           }
273 
274           *pTmpFuncPtr = NULL;
275 
276 
277 done:
278           if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
279                     ch_free( *ppFuncPtrs );
280                     *ppFuncPtrs = NULL;
281           }
282 
283           return rc;
284 }
285 
286 /*********************************************************************
287  * Function Name:      createExtendedOp
288  *
289  * Description: Creates an extended operation structure and
290  *              initializes the fields
291  *
292  * Return value: A newly allocated structure or NULL
293  ********************************************************************/
294 ExtendedOp *
createExtendedOp()295 createExtendedOp()
296 {
297           ExtendedOp *ret;
298 
299           ret = (ExtendedOp *)slapi_ch_malloc(sizeof(ExtendedOp));
300           ret->ext_oid.bv_val = NULL;
301           ret->ext_oid.bv_len = 0;
302           ret->ext_func = NULL;
303           ret->ext_be = NULL;
304           ret->ext_next = NULL;
305 
306           return ret;
307 }
308 
309 
310 /*********************************************************************
311  * Function Name:      slapi_int_unregister_extop
312  *
313  * Description:        This routine removes the ExtendedOp structures
314  *                                                   asscoiated with a particular extended operation
315  *                                                   plugin.
316  *
317  * Input:              pBE - pointer to a backend structure
318  *                     opList - pointer to a linked list of extended
319  *                              operation structures
320  *                     pPB - pointer to a slapi parameter block
321  *
322  * Output:
323  *
324  * Return Value:       none
325  *
326  * Messages:           None
327  *********************************************************************/
328 void
slapi_int_unregister_extop(Backend * pBE,ExtendedOp ** opList,Slapi_PBlock * pPB)329 slapi_int_unregister_extop(
330           Backend *pBE,
331           ExtendedOp **opList,
332           Slapi_PBlock *pPB )
333 {
334           ExtendedOp          *pTmpExtOp, *backExtOp;
335           char                **pTmpOIDs;
336           int                 i;
337 
338 #if 0
339           assert( pBE != NULL); /* unused */
340 #endif /* 0 */
341           assert( opList != NULL );
342           assert( pPB != NULL );
343 
344           if ( *opList == NULL ) {
345                     return;
346           }
347 
348           slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
349           if ( pTmpOIDs == NULL ) {
350                     return;
351           }
352 
353           for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
354                     backExtOp = NULL;
355                     pTmpExtOp = *opList;
356                     for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
357                               int       rc;
358                               rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
359                                                   pTmpOIDs[ i ] );
360                               if ( rc == 0 ) {
361                                         if ( backExtOp == NULL ) {
362                                                   *opList = pTmpExtOp->ext_next;
363                                         } else {
364                                                   backExtOp->ext_next
365                                                             = pTmpExtOp->ext_next;
366                                         }
367 
368                                         ch_free( pTmpExtOp );
369                                         break;
370                               }
371                               backExtOp = pTmpExtOp;
372                     }
373           }
374 }
375 
376 
377 /*********************************************************************
378  * Function Name:      slapi_int_register_extop
379  *
380  * Description:        This routine creates a new ExtendedOp structure, loads
381  *                     in the extended op module and put the extended op function address
382  *                     in the structure. The function will not be executed in
383  *                     this routine.
384  *
385  * Input:              pBE - pointer to a backend structure
386  *                     opList - pointer to a linked list of extended
387  *                              operation structures
388  *                     pPB - pointer to a slapi parameter block
389  *
390  * Output:
391  *
392  * Return Value:       an LDAP return code
393  *
394  * Messages:           None
395  *********************************************************************/
396 int
slapi_int_register_extop(Backend * pBE,ExtendedOp ** opList,Slapi_PBlock * pPB)397 slapi_int_register_extop(
398           Backend *pBE,
399           ExtendedOp **opList,
400           Slapi_PBlock *pPB )
401 {
402           ExtendedOp          *pTmpExtOp = NULL;
403           SLAPI_FUNC          tmpFunc;
404           char                **pTmpOIDs;
405           int                 rc = LDAP_OTHER;
406           int                 i;
407 
408           if ( (*opList) == NULL ) {
409                     *opList = createExtendedOp();
410                     if ( (*opList) == NULL ) {
411                               rc = LDAP_NO_MEMORY;
412                               goto error_return;
413                     }
414                     pTmpExtOp = *opList;
415 
416           } else {                        /* Find the end of the list */
417                     for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
418                                         pTmpExtOp = pTmpExtOp->ext_next )
419                               ; /* EMPTY */
420                     pTmpExtOp->ext_next = createExtendedOp();
421                     if ( pTmpExtOp->ext_next == NULL ) {
422                               rc = LDAP_NO_MEMORY;
423                               goto error_return;
424                     }
425                     pTmpExtOp = pTmpExtOp->ext_next;
426           }
427 
428           rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
429           if ( rc != 0 ) {
430                     rc = LDAP_OTHER;
431                     goto error_return;
432           }
433 
434           rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
435           if ( rc != 0 ) {
436                     rc = LDAP_OTHER;
437                     goto error_return;
438           }
439 
440           if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
441                     rc = LDAP_OTHER;
442                     goto error_return;
443           }
444 
445           for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
446                     pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
447                     pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
448                     pTmpExtOp->ext_func = tmpFunc;
449                     pTmpExtOp->ext_be = pBE;
450                     if ( pTmpOIDs[i + 1] != NULL ) {
451                               pTmpExtOp->ext_next = createExtendedOp();
452                               if ( pTmpExtOp->ext_next == NULL ) {
453                                         rc = LDAP_NO_MEMORY;
454                                         break;
455                               }
456                               pTmpExtOp = pTmpExtOp->ext_next;
457                     }
458           }
459 
460 error_return:
461           return rc;
462 }
463 
464 /*********************************************************************
465  * Function Name:      slapi_int_get_extop_plugin
466  *
467  * Description:        This routine gets the function address for a given function
468  *                     name.
469  *
470  * Input:
471  *                     funcName - name of the extended op function, ie. an OID.
472  *
473  * Output:             pFuncAddr - the function address of the requested function name.
474  *
475  * Return Values:      a pointer to a newly created ExtendOp structure or
476  *                     NULL - function failed
477  *
478  * Messages:           None
479  *********************************************************************/
480 int
slapi_int_get_extop_plugin(struct berval * reqoid,SLAPI_FUNC * pFuncAddr)481 slapi_int_get_extop_plugin(
482           struct berval *reqoid,
483           SLAPI_FUNC *pFuncAddr )
484 {
485           ExtendedOp          *pTmpExtOp;
486 
487           assert( reqoid != NULL );
488           assert( pFuncAddr != NULL );
489 
490           *pFuncAddr = NULL;
491 
492           if ( pGExtendedOps == NULL ) {
493                     return LDAP_OTHER;
494           }
495 
496           pTmpExtOp = pGExtendedOps;
497           while ( pTmpExtOp != NULL ) {
498                     int       rc;
499 
500                     rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
501                     if ( rc == 0 ) {
502                               *pFuncAddr = pTmpExtOp->ext_func;
503                               break;
504                     }
505                     pTmpExtOp = pTmpExtOp->ext_next;
506           }
507 
508           return ( *pFuncAddr == NULL ? 1 : 0 );
509 }
510 
511 /***************************************************************************
512  * This function is similar to slapi_int_get_extop_plugin above. except it returns one OID
513  * per call. It is called from root_dse_info (root_dse.c).
514  * The function is a modified version of get_supported_extop (file extended.c).
515  ***************************************************************************/
516 struct berval *
slapi_int_get_supported_extop(int index)517 slapi_int_get_supported_extop( int index )
518 {
519         ExtendedOp  *ext;
520 
521         for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
522                               ext = ext->ext_next) {
523                 ; /* empty */
524         }
525 
526         if ( ext == NULL ) {
527                     return NULL;
528           }
529 
530         return &ext->ext_oid ;
531 }
532 
533 /*********************************************************************
534  * Function Name:      slapi_int_load_plugin
535  *
536  * Description:        This routine loads the specified DLL, gets and executes the init function
537  *                     if requested.
538  *
539  * Input:
540  *                     pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
541  *                               the DLL init function.
542  *                     path - path name of the DLL to be load.
543  *                     initfunc - either the DLL initialization function or an OID of the
544  *                                loaded extended operation.
545  *                     doInit - if it is TRUE, execute the init function, otherwise, save the
546  *                              function address but not execute it.
547  *
548  * Output:             pInitFunc - the function address of the loaded function. This param
549  *                                 should be not be null if doInit is FALSE.
550  *                     pLdHandle - handle returned by lt_dlopen()
551  *
552  * Return Values:      LDAP_SUCCESS, LDAP_LOCAL_ERROR
553  *
554  * Messages:           None
555  *********************************************************************/
556 
557 static int
slapi_int_load_plugin(Slapi_PBlock * pPlugin,const char * path,const char * initfunc,int doInit,SLAPI_FUNC * pInitFunc,lt_dlhandle * pLdHandle)558 slapi_int_load_plugin(
559           Slapi_PBlock        *pPlugin,
560           const char          *path,
561           const char          *initfunc,
562           int                 doInit,
563           SLAPI_FUNC          *pInitFunc,
564           lt_dlhandle         *pLdHandle )
565 {
566           int                 rc = LDAP_SUCCESS;
567           SLAPI_FUNC          fpInitFunc = NULL;
568 
569           assert( pLdHandle != NULL );
570 
571           if ( lt_dlinit() ) {
572                     return LDAP_LOCAL_ERROR;
573           }
574 
575           /* load in the module */
576           *pLdHandle = lt_dlopen( path );
577           if ( *pLdHandle == NULL ) {
578                     fprintf( stderr, "failed to load plugin %s: %s\n",
579                                path, lt_dlerror() );
580                     return LDAP_LOCAL_ERROR;
581           }
582 
583           fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
584           if ( fpInitFunc == NULL ) {
585                     fprintf( stderr, "failed to find symbol %s in plugin %s: %s\n",
586                                initfunc, path, lt_dlerror() );
587                     lt_dlclose( *pLdHandle );
588                     return LDAP_LOCAL_ERROR;
589           }
590 
591           if ( doInit ) {
592                     rc = ( *fpInitFunc )( pPlugin );
593                     if ( rc != LDAP_SUCCESS ) {
594                               lt_dlclose( *pLdHandle );
595                     }
596 
597           } else {
598                     *pInitFunc = fpInitFunc;
599           }
600 
601           return rc;
602 }
603 
604 /*
605  * Special support for computed attribute plugins
606  */
607 int
slapi_int_call_plugins(Backend * be,int funcType,Slapi_PBlock * pPB)608 slapi_int_call_plugins(
609           Backend             *be,
610           int                 funcType,
611           Slapi_PBlock        *pPB )
612 {
613 
614           int rc = 0;
615           SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL;
616 
617           if ( pPB == NULL ) {
618                     return 1;
619           }
620 
621           rc = slapi_int_get_plugins( be, funcType, &tmpPlugin );
622           if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
623                     /* Nothing to do, front-end should ignore. */
624                     return rc;
625           }
626 
627           for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
628                     rc = (*pGetPlugin)(pPB);
629 
630                     /*
631                      * Only non-postoperation plugins abort processing on
632                      * failure (confirmed with SLAPI specification).
633                      */
634                     if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
635                               /*
636                                * Plugins generally return negative error codes
637                                * to indicate failure, although in the case of
638                                * bind plugins they may return SLAPI_BIND_xxx
639                                */
640                               break;
641                     }
642           }
643 
644           slapi_ch_free( (void **)&tmpPlugin );
645 
646           return rc;
647 }
648 
649 int
slapi_int_read_config(Backend * be,const char * fname,int lineno,int argc,char ** argv,int index)650 slapi_int_read_config(
651           Backend             *be,
652           const char          *fname,
653           int                 lineno,
654           int                 argc,
655           char                **argv,
656           int                 index )
657 {
658           int                 iType = -1;
659           int                 numPluginArgc = 0;
660 
661           if ( argc < 4 ) {
662                     fprintf( stderr,
663                               "%s: line %d: missing arguments "
664                               "in \"plugin <plugin_type> <lib_path> "
665                               "<init_function> [<arguments>]\" line\n",
666                               fname, lineno );
667                     return 1;
668           }
669 
670           /* automatically instantiate overlay if necessary */
671           if ( !slapi_over_is_inst( be ) ) {
672                     ConfigReply cr = { 0 };
673                     if ( slapi_over_config( be, &cr ) != 0 ) {
674                               fprintf( stderr, "Failed to instantiate SLAPI overlay: "
675                                         "err=%d msg=\"%s\"\n", cr.err, cr.msg );
676                               return -1;
677                     }
678           }
679 
680           if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
681                     iType = SLAPI_PLUGIN_PREOPERATION;
682           } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
683                     iType = SLAPI_PLUGIN_POSTOPERATION;
684           } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
685                     iType = SLAPI_PLUGIN_EXTENDEDOP;
686           } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
687                     iType = SLAPI_PLUGIN_OBJECT;
688           } else {
689                     fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
690                                         fname, lineno, argv[1] );
691                     return 1;
692           }
693 
694           numPluginArgc = argc - 4;
695 
696           if ( iType == SLAPI_PLUGIN_PREOPERATION ||
697                               iType == SLAPI_PLUGIN_EXTENDEDOP ||
698                               iType == SLAPI_PLUGIN_POSTOPERATION ||
699                               iType == SLAPI_PLUGIN_OBJECT ) {
700                     int rc;
701                     Slapi_PBlock *pPlugin;
702 
703                     pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
704                     if (pPlugin == NULL) {
705                               return 1;
706                     }
707 
708                     if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
709                               rc = slapi_int_register_extop(be, &pGExtendedOps, pPlugin);
710                               if ( rc != LDAP_SUCCESS ) {
711                                         slapi_pblock_destroy( pPlugin );
712                                         return 1;
713                               }
714                     }
715 
716                     rc = slapi_int_register_plugin_index( be, pPlugin, index );
717                     if ( rc != LDAP_SUCCESS ) {
718                               if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
719                                         slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
720                               }
721                               slapi_pblock_destroy( pPlugin );
722                               return 1;
723                     }
724           }
725 
726           return 0;
727 }
728 
729 int
slapi_int_unregister_plugin(Backend * be,Slapi_PBlock * pPlugin,Slapi_PBlock * pPrev)730 slapi_int_unregister_plugin(
731           Backend *be,
732           Slapi_PBlock *pPlugin,
733           Slapi_PBlock *pPrev
734 )
735 {
736           int type;
737 
738           assert( pPlugin != NULL );
739 
740           slapi_pblock_get( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
741           if ( type == SLAPI_PLUGIN_EXTENDEDOP ) {
742                     slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
743           }
744 
745           if ( pPrev != NULL ) {
746                     Slapi_PBlock *pNext = NULL;
747 
748                     slapi_pblock_get( pPlugin, SLAPI_IBM_PBLOCK, &pNext );
749                     slapi_pblock_set( pPrev, SLAPI_IBM_PBLOCK, &pNext );
750           }
751           slapi_pblock_destroy( pPlugin );
752 
753           return LDAP_SUCCESS;
754 }
755 
756 int
slapi_int_unregister_plugins(Backend * be,int index)757 slapi_int_unregister_plugins(
758           Backend *be,
759           int index
760 )
761 {
762           Slapi_PBlock        *pTmpPB = NULL;
763           Slapi_PBlock        *pSavePB = NULL;
764           int rc = LDAP_SUCCESS;
765 
766           pTmpPB = SLAPI_BACKEND_PBLOCK( be );
767           if ( pTmpPB == NULL ) {
768                     return ( index < 0 ) ? LDAP_SUCCESS : LDAP_OTHER;
769           }
770 
771           if ( index < 0 ) {
772                     /* All plugins must go */
773                     while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
774                               pSavePB = pTmpPB;
775                               rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
776                               if ( pSavePB != NULL ) {
777                                         slapi_int_unregister_plugin( be, pSavePB, NULL );
778                               }
779                     }
780           } else if ( index == 0 ) {
781                     slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pSavePB );
782                     SLAPI_BACKEND_PBLOCK( be ) = pSavePB;
783                     slapi_int_unregister_plugin( be, pTmpPB, NULL );
784           } else {
785                     int pos = -1;
786                     while ( pTmpPB != NULL && rc == LDAP_SUCCESS && ++pos < index ) {
787                               pSavePB = pTmpPB;
788                               rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
789                     }
790                     if ( pos == index ) {
791                               slapi_int_unregister_plugin( be, pTmpPB, pSavePB );
792                     }
793           }
794           return rc;
795 }
796 
797 void
slapi_int_plugin_unparse(Backend * be,BerVarray * out)798 slapi_int_plugin_unparse(
799           Backend *be,
800           BerVarray *out
801 )
802 {
803           Slapi_PBlock *pp;
804           int i, j;
805           char **argv, ibuf[32], *ptr;
806           struct berval idx, bv;
807 
808           *out = NULL;
809           idx.bv_val = ibuf;
810           i = 0;
811 
812           for ( pp = SLAPI_BACKEND_PBLOCK( be );
813                 pp != NULL;
814                 slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) )
815           {
816                     slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv );
817                     if ( argv == NULL ) /* could be dynamic plugin */
818                               continue;
819                     idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
820                     if ( idx.bv_len >= sizeof( ibuf ) ) {
821                               /* FIXME: just truncating by now */
822                               idx.bv_len = sizeof( ibuf ) - 1;
823                     }
824                     bv.bv_len = idx.bv_len;
825                     for (j=1; argv[j]; j++) {
826                               bv.bv_len += strlen(argv[j]);
827                               if ( j ) bv.bv_len++;
828                     }
829                     bv.bv_val = ch_malloc( bv.bv_len + 1 );
830                     ptr = lutil_strcopy( bv.bv_val, ibuf );
831                     for (j=1; argv[j]; j++) {
832                               if ( j ) *ptr++ = ' ';
833                               ptr = lutil_strcopy( ptr, argv[j] );
834                     }
835                     ber_bvarray_add( out, &bv );
836           }
837 }
838 #endif /* HAVE_LTDL_H */
839