ldapfct.c 125 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365
  1. #ident "ldclt @(#)ldapfct.c 1.68 01/05/04"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * This Program is free software; you can redistribute it and/or modify it under
  4. * the terms of the GNU General Public License as published by the Free Software
  5. * Foundation; version 2 of the License.
  6. *
  7. * This Program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with
  12. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  13. * Place, Suite 330, Boston, MA 02111-1307 USA.
  14. *
  15. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  16. * right to link the code of this Program with code not covered under the GNU
  17. * General Public License ("Non-GPL Code") and to distribute linked combinations
  18. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  19. * permitted under this exception must only link to the code of this Program
  20. * through those well defined interfaces identified in the file named EXCEPTION
  21. * found in the source code files (the "Approved Interfaces"). The files of
  22. * Non-GPL Code may instantiate templates or use macros or inline functions from
  23. * the Approved Interfaces without causing the resulting work to be covered by
  24. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  25. * additions to the list of Approved Interfaces. You must obey the GNU General
  26. * Public License in all respects for all of the Program code and other code used
  27. * in conjunction with the Program except the Non-GPL Code covered by this
  28. * exception. If you modify this file, you may extend this exception to your
  29. * version of the file, but you are not obligated to do so. If you do not wish to
  30. * provide this exception without modification, you must delete this exception
  31. * statement from your version and license this file solely under the GPL without
  32. * exception.
  33. *
  34. *
  35. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  36. * Copyright (C) 2006 Red Hat, Inc.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /*
  43. FILE : ldapfct.c
  44. AUTHOR : Jean-Luc SCHWING
  45. VERSION : 1.0
  46. DATE : 04 December 1998
  47. DESCRIPTION :
  48. This file contains the ldap part of this tool.
  49. LOCAL : None.
  50. HISTORY :
  51. ---------+--------------+------------------------------------------------------
  52. dd/mm/yy | Author | Comments
  53. ---------+--------------+------------------------------------------------------
  54. 04/12/98 | JL Schwing | Creation
  55. ---------+--------------+------------------------------------------------------
  56. 09/12/98 | JL Schwing | 1.2 : Forget to free ldap returned data.
  57. ---------+--------------+------------------------------------------------------
  58. 10/12/98 | JL Schwing | 1.3 : Add nb of errors statistics.
  59. ---------+--------------+------------------------------------------------------
  60. 10/12/98 | JL Schwing | 1.4 : Implement asynchronous mode.
  61. ---------+--------------+------------------------------------------------------
  62. 11/12/98 | JL Schwing | 1.5 : fflush(stdout) after each printf.
  63. ---------+--------------+------------------------------------------------------
  64. 14/12/98 | JL Schwing | 1.6 : Implement "-e close".
  65. | New function my_ldap_err2string() to prevent crashes.
  66. ---------+--------------+------------------------------------------------------
  67. 16/12/98 | JL Schwing | 1.7 : Implement "-e add" and "-e delete".
  68. | Create separate functions for connection operations.
  69. ---------+--------------+------------------------------------------------------
  70. 23/12/98 | JL Schwing | 1.8 : Factorise the doXxxx() functions.
  71. | Fix SIGSEGV in ldap_parse_result().
  72. | Implement result decoding in doAddEntry().
  73. ---------+--------------+------------------------------------------------------
  74. 24/12/98 | JL Schwing | 1.9 : Bug fix - should support no message in async.
  75. | Bug fix - forget to check mctx.asyncMax !!!
  76. | Modify the getPending() algorythm to empty the queue
  77. | (if possible).
  78. ---------+--------------+------------------------------------------------------
  79. 29/12/98 | JL Schwing | 1.10: Implement -Q.
  80. | Bug fix mode -q when asynchronous.
  81. ---------+--------------+------------------------------------------------------
  82. 11/01/99 | JL Schwing | 1.11: Implement "-e emailPerson".
  83. | Bug fix - bad building of rdn in buildNewEntry().
  84. ---------+--------------+------------------------------------------------------
  85. 13/01/99 | JL Schwing | 1.12: Implement "-e string".
  86. ---------+--------------+------------------------------------------------------
  87. 14/01/99 | JL Schwing | 1.13: Implement "-s <scope>".
  88. ---------+--------------+------------------------------------------------------
  89. 15/01/99 | JL Schwing | 1.14: Create automatically the missing nodes.
  90. ---------+--------------+------------------------------------------------------
  91. 18/01/99 | JL Schwing | 1.15: Implements "-e randombase".
  92. ---------+--------------+------------------------------------------------------
  93. 18/01/99 | JL Schwing | 1.16: Implements "-e v2".
  94. ---------+--------------+------------------------------------------------------
  95. 20/01/99 | JL Schwing | 1.17: Bug fix - should'nt fail in createMissingNodes()
  96. | if error 68 (Already exists).
  97. | Increment counter for intermediate node(s) too.
  98. ---------+--------------+------------------------------------------------------
  99. 23/01/99 | JL Schwing | 1.18: Improve traces.
  100. | Bug fix - remove leading spaces from rdn.
  101. ---------+--------------+------------------------------------------------------
  102. 26/01/99 | JL Schwing | 1.19: Implement "-e noloop".
  103. ---------+--------------+------------------------------------------------------
  104. 01/02/99 | JL Schwing | 1.20: Create *all* the nodes in createMissingNodes()
  105. ---------+--------------+------------------------------------------------------
  106. 03/02/99 | JL Schwing | 1.21: Create the leaf entry after createMissingNodes()
  107. ---------+--------------+------------------------------------------------------
  108. 26/02/99 | JL Schwing | 1.22: Detect "\," in createMissingNodes().
  109. ---------+--------------+------------------------------------------------------
  110. 04/05/99 | JL Schwing | 1.23: Add call to opAdd().
  111. ---------+--------------+------------------------------------------------------
  112. 04/05/99 | JL Schwing | 1.24: Forget some calls to opAdd().
  113. ---------+--------------+------------------------------------------------------
  114. 04/05/99 | JL Schwing | 1.25: Too many calls to opAdd() !!!
  115. ---------+--------------+------------------------------------------------------
  116. 19/05/99 | JL Schwing | 1.27: Implements doRename().
  117. | Do not print messages about intermediate nodes created
  118. | in quiet mode.
  119. | MOdify getPending()to support rename operations.
  120. ---------+--------------+------------------------------------------------------
  121. 06/03/00 | JL Schwing | 1.28: Test malloc() return value.
  122. ---------+--------------+------------------------------------------------------
  123. 06/03/00 | A. Hornik | 1.29: Bug fix - SEGV if no passwd provided.
  124. ---------+--------------+------------------------------------------------------
  125. 03/08/00 | JL Schwing | 1.30: Improve errors decoding. This improvement
  126. | is to retrieve the additional error string that
  127. | is returned by the server. This is implemented for
  128. | the asynchronous operations and for the synchronous
  129. | search only, because for the other synchronous ops
  130. | we should use ldap_get_lderrno() that is not
  131. | implement in Solaris's libldap.
  132. | Add new function printErrorFromLdap().
  133. ---------+--------------+------------------------------------------------------
  134. 03/08/00 | JL Schwing | 1.31: Fix SIGSEGV in printErrorFromLdap().
  135. ---------+--------------+------------------------------------------------------
  136. 11/08/00 | JL Schwing | 1.32: Improve error decoding.
  137. ---------+--------------+------------------------------------------------------
  138. 18/08/00 | JL Schwing | 1.33: Print begin and end dates.
  139. ---------+--------------+------------------------------------------------------
  140. 25/08/00 | JL Schwing | 1.34: Implement consistent exit status...
  141. ---------+--------------+------------------------------------------------------
  142. 11/10/00 | B Kolics | 1.35: Added SSL connection initialization to
  143. | | connectToServer, createMissingNodes
  144. ---------+--------------+------------------------------------------------------
  145. 26/10/00 | B Kolics | 1.36: Moved SSL client initialization to basicInit
  146. -------------------------------------------------------------------------------
  147. 07/11/00 | JL Schwing | 1.37: Implements dynamic load of ssl-related
  148. | functions.
  149. ---------+--------------+------------------------------------------------------
  150. 07/11/00 | JL Schwing | 1.38: Implement "-e inetOrgPerson".
  151. | Add new error message in createMissingNodes().
  152. ---------+--------------+------------------------------------------------------
  153. 13/11/00 | JL Schwing | 1.39: Add new options "-e randombaselow and ...high"
  154. ---------+--------------+------------------------------------------------------
  155. 14/11/00 | JL Schwing | 1.40: Will now use utils.c functions.
  156. ---------+--------------+------------------------------------------------------
  157. 14/11/00 | JL Schwing | 1.41 : Port on AIX.
  158. ---------+--------------+------------------------------------------------------
  159. 21/11/00 | JL Schwing | 1.42: Implement "-e attreplace=name:mask"
  160. | Add new function buildNewModAttrib().
  161. ---------+--------------+------------------------------------------------------
  162. 24/11/00 | B Kolics | 1.43: Added SSL client authentication
  163. ---------+--------------+------------------------------------------------------
  164. 29/11/00 | JL Schwing | 1.44: Port on NT 4.
  165. ---------+--------------+------------------------------------------------------
  166. 01/12/00 | JL Schwing | 1.45: Port on Linux.
  167. ---------+--------------+------------------------------------------------------
  168. 14/12/00 | JL Schwing | 1.46: Add more trace in VERY_VERBOSE mode.
  169. | Fix some trace messages.
  170. | Add new function dnFromMessage().
  171. ---------+--------------+------------------------------------------------------
  172. 15/12/00 | JL Schwing | 1.47: Implement "-e counteach".
  173. | Implement "-e withnewparent" - cf bug Scopus 526148
  174. ---------+--------------+------------------------------------------------------
  175. 18/12/00 | JL Schwing | 1.48: Add new exit status EXIT_RESSOURCE.
  176. ---------+--------------+------------------------------------------------------
  177. 18/12/00 | JL Schwing | 1.49: Bug fix when -e rename,counteach
  178. ---------+--------------+------------------------------------------------------
  179. 18/12/00 | JL Schwing | 1.50: Bug fix - support errors the user wants to
  180. | ignore in connectToServer().
  181. | Also a bug fix in tttctx->exitStatus management.
  182. ---------+--------------+------------------------------------------------------
  183. 03/01/01 | JL Schwing | 1.51: Implement "-e attrsonly=value".
  184. ---------+--------------+------------------------------------------------------
  185. 05/01/01 | JL Schwing | 1.52: Implement "-e randombinddn" and associated
  186. | "-e randombinddnlow/high"
  187. | Add new function buildNewBindDN().
  188. ---------+--------------+------------------------------------------------------
  189. 05/03/01 | JL Schwing | 1.53: Fix the "anonymous" mode.
  190. ---------+--------------+------------------------------------------------------
  191. 08/03/01 | JL Schwing | 1.54: Change referrals handling.
  192. | Add new functions refRebindProc() and referralSetup().
  193. ---------+--------------+------------------------------------------------------
  194. 14/03/01 | JL Schwing | 1.55: Implement "-e commoncounter"
  195. ---------+--------------+------------------------------------------------------
  196. 14/03/01 | JL Schwing | 1.56: Lint cleanup.
  197. | Port on _WIN32.
  198. ---------+--------------+------------------------------------------------------
  199. 15/03/01 | JL Schwing | 1.57: Implement "-e attrlist=name:name:name"
  200. | Implement "-e randomattrlist=name:name:name"
  201. ---------+--------------+------------------------------------------------------
  202. 19/03/01 | JL Schwing | 1.58: Implement "-e object=filename".
  203. | Implement "-e genldif=filename".
  204. | Add new functions buildVersatileObject() doGenldif()
  205. ---------+--------------+------------------------------------------------------
  206. 21/03/01 | JL Schwing | 1.59: Implements variables in "-e object=filename"
  207. ---------+--------------+------------------------------------------------------
  208. 23/03/01 | JL Schwing | 1.60: Implements data file list support in variants.
  209. | Implements "-e rdn=value".
  210. ---------+--------------+------------------------------------------------------
  211. 28/03/01 | JL Schwing | 1.61: Fix traces.
  212. ---------+--------------+------------------------------------------------------
  213. 28/03/01 | JL Schwing | 1.62: Support -e commoncounter with -e rdn/object
  214. | Increment counters in doGenldif().
  215. | Perfs tunning in doGenldif().
  216. ---------+--------------+------------------------------------------------------
  217. 02/04/01 | JL Schwing | 1.63: Bug fix : large files support for -e genldif.
  218. | Add new function ldclt_write_genldif().
  219. ---------+--------------+------------------------------------------------------
  220. 11/04/01 | JL Schwing | 1.64: Implement [INCRFROMFILE<NOLOOP>(myfile)]
  221. ---------+--------------+------------------------------------------------------
  222. 11/04/01 | JL Schwing | 1.65: Bug fix - should not crash if variable not set.
  223. ---------+--------------+------------------------------------------------------
  224. 03/05/01 | JL Schwing | 1.66: Implement -e randombinddnfromfile=filename.
  225. | Add new function getBindAndPasswdFromFile().
  226. ---------+--------------+------------------------------------------------------
  227. 04/05/01 | JL Schwing | 1.67: Implement -e bindonly.
  228. | Add new function doBindOnly().
  229. ---------+--------------+------------------------------------------------------
  230. 04/05/01 | JL Schwing | 1.68: Lint cleanup.
  231. ---------+--------------+------------------------------------------------------
  232. */
  233. #include <stdio.h> /* printf(), etc... */
  234. #include <string.h> /* strcpy(), etc... */
  235. #include <errno.h> /* errno, etc... */
  236. #include <stdlib.h> /* malloc(), etc... */
  237. #include <lber.h> /* ldap C-API BER declarations */
  238. #include <ldap.h> /* ldap C-API declarations */
  239. #ifdef LDAP_H_FROM_QA_WKA
  240. #include <proto-ldap.h> /* ldap C-API prototypes */
  241. #endif
  242. #ifndef _WIN32 /*JLS 29-11-00*/
  243. #include <unistd.h> /* close(), etc... */
  244. #include <pthread.h> /* pthreads(), etc... */
  245. #endif /*JLS 29-11-00*/
  246. #include "port.h" /* Portability definitions */ /*JLS 29-11-00*/
  247. #include "ldclt.h" /* This tool's include file */
  248. #include "utils.h" /* Utilities functions */ /*JLS 14-11-00*/
  249. #include <sasl.h>
  250. #include "ldaptool-sasl.h"
  251. #if !defined(USE_OPENLDAP)
  252. #include <ldap_ssl.h> /* ldapssl_init(), etc... */
  253. #endif
  254. #include <prprf.h>
  255. #define LDCLT_DEREF_ATTR "secretary"
  256. int ldclt_create_deref_control( LDAP *ld, char *derefAttr, char **attrs, LDAPControl **ctrlp );
  257. #if !defined(USE_OPENLDAP)
  258. int ldclt_build_control( char *oid, BerElement *ber, int freeber, char iscritical, LDAPControl **ctrlp );
  259. #endif
  260. int ldclt_alloc_ber( LDAP *ld, BerElement **berp );
  261. /* ****************************************************************************
  262. FUNCTION : my_ldap_err2string
  263. PURPOSE : This function is targetted to encapsulate the standard
  264. function ldap_err2string(), that sometimes returns
  265. a NULL pointer and thus crashes the appicaliton :-(
  266. INPUT : err = error to decode
  267. OUTPUT : None.
  268. RETURN : A string that describes the error.
  269. DESCRIPTION :
  270. *****************************************************************************/
  271. char *
  272. my_ldap_err2string (
  273. int err)
  274. {
  275. if (ldap_err2string (err) == NULL)
  276. return ("ldap_err2string() returns a NULL pointer !!!");
  277. else
  278. return (ldap_err2string(err));
  279. }
  280. /* New function */ /*JLS 14-12-00*/
  281. /* ****************************************************************************
  282. FUNCTION : dnFromMessage
  283. PURPOSE : Extract the matcheddnp value from an LDAP (error)
  284. message.
  285. INPUT : tttctx = thread context.
  286. res = result to parse
  287. OUTPUT : None.
  288. RETURN : The matcheddnp or an error string.
  289. DESCRIPTION :
  290. *****************************************************************************/
  291. char *
  292. dnFromMessage (
  293. thread_context *tttctx,
  294. LDAPMessage *res)
  295. {
  296. static char *notFound = "*** not found by ldclt ***";
  297. int ret;
  298. int errcodep;
  299. /*
  300. * Maybe a previous call to free...
  301. */
  302. if (tttctx->matcheddnp)
  303. ldap_memfree (tttctx->matcheddnp);
  304. /*
  305. * Get the requested information
  306. */
  307. ret = ldap_parse_result (tttctx->ldapCtx, res, &errcodep,
  308. &(tttctx->matcheddnp), NULL, NULL, NULL, 0);
  309. switch (ret)
  310. {
  311. case LDAP_SUCCESS:
  312. case LDAP_MORE_RESULTS_TO_RETURN:
  313. return (tttctx->matcheddnp);
  314. case LDAP_NO_RESULTS_RETURNED:
  315. case LDAP_DECODING_ERROR:
  316. case LDAP_PARAM_ERROR:
  317. case LDAP_NO_MEMORY:
  318. default:
  319. tttctx->matcheddnp = NULL;
  320. printf ("ldclt[%d]: T%03d: Cannot ldap_parse_result(), error=%d (%s)\n",
  321. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  322. fflush (stdout);
  323. return (notFound);
  324. }
  325. }
  326. /* New function */ /*JLS 03-05-01*/
  327. /* ****************************************************************************
  328. FUNCTION : getBindAndPasswdFromFile
  329. PURPOSE : Get the new bindDN and passwd to use from a dlf.
  330. INPUT : tttctx = this thread context
  331. OUTPUT : None.
  332. RETURN : -1 if error, 0 else.
  333. DESCRIPTION :
  334. *****************************************************************************/
  335. int
  336. getBindAndPasswdFromFile (
  337. thread_context *tttctx)
  338. {
  339. int num; /* Temp. number */
  340. int i; /* For the loops */
  341. /*
  342. * The bind DN is before the first '\t'
  343. */
  344. num = (lrand48() % mctx.rndBindDlf->strNb);
  345. for (i=0 ; mctx.rndBindDlf->str[num][i]!='\0' &&
  346. mctx.rndBindDlf->str[num][i]!='\t' ; i++);
  347. if (mctx.rndBindDlf->str[num][i] == '\0')
  348. {
  349. printf ("ldclt[%d]: %s: No bind DN find line %d of %s\n",
  350. mctx.pid, tttctx->thrdId, num+1, mctx.rndBindFname);
  351. return (-1);
  352. }
  353. strncpy (tttctx->bufBindDN, mctx.rndBindDlf->str[num], i);
  354. tttctx->bufBindDN[i] = '\0';
  355. /*
  356. * Skip the '\t' to find the password.
  357. * The password is from this place up to the end of the line.
  358. */
  359. while (mctx.rndBindDlf->str[num][i]!='\0' &&
  360. mctx.rndBindDlf->str[num][i]=='\t')
  361. i++;
  362. if (mctx.rndBindDlf->str[num][i] == '\0')
  363. {
  364. printf ("ldclt[%d]: %s: No password find line %d of %s\n",
  365. mctx.pid, tttctx->thrdId, num+1, mctx.rndBindFname);
  366. return (-1);
  367. }
  368. strcpy (tttctx->bufPasswd, &(mctx.rndBindDlf->str[num][i]));
  369. return (0);
  370. }
  371. /* New function */ /*JLS 05-01-01*/
  372. /* ****************************************************************************
  373. FUNCTION : buildNewBindDN
  374. PURPOSE : Purpose of the fct
  375. INPUT : tttctx = this thread context
  376. OUTPUT : None.
  377. RETURN : -1 if error, 0 else.
  378. DESCRIPTION :
  379. *****************************************************************************/
  380. int
  381. buildNewBindDN (
  382. thread_context *tttctx)
  383. {
  384. /*
  385. * Maybe we should get the bindDN and passwd from a file ?
  386. */
  387. if (mctx.mod2 & M2_RNDBINDFILE)
  388. return (getBindAndPasswdFromFile (tttctx));
  389. /*
  390. * If we shouldn't operate with a variable bind DN, then the buffers
  391. * are already initiated with the fixed values...
  392. */
  393. if (!(mctx.mode & RANDOM_BINDDN))
  394. return (0);
  395. /*
  396. * Generate the random value we will use for both the bind DN
  397. * and the password.
  398. */
  399. if (mctx.mode & STRING)
  400. (void) randomString (tttctx, mctx.bindDNNbDigit);
  401. else
  402. rnd (tttctx->buf2, mctx.bindDNLow, mctx.bindDNHigh, mctx.bindDNNbDigit);
  403. /*
  404. * First, randomize the bind DN.
  405. */
  406. strncpy (&(tttctx->bufBindDN[tttctx->startBindDN]), tttctx->buf2,
  407. mctx.bindDNNbDigit);
  408. if (mctx.mode & VERY_VERBOSE)
  409. printf ("ldclt[%d]: T%03d: bind DN=\"%s\"\n",
  410. mctx.pid, tttctx->thrdNum, tttctx->bufBindDN);
  411. /*
  412. * Second, randomize the bind password.
  413. */
  414. strncpy (&(tttctx->bufPasswd[tttctx->startPasswd]), tttctx->buf2,
  415. mctx.passwdNbDigit);
  416. if (mctx.mode & VERY_VERBOSE)
  417. printf ("ldclt[%d]: T%03d: bind passwd=\"%s\"\n",
  418. mctx.pid, tttctx->thrdNum, tttctx->bufPasswd);
  419. /*
  420. * No problem found.
  421. */
  422. return (0);
  423. }
  424. #if defined(USE_OPENLDAP)
  425. int
  426. refRebindProc(
  427. LDAP *ldapCtx,
  428. const char *url,
  429. ber_tag_t request,
  430. ber_int_t msgid,
  431. void *arg
  432. )
  433. {
  434. thread_context *tttctx;
  435. struct berval cred;
  436. tttctx = (thread_context *)arg;
  437. cred.bv_val = tttctx->bufPasswd;
  438. cred.bv_len = strlen(tttctx->bufPasswd);
  439. return ldap_sasl_bind_s(ldapCtx, tttctx->bufBindDN, LDAP_SASL_SIMPLE,
  440. &cred, NULL, NULL, NULL);
  441. }
  442. #else /* !USE_OPENLDAP */
  443. /* New function */ /*JLS 08-03-01*/
  444. /* ****************************************************************************
  445. FUNCTION : refRebindProc
  446. PURPOSE : This function is intended to perform the rebind when
  447. a referral requires it.
  448. INPUT : None.
  449. OUTPUT : None.
  450. RETURN : Always LDAP_SUCCESS for the moment...
  451. DESCRIPTION :
  452. *****************************************************************************/
  453. int
  454. refRebindProc (
  455. LDAP *ldapCtx,
  456. char **dnp,
  457. char **passwdp,
  458. int *authmethodp,
  459. int freeit,
  460. void *arg)
  461. {
  462. thread_context *tttctx;
  463. tttctx = (thread_context *)arg;
  464. /*
  465. * We will assume here that the same DN and passwd will be used to
  466. * bind to the referred server, so we will just get the values used
  467. * previously from the thread's context.
  468. */
  469. *dnp = tttctx->bufBindDN;
  470. *passwdp = tttctx->bufPasswd;
  471. *authmethodp = LDAP_AUTH_SIMPLE;
  472. /*
  473. * What should we do with the "freeit" argument ? I do not have any
  474. * memory to free, so let's just ignore it.
  475. */
  476. return (LDAP_SUCCESS);
  477. }
  478. #endif /* !USE_OPENLDAP */
  479. /* New function */ /*JLS 08-03-01*/
  480. /* ****************************************************************************
  481. FUNCTION : referralSetup
  482. PURPOSE : Initiates referral features. This function is called
  483. once after the ldap_init().
  484. INPUT : tttctx = this thread's thread_context
  485. OUTPUT : None.
  486. RETURN : -1 if error, 0 else.
  487. DESCRIPTION :
  488. *****************************************************************************/
  489. int
  490. referralSetup (
  491. thread_context *tttctx)
  492. {
  493. int ret; /* Return value */
  494. void *ref; /* Referral settings */
  495. /*
  496. * Set the referral options...
  497. */
  498. if (mctx.referral == REFERRAL_OFF)
  499. ref = LDAP_OPT_OFF;
  500. else
  501. ref = LDAP_OPT_ON;
  502. ret = ldap_set_option (tttctx->ldapCtx, LDAP_OPT_REFERRALS, &ref);
  503. if (ret < 0)
  504. {
  505. printf ("ldclt[%d]: %s: Cannot ldap_set_option(LDAP_OPT_REFERRALS)\n",
  506. mctx.pid, tttctx->thrdId);
  507. fflush (stdout);
  508. return (-1);
  509. }
  510. /*
  511. * Maybe the user would like to have an authenticated referral rebind ?
  512. * Note : at 09-03-01 ldap_set_rebind_proc() is a void return function
  513. * Note : cannot compile on _WIN32 without the cast... even if I cast to
  514. * the same thing !!!!
  515. */
  516. if (mctx.referral == REFERRAL_REBIND)
  517. #ifdef _WIN32 /*JLS 14-03-01*/
  518. ldap_set_rebind_proc (tttctx->ldapCtx, /*JLS 14-03-01*/
  519. (LDAP_REBINDPROC_CALLBACK *)refRebindProc, /*JLS 14-03-01*/
  520. (void *)tttctx); /*JLS 14-03-01*/
  521. #else /*JLS 14-03-01*/
  522. ldap_set_rebind_proc (tttctx->ldapCtx, refRebindProc, (void *)tttctx);
  523. #endif /*JLS 14-03-01*/
  524. /*
  525. * Normal end
  526. */
  527. return (0);
  528. }
  529. /* ****************************************************************************
  530. FUNCTION : connectToServer
  531. PURPOSE : Realise the connection to the server.
  532. If requested by the user, it also realize the
  533. disconnection prior to connect.
  534. INPUT : tttctx = this thread's thread_context
  535. OUTPUT : None.
  536. RETURN : -1 if error, 0 else.
  537. DESCRIPTION :
  538. *****************************************************************************/
  539. int
  540. connectToServer (
  541. thread_context *tttctx)
  542. {
  543. int ret; /* Return value */
  544. LBER_SOCKET fd; /* LDAP cnx's fd */
  545. int v2v3; /* LDAP version used */
  546. struct berval cred = {0, NULL};
  547. /*
  548. * Maybe close the connection ?
  549. * We will do this *here* to keep the cnx the longest time open.
  550. */
  551. if ((mctx.mode & BIND_EACH_OPER) && (tttctx->ldapCtx != NULL))
  552. {
  553. /*
  554. * Maybe the user want the connection to be *closed* rather than
  555. * being kindly unbinded ?
  556. */
  557. if (mctx.mode & CLOSE_FD)
  558. {
  559. /*
  560. * Get the corresponding fd
  561. */
  562. #ifdef WORKAROUND_4197228
  563. if (getFdFromLdapSession (tttctx->ldapCtx, &fd) < 0)
  564. {
  565. printf ("ldclt[%d]: T%03d: Cannot extract fd from ldap session\n",
  566. mctx.pid, tttctx->thrdNum);
  567. fflush (stdout);
  568. return (-1);
  569. }
  570. #else
  571. ret = ldap_get_option (tttctx->ldapCtx, LDAP_OPT_DESC, &fd);
  572. if (ret < 0)
  573. {
  574. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_DESC)\n",
  575. mctx.pid, tttctx->thrdNum);
  576. fflush (stdout);
  577. return (-1);
  578. }
  579. #endif
  580. #ifdef TRACE_FD_GET_OPTION_BUG
  581. printf ("ldclt[%d]: T%03d: fd=%d\n", mctx.pid, tttctx->thrdNum, (int)fd);
  582. #endif
  583. if (close ((int)fd) < 0)
  584. {
  585. perror ("ldctx");
  586. printf ("ldclt[%d]: T%03d: cannot close(fd=%d), error=%d (%s)\n",
  587. mctx.pid, tttctx->thrdNum, (int)fd, errno, strerror (errno));
  588. return (-1);
  589. }
  590. }
  591. /*
  592. * Ok, anyway, we must ldap_unbind() to release our contextes
  593. * at the client side, otherwise this process will rocket through
  594. * the ceiling.
  595. * But don't be afraid, the UNBIND operation never reach the
  596. * server that will only see a suddent socket disconnection.
  597. */
  598. ret = ldap_unbind_ext (tttctx->ldapCtx, NULL, NULL);
  599. if (ret != LDAP_SUCCESS)
  600. {
  601. fprintf (stderr, "ldclt[%d]: T%03d: cannot ldap_unbind(), error=%d (%s)\n",
  602. mctx.pid, tttctx->thrdNum, ret,strerror (ret));
  603. fflush (stderr);
  604. if (addErrorStat (ret) < 0)
  605. return (-1);
  606. return (-1);
  607. }
  608. tttctx->ldapCtx = NULL;
  609. }
  610. /*
  611. * Maybe create the LDAP context ?
  612. */
  613. if (tttctx->ldapCtx == NULL)
  614. {
  615. const char *mech = LDAP_SASL_SIMPLE;
  616. const char *binddn = NULL;
  617. const char *passwd = NULL;
  618. #if defined(USE_OPENLDAP)
  619. char *ldapurl = NULL;
  620. #endif
  621. #if defined(USE_OPENLDAP)
  622. ldapurl = PR_smprintf("ldap%s://%s:%d/",
  623. (mctx.mode & SSL) ? "s" : "",
  624. mctx.hostname, mctx.port);
  625. if ((ret = ldap_initialize(&tttctx->ldapCtx, ldapurl))) {
  626. printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n",
  627. mctx.pid, tttctx->thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret));
  628. fflush (stdout);
  629. PR_smprintf_free(ldapurl);
  630. return (-1);
  631. }
  632. PR_smprintf_free(ldapurl);
  633. ldapurl = NULL;
  634. #else /* !USE_OPENLDAP */
  635. /*
  636. * SSL is enabled ?
  637. */
  638. if (mctx.mode & SSL)
  639. {
  640. /*
  641. * LDAP session initialization in SSL mode
  642. * added by: B Kolics (11/10/00)
  643. */
  644. tttctx->ldapCtx = ldapssl_init(mctx.hostname, mctx.port, 1);
  645. if (mctx.mode & VERY_VERBOSE)
  646. printf ("ldclt[%d]: T%03d: After ldapssl_init (%s, %d), ldapCtx=0x%p\n",
  647. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port,
  648. tttctx->ldapCtx);
  649. if (tttctx->ldapCtx == NULL)
  650. {
  651. printf ("ldclt[%d]: T%03d: Cannot ldapssl_init (%s, %d), errno=%d\n",
  652. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port, errno);
  653. fflush (stdout);
  654. return (-1);
  655. }
  656. /*
  657. * Client authentication is used ?
  658. */
  659. if (mctx.mode & CLTAUTH)
  660. {
  661. ret = ldapssl_enable_clientauth(tttctx->ldapCtx, "", mctx.keydbpin, mctx.cltcertname);
  662. if (mctx.mode & VERY_VERBOSE)
  663. printf
  664. ("ldclt[%d]: T%03d: After ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  665. mctx.pid, tttctx->thrdNum, tttctx->ldapCtx, mctx.keydbpin,
  666. mctx.cltcertname);
  667. if (ret < 0)
  668. {
  669. printf
  670. ("ldclt[%d]: T%03d: Cannot ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  671. mctx.pid, tttctx->thrdNum, tttctx->ldapCtx, mctx.keydbpin,
  672. mctx.cltcertname);
  673. ldap_perror(tttctx->ldapCtx, "ldapssl_enable_clientauth");
  674. fflush (stdout);
  675. return (-1);
  676. }
  677. }
  678. } else {
  679. /*
  680. * connection initialization in normal, unencrypted mode
  681. */
  682. tttctx->ldapCtx = ldap_init (mctx.hostname, mctx.port);
  683. if (mctx.mode & VERY_VERBOSE)
  684. printf ("ldclt[%d]: T%03d: After ldap_init (%s, %d), ldapCtx=0x%p\n",
  685. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port,
  686. tttctx->ldapCtx);
  687. if (tttctx->ldapCtx == NULL)
  688. {
  689. printf ("ldclt[%d]: T%03d: Cannot ldap_init (%s, %d), errno=%d\n",
  690. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port, errno);
  691. fflush (stdout);
  692. return (-1);
  693. }
  694. }
  695. #endif /* !USE_OPENLDAP */
  696. if (mctx.mode & CLTAUTH) {
  697. mech = "EXTERNAL";
  698. binddn = "";
  699. passwd = NULL;
  700. } else {
  701. binddn = tttctx->bufBindDN?tttctx->bufBindDN:mctx.bindDN;
  702. passwd = tttctx->bufPasswd?tttctx->bufPasswd:mctx.passwd;
  703. if (passwd) {
  704. cred.bv_val = (char *)passwd;
  705. cred.bv_len = strlen(passwd);
  706. }
  707. }
  708. if (mctx.mode & LDAP_V2)
  709. v2v3 = LDAP_VERSION2;
  710. else
  711. v2v3 = LDAP_VERSION3;
  712. ret = ldap_set_option (tttctx->ldapCtx, LDAP_OPT_PROTOCOL_VERSION, &v2v3);
  713. if (ret < 0)
  714. {
  715. printf ("ldclt[%d]: T%03d: Cannot ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)\n",
  716. mctx.pid, tttctx->thrdNum);
  717. fflush (stdout);
  718. return (-1);
  719. }
  720. /*
  721. * Set the referral options...
  722. */
  723. if (referralSetup (tttctx) < 0)
  724. return (-1);
  725. }
  726. /*
  727. * Let's save some time here... If no bindDN is provided, the tool is
  728. * working in anonymous mode, i.e. we may consider it is always
  729. * binded.
  730. * NOTE : maybe some cleanup is needed with the tests mctx.bindDN!=NULL
  731. * below in this function ?
  732. * 03-05-01 : no cleanup I think, cf M2_RNDBINDFILE
  733. */
  734. if ((mctx.bindDN == NULL) && ((!(mctx.mod2 & M2_RNDBINDFILE))
  735. && (!(mctx.mod2 & M2_SASLAUTH))))
  736. { /*JLS 05-03-01*/
  737. tttctx->binded = 1; /*JLS 05-03-01*/
  738. return (0); /*JLS 05-03-01*/
  739. } /*JLS 05-03-01*/
  740. /*
  741. * Maybe we should bind ?
  742. */
  743. /*
  744. * for SSL client authentication, SASL BIND is used
  745. */
  746. if ((mctx.mode & CLTAUTH) && ((!(tttctx->binded)) ||
  747. (mctx.mode & BIND_EACH_OPER)))
  748. {
  749. if (mctx.mode & VERY_VERBOSE)
  750. printf ("ldclt[%d]: T%03d: Before ldap_sasl_bind_s\n",
  751. mctx.pid, tttctx->thrdNum);
  752. ret = ldap_sasl_bind_s (tttctx->ldapCtx, "", "EXTERNAL", NULL, NULL, NULL,
  753. NULL);
  754. if (mctx.mode & VERY_VERBOSE)
  755. printf ("ldclt[%d]: T%03d: After ldap_sasl_bind_s\n",
  756. mctx.pid, tttctx->thrdNum);
  757. if (ret == LDAP_SUCCESS) /*JLS 18-12-00*/
  758. tttctx->binded = 1; /*JLS 18-12-00*/
  759. else /*JLS 18-12-00*/
  760. { /*JLS 18-12-00*/
  761. tttctx->binded = 0; /*JLS 18-12-00*/
  762. if (ignoreError (ret)) /*JLS 18-12-00*/
  763. { /*JLS 18-12-00*/
  764. if (!(mctx.mode & QUIET)) /*JLS 18-12-00*/
  765. { /*JLS 18-12-00*/
  766. printf ("ldclt[%d]: T%03d: Cannot ldap_sasl_bind_s, error=%d (%s)\n",
  767. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  768. fflush (stdout); /*JLS 18-12-00*/
  769. } /*JLS 18-12-00*/
  770. if (addErrorStat (ret) < 0) /*JLS 18-12-00*/
  771. return (-1); /*JLS 18-12-00*/
  772. return (0); /*JLS 18-12-00*/
  773. } /*JLS 18-12-00*/
  774. else /*JLS 18-12-00*/
  775. { /*JLS 18-12-00*/
  776. printf ("ldclt[%d]: T%03d: Cannot ldap_sasl_bind_s, error=%d (%s)\n",
  777. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  778. fflush (stdout); /*JLS 18-12-00*/
  779. tttctx->exitStatus = EXIT_NOBIND; /*JLS 18-12-00*/
  780. if (addErrorStat (ret) < 0) /*JLS 18-12-00*/
  781. return (-1); /*JLS 18-12-00*/
  782. return (-1); /*JLS 18-12-00*/
  783. } /*JLS 18-12-00*/
  784. }
  785. } else if ((mctx.mod2 & M2_SASLAUTH) && ((!(tttctx->binded)) ||
  786. (mctx.mode & BIND_EACH_OPER))) {
  787. void *defaults;
  788. char *my_saslauthid = NULL;
  789. if ( mctx.sasl_mech == NULL) {
  790. fprintf( stderr, "Please specify the SASL mechanism name when "
  791. "using SASL options\n");
  792. return (-1);
  793. }
  794. if ( mctx.sasl_secprops != NULL) {
  795. ret = ldap_set_option( tttctx->ldapCtx, LDAP_OPT_X_SASL_SECPROPS,
  796. (void *) mctx.sasl_secprops );
  797. if ( ret != LDAP_SUCCESS ) {
  798. fprintf( stderr, "Unable to set LDAP_OPT_X_SASL_SECPROPS: %s\n",
  799. mctx.sasl_secprops );
  800. return (-1);
  801. }
  802. }
  803. /*
  804. * Generate the random authid if set up so
  805. */
  806. if (mctx.mod2 & M2_RANDOM_SASLAUTHID)
  807. {
  808. rnd (tttctx->buf2, mctx.sasl_authid_low, mctx.sasl_authid_high,
  809. mctx.sasl_authid_nbdigit);
  810. strncpy (&(tttctx->bufSaslAuthid[tttctx->startSaslAuthid]),
  811. tttctx->buf2, mctx.sasl_authid_nbdigit);
  812. my_saslauthid = tttctx->bufSaslAuthid;
  813. if (mctx.mode & VERY_VERBOSE)
  814. printf ("ldclt[%d]: T%03d: Sasl Authid=\"%s\"\n",
  815. mctx.pid, tttctx->thrdNum, tttctx->bufSaslAuthid);
  816. }
  817. else
  818. {
  819. my_saslauthid = mctx.sasl_authid;
  820. }
  821. defaults = ldaptool_set_sasl_defaults( tttctx->ldapCtx, mctx.sasl_flags, mctx.sasl_mech,
  822. my_saslauthid, mctx.sasl_username, mctx.passwd, mctx.sasl_realm );
  823. if (defaults == NULL) {
  824. perror ("malloc");
  825. exit (LDAP_NO_MEMORY);
  826. }
  827. #if defined(USE_OPENLDAP)
  828. ret = ldap_sasl_interactive_bind_s( tttctx->ldapCtx, mctx.bindDN, mctx.sasl_mech,
  829. NULL, NULL, mctx.sasl_flags,
  830. ldaptool_sasl_interact, defaults );
  831. #else
  832. ret = ldap_sasl_interactive_bind_ext_s( tttctx->ldapCtx, mctx.bindDN, mctx.sasl_mech,
  833. NULL, NULL, mctx.sasl_flags,
  834. ldaptool_sasl_interact, defaults, NULL );
  835. #endif
  836. if (ret != LDAP_SUCCESS ) {
  837. tttctx->binded = 0;
  838. if (!(mctx.mode & QUIET)) {
  839. fprintf(stderr, "Error: could not bind: %d:%s\n",
  840. ret, my_ldap_err2string(ret));
  841. }
  842. if (addErrorStat (ret) < 0)
  843. return (-1);
  844. } else {
  845. tttctx->binded = 1;
  846. }
  847. ldaptool_free_defaults( defaults );
  848. } else {
  849. if (((mctx.bindDN != NULL) || (mctx.mod2 & M2_RNDBINDFILE)) && /*03-05-01*/
  850. ((!(tttctx->binded)) || (mctx.mode & BIND_EACH_OPER)))
  851. {
  852. struct berval *servercredp = NULL;
  853. char *binddn = NULL;
  854. char *passwd = NULL;
  855. if (buildNewBindDN (tttctx) < 0) /*JLS 05-01-01*/
  856. return (-1); /*JLS 05-01-01*/
  857. if (tttctx->bufPasswd) {
  858. binddn = tttctx->bufBindDN;
  859. passwd = tttctx->bufPasswd;
  860. } else if (mctx.passwd) {
  861. binddn = mctx.bindDN;
  862. passwd = mctx.passwd;
  863. }
  864. if (passwd) {
  865. cred.bv_val = passwd;
  866. cred.bv_len = strlen(passwd);
  867. }
  868. if (mctx.mode & VERY_VERBOSE)
  869. printf ("ldclt[%d]: T%03d: Before ldap_simple_bind_s (%s, %s)\n",
  870. mctx.pid, tttctx->thrdNum, binddn,
  871. passwd?passwd:"NO PASSWORD PROVIDED");
  872. ret = ldap_sasl_bind_s (tttctx->ldapCtx, binddn,
  873. LDAP_SASL_SIMPLE, &cred, NULL, NULL, &servercredp); /*JLS 05-01-01*/
  874. ber_bvfree(servercredp);
  875. if (mctx.mode & VERY_VERBOSE)
  876. printf ("ldclt[%d]: T%03d: After ldap_simple_bind_s (%s, %s)\n",
  877. mctx.pid, tttctx->thrdNum, binddn,
  878. passwd?passwd:"NO PASSWORD PROVIDED");
  879. if (ret == LDAP_SUCCESS) /*JLS 18-12-00*/
  880. tttctx->binded = 1; /*JLS 18-12-00*/
  881. else /*JLS 18-12-00*/
  882. { /*JLS 18-12-00*/
  883. tttctx->binded = 0; /*JLS 18-12-00*/
  884. if (ignoreError (ret)) /*JLS 18-12-00*/
  885. { /*JLS 18-12-00*/
  886. if (!(mctx.mode & QUIET)) /*JLS 18-12-00*/
  887. { /*JLS 18-12-00*/
  888. printf("ldclt[%d]: T%03d: Cannot ldap_simple_bind_s (%s, %s), error=%d (%s)\n",
  889. mctx.pid, tttctx->thrdNum, tttctx->bufBindDN,
  890. mctx.passwd?tttctx->bufPasswd:"NO PASSWORD PROVIDED",
  891. ret, my_ldap_err2string (ret));
  892. fflush (stdout); /*JLS 18-12-00*/
  893. } /*JLS 18-12-00*/
  894. if (addErrorStat (ret) < 0) /*JLS 18-12-00*/
  895. return (-1); /*JLS 18-12-00*/
  896. return (0); /*JLS 18-12-00*/
  897. } /*JLS 18-12-00*/
  898. else /*JLS 18-12-00*/
  899. { /*JLS 18-12-00*/
  900. printf ("ldclt[%d]: T%03d: Cannot ldap_simple_bind_s (%s, %s), error=%d (%s)\n",
  901. mctx.pid, tttctx->thrdNum, tttctx->bufBindDN,
  902. mctx.passwd?tttctx->bufPasswd:"NO PASSWORD PROVIDED",
  903. ret, my_ldap_err2string (ret));
  904. fflush (stdout); /*JLS 18-12-00*/
  905. tttctx->exitStatus = EXIT_NOBIND; /*JLS 18-12-00*/
  906. if (addErrorStat (ret) < 0) /*JLS 18-12-00*/
  907. return (-1); /*JLS 18-12-00*/
  908. return (-1); /*JLS 18-12-00*/
  909. } /*JLS 18-12-00*/
  910. }
  911. }
  912. }
  913. /*
  914. * Normal end
  915. */
  916. return (0);
  917. }
  918. /* ****************************************************************************
  919. FUNCTION : buildVersatileAttribute
  920. PURPOSE : Build a new attribute value using the definitions of
  921. the parameters.
  922. The pointer returned is always to a safe buffer inside
  923. the attribute.
  924. INPUT : tttctx = thread context
  925. object = object definition
  926. attrib = attribute to build
  927. OUTPUT : None.
  928. RETURN : NULL if error, pointer to the new value else.
  929. DESCRIPTION :
  930. *****************************************************************************/
  931. char *
  932. buildVersatileAttribute (
  933. thread_context *tttctx,
  934. vers_object *object,
  935. vers_attribute *attrib)
  936. {
  937. vers_field *field; /* To parse the fields */
  938. int num; /* Temp. number */
  939. /*
  940. * Maybe this attribute has a constant value ?
  941. * (i.e. only one field, constant value)
  942. */
  943. if (attrib->buf == NULL)
  944. return (attrib->field->cst);
  945. /*
  946. * Well, it looks like we will have to build the new value
  947. */
  948. attrib->buf[0] = '\0'; /* No field yet */
  949. for (field=attrib->field ; field!=NULL ; field=field->next)
  950. {
  951. switch (field->how)
  952. {
  953. case HOW_CONSTANT:
  954. strcat (attrib->buf, field->cst);
  955. break;
  956. case HOW_INCR_FROM_FILE:
  957. if (mctx.mode & COMMON_COUNTER)
  958. {
  959. num = incrementCommonCounterObject (tttctx, field->commonField);
  960. if (num < 0)
  961. return (NULL);
  962. }
  963. else
  964. {
  965. if (field->cnt > field->high)
  966. field->cnt = field->low;
  967. num = field->cnt;
  968. field->cnt++; /* Next value for next loop */
  969. }
  970. strcat (attrib->buf, field->dlf->str[num]);
  971. if (field->var != -1)
  972. strcpy (object->var[field->var], field->dlf->str[num]);
  973. break;
  974. case HOW_INCR_FROM_FILE_NL:
  975. if (mctx.mode & COMMON_COUNTER)
  976. {
  977. num = incrementCommonCounterObject (tttctx, field->commonField);
  978. if (num < 0)
  979. return (NULL);
  980. }
  981. else
  982. {
  983. if (field->cnt > field->high)
  984. {
  985. printf ("ldclt[%d]: %s: Hit top incrementeal value\n",
  986. mctx.pid, tttctx->thrdId);
  987. return(NULL);
  988. }
  989. num = field->cnt;
  990. field->cnt++; /* Next value for next loop */
  991. }
  992. strcat (attrib->buf, field->dlf->str[num]);
  993. if (field->var != -1)
  994. strcpy (object->var[field->var], tttctx->buf2);
  995. break;
  996. case HOW_INCR_NB:
  997. if (mctx.mode & COMMON_COUNTER)
  998. {
  999. num = incrementCommonCounterObject (tttctx, field->commonField);
  1000. if (num < 0)
  1001. return (NULL);
  1002. }
  1003. else
  1004. {
  1005. if (field->cnt > field->high)
  1006. field->cnt = field->low;
  1007. num = field->cnt;
  1008. field->cnt++; /* Next value for next loop */
  1009. }
  1010. sprintf (tttctx->buf2, "%0*d", field->nb, num);
  1011. strcat (attrib->buf, tttctx->buf2);
  1012. if (field->var != -1)
  1013. strcpy (object->var[field->var], tttctx->buf2);
  1014. break;
  1015. case HOW_INCR_NB_NOLOOP:
  1016. if (mctx.mode & COMMON_COUNTER)
  1017. {
  1018. num = incrementCommonCounterObject (tttctx, field->commonField);
  1019. if (num < 0)
  1020. return (NULL);
  1021. }
  1022. else
  1023. {
  1024. if (field->cnt > field->high)
  1025. {
  1026. printf ("ldclt[%d]: %s: Hit top incrementeal value\n",
  1027. mctx.pid, tttctx->thrdId);
  1028. return(NULL);
  1029. }
  1030. num = field->cnt;
  1031. field->cnt++; /* Next value for next loop */
  1032. }
  1033. sprintf (tttctx->buf2, "%0*d", field->nb, num);
  1034. strcat (attrib->buf, tttctx->buf2);
  1035. if (field->var != -1)
  1036. strcpy (object->var[field->var], tttctx->buf2);
  1037. break;
  1038. case HOW_RND_FROM_FILE:
  1039. num = (lrand48() % field->dlf->strNb);
  1040. strcat (attrib->buf, field->dlf->str[num]);
  1041. if (field->var != -1)
  1042. strcpy (object->var[field->var], field->dlf->str[num]);
  1043. break;
  1044. case HOW_RND_NUMBER:
  1045. rnd (tttctx->buf2, field->low, field->high, field->nb);
  1046. strcat (attrib->buf, tttctx->buf2);
  1047. if (field->var != -1)
  1048. strcpy (object->var[field->var], tttctx->buf2);
  1049. break;
  1050. case HOW_RND_STRING:
  1051. (void) randomString (tttctx, field->nb);
  1052. strcat (attrib->buf, tttctx->buf2);
  1053. if (field->var != -1)
  1054. strcpy (object->var[field->var], tttctx->buf2);
  1055. break;
  1056. case HOW_VARIABLE:
  1057. if (object->var[field->var] == NULL) /*JLS 11-04-01*/
  1058. { /*JLS 11-04-01*/
  1059. printf ("ldclt[%d]: %s: Error : unset variable %c in %s\n",
  1060. mctx.pid, tttctx->thrdId,
  1061. 'A'+field->var, attrib->src); /*JLS 11-04-01*/
  1062. return(NULL); /*JLS 11-04-01*/
  1063. } /*JLS 11-04-01*/
  1064. strcat (attrib->buf, object->var[field->var]);
  1065. break;
  1066. default:
  1067. /*
  1068. * Should not happen, unless new variant parsed and not
  1069. * integrated here, or "jardinage"....
  1070. */
  1071. field = NULL;
  1072. field->how = 22; /* Crash !!! */
  1073. break;
  1074. }
  1075. }
  1076. /*
  1077. * Return the new value.
  1078. */
  1079. return (attrib->buf);
  1080. }
  1081. /* ****************************************************************************
  1082. FUNCTION : buildRandomRdnOrFilter
  1083. PURPOSE : This function will build a random string (rdn or filter)
  1084. to be used by ldap_search() or ldap_add() or etc...
  1085. The result is in tttctx->bufFilter
  1086. INPUT : tttctx = thread context
  1087. OUTPUT : None.
  1088. RETURN : -1 if error, 0 else.
  1089. DESCRIPTION :
  1090. *****************************************************************************/
  1091. int
  1092. buildRandomRdnOrFilter (
  1093. thread_context *tttctx)
  1094. {
  1095. /*
  1096. * Maybe we will operate with a variable base DN ?
  1097. */
  1098. if (mctx.mode & RANDOM_BASE)
  1099. {
  1100. if (mctx.mode & STRING)
  1101. (void) randomString (tttctx, mctx.baseDNNbDigit);
  1102. else
  1103. rnd (tttctx->buf2, mctx.baseDNLow, mctx.baseDNHigh, /*JLS 14-11-00*/
  1104. mctx.baseDNNbDigit); /*JLS 14-11-00*/
  1105. strncpy (&(tttctx->bufBaseDN[tttctx->startBaseDN]),
  1106. tttctx->buf2, mctx.baseDNNbDigit);
  1107. if (mctx.mode & VERY_VERBOSE)
  1108. printf ("ldclt[%d]: T%03d: base DN=\"%s\"\n",
  1109. mctx.pid, tttctx->thrdNum, tttctx->bufBaseDN);
  1110. }
  1111. /*
  1112. * Maybe we must build a random attribute value ?
  1113. * We only support random string generation here.
  1114. */
  1115. if (mctx.mode & ATTR_REPLACE) /*JLS 21-11-00*/
  1116. { /*JLS 21-11-00*/
  1117. (void) randomString (tttctx, mctx.attrplNbDigit); /*JLS 21-11-00*/
  1118. strncpy (&(tttctx->bufAttrpl[tttctx->startAttrpl]), /*JLS 21-11-00*/
  1119. tttctx->buf2, mctx.attrplNbDigit); /*JLS 21-11-00*/
  1120. if (mctx.mode & VERY_VERBOSE) /*JLS 21-11-00*/
  1121. printf ("ldclt[%d]: T%03d: attrib=\"%s\"\n",
  1122. mctx.pid, tttctx->thrdNum, tttctx->bufAttrpl);
  1123. } /*JLS 21-11-00*/
  1124. /*
  1125. * Maybe we must use a variant-rdn style ?
  1126. */
  1127. if (mctx.mod2 & M2_RDN_VALUE) /*JLS 23-03-01*/
  1128. { /*JLS 23-03-01*/
  1129. char *buf; /* Temp for new value */ /*JLS 23-03-01*/
  1130. /*JLS 23-03-01*/
  1131. buf = buildVersatileAttribute (tttctx, /*JLS 23-03-01*/
  1132. tttctx->object, tttctx->object->rdn); /*JLS 23-03-01*/
  1133. if (buf == NULL) /*JLS 23-03-01*/
  1134. return (-1); /*JLS 23-03-01*/
  1135. strcpy (tttctx->bufFilter, tttctx->object->rdnName); /*JLS 23-03-01*/
  1136. strcat (tttctx->bufFilter, "="); /*JLS 23-03-01*/
  1137. strcat (tttctx->bufFilter, buf); /*JLS 23-03-01*/
  1138. if (mctx.mode & VERY_VERBOSE) /*JLS 28-03-01*/
  1139. printf ("ldclt[%d]: %s: rdn variant mode:filter=\"%s\"\n",
  1140. mctx.pid, tttctx->thrdId, tttctx->bufFilter);
  1141. } /*JLS 23-03-01*/
  1142. else /*JLS 23-03-01*/
  1143. { /*JLS 23-03-01*/
  1144. /*
  1145. * Build the new filter string
  1146. */
  1147. if (mctx.mode & RANDOM)
  1148. {
  1149. if (mctx.mode & STRING)
  1150. (void) randomString (tttctx, mctx.randomNbDigit);
  1151. else
  1152. rnd (tttctx->buf2, mctx.randomLow, mctx.randomHigh, /*JLS 14-11-00*/
  1153. mctx.randomNbDigit); /*JLS 14-11-00*/
  1154. strncpy (&(tttctx->bufFilter[tttctx->startRandom]),
  1155. tttctx->buf2, mctx.randomNbDigit);
  1156. if (mctx.mode & VERY_VERBOSE)
  1157. printf ("ldclt[%d]: %s: random mode:filter=\"%s\"\n",
  1158. mctx.pid, tttctx->thrdId, tttctx->bufFilter);
  1159. }
  1160. if (mctx.mode & INCREMENTAL)
  1161. {
  1162. if (mctx.mode & COMMON_COUNTER) /*JLS 14-03-01*/
  1163. { /*JLS 14-03-01*/
  1164. int val; /*JLS 14-03-01*/
  1165. val = incrementCommonCounter (tttctx); /*JLS 14-03-01*/
  1166. if (val == -1) /*JLS 14-03-01*/
  1167. return (-1); /*JLS 14-03-01*/
  1168. sprintf (tttctx->buf2, "%0*d", mctx.randomNbDigit, val);/*JLS 14-03-01*/
  1169. } /*JLS 14-03-01*/
  1170. else /*JLS 14-03-01*/
  1171. { /*JLS 14-03-01*/
  1172. tttctx->lastVal++;
  1173. if (tttctx->lastVal > mctx.randomHigh)
  1174. {
  1175. if (!(mctx.mode & NOLOOP))
  1176. tttctx->lastVal = mctx.randomLow;
  1177. else
  1178. {
  1179. /*
  1180. * Well, there is no clean way to exit. Let's use the error
  1181. * condition and hope all will be ok.
  1182. */
  1183. printf ("ldclt[%d]: %s: Hit top incrementeal value\n",
  1184. mctx.pid, tttctx->thrdId);
  1185. return (-1);
  1186. }
  1187. }
  1188. sprintf (tttctx->buf2, "%0*d", mctx.randomNbDigit, tttctx->lastVal);
  1189. } /*JLS 14-03-01*/
  1190. strncpy (&(tttctx->bufFilter[tttctx->startRandom]), tttctx->buf2,
  1191. mctx.randomNbDigit);
  1192. if (mctx.mode & VERY_VERBOSE)
  1193. printf ("ldclt[%d]: %s: incremental mode:filter=\"%s\"\n",
  1194. mctx.pid, tttctx->thrdId, tttctx->bufFilter);
  1195. }
  1196. } /*JLS 23-03-01*/
  1197. return (0);
  1198. }
  1199. /* ****************************************************************************
  1200. FUNCTION : addAttrib
  1201. PURPOSE : Add a new attribute to the given LDAPMod array
  1202. INPUT : attrs = existing LDAPMod array
  1203. nb = number of entries in the array
  1204. newattr = new attribute to add to the list
  1205. OUTPUT : None.
  1206. RETURN : -1 if error, 0 else.
  1207. DESCRIPTION : Important note: the first time this function is called,
  1208. it must be with nb==0.
  1209. *****************************************************************************/
  1210. int
  1211. addAttrib (
  1212. LDAPMod **attrs,
  1213. int nb,
  1214. LDAPMod *newattr)
  1215. {
  1216. attrs[nb] = (LDAPMod *) malloc (sizeof (LDAPMod));
  1217. if (attrs[nb] == NULL) /*JLS 06-03-00*/
  1218. { /*JLS 06-03-00*/
  1219. printf ("ldclt[%d]: Txxx: cannot malloc(attrs[%d]), error=%d (%s)\n",
  1220. mctx.pid, nb, errno, strerror (errno));
  1221. return (-1); /*JLS 06-03-00*/
  1222. } /*JLS 06-03-00*/
  1223. memcpy (attrs[nb], newattr, sizeof (LDAPMod));
  1224. attrs[nb+1] = NULL;
  1225. return (0);
  1226. }
  1227. /* ****************************************************************************
  1228. FUNCTION : freeAttrib
  1229. PURPOSE : Free an array of addAttrib.
  1230. INPUT : attrs = LDAPMod array to free
  1231. OUTPUT : None.
  1232. RETURN : -1 if error, 0 else.
  1233. DESCRIPTION :
  1234. *****************************************************************************/
  1235. int
  1236. freeAttrib (
  1237. LDAPMod **attrs)
  1238. {
  1239. int i;
  1240. int j;
  1241. for (i=0 ; attrs[i]!=NULL ; i++) {
  1242. if (attrs[i]->mod_op & LDAP_MOD_BVALUES) {
  1243. for (j=0; attrs[i]->mod_bvalues[j] != NULL; j++) {
  1244. free (attrs[i]->mod_bvalues[j]);
  1245. }
  1246. free (attrs[i]->mod_bvalues);
  1247. } else {
  1248. free (attrs[i]->mod_values);
  1249. }
  1250. free (attrs[i]);
  1251. }
  1252. return (0);
  1253. }
  1254. /* ****************************************************************************
  1255. FUNCTION : strList1
  1256. PURPOSE : Create a list (array) of two strings
  1257. INPUT : str1 = the first string.
  1258. OUTPUT : None.
  1259. RETURN : Pointer to the char *str[2]
  1260. DESCRIPTION :
  1261. *****************************************************************************/
  1262. char **
  1263. strList1 (
  1264. char *str1)
  1265. {
  1266. char **p;
  1267. p = (char **) malloc (2 * sizeof (char *));
  1268. if (p == NULL) /*JLS 06-03-00*/
  1269. { /*JLS 06-03-00*/
  1270. printf ("ldclt[%d]: Txxx: cannot malloc(p), error=%d (%s)\n",
  1271. mctx.pid, errno, strerror (errno));
  1272. ldcltExit (EXIT_RESSOURCE); /*JLS 18-12-00*/
  1273. } /*JLS 06-03-00*/
  1274. p[0] = str1;
  1275. p[1] = NULL;
  1276. return (p);
  1277. }
  1278. /* New function */ /*JLS 03-08-00*/
  1279. /* ****************************************************************************
  1280. FUNCTION : printErrorFromLdap
  1281. PURPOSE : Print the error message returned by ldap.
  1282. INPUT : tttctx = thread context
  1283. res = LDAP result
  1284. errcode = error code
  1285. errmsg = error message
  1286. OUTPUT : None.
  1287. RETURN : -1 if error, 0 else.
  1288. DESCRIPTION :
  1289. *****************************************************************************/
  1290. int
  1291. printErrorFromLdap (
  1292. thread_context *tttctx,
  1293. LDAPMessage *res,
  1294. int errcode,
  1295. char *errmsg)
  1296. {
  1297. int ret; /* Return value */
  1298. char *addErrMsg; /* Additional error msg */
  1299. int errcodep; /* Async error code */ /*JLS 11-08-00*/
  1300. /*
  1301. * Print the error message and error code
  1302. */
  1303. printf ("ldclt[%d]: T%03d: %s, error=%d (%s",
  1304. mctx.pid, tttctx->thrdNum, errmsg,
  1305. errcode, my_ldap_err2string (errcode));
  1306. /*
  1307. * See if there is an additional error message...
  1308. */
  1309. ret = ldap_parse_result (tttctx->ldapCtx, res, &errcodep, /*JLS 11-08-00*/
  1310. NULL, &addErrMsg, NULL, NULL, 0);
  1311. if (ret != LDAP_SUCCESS)
  1312. {
  1313. printf (")\n");
  1314. printf ("ldclt[%d]: T%03d: errcodep = %d\n",
  1315. mctx.pid, tttctx->thrdNum, errcodep);
  1316. printf ("ldclt[%d]: T%03d: Cannot ldap_parse_result(), error=%d (%s)\n",
  1317. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  1318. return (-1);
  1319. }
  1320. /*
  1321. * Ok, we were able to retrieve more information...
  1322. * Well, the errcodep is the error of the operation parsed by
  1323. * ldap_parse_result(), so we will print it if different from
  1324. * the one given in argument to this function...
  1325. */
  1326. if (errcodep != errcode) /*JLS 11-08-00*/
  1327. printf ("ldclt[%d]: errcodep=%d (%s)",
  1328. mctx.pid, errcodep, my_ldap_err2string (errcodep));
  1329. if ((addErrMsg != NULL) && (*addErrMsg != '\0'))
  1330. {
  1331. printf (" - %s", addErrMsg);
  1332. ldap_memfree (addErrMsg);
  1333. }
  1334. printf (")\n");
  1335. /*
  1336. * Don't forget to flush !
  1337. */
  1338. fflush (stdout);
  1339. return (0);
  1340. }
  1341. /* ****************************************************************************
  1342. FUNCTION : buildNewModAttribFile
  1343. PURPOSE : Build a new (random or incremental) target DN and the
  1344. corresponding LDAPMod for attribute modification.
  1345. INPUT : tttctx = thread context
  1346. OUTPUT : newDN = DN of the new entry
  1347. attrs = attributes for the ldap_modify
  1348. RETURN : -1 if error, 0 else.
  1349. *****************************************************************************/
  1350. int
  1351. buildNewModAttribFile (
  1352. thread_context *tttctx,
  1353. char *newDn,
  1354. LDAPMod **attrs)
  1355. {
  1356. int nbAttribs; /* Nb of attributes */
  1357. LDAPMod attribute; /* To build the attributes */
  1358. struct berval *bv = malloc(sizeof(struct berval));
  1359. attribute.mod_bvalues = (struct berval **)malloc(2 * sizeof(struct berval *));
  1360. int rc = 0;
  1361. if ((bv == NULL) || (attribute.mod_bvalues == NULL)) {
  1362. rc = -1;
  1363. goto error;
  1364. }
  1365. /*
  1366. * Build the new DN
  1367. * We will assume that the filter (-f argument) is set to use it
  1368. * to build the rdn of the new entry.
  1369. * Note that the random new attribute is also build by this function.
  1370. */
  1371. if (buildRandomRdnOrFilter (tttctx) < 0) {
  1372. rc = -1;
  1373. goto error;
  1374. }
  1375. strcpy (newDn, tttctx->bufFilter);
  1376. strcat (newDn, ",");
  1377. strcat (newDn, tttctx->bufBaseDN);
  1378. /*
  1379. * Build the attributes modification
  1380. */
  1381. bv->bv_len = mctx.attrplFileSize;
  1382. bv->bv_val = mctx.attrplFileContent;
  1383. attrs[0] = NULL; /* No attributes yet */
  1384. nbAttribs = 0; /* No attributes yet */
  1385. attribute.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  1386. attribute.mod_type = mctx.attrplName;
  1387. attribute.mod_bvalues[0] = bv;
  1388. attribute.mod_bvalues[1] = NULL;
  1389. if (addAttrib (attrs, nbAttribs++, &attribute) < 0) {
  1390. rc = -1;
  1391. goto error;
  1392. }
  1393. goto done;
  1394. error:
  1395. if (bv != NULL) {
  1396. free(bv);
  1397. }
  1398. if (attribute.mod_bvalues != NULL) {
  1399. free(attribute.mod_bvalues);
  1400. }
  1401. done:
  1402. /*
  1403. * Normal end
  1404. */
  1405. return (0);
  1406. }
  1407. /* New function */ /*JLS 21-11-00*/
  1408. /* ****************************************************************************
  1409. FUNCTION : buildNewModAttrib
  1410. PURPOSE : Build a new (random or incremental) target DN and the
  1411. corresponding LDAPMod for attribute modification.
  1412. INPUT : tttctx = thread context
  1413. OUTPUT : newDN = DN of the new entry
  1414. attrs = attributes for the ldap_modify
  1415. RETURN : -1 if error, 0 else.
  1416. DESCRIPTION :
  1417. *****************************************************************************/
  1418. int
  1419. buildNewModAttrib (
  1420. thread_context *tttctx,
  1421. char *newDn,
  1422. LDAPMod **attrs)
  1423. {
  1424. int nbAttribs; /* Nb of attributes */
  1425. LDAPMod attribute; /* To build the attributes */
  1426. /*
  1427. * Build the new DN
  1428. * We will assume that the filter (-f argument) is set to use it
  1429. * to build the rdn of the new entry.
  1430. * Note that the random new attribute is also build by this function.
  1431. */
  1432. if (buildRandomRdnOrFilter (tttctx) < 0)
  1433. return (-1);
  1434. strcpy (newDn, tttctx->bufFilter);
  1435. strcat (newDn, ",");
  1436. strcat (newDn, tttctx->bufBaseDN);
  1437. /*
  1438. * Build the attributes modification
  1439. */
  1440. attrs[0] = NULL; /* No attributes yet */
  1441. nbAttribs = 0; /* No attributes yet */
  1442. attribute.mod_op = LDAP_MOD_REPLACE;
  1443. attribute.mod_type = mctx.attrplName;
  1444. attribute.mod_values = strList1 (tttctx->bufAttrpl);
  1445. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1446. return (-1);
  1447. /*
  1448. * Normal end
  1449. */
  1450. return (0);
  1451. }
  1452. /* New */ /*JLS 19-03-01*/
  1453. /* ****************************************************************************
  1454. FUNCTION : buildVersatileObject
  1455. PURPOSE : Build a new entry using the definitions in the object
  1456. given in parameter.
  1457. INPUT : tttctx = thread context
  1458. object = object definition
  1459. OUTPUT : attrs = resulting attributes.
  1460. RETURN : -1 if error, 0 else.
  1461. DESCRIPTION :
  1462. *****************************************************************************/
  1463. int
  1464. buildVersatileObject (
  1465. thread_context *tttctx,
  1466. vers_object *object,
  1467. LDAPMod **attrs)
  1468. {
  1469. int nbAttribs; /* Nb of attributes */
  1470. LDAPMod attribute; /* To build the attributes */
  1471. int i; /* For the loop */
  1472. char *newValue; /* New values for the attributes */
  1473. /*
  1474. * Initialization
  1475. */
  1476. attrs[0] = NULL; /* No attributes yet */
  1477. nbAttribs = 0; /* No attributes yet */
  1478. /*
  1479. * What is sure is that ttctx->bufFilter contains the rdn of the new entry !
  1480. * This rdn is build from the filter, and is independant from the
  1481. * object class.
  1482. */
  1483. for (i=0 ; tttctx->bufFilter[i] != '=' ; i++)
  1484. tttctx->buf2[i] = tttctx->bufFilter[i];
  1485. tttctx->buf2[i] = '\0';
  1486. strcpy (tttctx->bufObject1, tttctx->buf2);
  1487. attribute.mod_op = LDAP_MOD_ADD;
  1488. attribute.mod_type = tttctx->bufObject1;
  1489. attribute.mod_values = strList1 (&(tttctx->bufFilter[i+1]));
  1490. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1491. return (-1);
  1492. /*
  1493. * We are certain that there is enough space in attrs
  1494. */
  1495. for (i=0 ; i<object->attribsNb ; i++)
  1496. {
  1497. attribute.mod_op = LDAP_MOD_ADD;
  1498. attribute.mod_type = object->attribs[i].name;
  1499. newValue = buildVersatileAttribute (tttctx, object, &(object->attribs[i]));
  1500. if (newValue == NULL)
  1501. return (-1);
  1502. attribute.mod_values = strList1 (newValue);
  1503. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1504. return (-1);
  1505. }
  1506. return (0);
  1507. }
  1508. /* ****************************************************************************
  1509. FUNCTION : buildNewEntry
  1510. PURPOSE : Build a new (random or incremental) entry, to be used
  1511. for ldap_add() or ldap_modify() operations.
  1512. INPUT : tttctx = thread context
  1513. OUTPUT : newDn = DN of the new entry
  1514. attrs = attributes of the new entry
  1515. RETURN : -1 if error, 0 else.
  1516. DESCRIPTION :
  1517. *****************************************************************************/
  1518. int
  1519. buildNewEntry (
  1520. thread_context *tttctx,
  1521. char *newDn,
  1522. LDAPMod **attrs)
  1523. {
  1524. int nbAttribs; /* Nb of attributes */
  1525. LDAPMod attribute; /* To build the attributes */
  1526. int i; /* To loop */
  1527. /*
  1528. * Build the new DN
  1529. * We will assume that the filter (-f argument) is set to use it
  1530. * to build the rdn of the new entry.
  1531. */
  1532. if (buildRandomRdnOrFilter (tttctx) < 0)
  1533. return (-1);
  1534. strcpy (newDn, tttctx->bufFilter);
  1535. strcat (newDn, ",");
  1536. strcat (newDn, tttctx->bufBaseDN);
  1537. if (mctx.mode & VERY_VERBOSE)
  1538. printf ("ldclt[%d]: %s: tttctx->bufFilter=\"%s\"\n",
  1539. mctx.pid, tttctx->thrdId, tttctx->bufFilter);
  1540. /*
  1541. * Maybe we are using the new versatile object definition ?
  1542. */
  1543. if (mctx.mod2 & M2_OBJECT) /*JLS 19-03-01*/
  1544. { /*JLS 19-03-01*/
  1545. if (buildVersatileObject(tttctx, tttctx->object, attrs) < 0)/*JLS 19-03-01*/
  1546. return (-1); /*JLS 19-03-01*/
  1547. if (mctx.mode & VERY_VERBOSE) /*JLS 19-03-01*/
  1548. { /*JLS 19-03-01*/
  1549. for (i=0 ; attrs[i] != NULL ; i++) /*JLS 19-03-01*/
  1550. printf ("ldclt[%d]: %s: attrs[%d]=(\"%s\" , \"%s\")\n",
  1551. mctx.pid, tttctx->thrdId, i,
  1552. attrs[i]->mod_type, attrs[i]->mod_values[0]); /*JLS 19-03-01*/
  1553. } /*JLS 19-03-01*/
  1554. return (0); /*JLS 19-03-01*/
  1555. } /*JLS 19-03-01*/
  1556. /*
  1557. * Build the attributes
  1558. * First, the class...
  1559. * The classe depends of course on the user's choice.
  1560. * Up to now, we only accept person, or one of its subclasses, emailPerson.
  1561. * The difference is that emailPerson contains no other mandatory attributes,
  1562. * but an optionnal one caled "jpegPhoto". This one will be added at the end
  1563. * of this function.
  1564. * NOTE: When other classes will be managed, this function will be splitted
  1565. * to do this.
  1566. */
  1567. attrs[0] = NULL; /* No attributes yet */
  1568. nbAttribs = 0; /* No attributes yet */
  1569. attribute.mod_op = LDAP_MOD_ADD;
  1570. attribute.mod_type = "objectclass";
  1571. if (mctx.mode & OC_PERSON)
  1572. attribute.mod_values = strList1 ("person");
  1573. if (mctx.mode & OC_EMAILPERSON)
  1574. attribute.mod_values = strList1 ("emailPerson");
  1575. if (mctx.mode & OC_INETORGPRSON) /*JLS 07-11-00*/
  1576. attribute.mod_values = strList1 ("inetOrgPerson"); /*JLS 07-11-00*/
  1577. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1578. return (-1);
  1579. /*
  1580. * What is sure is that ttctx->bufFilter contains the rdn of the new entry !
  1581. * This rdn is build from the filter, and is independant from the
  1582. * object class.
  1583. */
  1584. for (i=0 ; tttctx->bufFilter[i] != '=' ; i++)
  1585. tttctx->buf2[i] = tttctx->bufFilter[i];
  1586. tttctx->buf2[i] = '\0';
  1587. attribute.mod_op = LDAP_MOD_ADD;
  1588. attribute.mod_type = tttctx->buf2;
  1589. attribute.mod_values = strList1 (&(tttctx->bufFilter[i+1]));
  1590. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1591. return (-1);
  1592. /*
  1593. * The other attributes...
  1594. */
  1595. if (mctx.mode & (OC_PERSON|OC_EMAILPERSON|OC_INETORGPRSON)) /*JLS 07-11-00*/
  1596. {
  1597. if (strcmp (tttctx->buf2, "cn"))
  1598. {
  1599. attribute.mod_op = LDAP_MOD_ADD;
  1600. attribute.mod_type = "cn";
  1601. attribute.mod_values = strList1 ("toto cn");
  1602. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1603. return (-1);
  1604. }
  1605. if (strcmp (tttctx->buf2, "sn"))
  1606. {
  1607. attribute.mod_op = LDAP_MOD_ADD;
  1608. attribute.mod_type = "sn";
  1609. attribute.mod_values = strList1 ("toto sn");
  1610. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1611. return (-1);
  1612. }
  1613. if ((mctx.mode & OC_INETORGPRSON) && (mctx.mod2 & M2_DEREF))
  1614. {
  1615. attribute.mod_op = LDAP_MOD_ADD;
  1616. attribute.mod_type = LDCLT_DEREF_ATTR;
  1617. /* refer itself */
  1618. attribute.mod_values = strList1 (newDn);
  1619. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1620. return (-1);
  1621. }
  1622. }
  1623. /*
  1624. * This object class is used because it contains an attribute photo...
  1625. */
  1626. if (mctx.mode & (OC_EMAILPERSON|OC_INETORGPRSON)) /*JLS 07-11-00*/
  1627. {
  1628. attribute.mod_op = (LDAP_MOD_ADD|LDAP_MOD_BVALUES);
  1629. attribute.mod_type = "jpegPhoto";
  1630. if (getImage (&attribute) < 0)
  1631. return (-1);
  1632. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1633. return (-1);
  1634. }
  1635. /*
  1636. * No more attributes. Dump the attributes...
  1637. */
  1638. if (mctx.mode & VERY_VERBOSE)
  1639. {
  1640. for (i=0 ; attrs[i] != NULL ; i++)
  1641. printf ("ldclt[%d]: T%03d: attrs[%d]=(\"%s\" , \"%s\")\n",
  1642. mctx.pid, tttctx->thrdNum, i,
  1643. attrs[i]->mod_type, attrs[i]->mod_values[0]);
  1644. }
  1645. return (0);
  1646. }
  1647. /* ****************************************************************************
  1648. FUNCTION : createMissingNodes
  1649. PURPOSE : Create the missing intermediate nodes.
  1650. INPUT : tttctx = thread context
  1651. newDN = new DN that was rejected due to error 32
  1652. LDAP_NO_SUCH_OBJECT
  1653. cnx = ldap connection. NULL if not connected.
  1654. OUTPUT : None.
  1655. RETURN : -1 if error, 0 else.
  1656. DESCRIPTION : This function will call itself recursively while it is
  1657. impossible to create the node, as long as the error is
  1658. LDAP_NO_SUCH_OBJECT (aka 32).
  1659. This function connects to the server to perform its
  1660. task, using the same DN and passwd as in the mctx, i.e.
  1661. the same as the rest of this tool. Hence it is possible
  1662. that it is impossible to initiate a database if the
  1663. user is not cn=admin and the database is empty, because
  1664. only cn=admin may create the root entry.
  1665. *****************************************************************************/
  1666. int
  1667. createMissingNodes (
  1668. thread_context *tttctx,
  1669. char *newDN,
  1670. LDAP *cnx)
  1671. {
  1672. int i, j; /* For the loops */
  1673. int ret; /* Return value */
  1674. char *nodeDN; /* Node to create */
  1675. char attrName[256]; /* nodeDN's rdn attribute name */
  1676. char attrVal[256]; /* nodeDN's rdn attribute value */
  1677. char *objClass; /* Object class to create */
  1678. int nbAttribs; /* Nb of attributes */
  1679. LDAPMod attribute; /* To build the attributes */
  1680. LDAPMod *attrs[4]; /* Attributes of this entry */
  1681. int v2v3; /* LDAP version used */
  1682. /*
  1683. * Skip the rdn of the given newDN, that was rejected.
  1684. * Don't forget to skip the leading spaces...
  1685. */
  1686. nodeDN=newDN;
  1687. while (*nodeDN != '\0')
  1688. {
  1689. if (*nodeDN == ',')
  1690. break;
  1691. if (*nodeDN == '\\')
  1692. {
  1693. nodeDN++;
  1694. if (*nodeDN == '\0')
  1695. break;
  1696. }
  1697. nodeDN++;
  1698. }
  1699. if (*nodeDN == ',')
  1700. nodeDN++; /* Skip the ',' */
  1701. while ((*nodeDN == ' ') && (*nodeDN != '\0'))
  1702. nodeDN++;
  1703. if (*nodeDN == '\0')
  1704. {
  1705. printf ("ldclt[%d]: T%03d: Reach top of DN for %s\n",
  1706. mctx.pid, tttctx->thrdNum, newDN);
  1707. fflush (stdout);
  1708. return (-1);
  1709. }
  1710. if (mctx.mode & VERY_VERBOSE) /*JLS 14-12-00*/
  1711. printf ("ldclt[%d]: T%03d: nodeDN: %s\n",
  1712. mctx.pid, tttctx->thrdNum, nodeDN);
  1713. /*
  1714. * Found the naming attribute used for nodeDN's rdn.
  1715. */
  1716. for (i=0 ; (nodeDN[i] != '=') && (nodeDN[i] != '\0') ; i++);
  1717. if (nodeDN[i] == '\0')
  1718. {
  1719. printf ("ldclt[%d]: T%03d: Cannot extract naming attribute from %s\n",
  1720. mctx.pid, tttctx->thrdNum, nodeDN);
  1721. fflush (stdout);
  1722. return (-1);
  1723. }
  1724. strncpy (attrName, nodeDN, i);
  1725. attrName[i] = '\0';
  1726. /*
  1727. * Get the value of this rdn
  1728. */
  1729. for (j=i ; (nodeDN[j] != ',') && (nodeDN[j] != '\0') ; j++);
  1730. if (nodeDN[j] == '\0')
  1731. {
  1732. printf ("ldclt[%d]: T%03d: Cannot extract naming attribute from %s\n",
  1733. mctx.pid, tttctx->thrdNum, nodeDN);
  1734. fflush (stdout);
  1735. return (-1);
  1736. }
  1737. strncpy (attrVal, nodeDN+i+1, j-i-1);
  1738. attrVal[j-i-1] = '\0';
  1739. /*
  1740. * What kind of entry should be create ?
  1741. */
  1742. if (!strcmp (attrName, "o"))
  1743. objClass = "organization";
  1744. else if (!strcmp (attrName, "ou"))
  1745. objClass = "organizationalUnit";
  1746. else if (!strcmp (attrName, "cn"))
  1747. objClass = "organizationalRole";
  1748. else
  1749. {
  1750. printf ("ldclt[%d]: T%03d: Don't know how to create entry when rdn is \"%s=%s\"\n",
  1751. mctx.pid, tttctx->thrdNum, attrName, attrVal);
  1752. fflush (stdout);
  1753. return (-1);
  1754. }
  1755. /*
  1756. * Maybe connect to the server ?
  1757. */
  1758. if (cnx == NULL)
  1759. {
  1760. const char *mech = LDAP_SASL_SIMPLE;
  1761. const char *binddn = NULL;
  1762. const char *passwd = NULL;
  1763. struct berval cred = {0, NULL};
  1764. #if defined(USE_OPENLDAP)
  1765. char *ldapurl = NULL;
  1766. #endif
  1767. if (mctx.mode & VERY_VERBOSE) /*JLS 14-12-00*/
  1768. printf ("ldclt[%d]: T%03d: must connect to the server.\n",
  1769. mctx.pid, tttctx->thrdNum);
  1770. #if defined(USE_OPENLDAP)
  1771. ldapurl = PR_smprintf("ldap%s://%s:%d/",
  1772. (mctx.mode & SSL) ? "s" : "",
  1773. mctx.hostname, mctx.port);
  1774. if ((ret = ldap_initialize(&tttctx->ldapCtx, ldapurl))) {
  1775. printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n",
  1776. mctx.pid, tttctx->thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret));
  1777. fflush (stdout);
  1778. PR_smprintf_free(ldapurl);
  1779. return (-1);
  1780. }
  1781. PR_smprintf_free(ldapurl);
  1782. ldapurl = NULL;
  1783. #else /* !USE_OPENLDAP */
  1784. /*
  1785. * SSL is enabled ?
  1786. */
  1787. if (mctx.mode & SSL)
  1788. {
  1789. /*
  1790. * LDAP session initialization in SSL mode
  1791. * added by: B Kolics (11/10/00)
  1792. */
  1793. tttctx->ldapCtx = ldapssl_init(mctx.hostname, mctx.port, 1);
  1794. if (mctx.mode & VERY_VERBOSE)
  1795. printf ("ldclt[%d]: T%03d: After ldapssl_init (%s, %d), ldapCtx=0x%p\n",
  1796. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port,
  1797. tttctx->ldapCtx);
  1798. if (tttctx->ldapCtx == NULL)
  1799. {
  1800. printf ("ldclt[%d]: T%03d: Cannot ldapssl_init (%s, %d), errno=%d\n",
  1801. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port, errno);
  1802. fflush (stdout);
  1803. return (-1);
  1804. }
  1805. /*
  1806. * Client authentication is used ?
  1807. */
  1808. if (mctx.mode & CLTAUTH)
  1809. {
  1810. ret = ldapssl_enable_clientauth(tttctx->ldapCtx, "", mctx.keydbpin, mctx.cltcertname);
  1811. if (mctx.mode & VERY_VERBOSE)
  1812. printf
  1813. ("ldclt[%d]: T%03d: After ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  1814. mctx.pid, tttctx->thrdNum, tttctx->ldapCtx, mctx.keydbpin,
  1815. mctx.cltcertname);
  1816. if (ret < 0)
  1817. {
  1818. printf
  1819. ("ldclt[%d]: T%03d: Cannot ldapssl_enable_clientauth (ldapCtx=0x%p, %s, %s)",
  1820. mctx.pid, tttctx->thrdNum, tttctx->ldapCtx, mctx.keydbpin,
  1821. mctx.cltcertname);
  1822. fflush (stdout);
  1823. return (-1);
  1824. }
  1825. }
  1826. } else {
  1827. /*
  1828. * connection initialization in normal, unencrypted mode
  1829. */
  1830. cnx = ldap_init (mctx.hostname, mctx.port);
  1831. if (cnx == NULL)
  1832. {
  1833. printf ("ldclt[%d]: T%03d: Cannot ldap_init (%s, %d), errno=%d\n",
  1834. mctx.pid, tttctx->thrdNum, mctx.hostname, mctx.port, errno);
  1835. fflush (stdout);
  1836. return (-1);
  1837. }
  1838. }
  1839. #endif /* !USE_OPENLDAP */
  1840. if (mctx.mode & CLTAUTH) {
  1841. mech = "EXTERNAL";
  1842. binddn = "";
  1843. passwd = NULL;
  1844. } else {
  1845. binddn = tttctx->bufBindDN?tttctx->bufBindDN:mctx.bindDN;
  1846. passwd = tttctx->bufPasswd?tttctx->bufPasswd:mctx.passwd;
  1847. if (passwd) {
  1848. cred.bv_val = (char *)passwd;
  1849. cred.bv_len = strlen(passwd);
  1850. }
  1851. }
  1852. if (mctx.mode & LDAP_V2)
  1853. v2v3 = LDAP_VERSION2;
  1854. else
  1855. v2v3 = LDAP_VERSION3;
  1856. ret = ldap_set_option (cnx, LDAP_OPT_PROTOCOL_VERSION, &v2v3);
  1857. if (ret < 0)
  1858. {
  1859. printf ("ldclt[%d]: T%03d: Cannot ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)\n",
  1860. mctx.pid, tttctx->thrdNum);
  1861. fflush (stdout);
  1862. return (-1);
  1863. }
  1864. /*
  1865. * Bind to the server
  1866. */
  1867. ret = ldap_sasl_bind_s (tttctx->ldapCtx, binddn, mech, &cred, NULL, NULL,
  1868. NULL);
  1869. if (ret != LDAP_SUCCESS)
  1870. {
  1871. printf ("ldclt[%d]: T%03d: Cannot bind using mech [%s] (%s, %s), error=%d (%s)\n",
  1872. mctx.pid, tttctx->thrdNum,
  1873. mech ? mech : "SIMPLE",
  1874. tttctx->bufBindDN ? tttctx->bufBindDN : "",
  1875. tttctx->bufPasswd ? tttctx->bufPasswd : "",
  1876. ret, my_ldap_err2string (ret));
  1877. fflush (stdout);
  1878. tttctx->exitStatus = EXIT_NOBIND; /*JLS 25-08-00*/
  1879. if (addErrorStat (ret) < 0)
  1880. return (-1);
  1881. return (-1);
  1882. }
  1883. }
  1884. /*
  1885. * Create the entry
  1886. */
  1887. attrs[0] = NULL; /* No attributes yet */
  1888. nbAttribs = 0; /* No attributes yet */
  1889. attribute.mod_op = LDAP_MOD_ADD;
  1890. attribute.mod_type = "objectclass";
  1891. attribute.mod_values = strList1 (objClass);
  1892. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1893. return (-1);
  1894. attribute.mod_op = LDAP_MOD_ADD;
  1895. attribute.mod_type = attrName;
  1896. attribute.mod_values = strList1 (attrVal);
  1897. if (addAttrib (attrs, nbAttribs++, &attribute) < 0)
  1898. return (-1);
  1899. /*
  1900. * Add the entry
  1901. * If it doesn't work, we will recurse on the nodeDN
  1902. */
  1903. ret = ldap_add_ext_s (cnx, nodeDN, attrs, NULL, NULL);
  1904. if ((ret != LDAP_SUCCESS) && (ret != LDAP_ALREADY_EXISTS))
  1905. {
  1906. if (ret == LDAP_NO_SUCH_OBJECT)
  1907. { /*JLS 07-11-00*/
  1908. printf ("ldclt[%d]: T%03d: Parent of %s doesn't exist, looping\n",
  1909. mctx.pid, tttctx->thrdNum, nodeDN);
  1910. if (createMissingNodes (tttctx, nodeDN, cnx) < 0)
  1911. return (-1);
  1912. else
  1913. {
  1914. /*
  1915. * Well, the upper node is created. Maybe we should now
  1916. * create the node requested for this instance of the function.
  1917. * Two solutions, retry a ldap_add_s() or recursive call to
  1918. * createMissingNodes()... Let's be simple and recurse ;-)
  1919. * Don't forget that the cnx was released in the previous call.
  1920. */
  1921. cnx = NULL;
  1922. return (createMissingNodes (tttctx, newDN, cnx));
  1923. }
  1924. } /*JLS 07-11-00*/
  1925. /*
  1926. * Well, looks like it is more serious !
  1927. */
  1928. printf ("ldclt[%d]: T%03d: Cannot add (%s), error=%d (%s)\n",
  1929. mctx.pid, tttctx->thrdNum, nodeDN, ret, my_ldap_err2string (ret));
  1930. fflush (stdout);
  1931. if (addErrorStat (ret) < 0)
  1932. return (-1);
  1933. return (-1);
  1934. }
  1935. /*
  1936. * Note that error this node may exist, i.e. being just created
  1937. * by another thread !
  1938. * Memorize this operation only if the entry was really created.
  1939. * Maybe we run in check mode, so be carreful...
  1940. */
  1941. if (ret != LDAP_ALREADY_EXISTS)
  1942. {
  1943. if (incrementNbOpers (tttctx) < 0)
  1944. return (-1);
  1945. #ifdef SOLARIS /*JLS 14-11-00*/
  1946. if (mctx.slavesNb > 0)
  1947. if (opAdd (tttctx, LDAP_REQ_ADD, nodeDN, attrs, NULL, NULL) < 0)
  1948. return (-1);
  1949. #endif /*JLS 14-11-00*/
  1950. }
  1951. else /*JLS 15-12-00*/
  1952. {
  1953. if (mctx.mode & COUNT_EACH) /*JLS 15-12-00*/
  1954. { /*JLS 15-12-00*/
  1955. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  1956. return (-1); /*JLS 15-12-00*/
  1957. } /*JLS 15-12-00*/
  1958. }
  1959. /*
  1960. * Ok, we succeed to create the entry ! or it already exist.
  1961. * Don't forget to free the attributes and to release the cnx !!
  1962. */
  1963. if (freeAttrib (attrs) < 0)
  1964. return (-1);
  1965. ret = ldap_unbind_ext (cnx, NULL, NULL);
  1966. if (ret != LDAP_SUCCESS)
  1967. {
  1968. fprintf (stderr, "ldclt[%d]: T%03d: cannot ldap_unbind(), error=%d (%s)\n",
  1969. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  1970. fflush (stderr);
  1971. if (addErrorStat (ret) < 0)
  1972. return (-1);
  1973. return (-1);
  1974. }
  1975. /*
  1976. * Ouf ! End of this function.
  1977. */
  1978. return (0);
  1979. }
  1980. /* ****************************************************************************
  1981. FUNCTION : getPending
  1982. PURPOSE : Get the pending results, and perform some basic controls
  1983. on them.
  1984. INPUT : tttctx = thread context
  1985. timeout = how many times wait for a result.
  1986. OUTPUT : None.
  1987. RETURN : -1 if error, 0 else.
  1988. DESCRIPTION :
  1989. *****************************************************************************/
  1990. int
  1991. getPending (
  1992. thread_context *tttctx,
  1993. struct timeval *timeout)
  1994. {
  1995. LDAPMessage *res; /* LDAP async results */
  1996. int ret; /* Return values */
  1997. int expected = 0; /* Expect this type */
  1998. char *verb; /* LDAP verb expected */
  1999. int type; /* Message type */
  2000. int errcodep; /* Async error code */
  2001. int msgid; /* Async message id */
  2002. int msgOk; /* Message read. */
  2003. char *addErrMsg; /* Additional error msg */ /*JLS 03-08-00*/
  2004. /*
  2005. * Initialization
  2006. */
  2007. msgOk = 0; /* No message received */
  2008. if (tttctx->mode & ADD_ENTRIES)
  2009. {
  2010. expected = LDAP_RES_ADD;
  2011. verb = "ldap_add";
  2012. }
  2013. else
  2014. if (tttctx->mode & DELETE_ENTRIES)
  2015. {
  2016. expected = LDAP_RES_DELETE;
  2017. verb = "ldap_delete";
  2018. }
  2019. else
  2020. if (tttctx->mode & RENAME_ENTRIES)
  2021. {
  2022. expected = LDAP_RES_MODRDN;
  2023. verb = "ldap_rename";
  2024. }
  2025. else /*JLS 21-11-00*/
  2026. if (tttctx->mode & ATTR_REPLACE) /*JLS 21-11-00*/
  2027. { /*JLS 21-11-00*/
  2028. expected = LDAP_RES_MODIFY; /*JLS 21-11-00*/
  2029. verb = "ldap_modify"; /*JLS 21-11-00*/
  2030. } /*JLS 21-11-00*/
  2031. /*
  2032. * Here, we are in asynchronous mode...
  2033. * Too bad, lot of things to do here.
  2034. * First, let's see if we are above the reading threshold.
  2035. * This function may be called recursivelly to empty the input queue. When
  2036. * it is used this way, the timeout is set to zero.
  2037. */
  2038. if ((timeout == &(mctx.timevalZero)) ||
  2039. (tttctx->pendingNb >= mctx.asyncMin))
  2040. {
  2041. /*
  2042. * Retrieve the next pending request
  2043. * The result of ldap_result() may be -1 (error), 0 (timeout).
  2044. * If timeout, well... let's ignore it and continue.
  2045. */
  2046. ret = ldap_result (tttctx->ldapCtx, LDAP_RES_ANY, 1, timeout, &res);
  2047. if (ret != 0)
  2048. {
  2049. msgOk = 1;
  2050. if (ret < 0)
  2051. {
  2052. if (!ignoreError (ret))
  2053. {
  2054. msgOk = 0;
  2055. if (!(mctx.mode & QUIET))
  2056. {
  2057. printf ("ldclt[%d]: T%03d: Cannot ldap_result(), error=%d (%s)\n",
  2058. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  2059. fflush (stdout);
  2060. }
  2061. }
  2062. if (addErrorStat (ret) < 0)
  2063. return (-1);
  2064. }
  2065. else
  2066. {
  2067. /*
  2068. * Ensure it is what we expect to see...
  2069. */
  2070. type = ldap_msgtype (res);
  2071. msgid = ldap_msgid (res);
  2072. if (type != expected)
  2073. {
  2074. msgOk = 0;
  2075. printf ("ldclt[%d]: T%03d: bad result type 0x%02x\n",
  2076. mctx.pid, tttctx->thrdNum, type);
  2077. fflush (stdout);
  2078. if (msgIdDel (tttctx, msgid, 1) < 0)
  2079. return (-1);
  2080. return (0);
  2081. }
  2082. /*
  2083. * Parse the result
  2084. */
  2085. addErrMsg = NULL; /*JLS 03-08-00*/
  2086. ret = ldap_parse_result (tttctx->ldapCtx, res, &errcodep,
  2087. NULL, &addErrMsg, NULL, NULL, 0); /*JLS 03-08-00*/
  2088. if (ret < 0)
  2089. {
  2090. if (!ignoreError (ret))
  2091. {
  2092. msgOk = 0;
  2093. if (!(mctx.mode & QUIET))
  2094. {
  2095. printf ("ldclt[%d]: T%03d: Cannot ldap_parse_result(%s), error=%d (%s",
  2096. mctx.pid, tttctx->thrdNum, msgIdStr (tttctx, msgid),
  2097. ret, my_ldap_err2string (ret));
  2098. if ((addErrMsg != NULL) && (*addErrMsg != '\0')) /*JLS 03-08-00*/
  2099. { /*JLS 03-08-00*/
  2100. printf (" - %s", addErrMsg); /*JLS 03-08-00*/
  2101. ldap_memfree (addErrMsg); /*JLS 03-08-00*/
  2102. } /*JLS 03-08-00*/
  2103. printf (")\n"); /*JLS 03-08-00*/
  2104. fflush (stdout);
  2105. }
  2106. }
  2107. if (msgIdDel (tttctx, msgid, 1) < 0)
  2108. return (-1);
  2109. if (addErrorStat (ret) < 0)
  2110. return (-1);
  2111. }
  2112. /*
  2113. * Ensure the operation was well performed
  2114. * Note that an error to be ignored should be considered as
  2115. * a good message received (cf boolean msgOk).
  2116. */
  2117. if (errcodep != LDAP_SUCCESS)
  2118. {
  2119. if (!ignoreError (ret))
  2120. {
  2121. msgOk = 0;
  2122. if (!(mctx.mode & QUIET))
  2123. {
  2124. printf ("ldclt[%d]: T%03d: Cannot %s(%s), error=%d (%s)\n",
  2125. mctx.pid, tttctx->thrdNum, verb, msgIdStr (tttctx, msgid),
  2126. errcodep, my_ldap_err2string (errcodep));
  2127. fflush (stdout);
  2128. }
  2129. }
  2130. /*
  2131. * Maybe we must create the intermediate nodes ?
  2132. */
  2133. if (((expected == LDAP_RES_ADD) || (expected == LDAP_RES_MODRDN)) &&
  2134. (errcodep == LDAP_NO_SUCH_OBJECT))
  2135. {
  2136. /*
  2137. * Attention, for the rename operation we will memorize the new
  2138. * parent node and not the entry itself.
  2139. */
  2140. if (createMissingNodes (tttctx, msgIdStr (tttctx, msgid), NULL) < 0)
  2141. {
  2142. printf ("ldclt[%d]: T%03d: Cannot create the intermediate nodes for %s\n",
  2143. mctx.pid, tttctx->thrdNum, msgIdStr (tttctx, msgid));
  2144. fflush (stdout);
  2145. return (-1);
  2146. }
  2147. if ((mctx.mode & VERBOSE) && (!(mctx.mode & QUIET)))
  2148. {
  2149. printf ("ldclt[%d]: T%03d: Intermediate nodes created for %s\n",
  2150. mctx.pid, tttctx->thrdNum, msgIdStr (tttctx, msgid));
  2151. fflush (stdout);
  2152. }
  2153. }
  2154. /*
  2155. * Free the message's data
  2156. */
  2157. if (msgIdDel (tttctx, msgid, 1) < 0)
  2158. return (-1);
  2159. if (addErrorStat (errcodep) < 0)
  2160. return (-1);
  2161. }
  2162. else
  2163. {
  2164. /*
  2165. * Ok, the operation is well performed !
  2166. * Maybe we are running in check mode ?
  2167. */
  2168. if (mctx.slavesNb == 0)
  2169. {
  2170. if (msgIdDel (tttctx, msgid, 1) < 0)
  2171. return (-1);
  2172. }
  2173. #ifdef SOLARIS /*JLS 14-11-00*/
  2174. else
  2175. {
  2176. switch (expected)
  2177. {
  2178. case LDAP_RES_ADD:
  2179. if (opAdd (tttctx, LDAP_REQ_ADD, msgIdDN(tttctx, msgid),
  2180. msgIdAttribs(tttctx, msgid), NULL, NULL) < 0)
  2181. return (-1);
  2182. break;
  2183. case LDAP_RES_DELETE:
  2184. if (opAdd (tttctx, LDAP_REQ_DELETE, msgIdDN(tttctx, msgid),
  2185. NULL, NULL, NULL) < 0)
  2186. return (-1);
  2187. break;
  2188. case LDAP_RES_MODRDN:
  2189. if (opAdd (tttctx, LDAP_REQ_DELETE, msgIdDN(tttctx, msgid),
  2190. NULL, NULL, NULL) < 0)
  2191. /*
  2192. TBC : memorize the newRdn and newParent
  2193. */
  2194. return (-1);
  2195. break;
  2196. }
  2197. if (msgIdDel (tttctx, msgid, 1) < 0)
  2198. return (-1);
  2199. }
  2200. #endif /* SOLARIS */ /*JLS 14-11-00*/
  2201. }
  2202. /*
  2203. * Ok, it is a "SUCCESS" message.
  2204. * Don't forget to free the returned message !
  2205. */
  2206. tttctx->pendingNb--;
  2207. if ((ret = ldap_msgfree (res)) < 0)
  2208. {
  2209. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2210. {
  2211. printf ("ldclt[%d]: T%03d: Cannot ldap_msgfree(), error=%d (%s)\n",
  2212. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  2213. fflush (stdout);
  2214. }
  2215. if (addErrorStat (ret) < 0)
  2216. return (-1);
  2217. }
  2218. }
  2219. }
  2220. }
  2221. /*
  2222. * Maybe recurse to read the next message ?
  2223. */
  2224. if (msgOk)
  2225. return (getPending (tttctx, &(mctx.timevalZero)));
  2226. return (0);
  2227. }
  2228. /* ****************************************************************************
  2229. FUNCTION : doRename
  2230. PURPOSE : Perform an ldap_rename() operation.
  2231. INPUT : tttctx = thread context
  2232. OUTPUT : None.
  2233. RETURN : -1 if error, 0 else.
  2234. DESCRIPTION :
  2235. *****************************************************************************/
  2236. int
  2237. doRename (
  2238. thread_context *tttctx)
  2239. {
  2240. char oldDn[MAX_DN_LENGTH]; /* DN of the entry to rename */
  2241. int ret; /* Return values */
  2242. int retry; /* Retry after createMissingNodes() */
  2243. int retryed; /* If already retryed */
  2244. int msgid; /* For asynchronous mode */
  2245. /*
  2246. * Connection to the server
  2247. * The function connectToServer() will take care of the various connection/
  2248. * disconnection, bind/unbind/close etc... requested by the user.
  2249. * The cost is one more function call in this application, but the
  2250. * resulting source code will be much more easiest to maintain.
  2251. */
  2252. if (connectToServer (tttctx) < 0) /*JLS 18-12-00*/
  2253. return (-1); /*JLS 18-12-00*/
  2254. if (!(tttctx->binded)) /*JLS 18-12-00*/
  2255. return (0); /*JLS 18-12-00*/
  2256. /*
  2257. * Build a random entry name. Of course, we are not sure it exist
  2258. * but there is no other simple solution...
  2259. * Anyway, the result is: tttctx->bufFilter , tttctx->bufBaseDN
  2260. */
  2261. if (buildRandomRdnOrFilter (tttctx) < 0)
  2262. return (-1);
  2263. strcpy (oldDn, tttctx->bufFilter);
  2264. strcat (oldDn, ",");
  2265. strcat (oldDn, tttctx->bufBaseDN);
  2266. /*
  2267. * Now, build a random new name for this entry
  2268. */
  2269. if (buildRandomRdnOrFilter (tttctx) < 0)
  2270. return (-1);
  2271. /*
  2272. * Do the rename
  2273. * Maybe we are in synchronous mode ?
  2274. * We won't try to recover from errors in this function, because the
  2275. * way the library will tell the application that the target parent
  2276. * (tttctx->bufBaseDN) doesn't exist is LDAP_PROTOCOL_ERROR that may
  2277. * report as well three other problems.
  2278. */
  2279. if (!(mctx.mode & ASYNC))
  2280. {
  2281. /*
  2282. * We will retry with this entry...
  2283. * We need to memorize we have already retry to add an entry, because
  2284. * ldap_rename_s() returns LDAP_PROTOCOL_ERROR if the randomly chosen
  2285. * entry we try to rename does not exist ! If we don't, the program will
  2286. * loop infinitely on this.
  2287. * The only way is to decide that LDAP_PROTOCOL_ERROR is not a *real*
  2288. * error, that is detailed below :
  2289. * The possible meanings of LDAP_PROTOCOL_ERROR are :
  2290. * - BER problem, unlike to happen
  2291. * - newrdn is invalid, also unlike to happen
  2292. * - ldclt is not running ldap v3 - ok, we could leave with this.
  2293. * - the newparent is invalid. I thing that we could take this for
  2294. * "doesn't exist"...
  2295. */
  2296. retry = 1;
  2297. retryed = 0;
  2298. while (retry && !retryed)
  2299. {
  2300. if (mctx.mode & WITH_NEWPARENT) /*JLS 15-12-00*/
  2301. ret = ldap_rename_s (tttctx->ldapCtx, oldDn,
  2302. tttctx->bufFilter, tttctx->bufBaseDN, 1, NULL, NULL);
  2303. else /*JLS 15-12-00*/
  2304. ret = ldap_rename_s (tttctx->ldapCtx, oldDn, /*JLS 15-12-00*/
  2305. tttctx->bufFilter, NULL, 1, NULL, NULL);/*JLS 15-12-00*/
  2306. if (ret == LDAP_SUCCESS) /*JLS 15-12-00*/
  2307. {
  2308. retry = 0;
  2309. if (incrementNbOpers (tttctx) < 0) /* Memorize operation */
  2310. return (-1);
  2311. #ifdef SOLARIS /*JLS 14-11-00*/
  2312. if (mctx.slavesNb > 0)
  2313. if (opAdd (tttctx, LDAP_REQ_MODRDN, oldDn, NULL,
  2314. tttctx->bufFilter, tttctx->bufBaseDN) < 0)
  2315. return (-1);
  2316. #endif /*JLS 14-11-00*/
  2317. }
  2318. else /* Error */
  2319. {
  2320. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2321. {
  2322. printf ("ldclt[%d]: T%03d: Cannot rename (%s, %s, %s), error=%d (%s)\n",
  2323. mctx.pid, tttctx->thrdNum, oldDn, tttctx->bufFilter, tttctx->bufBaseDN,
  2324. ret, my_ldap_err2string (ret));
  2325. fflush (stdout);
  2326. }
  2327. if (addErrorStat (ret) < 0)
  2328. return (-1);
  2329. /*
  2330. * Check what to do depending on the error.
  2331. * From the c-sdk function description, if the parent node of the
  2332. * new dn (i.e. tttctx->bufBaseDN) doesn't exist, the error returned
  2333. * is LDAP_PROTOCOL_ERROR that may report as well three other problems.
  2334. * See discussion above.
  2335. */
  2336. /*
  2337. * Maybe we should count each operation ?
  2338. */
  2339. if ((mctx.mode & COUNT_EACH) && /*JLS 18-12-00*/
  2340. ((ret == LDAP_PROTOCOL_ERROR) || /*JLS 18-12-00*/
  2341. (ret == LDAP_NO_SUCH_OBJECT) || /*JLS 18-12-00*/
  2342. (ret == LDAP_ALREADY_EXISTS))) /*JLS 18-12-00*/
  2343. { /*JLS 18-12-00*/
  2344. if (incrementNbOpers (tttctx) < 0) /*JLS 18-12-00*/
  2345. return (-1); /*JLS 18-12-00*/
  2346. } /*JLS 18-12-00*/
  2347. /*
  2348. * Maybe we must create the intermediate nodes ?
  2349. */
  2350. if (ret != LDAP_PROTOCOL_ERROR) /*JLS 15-12-00*/
  2351. retry = 0;
  2352. else
  2353. {
  2354. if (createMissingNodes (tttctx, tttctx->bufBaseDN, NULL) < 0)
  2355. {
  2356. retry = 0;
  2357. printf ("ldclt[%d]: T%03d: Cannot create the intermediate nodes for %s\n",
  2358. mctx.pid, tttctx->thrdNum, tttctx->bufBaseDN);
  2359. fflush (stdout);
  2360. return (-1);
  2361. }
  2362. if ((mctx.mode & VERBOSE) && (!(mctx.mode & QUIET)))
  2363. {
  2364. printf ("ldclt[%d]: T%03d: Intermediate nodes created for %s\n",
  2365. mctx.pid, tttctx->thrdNum, tttctx->bufBaseDN);
  2366. fflush (stdout);
  2367. }
  2368. retryed = 1;
  2369. }
  2370. }
  2371. }
  2372. /*
  2373. * End of synchronous operations
  2374. */
  2375. return (0);
  2376. }
  2377. /*
  2378. * Here, we are in asynchronous mode...
  2379. * Too bad, lot of things to do here.
  2380. * First, let's see if we are above the reading threshold.
  2381. */
  2382. if (getPending (tttctx, &(mctx.timeval)) < 0)
  2383. return (-1);
  2384. /*
  2385. * Maybe we may send another request ?
  2386. * Well... there is no proper way to retrieve the error number for
  2387. * this, so I guess I may use direct access to the ldap context
  2388. * to read the field ld_errno.
  2389. */
  2390. if (tttctx->pendingNb > mctx.asyncMax)
  2391. {
  2392. if ((mctx.mode & VERBOSE) &&
  2393. (tttctx->asyncHit == 1) &&
  2394. (!(mctx.mode & SUPER_QUIET)))
  2395. {
  2396. tttctx->asyncHit = 1;
  2397. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  2398. mctx.pid, tttctx->thrdNum);
  2399. fflush (stdout);
  2400. }
  2401. }
  2402. else
  2403. {
  2404. if ((mctx.mode & VERBOSE) &&
  2405. (tttctx->asyncHit == 1) &&
  2406. (!(mctx.mode & SUPER_QUIET)))
  2407. {
  2408. tttctx->asyncHit = 0;
  2409. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  2410. mctx.pid, tttctx->thrdNum);
  2411. fflush (stdout);
  2412. }
  2413. if (mctx.mode & WITH_NEWPARENT) /*JLS 15-12-00*/
  2414. ret = ldap_rename (tttctx->ldapCtx, oldDn,
  2415. tttctx->bufFilter, tttctx->bufBaseDN,
  2416. 1, NULL, NULL, &msgid);
  2417. else /*JLS 15-12-00*/
  2418. ret = ldap_rename (tttctx->ldapCtx, oldDn, /*JLS 15-12-00*/
  2419. tttctx->bufFilter, NULL, /*JLS 15-12-00*/
  2420. 1, NULL, NULL, &msgid); /*JLS 15-12-00*/
  2421. if (ret < 0)
  2422. {
  2423. if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0)
  2424. {
  2425. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_ERROR_NUMBER)\n",
  2426. mctx.pid, tttctx->thrdNum);
  2427. fflush (stdout);
  2428. return (-1);
  2429. }
  2430. else
  2431. {
  2432. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2433. {
  2434. printf ("ldclt[%d]: T%03d: Cannot rename (%s, %s, %s), error=%d (%s)\n",
  2435. mctx.pid, tttctx->thrdNum, oldDn, tttctx->bufFilter, tttctx->bufBaseDN,
  2436. ret, my_ldap_err2string (ret));
  2437. fflush (stdout);
  2438. }
  2439. if (addErrorStat (ret) < 0)
  2440. return (-1);
  2441. /*
  2442. * Maybe we should count each operation ?
  2443. */
  2444. if ((mctx.mode & COUNT_EACH) && /*JLS 18-12-00*/
  2445. ((ret == LDAP_PROTOCOL_ERROR) || /*JLS 18-12-00*/
  2446. (ret == LDAP_NO_SUCH_OBJECT) || /*JLS 18-12-00*/
  2447. (ret == LDAP_ALREADY_EXISTS))) /*JLS 18-12-00*/
  2448. { /*JLS 18-12-00*/
  2449. if (incrementNbOpers (tttctx) < 0) /*JLS 18-12-00*/
  2450. return (-1); /*JLS 18-12-00*/
  2451. } /*JLS 18-12-00*/
  2452. /*
  2453. * Maybe we must create the intermediate nodes ?
  2454. * Question: is it likely probable that such error is returned
  2455. * by the server on a *asynchornous* operation ?
  2456. * See discussion about the error returned in the synchronous section
  2457. * of this function.
  2458. */
  2459. if (ret == LDAP_PROTOCOL_ERROR) /*JLS 15-12-00*/
  2460. { /*JLS 15-12-00*/
  2461. if (createMissingNodes (tttctx, tttctx->bufBaseDN, NULL) < 0)
  2462. return (-1);
  2463. } /*JLS 15-12-00*/
  2464. }
  2465. }
  2466. else
  2467. {
  2468. /*
  2469. * Memorize the operation
  2470. */
  2471. /*
  2472. TBC : I'm not sure what will happen if we call msgIdAdd() with a NULL
  2473. pointer as attribs !!!!!
  2474. */
  2475. if (msgIdAdd (tttctx, msgid, tttctx->bufBaseDN, oldDn, NULL) < 0)
  2476. return (-1);
  2477. if (incrementNbOpers (tttctx) < 0)
  2478. return (-1);
  2479. tttctx->pendingNb++;
  2480. }
  2481. }
  2482. if (mctx.mode & VERY_VERBOSE)
  2483. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  2484. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  2485. /*
  2486. * End of asynchronous operation... and also end of function.
  2487. */
  2488. return (0);
  2489. }
  2490. /* New */ /*JLS 02-04-01*/
  2491. /* ****************************************************************************
  2492. FUNCTION : ldclt_write_genldif
  2493. PURPOSE : Implements buffered write to speed up -e genldif
  2494. implementation.
  2495. INPUT : str = string to write.
  2496. lgth = length of this string.
  2497. OUTPUT : None.
  2498. RETURN : None.
  2499. DESCRIPTION : Usual write() function is unbuffered on Solaris and
  2500. thus really slow down the whole process. Using this
  2501. function allow ldclt to perform 8 times faster.
  2502. We cannot use fprintf() because of portability issues
  2503. regarding large files support.
  2504. *****************************************************************************/
  2505. char *ldclt_write_genldif_buf = NULL;
  2506. char *ldclt_write_genldif_pt;
  2507. int ldclt_write_genldif_nb;
  2508. void
  2509. ldclt_flush_genldif (void)
  2510. {
  2511. write (mctx.genldifFile, ldclt_write_genldif_buf, ldclt_write_genldif_nb);
  2512. ldclt_write_genldif_pt = ldclt_write_genldif_buf;
  2513. ldclt_write_genldif_nb = 0;
  2514. }
  2515. void
  2516. ldclt_write_genldif (
  2517. char *str,
  2518. int lgth)
  2519. {
  2520. /*
  2521. * First call ?
  2522. */
  2523. if (ldclt_write_genldif_buf == NULL)
  2524. {
  2525. ldclt_write_genldif_buf = (char *) malloc (65536);
  2526. ldclt_write_genldif_pt = ldclt_write_genldif_buf;
  2527. ldclt_write_genldif_nb = 0;
  2528. }
  2529. /*
  2530. * Buffer full ?
  2531. */
  2532. if (ldclt_write_genldif_nb + lgth >= 65536)
  2533. ldclt_flush_genldif();
  2534. /*
  2535. * Add to the buffer
  2536. */
  2537. strncpy (ldclt_write_genldif_pt, str, lgth);
  2538. ldclt_write_genldif_pt += lgth;
  2539. ldclt_write_genldif_nb += lgth;
  2540. }
  2541. /* New */ /*JLS 19-03-01*/
  2542. /* ****************************************************************************
  2543. FUNCTION : doGenldif
  2544. PURPOSE : Create a ldif file from the given parameters.
  2545. INPUT : tttctx = thread context
  2546. OUTPUT : None.
  2547. RETURN : -1 if error, 0 else.
  2548. DESCRIPTION :
  2549. *****************************************************************************/
  2550. int
  2551. doGenldif (
  2552. thread_context *tttctx)
  2553. {
  2554. char newDn[MAX_DN_LENGTH]; /* DN of the new entry */
  2555. LDAPMod *attrs[MAX_ATTRIBS]; /* Attributes of this entry */
  2556. int i; /* For the loop */
  2557. /*
  2558. * Build a new entry
  2559. */
  2560. if (buildNewEntry (tttctx, newDn, attrs) < 0)
  2561. return (-1);
  2562. /*
  2563. * Dump this entry.
  2564. * Using a buffer speeds writes 3 times faster.
  2565. */
  2566. ldclt_write_genldif ("dn: ", 4); /*JLS 02-04-01*/
  2567. ldclt_write_genldif (newDn, strlen (newDn)); /*JLS 02-04-01*/
  2568. ldclt_write_genldif ("\n", 1); /*JLS 02-04-01*/
  2569. for (i=0 ; attrs[i]!=NULL ; i++) /*JLS 02-04-01*/
  2570. { /*JLS 02-04-01*/
  2571. ldclt_write_genldif (attrs[i]->mod_type, /*JLS 02-04-01*/
  2572. strlen (attrs[i]->mod_type)); /*JLS 02-04-01*/
  2573. ldclt_write_genldif (": ", 2); /*JLS 02-04-01*/
  2574. ldclt_write_genldif (attrs[i]->mod_values[0], /*JLS 02-04-01*/
  2575. strlen (attrs[i]->mod_values[0])); /*JLS 02-04-01*/
  2576. ldclt_write_genldif ("\n", 1); /*JLS 02-04-01*/
  2577. } /*JLS 02-04-01*/
  2578. ldclt_write_genldif ("\n", 1); /*JLS 02-04-01*/
  2579. /*
  2580. * Increment counters
  2581. */
  2582. if (incrementNbOpers (tttctx) < 0) /*JLS 28-03-01*/
  2583. return (-1); /*JLS 28-03-01*/
  2584. /*
  2585. * Free the memory and return
  2586. */
  2587. if (freeAttrib (attrs) < 0)
  2588. return (-1);
  2589. return (0);
  2590. }
  2591. /* ****************************************************************************
  2592. FUNCTION : doAddEntry
  2593. PURPOSE : Perform an ldap_add() operation.
  2594. INPUT : tttctx = thread context
  2595. OUTPUT : None.
  2596. RETURN : -1 if error, 0 else.
  2597. DESCRIPTION :
  2598. *****************************************************************************/
  2599. int
  2600. doAddEntry (
  2601. thread_context *tttctx)
  2602. {
  2603. char newDn[MAX_DN_LENGTH]; /* DN of the new entry */
  2604. LDAPMod *attrs[MAX_ATTRIBS]; /* Attributes of this entry */
  2605. int ret; /* Return values */
  2606. int retry; /* Retry after createMissingNodes() */
  2607. /*
  2608. * Connection to the server
  2609. * The function connectToServer() will take care of the various connection/
  2610. * disconnection, bind/unbind/close etc... requested by the user.
  2611. * The cost is one more function call in this application, but the
  2612. * resulting source code will be much more easiest to maintain.
  2613. */
  2614. if (connectToServer (tttctx) < 0)
  2615. return (-1);
  2616. if (!(tttctx->binded)) /*JLS 18-12-00*/
  2617. return (0); /*JLS 18-12-00*/
  2618. /*
  2619. * Do the add
  2620. * Maybe we are in synchronous mode ?
  2621. */
  2622. if (!(mctx.mode & ASYNC))
  2623. {
  2624. /*
  2625. * Build the new entry
  2626. */
  2627. if (buildNewEntry (tttctx, newDn, attrs) < 0)
  2628. return (-1);
  2629. /*
  2630. * We will retry with this entry...
  2631. */
  2632. retry = 1;
  2633. while (retry)
  2634. {
  2635. ret = ldap_add_ext_s (tttctx->ldapCtx, newDn, attrs, NULL, NULL);
  2636. if (ret != LDAP_SUCCESS)
  2637. {
  2638. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2639. {
  2640. printf ("ldclt[%d]: T%03d: Cannot add (%s), error=%d (%s)\n",
  2641. mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret));
  2642. fflush (stdout);
  2643. }
  2644. if (addErrorStat (ret) < 0)
  2645. return (-1);
  2646. /*
  2647. * Maybe we must create the intermediate nodes ?
  2648. */
  2649. if (ret != LDAP_NO_SUCH_OBJECT)
  2650. {
  2651. if ((ret == LDAP_ALREADY_EXISTS) && /*JLS 15-12-00*/
  2652. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  2653. { /*JLS 15-12-00*/
  2654. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  2655. return (-1); /*JLS 15-12-00*/
  2656. } /*JLS 15-12-00*/
  2657. retry = 0;
  2658. }
  2659. else
  2660. {
  2661. if (createMissingNodes (tttctx, newDn, NULL) < 0)
  2662. {
  2663. retry = 0;
  2664. printf ("ldclt[%d]: T%03d: Cannot create the intermediate nodes for %s\n",
  2665. mctx.pid, tttctx->thrdNum, newDn);
  2666. fflush (stdout);
  2667. return (-1);
  2668. }
  2669. if ((mctx.mode & VERBOSE) && (!(mctx.mode & QUIET)))
  2670. {
  2671. printf ("ldclt[%d]: T%03d: Intermediate nodes created for %s\n",
  2672. mctx.pid, tttctx->thrdNum, newDn);
  2673. fflush (stdout);
  2674. }
  2675. }
  2676. }
  2677. else
  2678. {
  2679. retry = 0;
  2680. if (incrementNbOpers (tttctx) < 0) /* Memorize operation */
  2681. return (-1);
  2682. #ifdef SOLARIS /*JLS 14-11-00*/
  2683. if (mctx.slavesNb > 0)
  2684. if (opAdd (tttctx, LDAP_REQ_ADD, newDn, attrs, NULL, NULL) < 0)
  2685. return (-1);
  2686. #endif /*JLS 14-11-00*/
  2687. }
  2688. }
  2689. /*
  2690. * Free the attributes
  2691. */
  2692. if (freeAttrib (attrs) < 0)
  2693. return (-1);
  2694. /*
  2695. * End of synchronous operations
  2696. */
  2697. return (0);
  2698. }
  2699. /*
  2700. * Here, we are in asynchronous mode...
  2701. * Too bad, lot of things to do here.
  2702. * First, let's see if we are above the reading threshold.
  2703. */
  2704. if (getPending (tttctx, &(mctx.timeval)) < 0)
  2705. return (-1);
  2706. /*
  2707. * Maybe we may send another request ?
  2708. * Well... there is no proper way to retrieve the error number for
  2709. * this, so I guess I may use direct access to the ldap context
  2710. * to read the field ld_errno.
  2711. */
  2712. if (tttctx->pendingNb > mctx.asyncMax)
  2713. {
  2714. if ((mctx.mode & VERBOSE) &&
  2715. (tttctx->asyncHit == 1) &&
  2716. (!(mctx.mode & SUPER_QUIET)))
  2717. {
  2718. tttctx->asyncHit = 1;
  2719. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  2720. mctx.pid, tttctx->thrdNum);
  2721. fflush (stdout);
  2722. }
  2723. }
  2724. else
  2725. {
  2726. int msgid = 0;
  2727. if ((mctx.mode & VERBOSE) &&
  2728. (tttctx->asyncHit == 1) &&
  2729. (!(mctx.mode & SUPER_QUIET)))
  2730. {
  2731. tttctx->asyncHit = 0;
  2732. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  2733. mctx.pid, tttctx->thrdNum);
  2734. fflush (stdout);
  2735. }
  2736. /*
  2737. * Build the new entry
  2738. */
  2739. if (buildNewEntry (tttctx, newDn, attrs) < 0)
  2740. return (-1);
  2741. ret = ldap_add_ext (tttctx->ldapCtx, newDn, attrs, NULL, NULL, &msgid);
  2742. if (ret < 0)
  2743. {
  2744. if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0)
  2745. {
  2746. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_ERROR_NUMBER)\n",
  2747. mctx.pid, tttctx->thrdNum);
  2748. fflush (stdout);
  2749. return (-1);
  2750. }
  2751. else
  2752. {
  2753. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2754. {
  2755. printf ("ldclt[%d]: T%03d: Cannot add(), error=%d (%s)\n",
  2756. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  2757. fflush (stdout);
  2758. }
  2759. if (addErrorStat (ret) < 0)
  2760. return (-1);
  2761. /*
  2762. * Maybe we must create the intermediate nodes ?
  2763. * Question: is it likely probable that sush error is returned
  2764. * by the server on a *asynchornous* operation ?
  2765. */
  2766. if (ret == LDAP_NO_SUCH_OBJECT)
  2767. if (createMissingNodes (tttctx, newDn, NULL) < 0)
  2768. return (-1);
  2769. if ((ret == LDAP_ALREADY_EXISTS) && /*JLS 15-12-00*/
  2770. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  2771. { /*JLS 15-12-00*/
  2772. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  2773. return (-1); /*JLS 15-12-00*/
  2774. } /*JLS 15-12-00*/
  2775. }
  2776. }
  2777. else
  2778. {
  2779. /*
  2780. * Memorize the operation
  2781. */
  2782. if (msgIdAdd (tttctx, msgid, newDn, newDn, attrs) < 0)
  2783. return (-1);
  2784. if (incrementNbOpers (tttctx) < 0)
  2785. return (-1);
  2786. tttctx->pendingNb++;
  2787. }
  2788. }
  2789. if (mctx.mode & VERY_VERBOSE)
  2790. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  2791. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  2792. /*
  2793. * End of asynchronous operation... and also end of function.
  2794. */
  2795. return (0);
  2796. }
  2797. /* ****************************************************************************
  2798. FUNCTION : doAttrReplace
  2799. PURPOSE : Perform an ldap_modify() operation, to replace an
  2800. attribute of the entry.
  2801. INPUT : tttctx = thread context
  2802. OUTPUT : None.
  2803. RETURN : -1 if error, 0 else.
  2804. DESCRIPTION :
  2805. *****************************************************************************/
  2806. int
  2807. doAttrReplace (
  2808. thread_context *tttctx)
  2809. {
  2810. char newDn[MAX_DN_LENGTH]; /* DN of the new entry */
  2811. LDAPMod *attrs[MAX_ATTRIBS]; /* Attributes of this entry */
  2812. int ret; /* Return values */
  2813. int msgid; /* For asynchronous mode */
  2814. /*
  2815. * Connection to the server
  2816. * The function connectToServer() will take care of the various connection/
  2817. * disconnection, bind/unbind/close etc... requested by the user.
  2818. * The cost is one more function call in this application, but the
  2819. * resulting source code will be much more easiest to maintain.
  2820. */
  2821. if (connectToServer (tttctx) < 0)
  2822. return (-1);
  2823. if (!(tttctx->binded)) /*JLS 18-12-00*/
  2824. return (0); /*JLS 18-12-00*/
  2825. /*
  2826. * Do the modify
  2827. * Maybe we are in synchronous mode ?
  2828. */
  2829. if (!(mctx.mode & ASYNC))
  2830. {
  2831. /*
  2832. * Build the new entry
  2833. */
  2834. if (buildNewModAttrib (tttctx, newDn, attrs) < 0)
  2835. return (-1);
  2836. /*
  2837. * We will modify this entry
  2838. */
  2839. ret = ldap_modify_ext_s (tttctx->ldapCtx, newDn, attrs, NULL, NULL);
  2840. if (ret != LDAP_SUCCESS)
  2841. {
  2842. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2843. {
  2844. printf ("ldclt[%d]: T%03d: Cannot modify (%s), error=%d (%s)\n",
  2845. mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret));
  2846. fflush (stdout);
  2847. }
  2848. if (addErrorStat (ret) < 0)
  2849. return (-1);
  2850. }
  2851. else
  2852. {
  2853. if (incrementNbOpers (tttctx) < 0) /* Memorize operation */
  2854. return (-1);
  2855. }
  2856. /*
  2857. * Free the attributes
  2858. */
  2859. if (freeAttrib (attrs) < 0)
  2860. return (-1);
  2861. /*
  2862. * End of synchronous operations
  2863. */
  2864. return (0);
  2865. }
  2866. /*
  2867. * Here, we are in asynchronous mode...
  2868. * Too bad, lot of things to do here.
  2869. * First, let's see if we are above the reading threshold.
  2870. */
  2871. if (getPending (tttctx, &(mctx.timeval)) < 0)
  2872. return (-1);
  2873. /*
  2874. * Maybe we may send another request ?
  2875. * Well... there is no proper way to retrieve the error number for
  2876. * this, so I guess I may use direct access to the ldap context
  2877. * to read the field ld_errno.
  2878. */
  2879. if (tttctx->pendingNb > mctx.asyncMax)
  2880. {
  2881. if ((mctx.mode & VERBOSE) &&
  2882. (tttctx->asyncHit == 1) &&
  2883. (!(mctx.mode & SUPER_QUIET)))
  2884. {
  2885. tttctx->asyncHit = 1;
  2886. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  2887. mctx.pid, tttctx->thrdNum);
  2888. fflush (stdout);
  2889. }
  2890. }
  2891. else
  2892. {
  2893. if ((mctx.mode & VERBOSE) &&
  2894. (tttctx->asyncHit == 1) &&
  2895. (!(mctx.mode & SUPER_QUIET)))
  2896. {
  2897. tttctx->asyncHit = 0;
  2898. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  2899. mctx.pid, tttctx->thrdNum);
  2900. fflush (stdout);
  2901. }
  2902. /*
  2903. * Build the new entry
  2904. */
  2905. if (buildNewModAttrib (tttctx, newDn, attrs) < 0)
  2906. return (-1);
  2907. ret = ldap_modify_ext (tttctx->ldapCtx, newDn, attrs, NULL, NULL, &msgid);
  2908. if (ret != LDAP_SUCCESS)
  2909. {
  2910. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2911. {
  2912. printf ("ldclt[%d]: T%03d: Cannot modify(%s), error=%d (%s)\n",
  2913. mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret));
  2914. fflush (stdout);
  2915. }
  2916. if (addErrorStat (ret) < 0)
  2917. return (-1);
  2918. }
  2919. else
  2920. {
  2921. /*
  2922. * Memorize the operation
  2923. */
  2924. if (msgIdAdd (tttctx, msgid, newDn, newDn, attrs) < 0)
  2925. return (-1);
  2926. if (incrementNbOpers (tttctx) < 0)
  2927. return (-1);
  2928. tttctx->pendingNb++;
  2929. }
  2930. }
  2931. if (mctx.mode & VERY_VERBOSE)
  2932. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  2933. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  2934. /*
  2935. * End of asynchronous operation... and also end of function.
  2936. */
  2937. return (0);
  2938. }
  2939. /* ****************************************************************************
  2940. FUNCTION : doAttrFileReplace
  2941. PURPOSE : Perform an ldap_modify() operation, to replace an
  2942. attribute of the entry with content read from file .
  2943. INPUT : tttctx = thread context
  2944. OUTPUT : None.
  2945. RETURN : -1 if error, 0 else.
  2946. DESCRIPTION :
  2947. *****************************************************************************/
  2948. int
  2949. doAttrFileReplace (
  2950. thread_context *tttctx)
  2951. {
  2952. char newDn[MAX_DN_LENGTH]; /* DN of the new entry */
  2953. LDAPMod *attrs[MAX_ATTRIBS]; /* Attributes of this entry */
  2954. int ret; /* Return values */
  2955. int msgid; /* For asynchronous mode */
  2956. /*
  2957. * Connection to the server
  2958. * The function connectToServer() will take care of the various connection/
  2959. * disconnection, bind/unbind/close etc... requested by the user.
  2960. * The cost is one more function call in this application, but the
  2961. * resulting source code will be much more easiest to maintain.
  2962. */
  2963. if (connectToServer (tttctx) < 0) /* if connection is being established, */
  2964. return (-1); /* then tttctx->ldapCtx would exist and holds connection */
  2965. if (!(tttctx->binded))
  2966. return (0);
  2967. /*
  2968. * Do the modify
  2969. * Maybe we are in synchronous mode ?
  2970. */
  2971. if (!(mctx.mode & ASYNC))
  2972. {
  2973. /*
  2974. * Build the new entry
  2975. */
  2976. if (buildNewModAttribFile (tttctx, newDn, attrs) < 0)
  2977. return (-1);
  2978. /*
  2979. * We will modify this entry
  2980. */
  2981. ret = ldap_modify_ext_s (tttctx->ldapCtx, newDn, attrs, NULL, NULL);
  2982. if (ret != LDAP_SUCCESS)
  2983. {
  2984. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  2985. {
  2986. printf ("ldclt[%d]: T%03d: AttriFileReplace Error Cannot modify (%s), error=%d (%s)\n",
  2987. mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret));
  2988. fflush (stdout);
  2989. }
  2990. if (addErrorStat (ret) < 0)
  2991. return (-1);
  2992. }
  2993. else
  2994. {
  2995. printf ("ldclt[%d]: T%03d: AttriFileReplace modify (%s) success ,\n",
  2996. mctx.pid, tttctx->thrdNum, newDn);
  2997. if (incrementNbOpers (tttctx) < 0) /* Memorize operation */
  2998. return (-1);
  2999. }
  3000. /*
  3001. * Free the attributes
  3002. */
  3003. if (freeAttrib (attrs) < 0)
  3004. return (-1);
  3005. /*
  3006. * End of synchronous operations
  3007. */
  3008. return (0);
  3009. }
  3010. /*
  3011. * Here, we are in asynchronous mode...
  3012. * Too bad, lot of things to do here.
  3013. * First, let's see if we are above the reading threshold.
  3014. */
  3015. if (getPending (tttctx, &(mctx.timeval)) < 0)
  3016. return (-1);
  3017. /*
  3018. * Maybe we may send another request ?
  3019. * Well... there is no proper way to retrieve the error number for
  3020. * this, so I guess I may use direct access to the ldap context
  3021. * to read the field ld_errno.
  3022. */
  3023. if (tttctx->pendingNb > mctx.asyncMax)
  3024. {
  3025. if ((mctx.mode & VERBOSE) &&
  3026. (tttctx->asyncHit == 1) &&
  3027. (!(mctx.mode & SUPER_QUIET)))
  3028. {
  3029. tttctx->asyncHit = 1;
  3030. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  3031. mctx.pid, tttctx->thrdNum);
  3032. fflush (stdout);
  3033. }
  3034. }
  3035. else
  3036. {
  3037. if ((mctx.mode & VERBOSE) &&
  3038. (tttctx->asyncHit == 1) &&
  3039. (!(mctx.mode & SUPER_QUIET)))
  3040. {
  3041. tttctx->asyncHit = 0;
  3042. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  3043. mctx.pid, tttctx->thrdNum);
  3044. fflush (stdout);
  3045. }
  3046. /*
  3047. * Build the new entry
  3048. */
  3049. if (buildNewModAttrib (tttctx, newDn, attrs) < 0)
  3050. return (-1);
  3051. ret = ldap_modify_ext (tttctx->ldapCtx, newDn, attrs, NULL, NULL, &msgid);
  3052. if (ret != LDAP_SUCCESS)
  3053. {
  3054. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3055. {
  3056. printf ("ldclt[%d]: T%03d: Cannot modify(%s), error=%d (%s)\n",
  3057. mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret));
  3058. fflush (stdout);
  3059. }
  3060. if (addErrorStat (ret) < 0)
  3061. return (-1);
  3062. }
  3063. else
  3064. {
  3065. /*
  3066. * Memorize the operation
  3067. */
  3068. if (msgIdAdd (tttctx, msgid, newDn, newDn, attrs) < 0)
  3069. return (-1);
  3070. if (incrementNbOpers (tttctx) < 0)
  3071. return (-1);
  3072. tttctx->pendingNb++;
  3073. }
  3074. }
  3075. if (mctx.mode & VERY_VERBOSE)
  3076. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  3077. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  3078. /*
  3079. * End of asynchronous operation... and also end of function.
  3080. */
  3081. return (0);
  3082. }
  3083. /* ****************************************************************************
  3084. FUNCTION : doDeleteEntry
  3085. PURPOSE : Perform an ldap_delete() operation.
  3086. INPUT : tttctx = thread context
  3087. OUTPUT : None.
  3088. RETURN : -1 if error, 0 else.
  3089. DESCRIPTION :
  3090. *****************************************************************************/
  3091. int
  3092. doDeleteEntry (
  3093. thread_context *tttctx)
  3094. {
  3095. int ret; /* Return values */
  3096. char delDn[MAX_DN_LENGTH]; /* The entry to delete */
  3097. /*
  3098. * Connection to the server
  3099. * The function connectToServer() will take care of the various connection/
  3100. * disconnection, bind/unbind/close etc... requested by the user.
  3101. * The cost is one more function call in this application, but the
  3102. * resulting source code will be much more easiest to maintain.
  3103. */
  3104. if (connectToServer (tttctx) < 0)
  3105. return (-1);
  3106. if (!(tttctx->binded)) /*JLS 18-12-00*/
  3107. return (0); /*JLS 18-12-00*/
  3108. /*
  3109. * Do the delete
  3110. * Maybe we are in synchronous mode ?
  3111. */
  3112. if (!(mctx.mode & ASYNC))
  3113. {
  3114. /*
  3115. * Random (or incremental) creation of the rdn to delete.
  3116. * The resulting rdn is in tttctx->bufFilter.
  3117. */
  3118. if (buildRandomRdnOrFilter (tttctx) < 0)
  3119. return (-1);
  3120. strcpy (delDn, tttctx->bufFilter);
  3121. strcat (delDn, ",");
  3122. strcat (delDn, tttctx->bufBaseDN);
  3123. ret = ldap_delete_ext_s (tttctx->ldapCtx, delDn, NULL, NULL);
  3124. if (ret != LDAP_SUCCESS)
  3125. {
  3126. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3127. {
  3128. printf ("ldclt[%d]: T%03d: Cannot ldap_delete (%s), error=%d (%s)\n",
  3129. mctx.pid, tttctx->thrdNum, delDn, ret, my_ldap_err2string (ret));
  3130. fflush (stdout);
  3131. }
  3132. if (addErrorStat (ret) < 0)
  3133. return (-1);
  3134. if ((ret == LDAP_NO_SUCH_OBJECT) && /*JLS 15-12-00*/
  3135. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  3136. { /*JLS 15-12-00*/
  3137. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  3138. return (-1); /*JLS 15-12-00*/
  3139. } /*JLS 15-12-00*/
  3140. }
  3141. else
  3142. {
  3143. if (incrementNbOpers (tttctx) < 0) /* Memorize operation */
  3144. return (-1);
  3145. #ifdef SOLARIS /*JLS 14-11-00*/
  3146. if (mctx.slavesNb > 0)
  3147. if (opAdd (tttctx, LDAP_REQ_DELETE, delDn, NULL, NULL, NULL) < 0)
  3148. return (-1);
  3149. #endif /*JLS 14-11-00*/
  3150. }
  3151. /*
  3152. * End of synchronous operations
  3153. */
  3154. return (0);
  3155. }
  3156. /*
  3157. * Here, we are in asynchronous mode...
  3158. * Too bad, lot of things to do here.
  3159. * First, let's see if we are above the reading threshold.
  3160. */
  3161. if (getPending (tttctx, &(mctx.timeval)) < 0)
  3162. return (-1);
  3163. /*
  3164. * Maybe we may send another request ?
  3165. * Well... there is no proper way to retrieve the error number for
  3166. * this, so I guess I may use direct access to the ldap context
  3167. * to read the field ld_errno.
  3168. */
  3169. if (tttctx->pendingNb > mctx.asyncMax)
  3170. {
  3171. if ((mctx.mode & VERBOSE) &&
  3172. (tttctx->asyncHit == 1) &&
  3173. (!(mctx.mode & SUPER_QUIET)))
  3174. {
  3175. tttctx->asyncHit = 1;
  3176. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  3177. mctx.pid, tttctx->thrdNum);
  3178. fflush (stdout);
  3179. }
  3180. }
  3181. else
  3182. {
  3183. int msgid = 0;
  3184. if ((mctx.mode & VERBOSE) &&
  3185. (tttctx->asyncHit == 1) &&
  3186. (!(mctx.mode & SUPER_QUIET)))
  3187. {
  3188. tttctx->asyncHit = 0;
  3189. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  3190. mctx.pid, tttctx->thrdNum);
  3191. fflush (stdout);
  3192. }
  3193. /*
  3194. * Random (or incremental) creation of the rdn to delete.
  3195. * The resulting rdn is in tttctx->bufFilter.
  3196. */
  3197. if (buildRandomRdnOrFilter (tttctx) < 0)
  3198. return (-1);
  3199. strcpy (delDn, tttctx->bufFilter);
  3200. strcat (delDn, ",");
  3201. strcat (delDn, tttctx->bufBaseDN);
  3202. ret = ldap_delete_ext (tttctx->ldapCtx, delDn, NULL, NULL, &msgid);
  3203. if (ret < 0)
  3204. {
  3205. if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0)
  3206. {
  3207. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_ERROR_NUMBER)\n",
  3208. mctx.pid, tttctx->thrdNum);
  3209. fflush (stdout);
  3210. return (-1);
  3211. }
  3212. else
  3213. {
  3214. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3215. {
  3216. printf ("ldclt[%d]: T%03d: Cannot ldap_delete(), error=%d (%s)\n",
  3217. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3218. fflush (stdout);
  3219. }
  3220. if (addErrorStat (ret) < 0)
  3221. return (-1);
  3222. if ((ret == LDAP_NO_SUCH_OBJECT) && /*JLS 15-12-00*/
  3223. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  3224. { /*JLS 15-12-00*/
  3225. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  3226. return (-1); /*JLS 15-12-00*/
  3227. } /*JLS 15-12-00*/
  3228. }
  3229. }
  3230. else
  3231. {
  3232. /*
  3233. * Memorize the operation
  3234. */
  3235. if (incrementNbOpers (tttctx) < 0)
  3236. return (-1);
  3237. tttctx->pendingNb++;
  3238. }
  3239. }
  3240. if (mctx.mode & VERY_VERBOSE)
  3241. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  3242. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  3243. /*
  3244. * End of asynchronous operation... and also end of doDeleteEntry().
  3245. */
  3246. return (0);
  3247. }
  3248. /* New function */ /*JLS 04-05-01*/
  3249. /* ****************************************************************************
  3250. FUNCTION : doBindOnly
  3251. PURPOSE : Perform only bind/unbind operations.
  3252. INPUT : tttctx = thread context
  3253. OUTPUT : None.
  3254. RETURN : -1 if error, 0 else.
  3255. DESCRIPTION :
  3256. *****************************************************************************/
  3257. int
  3258. doBindOnly (
  3259. thread_context *tttctx)
  3260. {
  3261. /*
  3262. * Connection to the server
  3263. * The function connectToServer() will take care of the various connection/
  3264. * disconnection, bind/unbind/close etc... requested by the user.
  3265. * The cost is one more function call in this application, but the
  3266. * resulting source code will be much more easiest to maintain.
  3267. */
  3268. if (connectToServer (tttctx) < 0)
  3269. return (-1);
  3270. /* don't count failed binds unless counteach option is used */
  3271. if (!(tttctx->binded) && !(mctx.mode & COUNT_EACH))
  3272. return (0);
  3273. if (incrementNbOpers (tttctx) < 0)
  3274. return (-1);
  3275. return (0);
  3276. }
  3277. /* ****************************************************************************
  3278. FUNCTION : doExactSearch
  3279. PURPOSE : Perform one exact search operation.
  3280. INPUT : tttctx = thread context
  3281. OUTPUT : None.
  3282. RETURN : -1 if error, 0 else.
  3283. DESCRIPTION :
  3284. *****************************************************************************/
  3285. int
  3286. doExactSearch (
  3287. thread_context *tttctx)
  3288. {
  3289. int ret; /* Return value */
  3290. LDAPMessage *res; /* LDAP results */
  3291. LDAPMessage *e; /* LDAP results */
  3292. char **attrlist; /* Attribs list */ /*JLS 15-03-01*/
  3293. LDAPControl **ctrlsp = NULL, *ctrls[2], *dctrl = NULL; /* derefence control */
  3294. /* the following variables are used for response parsing */
  3295. int msgtype, parse_rc , rc ; /* for search result parsing */
  3296. char *matcheddn, *errmsg, *dn ;
  3297. LDAPControl **resctrls;
  3298. LDAPControl **rcp;
  3299. /*
  3300. * Connection to the server
  3301. * The function connectToServer() will take care of the various connection/
  3302. * disconnection, bind/unbind/close etc... requested by the user.
  3303. * The cost is one more function call in this application, but the
  3304. * resulting source code will be much more easiest to maintain.
  3305. */
  3306. if (connectToServer (tttctx) < 0) /*JLS 18-12-00*/
  3307. return (-1); /*JLS 18-12-00*/
  3308. if (!(tttctx->binded)) /*JLS 18-12-00*/
  3309. return (0); /*JLS 18-12-00*/
  3310. /*
  3311. * Build the filter
  3312. */
  3313. if (buildRandomRdnOrFilter (tttctx) < 0)
  3314. return (-1);
  3315. /*
  3316. * Prepear the attribute list
  3317. */
  3318. if (mctx.attrlistNb == 0) /*JLS 15-03-01*/
  3319. attrlist = NULL; /*JLS 15-03-01*/
  3320. else /*JLS 15-03-01*/
  3321. if (mctx.mode & RANDOM_ATTRLIST) /*JLS 15-03-01*/
  3322. attrlist = selectRandomAttrList (tttctx); /*JLS 15-03-01*/
  3323. else /*JLS 15-03-01*/
  3324. attrlist = mctx.attrlist; /*JLS 15-03-01*/
  3325. if (mctx.mod2 & M2_DEREF) /* dereference */
  3326. {
  3327. char *attrs[2];
  3328. /* I have stored ref attr at mctx.attRef , deref attr at mctx.attRefDef */
  3329. /* using hard coded value for dereferenced attribute if no mctx.attRef is set */
  3330. if (mctx.attRef == NULL )
  3331. {
  3332. attrs[0] = "cn";
  3333. }else{
  3334. attrs[0] = mctx.attRefDef;
  3335. }
  3336. attrs[1] = NULL;
  3337. /* use pre-defined value if passin mctx.attrRefDef is null
  3338. * the pre-defined value LDCLT_DEREF_ATTR is "secretary"
  3339. */
  3340. if (mctx.attRef == NULL ){
  3341. ret = ldclt_create_deref_control(tttctx->ldapCtx,
  3342. LDCLT_DEREF_ATTR, attrs, &dctrl);
  3343. }else{
  3344. ret = ldclt_create_deref_control(tttctx->ldapCtx,
  3345. mctx.attRef , attrs, &dctrl);
  3346. }
  3347. /* dctrl contains the returned reference value */
  3348. if (LDAP_SUCCESS == ret)
  3349. {
  3350. ctrls[0] = dctrl;
  3351. ctrls[1] = NULL;
  3352. ctrlsp = ctrls;
  3353. }
  3354. else
  3355. {
  3356. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3357. fprintf (stderr,
  3358. "ldclt[%d]: T%03d: ldclt_create_deref_control() failed, error=%d\n",
  3359. mctx.pid, tttctx->thrdNum, ret);
  3360. if (dctrl) {
  3361. ldap_control_free(dctrl);
  3362. }
  3363. if (addErrorStat(ret) < 0)
  3364. return (-1);
  3365. }
  3366. }
  3367. /*
  3368. * Do the search
  3369. * Maybe we are in synchronous mode ? I hope so, it is really
  3370. * much simple ;-)
  3371. */
  3372. if (!(mctx.mode & ASYNC))
  3373. {
  3374. ret = ldap_search_ext_s (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope,
  3375. tttctx->bufFilter, attrlist, /*JLS 15-03-01*/
  3376. mctx.attrsonly, ctrlsp, NULL, NULL, -1, &res); /*JLS 03-01-01*/
  3377. if (ret != LDAP_SUCCESS)
  3378. { /* if search failed */
  3379. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3380. (void) printErrorFromLdap (tttctx, res, ret, /*JLS 03-08-00*/
  3381. "Cannot ldap_search()"); /*JLS 03-08-00*/
  3382. if (addErrorStat (ret) < 0)
  3383. {
  3384. goto bail;
  3385. }
  3386. if ((ret == LDAP_NO_SUCH_OBJECT) && /*JLS 15-12-00*/
  3387. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  3388. { /*JLS 15-12-00*/
  3389. if (incrementNbOpers (tttctx) < 0) /*JLS 15-12-00*/
  3390. {
  3391. goto bail;
  3392. }
  3393. } /*JLS 15-12-00*/
  3394. }
  3395. else
  3396. { /* if search success & we are in verbose mode */
  3397. if (mctx.mode & VERBOSE)
  3398. {
  3399. for (e = ldap_first_message (tttctx->ldapCtx, res); e != NULL ; e = ldap_next_message (tttctx->ldapCtx, e) )
  3400. {
  3401. msgtype = ldap_msgtype (e);
  3402. switch (msgtype)
  3403. {
  3404. /* if this is an entry that returned */
  3405. case LDAP_RES_SEARCH_ENTRY:
  3406. /* get dereferenced value into resctrls: deref parsing */
  3407. parse_rc = ldap_get_entry_controls ( tttctx->ldapCtx, e, &resctrls );
  3408. if ( resctrls != NULL )
  3409. {/* parse it only when we have return saved in server control */
  3410. /* get dn */
  3411. if (( dn = ldap_get_dn (tttctx->ldapCtx, e)) != NULL )
  3412. {
  3413. for ( rcp = resctrls; rcp && *rcp; rcp++ )
  3414. {
  3415. /* if very_verbose */
  3416. if ( mctx.mode & VERY_VERBOSE )
  3417. {
  3418. printf("dn: [%s] -> deref oid: %s, value: %s\n",
  3419. dn,
  3420. (**rcp).ldctl_oid?(**rcp).ldctl_oid:"none",
  3421. (**rcp).ldctl_value.bv_val?(**rcp).ldctl_value.bv_val:"none");
  3422. }
  3423. }
  3424. ldap_controls_free( resctrls );
  3425. ldap_memfree (dn);
  3426. }
  3427. }
  3428. break; /*end of case LDAP_RES_SEARCH_ENTRY */
  3429. /* if this is an reference that returned */
  3430. case LDAP_RES_SEARCH_REFERENCE: /* we do nothing here */
  3431. break;
  3432. /* if we reach the end of search result */
  3433. case LDAP_RES_SEARCH_RESULT:
  3434. /* just free the returned msg */
  3435. parse_rc = ldap_parse_result (tttctx->ldapCtx, e, &rc, &matcheddn, &errmsg, NULL , NULL , 0);
  3436. if ( parse_rc != LDAP_SUCCESS )
  3437. {
  3438. printf("ldap_parse_result error: [%s]\n", ldap_err2string( parse_rc ));
  3439. }
  3440. if ( rc != LDAP_SUCCESS )
  3441. {
  3442. printf ("ldap_search_ext_s error: [%s]\n", ldap_err2string( rc ));
  3443. }
  3444. break; /* end of case LDAP_RES_SEARCH_RESULT */
  3445. default:
  3446. break;
  3447. }
  3448. } /*end of message retriving */
  3449. } /* end of verbose mode */
  3450. if (incrementNbOpers (tttctx) < 0)/* Memorize operation */
  3451. {
  3452. goto bail;
  3453. }
  3454. /*
  3455. * Don't forget to free the returned message !
  3456. */
  3457. if ((ret = ldap_msgfree (res)) < 0)
  3458. {
  3459. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3460. {
  3461. printf ("ldclt[%d]: T%03d: Cannot ldap_msgfree(), error=%d (%s)\n",
  3462. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3463. fflush (stdout);
  3464. }
  3465. if (addErrorStat (ret) < 0)
  3466. {
  3467. goto bail;
  3468. }
  3469. }
  3470. }
  3471. /*
  3472. * End of synchronous operation
  3473. */
  3474. if (dctrl)
  3475. {
  3476. ldap_control_free(dctrl);
  3477. }
  3478. return (0);
  3479. }
  3480. /*
  3481. * Here, we are in asynchronous mode...
  3482. * Too bad, lot of things to do here.
  3483. * First, let's see if we are above the reading threshold.
  3484. */
  3485. if (tttctx->pendingNb >= mctx.asyncMin)
  3486. {
  3487. /*
  3488. * Retrieve the next pending request
  3489. */
  3490. ret = ldap_result (tttctx->ldapCtx, LDAP_RES_ANY, 1, &(mctx.timeval), &res);
  3491. if (ret < 0)
  3492. {
  3493. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3494. (void) printErrorFromLdap (tttctx, res, ret, /*JLS 03-08-00*/
  3495. "Cannot ldap_result()"); /*JLS 03-08-00*/
  3496. if (addErrorStat (ret) < 0)
  3497. {
  3498. goto bail;
  3499. }
  3500. }
  3501. else
  3502. {
  3503. tttctx->pendingNb--;
  3504. /*
  3505. * Don't forget to free the returned message !
  3506. */
  3507. if ((ret = ldap_msgfree (res)) < 0)
  3508. {
  3509. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3510. {
  3511. printf ("ldclt[%d]: T%03d: Cannot ldap_msgfree(), error=%d (%s)\n",
  3512. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3513. fflush (stdout);
  3514. }
  3515. if (addErrorStat (ret) < 0)
  3516. {
  3517. goto bail;
  3518. }
  3519. }
  3520. }
  3521. }
  3522. /*
  3523. * Maybe we may send another request ?
  3524. * Well... there is no proper way to retrieve the error number for
  3525. * this, so I guess I may use direct access to the ldap context
  3526. * to read the field ld_errno.
  3527. */
  3528. if (tttctx->pendingNb > mctx.asyncMax)
  3529. {
  3530. if ((mctx.mode & VERBOSE) &&
  3531. (tttctx->asyncHit == 1) &&
  3532. (!(mctx.mode & SUPER_QUIET)))
  3533. {
  3534. tttctx->asyncHit = 1;
  3535. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  3536. mctx.pid, tttctx->thrdNum);
  3537. fflush (stdout);
  3538. }
  3539. }
  3540. else
  3541. {
  3542. int msgid = 0;
  3543. if ((mctx.mode & VERBOSE) &&
  3544. (tttctx->asyncHit == 1) &&
  3545. (!(mctx.mode & SUPER_QUIET)))
  3546. {
  3547. tttctx->asyncHit = 0;
  3548. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  3549. mctx.pid, tttctx->thrdNum);
  3550. fflush (stdout);
  3551. }
  3552. ret = ldap_search_ext (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope,
  3553. tttctx->bufFilter, attrlist, /*JLS 15-03-01*/
  3554. mctx.attrsonly, ctrlsp, NULL, NULL, -1, &msgid); /*JLS 03-01-01*/
  3555. if (ret < 0)
  3556. {
  3557. if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0)
  3558. {
  3559. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_ERROR_NUMBER)\n",
  3560. mctx.pid, tttctx->thrdNum);
  3561. fflush (stdout);
  3562. goto bail;
  3563. }
  3564. else
  3565. {
  3566. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3567. {
  3568. printf ("ldclt[%d]: T%03d: Cannot ldap_search(), error=%d (%s)\n",
  3569. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3570. fflush (stdout);
  3571. }
  3572. if (addErrorStat (ret) < 0)
  3573. return (-1);
  3574. if ((ret == LDAP_NO_SUCH_OBJECT) && /*JLS 15-12-00*/
  3575. (mctx.mode & COUNT_EACH)) /*JLS 15-12-00*/
  3576. { /*JLS 15-12-00*/
  3577. if (incrementNbOpers (tttctx) < 0) { /*JLS 15-12-00*/
  3578. goto bail;
  3579. }
  3580. } /*JLS 15-12-00*/
  3581. }
  3582. }
  3583. else
  3584. {
  3585. /*
  3586. * Memorize the operation
  3587. */
  3588. if (incrementNbOpers (tttctx) < 0) {
  3589. goto bail;
  3590. }
  3591. tttctx->pendingNb++;
  3592. }
  3593. }
  3594. if (mctx.mode & VERY_VERBOSE)
  3595. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  3596. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  3597. /*
  3598. * End of asynchronous operation... and also end of function.
  3599. */
  3600. if (dctrl)
  3601. {
  3602. ldap_control_free(dctrl);
  3603. }
  3604. return (0);
  3605. bail:
  3606. if (dctrl)
  3607. {
  3608. ldap_control_free(dctrl);
  3609. }
  3610. return (-1);
  3611. }
  3612. /* ****************************************************************************
  3613. FUNCTION : doAbandon
  3614. PURPOSE : Perform one abandon operation against an async search.
  3615. INPUT : tttctx = thread context
  3616. OUTPUT : None.
  3617. RETURN : -1 if error, 0 else.
  3618. DESCRIPTION :
  3619. *****************************************************************************/
  3620. int
  3621. doAbandon (thread_context *tttctx)
  3622. {
  3623. int ret; /* Return value */
  3624. LDAPMessage *res; /* LDAP results */
  3625. char **attrlist; /* Attribs list */
  3626. struct timeval mytimeout;
  3627. int msgid;
  3628. /*
  3629. * Connection to the server
  3630. * The function connectToServer() will take care of the various connection/
  3631. * disconnection, bind/unbind/close etc... requested by the user.
  3632. * The cost is one more function call in this application, but the
  3633. * resulting source code will be much more easiest to maintain.
  3634. */
  3635. if (connectToServer (tttctx) < 0)
  3636. return (-1);
  3637. if (!(tttctx->binded))
  3638. return (0);
  3639. /*
  3640. * Build the filter
  3641. */
  3642. if (buildRandomRdnOrFilter (tttctx) < 0)
  3643. return (-1);
  3644. attrlist = NULL;
  3645. /*
  3646. * We use asynchronous search to abandon...
  3647. *
  3648. * set (1, 2) to (acyncMin, acyncMax), which combination does not stop write.
  3649. */
  3650. mctx.asyncMin = 1;
  3651. mctx.asyncMax = 2;
  3652. if (tttctx->pendingNb >= mctx.asyncMin)
  3653. {
  3654. mytimeout.tv_sec = 1;
  3655. mytimeout.tv_usec = 0;
  3656. ret = ldap_result (tttctx->ldapCtx,
  3657. LDAP_RES_ANY, LDAP_MSG_ONE, &mytimeout, &res);
  3658. if (ret < 0)
  3659. {
  3660. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3661. (void) printErrorFromLdap (tttctx, res, ret, "Cannot ldap_result()");
  3662. if (addErrorStat (ret) < 0)
  3663. return (-1);
  3664. }
  3665. else
  3666. {
  3667. /* ret == 0 --> timeout; op abandoned and no result is returned */
  3668. tttctx->pendingNb--;
  3669. /*
  3670. * Don't forget to free the returned message !
  3671. */
  3672. if ((ret = ldap_msgfree (res)) < 0)
  3673. {
  3674. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3675. {
  3676. printf ("ldclt[%d]: T%03d: Cannot ldap_msgfree(), error=%d (%s)\n",
  3677. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3678. fflush (stdout);
  3679. }
  3680. if (addErrorStat (ret) < 0)
  3681. return (-1);
  3682. }
  3683. }
  3684. }
  3685. /*
  3686. * Maybe we may send another request ?
  3687. * Well... there is no proper way to retrieve the error number for
  3688. * this, so I guess I may use direct access to the ldap context
  3689. * to read the field ld_errno.
  3690. */
  3691. if (tttctx->pendingNb > mctx.asyncMax)
  3692. {
  3693. if ((mctx.mode & VERBOSE) &&
  3694. (tttctx->asyncHit == 1) &&
  3695. (!(mctx.mode & SUPER_QUIET)))
  3696. {
  3697. tttctx->asyncHit = 1;
  3698. printf ("ldclt[%d]: T%03d: Max pending request hit.\n",
  3699. mctx.pid, tttctx->thrdNum);
  3700. fflush (stdout);
  3701. }
  3702. }
  3703. else
  3704. {
  3705. if ((mctx.mode & VERBOSE) &&
  3706. (tttctx->asyncHit == 1) &&
  3707. (!(mctx.mode & SUPER_QUIET)))
  3708. {
  3709. tttctx->asyncHit = 0;
  3710. printf ("ldclt[%d]: T%03d: Restart sending.\n",
  3711. mctx.pid, tttctx->thrdNum);
  3712. fflush (stdout);
  3713. }
  3714. msgid = -1;
  3715. /* for some reasons, it is an error to pass in a zero'd timeval */
  3716. mytimeout.tv_sec = mytimeout.tv_usec = -1;
  3717. ret = ldap_search_ext (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope,
  3718. tttctx->bufFilter, attrlist, mctx.attrsonly,
  3719. NULL, NULL, &mytimeout, -1, &msgid);
  3720. if (mctx.mode & VERY_VERBOSE)
  3721. printf ("ldclt[%d]: T%03d: ldap_search(%s)=>%d\n",
  3722. mctx.pid, tttctx->thrdNum, tttctx->bufFilter, ret);
  3723. if (ret != 0)
  3724. {
  3725. if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0)
  3726. {
  3727. printf ("ldclt[%d]: T%03d: Cannot ldap_get_option(LDAP_OPT_ERROR_NUMBER)\n",
  3728. mctx.pid, tttctx->thrdNum);
  3729. fflush (stdout);
  3730. return (-1);
  3731. }
  3732. else
  3733. {
  3734. if (!((mctx.mode & QUIET) && ignoreError (ret)))
  3735. {
  3736. printf ("ldclt[%d]: T%03d: Cannot ldap_search(), error=%d (%s)\n",
  3737. mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret));
  3738. fflush (stdout);
  3739. }
  3740. if (addErrorStat (ret) < 0)
  3741. return (-1);
  3742. }
  3743. }
  3744. else
  3745. {
  3746. if (msgid >= 0)
  3747. {
  3748. /* ABANDON the search request immediately */
  3749. (void) ldap_abandon_ext(tttctx->ldapCtx, msgid, NULL, NULL);
  3750. }
  3751. /*
  3752. * Memorize the operation
  3753. */
  3754. if (incrementNbOpers (tttctx) < 0)
  3755. return (-1);
  3756. tttctx->pendingNb++;
  3757. if (mctx.mode & VERY_VERBOSE)
  3758. printf ("ldclt[%d]: T%03d: ldap_abandon(%d)\n",
  3759. mctx.pid, tttctx->thrdNum, msgid);
  3760. }
  3761. }
  3762. if (mctx.mode & VERY_VERBOSE)
  3763. printf ("ldclt[%d]: T%03d: pendingNb=%d\n",
  3764. mctx.pid, tttctx->thrdNum, tttctx->pendingNb);
  3765. /*
  3766. * End of asynchronous operation... and also end of function.
  3767. */
  3768. return (0);
  3769. }
  3770. #define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16"
  3771. int
  3772. ldclt_create_deref_control(
  3773. LDAP *ld,
  3774. char *derefAttr,
  3775. char **attrs,
  3776. LDAPControl **ctrlp
  3777. )
  3778. {
  3779. BerElement *ber;
  3780. int rc;
  3781. #if defined(USE_OPENLDAP)
  3782. struct berval *bv = NULL;
  3783. #endif
  3784. if (ld == 0) {
  3785. return( LDAP_PARAM_ERROR );
  3786. }
  3787. if ( NULL == ctrlp || NULL == derefAttr ||
  3788. NULL == attrs || NULL == *attrs || 0 == strlen(*attrs) ) {
  3789. return ( LDAP_PARAM_ERROR );
  3790. }
  3791. if ( LDAP_SUCCESS != ldclt_alloc_ber( ld, &ber ) )
  3792. {
  3793. return( LDAP_NO_MEMORY );
  3794. }
  3795. if ( LBER_ERROR == ber_printf( ber, "{{s{v}}}", derefAttr, attrs ))
  3796. {
  3797. ber_free( ber, 1 );
  3798. return( LDAP_ENCODING_ERROR );
  3799. }
  3800. #if defined(USE_OPENLDAP)
  3801. if ( LBER_ERROR == ber_flatten(ber, &bv) ) {
  3802. ber_bvfree( bv );
  3803. ber_free( ber, 1 );
  3804. return( LDAP_ENCODING_ERROR );
  3805. }
  3806. if ( NULL == bv ) {
  3807. ber_free( ber, 1 );
  3808. return( LDAP_NO_MEMORY );
  3809. }
  3810. rc = ldap_control_create( LDAP_CONTROL_X_DEREF, 1, bv, 1, ctrlp );
  3811. ber_bvfree( bv );
  3812. ber_free( ber, 1 );
  3813. #else
  3814. rc = ldclt_build_control( LDAP_CONTROL_X_DEREF, ber, 1, 1, ctrlp );
  3815. ber_free( ber, 1 );
  3816. #endif
  3817. return( rc );
  3818. }
  3819. #if !defined(USE_OPENLDAP)
  3820. /*
  3821. * Duplicated nsldapi_build_control from
  3822. * mozilla/directory/c-sdk/ldap/libraries/libldap/control.c
  3823. *
  3824. * build an allocated LDAPv3 control. Returns an LDAP error code.
  3825. */
  3826. int
  3827. ldclt_build_control( char *oid, BerElement *ber, int freeber, char iscritical,
  3828. LDAPControl **ctrlp )
  3829. {
  3830. int rc;
  3831. struct berval *bvp;
  3832. if ( ber == NULL ) {
  3833. bvp = NULL;
  3834. } else {
  3835. /* allocate struct berval with contents of the BER encoding */
  3836. rc = ber_flatten( ber, &bvp );
  3837. if ( freeber ) {
  3838. ber_free( ber, 1 );
  3839. }
  3840. if ( rc == -1 ) {
  3841. return( LDAP_NO_MEMORY );
  3842. }
  3843. }
  3844. /* allocate the new control structure */
  3845. if (( *ctrlp = (LDAPControl *)malloc( sizeof(LDAPControl))) == NULL ) {
  3846. if ( bvp != NULL ) {
  3847. ber_bvfree( bvp );
  3848. }
  3849. return( LDAP_NO_MEMORY );
  3850. }
  3851. /* fill in the fields of this new control */
  3852. (*ctrlp)->ldctl_iscritical = iscritical;
  3853. if (( (*ctrlp)->ldctl_oid = strdup( oid )) == NULL ) {
  3854. free( *ctrlp );
  3855. if ( bvp != NULL ) {
  3856. ber_bvfree( bvp );
  3857. }
  3858. return( LDAP_NO_MEMORY );
  3859. }
  3860. if ( bvp == NULL ) {
  3861. (*ctrlp)->ldctl_value.bv_len = 0;
  3862. (*ctrlp)->ldctl_value.bv_val = NULL;
  3863. } else {
  3864. (*ctrlp)->ldctl_value = *bvp; /* struct copy */
  3865. free( bvp ); /* free container, not contents! */
  3866. }
  3867. return( LDAP_SUCCESS );
  3868. }
  3869. #endif
  3870. /*
  3871. * Duplicated nsldapi_build_control from
  3872. * mozilla/directory/c-sdk/ldap/libraries/libldap/request.c
  3873. *
  3874. * returns an LDAP error code and also sets error inside LDAP
  3875. */
  3876. int
  3877. ldclt_alloc_ber( LDAP *ld, BerElement **berp )
  3878. {
  3879. int err;
  3880. int beropt;
  3881. #if defined(USE_OPENLDAP)
  3882. beropt = LBER_USE_DER;
  3883. #else
  3884. beropt = LBER_OPT_USE_DER;
  3885. #endif
  3886. /* We use default lberoptions since the value is not public in mozldap. */
  3887. if (( *berp = ber_alloc_t( beropt )) == (BerElement *)NULL ) {
  3888. err = LDAP_NO_MEMORY;
  3889. } else {
  3890. err = LDAP_SUCCESS;
  3891. }
  3892. return( err );
  3893. }
  3894. /* End of file */