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