plugin.c 149 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. /* plugin.c - routines for setting up and calling plugins */
  13. #include <stddef.h>
  14. #include <stdio.h>
  15. #include <plhash.h>
  16. #include "slap.h"
  17. /* this defines are used for plugin configuration */
  18. #define LOCAL_DATA "local data"
  19. #define REMOTE_DATA "remote data"
  20. #define ALL_DATA "*"
  21. #define ROOT_BIND "directory manager"
  22. #define ANONYMOUS_BIND "anonymous"
  23. /* dependency checking flags */
  24. #define CHECK_ALL 0
  25. #define CHECK_TYPE 1
  26. /* plugin removal flags */
  27. #define PLUGIN_NOT_FOUND 0
  28. #define PLUGIN_REMOVED 1
  29. #define PLUGIN_BUSY 2
  30. static char *critical_plugins[] = {"cn=ldbm database,cn=plugins,cn=config",
  31. "cn=ACL Plugin,cn=plugins,cn=config",
  32. "cn=ACL preoperation,cn=plugins,cn=config",
  33. "cn=chaining database,cn=plugins,cn=config",
  34. "cn=Multimaster Replication Plugin,cn=plugins,cn=config",
  35. NULL};
  36. /* Forward Declarations */
  37. static int plugin_call_list(struct slapdplugin *list, int operation, Slapi_PBlock *pb);
  38. static int plugin_call_one(struct slapdplugin *list, int operation, Slapi_PBlock *pb);
  39. static int plugin_call_func(struct slapdplugin *list, int operation, Slapi_PBlock *pb, int call_one);
  40. static PRBool plugin_invoke_plugin_pb(struct slapdplugin *plugin, int operation, Slapi_PBlock *pb);
  41. static PRBool plugin_matches_operation(Slapi_DN *target_spec, PluginTargetData *ptd, PRBool bindop, PRBool isroot, PRBool islocal, ber_tag_t method);
  42. static void plugin_config_init(struct pluginconfig *config);
  43. static void plugin_config_cleanup(struct pluginconfig *config);
  44. static int plugin_config_set_action(int *action, char *value);
  45. static struct pluginconfig *plugin_get_config(struct slapdplugin *plugin);
  46. static void default_plugin_init(void);
  47. static void ptd_init(PluginTargetData *ptd);
  48. static void ptd_cleanup(PluginTargetData *ptd);
  49. static void ptd_add_subtree(PluginTargetData *ptd, Slapi_DN *subtree);
  50. static void ptd_set_special_data(PluginTargetData *ptd, int type);
  51. static Slapi_DN *ptd_get_first_subtree(const PluginTargetData *ptd, int *cookie);
  52. static Slapi_DN *ptd_get_next_subtree(const PluginTargetData *ptd, int *cookie);
  53. static PRBool ptd_is_special_data_set(const PluginTargetData *ptd, int type);
  54. int ptd_get_subtree_count(const PluginTargetData *ptd);
  55. static void plugin_set_global(PluginTargetData *ptd);
  56. static PRBool plugin_is_global(const PluginTargetData *ptd);
  57. static void plugin_set_default_access(struct pluginconfig *config);
  58. static int plugin_delete_check_dependency(struct slapdplugin *plugin_entry, int flag, char *returntext);
  59. static char *plugin_get_type_str(int type);
  60. static void plugin_cleanup_list(void);
  61. static int plugin_remove_plugins(struct slapdplugin *plugin_entry, char *plugin_type);
  62. static void plugin_remove_from_shutdown(struct slapdplugin *plugin_entry);
  63. static void plugin_free(struct slapdplugin *plugin);
  64. static PLHashTable *global_plugin_dns = NULL;
  65. /* The global plugin list is indexed by the PLUGIN_LIST_* constants defined in slap.h */
  66. static struct slapdplugin *global_plugin_list[PLUGIN_LIST_GLOBAL_MAX];
  67. /* plugin structure used to configure internal operation issued by the core server */
  68. static int global_server_plg_initialised = 0;
  69. struct slapdplugin global_server_plg;
  70. /* plugin structure used to configure internal operation issued by the core server */
  71. static int global_server_plg_id_initialised = 0;
  72. struct slapi_componentid global_server_id_plg;
  73. /* plugin structure used to configure operations issued by the old plugins that
  74. do not pass their identity in the operation */
  75. static struct slapdplugin global_default_plg;
  76. /* Enable/disable plugin callbacks for clean startup */
  77. static int global_plugin_callbacks_enabled = 0;
  78. static Slapi_RWLock *global_rwlock = NULL;
  79. void
  80. global_plugin_init()
  81. {
  82. if ((global_rwlock = slapi_new_rwlock()) == NULL) {
  83. slapi_log_err(SLAPI_LOG_ERR, "global_plugin_init",
  84. "Failed to create global plugin rwlock.\n");
  85. exit(1);
  86. }
  87. }
  88. static void
  89. add_plugin_to_list(struct slapdplugin **list, struct slapdplugin *plugin)
  90. {
  91. struct slapdplugin **tmp;
  92. struct slapdplugin *last = NULL;
  93. int plugin_added = 0;
  94. slapi_log_err(SLAPI_LOG_TRACE, "add_plugin_to_list", "Adding %s \n", plugin->plg_name);
  95. /* Insert the plugin into list based off of precedence. */
  96. for (tmp = list; *tmp; tmp = &(*tmp)->plg_next) {
  97. if (plugin->plg_precedence < (*tmp)->plg_precedence) {
  98. if (last) {
  99. /* Insert item between last and tmp. */
  100. plugin->plg_next = *tmp;
  101. last->plg_next = plugin;
  102. } else {
  103. /* Add as the first list item. */
  104. plugin->plg_next = *tmp;
  105. *list = plugin;
  106. }
  107. plugin_added = 1;
  108. /* We've added the plug-in to the
  109. * list, so bail from the loop. */
  110. break;
  111. }
  112. /* Save a pointer to this plugin so we can
  113. * refer to it on the next loop iteration. */
  114. last = *tmp;
  115. }
  116. /* If we didn't add the plug-in to the list yet,
  117. * it needs to be added to the end of the list. */
  118. if (!plugin_added) {
  119. *tmp = plugin;
  120. }
  121. }
  122. struct slapdplugin *
  123. get_plugin_list(int plugin_list_index)
  124. {
  125. return global_plugin_list[plugin_list_index];
  126. }
  127. /*
  128. * As the plugin configuration information is read an array of
  129. * entries is built which reflect the plugins. The entries
  130. * are added after the syntax plugins are started so that the
  131. * nodes in the attribute tree are initialised correctly.
  132. */
  133. typedef struct entry_and_plugin
  134. {
  135. Slapi_Entry *e;
  136. struct slapdplugin *plugin;
  137. struct entry_and_plugin *next;
  138. } entry_and_plugin_t;
  139. static entry_and_plugin_t *dep_plugin_entries = NULL; /* for dependencies */
  140. static int
  141. plugin_is_critical(Slapi_Entry *plugin_entry)
  142. {
  143. char *plugin_dn = NULL;
  144. int i;
  145. plugin_dn = slapi_entry_get_ndn(plugin_entry);
  146. for (i = 0; critical_plugins[i]; i++) {
  147. if (strcasecmp(plugin_dn, critical_plugins[i]) == 0) {
  148. return 1;
  149. }
  150. }
  151. return 0;
  152. }
  153. static void
  154. new_plugin_entry(entry_and_plugin_t **ep, Slapi_Entry *e, struct slapdplugin *plugin)
  155. {
  156. entry_and_plugin_t *oldep = 0;
  157. entry_and_plugin_t *iterep = *ep;
  158. entry_and_plugin_t *newep = (entry_and_plugin_t *)slapi_ch_calloc(1, sizeof(entry_and_plugin_t));
  159. newep->e = e;
  160. newep->plugin = plugin;
  161. while (iterep) {
  162. oldep = iterep;
  163. iterep = iterep->next;
  164. }
  165. newep->next = 0;
  166. if (oldep) {
  167. oldep->next = newep;
  168. } else {
  169. *ep = newep;
  170. }
  171. }
  172. static void
  173. add_plugin_entry_dn(const Slapi_DN *plugin_dn)
  174. {
  175. if (!global_plugin_dns) {
  176. global_plugin_dns = PL_NewHashTable(20, PL_HashString,
  177. PL_CompareStrings,
  178. PL_CompareValues, 0, 0);
  179. }
  180. PL_HashTableAdd(global_plugin_dns,
  181. slapi_sdn_get_ndn(plugin_dn),
  182. (void *)plugin_dn);
  183. }
  184. #define SLAPI_PLUGIN_NONE_IF_NULL(s) ((s) == NULL ? "none" : (s))
  185. /*
  186. * Allows a plugin to register a plugin.
  187. * This was added so that 'object' plugins could register all
  188. * the plugin interfaces that it supports.
  189. */
  190. int
  191. slapi_register_plugin(
  192. const char *plugintype,
  193. int enabled,
  194. const char *initsymbol,
  195. slapi_plugin_init_fnptr initfunc,
  196. const char *name,
  197. char **argv,
  198. void *group_identity)
  199. {
  200. return slapi_register_plugin_ext(plugintype, enabled, initsymbol,
  201. initfunc, name, argv, group_identity, PLUGIN_DEFAULT_PRECEDENCE);
  202. }
  203. int
  204. slapi_register_plugin_ext(
  205. const char *plugintype,
  206. int enabled,
  207. const char *initsymbol,
  208. slapi_plugin_init_fnptr initfunc,
  209. const char *name,
  210. char **argv,
  211. void *group_identity,
  212. int precedence)
  213. {
  214. Slapi_Entry *e = NULL;
  215. char returntext[SLAPI_DSE_RETURNTEXT_SIZE] = "";
  216. char *dn = slapi_ch_smprintf("cn=%s,%s", name, PLUGIN_BASE_DN);
  217. Slapi_DN *sdn = slapi_sdn_new_normdn_passin(dn);
  218. int found_precedence;
  219. int ii = 0;
  220. int rc = 0;
  221. e = slapi_entry_alloc();
  222. /* this function consumes dn */
  223. slapi_entry_init_ext(e, sdn, NULL);
  224. slapi_sdn_free(&sdn);
  225. slapi_entry_attr_set_charptr(e, "cn", name);
  226. /* Need a valid objectClass! No plugin OC so just use extensible :( */
  227. slapi_entry_add_string(e, "objectclass", "top");
  228. slapi_entry_add_string(e, "objectclass", "extensibleObject");
  229. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_TYPE, plugintype);
  230. if (!enabled) {
  231. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_ENABLED, "off");
  232. }
  233. slapi_entry_attr_set_charptr(e, ATTR_PLUGIN_INITFN, initsymbol);
  234. /* If the plugin belong to a group, get the precedence from the group */
  235. found_precedence = precedence;
  236. if ((found_precedence == PLUGIN_DEFAULT_PRECEDENCE) && group_identity) {
  237. struct slapi_componentid *cid = (struct slapi_componentid *)group_identity;
  238. if (cid->sci_plugin && (cid->sci_plugin->plg_precedence != PLUGIN_DEFAULT_PRECEDENCE)) {
  239. slapi_log_err(SLAPI_LOG_PLUGIN, "slapi_register_plugin_ext",
  240. "Plugin precedence (%s) reset to group precedence (%s): %d \n",
  241. name ? name : "",
  242. cid->sci_plugin->plg_name ? cid->sci_plugin->plg_name : "",
  243. cid->sci_plugin->plg_precedence);
  244. found_precedence = cid->sci_plugin->plg_precedence;
  245. }
  246. }
  247. slapi_entry_attr_set_int(e, ATTR_PLUGIN_PRECEDENCE, found_precedence);
  248. for (ii = 0; argv && argv[ii]; ++ii) {
  249. char argname[64];
  250. PR_snprintf(argname, sizeof(argname), "%s%d", ATTR_PLUGIN_ARG, ii);
  251. slapi_entry_attr_set_charptr(e, argname, argv[ii]);
  252. }
  253. /* plugin_setup copies the given entry */
  254. rc = plugin_setup(e, group_identity, initfunc, 0, returntext);
  255. slapi_entry_free(e);
  256. return rc;
  257. }
  258. int
  259. plugin_call_plugins(Slapi_PBlock *pb, int whichfunction)
  260. {
  261. int plugin_list_number = -1;
  262. int rc = 0;
  263. int do_op = global_plugin_callbacks_enabled;
  264. if (pb == NULL) {
  265. return (0);
  266. }
  267. switch (whichfunction) {
  268. case SLAPI_PLUGIN_PRE_BIND_FN:
  269. case SLAPI_PLUGIN_PRE_UNBIND_FN:
  270. case SLAPI_PLUGIN_PRE_SEARCH_FN:
  271. case SLAPI_PLUGIN_PRE_COMPARE_FN:
  272. case SLAPI_PLUGIN_PRE_MODIFY_FN:
  273. case SLAPI_PLUGIN_PRE_MODRDN_FN:
  274. case SLAPI_PLUGIN_PRE_ADD_FN:
  275. case SLAPI_PLUGIN_PRE_DELETE_FN:
  276. case SLAPI_PLUGIN_PRE_ABANDON_FN:
  277. case SLAPI_PLUGIN_PRE_ENTRY_FN:
  278. case SLAPI_PLUGIN_PRE_REFERRAL_FN:
  279. case SLAPI_PLUGIN_PRE_RESULT_FN:
  280. plugin_list_number = PLUGIN_LIST_PREOPERATION;
  281. break;
  282. case SLAPI_PLUGIN_POST_BIND_FN:
  283. case SLAPI_PLUGIN_POST_UNBIND_FN:
  284. case SLAPI_PLUGIN_POST_SEARCH_FN:
  285. case SLAPI_PLUGIN_POST_SEARCH_FAIL_FN:
  286. case SLAPI_PLUGIN_POST_COMPARE_FN:
  287. case SLAPI_PLUGIN_POST_MODIFY_FN:
  288. case SLAPI_PLUGIN_POST_MODRDN_FN:
  289. case SLAPI_PLUGIN_POST_ADD_FN:
  290. case SLAPI_PLUGIN_POST_DELETE_FN:
  291. case SLAPI_PLUGIN_POST_ABANDON_FN:
  292. case SLAPI_PLUGIN_POST_ENTRY_FN:
  293. case SLAPI_PLUGIN_POST_REFERRAL_FN:
  294. case SLAPI_PLUGIN_POST_RESULT_FN:
  295. plugin_list_number = PLUGIN_LIST_POSTOPERATION;
  296. break;
  297. case SLAPI_PLUGIN_BE_PRE_MODIFY_FN:
  298. case SLAPI_PLUGIN_BE_PRE_MODRDN_FN:
  299. case SLAPI_PLUGIN_BE_PRE_ADD_FN:
  300. case SLAPI_PLUGIN_BE_PRE_DELETE_FN:
  301. case SLAPI_PLUGIN_BE_PRE_CLOSE_FN:
  302. plugin_list_number = PLUGIN_LIST_BEPREOPERATION;
  303. do_op = 1; /* always allow backend callbacks (even during startup) */
  304. break;
  305. case SLAPI_PLUGIN_BE_POST_MODIFY_FN:
  306. case SLAPI_PLUGIN_BE_POST_MODRDN_FN:
  307. case SLAPI_PLUGIN_BE_POST_ADD_FN:
  308. case SLAPI_PLUGIN_BE_POST_DELETE_FN:
  309. case SLAPI_PLUGIN_BE_POST_OPEN_FN:
  310. case SLAPI_PLUGIN_BE_POST_EXPORT_FN:
  311. case SLAPI_PLUGIN_BE_POST_IMPORT_FN:
  312. plugin_list_number = PLUGIN_LIST_BEPOSTOPERATION;
  313. do_op = 1; /* always allow backend callbacks (even during startup) */
  314. break;
  315. case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN:
  316. case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
  317. case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
  318. case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
  319. case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
  320. plugin_list_number = PLUGIN_LIST_INTERNAL_PREOPERATION;
  321. break;
  322. case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
  323. case SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN:
  324. case SLAPI_PLUGIN_INTERNAL_POST_ADD_FN:
  325. case SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN:
  326. plugin_list_number = PLUGIN_LIST_INTERNAL_POSTOPERATION;
  327. break;
  328. case SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN:
  329. case SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN:
  330. case SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN:
  331. case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN:
  332. case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN:
  333. plugin_list_number = PLUGIN_LIST_BETXNPREOPERATION;
  334. do_op = 1; /* always allow backend callbacks (even during startup) */
  335. break;
  336. case SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN:
  337. case SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN:
  338. case SLAPI_PLUGIN_BE_TXN_POST_ADD_FN:
  339. case SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN:
  340. plugin_list_number = PLUGIN_LIST_BETXNPOSTOPERATION;
  341. do_op = 1; /* always allow backend callbacks (even during startup) */
  342. break;
  343. case SLAPI_PLUGIN_PRE_EXTOP_FN:
  344. plugin_list_number = PLUGIN_LIST_PREEXTENDED_OPERATION;
  345. break;
  346. case SLAPI_PLUGIN_POST_EXTOP_FN:
  347. plugin_list_number = PLUGIN_LIST_POSTEXTENDED_OPERATION;
  348. break;
  349. }
  350. if (plugin_list_number != -1 && do_op) {
  351. /* We stash the pblock plugin pointer to preserve the callers context */
  352. struct slapdplugin *p;
  353. int locked = 0;
  354. locked = slapi_td_get_plugin_locked();
  355. if (!locked) {
  356. slapi_rwlock_rdlock(global_rwlock);
  357. }
  358. slapi_pblock_get(pb, SLAPI_PLUGIN, &p);
  359. /* Call the operation on the Global Plugins */
  360. rc = plugin_call_list(global_plugin_list[plugin_list_number], whichfunction, pb);
  361. slapi_pblock_set(pb, SLAPI_PLUGIN, p);
  362. if (!locked) {
  363. slapi_rwlock_unlock(global_rwlock);
  364. }
  365. } else {
  366. /* Programmer error! or the callback is denied during startup */
  367. }
  368. return rc;
  369. }
  370. void
  371. plugin_call_entrystore_plugins(char **entrystr, uint *size)
  372. {
  373. struct slapdplugin *p;
  374. for (p = global_plugin_list[PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE];
  375. p != NULL; p = p->plg_next) {
  376. if (p->plg_entrystorefunc)
  377. (*p->plg_entrystorefunc)(entrystr, size);
  378. }
  379. }
  380. void
  381. plugin_call_entryfetch_plugins(char **entrystr, uint *size)
  382. {
  383. struct slapdplugin *p;
  384. for (p = global_plugin_list[PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE];
  385. p != NULL; p = p->plg_next) {
  386. if (p->plg_entryfetchfunc)
  387. (*p->plg_entryfetchfunc)(entrystr, size);
  388. }
  389. }
  390. /*
  391. * plugin_determine_exop_plugins
  392. *
  393. * A call to this function will determine the correct plugin that is required
  394. * based on the extended operation ID.
  395. *
  396. * extoid : The extended operation oid as a *char
  397. * plugin: A pointer to a struct slapdplugin *. IE &*p This will be set by the function.
  398. * return: SLAPI_PLUGIN_EXTENDED_NOT_HANDLED if no plugin. Otherwise, the SLAPI_PLUGIN_* type that the plugin is.
  399. */
  400. int
  401. plugin_determine_exop_plugins(const char *oid, struct slapdplugin **plugin)
  402. {
  403. struct slapdplugin *p = NULL;
  404. int list_type = 0;
  405. int i = 0;
  406. int l = 0;
  407. int rc = SLAPI_PLUGIN_EXTENDED_NOT_HANDLED;
  408. int list_types[] = {PLUGIN_LIST_EXTENDED_OPERATION, PLUGIN_LIST_BE_TXN_EXTENDED_OPERATION};
  409. for (l = 0; l < 2; ++l) {
  410. list_type = list_types[l];
  411. for (p = global_plugin_list[list_type]; p != NULL; p = p->plg_next) {
  412. if (p->plg_exhandler != NULL && p->plg_exoids != NULL) {
  413. for (i = 0; p->plg_exoids[i] != NULL; i++) {
  414. if (strcasecmp(oid, p->plg_exoids[i]) == 0) {
  415. *plugin = p;
  416. rc = p->plg_type;
  417. /* break; */
  418. /* WB - 48870, return early so that we can get the plugin
  419. * that is set earlier in the list. This prevents the
  420. * need to change add_plugin_to_list, which may have
  421. * side effects.
  422. */
  423. return rc;
  424. }
  425. }
  426. }
  427. }
  428. }
  429. return rc;
  430. }
  431. /*
  432. * call extended operation plugins
  433. *
  434. * return SLAPI_PLUGIN_EXTENDED_SENT_RESULT if one of the extended operation
  435. * plugins sent a result.
  436. * return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED if no extended operation plugins
  437. * handled the operation.
  438. * otherwise, return an LDAP error code (possibly a merge of the errors
  439. * returned by the plugins we called).
  440. */
  441. int
  442. plugin_call_exop_plugins(Slapi_PBlock *pb, struct slapdplugin *p)
  443. {
  444. int rc;
  445. slapi_pblock_set(pb, SLAPI_PLUGIN, p);
  446. set_db_default_result_handlers(pb);
  447. rc = (*p->plg_exhandler)(pb);
  448. return (rc);
  449. }
  450. /*
  451. * Attempt to convert the extended operation 'oid' to a string by
  452. * examining the registered plugins. Returns NULL if no plugin is
  453. * registered for this OID.
  454. *
  455. * Our first choice is to use an OID-specific name that has been
  456. * registered by a plugin via the SLAPI_PLUGIN_EXT_OP_NAMELIST pblock setting.
  457. * Our second choice is to use the plugin's ID (short name).
  458. * Our third choice is to use the plugin's RDN (under cn=config).
  459. */
  460. const char *
  461. plugin_extended_op_oid2string(const char *oid)
  462. {
  463. struct slapdplugin *p;
  464. int j = 0;
  465. int rc = 0;
  466. const char *rval = NULL;
  467. rc = plugin_determine_exop_plugins(oid, &p);
  468. if ((rc == SLAPI_PLUGIN_EXTENDEDOP || rc == SLAPI_PLUGIN_BETXNEXTENDEDOP) && p != NULL) {
  469. /* We have the plugin, p set, so lets fill it in */
  470. if (NULL != p->plg_exnames) {
  471. for (j = 0; p->plg_exnames[j] != NULL; ++j) {
  472. /* I'm not sure what this does ....*/
  473. ;
  474. }
  475. rval = p->plg_exnames[j]; /* OID-related name */
  476. }
  477. if (NULL == rval) {
  478. if (NULL != p->plg_desc.spd_id) {
  479. rval = p->plg_desc.spd_id; /* short name */
  480. } else {
  481. rval = p->plg_name; /* RDN */
  482. }
  483. }
  484. }
  485. return (rval);
  486. }
  487. Slapi_Backend *
  488. plugin_extended_op_getbackend(Slapi_PBlock *pb, struct slapdplugin *p)
  489. {
  490. // struct slapdplugin *p;
  491. int rc;
  492. /* This could be an error type, but for now we expect the caller to check
  493. * that it's not null
  494. */
  495. Slapi_Backend *result = NULL;
  496. rc = (*p->plg_be_exhandler)(pb, &result);
  497. if (rc != LDAP_SUCCESS) {
  498. /* Do we need to do anything? Or it is the parents job? */
  499. result = NULL;
  500. }
  501. return (result);
  502. }
  503. static int
  504. plugin_cmp_plugins(struct slapdplugin *p1, struct slapdplugin *p2)
  505. {
  506. int rc = 0;
  507. if (p1->plg_dn) {
  508. if (p2->plg_dn && strcasecmp(p1->plg_dn, p2->plg_dn) == 0) {
  509. rc = 1;
  510. } else if (p2->plg_id && strcasecmp(p1->plg_dn, p2->plg_id) == 0) {
  511. rc = 1;
  512. }
  513. } else if (p1->plg_id) {
  514. if (p2->plg_id && strcasecmp(p1->plg_id, p2->plg_id) == 0) {
  515. rc = 1;
  516. } else if (p2->plg_dn && strcasecmp(p2->plg_dn, p1->plg_id) == 0) {
  517. rc = 1;
  518. }
  519. }
  520. return rc;
  521. }
  522. /*
  523. * kexcoff: return the slapdplugin structure
  524. */
  525. struct slapdplugin *
  526. plugin_get_pwd_storage_scheme(char *name, int len, int index)
  527. {
  528. /* index could be PLUGIN_LIST_PWD_STORAGE_SCHEME or PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME */
  529. struct slapdplugin *p;
  530. for (p = global_plugin_list[index]; p != NULL; p = p->plg_next) {
  531. if ((int)strlen(p->plg_pwdstorageschemename) == len) {
  532. if (strncasecmp(p->plg_pwdstorageschemename, name, len) == 0) {
  533. return (p);
  534. }
  535. }
  536. }
  537. return (NULL);
  538. }
  539. char *
  540. plugin_get_pwd_storage_scheme_list(int index)
  541. {
  542. /* index could be PLUGIN_LIST_PWD_STORAGE_SCHEME or PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME */
  543. struct slapdplugin *p = NULL;
  544. char *names_list = NULL;
  545. int len = 0;
  546. /* first pass - calculate space needed for comma delimited list */
  547. for (p = global_plugin_list[index]; p != NULL; p = p->plg_next) {
  548. if (p->plg_pwdstorageschemeenc != NULL) {
  549. /* + 1 for comma, 1 for space, 1 for null */
  550. len += strlen(p->plg_pwdstorageschemename) + 3;
  551. }
  552. }
  553. /* no plugins? */
  554. if (!len)
  555. return NULL;
  556. /* next, allocate the space */
  557. names_list = (char *)slapi_ch_malloc(len + 1);
  558. *names_list = 0;
  559. /* second pass - write the string */
  560. for (p = global_plugin_list[index]; p != NULL; p = p->plg_next) {
  561. if (p->plg_pwdstorageschemeenc != NULL) {
  562. strcat(names_list, p->plg_pwdstorageschemename);
  563. if (p->plg_next != NULL)
  564. strcat(names_list, ", ");
  565. }
  566. }
  567. return (names_list);
  568. }
  569. int
  570. slapi_send_ldap_intermediate(Slapi_PBlock *pb, LDAPControl **ectrls, char *responseName, struct berval *responseValue)
  571. {
  572. /* no SLAPI_PLUGIN_DB_INTERMEDIATE_FN defined
  573. * always directly call slapd_ function
  574. */
  575. return send_ldap_intermediate(pb, ectrls, responseName, responseValue);
  576. }
  577. int
  578. slapi_send_ldap_search_entry(Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls, char **attrs, int attrsonly)
  579. {
  580. IFP fn = NULL;
  581. slapi_pblock_get(pb, SLAPI_PLUGIN_DB_ENTRY_FN, (void *)&fn);
  582. if (NULL == fn) {
  583. return -1;
  584. }
  585. return (*fn)(pb, e, ectrls, attrs, attrsonly);
  586. }
  587. void
  588. slapi_set_ldap_result(Slapi_PBlock *pb, int err, char *matched, char *text, int nentries __attribute__((unused)), struct berval **urls __attribute__((unused)))
  589. {
  590. char *old_matched = NULL;
  591. char *old_text = NULL;
  592. char *matched_copy = slapi_ch_strdup(matched);
  593. char *text_copy = slapi_ch_strdup(text);
  594. /* free the old matched and text, if any */
  595. slapi_pblock_get(pb, SLAPI_RESULT_MATCHED, &old_matched);
  596. slapi_ch_free_string(&old_matched);
  597. slapi_pblock_get(pb, SLAPI_RESULT_TEXT, &old_text);
  598. slapi_ch_free_string(&old_text);
  599. /* set the new stuff */
  600. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
  601. slapi_pblock_set(pb, SLAPI_RESULT_MATCHED, matched_copy);
  602. slapi_pblock_set(pb, SLAPI_RESULT_TEXT, text_copy);
  603. }
  604. void
  605. slapi_send_ldap_result_from_pb(Slapi_PBlock *pb)
  606. {
  607. int err;
  608. char *matched;
  609. char *text;
  610. IFP fn = NULL;
  611. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &err);
  612. slapi_pblock_get(pb, SLAPI_RESULT_TEXT, &text);
  613. slapi_pblock_get(pb, SLAPI_RESULT_MATCHED, &matched);
  614. slapi_pblock_get(pb, SLAPI_PLUGIN_DB_RESULT_FN, (void *)&fn);
  615. if (NULL != fn) {
  616. (*fn)(pb, err, matched, text, 0, NULL);
  617. }
  618. slapi_pblock_set(pb, SLAPI_RESULT_TEXT, NULL);
  619. slapi_pblock_set(pb, SLAPI_RESULT_MATCHED, NULL);
  620. slapi_ch_free((void **)&matched);
  621. slapi_ch_free((void **)&text);
  622. }
  623. void
  624. slapi_send_ldap_result(Slapi_PBlock *pb, int err, char *matched, char *text, int nentries, struct berval **urls)
  625. {
  626. IFP fn = NULL;
  627. Slapi_Operation *operation;
  628. long op_type;
  629. /* GB : for spanning requests over multiple backends */
  630. if (err == LDAP_NO_SUCH_OBJECT) {
  631. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  632. op_type = operation_get_type(operation);
  633. if (op_type == SLAPI_OPERATION_SEARCH) {
  634. if (urls || nentries) {
  635. slapi_log_err(SLAPI_LOG_ERR, "slapi_send_ldap_result",
  636. "urls or nentries set in sendldap_result while NO_SUCH_OBJECT returned\n");
  637. }
  638. slapi_set_ldap_result(pb, err, matched, text, 0, NULL);
  639. return;
  640. }
  641. }
  642. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
  643. slapi_pblock_get(pb, SLAPI_PLUGIN_DB_RESULT_FN, (void *)&fn);
  644. if (NULL == fn) {
  645. return;
  646. }
  647. /*
  648. * Call the result function. It should set pb->pb_op->o_status to
  649. * SLAPI_OP_STATUS_RESULT_SENT right after sending the result to
  650. * the client or otherwise consuming it.
  651. */
  652. (*fn)(pb, err, matched, text, nentries, urls);
  653. }
  654. int
  655. slapi_send_ldap_referral(Slapi_PBlock *pb, Slapi_Entry *e, struct berval **refs, struct berval ***urls)
  656. {
  657. IFP fn = NULL;
  658. slapi_pblock_get(pb, SLAPI_PLUGIN_DB_REFERRAL_FN, (void *)&fn);
  659. if (NULL == fn) {
  660. return -1;
  661. }
  662. return (*fn)(pb, e, refs, urls);
  663. }
  664. /***********************************************************
  665. start of plugin dependency code
  666. ************************************************************/
  667. /* struct _plugin_dep_type
  668. * we shall not presume to know all plugin types
  669. * so as to allow new types to be added without
  670. * requiring changes to this code (hopefully)
  671. * so we need to dynamically keep track of them
  672. */
  673. typedef struct _plugin_dep_type
  674. {
  675. char *type; /* the string descriptor */
  676. int num_not_started; /* the count of plugins which have yet to be started for this type */
  677. struct _plugin_dep_type *next;
  678. } * plugin_dep_type;
  679. /* _plugin_dep_config
  680. * we need somewhere to collect the plugin configurations
  681. * prior to attempting to resolve dependencies
  682. */
  683. typedef struct _plugin_dep_config
  684. {
  685. char *name;
  686. char *type;
  687. Slapi_PBlock *pb;
  688. struct slapdplugin *plugin;
  689. Slapi_Entry *e;
  690. int entry_created;
  691. int op_done;
  692. char **depends_type_list;
  693. int total_type;
  694. char **depends_named_list;
  695. int total_named;
  696. char *config_area;
  697. int removed;
  698. } plugin_dep_config;
  699. static void plugin_free_plugin_dep_config(plugin_dep_config **config);
  700. /* list of plugins which should be shutdown in reverse order */
  701. static plugin_dep_config *global_plugin_shutdown_order = 0;
  702. static int global_plugins_started = 0;
  703. /*
  704. * find_plugin_type
  705. *
  706. * searches the list for the plugin type
  707. * and returns the plugin_dep_type if found
  708. */
  709. static plugin_dep_type
  710. find_plugin_type(plugin_dep_type head, char *type)
  711. {
  712. plugin_dep_type ret = 0;
  713. plugin_dep_type iter = head;
  714. while (iter) {
  715. if (!slapi_UTF8CASECMP(iter->type, type)) {
  716. ret = iter;
  717. break;
  718. }
  719. iter = iter->next;
  720. }
  721. return ret;
  722. }
  723. /*
  724. * increment_plugin_type
  725. *
  726. * searches the list for the plugin type
  727. * and increments its not started value
  728. * returns the current type count on success -1 on failure
  729. * to find the type
  730. */
  731. static int
  732. increment_plugin_type(plugin_dep_type head, char *type)
  733. {
  734. int ret = -1;
  735. plugin_dep_type the_type;
  736. if ((the_type = find_plugin_type(head, type)) != NULL)
  737. ret = ++the_type->num_not_started;
  738. return ret;
  739. }
  740. /*
  741. * decrement_plugin_type
  742. *
  743. * searches the list for the plugin type
  744. * and decrements its not started value
  745. * returns the current type count on success -1 on failure
  746. * to find the type
  747. */
  748. static int
  749. decrement_plugin_type(plugin_dep_type head, char *type)
  750. {
  751. int ret = -1;
  752. plugin_dep_type the_type;
  753. if ((the_type = find_plugin_type(head, type)) != NULL)
  754. ret = --the_type->num_not_started;
  755. return ret;
  756. }
  757. /*
  758. * add_plugin_type
  759. *
  760. * Either increments the count of the plugin type
  761. * or when it does not exist, adds it to the list
  762. */
  763. static int
  764. add_plugin_type(plugin_dep_type *head, char *type)
  765. {
  766. int ret = -1;
  767. if (*head) {
  768. if (0 < increment_plugin_type(*head, type)) {
  769. ret = 0;
  770. }
  771. }
  772. if (ret) {
  773. /* create new head */
  774. plugin_dep_type tmp_head;
  775. tmp_head = (plugin_dep_type)slapi_ch_malloc(sizeof(struct _plugin_dep_type));
  776. tmp_head->num_not_started = 1;
  777. tmp_head->type = slapi_ch_strdup(type);
  778. ret = 0;
  779. tmp_head->next = *head;
  780. (*head) = tmp_head;
  781. }
  782. return ret;
  783. }
  784. /*
  785. * plugin_create_stringlist
  786. *
  787. * Creates a string list from values of the entries
  788. * attribute passed in as args - used to track dependencies
  789. *
  790. */
  791. int
  792. plugin_create_stringlist(Slapi_Entry *plugin_entry, char *attr_name, int *total_strings, char ***list)
  793. {
  794. Slapi_Attr *attr = 0;
  795. int hint = 0;
  796. int num_vals = 0;
  797. int val_index = 0;
  798. Slapi_Value *val = NULL;
  799. if (0 == slapi_entry_attr_find(plugin_entry, attr_name, &attr)) {
  800. /* allocate memory for the string array */
  801. slapi_attr_get_numvalues(attr, &num_vals);
  802. if (num_vals) {
  803. *total_strings = num_vals;
  804. *list = (char **)slapi_ch_calloc(num_vals + 1, sizeof(char *));
  805. } else
  806. goto bail; /* if this ever happens, then they are running on a TSR-80 */
  807. val_index = 0;
  808. hint = slapi_attr_first_value(attr, &val);
  809. while (val_index < num_vals) {
  810. /* add the value to the array */
  811. (*list)[val_index] = (char *)slapi_ch_strdup(slapi_value_get_string(val));
  812. hint = slapi_attr_next_value(attr, hint, &val);
  813. val_index++;
  814. }
  815. } else
  816. *total_strings = num_vals;
  817. bail:
  818. return num_vals;
  819. }
  820. /*
  821. * Remove the plugin from the DN hashtable
  822. */
  823. static void
  824. plugin_remove_from_list(char *plugin_dn)
  825. {
  826. Slapi_DN *hash_sdn;
  827. hash_sdn = (Slapi_DN *)PL_HashTableLookup(global_plugin_dns, plugin_dn);
  828. if (hash_sdn) {
  829. PL_HashTableRemove(global_plugin_dns, plugin_dn);
  830. slapi_sdn_free(&hash_sdn);
  831. }
  832. }
  833. /*
  834. * The main plugin was successfully started, set it and its
  835. * registered plugin functions as started.
  836. */
  837. static void
  838. plugin_set_plugins_started(struct slapdplugin *plugin_entry)
  839. {
  840. struct slapdplugin *plugin = NULL;
  841. int type = 0;
  842. /* look everywhere for other plugin functions with the plugin id */
  843. for (type = 0; type < PLUGIN_LIST_GLOBAL_MAX; type++) {
  844. plugin = global_plugin_list[type];
  845. while (plugin) {
  846. if (plugin_cmp_plugins(plugin_entry, plugin)) {
  847. plugin->plg_started = 1;
  848. }
  849. plugin = plugin->plg_next;
  850. }
  851. }
  852. }
  853. /*
  854. * A plugin dependency changed, update the dependency list
  855. */
  856. void
  857. plugin_update_dep_entries(Slapi_Entry *plugin_entry)
  858. {
  859. entry_and_plugin_t *ep;
  860. slapi_rwlock_wrlock(global_rwlock);
  861. ep = dep_plugin_entries;
  862. while (ep) {
  863. if (ep->plugin && ep->e) {
  864. if (slapi_sdn_compare(slapi_entry_get_sdn(ep->e), slapi_entry_get_sdn(plugin_entry)) == 0) {
  865. slapi_entry_free(ep->e);
  866. ep->e = slapi_entry_dup(plugin_entry);
  867. break;
  868. }
  869. }
  870. ep = ep->next;
  871. }
  872. slapi_rwlock_unlock(global_rwlock);
  873. }
  874. /*
  875. * Attempt to start a plugin that was either just added or just enabled.
  876. */
  877. int
  878. plugin_start(Slapi_Entry *entry, char *returntext)
  879. {
  880. entry_and_plugin_t *ep = dep_plugin_entries;
  881. plugin_dep_config *global_tmp_list = NULL;
  882. plugin_dep_config *config = NULL;
  883. plugin_dep_type the_plugin_type;
  884. plugin_dep_type plugin_head = 0;
  885. Slapi_PBlock *pb;
  886. Slapi_Entry *plugin_entry;
  887. struct slapdplugin *plugin;
  888. char *value;
  889. int plugins_started = 1;
  890. int num_plg_started = 0;
  891. int shutdown_index = 0;
  892. int total_plugins = 0;
  893. int plugin_index = 0;
  894. int plugin_idx = -1;
  895. int index = 0;
  896. int ret = 0;
  897. int i = 0;
  898. global_plugins_started = 0;
  899. /* Count the plugins so we can allocate memory for the config array */
  900. while (ep) {
  901. if (slapi_sdn_compare(slapi_entry_get_sdn(ep->e), slapi_entry_get_sdn(entry)) == 0) {
  902. plugin_idx = total_plugins;
  903. }
  904. total_plugins++;
  905. ep = ep->next;
  906. }
  907. /* allocate the config array */
  908. config = (plugin_dep_config *)slapi_ch_calloc(total_plugins + 1, sizeof(plugin_dep_config));
  909. ep = dep_plugin_entries;
  910. /* Collect relevant config */
  911. while (ep) {
  912. plugin = ep->plugin;
  913. if (plugin == 0) {
  914. continue;
  915. }
  916. pb = slapi_pblock_new();
  917. slapi_pblock_set(pb, SLAPI_ARGC, &plugin->plg_argc);
  918. slapi_pblock_set(pb, SLAPI_ARGV, &plugin->plg_argv);
  919. config[plugin_index].pb = pb;
  920. config[plugin_index].e = ep->e;
  921. /* add type */
  922. plugin_entry = ep->e;
  923. if (plugin_entry) {
  924. /*
  925. * Pass the plugin DN in SLAPI_TARGET_SDN and the plugin entry
  926. * in SLAPI_ADD_ENTRY. For this to actually work, we need to
  927. * create an operation and include that in the pblock as well,
  928. * because these two items are stored in the operation parameters.
  929. */
  930. Operation *op = internal_operation_new(SLAPI_OPERATION_ADD, 0);
  931. slapi_pblock_set(config[plugin_index].pb, SLAPI_OPERATION, op);
  932. slapi_pblock_set(config[plugin_index].pb, SLAPI_TARGET_SDN,
  933. (void *)(slapi_entry_get_sdn_const(plugin_entry)));
  934. slapi_pblock_set(config[plugin_index].pb, SLAPI_ADD_ENTRY,
  935. plugin_entry);
  936. /* Pass the plugin alternate config area DN in SLAPI_PLUGIN_CONFIG_AREA. */
  937. value = slapi_entry_attr_get_charptr(plugin_entry, ATTR_PLUGIN_CONFIG_AREA);
  938. if (value) {
  939. config[plugin_index].config_area = value;
  940. value = NULL;
  941. slapi_pblock_set(config[plugin_index].pb, SLAPI_PLUGIN_CONFIG_AREA,
  942. config[plugin_index].config_area);
  943. }
  944. value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype");
  945. if (value) {
  946. add_plugin_type(&plugin_head, value);
  947. config[plugin_index].type = value;
  948. value = NULL;
  949. }
  950. /* now the name */
  951. value = slapi_entry_attr_get_charptr(plugin_entry, "cn");
  952. if (value) {
  953. config[plugin_index].name = value;
  954. value = NULL;
  955. }
  956. config[plugin_index].plugin = plugin;
  957. /* now add dependencies */
  958. plugin_create_stringlist(plugin_entry, ATTR_PLUGIN_DEPENDS_ON_NAMED,
  959. &(config[plugin_index].total_named), &(config[plugin_index].depends_named_list));
  960. plugin_create_stringlist(plugin_entry, ATTR_PLUGIN_DEPENDS_ON_TYPE,
  961. &(config[plugin_index].total_type), &(config[plugin_index].depends_type_list));
  962. }
  963. plugin_index++;
  964. ep = ep->next;
  965. }
  966. /*
  967. * Prepare list of shutdown order (we need nothing fancier right now
  968. * than the reverse startup order) The list may include NULL entries,
  969. * these will be plugins which were never started
  970. */
  971. shutdown_index = total_plugins - 1;
  972. global_tmp_list = (plugin_dep_config *)slapi_ch_calloc(total_plugins, sizeof(plugin_dep_config));
  973. /* now resolve dependencies
  974. * cycle through list, if a plugin has no dependencies then start it
  975. * then remove it from the dependency lists of all other plugins
  976. * and decrement the corresponding element of the plugin types array
  977. * for depends_type we will need to check the array of plugin types
  978. * to see if all type dependencies are at zero prior to start
  979. * if one cycle fails to load any plugins we have failed, however
  980. * we shall continue loading plugins in case a configuration error
  981. * can correct itself
  982. */
  983. while (plugins_started && num_plg_started < total_plugins) {
  984. for (plugin_index = 0, plugins_started = 0; plugin_index < total_plugins; plugin_index++) {
  985. /* perform op on plugins only once */
  986. if (config[plugin_index].op_done == 0) {
  987. int enabled = 0;
  988. int satisfied = 0;
  989. int break_out = 0;
  990. /*
  991. * determine if plugin is enabled
  992. * some processing is necessary even
  993. * if it is not
  994. */
  995. if (NULL != config[plugin_index].e) {
  996. value = (char *)slapi_entry_attr_get_ref(config[plugin_index].e, ATTR_PLUGIN_ENABLED);
  997. if (value && !strcasecmp(value, "on")) {
  998. enabled = 1;
  999. }
  1000. }
  1001. /*
  1002. * make sure named dependencies have been satisfied
  1003. * that means that the list of names should contain all
  1004. * null entries
  1005. */
  1006. if (enabled && config[plugin_index].total_named) {
  1007. i = 0;
  1008. while (break_out == 0 && i < config[plugin_index].total_named) {
  1009. satisfied = 1;
  1010. if ((config[plugin_index].depends_named_list)[i] != 0) {
  1011. satisfied = 0;
  1012. break_out = 1;
  1013. }
  1014. i++;
  1015. }
  1016. if (!satisfied) {
  1017. continue;
  1018. }
  1019. }
  1020. /*
  1021. * make sure the type dependencies have been satisfied
  1022. * that means for each type in the list, it's number of
  1023. * plugins left not started is zero
  1024. */
  1025. satisfied = 0;
  1026. break_out = 0;
  1027. if (enabled && config[plugin_index].total_type) {
  1028. i = 0;
  1029. while (break_out == 0 && i < config[plugin_index].total_type) {
  1030. satisfied = 1;
  1031. the_plugin_type = find_plugin_type(plugin_head, (config[plugin_index].depends_type_list)[i]);
  1032. if (the_plugin_type && the_plugin_type->num_not_started != 0) {
  1033. satisfied = 0;
  1034. break_out = 1;
  1035. }
  1036. i++;
  1037. }
  1038. if (!satisfied) {
  1039. continue;
  1040. }
  1041. }
  1042. /**** This plugins dependencies have now been satisfied ****/
  1043. satisfied = 1; /* symbolic only */
  1044. config[plugin_index].entry_created = 1;
  1045. if (enabled) {
  1046. if (plugin_index == plugin_idx) {
  1047. /* finally, perform the op on the plugin */
  1048. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_start", "Starting %s plugin %s\n",
  1049. config[plugin_index].type, config[plugin_index].name);
  1050. /*
  1051. * Put the plugin into the temporary pblock so the startup functions have
  1052. * access to the real plugin for registering callbacks, task, etc.
  1053. */
  1054. slapi_pblock_set(config[plugin_index].pb, SLAPI_PLUGIN, config[plugin_index].plugin);
  1055. ret = plugin_call_one(config[plugin_index].plugin, SLAPI_PLUGIN_START_FN,
  1056. config[plugin_index].pb);
  1057. // slapi_pblock_destroy(config[plugin_index].pb);
  1058. if (ret) {
  1059. /*
  1060. * Delete the plugin(undo everything), as we don't know how far the start
  1061. * function got.
  1062. */
  1063. slapi_log_err(SLAPI_LOG_ERR, "plugin_start", "Failed to start %s plugin %s\n",
  1064. config[plugin_index].type, config[plugin_index].name);
  1065. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Failed to start plugin \"%s\". See errors log.",
  1066. config[plugin_index].name);
  1067. plugin_delete(entry, returntext, 1);
  1068. goto done;
  1069. } else {
  1070. /*
  1071. * Set the plugin and its registered functions as started.
  1072. */
  1073. plugin_set_plugins_started(config[plugin_index].plugin);
  1074. }
  1075. }
  1076. /* Add this plugin to the shutdown list */
  1077. global_tmp_list[shutdown_index] = config[plugin_index];
  1078. shutdown_index--;
  1079. global_plugins_started++;
  1080. /* remove this named plugin from other plugins lists */
  1081. for (i = 0; i < total_plugins; i++) {
  1082. index = 0;
  1083. while (index < config[i].total_named) {
  1084. if ((config[i].depends_named_list)[index] != 0 &&
  1085. !slapi_UTF8CASECMP((config[i].depends_named_list)[index], config[plugin_index].name)) {
  1086. slapi_ch_free((void **)&((config[i].depends_named_list)[index]));
  1087. }
  1088. index++;
  1089. }
  1090. }
  1091. // } else {
  1092. // /slapi_pblock_destroy(config[plugin_index].pb);
  1093. }
  1094. /* decrement the type counter for this plugin type */
  1095. decrement_plugin_type(plugin_head, config[plugin_index].type);
  1096. config[plugin_index].op_done = 1;
  1097. num_plg_started++;
  1098. plugins_started = 1;
  1099. } /* !op_done */
  1100. } /* plugin loop */
  1101. } /* while plugins not started */
  1102. if (plugins_started == 0) {
  1103. /* a dependency was not resolved - error */
  1104. slapi_log_err(SLAPI_LOG_ERR, "plugin_start", "Failed to resolve plugin dependencies\n");
  1105. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Failed to resolve plugin dependencies.");
  1106. /* list the plugins yet to perform op */
  1107. i = 0;
  1108. while (i < total_plugins) {
  1109. if (config[i].op_done == 0) {
  1110. slapi_log_err(SLAPI_LOG_ERR, "plugin_start",
  1111. "%s plugin %s is not started\n", config[i].type, config[i].name);
  1112. plugin_remove_plugins(config[i].plugin, config[i].type);
  1113. }
  1114. i++;
  1115. }
  1116. ret = -1;
  1117. }
  1118. done:
  1119. /*
  1120. * Free the plugin list, then rebuild it
  1121. */
  1122. if (ret == LDAP_SUCCESS) {
  1123. /* Ok, everything went well, use the new global_shutdown list */
  1124. plugin_free_plugin_dep_config(&global_plugin_shutdown_order);
  1125. global_plugin_shutdown_order = global_tmp_list;
  1126. } else {
  1127. /*
  1128. * problem, undo what we've done in plugin_setup.
  1129. */
  1130. plugin_free_plugin_dep_config(&global_tmp_list);
  1131. }
  1132. /*
  1133. * need the details in config to hang around for shutdown
  1134. * config itself may be deleted since its contents have been
  1135. * copied by value to the shutdown list
  1136. */
  1137. plugin_free_plugin_dep_config(&config);
  1138. if (plugin_head) {
  1139. plugin_dep_type next;
  1140. while (plugin_head) {
  1141. next = plugin_head->next;
  1142. slapi_ch_free_string(&plugin_head->type);
  1143. slapi_ch_free((void *)&plugin_head);
  1144. plugin_head = next;
  1145. }
  1146. }
  1147. /* Finally enable registered plugin functions */
  1148. global_plugin_callbacks_enabled = 1;
  1149. return ret;
  1150. }
  1151. static void
  1152. plugin_free_plugin_dep_config(plugin_dep_config **cfg)
  1153. {
  1154. plugin_dep_config *config = *cfg;
  1155. int index = 0;
  1156. int i = 0;
  1157. if (config) {
  1158. while (config[index].plugin) {
  1159. if (config[index].depends_named_list) {
  1160. for (i = 0; i < config[index].total_named; i++) {
  1161. slapi_ch_free((void **)&(config[index].depends_named_list)[i]);
  1162. }
  1163. slapi_ch_free((void **)&(config[index].depends_named_list));
  1164. }
  1165. if (config[index].depends_type_list) {
  1166. for (i = 0; i < config[index].total_type; i++) {
  1167. slapi_ch_free((void **)&(config[index].depends_type_list)[i]);
  1168. }
  1169. slapi_ch_free((void **)&(config[index].depends_type_list));
  1170. }
  1171. slapi_ch_free_string(&config[index].type);
  1172. slapi_ch_free_string(&config[index].name);
  1173. slapi_ch_free_string(&config[index].config_area);
  1174. slapi_pblock_destroy(config[index].pb);
  1175. index++;
  1176. }
  1177. slapi_ch_free((void **)&config);
  1178. *cfg = NULL;
  1179. }
  1180. }
  1181. /*
  1182. * Take a given plugin and recursively set all the plugin dependency names
  1183. */
  1184. void
  1185. plugin_get_plugin_dependencies(char *plugin_name, char ***names)
  1186. {
  1187. entry_and_plugin_t *ep = dep_plugin_entries;
  1188. char **depends = NULL;
  1189. char *dep_attr = "nsslapd-plugin-depends-on-named";
  1190. int i;
  1191. /* Add the original plugin name to the list */
  1192. if (!charray_inlist(*names, plugin_name)) {
  1193. charray_add(names, slapi_ch_strdup(plugin_name));
  1194. }
  1195. /* Find the plugin and grab its dependencies */
  1196. while (ep) {
  1197. if (ep->plugin) {
  1198. if (strcasecmp(ep->plugin->plg_name, plugin_name) == 0) {
  1199. /* We found our plugin, now grab its dependencies */
  1200. depends = slapi_entry_attr_get_charray(ep->e, dep_attr);
  1201. break;
  1202. }
  1203. }
  1204. ep = ep->next;
  1205. }
  1206. if (depends) {
  1207. /* Add the plugin's dependencies */
  1208. charray_merge_nodup(names, depends, 1);
  1209. /* Add each dependency's dependencies */
  1210. for (i = 0; depends[i]; i++) {
  1211. /* recurse */
  1212. plugin_get_plugin_dependencies(depends[i], names);
  1213. }
  1214. slapi_ch_array_free(depends);
  1215. }
  1216. }
  1217. /*
  1218. * plugin_dependency_startall()
  1219. *
  1220. * Starts all plugins (apart from syntax and matching rule) in order
  1221. * of dependency.
  1222. *
  1223. * Dependencies will be determined by these multi-valued attributes:
  1224. *
  1225. * nsslapd-plugin-depends-on-type : all plugins whose type value matches one of these values must
  1226. * be started prior to this plugin
  1227. *
  1228. * nsslapd-plugin-depends-on-named : the plugin whose cn value matches one of these values must
  1229. * be started prior to this plugin
  1230. */
  1231. static int
  1232. plugin_dependency_startall(int argc, char **argv, char *errmsg __attribute__((unused)), int operation, char **plugin_list)
  1233. {
  1234. int ret = 0;
  1235. Slapi_PBlock *pb;
  1236. int total_plugins = 0;
  1237. plugin_dep_config *config = 0;
  1238. plugin_dep_type plugin_head = 0;
  1239. int plugin_index = 0;
  1240. Slapi_Entry *plugin_entry;
  1241. int i = 0; /* general index iterator */
  1242. plugin_dep_type the_plugin_type;
  1243. int index = 0;
  1244. char *value = NULL;
  1245. int plugins_started;
  1246. int num_plg_started;
  1247. struct slapdplugin *plugin;
  1248. entry_and_plugin_t *ep = dep_plugin_entries;
  1249. int shutdown_index = 0;
  1250. /*
  1251. * Disable registered plugin functions so preops/postops/etc
  1252. * dont get called prior to the plugin being started (due to
  1253. * plugins performing ops on the DIT)
  1254. */
  1255. global_plugin_callbacks_enabled = 0;
  1256. /* Count the plugins so we can allocate memory for the config array */
  1257. while (ep) {
  1258. total_plugins++;
  1259. ep = ep->next;
  1260. }
  1261. /* allocate the config array */
  1262. config = (plugin_dep_config *)slapi_ch_calloc(total_plugins + 1, sizeof(plugin_dep_config));
  1263. ep = dep_plugin_entries;
  1264. if (plugin_list) {
  1265. /* We have a plugin list, so we need to reset the plugin count */
  1266. total_plugins = 0;
  1267. }
  1268. /* Collect relevant config */
  1269. while (ep) {
  1270. plugin = ep->plugin;
  1271. if (plugin == 0) {
  1272. ep = ep->next;
  1273. continue;
  1274. }
  1275. if (plugin_list) {
  1276. /*
  1277. * We have a specific list of plugins to start, skip the others...
  1278. */
  1279. int found = 0;
  1280. for (i = 0; plugin_list[i]; i++) {
  1281. if (strcasecmp(plugin->plg_name, plugin_list[i]) == 0) {
  1282. found = 1;
  1283. break;
  1284. }
  1285. }
  1286. if (!found) {
  1287. /* Skip this plugin, it's not in the list */
  1288. ep = ep->next;
  1289. continue;
  1290. } else {
  1291. total_plugins++;
  1292. }
  1293. }
  1294. pb = slapi_pblock_new();
  1295. slapi_pblock_set(pb, SLAPI_ARGC, &argc);
  1296. slapi_pblock_set(pb, SLAPI_ARGV, &argv);
  1297. config[plugin_index].pb = pb;
  1298. config[plugin_index].e = ep->e;
  1299. /* add type */
  1300. plugin_entry = ep->e;
  1301. if (plugin_entry) {
  1302. /*
  1303. * Pass the plugin DN in SLAPI_TARGET_SDN and the plugin entry
  1304. * in SLAPI_ADD_ENTRY. For this to actually work, we need to
  1305. * create an operation and include that in the pblock as well,
  1306. * because these two items are stored in the operation parameters.
  1307. */
  1308. /* WARNING: memory leak here - op is only freed by a pblock_done,
  1309. and this only happens below if the plugin is enabled - a short
  1310. circuit goto bail may also cause a leak - however, since this
  1311. only happens a few times at startup, this is not a very serious
  1312. leak - just after the call to plugin_call_one */
  1313. Operation *op = internal_operation_new(SLAPI_OPERATION_ADD, 0);
  1314. slapi_pblock_set(config[plugin_index].pb, SLAPI_OPERATION, op);
  1315. slapi_pblock_set(config[plugin_index].pb, SLAPI_TARGET_SDN,
  1316. (void *)(slapi_entry_get_sdn_const(plugin_entry)));
  1317. slapi_pblock_set(config[plugin_index].pb, SLAPI_ADD_ENTRY,
  1318. plugin_entry);
  1319. /* Pass the plugin alternate config area DN in SLAPI_PLUGIN_CONFIG_AREA. */
  1320. value = slapi_entry_attr_get_charptr(plugin_entry, ATTR_PLUGIN_CONFIG_AREA);
  1321. if (value) {
  1322. config[plugin_index].config_area = value;
  1323. value = NULL;
  1324. slapi_pblock_set(config[plugin_index].pb, SLAPI_PLUGIN_CONFIG_AREA,
  1325. config[plugin_index].config_area);
  1326. }
  1327. value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype");
  1328. if (value) {
  1329. add_plugin_type(&plugin_head, value);
  1330. config[plugin_index].type = value;
  1331. value = NULL;
  1332. }
  1333. /* now the name */
  1334. value = slapi_entry_attr_get_charptr(plugin_entry, "cn");
  1335. if (value) {
  1336. config[plugin_index].name = value;
  1337. value = NULL;
  1338. }
  1339. config[plugin_index].plugin = plugin;
  1340. /* now add dependencies */
  1341. plugin_create_stringlist(plugin_entry, "nsslapd-plugin-depends-on-named",
  1342. &(config[plugin_index].total_named), &(config[plugin_index].depends_named_list));
  1343. plugin_create_stringlist(plugin_entry, "nsslapd-plugin-depends-on-type",
  1344. &(config[plugin_index].total_type), &(config[plugin_index].depends_type_list));
  1345. }
  1346. plugin_index++;
  1347. ep = ep->next;
  1348. }
  1349. /* prepare list of shutdown order (we need nothing fancier right now
  1350. * than the reverse startup order) The list may include NULL entries,
  1351. * these will be plugins which were never started
  1352. */
  1353. shutdown_index = total_plugins - 1;
  1354. global_plugin_shutdown_order = (plugin_dep_config *)slapi_ch_calloc(total_plugins + 1, sizeof(plugin_dep_config));
  1355. /* now resolve dependencies
  1356. * cycle through list, if a plugin has no dependencies then start it
  1357. * then remove it from the dependency lists of all other plugins
  1358. * and decrement the corresponding element of the plugin types array
  1359. * for depends_type we will need to check the array of plugin types
  1360. * to see if all type dependencies are at zero prior to start
  1361. * if one cycle fails to load any plugins we have failed, however
  1362. * we shall continue loading plugins in case a configuration error
  1363. * can correct itself
  1364. */
  1365. plugins_started = 1;
  1366. num_plg_started = 0;
  1367. while (plugins_started && num_plg_started < total_plugins) {
  1368. plugins_started = 0;
  1369. for (plugin_index = 0; plugin_index < total_plugins; plugin_index++) {
  1370. /* perform op on plugins only once */
  1371. if (config[plugin_index].op_done == 0) {
  1372. int enabled = 0;
  1373. int satisfied = 0;
  1374. int break_out = 0;
  1375. /*
  1376. * determine if plugin is enabled
  1377. * some processing is necessary even
  1378. * if it is not
  1379. */
  1380. if (NULL != config[plugin_index].e) {
  1381. value = (char *)slapi_entry_attr_get_ref(config[plugin_index].e, ATTR_PLUGIN_ENABLED);
  1382. if (value && !strcasecmp(value, "on")) {
  1383. enabled = 1;
  1384. }
  1385. }
  1386. /*
  1387. * make sure named dependencies have been satisfied
  1388. * that means that the list of names should contain all
  1389. * null entries
  1390. */
  1391. if (enabled && config[plugin_index].total_named) {
  1392. i = 0;
  1393. while (break_out == 0 && i < config[plugin_index].total_named) {
  1394. satisfied = 1;
  1395. if ((config[plugin_index].depends_named_list)[i] != 0) {
  1396. satisfied = 0;
  1397. break_out = 1;
  1398. }
  1399. i++;
  1400. }
  1401. if (!satisfied) {
  1402. continue;
  1403. }
  1404. }
  1405. /*
  1406. * make sure the type dependencies have been satisfied
  1407. * that means for each type in the list, it's number of
  1408. * plugins left not started is zero
  1409. *
  1410. */
  1411. satisfied = 0;
  1412. break_out = 0;
  1413. if (enabled && config[plugin_index].total_type) {
  1414. i = 0;
  1415. while (break_out == 0 && i < config[plugin_index].total_type) {
  1416. satisfied = 1;
  1417. the_plugin_type = find_plugin_type(plugin_head, (config[plugin_index].depends_type_list)[i]);
  1418. if (the_plugin_type && the_plugin_type->num_not_started != 0) {
  1419. satisfied = 0;
  1420. break_out = 1;
  1421. }
  1422. i++;
  1423. }
  1424. if (!satisfied) {
  1425. continue;
  1426. }
  1427. }
  1428. /**** This plugins dependencies have now been satisfied ****/
  1429. satisfied = 1; /* symbolic only */
  1430. /*
  1431. * Add the plugins entry to the DSE so the plugin can get
  1432. * its config (both enabled and disabled have entries
  1433. */
  1434. if (!config[plugin_index].entry_created) {
  1435. int plugin_actions = 0;
  1436. Slapi_PBlock *newpb = slapi_pblock_new();
  1437. Slapi_Entry *newe;
  1438. newe = slapi_entry_dup(config[plugin_index].e);
  1439. slapi_add_entry_internal_set_pb(newpb, newe, NULL,
  1440. plugin_get_default_component_id(), plugin_actions);
  1441. slapi_pblock_set(newpb, SLAPI_TARGET_SDN, (void *)slapi_entry_get_sdn_const(newe));
  1442. slapi_add_internal_pb(newpb);
  1443. slapi_pblock_destroy(newpb);
  1444. config[plugin_index].entry_created = 1;
  1445. }
  1446. /*
  1447. * only actually start plugin and remove from lists if its enabled
  1448. * we do remove from plugin type list however - rule is dependency on
  1449. * zero or more for type
  1450. */
  1451. if (enabled) {
  1452. /* finally, perform the op on the plugin */
  1453. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_dependency_startall",
  1454. "Starting %s plugin %s\n", config[plugin_index].type, config[plugin_index].name);
  1455. /*
  1456. * Put the plugin into the temporary pblock so the startup functions have
  1457. * access to the real plugin for registering callbacks, tasks, etc.
  1458. */
  1459. slapi_pblock_set(config[plugin_index].pb, SLAPI_PLUGIN, config[plugin_index].plugin);
  1460. ret = plugin_call_one(config[plugin_index].plugin, operation, config[plugin_index].pb);
  1461. /* We used to call pblock done here, bet we try to restart
  1462. * the plugin. If we call done on the pb here, the next attempt
  1463. * can have even MORE issues!
  1464. */
  1465. if (ret) {
  1466. /*
  1467. * We will not exit here. If we allow plugins to load normally it is
  1468. * possible that a configuration error (dependencies which were not
  1469. * configured properly) can be recovered from. If there really is a
  1470. * problem then the plugin will never start and eventually it will
  1471. * trigger an exit anyway.
  1472. */
  1473. slapi_log_err(SLAPI_LOG_ERR, "plugin_dependency_startall",
  1474. "Failed to start %s plugin %s\n",
  1475. config[plugin_index].type, config[plugin_index].name);
  1476. continue;
  1477. } else {
  1478. /* now set the plugin and all its registered plugin functions as started */
  1479. plugin_set_plugins_started(config[plugin_index].plugin);
  1480. }
  1481. /* See above note about pblock done: Now we call it here
  1482. * because at this point we *have* started correctly, so we
  1483. * can now free this.
  1484. */
  1485. /* This is freed in free_plugin_dep_config */
  1486. /*
  1487. slapi_pblock_destroy(config[plugin_index].pb);
  1488. */
  1489. /* Add this plugin to the shutdown list */
  1490. global_plugin_shutdown_order[shutdown_index] = config[plugin_index];
  1491. shutdown_index--;
  1492. global_plugins_started++;
  1493. /* remove this named plugin from other plugins lists */
  1494. for (i = 0; i < total_plugins; i++) {
  1495. index = 0;
  1496. while (index < config[i].total_named) {
  1497. if ((config[i].depends_named_list)[index] != 0 && !slapi_UTF8CASECMP((config[i].depends_named_list)[index], config[plugin_index].name)) {
  1498. slapi_ch_free((void **)&((config[i].depends_named_list)[index]));
  1499. (config[i].depends_named_list)[index] = 0;
  1500. }
  1501. index++;
  1502. }
  1503. }
  1504. } else { /* if (enabled) == false */
  1505. /* slapi_pblock_destroy(config[plugin_index].pb); */
  1506. /* This is freed in plugin_free_plugin_dep_config for us */
  1507. }
  1508. /* decrement the type counter for this plugin type */
  1509. decrement_plugin_type(plugin_head, config[plugin_index].type);
  1510. config[plugin_index].op_done = 1;
  1511. num_plg_started++;
  1512. plugins_started = 1;
  1513. }
  1514. }
  1515. }
  1516. if (plugins_started == 0) {
  1517. /* a dependency was not resolved - error */
  1518. slapi_log_err(SLAPI_LOG_ERR, "plugin_dependency_startall", "Failed to resolve plugin dependencies\n");
  1519. /* list the plugins yet to perform op */
  1520. i = 0;
  1521. while (i < total_plugins) {
  1522. if (config[i].op_done == 0) {
  1523. slapi_log_err(SLAPI_LOG_ERR, "plugin_dependency_startall", "%s plugin %s is not started\n",
  1524. config[i].type, config[i].name);
  1525. }
  1526. i++;
  1527. }
  1528. plugin_closeall(1 /* Close Backends */, 1 /* Close Globals */);
  1529. exit(1);
  1530. }
  1531. /*
  1532. * need the details in config to hang around for shutdown
  1533. * config itself may be deleted since its contents have been
  1534. * copied by value to the shutdown list
  1535. */
  1536. plugin_free_plugin_dep_config(&config);
  1537. if (plugin_head) {
  1538. plugin_dep_type next;
  1539. while (plugin_head) {
  1540. next = plugin_head->next;
  1541. slapi_ch_free_string(&plugin_head->type);
  1542. slapi_ch_free((void *)&plugin_head);
  1543. plugin_head = next;
  1544. }
  1545. }
  1546. /* Finally enable registered plugin functions */
  1547. global_plugin_callbacks_enabled = 1;
  1548. return ret;
  1549. }
  1550. /*
  1551. * plugin_dependency_closeall
  1552. *
  1553. * uses the shutdown list created at startup to close
  1554. * plugins in the correct order
  1555. *
  1556. * For now this leaks the list and contents, but since
  1557. * it hangs around until shutdown anyway, we don't care
  1558. *
  1559. */
  1560. void
  1561. plugin_dependency_closeall(void)
  1562. {
  1563. Slapi_PBlock *pb;
  1564. int plugins_closed = 0;
  1565. int index = 0;
  1566. while (plugins_closed < global_plugins_started) {
  1567. /*
  1568. * the first few entries may not be valid
  1569. * since the list was created in the reverse
  1570. * order and some plugins may have been counted
  1571. * for the purpose of list allocation but are
  1572. * disabled and so were never started
  1573. *
  1574. * we check that here
  1575. */
  1576. if (global_plugin_shutdown_order[index].name) {
  1577. if (!global_plugin_shutdown_order[index].removed) {
  1578. pb = slapi_pblock_new();
  1579. plugin_set_stopped(global_plugin_shutdown_order[index].plugin);
  1580. plugin_op_all_finished(global_plugin_shutdown_order[index].plugin);
  1581. plugin_call_one(global_plugin_shutdown_order[index].plugin, SLAPI_PLUGIN_CLOSE_FN, pb);
  1582. /* set plg_closed to 1 to prevent any further plugin pre/post op function calls */
  1583. global_plugin_shutdown_order[index].plugin->plg_closed = 1;
  1584. slapi_pblock_destroy(pb);
  1585. }
  1586. plugins_closed++;
  1587. }
  1588. index++;
  1589. }
  1590. }
  1591. void
  1592. plugin_freeall(void)
  1593. {
  1594. struct slapdplugin *plugin = NULL;
  1595. struct slapdplugin *plugin_next = NULL;
  1596. int type = 0;
  1597. /* look everywhere for other plugin functions with the plugin id */
  1598. for (type = 0; type < PLUGIN_LIST_GLOBAL_MAX; type++) {
  1599. plugin = global_plugin_list[type];
  1600. while (plugin) {
  1601. plugin_next = plugin->plg_next;
  1602. plugin_free(plugin);
  1603. plugin = plugin_next;
  1604. }
  1605. }
  1606. }
  1607. /*
  1608. * Function: plugin_dependency_freeall
  1609. *
  1610. * Description: Free the plugin dependency list.
  1611. * It need to be called after be_cleanupall so that the
  1612. * ldbm_database plugin is not freed when be_cleanupall calls the cleanup
  1613. * callback of the backend
  1614. */
  1615. void
  1616. plugin_dependency_freeall()
  1617. {
  1618. entry_and_plugin_t *iterp, *nextp;
  1619. char *value;
  1620. /* free the plugin dependency entry list */
  1621. iterp = dep_plugin_entries;
  1622. while (iterp) {
  1623. nextp = iterp->next;
  1624. if ((value = (char *)slapi_entry_attr_get_ref(iterp->e, ATTR_PLUGIN_ENABLED)) &&
  1625. !strcasecmp(value, "off")) {
  1626. plugin_free(iterp->plugin);
  1627. }
  1628. slapi_entry_free(iterp->e);
  1629. slapi_ch_free((void **)&iterp);
  1630. iterp = nextp;
  1631. }
  1632. dep_plugin_entries = NULL;
  1633. plugin_freeall();
  1634. }
  1635. /***********************************************************
  1636. end of plugin dependency code
  1637. ************************************************************/
  1638. /*
  1639. * Function: plugin_startall
  1640. *
  1641. * Returns: squat
  1642. *
  1643. * Description: Some plugins may need to do some stuff after all the config
  1644. * stuff is done with. So this function goes through and starts all plugins
  1645. */
  1646. void
  1647. plugin_startall(int argc, char **argv, char **plugin_list)
  1648. {
  1649. /* initialize special plugin structures */
  1650. default_plugin_init();
  1651. plugin_dependency_startall(argc, argv, "plugin startup failed\n",
  1652. SLAPI_PLUGIN_START_FN, plugin_list);
  1653. }
  1654. /*
  1655. * Function: plugin_close_all
  1656. *
  1657. * Returns: squat
  1658. *
  1659. * Description: cleanup routine, allows plugins to kill threads, free memory started in start fn
  1660. *
  1661. */
  1662. void
  1663. plugin_closeall(int close_backends __attribute__((unused)), int close_globals __attribute__((unused)))
  1664. {
  1665. plugin_dependency_closeall();
  1666. }
  1667. static int
  1668. plugin_call_list(struct slapdplugin *list, int operation, Slapi_PBlock *pb)
  1669. {
  1670. return plugin_call_func(list, operation, pb, 0);
  1671. }
  1672. static int
  1673. plugin_call_one(struct slapdplugin *list, int operation, Slapi_PBlock *pb)
  1674. {
  1675. return plugin_call_func(list, operation, pb, 1);
  1676. }
  1677. /*
  1678. * Return codes:
  1679. * - For preoperation plugins, returns the return code passed back from the first
  1680. * plugin that fails, or zero if all plugins succeed.
  1681. * - For bepreop and bepostop plugins, returns a bitwise OR of the return codes
  1682. * returned by all the plugins called (there's only one bepreop and one bepostop
  1683. * in DS 5.0 anyway).
  1684. * - For postoperation plugins, returns 0.
  1685. */
  1686. static int
  1687. plugin_call_func(struct slapdplugin *list, int operation, Slapi_PBlock *pb, int call_one)
  1688. {
  1689. /* Invoke the operation on the plugins that are registered for the subtree effected by the operation. */
  1690. int rc;
  1691. int return_value = 0;
  1692. int count = 0;
  1693. for (; list != NULL; list = list->plg_next) {
  1694. IFP func = NULL;
  1695. slapi_pblock_set(pb, SLAPI_PLUGIN, list);
  1696. set_db_default_result_handlers(pb); /* JCM: What's this do? Is it needed here? */
  1697. if (slapi_pblock_get(pb, operation, &func) == 0 &&
  1698. func != NULL &&
  1699. plugin_invoke_plugin_pb(list, operation, pb) &&
  1700. list->plg_closed == 0) {
  1701. char *n = list->plg_name;
  1702. slapi_log_err(SLAPI_LOG_TRACE, "plugin_call_func",
  1703. "Calling plugin '%s' #%d type %d\n",
  1704. (n == NULL ? "noname" : n), count, operation);
  1705. /* counters_to_errors_log("before plugin call"); */
  1706. /*
  1707. * Only call the plugin function if:
  1708. *
  1709. * [1] The plugin is started, and we are NOT trying to restart it.
  1710. * [2] The plugin is started, and we are stopping it.
  1711. * [3] The plugin is stopped, and we are trying to start it.
  1712. *
  1713. * This frees up the plugins from having to check if the plugin is already started when
  1714. * calling the START and CLOSE functions - prevents double starts and stops.
  1715. */
  1716. slapi_plugin_op_started(list);
  1717. if (((SLAPI_PLUGIN_START_FN == operation && !list->plg_started) || /* Starting it up for the first time */
  1718. (SLAPI_PLUGIN_CLOSE_FN == operation && !list->plg_stopped) || /* Shutting down, plugin has been stopped */
  1719. (SLAPI_PLUGIN_START_FN != operation && list->plg_started)) && /* Started, and not trying to start again */
  1720. (rc = func(pb)) != 0) {
  1721. slapi_plugin_op_finished(list);
  1722. if (SLAPI_PLUGIN_PREOPERATION == list->plg_type ||
  1723. SLAPI_PLUGIN_INTERNAL_PREOPERATION == list->plg_type ||
  1724. SLAPI_PLUGIN_START_FN == operation) {
  1725. /*
  1726. * We bail out of plugin processing for preop plugins
  1727. * that return a non-zero return code. This allows preop
  1728. * plugins to cause further preop processing to terminate, and
  1729. * causes the operation to be vetoed.
  1730. */
  1731. return_value = rc;
  1732. break;
  1733. } else if (SLAPI_PLUGIN_BEPREOPERATION == list->plg_type ||
  1734. SLAPI_PLUGIN_BETXNPREOPERATION == list->plg_type ||
  1735. SLAPI_PLUGIN_BEPOSTOPERATION == list->plg_type ||
  1736. SLAPI_PLUGIN_BETXNPOSTOPERATION == list->plg_type) {
  1737. /*
  1738. * respect fatal error SLAPI_PLUGIN_FAILURE (-1);
  1739. * should not OR it.
  1740. */
  1741. if (SLAPI_PLUGIN_FAILURE == rc) {
  1742. return_value = rc;
  1743. } else if (SLAPI_PLUGIN_FAILURE != return_value) {
  1744. /* OR the result into the return value
  1745. * for be pre/postops */
  1746. return_value |= rc;
  1747. }
  1748. }
  1749. } else {
  1750. if (SLAPI_PLUGIN_CLOSE_FN == operation) {
  1751. /* successfully stopped the plugin */
  1752. list->plg_stopped = 1;
  1753. }
  1754. slapi_plugin_op_finished(list);
  1755. }
  1756. /* counters_to_errors_log("after plugin call"); */
  1757. }
  1758. count++;
  1759. if (call_one)
  1760. break;
  1761. }
  1762. return (return_value);
  1763. }
  1764. int
  1765. slapi_berval_cmp(const struct berval *L, const struct berval *R) /* JCM - This does not belong here. But, where should it go? */
  1766. {
  1767. int result = 0;
  1768. if (L == NULL && R != NULL) {
  1769. return 1;
  1770. } else if (L != NULL && R == NULL) {
  1771. return -1;
  1772. } else if (L == NULL && R == NULL) {
  1773. return 0;
  1774. }
  1775. if (L->bv_len < R->bv_len) {
  1776. result = memcmp(L->bv_val, R->bv_val, L->bv_len);
  1777. if (result == 0)
  1778. result = -1;
  1779. } else {
  1780. result = memcmp(L->bv_val, R->bv_val, R->bv_len);
  1781. if (result == 0 && (L->bv_len > R->bv_len))
  1782. result = 1;
  1783. }
  1784. return result;
  1785. }
  1786. static char **supported_saslmechanisms = NULL;
  1787. static Slapi_RWLock *supported_saslmechanisms_lock = NULL;
  1788. /*
  1789. * register a supported SASL mechanism so it will be returned as part of the
  1790. * root DSE.
  1791. */
  1792. void
  1793. slapi_register_supported_saslmechanism(char *mechanism)
  1794. {
  1795. if (mechanism != NULL) {
  1796. if (NULL == supported_saslmechanisms_lock) {
  1797. /* This is thread safe, as it gets executed by
  1798. * a single thread at init time (main->init_saslmechanisms) */
  1799. supported_saslmechanisms_lock = slapi_new_rwlock();
  1800. if (NULL == supported_saslmechanisms_lock) {
  1801. /* Out of resources */
  1802. slapi_log_err(SLAPI_LOG_ERR,
  1803. "slapi_register_supported_saslmechanism", "Failed to create lock.\n");
  1804. exit(1);
  1805. }
  1806. }
  1807. slapi_rwlock_wrlock(supported_saslmechanisms_lock);
  1808. charray_add(&supported_saslmechanisms, slapi_ch_strdup(mechanism));
  1809. slapi_rwlock_unlock(supported_saslmechanisms_lock);
  1810. }
  1811. }
  1812. /*
  1813. * return pointer to NULL-terminated array of supported SASL mechanisms.
  1814. * This function is not MTSafe and should be deprecated.
  1815. * slapi_get_supported_saslmechanisms_copy should be used instead.
  1816. */
  1817. char **
  1818. slapi_get_supported_saslmechanisms(void)
  1819. {
  1820. return (supported_saslmechanisms);
  1821. }
  1822. /*
  1823. * return pointer to NULL-terminated array of supported SASL mechanisms.
  1824. */
  1825. char **
  1826. slapi_get_supported_saslmechanisms_copy(void)
  1827. {
  1828. char **ret = NULL;
  1829. slapi_rwlock_rdlock(supported_saslmechanisms_lock);
  1830. ret = charray_dup(supported_saslmechanisms);
  1831. slapi_rwlock_unlock(supported_saslmechanisms_lock);
  1832. return (ret);
  1833. }
  1834. static char **supported_extended_ops = NULL;
  1835. static Slapi_RWLock *extended_ops_lock = NULL;
  1836. /*
  1837. * register all of the LDAPv3 extended operations we know about.
  1838. */
  1839. void
  1840. ldapi_init_extended_ops(void)
  1841. {
  1842. extended_ops_lock = slapi_new_rwlock();
  1843. if (NULL == extended_ops_lock) {
  1844. /* Out of resources */
  1845. slapi_log_err(SLAPI_LOG_ERR, "ldapi_init_extended_ops",
  1846. "Failed to create lock.\n");
  1847. exit(1);
  1848. }
  1849. slapi_rwlock_wrlock(extended_ops_lock);
  1850. charray_add(&supported_extended_ops,
  1851. slapi_ch_strdup(EXTOP_BULK_IMPORT_START_OID));
  1852. charray_add(&supported_extended_ops,
  1853. slapi_ch_strdup(EXTOP_BULK_IMPORT_DONE_OID));
  1854. /* add future supported extops here... */
  1855. slapi_rwlock_unlock(extended_ops_lock);
  1856. }
  1857. /*
  1858. * register an extended op. so it can be returned as part of the root DSE.
  1859. */
  1860. void
  1861. ldapi_register_extended_op(char **opoids)
  1862. {
  1863. int i;
  1864. slapi_rwlock_wrlock(extended_ops_lock);
  1865. for (i = 0; opoids != NULL && opoids[i] != NULL; ++i) {
  1866. if (!charray_inlist(supported_extended_ops, opoids[i])) {
  1867. charray_add(&supported_extended_ops, slapi_ch_strdup(opoids[i]));
  1868. }
  1869. }
  1870. slapi_rwlock_unlock(extended_ops_lock);
  1871. }
  1872. /*
  1873. * retrieve supported extended operation OIDs
  1874. * return 0 if successful and -1 if not.
  1875. * This function is not MTSafe and should be deprecated.
  1876. * slapi_get_supported_extended_ops_copy should be used instead.
  1877. */
  1878. char **
  1879. slapi_get_supported_extended_ops(void)
  1880. {
  1881. return (supported_extended_ops);
  1882. }
  1883. /*
  1884. * retrieve supported extended operation OIDs
  1885. * return 0 if successful and -1 if not.
  1886. */
  1887. char **
  1888. slapi_get_supported_extended_ops_copy(void)
  1889. {
  1890. char **ret = NULL;
  1891. slapi_rwlock_rdlock(extended_ops_lock);
  1892. ret = charray_dup(supported_extended_ops);
  1893. slapi_rwlock_unlock(extended_ops_lock);
  1894. return (ret);
  1895. }
  1896. /*
  1897. looks up the given string type to convert to the internal integral type; also
  1898. returns the plugin list associated with the plugin type
  1899. returns 0 upon success and non-zero upon failure
  1900. */
  1901. static int
  1902. plugin_get_type_and_list(
  1903. const char *plugintype,
  1904. int *type,
  1905. struct slapdplugin ***plugin_list)
  1906. {
  1907. int plugin_list_index = -1;
  1908. if (strcasecmp(plugintype, "database") == 0) {
  1909. *type = SLAPI_PLUGIN_DATABASE;
  1910. plugin_list_index = PLUGIN_LIST_DATABASE;
  1911. } else if (strcasecmp(plugintype, "extendedop") == 0) {
  1912. *type = SLAPI_PLUGIN_EXTENDEDOP;
  1913. plugin_list_index = PLUGIN_LIST_EXTENDED_OPERATION;
  1914. } else if (strcasecmp(plugintype, "preoperation") == 0) {
  1915. *type = SLAPI_PLUGIN_PREOPERATION;
  1916. plugin_list_index = PLUGIN_LIST_PREOPERATION;
  1917. } else if (strcasecmp(plugintype, "postoperation") == 0) {
  1918. *type = SLAPI_PLUGIN_POSTOPERATION;
  1919. plugin_list_index = PLUGIN_LIST_POSTOPERATION;
  1920. } else if (strcasecmp(plugintype, "matchingrule") == 0) {
  1921. *type = SLAPI_PLUGIN_MATCHINGRULE;
  1922. plugin_list_index = PLUGIN_LIST_MATCHINGRULE;
  1923. } else if (strcasecmp(plugintype, "syntax") == 0) {
  1924. *type = SLAPI_PLUGIN_SYNTAX;
  1925. plugin_list_index = PLUGIN_LIST_SYNTAX;
  1926. } else if (strcasecmp(plugintype, "accesscontrol") == 0) {
  1927. *type = SLAPI_PLUGIN_ACL;
  1928. plugin_list_index = PLUGIN_LIST_ACL;
  1929. } else if ( strcasecmp( plugintype, "mmr" ) == 0 ) {
  1930. *type = SLAPI_PLUGIN_MMR;
  1931. plugin_list_index = PLUGIN_LIST_MMR;
  1932. } else if (strcasecmp(plugintype, "bepreoperation") == 0) {
  1933. *type = SLAPI_PLUGIN_BEPREOPERATION;
  1934. plugin_list_index = PLUGIN_LIST_BEPREOPERATION;
  1935. } else if (strcasecmp(plugintype, "bepostoperation") == 0) {
  1936. *type = SLAPI_PLUGIN_BEPOSTOPERATION;
  1937. plugin_list_index = PLUGIN_LIST_BEPOSTOPERATION;
  1938. } else if (strcasecmp(plugintype, "betxnpreoperation") == 0) {
  1939. *type = SLAPI_PLUGIN_BETXNPREOPERATION;
  1940. plugin_list_index = PLUGIN_LIST_BETXNPREOPERATION;
  1941. } else if (strcasecmp(plugintype, "betxnpostoperation") == 0) {
  1942. *type = SLAPI_PLUGIN_BETXNPOSTOPERATION;
  1943. plugin_list_index = PLUGIN_LIST_BETXNPOSTOPERATION;
  1944. } else if (strcasecmp(plugintype, "internalpreoperation") == 0) {
  1945. *type = SLAPI_PLUGIN_INTERNAL_PREOPERATION;
  1946. plugin_list_index = PLUGIN_LIST_INTERNAL_PREOPERATION;
  1947. } else if (strcasecmp(plugintype, "internalpostoperation") == 0) {
  1948. *type = SLAPI_PLUGIN_INTERNAL_POSTOPERATION;
  1949. plugin_list_index = PLUGIN_LIST_INTERNAL_POSTOPERATION;
  1950. } else if (strcasecmp(plugintype, "entry") == 0) {
  1951. *type = SLAPI_PLUGIN_ENTRY;
  1952. plugin_list_index = PLUGIN_LIST_ENTRY;
  1953. } else if (strcasecmp(plugintype, "object") == 0) {
  1954. *type = SLAPI_PLUGIN_TYPE_OBJECT;
  1955. plugin_list_index = PLUGIN_LIST_OBJECT;
  1956. } else if (strcasecmp(plugintype, "pwdstoragescheme") == 0) {
  1957. *type = SLAPI_PLUGIN_PWD_STORAGE_SCHEME;
  1958. plugin_list_index = PLUGIN_LIST_PWD_STORAGE_SCHEME;
  1959. } else if (strcasecmp(plugintype, "reverpwdstoragescheme") == 0) {
  1960. *type = SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME;
  1961. plugin_list_index = PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME;
  1962. } else if (strcasecmp(plugintype, "vattrsp") == 0) {
  1963. *type = SLAPI_PLUGIN_VATTR_SP;
  1964. plugin_list_index = PLUGIN_LIST_VATTR_SP;
  1965. } else if (strcasecmp(plugintype, "ldbmentryfetchstore") == 0) {
  1966. *type = SLAPI_PLUGIN_LDBM_ENTRY_FETCH_STORE;
  1967. plugin_list_index = PLUGIN_LIST_LDBM_ENTRY_FETCH_STORE;
  1968. } else if (strcasecmp(plugintype, "index") == 0) {
  1969. *type = SLAPI_PLUGIN_INDEX;
  1970. plugin_list_index = PLUGIN_LIST_INDEX;
  1971. } else if (strcasecmp(plugintype, "betxnextendedop") == 0) {
  1972. *type = SLAPI_PLUGIN_BETXNEXTENDEDOP;
  1973. plugin_list_index = PLUGIN_LIST_BE_TXN_EXTENDED_OPERATION;
  1974. } else if (strcasecmp(plugintype, "preextendedop") == 0) {
  1975. *type = SLAPI_PLUGIN_PREEXTOPERATION;
  1976. plugin_list_index = PLUGIN_LIST_PREEXTENDED_OPERATION;
  1977. } else if (strcasecmp(plugintype, "postextendedop") == 0) {
  1978. *type = SLAPI_PLUGIN_POSTEXTOPERATION;
  1979. plugin_list_index = PLUGIN_LIST_POSTEXTENDED_OPERATION;
  1980. } else {
  1981. return (1); /* unknown plugin type - pass to backend */
  1982. }
  1983. if (plugin_list_index >= 0) {
  1984. *plugin_list = &global_plugin_list[plugin_list_index];
  1985. }
  1986. return 0;
  1987. }
  1988. static char *
  1989. plugin_get_type_str(int type)
  1990. {
  1991. if (type == SLAPI_PLUGIN_DATABASE) {
  1992. return "database";
  1993. } else if (type == SLAPI_PLUGIN_EXTENDEDOP) {
  1994. return "extendedop";
  1995. } else if (type == SLAPI_PLUGIN_PREOPERATION) {
  1996. return "preoperation";
  1997. } else if (type == SLAPI_PLUGIN_POSTOPERATION) {
  1998. return "postoperation";
  1999. } else if (type == SLAPI_PLUGIN_MATCHINGRULE) {
  2000. return "matchingrule";
  2001. } else if (type == SLAPI_PLUGIN_SYNTAX) {
  2002. return "syntax";
  2003. } else if (type == SLAPI_PLUGIN_ACL) {
  2004. return "accesscontrol";
  2005. } else if (type == SLAPI_PLUGIN_MMR){
  2006. return "mmr";
  2007. } else if (type == SLAPI_PLUGIN_BEPREOPERATION) {
  2008. return "bepreoperation";
  2009. } else if (type == SLAPI_PLUGIN_BEPOSTOPERATION) {
  2010. return "bepostoperation";
  2011. } else if (type == SLAPI_PLUGIN_BETXNPREOPERATION) {
  2012. return "betxnpreoperation";
  2013. } else if (type == SLAPI_PLUGIN_BETXNPOSTOPERATION) {
  2014. return "betxnpostoperation";
  2015. } else if (type == SLAPI_PLUGIN_INTERNAL_PREOPERATION) {
  2016. return "internalpreoperation";
  2017. } else if (type == SLAPI_PLUGIN_INTERNAL_POSTOPERATION) {
  2018. return "internalpostoperation";
  2019. } else if (type == SLAPI_PLUGIN_ENTRY) {
  2020. return "entry";
  2021. } else if (type == SLAPI_PLUGIN_TYPE_OBJECT) {
  2022. return "object";
  2023. } else if (type == SLAPI_PLUGIN_PWD_STORAGE_SCHEME) {
  2024. return "pwdstoragescheme";
  2025. } else if (type == SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME) {
  2026. return "reverpwdstoragescheme";
  2027. } else if (type == SLAPI_PLUGIN_VATTR_SP) {
  2028. return "vattrsp";
  2029. } else if (type == SLAPI_PLUGIN_LDBM_ENTRY_FETCH_STORE) {
  2030. return "ldbmentryfetchstore";
  2031. } else if (type == SLAPI_PLUGIN_INDEX) {
  2032. return "index";
  2033. } else {
  2034. return NULL; /* unknown plugin type - pass to backend */
  2035. }
  2036. }
  2037. static const char *
  2038. plugin_exists(const Slapi_DN *plugin_dn)
  2039. {
  2040. /* check to see if the plugin name is unique */
  2041. const char *retval = 0;
  2042. if (global_plugin_dns && PL_HashTableLookup(global_plugin_dns,
  2043. slapi_sdn_get_ndn(plugin_dn))) {
  2044. retval = slapi_sdn_get_dn(plugin_dn);
  2045. }
  2046. return retval;
  2047. }
  2048. /*
  2049. * A plugin config change has occurred, restart the plugin (delete/add).
  2050. * If something goes wrong, revert to the original plugin entry.
  2051. */
  2052. int
  2053. plugin_restart(Slapi_Entry *pentryBefore, Slapi_Entry *pentryAfter)
  2054. {
  2055. char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
  2056. int rc = LDAP_SUCCESS;
  2057. /*
  2058. * We can not restart a critical plugin, but the operation should still
  2059. * be allowed
  2060. */
  2061. if (plugin_is_critical(pentryBefore)) {
  2062. slapi_log_err(SLAPI_LOG_ERR, "plugin_restart",
  2063. "Plugin (%s) is critical to server operation. "
  2064. "Server requires restart for changes to take effect.\n",
  2065. slapi_entry_get_dn(pentryBefore));
  2066. return 0;
  2067. }
  2068. slapi_rwlock_wrlock(global_rwlock);
  2069. slapi_td_set_plugin_locked();
  2070. if (plugin_delete(pentryBefore, returntext, 1) == LDAP_SUCCESS) {
  2071. if (plugin_add(pentryAfter, returntext, 1) == LDAP_SUCCESS) {
  2072. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_restart",
  2073. "Plugin (%s) has been successfully restarted after configuration change.\n",
  2074. slapi_entry_get_dn(pentryAfter));
  2075. } else {
  2076. slapi_log_err(SLAPI_LOG_ERR, "plugin_restart",
  2077. "Plugin (%s) failed to restart after configuration change (%s). "
  2078. "Reverting to original plugin entry.\n",
  2079. slapi_entry_get_dn(pentryAfter), returntext);
  2080. if (plugin_add(pentryBefore, returntext, 1) != LDAP_SUCCESS) {
  2081. slapi_log_err(SLAPI_LOG_ERR, "plugin_restart",
  2082. "Plugin (%s) failed to reload original plugin (%s)\n",
  2083. slapi_entry_get_dn(pentryBefore), returntext);
  2084. }
  2085. rc = 1;
  2086. }
  2087. } else {
  2088. slapi_log_err(SLAPI_LOG_ERR, "plugin_restart",
  2089. "Failed to disable/stop the plugin (%s): %s\n",
  2090. slapi_entry_get_dn(pentryBefore), returntext);
  2091. rc = 1;
  2092. }
  2093. slapi_rwlock_unlock(global_rwlock);
  2094. slapi_td_set_plugin_unlocked();
  2095. return rc;
  2096. }
  2097. static int
  2098. plugin_set_subtree_config(PluginTargetData *subtree_config, const char *val)
  2099. {
  2100. int status = 0;
  2101. if (strcasecmp(val, ALL_DATA) == 0) /* allow access to both local and remote data */
  2102. {
  2103. plugin_set_global(subtree_config);
  2104. } else if (strcasecmp(val, LOCAL_DATA) == 0) /* allow access to all locally hosted data */
  2105. {
  2106. ptd_set_special_data(subtree_config, PLGC_DATA_LOCAL);
  2107. } else if (strcasecmp(val, REMOTE_DATA) == 0) /* allow access to requests for remote data */
  2108. {
  2109. ptd_set_special_data(subtree_config, PLGC_DATA_REMOTE);
  2110. } else /* dn */
  2111. {
  2112. ptd_add_subtree(subtree_config, slapi_sdn_new_dn_byval(val));
  2113. }
  2114. /* I suppose we could check the val at this point to make sure
  2115. its a valid DN . . . */
  2116. return status;
  2117. }
  2118. static int
  2119. set_plugin_config_from_entry(
  2120. const Slapi_Entry *plugin_entry,
  2121. struct slapdplugin *plugin)
  2122. {
  2123. struct pluginconfig *config = &plugin->plg_conf;
  2124. char *value = 0;
  2125. char **values = 0;
  2126. int i = 0;
  2127. int status = 0;
  2128. PRBool target_seen = PR_FALSE;
  2129. PRBool bind_seen = PR_FALSE;
  2130. if ((value = (char *)slapi_entry_attr_get_ref((Slapi_Entry *)plugin_entry, ATTR_PLUGIN_SCHEMA_CHECK)) != NULL) {
  2131. if (plugin_config_set_action(&config->plgc_schema_check, value)) {
  2132. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2133. "Invalid value %s for attribute %s from entry %s\n",
  2134. value, ATTR_PLUGIN_SCHEMA_CHECK, slapi_entry_get_dn_const(plugin_entry));
  2135. status = 1;
  2136. }
  2137. }
  2138. if ((value = (char *)slapi_entry_attr_get_ref((Slapi_Entry *)plugin_entry, ATTR_PLUGIN_LOG_ACCESS)) != NULL) {
  2139. if (plugin_config_set_action(&config->plgc_log_access, value)) {
  2140. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2141. "Invalid value %s for attribute %s from entry %s\n",
  2142. value, ATTR_PLUGIN_LOG_ACCESS, slapi_entry_get_dn_const(plugin_entry));
  2143. status = 1;
  2144. }
  2145. }
  2146. if ((value = (char *)slapi_entry_attr_get_ref((Slapi_Entry *)plugin_entry, ATTR_PLUGIN_LOG_AUDIT)) != NULL) {
  2147. if (plugin_config_set_action(&config->plgc_log_audit, value)) {
  2148. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2149. "Invalid value %s for attribute %s from entry %s\n",
  2150. value, ATTR_PLUGIN_LOG_AUDIT, slapi_entry_get_dn_const(plugin_entry));
  2151. status = 1;
  2152. }
  2153. }
  2154. if ((value = (char *)slapi_entry_attr_get_ref((Slapi_Entry *)plugin_entry, ATTR_PLUGIN_INVOKE_FOR_REPLOP)) != NULL) {
  2155. if (plugin_config_set_action(&config->plgc_invoke_for_replop, value)) {
  2156. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2157. "Invalid value %s for attribute %s from entry %s\n",
  2158. value, ATTR_PLUGIN_INVOKE_FOR_REPLOP,
  2159. slapi_entry_get_dn_const(plugin_entry));
  2160. status = 1;
  2161. }
  2162. }
  2163. values = slapi_entry_attr_get_charray(plugin_entry,
  2164. ATTR_PLUGIN_TARGET_SUBTREE);
  2165. for (i = 0; values && values[i]; i++) {
  2166. if (plugin_set_subtree_config(&(config->plgc_target_subtrees), values[i])) {
  2167. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2168. "Invalid value %s for attribute %s from entry %s\n",
  2169. values[i], ATTR_PLUGIN_TARGET_SUBTREE,
  2170. slapi_entry_get_dn_const(plugin_entry));
  2171. status = 1;
  2172. break;
  2173. } else {
  2174. target_seen = PR_TRUE;
  2175. }
  2176. }
  2177. slapi_ch_array_free(values);
  2178. values = slapi_entry_attr_get_charray(plugin_entry,
  2179. ATTR_PLUGIN_EXCLUDE_TARGET_SUBTREE);
  2180. for (i = 0; values && values[i]; i++) {
  2181. if (plugin_set_subtree_config(&(config->plgc_excluded_target_subtrees), values[i])) {
  2182. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2183. "Invalid value %s for attribute %s from entry %s\n",
  2184. values[i], ATTR_PLUGIN_EXCLUDE_TARGET_SUBTREE,
  2185. slapi_entry_get_dn_const(plugin_entry));
  2186. status = 1;
  2187. break;
  2188. }
  2189. }
  2190. slapi_ch_array_free(values);
  2191. values = slapi_entry_attr_get_charray(plugin_entry,
  2192. ATTR_PLUGIN_BIND_SUBTREE);
  2193. for (i = 0; values && values[i]; i++) {
  2194. if (plugin_set_subtree_config(&(config->plgc_bind_subtrees), values[i])) {
  2195. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2196. "Invalid value %s for attribute %s from entry %s\n",
  2197. values[i], ATTR_PLUGIN_BIND_SUBTREE,
  2198. slapi_entry_get_dn_const(plugin_entry));
  2199. status = 1;
  2200. break;
  2201. } else {
  2202. bind_seen = PR_TRUE;
  2203. }
  2204. }
  2205. slapi_ch_array_free(values);
  2206. values = slapi_entry_attr_get_charray(plugin_entry,
  2207. ATTR_PLUGIN_EXCLUDE_BIND_SUBTREE);
  2208. for (i = 0; values && values[i]; i++) {
  2209. if (plugin_set_subtree_config(&(config->plgc_excluded_bind_subtrees), values[i])) {
  2210. slapi_log_err(SLAPI_LOG_PLUGIN, "set_plugin_config_from_entry",
  2211. "Invalid value %s for attribute %s from entry %s\n",
  2212. values[i], ATTR_PLUGIN_EXCLUDE_BIND_SUBTREE,
  2213. slapi_entry_get_dn_const(plugin_entry));
  2214. status = 1;
  2215. break;
  2216. }
  2217. }
  2218. slapi_ch_array_free(values);
  2219. /* set target subtree default - allow access to all data */
  2220. if (!target_seen) {
  2221. plugin_set_global(&(config->plgc_target_subtrees));
  2222. }
  2223. /* set bind subtree default - allow access to local data only */
  2224. if (!bind_seen) {
  2225. ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_LOCAL);
  2226. ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_REMOTE);
  2227. }
  2228. return status;
  2229. }
  2230. /* This function is called after the plugin init function has been called
  2231. which fills in the desc part of the plugin
  2232. */
  2233. static int
  2234. add_plugin_description(Slapi_Entry *e, const char *attrname, char *val)
  2235. {
  2236. struct berval desc;
  2237. struct berval *newval[2] = {0, 0};
  2238. int status = 0;
  2239. desc.bv_val = SLAPI_PLUGIN_NONE_IF_NULL(val);
  2240. desc.bv_len = strlen(desc.bv_val);
  2241. newval[0] = &desc;
  2242. if ((status = entry_replace_values(e, attrname, newval)) != 0) {
  2243. slapi_log_err(SLAPI_LOG_PLUGIN, "add_plugin_description",
  2244. "Error: failed to add value %s to attribute %s of entry %s\n",
  2245. val, attrname, slapi_entry_get_dn_const(e));
  2246. status = 1;
  2247. }
  2248. return status;
  2249. }
  2250. /*
  2251. * The plugin initfunc sets some vendor and version information in the plugin.
  2252. * This function extracts that and adds it as attributes to `e'. If
  2253. * `plugin' is NULL, the plugin is located based on the DN in `e'.
  2254. *
  2255. * Returns 0 if all goes well and 1 if not.
  2256. */
  2257. int
  2258. plugin_add_descriptive_attributes(Slapi_Entry *e, struct slapdplugin *plugin)
  2259. {
  2260. int status = 0;
  2261. if (NULL == plugin) {
  2262. int i;
  2263. const Slapi_DN *ednp = slapi_entry_get_sdn_const(e);
  2264. Slapi_DN pdn;
  2265. struct slapdplugin *plugtmp;
  2266. for (i = 0; NULL == plugin && i < PLUGIN_LIST_GLOBAL_MAX; ++i) {
  2267. for (plugtmp = global_plugin_list[i]; NULL == plugin && plugtmp;
  2268. plugtmp = plugtmp->plg_next) {
  2269. slapi_sdn_init_normdn_byref(&pdn, plugtmp->plg_dn);
  2270. if (0 == slapi_sdn_compare(&pdn, ednp)) {
  2271. plugin = plugtmp;
  2272. }
  2273. slapi_sdn_done(&pdn);
  2274. }
  2275. }
  2276. if (NULL == plugin) {
  2277. /* This can happen for things such as disabled syntax plug-ins. We
  2278. * just treat this as a warning to allow the description attributes
  2279. * to be set to a default value to avoid an objectclass violation. */
  2280. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_add_descriptive_attributes",
  2281. "Couldn't find plugin %s in global list. "
  2282. "Adding default descriptive values.\n",
  2283. slapi_entry_get_dn_const(e));
  2284. }
  2285. }
  2286. if (add_plugin_description(e, ATTR_PLUGIN_PLUGINID,
  2287. plugin ? plugin->plg_desc.spd_id : NULL)) {
  2288. status = 1;
  2289. }
  2290. if (add_plugin_description(e, ATTR_PLUGIN_VERSION,
  2291. plugin ? plugin->plg_desc.spd_version : NULL)) {
  2292. status = 1;
  2293. }
  2294. if (add_plugin_description(e, ATTR_PLUGIN_VENDOR,
  2295. plugin ? plugin->plg_desc.spd_vendor : NULL)) {
  2296. status = 1;
  2297. }
  2298. if (add_plugin_description(e, ATTR_PLUGIN_DESC,
  2299. plugin ? plugin->plg_desc.spd_description : NULL)) {
  2300. status = 1;
  2301. }
  2302. return status;
  2303. }
  2304. /*
  2305. clean up the memory associated with the plugin
  2306. */
  2307. static void
  2308. plugin_free(struct slapdplugin *plugin)
  2309. {
  2310. slapi_log_err(SLAPI_LOG_TRACE, "plugin_free", "Freeing %s \n", plugin->plg_name);
  2311. charray_free(plugin->plg_argv);
  2312. slapi_ch_free_string(&plugin->plg_libpath);
  2313. slapi_ch_free_string(&plugin->plg_initfunc);
  2314. slapi_ch_free_string(&plugin->plg_name);
  2315. slapi_ch_free_string(&plugin->plg_dn);
  2316. if (plugin->plg_type == SLAPI_PLUGIN_PWD_STORAGE_SCHEME || plugin->plg_type == SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME) {
  2317. slapi_ch_free_string(&plugin->plg_pwdstorageschemename);
  2318. }
  2319. if (plugin->plg_type == SLAPI_PLUGIN_SYNTAX) {
  2320. slapi_ch_free_string(&plugin->plg_syntax_oid);
  2321. slapi_ch_array_free(plugin->plg_syntax_names);
  2322. }
  2323. if (plugin->plg_type == SLAPI_PLUGIN_MATCHINGRULE) {
  2324. slapi_ch_array_free(plugin->plg_mr_names);
  2325. }
  2326. release_componentid(plugin->plg_identity);
  2327. slapi_counter_destroy(&plugin->plg_op_counter);
  2328. if (!plugin->plg_group) {
  2329. plugin_config_cleanup(&plugin->plg_conf);
  2330. }
  2331. slapi_ch_free((void **)&plugin);
  2332. }
  2333. /***********************************
  2334. This is the main entry point for plugin configuration. The plugin_entry argument
  2335. should already contain the necessary fields required to initialize the plugin and
  2336. to give it a proper name in the plugin configuration DIT.
  2337. Argument:
  2338. Slapi_Entry *plugin_entry - the required attributes are
  2339. dn: the dn of the plugin entry
  2340. cn: the unique name of the plugin
  2341. nsslapd-pluginType: one of the several recognized plugin types e.g. "postoperation"
  2342. if p_initfunc is given, pluginPath and pluginInitFunc are optional
  2343. nsslapd-pluginPath: full path and file name of the dll implementing the plugin
  2344. nsslapd-pluginInitFunc: the name of the plugin initialization function
  2345. the optional attributes are:
  2346. nsslapd-pluginArg0
  2347. ...
  2348. nsslapd-pluginArg[N-1] - the (old style) arguments to the plugin, where N varies
  2349. from 0 to the number of arguments. The numbers must be consecutive i.e. no
  2350. skipping
  2351. Instead of using nsslapd-pluginArgN, it is encouraged for you to use named
  2352. parameters e.g.
  2353. nsslapd-tweakThis: 1
  2354. nsslapd-tweakThat: 2
  2355. etc.
  2356. nsslapd-pluginEnabled: "on"|"off" - by default, the plugin will be enabled unless
  2357. this attribute is present and has the value "off"
  2358. for other known attributes, see set_plugin_config_from_entry() above
  2359. all other attributes will be ignored
  2360. The reason this parameter is not const is because it may be modified. This
  2361. function will modify it if the plugin init function is called successfully
  2362. to add the description attributes, and the plugin init function may modify
  2363. it as well.
  2364. Argument:
  2365. group - the group to which this plugin will belong - each member of a plugin group
  2366. shares the pluginconfig of the group leader; refer to the function plugin_get_config
  2367. for more information
  2368. Argument:
  2369. add_entry - if true, the entry will be added to the DIT using the given
  2370. DN in the plugin_entry - this is the default behavior; if false, the
  2371. plugin entry will not show up in the DIT
  2372. ************************************/
  2373. int
  2374. plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid *group, slapi_plugin_init_fnptr p_initfunc, int add_entry, char *returntext)
  2375. {
  2376. int ii = 0;
  2377. char attrname[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  2378. char *value = NULL;
  2379. char **values = NULL;
  2380. struct slapdplugin *plugin = NULL;
  2381. struct slapdplugin **plugin_list = NULL;
  2382. struct slapi_componentid *cid = NULL;
  2383. const char *existname = 0;
  2384. slapi_plugin_init_fnptr initfunc = p_initfunc;
  2385. Slapi_PBlock *pb = NULL;
  2386. int status = 0;
  2387. int enabled = 1;
  2388. char *configdir = 0;
  2389. int skipped;
  2390. attrname[0] = '\0';
  2391. if (!slapi_entry_get_sdn_const(plugin_entry)) {
  2392. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "DN is missing from the plugin.\n");
  2393. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin is missing dn.");
  2394. return -1;
  2395. }
  2396. if ((existname = plugin_exists(slapi_entry_get_sdn_const(plugin_entry))) != NULL) {
  2397. slapi_log_err(SLAPI_LOG_TRACE, "plugin_setup", "The plugin named %s already exists, "
  2398. "or is already setup.\n",
  2399. existname);
  2400. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  2401. "the plugin named %s already exists, or is already setup.", existname);
  2402. return 1;
  2403. }
  2404. /*
  2405. * create a new plugin structure, fill it in, and prepare to
  2406. * call the plugin's init function. the init function will
  2407. * set the plugin function pointers.
  2408. */
  2409. plugin = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin));
  2410. plugin->plg_dn = slapi_ch_strdup(slapi_entry_get_ndn(plugin_entry));
  2411. plugin->plg_closed = 0;
  2412. if (!(value = (char *)slapi_entry_attr_get_ref(plugin_entry, ATTR_PLUGIN_TYPE))) {
  2413. /* error: required attribute %s missing */
  2414. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Required attribute %s is missing from entry \"%s\"\n",
  2415. ATTR_PLUGIN_TYPE, slapi_entry_get_dn_const(plugin_entry));
  2416. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Required attribute %s is missing from entry",
  2417. ATTR_PLUGIN_TYPE);
  2418. status = -1;
  2419. goto PLUGIN_CLEANUP;
  2420. } else {
  2421. status = plugin_get_type_and_list(value, &plugin->plg_type,
  2422. &plugin_list);
  2423. if (status != 0) {
  2424. /* error: unknown plugin type */
  2425. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Unknown plugin type \"%s\" in entry \"%s\"\n",
  2426. value, slapi_entry_get_dn_const(plugin_entry));
  2427. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Unknown plugin type \"%s\" in entry", value);
  2428. status = -1;
  2429. goto PLUGIN_CLEANUP;
  2430. }
  2431. }
  2432. if (!status &&
  2433. !(value = (char *)slapi_entry_attr_get_ref(plugin_entry, "cn"))) {
  2434. /* error: required attribute %s missing */
  2435. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Required attribute %s is missing from entry \"%s\"\n",
  2436. "cn", slapi_entry_get_dn_const(plugin_entry));
  2437. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Required attribute \"cn\" is missing from entry");
  2438. status = -1;
  2439. goto PLUGIN_CLEANUP;
  2440. } else {
  2441. /* plg_name is normalized once here */
  2442. plugin->plg_name = slapi_create_rdn_value("%s", value);
  2443. }
  2444. if (!(value = (char *)slapi_entry_attr_get_ref(plugin_entry, ATTR_PLUGIN_PRECEDENCE))) {
  2445. /* A precedence isn't set, so just use the default. */
  2446. plugin->plg_precedence = PLUGIN_DEFAULT_PRECEDENCE;
  2447. } else {
  2448. /* A precedence was set, so let's make sure it's valid. */
  2449. int precedence = 0;
  2450. char *endptr = NULL;
  2451. /* Convert the value. */
  2452. precedence = strtol(value, &endptr, 10);
  2453. /* Make sure the precedence is within our valid
  2454. * range and that we had no conversion errors. */
  2455. if ((*value == '\0') || (*endptr != '\0') ||
  2456. (precedence < PLUGIN_MIN_PRECEDENCE) || (precedence > PLUGIN_MAX_PRECEDENCE)) {
  2457. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Value for attribute %s must be "
  2458. "an integer between %d and %d\n",
  2459. ATTR_PLUGIN_PRECEDENCE,
  2460. PLUGIN_MIN_PRECEDENCE, PLUGIN_MAX_PRECEDENCE);
  2461. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Value for attribute %s must be "
  2462. "an integer between %d and %d.",
  2463. ATTR_PLUGIN_PRECEDENCE,
  2464. PLUGIN_MIN_PRECEDENCE, PLUGIN_MAX_PRECEDENCE);
  2465. status = -1;
  2466. goto PLUGIN_CLEANUP;
  2467. } else {
  2468. plugin->plg_precedence = precedence;
  2469. }
  2470. }
  2471. if (!(value = slapi_entry_attr_get_charptr(plugin_entry, ATTR_PLUGIN_INITFN))) {
  2472. if (!initfunc) {
  2473. /* error: required attribute %s missing */
  2474. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Required attribute %s is missing from entry \"%s\"\n",
  2475. ATTR_PLUGIN_INITFN, slapi_entry_get_dn_const(plugin_entry));
  2476. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Required attribute %s is missing from entry.",
  2477. ATTR_PLUGIN_INITFN);
  2478. status = -1;
  2479. goto PLUGIN_CLEANUP;
  2480. }
  2481. } else {
  2482. plugin->plg_initfunc = value; /* plugin owns value's memory now, don't free */
  2483. }
  2484. if (!initfunc) {
  2485. PRBool loadNow = PR_FALSE;
  2486. PRBool loadGlobal = PR_FALSE;
  2487. if (!(value = slapi_entry_attr_get_charptr(plugin_entry,
  2488. ATTR_PLUGIN_PATH))) {
  2489. /* error: required attribute %s missing */
  2490. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Required attribute %s is missing from entry \"%s\"\n",
  2491. ATTR_PLUGIN_PATH, slapi_entry_get_dn_const(plugin_entry));
  2492. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Required attribute %s is missing from entry.",
  2493. ATTR_PLUGIN_PATH);
  2494. status = -1;
  2495. goto PLUGIN_CLEANUP;
  2496. } else {
  2497. plugin->plg_libpath = value; /* plugin owns value's memory now, don't free */
  2498. }
  2499. loadNow = slapi_entry_attr_get_bool(plugin_entry, ATTR_PLUGIN_LOAD_NOW);
  2500. loadGlobal = slapi_entry_attr_get_bool(plugin_entry, ATTR_PLUGIN_LOAD_GLOBAL);
  2501. /*
  2502. * load the plugin's init function
  2503. */
  2504. if ((initfunc = (slapi_plugin_init_fnptr)sym_load_with_flags(plugin->plg_libpath,
  2505. plugin->plg_initfunc, plugin->plg_name, 1 /* report errors */,
  2506. loadNow, loadGlobal)) == NULL) {
  2507. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Failed to load plugin's init function.");
  2508. status = -1;
  2509. goto PLUGIN_CLEANUP;
  2510. }
  2511. }
  2512. if (!status && group) /* uses group's config; see plugin_get_config */
  2513. {
  2514. struct slapi_componentid *cid = (struct slapi_componentid *)group;
  2515. plugin->plg_group = (struct slapdplugin *)cid->sci_plugin;
  2516. } else if (!status) /* using own config */
  2517. {
  2518. plugin_config_init(&(plugin->plg_conf));
  2519. set_plugin_config_from_entry(plugin_entry, plugin);
  2520. }
  2521. /*
  2522. * If this is a registered plugin function, then set the plugin id so we can remove
  2523. * this plugin later if needed.
  2524. */
  2525. if (group) {
  2526. plugin->plg_id = group->sci_component_name;
  2527. }
  2528. /* add the plugin arguments */
  2529. value = 0;
  2530. ii = 0;
  2531. PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ii);
  2532. skipped = 0;
  2533. #define MAXSKIPPED 10 /* Max allowed missing args */
  2534. do {
  2535. /*
  2536. * nsslapd-pluginarg0: val0
  2537. * nsslapd-pluginarg0: val00
  2538. * nsslapd-pluginarg2: val2
  2539. * nsslapd-pluginarg5: val5
  2540. * ==>
  2541. * treated as
  2542. * nsslapd-pluginarg0: val0
  2543. * nsslapd-pluginarg1: val00
  2544. * nsslapd-pluginarg2: val2
  2545. * nsslapd-pluginarg3: val5
  2546. */
  2547. char **vp = values = slapi_entry_attr_get_charray(plugin_entry, attrname);
  2548. if (values) {
  2549. charray_add(&plugin->plg_argv, slapi_ch_strdup(*vp));
  2550. plugin->plg_argc++;
  2551. for (vp++; vp && *vp; vp++) {
  2552. charray_add(&plugin->plg_argv, slapi_ch_strdup(*vp));
  2553. plugin->plg_argc++;
  2554. }
  2555. charray_free(values);
  2556. } else {
  2557. skipped++;
  2558. }
  2559. PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ++ii);
  2560. } while (skipped < MAXSKIPPED);
  2561. pb = slapi_pblock_new();
  2562. slapi_pblock_set(pb, SLAPI_PLUGIN, plugin);
  2563. slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, (void *)SLAPI_PLUGIN_CURRENT_VERSION);
  2564. cid = generate_componentid(plugin, NULL);
  2565. /* We take a copy of the pointer to this so we can free it correctly. */
  2566. plugin->plg_identity = cid;
  2567. slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, (void *)cid);
  2568. configdir = config_get_configdir();
  2569. slapi_pblock_set(pb, SLAPI_CONFIG_DIRECTORY, configdir);
  2570. /* see if the plugin is enabled or not */
  2571. if ((value = (char *)slapi_entry_attr_get_ref(plugin_entry, ATTR_PLUGIN_ENABLED)) &&
  2572. !strcasecmp(value, "off")) {
  2573. enabled = 0;
  2574. } else {
  2575. enabled = 1;
  2576. }
  2577. slapi_pblock_set(pb, SLAPI_PLUGIN_ENABLED, &enabled);
  2578. slapi_pblock_set(pb, SLAPI_PLUGIN_CONFIG_ENTRY, plugin_entry);
  2579. plugin->plg_op_counter = slapi_counter_new();
  2580. if (enabled && (*initfunc)(pb) != 0) {
  2581. slapi_log_err(SLAPI_LOG_ERR, "plugin_setup", "Init function \"%s\" for \"%s\" plugin in library \"%s\" failed\n",
  2582. plugin->plg_initfunc, plugin->plg_name, plugin->plg_libpath);
  2583. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Init function \"%s\" for \"%s\" plugin in "
  2584. "library \"%s\" failed.",
  2585. plugin->plg_initfunc, plugin->plg_name, plugin->plg_libpath);
  2586. status = -1;
  2587. /*
  2588. * The init function might have added the plugin to the global list before
  2589. * it failed - attempt to remove it just in case it was added.
  2590. */
  2591. plugin_remove_plugins(plugin, value);
  2592. goto PLUGIN_CLEANUP;
  2593. }
  2594. if (!status) {
  2595. if (plugin_add_descriptive_attributes(plugin_entry, plugin) != 0) {
  2596. status = -1;
  2597. }
  2598. }
  2599. if (enabled) {
  2600. /* don't use raw pointer from plugin_entry because it
  2601. will be freed later by the caller */
  2602. Slapi_DN *dn_copy = slapi_sdn_dup(slapi_entry_get_sdn_const(plugin_entry));
  2603. add_plugin_to_list(plugin_list, plugin);
  2604. add_plugin_entry_dn(dn_copy);
  2605. }
  2606. if (add_entry) {
  2607. /* make a copy of the plugin entry for our own use because it will
  2608. be freed later by the caller */
  2609. Slapi_Entry *e_copy = slapi_entry_dup(plugin_entry);
  2610. /* new_plugin_entry(&plugin_entries, plugin_entry, plugin); */
  2611. new_plugin_entry(&dep_plugin_entries, e_copy, plugin);
  2612. }
  2613. PLUGIN_CLEANUP:
  2614. if (status) {
  2615. plugin_free(plugin);
  2616. }
  2617. slapi_ch_free((void **)&configdir);
  2618. slapi_pblock_destroy(pb);
  2619. return status;
  2620. }
  2621. /*
  2622. * We added a plugin, do our setup and then start the plugin. This is the same as adding a plugin
  2623. * or enabling a disabled plugin.
  2624. */
  2625. int
  2626. plugin_add(Slapi_Entry *entry, char *returntext, int locked)
  2627. {
  2628. int rc = LDAP_SUCCESS;
  2629. if (!locked) {
  2630. slapi_rwlock_wrlock(global_rwlock);
  2631. slapi_td_set_plugin_locked();
  2632. }
  2633. if ((rc = plugin_setup(entry, 0, 0, 1, returntext)) != LDAP_SUCCESS) {
  2634. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_add", "plugin_setup failed for (%s) %d\n",
  2635. slapi_entry_get_dn(entry), rc);
  2636. goto done;
  2637. }
  2638. if ((rc = plugin_start(entry, returntext)) != LDAP_SUCCESS) {
  2639. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_add", "plugin_start failed for (%s) %d\n",
  2640. slapi_entry_get_dn(entry), rc);
  2641. goto done;
  2642. }
  2643. done:
  2644. if (!locked) {
  2645. slapi_rwlock_unlock(global_rwlock);
  2646. slapi_td_set_plugin_unlocked();
  2647. }
  2648. return rc;
  2649. }
  2650. static char *
  2651. get_dep_plugin_list(char **plugins)
  2652. {
  2653. char output[1024];
  2654. int first_plugin = 1;
  2655. PRUint32 len = 0;
  2656. int i;
  2657. for (i = 0; plugins && plugins[i]; i++) {
  2658. if (first_plugin) {
  2659. PL_strncpyz(output, plugins[i], sizeof(output) - 3);
  2660. len += strlen(plugins[i]);
  2661. first_plugin = 0;
  2662. } else {
  2663. PL_strcatn(output, sizeof(output) - 3, ", ");
  2664. PL_strcatn(output, sizeof(output) - 3, plugins[i]);
  2665. len += strlen(plugins[i]);
  2666. }
  2667. if (len > (sizeof(output) - 3)) {
  2668. /*
  2669. * We could not print all the plugins, show that we truncated
  2670. * the list by adding "..."
  2671. */
  2672. PL_strcatn(output, sizeof(output), "...");
  2673. }
  2674. }
  2675. return slapi_ch_strdup(output);
  2676. }
  2677. /*
  2678. * Make sure the removal of this plugin does not breaking any existing dependencies
  2679. */
  2680. static int
  2681. plugin_delete_check_dependency(struct slapdplugin *plugin_entry, int flag, char *returntext)
  2682. {
  2683. entry_and_plugin_t *ep = dep_plugin_entries;
  2684. plugin_dep_config *config = NULL;
  2685. struct slapdplugin *plugin = NULL;
  2686. Slapi_Entry *pentry = NULL;
  2687. char *plugin_name = plugin_entry->plg_name;
  2688. char *plugin_type = plugin_get_type_str(plugin_entry->plg_type);
  2689. char **dep_plugins = NULL;
  2690. char *value = NULL;
  2691. char **list = NULL;
  2692. int dep_type_count = 0;
  2693. int type_count = 0;
  2694. int total_plugins = 0;
  2695. int plugin_index = 0;
  2696. int index = 0;
  2697. int rc = LDAP_SUCCESS;
  2698. int i;
  2699. while (ep) {
  2700. total_plugins++;
  2701. ep = ep->next;
  2702. }
  2703. /* allocate the config array */
  2704. config = (plugin_dep_config *)slapi_ch_calloc(total_plugins + 1, sizeof(plugin_dep_config));
  2705. ep = dep_plugin_entries;
  2706. /*
  2707. * Collect relevant config
  2708. */
  2709. while (ep) {
  2710. plugin = ep->plugin;
  2711. if (plugin == 0) {
  2712. goto next;
  2713. }
  2714. /*
  2715. * We are not concerned with disabled plugins
  2716. */
  2717. value = (char *)slapi_entry_attr_get_ref(ep->e, ATTR_PLUGIN_ENABLED);
  2718. if (value) {
  2719. if (strcasecmp(value, "off") == 0) {
  2720. goto next;
  2721. }
  2722. } else {
  2723. goto next;
  2724. }
  2725. if (!ep->plugin) {
  2726. goto next;
  2727. }
  2728. config[plugin_index].e = ep->e;
  2729. pentry = ep->e;
  2730. if (pentry) {
  2731. config[plugin_index].plugin = plugin;
  2732. plugin_create_stringlist(pentry, "nsslapd-plugin-depends-on-named",
  2733. &(config[plugin_index].total_named), &(config[plugin_index].depends_named_list));
  2734. plugin_create_stringlist(pentry, "nsslapd-plugin-depends-on-type",
  2735. &(config[plugin_index].total_type), &(config[plugin_index].depends_type_list));
  2736. }
  2737. plugin_index++;
  2738. next:
  2739. ep = ep->next;
  2740. }
  2741. /*
  2742. * Start checking every plugin for dependency issues
  2743. */
  2744. for (index = 0; index < plugin_index; index++) {
  2745. if ((plugin = config[index].plugin)) {
  2746. /*
  2747. * We can skip ourselves, and our registered plugins.
  2748. */
  2749. if (plugin_cmp_plugins(plugin, plugin_entry)) {
  2750. continue;
  2751. }
  2752. /*
  2753. * Check all the plugins to see if one is depending on this plugin(name)
  2754. */
  2755. if (flag == CHECK_ALL && config[index].depends_named_list) {
  2756. list = config[index].depends_named_list;
  2757. for (i = 0; list && list[i]; i++) {
  2758. if (strcasecmp(list[i], plugin_name) == 0) {
  2759. /* We have a dependency, we can not disable this pluign */
  2760. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete_check_dependency",
  2761. "Can not disable plugin(%s) due to dependency name issues with plugin (%s)\n",
  2762. plugin_name, config[index].plugin->plg_name);
  2763. rc = -1;
  2764. goto free_and_return;
  2765. }
  2766. }
  2767. }
  2768. /*
  2769. * Check all the plugins to see if one is depending on this plugin(type).
  2770. */
  2771. if (config[index].depends_type_list) {
  2772. list = config[index].depends_type_list;
  2773. for (i = 0; list && list[i]; i++) {
  2774. if (strcasecmp(list[i], plugin_type) == 0) {
  2775. charray_add(&dep_plugins, slapi_ch_strdup(plugin->plg_name));
  2776. dep_type_count++;
  2777. break;
  2778. }
  2779. }
  2780. }
  2781. }
  2782. }
  2783. /*
  2784. * Now check the dependency type count.
  2785. */
  2786. if (dep_type_count > 0) {
  2787. /*
  2788. * There are plugins that depend on this plugin type. Now, get a plugin count of this
  2789. * type of plugin. If we are the only plugin of this type, we can not disable it.
  2790. */
  2791. for (index = 0; index < plugin_index; index++) {
  2792. if ((plugin = config[index].plugin)) {
  2793. /* Skip ourselves, and our registered plugins. */
  2794. if (plugin_cmp_plugins(plugin, plugin_entry)) {
  2795. continue;
  2796. }
  2797. if (plugin->plg_type == plugin_entry->plg_type) {
  2798. /* there is at least one other plugin of this type, its ok to disable */
  2799. type_count = 1;
  2800. break;
  2801. }
  2802. }
  2803. }
  2804. if (type_count == 0) { /* this is the only plugin of this type - return an error */
  2805. char *plugins = get_dep_plugin_list(dep_plugins);
  2806. /*
  2807. * The plugin type was changed, but since other plugins currently have dependencies,
  2808. * we can not dynamically apply the change. This is will most likely cause issues
  2809. * at the next server startup.
  2810. */
  2811. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin (%s) type (%s) is needed "
  2812. "by other plugins(%s), it can not be dynamically disabled/removed at this time.",
  2813. plugin_name, plugin_type, plugins);
  2814. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete_check_dependency", "%s\n",
  2815. returntext);
  2816. slapi_ch_free_string(&plugins);
  2817. rc = -1;
  2818. }
  2819. }
  2820. free_and_return:
  2821. /*
  2822. * Free the config list
  2823. */
  2824. charray_free(dep_plugins);
  2825. if (config) {
  2826. index = 0;
  2827. while (config[index].plugin) {
  2828. charray_free(config[index].depends_type_list);
  2829. charray_free(config[index].depends_named_list);
  2830. index++;
  2831. }
  2832. slapi_ch_free((void **)&config);
  2833. }
  2834. return rc;
  2835. }
  2836. /*
  2837. * Mark the plugin in the shutdown list a removed
  2838. */
  2839. static void
  2840. plugin_remove_from_shutdown(struct slapdplugin *plugin_entry)
  2841. {
  2842. struct slapdplugin *plugin = NULL;
  2843. int index = 0;
  2844. for (; index < global_plugins_started; index++) {
  2845. if ((plugin = global_plugin_shutdown_order[index].plugin)) {
  2846. if (global_plugin_shutdown_order[index].removed) {
  2847. continue;
  2848. }
  2849. /* "plugin_entry" can be the main plugin for registered function */
  2850. if (plugin_cmp_plugins(plugin, plugin_entry)) {
  2851. /*
  2852. * We have our index, just mark it as removed. The global list gets rewritten
  2853. * the next time we add or enable a plugin.
  2854. */
  2855. global_plugin_shutdown_order[index].removed = 1;
  2856. return;
  2857. }
  2858. }
  2859. }
  2860. }
  2861. /*
  2862. * Free the plugins that have been set to be removed.
  2863. */
  2864. static void
  2865. plugin_cleanup_list(void)
  2866. {
  2867. struct slapdplugin *plugin = NULL;
  2868. entry_and_plugin_t *ep = dep_plugin_entries;
  2869. entry_and_plugin_t *ep_prev = NULL, *ep_next = NULL;
  2870. while (ep) {
  2871. plugin = ep->plugin;
  2872. ep_next = ep->next;
  2873. if (plugin && plugin->plg_removed) {
  2874. if (ep_prev) {
  2875. ep_prev->next = ep->next;
  2876. } else {
  2877. dep_plugin_entries = ep->next;
  2878. }
  2879. slapi_entry_free(ep->e);
  2880. if (ep->plugin) {
  2881. plugin_free(ep->plugin);
  2882. }
  2883. slapi_ch_free((void **)&ep);
  2884. } else {
  2885. ep_prev = ep;
  2886. }
  2887. ep = ep_next;
  2888. }
  2889. }
  2890. /*
  2891. * Look at all the plugins for any matches. Then mark the ones we need
  2892. * to delete. After checking all the plugins, then we free the ones that
  2893. * were marked to be removed.
  2894. */
  2895. static int
  2896. plugin_remove_plugins(struct slapdplugin *plugin_entry, char *plugin_type __attribute__((unused)))
  2897. {
  2898. struct slapdplugin *plugin = NULL;
  2899. struct slapdplugin *plugin_next = NULL;
  2900. struct slapdplugin *plugin_prev = NULL;
  2901. int removed = PLUGIN_NOT_FOUND;
  2902. int type;
  2903. /* look everywhere for other plugin functions with the plugin id */
  2904. for (type = 0; type < PLUGIN_LIST_GLOBAL_MAX; type++) {
  2905. plugin = global_plugin_list[type];
  2906. plugin_prev = NULL;
  2907. while (plugin) {
  2908. plugin_next = plugin->plg_next;
  2909. /*
  2910. * Check for the two types of plugins:
  2911. * the main plugin, and its registered plugin functions.
  2912. */
  2913. if (plugin_cmp_plugins(plugin_entry, plugin)) {
  2914. /*
  2915. * Call the close function, cleanup the hashtable & the global shutdown list
  2916. */
  2917. plugin_set_stopped(plugin);
  2918. if (slapi_counter_get_value(plugin->plg_op_counter) > 0) {
  2919. /*
  2920. * Plugin is still busy, and we might be blocking it
  2921. * by holding global plugin lock so return for now.
  2922. */
  2923. return PLUGIN_BUSY;
  2924. }
  2925. Slapi_PBlock *pb = slapi_pblock_new();
  2926. plugin_call_one(plugin, SLAPI_PLUGIN_CLOSE_FN, pb);
  2927. slapi_pblock_destroy(pb);
  2928. if (plugin_prev) {
  2929. plugin_prev->plg_next = plugin_next;
  2930. } else {
  2931. global_plugin_list[type] = plugin_next;
  2932. }
  2933. /*
  2934. * Remove plugin the DN hashtable, update the shutdown list,
  2935. * and mark the plugin for deletion
  2936. */
  2937. plugin_remove_from_list(plugin->plg_dn);
  2938. plugin_remove_from_shutdown(plugin);
  2939. plugin->plg_removed = 1;
  2940. plugin->plg_started = 0;
  2941. removed = PLUGIN_REMOVED;
  2942. } else {
  2943. plugin_prev = plugin;
  2944. }
  2945. plugin = plugin_next;
  2946. }
  2947. }
  2948. if (removed) {
  2949. /*
  2950. * Now free the marked plugins, we could not do this earlier because
  2951. * we also needed to check for plugins registered functions. As both
  2952. * plugin types share the same slapi_plugin entry.
  2953. */
  2954. plugin_cleanup_list();
  2955. }
  2956. return removed;
  2957. }
  2958. /*
  2959. * We are removing a plugin from the global list. This happens when we delete a plugin, or disable it.
  2960. */
  2961. int
  2962. plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int locked)
  2963. {
  2964. struct slapdplugin **plugin_list = NULL;
  2965. struct slapdplugin *plugin = NULL;
  2966. const char *plugin_dn = slapi_entry_get_dn_const(plugin_entry);
  2967. char *value = NULL;
  2968. int removed = PLUGIN_BUSY;
  2969. int type = 0;
  2970. int rc = LDAP_SUCCESS;
  2971. /* Critical server plugins can not be disabled */
  2972. if (plugin_is_critical(plugin_entry)) {
  2973. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete", "Plugin \"%s\" is critical to server operations, and can not be disabled\n",
  2974. slapi_entry_get_dn_const(plugin_entry));
  2975. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin \"%s\" is critical to server operations, and can not "
  2976. "be disabled.\n",
  2977. slapi_entry_get_dn_const(plugin_entry));
  2978. rc = -1;
  2979. goto done;
  2980. }
  2981. if (!(value = (char *)slapi_entry_attr_get_ref(plugin_entry, ATTR_PLUGIN_TYPE))) {
  2982. /* error: required attribute %s missing */
  2983. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete", "Required attribute %s is missing from entry \"%s\"\n",
  2984. ATTR_PLUGIN_TYPE, slapi_entry_get_dn_const(plugin_entry));
  2985. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Required attribute %s "
  2986. "is missing from entry.",
  2987. ATTR_PLUGIN_TYPE);
  2988. rc = -1;
  2989. goto done;
  2990. } else {
  2991. while (removed == PLUGIN_BUSY) {
  2992. removed = PLUGIN_NOT_FOUND;
  2993. if (!locked) {
  2994. slapi_rwlock_wrlock(global_rwlock);
  2995. slapi_td_set_plugin_locked();
  2996. }
  2997. rc = plugin_get_type_and_list(value, &type, &plugin_list);
  2998. if (rc != 0) {
  2999. /* error: unknown plugin type */
  3000. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete", "Unknown plugin type \"%s\" in entry \"%s\"\n",
  3001. value, slapi_entry_get_dn_const(plugin_entry));
  3002. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Unknown plugin type \"%s\" in entry.",
  3003. value);
  3004. rc = -1;
  3005. goto unlock;
  3006. }
  3007. /*
  3008. * Skip syntax/matching rule/database plugins - these can not be disabled as it
  3009. * could break existing schema. We allow the update to occur, but it will
  3010. * not take effect until the next server restart.
  3011. */
  3012. if (type == SLAPI_PLUGIN_SYNTAX || type == SLAPI_PLUGIN_MATCHINGRULE || type == SLAPI_PLUGIN_DATABASE) {
  3013. removed = PLUGIN_REMOVED; /* avoids error check below */
  3014. goto unlock;
  3015. }
  3016. /*
  3017. * Now remove the plugin from the list and the hashtable
  3018. */
  3019. for (plugin = *plugin_list; plugin; plugin = plugin->plg_next) {
  3020. if (strcasecmp(plugin->plg_dn, plugin_dn) == 0) {
  3021. /*
  3022. * Make sure there are no other plugins that depend on this one before removing it
  3023. */
  3024. if (plugin_delete_check_dependency(plugin, CHECK_ALL, returntext) != LDAP_SUCCESS) {
  3025. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete", "Failed to disable/delete plugin (%s)\n",
  3026. plugin->plg_dn);
  3027. rc = -1;
  3028. break;
  3029. }
  3030. removed = plugin_remove_plugins(plugin, value);
  3031. break;
  3032. }
  3033. }
  3034. unlock:
  3035. if (!locked) {
  3036. slapi_rwlock_unlock(global_rwlock);
  3037. slapi_td_set_plugin_unlocked();
  3038. }
  3039. }
  3040. }
  3041. done:
  3042. if (!removed && rc == 0) {
  3043. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin delete failed: could not find plugin "
  3044. "in the global list.");
  3045. slapi_log_err(SLAPI_LOG_ERR, "plugin_delete", "Did not find plugin (%s) in the global list.\n",
  3046. slapi_entry_get_dn_const(plugin_entry));
  3047. rc = -1;
  3048. }
  3049. return rc;
  3050. }
  3051. /* set default configuration parameters */
  3052. static void
  3053. plugin_config_init(struct pluginconfig *config)
  3054. {
  3055. PR_ASSERT(config);
  3056. ptd_init(&config->plgc_target_subtrees);
  3057. ptd_init(&config->plgc_excluded_target_subtrees);
  3058. ptd_init(&config->plgc_bind_subtrees);
  3059. ptd_init(&config->plgc_excluded_bind_subtrees);
  3060. config->plgc_schema_check = PLGC_ON;
  3061. config->plgc_invoke_for_replop = PLGC_ON;
  3062. /* currently, we leave it up to plugin, but don't actually tell plugins that they can choose.
  3063. We want changes to always be logged by regular plugins to avoid data inconsistency, but we
  3064. want to allow internal plugins like replication to make the decision.*/
  3065. config->plgc_log_change = PLGC_UPTOPLUGIN;
  3066. config->plgc_log_access = PLGC_OFF;
  3067. config->plgc_log_audit = PLGC_OFF;
  3068. }
  3069. static int
  3070. plugin_config_set_action(int *action, char *value)
  3071. {
  3072. PR_ASSERT(action);
  3073. PR_ASSERT(value);
  3074. if (strcasecmp(value, "on") == 0) {
  3075. *action = PLGC_ON;
  3076. } else if (strcasecmp(value, "off") == 0) {
  3077. *action = PLGC_OFF;
  3078. } else if (strcasecmp(value, "uptoplugin") == 0) {
  3079. *action = PLGC_UPTOPLUGIN;
  3080. } else {
  3081. slapi_log_err(SLAPI_LOG_ERR, "plugin_config_set_action",
  3082. "Invalid action %s\n", value);
  3083. return -1;
  3084. }
  3085. return 0;
  3086. }
  3087. static void
  3088. plugin_config_cleanup(struct pluginconfig *config)
  3089. {
  3090. PR_ASSERT(config);
  3091. ptd_cleanup(&config->plgc_target_subtrees);
  3092. ptd_cleanup(&config->plgc_excluded_target_subtrees);
  3093. ptd_cleanup(&config->plgc_bind_subtrees);
  3094. ptd_cleanup(&config->plgc_excluded_bind_subtrees);
  3095. }
  3096. static struct pluginconfig *
  3097. plugin_get_config(struct slapdplugin *plugin)
  3098. {
  3099. struct slapdplugin *temp = plugin;
  3100. PR_ASSERT(plugin);
  3101. while (temp->plg_group) {
  3102. temp = temp->plg_group;
  3103. }
  3104. return &(temp->plg_conf);
  3105. }
  3106. static PRBool
  3107. plugin_invoke_plugin_pb(struct slapdplugin *plugin, int operation, Slapi_PBlock *pb)
  3108. {
  3109. Slapi_DN *target_spec;
  3110. Operation *pb_op = NULL;
  3111. PRBool rc;
  3112. PR_ASSERT(plugin);
  3113. PR_ASSERT(pb);
  3114. /* we always allow initialization and cleanup operations */
  3115. if (operation == SLAPI_PLUGIN_START_FN ||
  3116. operation == SLAPI_PLUGIN_POSTSTART_FN ||
  3117. operation == SLAPI_PLUGIN_CLOSE_FN ||
  3118. operation == SLAPI_PLUGIN_CLEANUP_FN ||
  3119. operation == SLAPI_PLUGIN_BE_PRE_CLOSE_FN ||
  3120. operation == SLAPI_PLUGIN_BE_POST_OPEN_FN ||
  3121. operation == SLAPI_PLUGIN_BE_POST_EXPORT_FN ||
  3122. operation == SLAPI_PLUGIN_BE_POST_IMPORT_FN)
  3123. return PR_TRUE;
  3124. slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
  3125. if (pb_op == NULL) {
  3126. slapi_log_err(SLAPI_LOG_ERR, "plugin_invoke_plugin_pb", "pb_op is NULL");
  3127. PR_ASSERT(0);
  3128. return PR_FALSE;
  3129. }
  3130. target_spec = operation_get_target_spec(pb_op);
  3131. rc = plugin_invoke_plugin_sdn(plugin, operation, pb, target_spec);
  3132. return rc;
  3133. }
  3134. PRBool
  3135. plugin_invoke_plugin_sdn(struct slapdplugin *plugin, int operation __attribute__((unused)), Slapi_PBlock *pb, Slapi_DN *target_spec)
  3136. {
  3137. PluginTargetData *ptd;
  3138. PluginTargetData *excludedPtd;
  3139. struct pluginconfig *config;
  3140. Slapi_Backend *be;
  3141. int isroot;
  3142. PRBool islocal;
  3143. PRBool bindop;
  3144. unsigned long op;
  3145. ber_tag_t method = LBER_ERROR;
  3146. PR_ASSERT(plugin);
  3147. if (!pb) {
  3148. slapi_log_err(SLAPI_LOG_ERR, "plugin_invoke_plugin_sdn", "NULL pblock.\n");
  3149. return PR_FALSE;
  3150. }
  3151. Operation *pb_op;
  3152. slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
  3153. /* get configuration from the group plugin if necessary */
  3154. config = plugin_get_config(plugin);
  3155. slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
  3156. /* check if plugin is configured to service replicated operations */
  3157. if (!config->plgc_invoke_for_replop) {
  3158. int repl_op;
  3159. slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
  3160. if (repl_op) {
  3161. return PR_FALSE;
  3162. }
  3163. }
  3164. if (pb_op) {
  3165. op = operation_get_type(pb_op);
  3166. if (op == SLAPI_OPERATION_BIND || op == SLAPI_OPERATION_UNBIND) {
  3167. bindop = PR_TRUE;
  3168. } else {
  3169. bindop = PR_FALSE;
  3170. }
  3171. slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  3172. } else {
  3173. bindop = PR_FALSE;
  3174. isroot = 1;
  3175. }
  3176. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  3177. /* determine whether data are local or remote */
  3178. /* remote if chaining backend or default backend */
  3179. if (be != NULL) {
  3180. islocal = !(slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA));
  3181. } else {
  3182. islocal = be != defbackend_get_backend();
  3183. }
  3184. if (bindop) {
  3185. ptd = &(config->plgc_bind_subtrees);
  3186. excludedPtd = &(config->plgc_excluded_bind_subtrees);
  3187. } else {
  3188. ptd = &(config->plgc_target_subtrees);
  3189. excludedPtd = &(config->plgc_excluded_target_subtrees);
  3190. }
  3191. if (plugin_matches_operation(target_spec, excludedPtd, bindop, isroot, islocal, method) == PR_TRUE) {
  3192. return PR_FALSE;
  3193. }
  3194. return plugin_matches_operation(target_spec, ptd, bindop, isroot, islocal, method);
  3195. }
  3196. /* this interface is exposed to be used by internal operations.
  3197. */
  3198. char *
  3199. plugin_get_dn(const struct slapdplugin *plugin)
  3200. {
  3201. char *plugindn = NULL;
  3202. char *pattern = "cn=%s," PLUGIN_BASE_DN; /* cn=plugins,cn=config */
  3203. if (plugin == NULL) /* old plugin that does not pass identity - use default */
  3204. plugin = &global_default_plg;
  3205. if (plugin->plg_name == NULL)
  3206. return NULL;
  3207. /* plg_name is normalized in plugin_setup. So, we can use smprintf */
  3208. plugindn = slapi_ch_smprintf(pattern, plugin->plg_name);
  3209. if (NULL == plugindn) {
  3210. slapi_log_err(SLAPI_LOG_ERR, "plugin_get_dn",
  3211. "Failed to create plugin dn (plugin name: %s)\n", plugin->plg_name);
  3212. return NULL;
  3213. }
  3214. return plugindn;
  3215. }
  3216. static PRBool
  3217. plugin_is_global(const PluginTargetData *ptd)
  3218. {
  3219. /* plugin is considered to be global if it is invoked for
  3220. global data, local data and anonymous bind (bind target
  3221. data only). We don't include directory manager here
  3222. as it is considered to be part of local data */
  3223. return (ptd_is_special_data_set(ptd, PLGC_DATA_LOCAL) &&
  3224. ptd_is_special_data_set(ptd, PLGC_DATA_REMOTE) &&
  3225. ptd_is_special_data_set(ptd, PLGC_DATA_BIND_ANONYMOUS) &&
  3226. ptd_is_special_data_set(ptd, PLGC_DATA_BIND_ROOT));
  3227. }
  3228. static void
  3229. plugin_set_global(PluginTargetData *ptd)
  3230. {
  3231. PR_ASSERT(ptd);
  3232. /* plugin is global if it is allowed access to all data */
  3233. ptd_set_special_data(ptd, PLGC_DATA_LOCAL);
  3234. ptd_set_special_data(ptd, PLGC_DATA_REMOTE);
  3235. ptd_set_special_data(ptd, PLGC_DATA_BIND_ANONYMOUS);
  3236. ptd_set_special_data(ptd, PLGC_DATA_BIND_ROOT);
  3237. }
  3238. static void
  3239. plugin_set_default_access(struct pluginconfig *config)
  3240. {
  3241. /* by default, plugins are invoked if dn is local for bind operations,
  3242. and for all requests for all other operations */
  3243. PR_ASSERT(config);
  3244. plugin_set_global(&config->plgc_target_subtrees);
  3245. ptd_set_special_data(&config->plgc_bind_subtrees, PLGC_DATA_LOCAL);
  3246. ptd_set_special_data(&config->plgc_bind_subtrees, PLGC_DATA_REMOTE);
  3247. }
  3248. /* determine whether operation should be allowed based on plugin configuration */
  3249. PRBool
  3250. plugin_allow_internal_op(Slapi_DN *target_spec, struct slapdplugin *plugin)
  3251. {
  3252. struct pluginconfig *config = plugin_get_config(plugin);
  3253. Slapi_Backend *be;
  3254. int islocal;
  3255. if (plugin_is_global(&config->plgc_excluded_target_subtrees))
  3256. return PR_FALSE;
  3257. if (plugin_is_global(&config->plgc_target_subtrees))
  3258. return PR_TRUE;
  3259. /* ONREPL - we do be_select to decide whether the request is for local
  3260. or remote data. We might need to reconsider how to do this
  3261. for performance reasons since be_select will be done again
  3262. once the operation goes through */
  3263. be = slapi_be_select(target_spec);
  3264. /* determine whether data are local or remote */
  3265. /* remote if chaining backend or default backend */
  3266. if (be != NULL) {
  3267. islocal = !(slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA));
  3268. } else {
  3269. islocal = be != defbackend_get_backend();
  3270. }
  3271. /* SIMPLE auth method sends us through original code path in plugin_mathches_operation */
  3272. if (plugin_matches_operation(target_spec, &config->plgc_excluded_target_subtrees,
  3273. PR_FALSE, PR_FALSE, islocal, LDAP_AUTH_SIMPLE) == PR_TRUE) {
  3274. return PR_FALSE;
  3275. }
  3276. return plugin_matches_operation(target_spec, &config->plgc_target_subtrees,
  3277. PR_FALSE, PR_FALSE, islocal, LDAP_AUTH_SIMPLE);
  3278. }
  3279. static PRBool
  3280. plugin_matches_operation(Slapi_DN *target_spec, PluginTargetData *ptd, PRBool bindop, PRBool isroot, PRBool islocal, ber_tag_t method)
  3281. {
  3282. int cookie;
  3283. Slapi_DN *subtree;
  3284. /* check for special cases */
  3285. if (plugin_is_global(ptd))
  3286. return PR_TRUE;
  3287. /* if method is SASL we can have a null DN so bypass this check*/
  3288. if (method != LDAP_AUTH_SASL) {
  3289. if (bindop && target_spec && (slapi_sdn_get_dn(target_spec) == NULL ||
  3290. slapi_sdn_get_dn(target_spec)[0] == '\0')) {
  3291. return (ptd_is_special_data_set(ptd, PLGC_DATA_BIND_ANONYMOUS));
  3292. }
  3293. }
  3294. /* check for root bind */
  3295. if (bindop && isroot) {
  3296. return (ptd_is_special_data_set(ptd, PLGC_DATA_BIND_ROOT));
  3297. }
  3298. /* check for local data */
  3299. if (ptd_is_special_data_set(ptd, PLGC_DATA_LOCAL) && islocal) {
  3300. return PR_TRUE;
  3301. }
  3302. /* check for remote data */
  3303. if (ptd_is_special_data_set(ptd, PLGC_DATA_REMOTE) && !islocal) {
  3304. return (PR_TRUE);
  3305. }
  3306. subtree = ptd_get_first_subtree(ptd, &cookie);
  3307. while (subtree) {
  3308. if (slapi_sdn_issuffix(target_spec, subtree))
  3309. return (PR_TRUE);
  3310. subtree = ptd_get_next_subtree(ptd, &cookie);
  3311. }
  3312. return PR_FALSE;
  3313. }
  3314. /* build operation action bitmap based on plugin configuration and actions specified for the operation */
  3315. int
  3316. plugin_build_operation_action_bitmap(int input_actions __attribute__((unused)), const struct slapdplugin *plugin)
  3317. {
  3318. int result_actions = 0;
  3319. /* old plugin that does not pass its identity to the operation */
  3320. if (plugin == NULL)
  3321. plugin = &global_default_plg;
  3322. if (plugin->plg_conf.plgc_log_access || config_get_plugin_logging())
  3323. result_actions |= OP_FLAG_ACTION_LOG_ACCESS;
  3324. if (plugin->plg_conf.plgc_log_audit || config_get_plugin_logging())
  3325. result_actions |= OP_FLAG_ACTION_LOG_AUDIT;
  3326. /*
  3327. * OP_FLAG_ACTION_INVOKE_FOR_REPLOP is now used only by URP code.
  3328. * If someday this code needs to reclaim the flag, it has to use
  3329. * another flag to avoid the conflict with URP code.
  3330. *
  3331. * if (plugin->plg_conf.plgc_invoke_for_replop)
  3332. * result_actions |= OP_FLAG_ACTION_INVOKE_FOR_REPLOP;
  3333. */
  3334. switch (plugin->plg_conf.plgc_schema_check) {
  3335. case PLGC_OFF:
  3336. result_actions &= ~OP_FLAG_ACTION_SCHEMA_CHECK;
  3337. break;
  3338. case PLGC_ON:
  3339. result_actions |= OP_FLAG_ACTION_SCHEMA_CHECK;
  3340. break;
  3341. case PLGC_UPTOPLUGIN:
  3342. break;
  3343. default:
  3344. PR_ASSERT(PR_FALSE);
  3345. }
  3346. switch (plugin->plg_conf.plgc_log_change) {
  3347. case PLGC_OFF:
  3348. result_actions &= ~OP_FLAG_ACTION_LOG_CHANGES;
  3349. break;
  3350. case PLGC_ON:
  3351. result_actions |= OP_FLAG_ACTION_LOG_CHANGES;
  3352. break;
  3353. case PLGC_UPTOPLUGIN:
  3354. break;
  3355. default:
  3356. PR_ASSERT(PR_FALSE);
  3357. }
  3358. return result_actions;
  3359. }
  3360. const struct slapdplugin *
  3361. plugin_get_server_plg(void)
  3362. {
  3363. if (!global_server_plg_initialised) {
  3364. global_server_plg.plg_name = "server";
  3365. plugin_set_global(&global_server_plg.plg_conf.plgc_target_subtrees);
  3366. global_server_plg.plg_conf.plgc_log_access = 1;
  3367. global_server_plg.plg_conf.plgc_log_audit = 1;
  3368. global_server_plg.plg_conf.plgc_schema_check = 1;
  3369. global_server_plg.plg_conf.plgc_log_change = 1;
  3370. global_server_plg_initialised = 1;
  3371. global_server_plg_initialised = 1;
  3372. }
  3373. return &global_server_plg;
  3374. }
  3375. struct slapi_componentid *
  3376. plugin_get_default_component_id(void)
  3377. {
  3378. if (!global_server_plg_id_initialised) {
  3379. global_server_id_plg.sci_plugin = plugin_get_server_plg();
  3380. global_server_id_plg.sci_component_name =
  3381. plugin_get_dn(global_server_id_plg.sci_plugin);
  3382. global_server_plg_id_initialised = 1;
  3383. }
  3384. return &global_server_id_plg;
  3385. }
  3386. static void
  3387. default_plugin_init(void)
  3388. {
  3389. global_default_plg.plg_name = "old plugin";
  3390. plugin_config_init(&global_default_plg.plg_conf);
  3391. plugin_set_default_access(&global_default_plg.plg_conf);
  3392. }
  3393. /* functions to manipulate PluginTargetData type */
  3394. static void
  3395. ptd_init(PluginTargetData *ptd)
  3396. {
  3397. PR_ASSERT(ptd);
  3398. dl_init(&ptd->subtrees, 0 /* initial count */);
  3399. memset(&ptd->special_data, 0, sizeof(ptd->special_data));
  3400. }
  3401. static void
  3402. ptd_cleanup(PluginTargetData *ptd)
  3403. {
  3404. PR_ASSERT(ptd);
  3405. dl_cleanup(&ptd->subtrees, (FREEFN)slapi_sdn_free);
  3406. memset(&ptd->special_data, 0, sizeof(ptd->special_data));
  3407. }
  3408. static void
  3409. ptd_add_subtree(PluginTargetData *ptd, Slapi_DN *subtree)
  3410. {
  3411. PR_ASSERT(ptd);
  3412. PR_ASSERT(subtree);
  3413. dl_add(&ptd->subtrees, subtree);
  3414. }
  3415. static void
  3416. ptd_set_special_data(PluginTargetData *ptd, int type)
  3417. {
  3418. PR_ASSERT(ptd);
  3419. PR_ASSERT(type >= 0 && type < PLGC_DATA_MAX);
  3420. ptd->special_data[type] = PR_TRUE;
  3421. }
  3422. static Slapi_DN *
  3423. ptd_get_first_subtree(const PluginTargetData *ptd, int *cookie)
  3424. {
  3425. PR_ASSERT(ptd);
  3426. return dl_get_first(&ptd->subtrees, cookie);
  3427. }
  3428. static Slapi_DN *
  3429. ptd_get_next_subtree(const PluginTargetData *ptd, int *cookie)
  3430. {
  3431. PR_ASSERT(ptd);
  3432. return dl_get_next(&ptd->subtrees, cookie);
  3433. }
  3434. static PRBool
  3435. ptd_is_special_data_set(const PluginTargetData *ptd, int type)
  3436. {
  3437. PR_ASSERT(ptd);
  3438. PR_ASSERT(type >= 0 && type < PLGC_DATA_MAX);
  3439. return ptd->special_data[type];
  3440. }
  3441. int
  3442. ptd_get_subtree_count(const PluginTargetData *ptd)
  3443. {
  3444. PR_ASSERT(ptd);
  3445. return dl_get_count(&ptd->subtrees);
  3446. }
  3447. /* needed by command-line tasks to find an instance's plugin */
  3448. struct slapdplugin *
  3449. plugin_get_by_name(char *name)
  3450. {
  3451. int x;
  3452. struct slapdplugin *plugin;
  3453. for (x = 0; x < PLUGIN_LIST_GLOBAL_MAX; x++) {
  3454. for (plugin = global_plugin_list[x]; plugin; plugin = plugin->plg_next) {
  3455. if (!strcmp(name, plugin->plg_name)) {
  3456. return plugin;
  3457. }
  3458. }
  3459. }
  3460. return NULL;
  3461. }
  3462. struct slapi_componentid *
  3463. generate_componentid(struct slapdplugin *pp, char *name)
  3464. {
  3465. struct slapi_componentid *idp;
  3466. idp = (struct slapi_componentid *)slapi_ch_calloc(1, sizeof(*idp));
  3467. if (pp) {
  3468. idp->sci_plugin = pp;
  3469. } else {
  3470. idp->sci_plugin = (struct slapdplugin *)plugin_get_server_plg();
  3471. }
  3472. if (name) {
  3473. idp->sci_component_name = slapi_ch_strdup(name);
  3474. } else {
  3475. /* Use plugin dn */
  3476. idp->sci_component_name = plugin_get_dn(idp->sci_plugin);
  3477. }
  3478. if (idp->sci_component_name) {
  3479. slapi_dn_normalize(idp->sci_component_name);
  3480. }
  3481. return idp;
  3482. }
  3483. void
  3484. release_componentid(struct slapi_componentid *id)
  3485. {
  3486. if (id) {
  3487. if (id->sci_component_name) {
  3488. slapi_ch_free((void **)&id->sci_component_name);
  3489. id->sci_component_name = NULL;
  3490. }
  3491. slapi_ch_free((void **)&id);
  3492. }
  3493. }
  3494. /* used in main.c if -V flag is given */
  3495. static void
  3496. slapd_print_plugin_version(
  3497. struct slapdplugin *plg,
  3498. struct slapdplugin *prev)
  3499. {
  3500. if (plg == NULL || plg->plg_libpath == NULL)
  3501. return;
  3502. /* same library as previous - don't print twice */
  3503. if (prev != NULL && prev->plg_libpath != NULL) {
  3504. if (strcmp(prev->plg_libpath, plg->plg_libpath) == 0) {
  3505. return;
  3506. }
  3507. }
  3508. printf("%s: %s\n",
  3509. plg->plg_libpath,
  3510. plg->plg_desc.spd_version ? plg->plg_desc.spd_version : "");
  3511. }
  3512. static void
  3513. slapd_print_pluginlist_versions(struct slapdplugin *plg)
  3514. {
  3515. struct slapdplugin *p, *prev = NULL;
  3516. for (p = plg; p != NULL; p = p->plg_next) {
  3517. slapd_print_plugin_version(p, prev);
  3518. prev = p;
  3519. }
  3520. }
  3521. void
  3522. plugin_print_versions(void)
  3523. {
  3524. int i;
  3525. for (i = 0; i < PLUGIN_LIST_GLOBAL_MAX; i++) {
  3526. slapd_print_pluginlist_versions(get_plugin_list(i));
  3527. }
  3528. }
  3529. /*
  3530. * Prints a list of plugins in execution order for each
  3531. * plug-in type. This will only be printed at the
  3532. * SLAPI_LOG_PLUGIN log level.
  3533. */
  3534. void
  3535. plugin_print_lists(void)
  3536. {
  3537. int i;
  3538. struct slapdplugin *list = NULL;
  3539. struct slapdplugin *tmp = NULL;
  3540. for (i = 0; i < PLUGIN_LIST_GLOBAL_MAX; i++) {
  3541. if ((list = get_plugin_list(i))) {
  3542. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_print_lists",
  3543. "---- Plugin List (type %d) ----\n", i);
  3544. for (tmp = list; tmp; tmp = tmp->plg_next) {
  3545. slapi_log_err(SLAPI_LOG_PLUGIN, "plugin_print_lists", " %s (precedence: %d)\n",
  3546. tmp->plg_name, tmp->plg_precedence);
  3547. }
  3548. }
  3549. }
  3550. }
  3551. /*
  3552. * check the spedified plugin entry and its nssladp-pluginEnabled value
  3553. * Return Value: 1 if the plugin is on.
  3554. * : 0 otherwise.
  3555. */
  3556. int
  3557. plugin_enabled(const char *plugin_name, void *identity)
  3558. {
  3559. Slapi_PBlock *search_pb = NULL;
  3560. Slapi_Entry **entries = NULL, **ep = NULL;
  3561. Slapi_Value *on_off = slapi_value_new_string("on");
  3562. char *filter = NULL;
  3563. int rc = 0; /* disabled, by default */
  3564. filter = slapi_filter_sprintf("cn=%s%s", ESC_NEXT_VAL, plugin_name);
  3565. search_pb = slapi_pblock_new();
  3566. slapi_search_internal_set_pb(search_pb, PLUGIN_BASE_DN, LDAP_SCOPE_ONELEVEL,
  3567. filter, NULL, 0, NULL, NULL, identity, 0);
  3568. slapi_search_internal_pb(search_pb);
  3569. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  3570. if (LDAP_SUCCESS != rc) { /* plugin is not available */
  3571. rc = 0; /* disabled, by default */
  3572. goto bail;
  3573. }
  3574. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  3575. for (ep = entries; ep && *ep; ep++) {
  3576. if (slapi_entry_attr_has_syntax_value(*ep, "nsslapd-pluginEnabled", on_off)) {
  3577. rc = 1; /* plugin is on */
  3578. goto bail;
  3579. }
  3580. }
  3581. bail:
  3582. slapi_value_free(&on_off);
  3583. slapi_free_search_results_internal(search_pb);
  3584. slapi_pblock_destroy(search_pb);
  3585. slapi_ch_free_string(&filter);
  3586. return rc;
  3587. }
  3588. /*
  3589. * Set given "type: attr" to the plugin default config entry
  3590. * (cn=plugin default config,cn=config) unless the same "type: attr" pair
  3591. * already exists in the entry.
  3592. */
  3593. int
  3594. slapi_set_plugin_default_config(const char *type, Slapi_Value *value)
  3595. {
  3596. Slapi_PBlock *pb;
  3597. Slapi_Entry **entries = NULL;
  3598. int rc = LDAP_SUCCESS;
  3599. char **search_attrs = NULL; /* used by search */
  3600. if (NULL == type || '\0' == *type || NULL == value) { /* nothing to do */
  3601. return rc;
  3602. }
  3603. pb = slapi_pblock_new();
  3604. charray_add(&search_attrs, slapi_ch_strdup(type));
  3605. /* cn=plugin default config,cn=config */
  3606. slapi_search_internal_set_pb(pb,
  3607. SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN (normalized) */
  3608. LDAP_SCOPE_BASE,
  3609. "(objectclass=*)",
  3610. search_attrs, /* Attrs */
  3611. 0, /* AttrOnly */
  3612. NULL, /* Controls */
  3613. NULL, /* UniqueID */
  3614. (void *)plugin_get_default_component_id(),
  3615. 0);
  3616. slapi_search_internal_pb(pb);
  3617. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  3618. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  3619. if (LDAP_SUCCESS == rc && entries && *entries) {
  3620. /* plugin default config entry exists */
  3621. int exists = 0;
  3622. Slapi_Attr *attr = NULL;
  3623. rc = slapi_entry_attr_find(*entries, type, &attr);
  3624. if (0 == rc) { /* type exists in the entry */
  3625. if (0 ==
  3626. slapi_attr_value_find(attr, slapi_value_get_berval(value))) {
  3627. /* value exists in the entry; we don't have to do anything. */
  3628. exists = 1;
  3629. }
  3630. }
  3631. slapi_free_search_results_internal(pb);
  3632. slapi_pblock_destroy(pb);
  3633. if (!exists) {
  3634. /* The argument attr is not in the plugin default config.
  3635. * Let's add it. */
  3636. Slapi_Mods smods;
  3637. Slapi_Value *va[2];
  3638. va[0] = value;
  3639. va[1] = NULL;
  3640. slapi_mods_init(&smods, 1);
  3641. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va);
  3642. pb = slapi_pblock_new();
  3643. slapi_modify_internal_set_pb(pb, SLAPI_PLUGIN_DEFAULT_CONFIG,
  3644. slapi_mods_get_ldapmods_byref(&smods),
  3645. NULL, NULL, /* UniqueID */
  3646. (void *)plugin_get_default_component_id(),
  3647. 0 /* Flags */);
  3648. slapi_modify_internal_pb(pb);
  3649. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  3650. slapi_mods_done(&smods);
  3651. slapi_pblock_destroy(pb);
  3652. }
  3653. } else { /* cn=plugin default config does not exist. Let's add it. */
  3654. Slapi_Mods smods;
  3655. Slapi_Value *va[2];
  3656. slapi_free_search_results_internal(pb);
  3657. slapi_pblock_destroy(pb);
  3658. va[0] = value;
  3659. va[1] = NULL;
  3660. slapi_mods_init(&smods, 1);
  3661. slapi_mods_add_string(&smods, LDAP_MOD_ADD, "objectClass", "top");
  3662. slapi_mods_add_string(&smods, LDAP_MOD_ADD, "objectClass",
  3663. "extensibleObject");
  3664. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va);
  3665. pb = slapi_pblock_new();
  3666. slapi_add_internal_set_pb(pb, SLAPI_PLUGIN_DEFAULT_CONFIG,
  3667. slapi_mods_get_ldapmods_byref(&smods), NULL,
  3668. (void *)plugin_get_default_component_id(),
  3669. 0 /* Flags */);
  3670. slapi_add_internal_pb(pb);
  3671. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  3672. slapi_mods_done(&smods);
  3673. slapi_pblock_destroy(pb);
  3674. }
  3675. charray_free(search_attrs);
  3676. return rc;
  3677. }
  3678. /*
  3679. * Get attribute values of given type from the plugin default config entry
  3680. * (cn=plugin default config,cn=config).
  3681. *
  3682. * Caller is responsible to free attrs by slapi_valueset_free.
  3683. */
  3684. int
  3685. slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset)
  3686. {
  3687. Slapi_Entry **entries = NULL;
  3688. int rc = LDAP_PARAM_ERROR;
  3689. char **search_attrs = NULL; /* used by search */
  3690. if (NULL == type || '\0' == *type || NULL == valueset) { /* nothing to do */
  3691. return rc;
  3692. }
  3693. charray_add(&search_attrs, slapi_ch_strdup(type));
  3694. Slapi_PBlock *pb = slapi_pblock_new();
  3695. /* cn=plugin default config,cn=config */
  3696. slapi_search_internal_set_pb(pb,
  3697. SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN (normalized) */
  3698. LDAP_SCOPE_BASE,
  3699. "(objectclass=*)",
  3700. search_attrs, /* Attrs */
  3701. 0, /* AttrOnly */
  3702. NULL, /* Controls */
  3703. NULL, /* UniqueID */
  3704. (void *)plugin_get_default_component_id(),
  3705. 0);
  3706. slapi_search_internal_pb(pb);
  3707. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  3708. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  3709. if (LDAP_SUCCESS == rc && entries && *entries) {
  3710. /* default config entry exists */
  3711. /* retrieve attribute values from the entry */
  3712. Slapi_Attr *attr = NULL;
  3713. rc = slapi_entry_attr_find(*entries, type, &attr);
  3714. if (0 == rc) { /* type value exists */
  3715. rc = slapi_attr_get_valueset(attr, valueset);
  3716. } else {
  3717. rc = LDAP_NO_SUCH_ATTRIBUTE;
  3718. }
  3719. }
  3720. slapi_free_search_results_internal(pb);
  3721. slapi_pblock_destroy(pb);
  3722. charray_free(search_attrs);
  3723. return rc;
  3724. }
  3725. void
  3726. slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb)
  3727. {
  3728. struct slapdplugin *plug;
  3729. slapi_pblock_get(pb, SLAPI_PLUGIN, &plug);
  3730. struct pluginconfig *config = &plug->plg_conf;
  3731. ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_BIND_ROOT);
  3732. }
  3733. PRBool
  3734. slapi_disorderly_shutdown(PRBool set)
  3735. {
  3736. static PRBool is_disorderly_shutdown = PR_FALSE;
  3737. if (set) {
  3738. is_disorderly_shutdown = PR_TRUE;
  3739. }
  3740. return (is_disorderly_shutdown);
  3741. }
  3742. /*
  3743. * Plugin operation counters
  3744. *
  3745. * Since most plugins can now be stopped and started dynamically we need
  3746. * to take special care when calling a close function. Since many plugins
  3747. * use global locks and data structures, these can not be freed/destroyed
  3748. * while there are active operations using them.
  3749. */
  3750. void
  3751. slapi_plugin_op_started(void *p)
  3752. {
  3753. struct slapdplugin *plugin = (struct slapdplugin *)p;
  3754. if (plugin) {
  3755. slapi_counter_increment(plugin->plg_op_counter);
  3756. }
  3757. }
  3758. void
  3759. slapi_plugin_op_finished(void *p)
  3760. {
  3761. struct slapdplugin *plugin = (struct slapdplugin *)p;
  3762. if (plugin) {
  3763. slapi_counter_decrement(plugin->plg_op_counter);
  3764. }
  3765. }
  3766. /*
  3767. * Waits for the operation counter to hit zero
  3768. */
  3769. void
  3770. plugin_op_all_finished(struct slapdplugin *p)
  3771. {
  3772. while (p && slapi_counter_get_value(p->plg_op_counter) > 0) {
  3773. DS_Sleep(PR_MillisecondsToInterval(100));
  3774. }
  3775. }
  3776. void
  3777. plugin_set_started(struct slapdplugin *p)
  3778. {
  3779. p->plg_started = 1;
  3780. p->plg_stopped = 0;
  3781. }
  3782. void
  3783. plugin_set_stopped(struct slapdplugin *p)
  3784. {
  3785. /*
  3786. * We do not set "plg_stopped" here, because that is only used
  3787. * once the plugin has called its CLOSE function. Setting
  3788. * "plg_started" to 0 will prevent new operations from calling
  3789. * the plugin.
  3790. */
  3791. p->plg_started = 0;
  3792. }
  3793. int
  3794. slapi_plugin_running(Slapi_PBlock *pb)
  3795. {
  3796. int rc = 0;
  3797. struct slapdplugin *plugin;
  3798. slapi_pblock_get(pb, SLAPI_PLUGIN, &plugin);
  3799. if (plugin) {
  3800. rc = plugin->plg_started;
  3801. }
  3802. return rc;
  3803. }
  3804. /*
  3805. * Allow "database" plugins to call the backend/backend txn plugins.
  3806. */
  3807. int
  3808. slapi_plugin_call_preop_be_plugins(Slapi_PBlock *pb, int function)
  3809. {
  3810. int be_func, betxn_func;
  3811. int rc = 0;
  3812. switch (function) {
  3813. case SLAPI_PLUGIN_ADD_OP:
  3814. be_func = SLAPI_PLUGIN_BE_PRE_ADD_FN;
  3815. betxn_func = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
  3816. break;
  3817. case SLAPI_PLUGIN_MOD_OP:
  3818. be_func = SLAPI_PLUGIN_BE_PRE_MODIFY_FN;
  3819. betxn_func = SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN;
  3820. break;
  3821. case SLAPI_PLUGIN_MODRDN_OP:
  3822. be_func = SLAPI_PLUGIN_BE_PRE_MODRDN_FN;
  3823. betxn_func = SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN;
  3824. break;
  3825. case SLAPI_PLUGIN_DEL_OP:
  3826. be_func = SLAPI_PLUGIN_BE_PRE_DELETE_FN;
  3827. betxn_func = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN;
  3828. break;
  3829. default:
  3830. /* invalid function */
  3831. slapi_log_err(SLAPI_LOG_ERR, "slapi_plugin_call_preop_be_plugins",
  3832. "Invalid function specified - backend plugins will not be called.\n");
  3833. return 0;
  3834. }
  3835. /*
  3836. * Call the be preop plugins.
  3837. */
  3838. plugin_call_plugins(pb, be_func);
  3839. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  3840. /*
  3841. * Call the betxn preop plugins.
  3842. */
  3843. if (rc == LDAP_SUCCESS) {
  3844. plugin_call_plugins(pb, betxn_func);
  3845. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  3846. }
  3847. return rc;
  3848. }
  3849. int
  3850. slapi_plugin_call_postop_be_plugins(Slapi_PBlock *pb, int function)
  3851. {
  3852. int be_func, betxn_func;
  3853. int rc = 0;
  3854. switch (function) {
  3855. case SLAPI_PLUGIN_ADD_OP:
  3856. be_func = SLAPI_PLUGIN_BE_POST_ADD_FN;
  3857. betxn_func = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
  3858. break;
  3859. case SLAPI_PLUGIN_MOD_OP:
  3860. be_func = SLAPI_PLUGIN_BE_POST_MODIFY_FN;
  3861. betxn_func = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
  3862. break;
  3863. case SLAPI_PLUGIN_MODRDN_OP:
  3864. be_func = SLAPI_PLUGIN_BE_POST_MODRDN_FN;
  3865. betxn_func = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
  3866. break;
  3867. case SLAPI_PLUGIN_DEL_OP:
  3868. be_func = SLAPI_PLUGIN_BE_POST_DELETE_FN;
  3869. betxn_func = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
  3870. break;
  3871. default:
  3872. /* invalid function */
  3873. slapi_log_err(SLAPI_LOG_ERR, "slapi_plugin_call_postop_be_plugins",
  3874. "Invalid function specified - backend plugins will not be called.\n");
  3875. return 0;
  3876. }
  3877. /* next, give the be txn plugins a crack at it */;
  3878. plugin_call_plugins(pb, betxn_func);
  3879. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  3880. /* finally, give the be plugins a crack at it */
  3881. plugin_call_plugins(pb, be_func);
  3882. if (rc == LDAP_SUCCESS) {
  3883. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  3884. }
  3885. return rc;
  3886. }