plugin.c 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /* plugin.c - routines for setting up and calling plugins */
  39. #include <stddef.h>
  40. #include <stdio.h>
  41. #include <plhash.h>
  42. #include "slap.h"
  43. /* this defines are used for plugin configuration */
  44. #define LOCAL_DATA "local data"
  45. #define REMOTE_DATA "remote data"
  46. #define ALL_DATA "*"
  47. #define ROOT_BIND "directory manager"
  48. #define ANONYMOUS_BIND "anonymous"
  49. /* Forward Declarations */
  50. static int plugin_call_list (struct slapdplugin *list, int operation, Slapi_PBlock *pb);
  51. static int plugin_call_one (struct slapdplugin *list, int operation, Slapi_PBlock *pb);
  52. static int plugin_call_func (struct slapdplugin *list, int operation, Slapi_PBlock *pb, int call_one);
  53. static PRBool plugin_invoke_plugin_pb (struct slapdplugin *plugin, int operation, Slapi_PBlock *pb);
  54. static PRBool plugin_matches_operation (Slapi_DN *target_spec, PluginTargetData *ptd,
  55. PRBool bindop, PRBool isroot, PRBool islocal, int method);
  56. static int isApprovedPlugin( struct slapdplugin *plugin );
  57. static void plugin_config_init (struct pluginconfig *config);
  58. static void plugin_config_cleanup (struct pluginconfig *config);
  59. static int plugin_config_set_action (int *action, char *value);
  60. static struct pluginconfig* plugin_get_config (struct slapdplugin *plugin);
  61. static void default_plugin_init();
  62. static void ptd_init (PluginTargetData *ptd);
  63. static void ptd_cleanup (PluginTargetData *ptd);
  64. static void ptd_add_subtree (PluginTargetData *ptd, Slapi_DN *subtree);
  65. static void ptd_set_special_data (PluginTargetData *ptd, int type);
  66. static Slapi_DN *ptd_get_first_subtree (const PluginTargetData *ptd, int *cookie);
  67. static Slapi_DN *ptd_get_next_subtree (const PluginTargetData *ptd, int *cookie);
  68. static PRBool ptd_is_special_data_set (const PluginTargetData *ptd, int type);
  69. int ptd_get_subtree_count (const PluginTargetData *ptd);
  70. static void plugin_set_global (PluginTargetData *ptd);
  71. static PRBool plugin_is_global (const PluginTargetData *ptd);
  72. static void plugin_set_default_access (struct pluginconfig *config);
  73. static PLHashTable *global_plugin_dns = NULL;
  74. /* The global plugin list is indexed by the PLUGIN_LIST_* constants defined in slap.h */
  75. static struct slapdplugin *global_plugin_list[PLUGIN_LIST_GLOBAL_MAX];
  76. /* plugin structure used to configure internal operation issued by the core server */
  77. static int global_server_plg_initialised= 0;
  78. struct slapdplugin global_server_plg;
  79. /* plugin structure used to configure internal operation issued by the core server */
  80. static int global_server_plg_id_initialised= 0;
  81. struct slapi_componentid global_server_id_plg;
  82. /* plugin structure used to configure operations issued by the old plugins that
  83. do not pass their identity in the operation */
  84. static struct slapdplugin global_default_plg;
  85. /* Enable/disable plugin callbacks for clean startup */
  86. static int global_plugin_callbacks_enabled = 0;
  87. static void
  88. add_plugin_to_list(struct slapdplugin **list, struct slapdplugin *plugin)
  89. {
  90. struct slapdplugin **tmp;
  91. for ( tmp = list; *tmp; tmp = &(*tmp)->plg_next )
  92. {
  93. ; /* NULL */
  94. }
  95. *tmp = plugin;
  96. }
  97. struct slapdplugin *
  98. get_plugin_list(int plugin_list_index)
  99. {
  100. return global_plugin_list[plugin_list_index];
  101. }
  102. /*
  103. * As the plugin configuration information is read an array of
  104. * entries is built which reflect the plugins. The entries
  105. * are added after the syntax plugins are started so that the
  106. * nodes in the attribute tree are initialised correctly.
  107. */
  108. typedef struct entry_and_plugin {
  109. Slapi_Entry *e;
  110. struct slapdplugin *plugin;
  111. struct entry_and_plugin *next;
  112. } entry_and_plugin_t;
  113. static entry_and_plugin_t *dep_plugin_entries = NULL; /* for dependencies */
  114. #if 0
  115. static entry_and_plugin_t *plugin_entries = NULL;
  116. static void
  117. add_plugin_entries()
  118. {
  119. entry_and_plugin_t *ep = plugin_entries;
  120. entry_and_plugin_t *deleteep = 0;
  121. while (ep)
  122. {
  123. int plugin_actions = 0;
  124. Slapi_PBlock newpb;
  125. pblock_init(&newpb);
  126. slapi_add_entry_internal_set_pb(&newpb, ep->e, NULL,
  127. ep->plugin, plugin_actions);
  128. slapi_pblock_set(&newpb, SLAPI_TARGET_DN, (void*)slapi_entry_get_dn_const(ep->e));
  129. slapi_add_internal_pb(&newpb);
  130. deleteep = ep;
  131. ep = ep->next;
  132. slapi_ch_free((void**)&deleteep);
  133. pblock_done(&newpb);
  134. }
  135. plugin_entries = NULL;
  136. }
  137. #endif
  138. static void
  139. new_plugin_entry(entry_and_plugin_t **ep, Slapi_Entry *e, struct slapdplugin *plugin)
  140. {
  141. entry_and_plugin_t *oldep = 0;
  142. entry_and_plugin_t *iterep = *ep;
  143. entry_and_plugin_t *newep =
  144. (entry_and_plugin_t*)slapi_ch_calloc(1,sizeof(entry_and_plugin_t));
  145. newep->e = e;
  146. newep->plugin = plugin;
  147. while(iterep)
  148. {
  149. oldep = iterep;
  150. iterep = iterep->next;
  151. }
  152. newep->next = 0;
  153. if(oldep)
  154. oldep->next = newep;
  155. else
  156. *ep = newep;
  157. }
  158. static void
  159. add_plugin_entry_dn(const Slapi_DN *plugin_dn)
  160. {
  161. if (!global_plugin_dns)
  162. {
  163. global_plugin_dns = PL_NewHashTable(20, PL_HashString,
  164. PL_CompareStrings,
  165. PL_CompareValues, 0, 0);
  166. }
  167. PL_HashTableAdd(global_plugin_dns,
  168. slapi_sdn_get_ndn(plugin_dn),
  169. (void*)plugin_dn);
  170. }
  171. #define SLAPI_PLUGIN_NONE_IF_NULL( s ) ((s) == NULL ? "none" : (s))
  172. /*
  173. * Allows a plugin to register a plugin.
  174. * This was added so that 'object' plugins could register all
  175. * the plugin interfaces that it supports.
  176. */
  177. int
  178. slapi_register_plugin(
  179. const char *plugintype,
  180. int enabled,
  181. const char *initsymbol,
  182. slapi_plugin_init_fnptr initfunc,
  183. const char *name,
  184. char **argv,
  185. void *group_identity
  186. )
  187. {
  188. int ii = 0;
  189. int rc = 0;
  190. Slapi_Entry *e = slapi_entry_alloc();
  191. char *dn = slapi_ch_smprintf("cn=%s, %s", name, PLUGIN_BASE_DN);
  192. /* this function consumes dn */
  193. slapi_entry_init(e, dn, NULL);
  194. slapi_entry_attr_set_charptr(e, "cn", name);
  195. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_TYPE, plugintype);
  196. if (!enabled)
  197. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_ENABLED, "off");
  198. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_INITFN, initsymbol);
  199. for (ii = 0; argv && argv[ii]; ++ii) {
  200. char argname[64];
  201. PR_snprintf(argname, sizeof(argname), "%s%d", ATTR_PLUGIN_ARG, ii);
  202. slapi_entry_attr_set_charptr(e, argname, argv[ii]);
  203. }
  204. /* plugin_setup copies the given entry */
  205. plugin_setup(e, group_identity, initfunc, 0);
  206. slapi_entry_free(e);
  207. return rc;
  208. }
  209. int
  210. plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
  211. {
  212. int plugin_list_number= -1;
  213. int rc= 0;
  214. int do_op = global_plugin_callbacks_enabled;
  215. if ( pb == NULL )
  216. {
  217. return( 0 );
  218. }
  219. switch ( whichfunction ) {
  220. case SLAPI_PLUGIN_PRE_BIND_FN:
  221. case SLAPI_PLUGIN_PRE_UNBIND_FN:
  222. case SLAPI_PLUGIN_PRE_SEARCH_FN:
  223. case SLAPI_PLUGIN_PRE_COMPARE_FN:
  224. case SLAPI_PLUGIN_PRE_MODIFY_FN:
  225. case SLAPI_PLUGIN_PRE_MODRDN_FN:
  226. case SLAPI_PLUGIN_PRE_ADD_FN:
  227. case SLAPI_PLUGIN_PRE_DELETE_FN:
  228. case SLAPI_PLUGIN_PRE_ABANDON_FN:
  229. case SLAPI_PLUGIN_PRE_ENTRY_FN:
  230. case SLAPI_PLUGIN_PRE_REFERRAL_FN:
  231. case SLAPI_PLUGIN_PRE_RESULT_FN:
  232. plugin_list_number= PLUGIN_LIST_PREOPERATION;
  233. break;
  234. case SLAPI_PLUGIN_POST_BIND_FN:
  235. case SLAPI_PLUGIN_POST_UNBIND_FN:
  236. case SLAPI_PLUGIN_POST_SEARCH_FN:
  237. case SLAPI_PLUGIN_POST_SEARCH_FAIL_FN:
  238. case SLAPI_PLUGIN_POST_COMPARE_FN:
  239. case SLAPI_PLUGIN_POST_MODIFY_FN:
  240. case SLAPI_PLUGIN_POST_MODRDN_FN:
  241. case SLAPI_PLUGIN_POST_ADD_FN:
  242. case SLAPI_PLUGIN_POST_DELETE_FN:
  243. case SLAPI_PLUGIN_POST_ABANDON_FN:
  244. case SLAPI_PLUGIN_POST_ENTRY_FN:
  245. case SLAPI_PLUGIN_POST_REFERRAL_FN:
  246. case SLAPI_PLUGIN_POST_RESULT_FN:
  247. plugin_list_number= PLUGIN_LIST_POSTOPERATION;
  248. break;
  249. case SLAPI_PLUGIN_BE_PRE_MODIFY_FN:
  250. case SLAPI_PLUGIN_BE_PRE_MODRDN_FN:
  251. case SLAPI_PLUGIN_BE_PRE_ADD_FN:
  252. case SLAPI_PLUGIN_BE_PRE_DELETE_FN:
  253. plugin_list_number= PLUGIN_LIST_BEPREOPERATION;
  254. do_op = 1; /* always allow backend callbacks (even during startup) */
  255. break;
  256. case SLAPI_PLUGIN_BE_POST_MODIFY_FN:
  257. case SLAPI_PLUGIN_BE_POST_MODRDN_FN:
  258. case SLAPI_PLUGIN_BE_POST_ADD_FN:
  259. case SLAPI_PLUGIN_BE_POST_DELETE_FN:
  260. plugin_list_number= PLUGIN_LIST_BEPOSTOPERATION;
  261. do_op = 1; /* always allow backend callbacks (even during startup) */
  262. break;
  263. case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN:
  264. case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
  265. case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
  266. case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
  267. plugin_list_number= PLUGIN_LIST_INTERNAL_PREOPERATION;
  268. break;
  269. case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
  270. case SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN:
  271. case SLAPI_PLUGIN_INTERNAL_POST_ADD_FN:
  272. case SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN:
  273. plugin_list_number= PLUGIN_LIST_INTERNAL_POSTOPERATION;
  274. break;
  275. }
  276. if(plugin_list_number!=-1 && do_op)
  277. {
  278. /* We stash the pblock plugin pointer to preserve the callers context */
  279. struct slapdplugin *p;
  280. slapi_pblock_get(pb, SLAPI_PLUGIN, &p);
  281. /* Call the operation on the Global Plugins */
  282. rc= plugin_call_list(global_plugin_list[plugin_list_number], whichfunction, pb);
  283. slapi_pblock_set(pb, SLAPI_PLUGIN, p);
  284. }
  285. else
  286. {
  287. /* Programmer error! or the callback is denied during startup */
  288. }
  289. return rc;
  290. }
  291. void
  292. plugin_call_entrystore_plugins(char **entrystr, uint *size)
  293. {
  294. struct slapdplugin *p;
  295. for (p = global_plugin_list[PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE];
  296. p != NULL; p = p->plg_next )
  297. {
  298. if (p->plg_entrystorefunc)
  299. (*p->plg_entrystorefunc)(entrystr, size);
  300. }
  301. }
  302. void
  303. plugin_call_entryfetch_plugins(char **entrystr, uint *size)
  304. {
  305. struct slapdplugin *p;
  306. for (p = global_plugin_list[PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE];
  307. p != NULL; p = p->plg_next )
  308. {
  309. if (p->plg_entryfetchfunc)
  310. (*p->plg_entryfetchfunc)(entrystr, size);
  311. }
  312. }
  313. /*
  314. * call extended operation plugins
  315. *
  316. * return SLAPI_PLUGIN_EXTENDED_SENT_RESULT if one of the extended operation
  317. * plugins sent a result.
  318. * return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED if no extended operation plugins
  319. * handled the operation.
  320. * otherwise, return an LDAP error code (possibly a merge of the errors
  321. * returned by the plugins we called).
  322. */
  323. int
  324. plugin_call_exop_plugins( Slapi_PBlock *pb, char *oid )
  325. {
  326. struct slapdplugin *p;
  327. int i, rc;
  328. int lderr = SLAPI_PLUGIN_EXTENDED_NOT_HANDLED;
  329. for ( p = global_plugin_list[PLUGIN_LIST_EXTENDED_OPERATION]; p != NULL; p = p->plg_next ) {
  330. if ( p->plg_exhandler != NULL ) {
  331. if ( p->plg_exoids != NULL ) {
  332. for ( i = 0; p->plg_exoids[i] != NULL; i++ ) {
  333. if ( strcasecmp( oid, p->plg_exoids[i] )
  334. == 0 ) {
  335. break;
  336. }
  337. }
  338. if ( p->plg_exoids[i] == NULL ) {
  339. continue;
  340. }
  341. }
  342. slapi_pblock_set( pb, SLAPI_PLUGIN, p );
  343. set_db_default_result_handlers( pb );
  344. if ( (rc = (*p->plg_exhandler)( pb ))
  345. == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) {
  346. return( rc ); /* result sent */
  347. } else if ( rc != SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) {
  348. /*
  349. * simple merge: report last real error
  350. */
  351. if ( lderr == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED
  352. || rc != LDAP_SUCCESS ) {
  353. lderr = rc;
  354. }
  355. }
  356. }
  357. }
  358. return( lderr );
  359. }
  360. /*
  361. * Attempt to convert the extended operation 'oid' to a string by
  362. * examining the registered plugins. Returns NULL if no plugin is
  363. * registered for this OID.
  364. *
  365. * Our first choice is to use an OID-specific name that has been
  366. * registered by a plugin via the SLAPI_PLUGIN_EXT_OP_NAMELIST pblock setting.
  367. * Our second choice is to use the plugin's ID (short name).
  368. * Our third choice is to use the plugin's RDN (under cn=config).
  369. */
  370. const char *
  371. plugin_extended_op_oid2string( const char *oid )
  372. {
  373. struct slapdplugin *p;
  374. int i, j;
  375. const char *rval = NULL;
  376. for ( p = global_plugin_list[PLUGIN_LIST_EXTENDED_OPERATION]; p != NULL;
  377. p = p->plg_next ) {
  378. if ( p->plg_exhandler != NULL && p->plg_exoids != NULL ) {
  379. for ( i = 0; p->plg_exoids[i] != NULL; i++ ) {
  380. if ( strcasecmp( oid, p->plg_exoids[i] ) == 0 ) {
  381. if ( NULL != p->plg_exnames ) {
  382. for ( j = 0; j < i && p->plg_exnames[j] != NULL; ++j ) {
  383. ;
  384. }
  385. rval = p->plg_exnames[j]; /* OID-related name */
  386. }
  387. if ( NULL == rval ) {
  388. if ( NULL != p->plg_desc.spd_id ) {
  389. rval = p->plg_desc.spd_id; /* short name */
  390. } else {
  391. rval = p->plg_name; /* RDN */
  392. }
  393. }
  394. break;
  395. }
  396. if ( p->plg_exoids[i] != NULL ) {
  397. break;
  398. }
  399. }
  400. }
  401. }
  402. return( rval );
  403. }
  404. /*
  405. * kexcoff: return the slapdplugin structure
  406. */
  407. struct slapdplugin *
  408. plugin_get_pwd_storage_scheme(char *name, int len, int index)
  409. {
  410. /* index could be PLUGIN_LIST_PWD_STORAGE_SCHEME or PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME */
  411. struct slapdplugin *p;
  412. for ( p = global_plugin_list[index]; p != NULL; p = p->plg_next ) {
  413. if (strncasecmp(p->plg_pwdstorageschemename, name, len) == 0)
  414. return( p );
  415. }
  416. return( NULL );
  417. }
  418. char *
  419. plugin_get_pwd_storage_scheme_list(int index)
  420. {
  421. /* index could be PLUGIN_LIST_PWD_STORAGE_SCHEME or PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME */
  422. struct slapdplugin *p = NULL;
  423. char *names_list = NULL;
  424. int len = 0;
  425. /* first pass - calculate space needed for comma delimited list */
  426. for ( p = global_plugin_list[index]; p != NULL; p = p->plg_next ) {
  427. if ( p->plg_pwdstorageschemeenc != NULL )
  428. {
  429. /* + 1 for comma, 1 for space, 1 for null */
  430. len += strlen(p->plg_pwdstorageschemename) + 3;
  431. }
  432. }
  433. /* no plugins? */
  434. if (!len)
  435. return NULL;
  436. /* next, allocate the space */
  437. names_list = (char *)slapi_ch_malloc(len+1);
  438. *names_list = 0;
  439. /* second pass - write the string */
  440. for ( p = global_plugin_list[index]; p != NULL; p = p->plg_next ) {
  441. if ( p->plg_pwdstorageschemeenc != NULL )
  442. {
  443. strcat(names_list, p->plg_pwdstorageschemename);
  444. if (p->plg_next != NULL)
  445. strcat(names_list, ", ");
  446. }
  447. }
  448. return( names_list );
  449. }
  450. int
  451. slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls,
  452. char **attrs, int attrsonly )
  453. {
  454. IFP fn = NULL;
  455. slapi_pblock_get(pb,SLAPI_PLUGIN_DB_ENTRY_FN,(void*)&fn);
  456. if (NULL == fn)
  457. {
  458. return -1;
  459. }
  460. return (*fn)(pb,e,ectrls,attrs,attrsonly);
  461. }
  462. void
  463. slapi_set_ldap_result( Slapi_PBlock *pb, int err, char *matched, char *text,
  464. int nentries, struct berval **urls )
  465. {
  466. char * old_matched = NULL;
  467. char * old_text = NULL;
  468. char * matched_copy = slapi_ch_strdup(matched);
  469. char * text_copy = slapi_ch_strdup(text);
  470. /* free the old matched and text, if any */
  471. slapi_pblock_get(pb, SLAPI_RESULT_MATCHED, &old_matched);
  472. slapi_ch_free_string(&old_matched);
  473. slapi_pblock_get(pb, SLAPI_RESULT_TEXT, &old_text);
  474. slapi_ch_free_string(&old_text);
  475. /* set the new stuff */
  476. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
  477. slapi_pblock_set(pb, SLAPI_RESULT_MATCHED, matched_copy);
  478. slapi_pblock_set(pb, SLAPI_RESULT_TEXT, text_copy);
  479. }
  480. void
  481. slapi_send_ldap_result_from_pb( Slapi_PBlock *pb)
  482. {
  483. int err;
  484. char *matched;
  485. char *text;
  486. IFP fn = NULL;
  487. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &err);
  488. slapi_pblock_get(pb, SLAPI_RESULT_TEXT, &text);
  489. slapi_pblock_get(pb, SLAPI_RESULT_MATCHED, &matched);
  490. slapi_pblock_get(pb,SLAPI_PLUGIN_DB_RESULT_FN,(void*)&fn);
  491. if (NULL != fn)
  492. {
  493. (*fn)(pb,err,matched,text,0,NULL);
  494. }
  495. slapi_pblock_set(pb, SLAPI_RESULT_TEXT, NULL);
  496. slapi_pblock_set(pb, SLAPI_RESULT_MATCHED, NULL);
  497. slapi_ch_free((void **)&matched);
  498. slapi_ch_free((void **)&text);
  499. }
  500. void
  501. slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched, char *text,
  502. int nentries, struct berval **urls )
  503. {
  504. IFP fn = NULL;
  505. Slapi_Operation *operation;
  506. long op_type;
  507. /* GB : for spanning requests over multiple backends */
  508. if (err == LDAP_NO_SUCH_OBJECT)
  509. {
  510. slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
  511. op_type = operation_get_type(operation);
  512. if (op_type == SLAPI_OPERATION_SEARCH)
  513. {
  514. if (urls || nentries)
  515. {
  516. LDAPDebug( LDAP_DEBUG_ANY, "ERROR : urls or nentries set"
  517. "in sendldap_result while NO_SUCH_OBJECT returned\n",0,0,0);
  518. }
  519. slapi_set_ldap_result(pb, err, matched, text, 0, NULL);
  520. return;
  521. }
  522. }
  523. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
  524. slapi_pblock_get(pb,SLAPI_PLUGIN_DB_RESULT_FN,(void*)&fn);
  525. if (NULL == fn)
  526. {
  527. return ;
  528. }
  529. /*
  530. * Call the result function. It should set pb->pb_op->o_status to
  531. * SLAPI_OP_STATUS_RESULT_SENT right after sending the result to
  532. * the client or otherwise consuming it.
  533. */
  534. (*fn)(pb,err,matched,text,nentries,urls);
  535. }
  536. int
  537. slapi_send_ldap_referral( Slapi_PBlock *pb, Slapi_Entry *e, struct berval **refs,
  538. struct berval ***urls )
  539. {
  540. IFP fn = NULL;
  541. slapi_pblock_get(pb,SLAPI_PLUGIN_DB_REFERRAL_FN,(void*)&fn);
  542. if (NULL == fn)
  543. {
  544. return -1;
  545. }
  546. return (*fn)(pb,e,refs,urls);
  547. }
  548. /***********************************************************
  549. start of plugin dependency code
  550. ************************************************************/
  551. /* struct _plugin_dep_type
  552. * we shall not presume to know all plugin types
  553. * so as to allow new types to be added without
  554. * requiring changes to this code (hopefully)
  555. * so we need to dynamically keep track of them
  556. */
  557. typedef struct _plugin_dep_type{
  558. char *type; /* the string descriptor */
  559. int num_not_started; /* the count of plugins which have yet to be started for this type */
  560. struct _plugin_dep_type *next;
  561. } *plugin_dep_type;
  562. /* _plugin_dep_config
  563. * we need somewhere to collect the plugin configurations
  564. * prior to attempting to resolve dependencies
  565. */
  566. typedef struct _plugin_dep_config {
  567. char *name;
  568. char *type;
  569. Slapi_PBlock pb;
  570. struct slapdplugin *plugin;
  571. Slapi_Entry *e;
  572. int entry_created;
  573. int op_done;
  574. char **depends_type_list;
  575. int total_type;
  576. char **depends_named_list;
  577. int total_named;
  578. } plugin_dep_config;
  579. /* list of plugins which should be shutdown in reverse order */
  580. static plugin_dep_config *global_plugin_shutdown_order = 0;
  581. static int global_plugins_started = 0;
  582. /*
  583. * find_plugin_type
  584. *
  585. * searches the list for the plugin type
  586. * and returns the plugin_dep_type if found
  587. */
  588. static plugin_dep_type
  589. find_plugin_type(plugin_dep_type head, char *type)
  590. {
  591. plugin_dep_type ret = 0;
  592. plugin_dep_type iter = head;
  593. while(iter)
  594. {
  595. if(!slapi_UTF8CASECMP(iter->type, type))
  596. {
  597. ret = iter;
  598. break;
  599. }
  600. iter = iter->next;
  601. }
  602. return ret;
  603. }
  604. /*
  605. * increment_plugin_type
  606. *
  607. * searches the list for the plugin type
  608. * and increments its not started value
  609. * returns the current type count on success -1 on failure
  610. * to find the type
  611. */
  612. static int
  613. increment_plugin_type(plugin_dep_type head, char *type)
  614. {
  615. int ret = -1;
  616. plugin_dep_type the_type;
  617. if ((the_type = find_plugin_type(head, type)) != NULL)
  618. ret = ++the_type->num_not_started;
  619. return ret;
  620. }
  621. /*
  622. * decrement_plugin_type
  623. *
  624. * searches the list for the plugin type
  625. * and decrements its not started value
  626. * returns the current type count on success -1 on failure
  627. * to find the type
  628. */
  629. static int
  630. decrement_plugin_type(plugin_dep_type head, char *type)
  631. {
  632. int ret = -1;
  633. plugin_dep_type the_type;
  634. if ((the_type = find_plugin_type(head, type)) != NULL)
  635. ret = --the_type->num_not_started;
  636. return ret;
  637. }
  638. /*
  639. * add_plugin_type
  640. *
  641. * Either increments the count of the plugin type
  642. * or when it does not exist, adds it to the list
  643. */
  644. static int
  645. add_plugin_type(plugin_dep_type *head, char *type)
  646. {
  647. int ret = -1;
  648. if(*head)
  649. {
  650. if(0 < increment_plugin_type(*head, type))
  651. {
  652. ret = 0;
  653. }
  654. }
  655. if(ret)
  656. {
  657. /* create new head */
  658. plugin_dep_type tmp_head;
  659. tmp_head = (plugin_dep_type)slapi_ch_malloc(sizeof(struct _plugin_dep_type));
  660. tmp_head->num_not_started = 1;
  661. tmp_head->type = slapi_ch_strdup(type);
  662. ret = 0;
  663. tmp_head->next = *head;
  664. (*head) = tmp_head;
  665. }
  666. return ret;
  667. }
  668. /*
  669. * plugin_create_stringlist
  670. *
  671. * Creates a string list from values of the entries
  672. * attribute passed in as args - used to track dependencies
  673. *
  674. */
  675. int
  676. plugin_create_stringlist( Slapi_Entry *plugin_entry, char *attr_name,
  677. int *total_strings, char ***list)
  678. {
  679. Slapi_Attr *attr = 0;
  680. int hint =0;
  681. int num_vals = 0;
  682. int val_index = 0;
  683. Slapi_Value *val;
  684. if(0 == slapi_entry_attr_find( plugin_entry, attr_name, &attr ))
  685. {
  686. /* allocate memory for the string array */
  687. slapi_attr_get_numvalues( attr, &num_vals);
  688. if(num_vals)
  689. {
  690. *total_strings = num_vals;
  691. *list = (char **)slapi_ch_malloc(sizeof(char*) * num_vals);
  692. }
  693. else
  694. goto bail; /* if this ever happens, then they are running on a TSR-80 */
  695. val_index = 0;
  696. hint = slapi_attr_first_value( attr, &val );
  697. while(val_index < num_vals)
  698. {
  699. /* add the value to the array */
  700. (*list)[val_index] = (char*)slapi_ch_strdup(slapi_value_get_string(val));
  701. hint = slapi_attr_next_value( attr, hint, &val );
  702. val_index++;
  703. }
  704. }
  705. else
  706. *total_strings = num_vals;
  707. bail:
  708. return num_vals;
  709. }
  710. /*
  711. * plugin_dependency_startall()
  712. *
  713. * Starts all plugins (apart from syntax and matching rule) in order
  714. * of dependency.
  715. *
  716. * Dependencies will be determined by these multi-valued attributes:
  717. *
  718. * nsslapd-plugin-depends-on-type : all plugins whose type value matches one of these values must
  719. * be started prior to this plugin
  720. *
  721. * nsslapd-plugin-depends-on-named : the plugin whose cn value matches one of these values must
  722. * be started prior to this plugin
  723. */
  724. static int
  725. plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation)
  726. {
  727. int ret = 0;
  728. Slapi_PBlock pb;
  729. int total_plugins = 0;
  730. plugin_dep_config *config = 0;
  731. plugin_dep_type plugin_head = 0;
  732. int plugin_index = 0;
  733. Slapi_Entry *plugin_entry;
  734. int i = 0; /* general index iterator */
  735. plugin_dep_type the_plugin_type;
  736. int index = 0;
  737. char * value;
  738. int plugins_started;
  739. int num_plg_started;
  740. struct slapdplugin *plugin;
  741. entry_and_plugin_t *ep = dep_plugin_entries;
  742. int shutdown_index = 0;
  743. /*
  744. * Disable registered plugin functions so preops/postops/etc
  745. * dont get called prior to the plugin being started (due to
  746. * plugins performing ops on the DIT)
  747. */
  748. global_plugin_callbacks_enabled = 0;
  749. /* Count the plugins so we can allocate memory for the config array */
  750. while(ep)
  751. {
  752. total_plugins++;
  753. ep = ep->next;
  754. }
  755. /* allocate the config array */
  756. config = (plugin_dep_config*)slapi_ch_malloc(sizeof(plugin_dep_config) * total_plugins);
  757. if(config)
  758. memset(config, 0, sizeof(plugin_dep_config) * total_plugins);
  759. else
  760. {
  761. ret = -1;
  762. goto bail;
  763. }
  764. ep = dep_plugin_entries;
  765. /* Collect relevant config */
  766. while(ep)
  767. {
  768. plugin = ep->plugin;
  769. if(plugin == 0)
  770. continue;
  771. pblock_init(&pb);
  772. slapi_pblock_set( &pb, SLAPI_ARGC, &argc);
  773. slapi_pblock_set( &pb, SLAPI_ARGV, &argv);
  774. config[plugin_index].pb = pb;
  775. config[plugin_index].e = ep->e;
  776. /* add type */
  777. plugin_entry = ep->e;
  778. ep->e = NULL; /* consumed by the operation above, and eventually by the
  779. slapi_internal_add operation below */
  780. if(plugin_entry)
  781. {
  782. /*
  783. * Pass the plugin DN in SLAPI_TARGET_DN and the plugin entry
  784. * in SLAPI_ADD_ENTRY. For this to actually work, we need to
  785. * create an operation and include that in the pblock as well,
  786. * because these two items are stored in the operation parameters.
  787. */
  788. /* WARNING: memory leak here - op is only freed by a pblock_done,
  789. and this only happens below if the plugin is enabled - a short
  790. circuit goto bail may also cause a leak - however, since this
  791. only happens a few times at startup, this is not a very serious
  792. leak - just after the call to plugin_call_one */
  793. Operation *op = internal_operation_new(SLAPI_OPERATION_ADD, 0);
  794. slapi_pblock_set(&(config[plugin_index].pb), SLAPI_OPERATION, op);
  795. slapi_pblock_set(&(config[plugin_index].pb), SLAPI_TARGET_DN,
  796. (void*)(slapi_entry_get_dn_const(plugin_entry)));
  797. slapi_pblock_set(&(config[plugin_index].pb), SLAPI_ADD_ENTRY,
  798. plugin_entry );
  799. value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype");
  800. if(value)
  801. {
  802. add_plugin_type( &plugin_head, value);
  803. config[plugin_index].type = value;
  804. value = NULL;
  805. }
  806. /* now the name */
  807. value = slapi_entry_attr_get_charptr(plugin_entry, "cn");
  808. if(value)
  809. {
  810. config[plugin_index].name = value;
  811. value = NULL;
  812. }
  813. config[plugin_index].plugin = plugin;
  814. /* now add dependencies */
  815. plugin_create_stringlist( plugin_entry, "nsslapd-plugin-depends-on-named",
  816. &(config[plugin_index].total_named), &(config[plugin_index].depends_named_list));
  817. plugin_create_stringlist( plugin_entry, "nsslapd-plugin-depends-on-type",
  818. &(config[plugin_index].total_type), &(config[plugin_index].depends_type_list));
  819. }
  820. plugin_index++;
  821. ep = ep->next;
  822. }
  823. /* prepare list of shutdown order (we need nothing fancier right now
  824. * than the reverse startup order) The list may include NULL entries,
  825. * these will be plugins which were never started
  826. */
  827. shutdown_index = total_plugins - 1;
  828. global_plugin_shutdown_order = (plugin_dep_config*)slapi_ch_malloc(sizeof(plugin_dep_config) * total_plugins);
  829. if(global_plugin_shutdown_order)
  830. memset(global_plugin_shutdown_order, 0, sizeof(plugin_dep_config) * total_plugins);
  831. else
  832. {
  833. ret = -1;
  834. goto bail;
  835. }
  836. /* now resolve dependencies
  837. * cycle through list, if a plugin has no dependencies then start it
  838. * then remove it from the dependency lists of all other plugins
  839. * and decrement the corresponding element of the plugin types array
  840. * for depends_type we will need to check the array of plugin types
  841. * to see if all type dependencies are at zero prior to start
  842. * if one cycle fails to load any plugins we have failed, however
  843. * we shall continue loading plugins in case a configuration error
  844. * can correct itself
  845. */
  846. plugins_started = 1;
  847. num_plg_started = 0;
  848. while(plugins_started && num_plg_started < total_plugins)
  849. {
  850. plugins_started = 0;
  851. for(plugin_index=0; plugin_index < total_plugins; plugin_index++)
  852. {
  853. /* perform op on plugins only once */
  854. if(config[plugin_index].op_done == 0)
  855. {
  856. int enabled = 0;
  857. int satisfied = 0;
  858. int break_out = 0;
  859. /*
  860. * determine if plugin is enabled
  861. * some processing is necessary even
  862. * if it is not
  863. */
  864. if ( NULL != config[plugin_index].e && (value = slapi_entry_attr_get_charptr(config[plugin_index].e,
  865. ATTR_PLUGIN_ENABLED)) &&
  866. !strcasecmp(value, "on"))
  867. {
  868. enabled = 1;
  869. }
  870. else
  871. enabled = 0;
  872. slapi_ch_free((void**)&value);
  873. /*
  874. * make sure named dependencies have been satisfied
  875. * that means that the list of names should contain all
  876. * null entries
  877. */
  878. if(enabled && config[plugin_index].total_named)
  879. {
  880. i = 0;
  881. while(break_out == 0 && i < config[plugin_index].total_named)
  882. {
  883. satisfied = 1;
  884. if((config[plugin_index].depends_named_list)[i] != 0)
  885. {
  886. satisfied = 0;
  887. break_out = 1;
  888. }
  889. i++;
  890. }
  891. if(!satisfied)
  892. continue;
  893. }
  894. /*
  895. * make sure the type dependencies have been satisfied
  896. * that means for each type in the list, it's number of
  897. * plugins left not started is zero
  898. *
  899. */
  900. satisfied = 0;
  901. break_out = 0;
  902. if(enabled && config[plugin_index].total_type)
  903. {
  904. i = 0;
  905. while(break_out == 0 && i < config[plugin_index].total_type)
  906. {
  907. satisfied = 1;
  908. the_plugin_type = find_plugin_type(plugin_head, (config[plugin_index].depends_type_list)[i]);
  909. if(the_plugin_type && the_plugin_type->num_not_started != 0)
  910. {
  911. satisfied = 0;
  912. break_out = 1;
  913. }
  914. i++;
  915. }
  916. if(!satisfied)
  917. continue;
  918. }
  919. /**** This plugins dependencies have now been satisfied ****/
  920. satisfied = 1; /* symbolic only */
  921. /*
  922. * Add the plugins entry to the DSE so the plugin can get
  923. * its config (both enabled and disabled have entries
  924. */
  925. if(!config[plugin_index].entry_created)
  926. {
  927. int plugin_actions = 0;
  928. Slapi_PBlock newpb;
  929. Slapi_Entry *newe;
  930. pblock_init(&newpb);
  931. /*
  932. * config[plugin_index].e is freed up by
  933. * below function calls, but we may need
  934. * it later, so create a copy
  935. */
  936. newe = slapi_entry_dup( config[plugin_index].e );
  937. slapi_add_entry_internal_set_pb(&newpb, newe, NULL,
  938. plugin_get_default_component_id(), plugin_actions);
  939. slapi_pblock_set(&newpb, SLAPI_TARGET_DN, (void*)slapi_entry_get_dn_const(newe));
  940. slapi_add_internal_pb(&newpb);
  941. pblock_done(&newpb);
  942. config[plugin_index].entry_created = 1;
  943. }
  944. /*
  945. * only actually start plugin and remove from lists if its enabled
  946. * we do remove from plugin type list however - rule is dependency on
  947. * zero or more for type
  948. */
  949. if (enabled)
  950. {
  951. /* finally, perform the op on the plugin */
  952. LDAPDebug( LDAP_DEBUG_PLUGIN, "Starting %s plugin %s\n" , config[plugin_index].type, config[plugin_index].name, 0 );
  953. ret = plugin_call_one( config[plugin_index].plugin, operation, &(config[plugin_index].pb));
  954. pblock_done(&(config[plugin_index].pb));
  955. if(ret)
  956. {
  957. /*
  958. * We will not exit here. If we allow plugins to load normally it is
  959. * possible that a configuration error (dependedncies which were not
  960. * configured properly) can be recovered from. If there really is a
  961. * problem then the plugin will never start and eventually it will
  962. * trigger an exit anyway.
  963. */
  964. LDAPDebug( LDAP_DEBUG_ANY, "Failed to start %s plugin %s\n" , config[plugin_index].type, config[plugin_index].name, 0 );
  965. continue;
  966. }
  967. /* Add this plugin to the shutdown list */
  968. global_plugin_shutdown_order[shutdown_index] = config[plugin_index];
  969. shutdown_index--;
  970. global_plugins_started++;
  971. /* remove this named plugin from other plugins lists */
  972. for(i=0; i<total_plugins; i++)
  973. {
  974. index = 0;
  975. while(index < config[i].total_named)
  976. {
  977. if((config[i].depends_named_list)[index] != 0 && !slapi_UTF8CASECMP((config[i].depends_named_list)[index], config[plugin_index].name))
  978. {
  979. slapi_ch_free((void**)&((config[i].depends_named_list)[index]));
  980. (config[i].depends_named_list)[index] = 0;
  981. }
  982. index++;
  983. }
  984. }
  985. }
  986. /* decrement the type counter for this plugin type */
  987. decrement_plugin_type(plugin_head, config[plugin_index].type);
  988. config[plugin_index].op_done = 1;
  989. num_plg_started++;
  990. plugins_started = 1;
  991. }
  992. }
  993. }
  994. if(plugins_started == 0)
  995. {
  996. /* a dependency was not resolved - error */
  997. LDAPDebug( LDAP_DEBUG_ANY, "Error: Failed to resolve plugin dependencies\n" , 0, 0, 0 );
  998. /* list the plugins yet to perform op */
  999. index = 0;
  1000. while(i < total_plugins)
  1001. {
  1002. if(config[i].op_done == 0)
  1003. {
  1004. LDAPDebug( LDAP_DEBUG_ANY, "Error: %s plugin %s is not started\n" , config[i].type, config[i].name, 0 );
  1005. }
  1006. i++;
  1007. }
  1008. exit(1);
  1009. }
  1010. bail:
  1011. /*
  1012. * need the details in config to hang around for shutdown
  1013. * config itself may be deleted since its contents have been
  1014. * copied by value to the shutdown list
  1015. */
  1016. if(config)
  1017. {
  1018. index = 0;
  1019. while(index < total_plugins)
  1020. {
  1021. /*
  1022. if(config[index].depends_named_list)
  1023. {
  1024. slapi_ch_free((void**)&(config[index].depends_named_list));
  1025. }
  1026. */
  1027. if(config[index].depends_type_list)
  1028. {
  1029. i = 0;
  1030. while(i < config[index].total_type)
  1031. {
  1032. slapi_ch_free((void**)&(config[index].depends_type_list)[i]);
  1033. i++;
  1034. }
  1035. slapi_ch_free((void**)&(config[index].depends_type_list));
  1036. }
  1037. /*
  1038. slapi_ch_free((void**)&(config[index].name));
  1039. slapi_ch_free((void**)&(config[index].type));
  1040. */
  1041. index++;
  1042. }
  1043. slapi_ch_free((void**)&config);
  1044. }
  1045. /* Finally enable registered plugin functions */
  1046. global_plugin_callbacks_enabled = 1;
  1047. return ret;
  1048. }
  1049. /*
  1050. * plugin_dependency_closeall
  1051. *
  1052. * uses the shutdown list created at startup to close
  1053. * plugins in the correct order
  1054. *
  1055. * For now this leaks the list and contents, but since
  1056. * it hangs around until shutdown anyway, we don't care
  1057. *
  1058. */
  1059. void
  1060. plugin_dependency_closeall()
  1061. {
  1062. Slapi_PBlock pb;
  1063. int plugins_closed = 0;
  1064. int index = 0;
  1065. while(plugins_closed<global_plugins_started)
  1066. {
  1067. /*
  1068. * the first few entries may not be valid
  1069. * since the list was created in the reverse
  1070. * order and some plugins may have been counted
  1071. * for the purpose of list allocation but are
  1072. * disabled and so were never started
  1073. *
  1074. * we check that here
  1075. */
  1076. if(global_plugin_shutdown_order[index].name)
  1077. {
  1078. pblock_init(&pb);
  1079. plugin_call_one( global_plugin_shutdown_order[index].plugin, SLAPI_PLUGIN_CLOSE_FN, &pb );
  1080. plugins_closed++;
  1081. }
  1082. index++;
  1083. }
  1084. }
  1085. /***********************************************************
  1086. end of plugin dependency code
  1087. ************************************************************/
  1088. /*
  1089. * Function: plugin_startall
  1090. *
  1091. * Returns: squat
  1092. *
  1093. * Description: Some plugins may need to do some stuff after all the config
  1094. * stuff is done with. So this function goes through and starts all plugins
  1095. */
  1096. void
  1097. plugin_startall(int argc, char** argv, int start_backends, int start_global)
  1098. {
  1099. /* initialize special plugin structures */
  1100. default_plugin_init ();
  1101. plugin_dependency_startall(argc, argv, "plugin startup failed\n", SLAPI_PLUGIN_START_FN);
  1102. }
  1103. /*
  1104. * Function: plugin_close_all
  1105. *
  1106. * Returns: squat
  1107. *
  1108. * Description: cleanup routine, allows plugins to kill threads, free memory started in start fn
  1109. *
  1110. */
  1111. void
  1112. plugin_closeall(int close_backends, int close_globals)
  1113. {
  1114. plugin_dependency_closeall();
  1115. }
  1116. static int
  1117. plugin_call_list (struct slapdplugin *list, int operation, Slapi_PBlock *pb)
  1118. {
  1119. return plugin_call_func(list, operation, pb, 0);
  1120. }
  1121. static int
  1122. plugin_call_one (struct slapdplugin *list, int operation, Slapi_PBlock *pb)
  1123. {
  1124. return plugin_call_func(list, operation, pb, 1);
  1125. }
  1126. /*
  1127. * Return codes:
  1128. * - For preoperation plugins, returns the return code passed back from the first
  1129. * plugin that fails, or zero if all plugins succeed.
  1130. * - For bepreop and bepostop plugins, returns a bitwise OR of the return codes
  1131. * returned by all the plugins called (there's only one bepreop and one bepostop
  1132. * in DS 5.0 anyway).
  1133. * - For postoperation plugins, returns 0.
  1134. */
  1135. static int
  1136. plugin_call_func (struct slapdplugin *list, int operation, Slapi_PBlock *pb, int call_one)
  1137. {
  1138. /* Invoke the operation on the plugins that are registered for the subtree effected by the operation. */
  1139. int rc;
  1140. int return_value = 0;
  1141. int count= 0;
  1142. for (; list != NULL; list = list->plg_next)
  1143. {
  1144. IFP func = NULL;
  1145. slapi_pblock_set (pb, SLAPI_PLUGIN, list);
  1146. set_db_default_result_handlers (pb); /* JCM: What's this do? Is it needed here? */
  1147. if (slapi_pblock_get (pb, operation, &func) == 0 && func != NULL &&
  1148. plugin_invoke_plugin_pb (list, operation, pb))
  1149. {
  1150. char *n= list->plg_name;
  1151. LDAPDebug( LDAP_DEBUG_TRACE, "Calling plugin '%s' #%d type %d\n", (n==NULL?"noname":n), count, operation );
  1152. /* counters_to_errors_log("before plugin call"); */
  1153. if (( rc = func (pb)) != 0 )
  1154. {
  1155. if (SLAPI_PLUGIN_PREOPERATION == list->plg_type ||
  1156. SLAPI_PLUGIN_INTERNAL_PREOPERATION == list->plg_type ||
  1157. SLAPI_PLUGIN_START_FN == operation )
  1158. {
  1159. /*
  1160. * We bail out of plugin processing for preop plugins
  1161. * that return a non-zero return code. This allows preop
  1162. * plugins to cause further preop processing to terminate, and
  1163. * causes the operation to be vetoed.
  1164. */
  1165. return_value = rc;
  1166. break;
  1167. } else if (SLAPI_PLUGIN_BEPREOPERATION == list->plg_type ||
  1168. SLAPI_PLUGIN_BEPOSTOPERATION == list->plg_type)
  1169. {
  1170. /* OR the result into the return value for be pre/postops */
  1171. return_value |= rc;
  1172. }
  1173. }
  1174. /* counters_to_errors_log("after plugin call"); */
  1175. }
  1176. count++;
  1177. if(call_one)
  1178. break;
  1179. }
  1180. return( return_value );
  1181. }
  1182. int
  1183. slapi_berval_cmp (const struct berval* L, const struct berval* R) /* JCM - This does not belong here. But, where should it go? */
  1184. {
  1185. int result = 0;
  1186. if (L->bv_len < R->bv_len) {
  1187. result = memcmp (L->bv_val, R->bv_val, L->bv_len);
  1188. if (result == 0)
  1189. result = -1;
  1190. } else {
  1191. result = memcmp (L->bv_val, R->bv_val, R->bv_len);
  1192. if (result == 0 && (L->bv_len > R->bv_len))
  1193. result = 1;
  1194. }
  1195. return result;
  1196. }
  1197. static char **supported_saslmechanisms = NULL;
  1198. static PRRWLock *supported_saslmechanisms_lock = NULL;
  1199. /*
  1200. * register a supported SASL mechanism so it will be returned as part of the
  1201. * root DSE.
  1202. */
  1203. void
  1204. slapi_register_supported_saslmechanism( char *mechanism )
  1205. {
  1206. if ( mechanism != NULL ) {
  1207. if (NULL == supported_saslmechanisms_lock) {
  1208. /* This is thread safe, as it gets executed by
  1209. * a single thread at init time (main->init_saslmechanisms) */
  1210. supported_saslmechanisms_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,
  1211. "supported saslmechanisms rwlock");
  1212. if (NULL == supported_saslmechanisms_lock) {
  1213. /* Out of resources */
  1214. slapi_log_error(SLAPI_LOG_FATAL, "startup",
  1215. "slapi_register_supported_saslmechanism: failed to create lock.\n");
  1216. exit (1);
  1217. }
  1218. }
  1219. PR_RWLock_Wlock(supported_saslmechanisms_lock);
  1220. charray_add( &supported_saslmechanisms, slapi_ch_strdup( mechanism ));
  1221. PR_RWLock_Unlock(supported_saslmechanisms_lock);
  1222. }
  1223. }
  1224. /*
  1225. * return pointer to NULL-terminated array of supported SASL mechanisms.
  1226. * This function is not MTSafe and should be deprecated.
  1227. * slapi_get_supported_saslmechanisms_copy should be used instead.
  1228. */
  1229. char **
  1230. slapi_get_supported_saslmechanisms( void )
  1231. {
  1232. return( supported_saslmechanisms );
  1233. }
  1234. /*
  1235. * return pointer to NULL-terminated array of supported SASL mechanisms.
  1236. */
  1237. char **
  1238. slapi_get_supported_saslmechanisms_copy( void )
  1239. {
  1240. char ** ret = NULL;
  1241. PR_RWLock_Rlock(supported_saslmechanisms_lock);
  1242. ret = charray_dup(supported_saslmechanisms);
  1243. PR_RWLock_Unlock(supported_saslmechanisms_lock);
  1244. return( ret );
  1245. }
  1246. static char **supported_extended_ops = NULL;
  1247. static PRRWLock *extended_ops_lock = NULL;
  1248. /*
  1249. * register all of the LDAPv3 extended operations we know about.
  1250. */
  1251. void
  1252. ldapi_init_extended_ops( void )
  1253. {
  1254. extended_ops_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,
  1255. "supported extended ops rwlock");
  1256. if (NULL == extended_ops_lock) {
  1257. /* Out of resources */
  1258. slapi_log_error(SLAPI_LOG_FATAL, "startup",
  1259. "ldapi_init_extended_ops: failed to create lock.\n");
  1260. exit (1);
  1261. }
  1262. PR_RWLock_Wlock(extended_ops_lock);
  1263. charray_add(&supported_extended_ops,
  1264. slapi_ch_strdup(EXTOP_BULK_IMPORT_START_OID));
  1265. charray_add(&supported_extended_ops,
  1266. slapi_ch_strdup(EXTOP_BULK_IMPORT_DONE_OID));
  1267. /* add future supported extops here... */
  1268. PR_RWLock_Unlock(extended_ops_lock);
  1269. }
  1270. /*
  1271. * register an extended op. so it can be returned as part of the root DSE.
  1272. */
  1273. void
  1274. ldapi_register_extended_op( char **opoids )
  1275. {
  1276. int i;
  1277. PR_RWLock_Wlock(extended_ops_lock);
  1278. for ( i = 0; opoids != NULL && opoids[i] != NULL; ++i ) {
  1279. if ( !charray_inlist( supported_extended_ops, opoids[i] )) {
  1280. charray_add( &supported_extended_ops, slapi_ch_strdup( opoids[i] ));
  1281. }
  1282. }
  1283. PR_RWLock_Unlock(extended_ops_lock);
  1284. }
  1285. /*
  1286. * retrieve supported extended operation OIDs
  1287. * return 0 if successful and -1 if not.
  1288. * This function is not MTSafe and should be deprecated.
  1289. * slapi_get_supported_extended_ops_copy should be used instead.
  1290. */
  1291. char **
  1292. slapi_get_supported_extended_ops( void )
  1293. {
  1294. return( supported_extended_ops );
  1295. }
  1296. /*
  1297. * retrieve supported extended operation OIDs
  1298. * return 0 if successful and -1 if not.
  1299. */
  1300. char **
  1301. slapi_get_supported_extended_ops_copy( void )
  1302. {
  1303. char ** ret = NULL;
  1304. PR_RWLock_Rlock(extended_ops_lock);
  1305. ret = charray_dup(supported_extended_ops);
  1306. PR_RWLock_Unlock(extended_ops_lock);
  1307. return( ret );
  1308. }
  1309. /* isApprovedPlugin:
  1310. * returns 1 if the plugin is approved to be loaded, 0 otherwise.
  1311. *
  1312. * If the server is running as the Full version, all plugins are approved,
  1313. * otherwise, if the server is running as DirectoryLite, only plugins from
  1314. * Red Hat are approved.
  1315. *
  1316. * We have a special case for the NT Synch plugin, which is disabled for DLite.
  1317. */
  1318. static int
  1319. isApprovedPlugin( struct slapdplugin *plugin )
  1320. {
  1321. if ( config_is_slapd_lite() == 0 ) {
  1322. /* All the plugins are approved for Directory Full */
  1323. return 1;
  1324. }
  1325. if ( plugin == NULL ) {
  1326. LDAPDebug( LDAP_DEBUG_ANY, "isApprovedPlugin: plugin is NULL\n", 0,0,0 );
  1327. return 0;
  1328. }
  1329. if (plugin->plg_desc.spd_vendor == NULL ) {
  1330. LDAPDebug( LDAP_DEBUG_ANY, "isApprovedPlugin: plugin vendor is NULL\n",0,0,0 );
  1331. return 0;
  1332. }
  1333. LDAPDebug ( LDAP_DEBUG_TRACE, "isApprovedPlugin() looking at plugin \"%s\" from vendor %s\n",
  1334. plugin->plg_name, plugin->plg_desc.spd_vendor, 0 );
  1335. /*
  1336. * approved plugins must have their vendor string set to PLUGIN_MAGIC VENDOR_STR. External
  1337. * plugins are not allowed for Lite.
  1338. */
  1339. if ( strcmp( plugin->plg_desc.spd_vendor, PLUGIN_MAGIC_VENDOR_STR ) == 0)
  1340. return 1;
  1341. LDAPDebug ( LDAP_DEBUG_ANY, "isApprovedPlugin() plugin \"%s\" is not approved for Directory Lite\n",
  1342. plugin->plg_name, 0,0 );
  1343. return 0;
  1344. }
  1345. /*
  1346. looks up the given string type to convert to the internal integral type; also
  1347. returns the plugin list associated with the plugin type
  1348. returns 0 upon success and non-zero upon failure
  1349. */
  1350. static int
  1351. plugin_get_type_and_list(
  1352. const char *plugintype,
  1353. int *type,
  1354. struct slapdplugin ***plugin_list
  1355. )
  1356. {
  1357. int plugin_list_index = -1;
  1358. if ( strcasecmp( plugintype, "database" ) == 0 ) {
  1359. *type = SLAPI_PLUGIN_DATABASE;
  1360. plugin_list_index= PLUGIN_LIST_DATABASE;
  1361. } else if ( strcasecmp( plugintype, "extendedop" ) == 0 ) {
  1362. *type = SLAPI_PLUGIN_EXTENDEDOP;
  1363. plugin_list_index= PLUGIN_LIST_EXTENDED_OPERATION;
  1364. } else if ( strcasecmp( plugintype, "preoperation" ) == 0 ) {
  1365. *type = SLAPI_PLUGIN_PREOPERATION;
  1366. plugin_list_index= PLUGIN_LIST_PREOPERATION;
  1367. } else if ( strcasecmp( plugintype, "postoperation" ) == 0 ) {
  1368. *type = SLAPI_PLUGIN_POSTOPERATION;
  1369. plugin_list_index= PLUGIN_LIST_POSTOPERATION;
  1370. } else if ( strcasecmp( plugintype, "matchingrule" ) == 0 ) {
  1371. *type = SLAPI_PLUGIN_MATCHINGRULE;
  1372. plugin_list_index= PLUGIN_LIST_MATCHINGRULE;
  1373. } else if ( strcasecmp( plugintype, "syntax" ) == 0 ) {
  1374. *type = SLAPI_PLUGIN_SYNTAX;
  1375. plugin_list_index= PLUGIN_LIST_SYNTAX;
  1376. } else if ( strcasecmp( plugintype, "accesscontrol" ) == 0 ) {
  1377. *type = SLAPI_PLUGIN_ACL;
  1378. plugin_list_index= PLUGIN_LIST_ACL;
  1379. } else if ( strcasecmp( plugintype, "bepreoperation" ) == 0 ) {
  1380. *type = SLAPI_PLUGIN_BEPREOPERATION;
  1381. plugin_list_index= PLUGIN_LIST_BEPREOPERATION;
  1382. } else if ( strcasecmp( plugintype, "bepostoperation" ) == 0 ) {
  1383. *type = SLAPI_PLUGIN_BEPOSTOPERATION;
  1384. plugin_list_index= PLUGIN_LIST_BEPOSTOPERATION;
  1385. } else if ( strcasecmp( plugintype, "internalpreoperation" ) == 0 ) {
  1386. *type = SLAPI_PLUGIN_INTERNAL_PREOPERATION;
  1387. plugin_list_index= PLUGIN_LIST_INTERNAL_PREOPERATION;
  1388. } else if ( strcasecmp( plugintype, "internalpostoperation" ) == 0 ) {
  1389. *type = SLAPI_PLUGIN_INTERNAL_POSTOPERATION;
  1390. plugin_list_index= PLUGIN_LIST_INTERNAL_POSTOPERATION;
  1391. } else if ( strcasecmp( plugintype, "entry" ) == 0 ) {
  1392. *type = SLAPI_PLUGIN_ENTRY;
  1393. plugin_list_index= PLUGIN_LIST_ENTRY;
  1394. } else if ( strcasecmp( plugintype, "object" ) == 0 ) {
  1395. *type = SLAPI_PLUGIN_TYPE_OBJECT;
  1396. plugin_list_index= PLUGIN_LIST_OBJECT;
  1397. } else if ( strcasecmp( plugintype, "pwdstoragescheme" ) == 0 ) {
  1398. *type = SLAPI_PLUGIN_PWD_STORAGE_SCHEME;
  1399. plugin_list_index= PLUGIN_LIST_PWD_STORAGE_SCHEME;
  1400. } else if ( strcasecmp( plugintype, "reverpwdstoragescheme" ) == 0 ) {
  1401. *type = SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME;
  1402. plugin_list_index= PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME;
  1403. } else if ( strcasecmp( plugintype, "vattrsp" ) == 0 ) {
  1404. *type = SLAPI_PLUGIN_VATTR_SP;
  1405. plugin_list_index= PLUGIN_LIST_VATTR_SP;
  1406. } else if ( strcasecmp( plugintype, "ldbmentryfetchstore" ) == 0 ) {
  1407. *type = SLAPI_PLUGIN_LDBM_ENTRY_FETCH_STORE;
  1408. plugin_list_index= PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE;
  1409. } else if ( strcasecmp( plugintype, "index" ) == 0 ) {
  1410. *type = SLAPI_PLUGIN_INDEX;
  1411. plugin_list_index= PLUGIN_LIST_INDEX;
  1412. } else {
  1413. return( 1 ); /* unknown plugin type - pass to backend */
  1414. }
  1415. if (plugin_list_index >= 0)
  1416. *plugin_list = &global_plugin_list[plugin_list_index];
  1417. return 0;
  1418. }
  1419. static const char *
  1420. plugin_exists(const Slapi_DN *plugin_dn)
  1421. {
  1422. /* check to see if the plugin name is unique */
  1423. const char *retval = 0;
  1424. if (global_plugin_dns && PL_HashTableLookup(global_plugin_dns,
  1425. slapi_sdn_get_ndn(plugin_dn)))
  1426. {
  1427. retval = slapi_sdn_get_dn(plugin_dn);
  1428. }
  1429. return retval;
  1430. }
  1431. static int
  1432. plugin_set_subtree_config(PluginTargetData *subtree_config, const char *val)
  1433. {
  1434. int status = 0;
  1435. if (strcasecmp (val, ALL_DATA) == 0) /* allow access to both local and remote data */
  1436. {
  1437. plugin_set_global (subtree_config);
  1438. }
  1439. else if (strcasecmp (val, LOCAL_DATA) == 0) /* allow access to all locally hosted data */
  1440. {
  1441. ptd_set_special_data (subtree_config, PLGC_DATA_LOCAL);
  1442. }
  1443. else if (strcasecmp (val, REMOTE_DATA) == 0)/* allow access to requests for remote data */
  1444. {
  1445. ptd_set_special_data (subtree_config, PLGC_DATA_REMOTE);
  1446. }
  1447. else /* dn */
  1448. {
  1449. ptd_add_subtree (subtree_config, slapi_sdn_new_dn_byval(val));
  1450. }
  1451. /* I suppose we could check the val at this point to make sure
  1452. its a valid DN . . . */
  1453. return status;
  1454. }
  1455. static int
  1456. set_plugin_config_from_entry(
  1457. const Slapi_Entry *plugin_entry,
  1458. struct slapdplugin *plugin
  1459. )
  1460. {
  1461. struct pluginconfig *config = &plugin->plg_conf;
  1462. char *value = 0;
  1463. int status = 0;
  1464. PRBool target_seen = PR_FALSE;
  1465. PRBool bind_seen = PR_FALSE;
  1466. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1467. ATTR_PLUGIN_SCHEMA_CHECK)) != NULL)
  1468. {
  1469. if (plugin_config_set_action(&config->plgc_schema_check, value))
  1470. {
  1471. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1472. "from entry %s\n", value, ATTR_PLUGIN_SCHEMA_CHECK,
  1473. slapi_entry_get_dn_const(plugin_entry));
  1474. status = 1;
  1475. }
  1476. slapi_ch_free((void**)&value);
  1477. }
  1478. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1479. ATTR_PLUGIN_LOG_ACCESS)) != NULL)
  1480. {
  1481. if (plugin_config_set_action(&config->plgc_log_access, value))
  1482. {
  1483. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1484. "from entry %s\n", value, ATTR_PLUGIN_LOG_ACCESS,
  1485. slapi_entry_get_dn_const(plugin_entry));
  1486. status = 1;
  1487. }
  1488. slapi_ch_free((void**)&value);
  1489. }
  1490. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1491. ATTR_PLUGIN_LOG_AUDIT)) != NULL)
  1492. {
  1493. if (plugin_config_set_action(&config->plgc_log_audit, value))
  1494. {
  1495. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1496. "from entry %s\n", value, ATTR_PLUGIN_LOG_AUDIT,
  1497. slapi_entry_get_dn_const(plugin_entry));
  1498. status = 1;
  1499. }
  1500. slapi_ch_free((void**)&value);
  1501. }
  1502. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1503. ATTR_PLUGIN_INVOKE_FOR_REPLOP)) != NULL)
  1504. {
  1505. if (plugin_config_set_action(&config->plgc_invoke_for_replop, value))
  1506. {
  1507. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1508. "from entry %s\n", value, ATTR_PLUGIN_INVOKE_FOR_REPLOP,
  1509. slapi_entry_get_dn_const(plugin_entry));
  1510. status = 1;
  1511. }
  1512. slapi_ch_free((void**)&value);
  1513. }
  1514. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1515. ATTR_PLUGIN_TARGET_SUBTREE)) != NULL)
  1516. {
  1517. if (plugin_set_subtree_config(&(config->plgc_target_subtrees), value))
  1518. {
  1519. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1520. "from entry %s\n", value, ATTR_PLUGIN_TARGET_SUBTREE,
  1521. slapi_entry_get_dn_const(plugin_entry));
  1522. status = 1;
  1523. }
  1524. else
  1525. {
  1526. target_seen = PR_TRUE;
  1527. }
  1528. slapi_ch_free((void**)&value);
  1529. }
  1530. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1531. ATTR_PLUGIN_BIND_SUBTREE)) != NULL)
  1532. {
  1533. if (plugin_set_subtree_config(&(config->plgc_bind_subtrees), value))
  1534. {
  1535. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: invalid value %s for attribute %s "
  1536. "from entry %s\n", value, ATTR_PLUGIN_BIND_SUBTREE,
  1537. slapi_entry_get_dn_const(plugin_entry));
  1538. status = 1;
  1539. }
  1540. else
  1541. {
  1542. bind_seen = PR_TRUE;
  1543. }
  1544. slapi_ch_free((void**)&value);
  1545. }
  1546. /* set target subtree default - allow access to all data */
  1547. if (!target_seen)
  1548. {
  1549. plugin_set_global(&(config->plgc_target_subtrees));
  1550. }
  1551. /* set bind subtree default - allow access to local data only */
  1552. if (!bind_seen)
  1553. {
  1554. ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_LOCAL);
  1555. ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_REMOTE);
  1556. }
  1557. return status;
  1558. }
  1559. /* This function is called after the plugin init function has been called
  1560. which fills in the desc part of the plugin
  1561. */
  1562. static int
  1563. add_plugin_description(Slapi_Entry *e, const char *attrname, char *val)
  1564. {
  1565. struct berval desc;
  1566. struct berval *newval[2] = {0, 0};
  1567. int status = 0;
  1568. desc.bv_val = SLAPI_PLUGIN_NONE_IF_NULL( val );
  1569. desc.bv_len = strlen(desc.bv_val);
  1570. newval[0] = &desc;
  1571. if ((status = entry_replace_values(e, attrname, newval)) != 0)
  1572. {
  1573. LDAPDebug(LDAP_DEBUG_PLUGIN, "Error: failed to add value %s to "
  1574. "attribute %s of entry %s\n", val, attrname,
  1575. slapi_entry_get_dn_const(e));
  1576. status = 1;
  1577. }
  1578. return status;
  1579. }
  1580. /*
  1581. * The plugin initfunc sets some vendor and version information in the plugin.
  1582. * This function extracts that and adds it as attributes to `e'. If
  1583. * `plugin' is NULL, the plugin is located based on the DN in `e'.
  1584. *
  1585. * Returns 0 if all goes well and 1 if not.
  1586. */
  1587. int
  1588. plugin_add_descriptive_attributes( Slapi_Entry *e, struct slapdplugin *plugin )
  1589. {
  1590. int status = 0;
  1591. if ( NULL == plugin ) {
  1592. int i;
  1593. const Slapi_DN *ednp = slapi_entry_get_sdn_const( e );
  1594. Slapi_DN pdn;
  1595. struct slapdplugin *plugtmp;
  1596. for( i = 0; NULL == plugin && i < PLUGIN_LIST_GLOBAL_MAX; ++i )
  1597. {
  1598. for ( plugtmp = global_plugin_list[i]; NULL == plugin && plugtmp;
  1599. plugtmp = plugtmp->plg_next)
  1600. {
  1601. slapi_sdn_init_dn_byref( &pdn, plugtmp->plg_dn );
  1602. if ( 0 == slapi_sdn_compare( &pdn, ednp ))
  1603. {
  1604. plugin = plugtmp;
  1605. }
  1606. slapi_sdn_done( &pdn );
  1607. }
  1608. }
  1609. if ( NULL == plugin )
  1610. {
  1611. LDAPDebug(LDAP_DEBUG_PLUGIN,
  1612. "Error: failed to add descriptive values for plugin %s"
  1613. " (could not find plugin entry)\n",
  1614. slapi_entry_get_dn_const(e), 0, 0 );
  1615. return 1; /* failure */
  1616. }
  1617. }
  1618. if (add_plugin_description(e, ATTR_PLUGIN_PLUGINID,
  1619. plugin->plg_desc.spd_id))
  1620. {
  1621. status = 1;
  1622. }
  1623. if (add_plugin_description(e, ATTR_PLUGIN_VERSION,
  1624. plugin->plg_desc.spd_version))
  1625. {
  1626. status = 1;
  1627. }
  1628. if (add_plugin_description(e, ATTR_PLUGIN_VENDOR,
  1629. plugin->plg_desc.spd_vendor))
  1630. {
  1631. status = 1;
  1632. }
  1633. if (add_plugin_description(e, ATTR_PLUGIN_DESC,
  1634. plugin->plg_desc.spd_description))
  1635. {
  1636. status = 1;
  1637. }
  1638. return status;
  1639. }
  1640. /*
  1641. clean up the memory associated with the plugin
  1642. */
  1643. static void
  1644. plugin_free(struct slapdplugin *plugin)
  1645. {
  1646. charray_free(plugin->plg_argv);
  1647. slapi_ch_free((void**)&plugin->plg_libpath);
  1648. slapi_ch_free((void**)&plugin->plg_initfunc);
  1649. slapi_ch_free((void**)&plugin->plg_name);
  1650. slapi_ch_free((void**)&plugin->plg_dn);
  1651. if (!plugin->plg_group)
  1652. plugin_config_cleanup(&plugin->plg_conf);
  1653. slapi_ch_free((void**)&plugin);
  1654. }
  1655. /***********************************
  1656. This is the main entry point for plugin configuration. The plugin_entry argument
  1657. should already contain the necessary fields required to initialize the plugin and
  1658. to give it a proper name in the plugin configuration DIT.
  1659. Argument:
  1660. Slapi_Entry *plugin_entry - the required attributes are
  1661. dn: the dn of the plugin entry
  1662. cn: the unique name of the plugin
  1663. nsslapd-pluginType: one of the several recognized plugin types e.g. "postoperation"
  1664. if p_initfunc is given, pluginPath and pluginInitFunc are optional
  1665. nsslapd-pluginPath: full path and file name of the dll implementing the plugin
  1666. nsslapd-pluginInitFunc: the name of the plugin initialization function
  1667. the optional attributes are:
  1668. nsslapd-pluginArg0
  1669. ...
  1670. nsslapd-pluginArg[N-1] - the (old style) arguments to the plugin, where N varies
  1671. from 0 to the number of arguments. The numbers must be consecutive i.e. no
  1672. skipping
  1673. Instead of using nsslapd-pluginArgN, it is encouraged for you to use named
  1674. parameters e.g.
  1675. nsslapd-tweakThis: 1
  1676. nsslapd-tweakThat: 2
  1677. etc.
  1678. nsslapd-pluginEnabled: "on"|"off" - by default, the plugin will be enabled unless
  1679. this attribute is present and has the value "off"
  1680. for other known attributes, see set_plugin_config_from_entry() above
  1681. all other attributes will be ignored
  1682. The reason this parameter is not const is because it may be modified. This
  1683. function will modify it if the plugin init function is called successfully
  1684. to add the description attributes, and the plugin init function may modify
  1685. it as well.
  1686. Argument:
  1687. group - the group to which this plugin will belong - each member of a plugin group
  1688. shares the pluginconfig of the group leader; refer to the function plugin_get_config
  1689. for more information
  1690. Argument:
  1691. add_entry - if true, the entry will be added to the DIT using the given
  1692. DN in the plugin_entry - this is the default behavior; if false, the
  1693. plugin entry will not show up in the DIT
  1694. ************************************/
  1695. int
  1696. plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid *group,
  1697. slapi_plugin_init_fnptr p_initfunc, int add_entry)
  1698. {
  1699. int ii = 0;
  1700. char attrname[BUFSIZ];
  1701. char *value = 0;
  1702. struct slapdplugin *plugin = NULL;
  1703. struct slapdplugin **plugin_list = NULL;
  1704. struct slapi_componentid *cid=NULL;
  1705. const char *existname = 0;
  1706. slapi_plugin_init_fnptr initfunc = p_initfunc;
  1707. Slapi_PBlock pb;
  1708. int status = 0;
  1709. int approved = 1;
  1710. int enabled = 1;
  1711. char *configdir = 0;
  1712. attrname[0] = '\0';
  1713. if (!slapi_entry_get_sdn_const(plugin_entry))
  1714. {
  1715. LDAPDebug(LDAP_DEBUG_ANY, "Error: DN is missing from the plugin.\n",
  1716. 0, 0, 0);
  1717. return -1;
  1718. }
  1719. if ((existname = plugin_exists(slapi_entry_get_sdn_const(plugin_entry))) != NULL)
  1720. {
  1721. LDAPDebug(LDAP_DEBUG_ANY, "Error: the plugin named %s "
  1722. "already exists.\n", existname, 0, 0);
  1723. return -1;
  1724. }
  1725. /*
  1726. * create a new plugin structure, fill it in, and prepare to
  1727. * call the plugin's init function. the init function will
  1728. * set the plugin function pointers.
  1729. */
  1730. plugin = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin));
  1731. plugin->plg_dn = slapi_ch_strdup(slapi_entry_get_dn_const(plugin_entry));
  1732. if (!(value = slapi_entry_attr_get_charptr(plugin_entry,
  1733. ATTR_PLUGIN_TYPE)))
  1734. {
  1735. /* error: required attribute %s missing */
  1736. LDAPDebug(LDAP_DEBUG_ANY, "Error: required attribute %s is missing "
  1737. "from entry \"%s\"\n", ATTR_PLUGIN_TYPE,
  1738. slapi_entry_get_dn_const(plugin_entry), 0);
  1739. status = -1;
  1740. goto PLUGIN_CLEANUP;
  1741. }
  1742. else
  1743. {
  1744. status = plugin_get_type_and_list(value, &plugin->plg_type,
  1745. &plugin_list);
  1746. if ( status != 0 ) {
  1747. /* error: unknown plugin type */
  1748. LDAPDebug(LDAP_DEBUG_ANY, "Error: unknown plugin type \"%s\" "
  1749. "in entry \"%s\"\n",
  1750. value, slapi_entry_get_dn_const(plugin_entry), 0);
  1751. slapi_ch_free((void**)&value);
  1752. status = -1;
  1753. goto PLUGIN_CLEANUP;
  1754. }
  1755. slapi_ch_free((void**)&value);
  1756. }
  1757. if (!status &&
  1758. !(value = slapi_entry_attr_get_charptr(plugin_entry, "cn")))
  1759. {
  1760. /* error: required attribute %s missing */
  1761. LDAPDebug(LDAP_DEBUG_ANY, "Error: required attribute %s is missing "
  1762. "from entry \"%s\"\n", "cn",
  1763. slapi_entry_get_dn_const(plugin_entry), 0);
  1764. status = -1;
  1765. goto PLUGIN_CLEANUP;
  1766. }
  1767. else
  1768. {
  1769. plugin->plg_name = value; /* plugin owns value's memory now, don't free */
  1770. }
  1771. if (!(value = slapi_entry_attr_get_charptr(plugin_entry,
  1772. ATTR_PLUGIN_INITFN)))
  1773. {
  1774. if (!initfunc)
  1775. {
  1776. /* error: required attribute %s missing */
  1777. LDAPDebug(LDAP_DEBUG_ANY, "Error: required attribute %s is missing "
  1778. "from entry \"%s\"\n", ATTR_PLUGIN_INITFN,
  1779. slapi_entry_get_dn_const(plugin_entry), 0);
  1780. status = -1;
  1781. goto PLUGIN_CLEANUP;
  1782. }
  1783. }
  1784. else
  1785. {
  1786. plugin->plg_initfunc = value; /* plugin owns value's memory now, don't free */
  1787. }
  1788. if (!initfunc)
  1789. {
  1790. PRBool loadNow = PR_FALSE;
  1791. PRBool loadGlobal = PR_FALSE;
  1792. if (!(value = slapi_entry_attr_get_charptr(plugin_entry,
  1793. ATTR_PLUGIN_PATH)))
  1794. {
  1795. /* error: required attribute %s missing */
  1796. LDAPDebug(LDAP_DEBUG_ANY, "Error: required attribute %s is missing "
  1797. "from entry \"%s\"\n", ATTR_PLUGIN_PATH,
  1798. slapi_entry_get_dn_const(plugin_entry), 0);
  1799. status = -1;
  1800. goto PLUGIN_CLEANUP;
  1801. }
  1802. else
  1803. {
  1804. plugin->plg_libpath = value; /* plugin owns value's memory now, don't free */
  1805. }
  1806. loadNow = slapi_entry_attr_get_bool(plugin_entry, ATTR_PLUGIN_LOAD_NOW);
  1807. loadGlobal = slapi_entry_attr_get_bool(plugin_entry, ATTR_PLUGIN_LOAD_GLOBAL);
  1808. /*
  1809. * load the plugin's init function
  1810. */
  1811. if ((initfunc = (slapi_plugin_init_fnptr)sym_load_with_flags(plugin->plg_libpath,
  1812. plugin->plg_initfunc, plugin->plg_name, 1 /* report errors */,
  1813. loadNow, loadGlobal)) == NULL)
  1814. {
  1815. status = -1;
  1816. goto PLUGIN_CLEANUP;
  1817. }
  1818. #ifdef _WIN32
  1819. {
  1820. set_debug_level_fn_t fn;
  1821. /* for Win32 only, attempt to get its debug level init function */
  1822. if ((fn = (set_debug_level_fn_t)sym_load(plugin->plg_libpath,
  1823. "plugin_init_debug_level", plugin->plg_name,
  1824. 0 /* do not report errors */ )) != NULL) {
  1825. /* we hooked the function, so call it */
  1826. (*fn)(module_ldap_debug);
  1827. }
  1828. }
  1829. #endif
  1830. }
  1831. if (!status && group) /* uses group's config; see plugin_get_config */
  1832. {
  1833. struct slapi_componentid * cid = (struct slapi_componentid *) group;
  1834. plugin->plg_group = (struct slapdplugin *) cid->sci_plugin;
  1835. }
  1836. else if (!status) /* using own config */
  1837. {
  1838. plugin_config_init(&(plugin->plg_conf));
  1839. set_plugin_config_from_entry(plugin_entry, plugin);
  1840. }
  1841. /* add the plugin arguments */
  1842. value = 0;
  1843. ii = 0;
  1844. PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ii);
  1845. while ((value = slapi_entry_attr_get_charptr(plugin_entry, attrname)) != NULL)
  1846. {
  1847. charray_add(&plugin->plg_argv, value);
  1848. plugin->plg_argc++;
  1849. ++ii;
  1850. PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ii);
  1851. }
  1852. memset((char *)&pb, '\0', sizeof(pb));
  1853. slapi_pblock_set(&pb, SLAPI_PLUGIN, plugin);
  1854. slapi_pblock_set(&pb, SLAPI_PLUGIN_VERSION, (void *)SLAPI_PLUGIN_CURRENT_VERSION);
  1855. cid = generate_componentid (plugin,NULL);
  1856. slapi_pblock_set(&pb, SLAPI_PLUGIN_IDENTITY, (void*)cid);
  1857. configdir = config_get_configdir();
  1858. slapi_pblock_set(&pb, SLAPI_CONFIG_DIRECTORY, configdir);
  1859. if ((*initfunc)(&pb) != 0)
  1860. {
  1861. LDAPDebug(LDAP_DEBUG_ANY, "Init function \"%s\" for \"%s\" plugin"
  1862. " in library \"%s\" failed\n",
  1863. plugin->plg_initfunc, plugin->plg_name,
  1864. plugin->plg_libpath);
  1865. status = -1;
  1866. goto PLUGIN_CLEANUP;
  1867. }
  1868. if ( !status ) {
  1869. status = plugin_add_descriptive_attributes( plugin_entry, plugin );
  1870. }
  1871. /* see if the plugin is approved or not */
  1872. if ((approved = isApprovedPlugin(plugin)) != 0)
  1873. {
  1874. if ((!plugin->plg_version) ||
  1875. (!SLAPI_PLUGIN_IS_COMPAT(plugin->plg_version))) {
  1876. LDAPDebug( LDAP_DEBUG_ANY, "Plugin \"%s\" from library \"%s\""
  1877. " has wrong version (supported versions: %s)\n",
  1878. plugin->plg_name, plugin->plg_libpath,
  1879. SLAPI_PLUGIN_SUPPORTED_VERSIONS);
  1880. approved = 0;
  1881. }
  1882. }
  1883. /* see if the plugin is enabled or not */
  1884. if ((value = slapi_entry_attr_get_charptr(plugin_entry,
  1885. ATTR_PLUGIN_ENABLED)) &&
  1886. !strcasecmp(value, "off"))
  1887. {
  1888. enabled = 0;
  1889. }
  1890. else
  1891. {
  1892. enabled = 1;
  1893. }
  1894. if (value)
  1895. slapi_ch_free((void**)&value);
  1896. if (!approved) {
  1897. enabled = 0;
  1898. LDAPDebug(LDAP_DEBUG_ANY, "Plugin \"%s\" is disabled.\n",
  1899. plugin->plg_name,0,0);
  1900. }
  1901. if (approved)
  1902. {
  1903. if(enabled)
  1904. {
  1905. /* don't use raw pointer from plugin_entry because it
  1906. will be freed later by the caller */
  1907. Slapi_DN *dn_copy = slapi_sdn_dup(slapi_entry_get_sdn_const(plugin_entry));
  1908. add_plugin_to_list(plugin_list, plugin);
  1909. add_plugin_entry_dn(dn_copy);
  1910. }
  1911. if (add_entry)
  1912. {
  1913. /* make a copy of the plugin entry for our own use because it will
  1914. be freed later by the caller */
  1915. Slapi_Entry *e_copy = slapi_entry_dup(plugin_entry);
  1916. /* new_plugin_entry(&plugin_entries, plugin_entry, plugin); */
  1917. new_plugin_entry(&dep_plugin_entries, e_copy, plugin);
  1918. }
  1919. }
  1920. PLUGIN_CLEANUP:
  1921. if (status)
  1922. plugin_free(plugin);
  1923. slapi_ch_free((void **)&configdir);
  1924. return status;
  1925. }
  1926. /* set default configuration parameters */
  1927. static void
  1928. plugin_config_init (struct pluginconfig *config)
  1929. {
  1930. PR_ASSERT (config);
  1931. ptd_init (&config->plgc_target_subtrees);
  1932. ptd_init (&config->plgc_bind_subtrees);
  1933. config->plgc_schema_check = PLGC_ON;
  1934. config->plgc_invoke_for_replop = PLGC_ON;
  1935. /* currently, we leave it up to plugin, but don't actually tell plugins that they can choose.
  1936. We want changes to always be logged by regular plugins to avoid data inconsistency, but we
  1937. want to allow internal plugins like replication to make the decision.*/
  1938. config->plgc_log_change = PLGC_UPTOPLUGIN;
  1939. config->plgc_log_access = PLGC_OFF;
  1940. config->plgc_log_audit = PLGC_OFF;
  1941. }
  1942. static int
  1943. plugin_config_set_action (int *action, char *value)
  1944. {
  1945. PR_ASSERT (action);
  1946. PR_ASSERT (value);
  1947. if (strcasecmp (value, "on") == 0)
  1948. {
  1949. *action = PLGC_ON;
  1950. }
  1951. else if (strcasecmp (value, "off") == 0)
  1952. {
  1953. *action = PLGC_OFF;
  1954. }
  1955. else if (strcasecmp (value, "uptoplugin") == 0)
  1956. {
  1957. *action = PLGC_UPTOPLUGIN;
  1958. }
  1959. else
  1960. {
  1961. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  1962. "plugin_config_set_action: invalid action %s\n", value);
  1963. return -1;
  1964. }
  1965. return 0;
  1966. }
  1967. static void
  1968. plugin_config_cleanup (struct pluginconfig *config)
  1969. {
  1970. PR_ASSERT (config);
  1971. ptd_cleanup (&config->plgc_target_subtrees);
  1972. ptd_cleanup (&config->plgc_bind_subtrees);
  1973. }
  1974. #if 0
  1975. static char*
  1976. plugin_config_action_to_string (int action)
  1977. {
  1978. switch (action)
  1979. {
  1980. case PLGC_ON: return "on";
  1981. case PLGC_OFF: return "off";
  1982. case PLGC_UPTOPLUGIN: return "uptoplugin";
  1983. default: return NULL;
  1984. }
  1985. }
  1986. #endif
  1987. static struct pluginconfig*
  1988. plugin_get_config (struct slapdplugin *plugin)
  1989. {
  1990. struct slapdplugin *temp = plugin;
  1991. PR_ASSERT (plugin);
  1992. while (temp->plg_group)
  1993. {
  1994. temp = temp->plg_group;
  1995. }
  1996. return &(temp->plg_conf);
  1997. }
  1998. static PRBool
  1999. plugin_invoke_plugin_pb (struct slapdplugin *plugin, int operation, Slapi_PBlock *pb)
  2000. {
  2001. Slapi_DN *target_spec;
  2002. PRBool rc;
  2003. PR_ASSERT (plugin);
  2004. PR_ASSERT (pb);
  2005. /* we always allow initialization and cleanup operations */
  2006. if (operation == SLAPI_PLUGIN_START_FN || operation == SLAPI_PLUGIN_POSTSTART_FN ||
  2007. operation == SLAPI_PLUGIN_CLOSE_FN || operation == SLAPI_PLUGIN_CLEANUP_FN)
  2008. return PR_TRUE;
  2009. PR_ASSERT (pb->pb_op);
  2010. target_spec = operation_get_target_spec (pb->pb_op);
  2011. PR_ASSERT (target_spec);
  2012. rc = plugin_invoke_plugin_sdn (plugin, operation, pb, target_spec);
  2013. return rc;
  2014. }
  2015. PRBool
  2016. plugin_invoke_plugin_sdn (struct slapdplugin *plugin, int operation, Slapi_PBlock *pb, Slapi_DN *target_spec)
  2017. {
  2018. PluginTargetData *ptd;
  2019. struct pluginconfig *config;
  2020. Slapi_Backend *be;
  2021. int isroot;
  2022. PRBool islocal;
  2023. PRBool bindop;
  2024. unsigned long op;
  2025. PRBool rc;
  2026. int method = -1;
  2027. PR_ASSERT (plugin);
  2028. /* get configuration from the group plugin if necessary */
  2029. config = plugin_get_config (plugin);
  2030. slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
  2031. /* check if plugin is configured to service replicated operations */
  2032. if (!config->plgc_invoke_for_replop)
  2033. {
  2034. int repl_op;
  2035. /* if pb is NULL we assume it is not a replicated operation */
  2036. if (pb)
  2037. {
  2038. slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
  2039. if (repl_op)
  2040. return PR_FALSE;
  2041. }
  2042. }
  2043. if (pb)
  2044. {
  2045. if (pb->pb_op)
  2046. {
  2047. op = operation_get_type(pb->pb_op);
  2048. if (op == SLAPI_OPERATION_BIND || op == SLAPI_OPERATION_UNBIND)
  2049. {
  2050. bindop = PR_TRUE;
  2051. }
  2052. else
  2053. {
  2054. bindop = PR_FALSE;
  2055. }
  2056. slapi_pblock_get (pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  2057. }
  2058. else
  2059. {
  2060. bindop = PR_FALSE;
  2061. isroot = 1;
  2062. }
  2063. slapi_pblock_get (pb, SLAPI_BACKEND, &be);
  2064. /* determine whether data are local or remote */
  2065. /* remote if chaining backend or default backend */
  2066. if ( be!=NULL ) {
  2067. islocal=!(slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA));
  2068. } else {
  2069. islocal = be != defbackend_get_backend();
  2070. }
  2071. }
  2072. else
  2073. {
  2074. bindop = PR_FALSE;
  2075. islocal = PR_TRUE;
  2076. isroot = 1;
  2077. }
  2078. if (bindop)
  2079. {
  2080. ptd = &(config->plgc_bind_subtrees);
  2081. }
  2082. else
  2083. {
  2084. ptd = &(config->plgc_target_subtrees);
  2085. }
  2086. rc = plugin_matches_operation (target_spec, ptd, bindop, isroot, islocal, method);
  2087. return rc;
  2088. }
  2089. /* this interface is exposed to be used by internal operations.
  2090. */
  2091. char* plugin_get_dn (const struct slapdplugin *plugin)
  2092. {
  2093. char *plugindn;
  2094. char *pattern = "cn=%s," PLUGIN_BASE_DN;
  2095. if (plugin == NULL) /* old plugin that does not pass identity - use default */
  2096. plugin = &global_default_plg;
  2097. if (plugin->plg_name == NULL)
  2098. return NULL;
  2099. plugindn = slapi_ch_smprintf(pattern, plugin->plg_name);
  2100. return plugindn;
  2101. }
  2102. static PRBool plugin_is_global (const PluginTargetData *ptd)
  2103. {
  2104. /* plugin is considered to be global if it is invoked for
  2105. global data, local data and anonymous bind (bind target
  2106. data only). We don't include directory manager here
  2107. as it is considered to be part of local data */
  2108. return (ptd_is_special_data_set (ptd, PLGC_DATA_LOCAL) &&
  2109. ptd_is_special_data_set (ptd, PLGC_DATA_REMOTE) &&
  2110. ptd_is_special_data_set (ptd, PLGC_DATA_BIND_ANONYMOUS) &&
  2111. ptd_is_special_data_set (ptd, PLGC_DATA_BIND_ROOT));
  2112. }
  2113. static void plugin_set_global (PluginTargetData *ptd)
  2114. {
  2115. PR_ASSERT (ptd);
  2116. /* plugin is global if it is allowed access to all data */
  2117. ptd_set_special_data (ptd, PLGC_DATA_LOCAL);
  2118. ptd_set_special_data (ptd, PLGC_DATA_REMOTE);
  2119. ptd_set_special_data (ptd, PLGC_DATA_BIND_ANONYMOUS);
  2120. ptd_set_special_data (ptd, PLGC_DATA_BIND_ROOT);
  2121. }
  2122. static void plugin_set_default_access (struct pluginconfig *config)
  2123. {
  2124. /* by default, plugins are invoked if dn is local for bind operations,
  2125. and for all requests for all other operations */
  2126. PR_ASSERT (config);
  2127. plugin_set_global (&config->plgc_target_subtrees);
  2128. ptd_set_special_data (&config->plgc_bind_subtrees, PLGC_DATA_LOCAL);
  2129. ptd_set_special_data (&config->plgc_bind_subtrees, PLGC_DATA_REMOTE);
  2130. }
  2131. /* determine whether operation should be allowed based on plugin configuration */
  2132. PRBool plugin_allow_internal_op (Slapi_DN *target_spec, struct slapdplugin *plugin)
  2133. {
  2134. struct pluginconfig *config = plugin_get_config (plugin);
  2135. Slapi_Backend *be;
  2136. int islocal;
  2137. if (plugin_is_global (&config->plgc_target_subtrees))
  2138. return PR_TRUE;
  2139. /* ONREPL - we do be_select to decide whether the request is for local
  2140. or remote data. We might need to reconsider how to do this
  2141. for performance reasons since be_select will be done again
  2142. once the operation goes through */
  2143. be = slapi_be_select(target_spec);
  2144. /* determine whether data are local or remote */
  2145. /* remote if chaining backend or default backend */
  2146. if ( be!=NULL ) {
  2147. islocal=!(slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA));
  2148. } else {
  2149. islocal = be != defbackend_get_backend();
  2150. }
  2151. /* SIMPLE auth method sends us through original code path in plugin_mathches_operation */
  2152. return plugin_matches_operation (target_spec, &config->plgc_target_subtrees,
  2153. PR_FALSE, PR_FALSE, islocal, LDAP_AUTH_SIMPLE);
  2154. }
  2155. static PRBool plugin_matches_operation (Slapi_DN *target_spec, PluginTargetData *ptd,
  2156. PRBool bindop, PRBool isroot, PRBool islocal, int method)
  2157. {
  2158. int cookie;
  2159. Slapi_DN *subtree;
  2160. /* check for special cases */
  2161. if (plugin_is_global (ptd))
  2162. return PR_TRUE;
  2163. /* if method is SASL we can have a null DN so bypass this check*/
  2164. if(method != LDAP_AUTH_SASL) {
  2165. if (bindop && target_spec && (slapi_sdn_get_dn (target_spec) == NULL ||
  2166. slapi_sdn_get_dn (target_spec)[0] == '\0'))
  2167. {
  2168. return (ptd_is_special_data_set (ptd, PLGC_DATA_BIND_ANONYMOUS));
  2169. }
  2170. }
  2171. /* check for root bind */
  2172. if (bindop && isroot)
  2173. {
  2174. return (ptd_is_special_data_set (ptd, PLGC_DATA_BIND_ROOT));
  2175. }
  2176. /* check for local data */
  2177. if (ptd_is_special_data_set (ptd, PLGC_DATA_LOCAL) && islocal)
  2178. {
  2179. return PR_TRUE;
  2180. }
  2181. /* check for remote data */
  2182. if (ptd_is_special_data_set (ptd, PLGC_DATA_REMOTE) && !islocal)
  2183. {
  2184. return (PR_TRUE);
  2185. }
  2186. subtree = ptd_get_first_subtree (ptd, &cookie);
  2187. while (subtree)
  2188. {
  2189. if (slapi_sdn_issuffix (target_spec, subtree))
  2190. return (PR_TRUE);
  2191. subtree = ptd_get_next_subtree (ptd, &cookie);
  2192. }
  2193. return PR_FALSE;
  2194. }
  2195. /* build operation action bitmap based on plugin configuration and actions specified for the operation */
  2196. int plugin_build_operation_action_bitmap (int input_actions, const struct slapdplugin *plugin)
  2197. {
  2198. int result_actions = 0;
  2199. /* old plugin that does not pass its identity to the operation */
  2200. if (plugin == NULL)
  2201. plugin = &global_default_plg;
  2202. if (plugin->plg_conf.plgc_log_access)
  2203. result_actions |= OP_FLAG_ACTION_LOG_ACCESS;
  2204. if (plugin->plg_conf.plgc_log_audit)
  2205. result_actions |= OP_FLAG_ACTION_LOG_AUDIT;
  2206. /*
  2207. * OP_FLAG_ACTION_INVOKE_FOR_REPLOP is now used only by URP code.
  2208. * If someday this code needs to reclaim the flag, it has to use
  2209. * another flag to avoid the conflict with URP code.
  2210. *
  2211. * if (plugin->plg_conf.plgc_invoke_for_replop)
  2212. * result_actions |= OP_FLAG_ACTION_INVOKE_FOR_REPLOP;
  2213. */
  2214. switch (plugin->plg_conf.plgc_schema_check)
  2215. {
  2216. case PLGC_OFF: result_actions &= ~OP_FLAG_ACTION_SCHEMA_CHECK;
  2217. break;
  2218. case PLGC_ON: result_actions |= OP_FLAG_ACTION_SCHEMA_CHECK;
  2219. break;
  2220. case PLGC_UPTOPLUGIN: break;
  2221. default: PR_ASSERT (PR_FALSE);
  2222. }
  2223. switch (plugin->plg_conf.plgc_log_change)
  2224. {
  2225. case PLGC_OFF: result_actions &= ~OP_FLAG_ACTION_LOG_CHANGES;
  2226. break;
  2227. case PLGC_ON: result_actions |= OP_FLAG_ACTION_LOG_CHANGES;
  2228. break;
  2229. case PLGC_UPTOPLUGIN: break;
  2230. default: PR_ASSERT (PR_FALSE);
  2231. }
  2232. return result_actions;
  2233. }
  2234. const struct slapdplugin*
  2235. plugin_get_server_plg()
  2236. {
  2237. if(!global_server_plg_initialised)
  2238. {
  2239. global_server_plg.plg_name = "server";
  2240. plugin_set_global (&global_server_plg.plg_conf.plgc_target_subtrees);
  2241. global_server_plg.plg_conf.plgc_log_access = 1;
  2242. global_server_plg.plg_conf.plgc_log_audit = 1;
  2243. global_server_plg.plg_conf.plgc_schema_check = 1;
  2244. global_server_plg.plg_conf.plgc_log_change = 1;
  2245. global_server_plg_initialised= 1;
  2246. global_server_plg_initialised= 1;
  2247. }
  2248. return &global_server_plg;
  2249. }
  2250. struct slapi_componentid * plugin_get_default_component_id() {
  2251. if(!global_server_plg_id_initialised) {
  2252. global_server_id_plg.sci_plugin=plugin_get_server_plg();
  2253. global_server_id_plg.sci_component_name=
  2254. plugin_get_dn(global_server_id_plg.sci_plugin);
  2255. global_server_plg_id_initialised=1;
  2256. }
  2257. return &global_server_id_plg;
  2258. }
  2259. static void
  2260. default_plugin_init()
  2261. {
  2262. global_default_plg.plg_name = "old plugin";
  2263. plugin_config_init (&global_default_plg.plg_conf);
  2264. plugin_set_default_access (&global_default_plg.plg_conf);
  2265. }
  2266. #if 0
  2267. static void trace_plugin_invocation (Slapi_DN *target_spec, PluginTargetData *ptd,
  2268. PRBool bindop, PRBool isroot, PRBool islocal, int invoked)
  2269. {
  2270. int cookie, i = 0;
  2271. Slapi_DN *sdn;
  2272. slapi_log_error (SLAPI_LOG_FATAL, NULL,
  2273. "Invocation parameters: target_spec = %s, bindop = %d, isroot=%d, islocal=%d\n"
  2274. "Plugin configuration: local_data=%d, remote_data=%d, anonymous_bind=%d, root_bind=%d\n",
  2275. slapi_sdn_get_ndn (target_spec), bindop, isroot, islocal, ptd->special_data[0],
  2276. ptd->special_data[1], ptd->special_data[2], ptd->special_data[3]);
  2277. sdn = ptd_get_first_subtree (ptd, &cookie);
  2278. while (sdn)
  2279. {
  2280. slapi_log_error (SLAPI_LOG_FATAL, NULL, "target_subtree%d: %s\n", i, slapi_sdn_get_ndn (sdn));
  2281. sdn = ptd_get_next_subtree (ptd, &cookie);
  2282. }
  2283. slapi_log_error (SLAPI_LOG_FATAL, NULL, invoked ? "Plugin is invoked\n" : "Plugin is not invoked\n");
  2284. }
  2285. #endif
  2286. /* functions to manipulate PluginTargetData type */
  2287. static void ptd_init (PluginTargetData *ptd)
  2288. {
  2289. PR_ASSERT (ptd);
  2290. dl_init (&ptd->subtrees, 0 /* initial count */);
  2291. memset (&ptd->special_data, 0, sizeof (ptd->special_data));
  2292. }
  2293. static void ptd_cleanup (PluginTargetData *ptd)
  2294. {
  2295. PR_ASSERT (ptd);
  2296. dl_cleanup (&ptd->subtrees, (FREEFN)slapi_sdn_free);
  2297. memset (&ptd->special_data, 0, sizeof (ptd->special_data));
  2298. }
  2299. static void ptd_add_subtree (PluginTargetData *ptd, Slapi_DN *subtree)
  2300. {
  2301. PR_ASSERT (ptd);
  2302. PR_ASSERT (subtree);
  2303. dl_add (&ptd->subtrees, subtree);
  2304. }
  2305. static void ptd_set_special_data (PluginTargetData *ptd, int type)
  2306. {
  2307. PR_ASSERT (ptd);
  2308. PR_ASSERT (type >= 0 && type < PLGC_DATA_MAX);
  2309. ptd->special_data [type] = PR_TRUE;
  2310. }
  2311. #if 0
  2312. static void ptd_clear_special_data (PluginTargetData *ptd, int type)
  2313. {
  2314. PR_ASSERT (ptd);
  2315. PR_ASSERT (type >= 0 && type < PLGC_DATA_MAX);
  2316. ptd->special_data [type] = PR_FALSE;
  2317. }
  2318. #endif
  2319. static Slapi_DN *ptd_get_first_subtree (const PluginTargetData *ptd, int *cookie)
  2320. {
  2321. PR_ASSERT (ptd);
  2322. return dl_get_first (&ptd->subtrees, cookie);
  2323. }
  2324. static Slapi_DN *ptd_get_next_subtree (const PluginTargetData *ptd, int *cookie)
  2325. {
  2326. PR_ASSERT (ptd);
  2327. return dl_get_next (&ptd->subtrees, cookie);
  2328. }
  2329. static PRBool ptd_is_special_data_set (const PluginTargetData *ptd, int type)
  2330. {
  2331. PR_ASSERT (ptd);
  2332. PR_ASSERT (type >= 0 && type < PLGC_DATA_MAX);
  2333. return ptd->special_data [type];
  2334. }
  2335. #if 0
  2336. static Slapi_DN* ptd_delete_subtree (PluginTargetData *ptd, Slapi_DN *subtree)
  2337. {
  2338. PR_ASSERT (ptd);
  2339. PR_ASSERT (subtree);
  2340. return (Slapi_DN*)dl_delete (&ptd->subtrees, subtree, (CMPFN)slapi_sdn_compare, NULL);
  2341. }
  2342. #endif
  2343. int ptd_get_subtree_count (const PluginTargetData *ptd)
  2344. {
  2345. PR_ASSERT (ptd);
  2346. return dl_get_count (&ptd->subtrees);
  2347. }
  2348. /* needed by command-line tasks to find an instance's plugin */
  2349. struct slapdplugin *plugin_get_by_name(char *name)
  2350. {
  2351. int x;
  2352. struct slapdplugin *plugin;
  2353. for(x = 0; x < PLUGIN_LIST_GLOBAL_MAX; x++) {
  2354. for(plugin = global_plugin_list[x]; plugin; plugin = plugin->plg_next) {
  2355. if (!strcmp(name, plugin->plg_name)) {
  2356. return plugin;
  2357. }
  2358. }
  2359. }
  2360. return NULL;
  2361. }
  2362. struct slapi_componentid *
  2363. generate_componentid ( struct slapdplugin * pp , char * name )
  2364. {
  2365. struct slapi_componentid * idp;
  2366. idp = (struct slapi_componentid *) slapi_ch_calloc(1, sizeof( *idp ));
  2367. if ( pp )
  2368. idp->sci_plugin=pp;
  2369. else
  2370. idp->sci_plugin=(struct slapdplugin *) plugin_get_server_plg();
  2371. if ( name )
  2372. idp->sci_component_name = slapi_ch_strdup(name);
  2373. else
  2374. /* Use plugin dn */
  2375. idp->sci_component_name = plugin_get_dn( idp->sci_plugin );
  2376. if (idp->sci_component_name)
  2377. slapi_dn_normalize(idp->sci_component_name);
  2378. return idp;
  2379. }
  2380. void release_componentid ( struct slapi_componentid * id )
  2381. {
  2382. if ( id ) {
  2383. if ( id->sci_component_name ) {
  2384. slapi_ch_free((void **)&id->sci_component_name);
  2385. id->sci_component_name=NULL;
  2386. }
  2387. slapi_ch_free((void **)&id);
  2388. }
  2389. }
  2390. /* used in main.c if -V flag is given */
  2391. static void slapd_print_plugin_version (
  2392. struct slapdplugin *plg,
  2393. struct slapdplugin *prev
  2394. )
  2395. {
  2396. if (plg == NULL || plg->plg_libpath == NULL) return;
  2397. /* same library as previous - don't print twice */
  2398. if (prev != NULL && prev->plg_libpath != NULL) {
  2399. if (strcmp(prev->plg_libpath,plg->plg_libpath) == 0) {
  2400. return;
  2401. }
  2402. }
  2403. printf("%s: %s\n",
  2404. plg->plg_libpath,
  2405. plg->plg_desc.spd_version ? plg->plg_desc.spd_version : "");
  2406. }
  2407. static void slapd_print_pluginlist_versions(struct slapdplugin *plg)
  2408. {
  2409. struct slapdplugin *p,*prev = NULL;
  2410. for (p = plg; p != NULL; p = p->plg_next) {
  2411. slapd_print_plugin_version(p,prev);
  2412. prev = p;
  2413. }
  2414. }
  2415. void plugin_print_versions(void)
  2416. {
  2417. int i;
  2418. for (i = 0; i < PLUGIN_LIST_GLOBAL_MAX; i++) {
  2419. slapd_print_pluginlist_versions(get_plugin_list(i));
  2420. }
  2421. }