ldapconnection.cpp 172 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. // LDAP prototypes use char* where they should be using const char *, resulting in lots of spurious warnings
  15. #pragma warning( disable : 4786 )
  16. #ifdef __GNUC__
  17. #pragma GCC diagnostic ignored "-Wwrite-strings"
  18. #endif
  19. #include "permissions.ipp"
  20. #include "aci.ipp"
  21. #include "ldapsecurity.ipp"
  22. #include "jsmartsock.hpp"
  23. #include "jrespool.tpp"
  24. #undef new
  25. #include <map>
  26. #include <string>
  27. #include <set>
  28. #if defined(_DEBUG) && defined(_WIN32) && !defined(USING_MPATROL)
  29. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
  30. #endif
  31. #ifdef _WIN32
  32. #include <lm.h>
  33. #define LdapRename ldap_rename_ext_s
  34. LDAPMessage* (*LdapFirstEntry)(LDAP*, LDAPMessage*) = &ldap_first_entry;
  35. LDAPMessage* (*LdapNextEntry)(LDAP* ld, LDAPMessage* entry) = &ldap_next_entry;
  36. #else
  37. #define LdapRename ldap_rename_s
  38. LDAPMessage* (__stdcall *LdapFirstEntry)(LDAP*, LDAPMessage*) = &ldap_first_message;
  39. LDAPMessage* (__stdcall *LdapNextEntry)(LDAP* ld, LDAPMessage* entry) = &ldap_next_message;
  40. #endif
  41. #define LDAPSEC_MAX_RETRIES 2
  42. #define LDAPSEC_RETRY_WAIT 3
  43. #ifdef _WIN32
  44. #define LDAP_NO_ATTRS "1.1"
  45. #endif
  46. class CLoadBalancer : public CInterface, implements IInterface
  47. {
  48. private:
  49. StringArray hostArray;
  50. unsigned nextIndex;
  51. Mutex m_mutex;
  52. public:
  53. IMPLEMENT_IINTERFACE
  54. CLoadBalancer(const char* addrlist)
  55. {
  56. char *copyFullText = strdup(addrlist);
  57. char *saveptr;
  58. char *ip = strtok_r(copyFullText, "|", &saveptr);
  59. while (ip != NULL)
  60. {
  61. if (isdigit(*ip))
  62. {
  63. char *dash = strrchr(ip, '-');
  64. if (dash)
  65. {
  66. *dash = 0;
  67. int last = atoi(dash+1);
  68. char *dot = strrchr(ip, '.');
  69. *dot = 0;
  70. int first = atoi(dot+1);
  71. for (int i = first; i <= last; i++)
  72. {
  73. StringBuffer t;
  74. t.append(ip).append('.').append(i);
  75. hostArray.append(t.str());
  76. }
  77. }
  78. else
  79. {
  80. hostArray.append(ip);
  81. }
  82. }
  83. else
  84. {
  85. hostArray.append(ip);
  86. }
  87. ip = strtok_r(NULL, "|", &saveptr);
  88. }
  89. free(copyFullText);
  90. if(hostArray.length() == 0)
  91. {
  92. throw MakeStringException(-1, "No valid ldap server address specified");
  93. }
  94. Owned<IRandomNumberGenerator> random = createRandomNumberGenerator();
  95. random->seed((unsigned)get_cycles_now());
  96. unsigned i = hostArray.ordinality();
  97. while (i > 1)
  98. {
  99. unsigned j = random->next() % i;
  100. i--;
  101. hostArray.swap(i, j);
  102. }
  103. nextIndex = 0;
  104. for(unsigned ind = 0; ind < hostArray.length(); ind++)
  105. {
  106. DBGLOG("Added ldap server %s", hostArray.item(ind));
  107. }
  108. }
  109. virtual ~CLoadBalancer()
  110. {
  111. }
  112. const char* next()
  113. {
  114. unsigned curindex = 0;
  115. {
  116. synchronized block(m_mutex);
  117. curindex = nextIndex;
  118. ++nextIndex %= hostArray.ordinality();
  119. }
  120. return (hostArray.item(curindex));
  121. }
  122. };
  123. bool LdapServerDown(int rc)
  124. {
  125. return rc==LDAP_SERVER_DOWN||rc==LDAP_UNAVAILABLE||rc==LDAP_TIMEOUT;
  126. }
  127. class CLdapConfig : public CInterface, implements ILdapConfig
  128. {
  129. private:
  130. LdapServerType m_serverType;
  131. Owned<IPropertyTree> m_cfg;
  132. Owned<CLoadBalancer> m_ldaphosts;
  133. int m_ldapport;
  134. int m_ldap_secure_port;
  135. StringBuffer m_protocol;
  136. StringBuffer m_basedn;
  137. StringBuffer m_domain;
  138. StringBuffer m_authmethod;
  139. StringBuffer m_user_basedn;
  140. StringBuffer m_group_basedn;
  141. StringBuffer m_resource_basedn;
  142. StringBuffer m_filescope_basedn;
  143. StringBuffer m_workunitscope_basedn;
  144. StringBuffer m_sudoers_basedn;
  145. StringBuffer m_template_name;
  146. StringBuffer m_sysuser;
  147. StringBuffer m_sysuser_commonname;
  148. StringBuffer m_sysuser_password;
  149. StringBuffer m_sysuser_basedn;
  150. bool m_sysuser_specified;
  151. StringBuffer m_sysuser_dn;
  152. int m_maxConnections;
  153. StringBuffer m_sdfieldname;
  154. public:
  155. IMPLEMENT_IINTERFACE
  156. CLdapConfig(IPropertyTree* cfg)
  157. {
  158. int version = LDAP_VERSION3;
  159. ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
  160. m_serverType = ACTIVE_DIRECTORY;
  161. m_cfg.set(cfg);
  162. StringBuffer hostsbuf;
  163. cfg->getProp(".//@ldapAddress", hostsbuf);
  164. if(hostsbuf.length() == 0)
  165. {
  166. throw MakeStringException(-1, "ldapAddress not found in config");
  167. }
  168. m_ldaphosts.setown(new CLoadBalancer(hostsbuf.str()));
  169. cfg->getProp(".//@ldapProtocol", m_protocol);
  170. if(m_protocol.length() == 0)
  171. {
  172. m_protocol.append("ldap");
  173. }
  174. StringBuffer portbuf;
  175. cfg->getProp(".//@ldapPort", portbuf);
  176. if(portbuf.length() == 0)
  177. m_ldapport = 389;
  178. else
  179. m_ldapport = atoi(portbuf.str());
  180. portbuf.clear();
  181. cfg->getProp(".//@ldapSecurePort", portbuf);
  182. if(portbuf.length() == 0)
  183. m_ldap_secure_port = 636;
  184. else
  185. m_ldap_secure_port = atoi(portbuf.str());
  186. StringBuffer hostbuf, dcbuf;
  187. int rc = 0;
  188. getLdapHost(hostbuf);
  189. for(int retries = 0; retries <= LDAPSEC_MAX_RETRIES; retries++)
  190. {
  191. rc = LdapUtils::getServerInfo(hostbuf.str(), m_ldapport, dcbuf, m_serverType, cfg->queryProp(".//@ldapDomain"));
  192. if(!LdapServerDown(rc) || retries > LDAPSEC_MAX_RETRIES)
  193. break;
  194. sleep(LDAPSEC_RETRY_WAIT);
  195. if(retries < LDAPSEC_MAX_RETRIES)
  196. {
  197. DBGLOG("Server %s temporarily unreachable.", hostbuf.str());
  198. // Retrying next ldap sever, might be the same server
  199. hostbuf.clear();
  200. getLdapHost(hostbuf);
  201. DBGLOG("Retrying with %s...", hostbuf.str());
  202. }
  203. }
  204. if(rc != LDAP_SUCCESS)
  205. {
  206. throw MakeStringException(-1, "getServerInfo error - %s", ldap_err2string(rc));
  207. }
  208. const char* basedn = cfg->queryProp(".//@commonBasedn");
  209. if(basedn == NULL || *basedn == '\0')
  210. {
  211. basedn = dcbuf.str();
  212. }
  213. LdapUtils::cleanupDn(basedn, m_basedn);
  214. StringBuffer user_basedn;
  215. cfg->getProp(".//@usersBasedn", user_basedn);
  216. if(user_basedn.length() == 0)
  217. {
  218. throw MakeStringException(-1, "users basedn not found in config");
  219. }
  220. LdapUtils::normalizeDn(user_basedn.str(), m_basedn.str(), m_user_basedn);
  221. StringBuffer group_basedn;
  222. cfg->getProp(".//@groupsBasedn", group_basedn);
  223. if(group_basedn.length() == 0)
  224. {
  225. throw MakeStringException(-1, "groups basedn not found in config");
  226. }
  227. LdapUtils::normalizeDn(group_basedn.str(), m_basedn.str(), m_group_basedn);
  228. StringBuffer dnbuf;
  229. cfg->getProp(".//@modulesBasedn", dnbuf);
  230. if(dnbuf.length() == 0)
  231. cfg->getProp(".//@resourcesBasedn", dnbuf);
  232. if(dnbuf.length() > 0)
  233. LdapUtils::normalizeDn(dnbuf.str(), m_basedn.str(), m_resource_basedn);
  234. dnbuf.clear();
  235. cfg->getProp(".//@filesBasedn", dnbuf);
  236. if(dnbuf.length() > 0)
  237. LdapUtils::normalizeDn(dnbuf.str(), m_basedn.str(), m_filescope_basedn);
  238. dnbuf.clear();
  239. cfg->getProp(".//@workunitsBasedn", dnbuf);
  240. if(dnbuf.length() > 0)
  241. LdapUtils::normalizeDn(dnbuf.str(), m_basedn.str(), m_workunitscope_basedn);
  242. if(m_resource_basedn.length() + m_filescope_basedn.length() + m_workunitscope_basedn.length() == 0)
  243. {
  244. throw MakeStringException(-1, "One of the following basedns need to be defined: modulesBasedn, resourcesBasedn, filesBasedn or workunitScopesBasedn.");
  245. }
  246. dnbuf.clear();
  247. cfg->getProp(".//@sudoersBasedn", dnbuf);
  248. if(dnbuf.length() == 0)
  249. dnbuf.append("ou=SUDOers");
  250. LdapUtils::normalizeDn(dnbuf.str(), m_basedn.str(), m_sudoers_basedn);
  251. cfg->getProp(".//@templateName", m_template_name);
  252. cfg->getProp(".//@authMethod", m_authmethod);
  253. cfg->getProp(".//@ldapDomain", m_domain);
  254. if(m_domain.length() == 0)
  255. {
  256. const char* dptr = strchr(m_basedn.str(), '=');
  257. if(dptr != NULL)
  258. {
  259. dptr++;
  260. while(*dptr != 0 && *dptr != ',')
  261. {
  262. char c = *dptr++;
  263. m_domain.append(c);
  264. }
  265. }
  266. }
  267. m_sysuser_specified = true;
  268. cfg->getProp(".//@systemUser", m_sysuser);
  269. if(m_sysuser.length() == 0)
  270. {
  271. m_sysuser_specified = false;
  272. }
  273. cfg->getProp(".//@systemCommonName", m_sysuser_commonname);
  274. if(m_sysuser_specified && (m_sysuser_commonname.length() == 0))
  275. {
  276. throw MakeStringException(-1, "SystemUser commonname is empty");
  277. }
  278. StringBuffer passbuf;
  279. cfg->getProp(".//@systemPassword", passbuf);
  280. decrypt(m_sysuser_password, passbuf.str());
  281. StringBuffer sysuser_basedn;
  282. cfg->getProp(".//@systemBasedn", sysuser_basedn);
  283. if(sysuser_basedn.length() == 0)
  284. {
  285. if(m_serverType == ACTIVE_DIRECTORY)
  286. LdapUtils::normalizeDn( "cn=Users", m_basedn.str(), m_sysuser_basedn);
  287. else if(m_serverType == IPLANET)
  288. m_sysuser_basedn.append("ou=administrators,ou=topologymanagement,o=netscaperoot");
  289. else if(m_serverType == OPEN_LDAP)
  290. m_sysuser_basedn.append(m_basedn.str());
  291. }
  292. else
  293. {
  294. if(m_serverType == ACTIVE_DIRECTORY)
  295. LdapUtils::normalizeDn(sysuser_basedn.str(), m_basedn.str(), m_sysuser_basedn);
  296. else
  297. m_sysuser_basedn.append(sysuser_basedn.str());
  298. }
  299. if(m_sysuser_specified)
  300. {
  301. if(m_serverType == IPLANET)
  302. m_sysuser_dn.append("uid=").append(m_sysuser.str()).append(",").append(m_sysuser_basedn.str());
  303. else if(m_serverType == ACTIVE_DIRECTORY)
  304. m_sysuser_dn.append("cn=").append(m_sysuser_commonname.str()).append(",").append(m_sysuser_basedn.str());
  305. else if(m_serverType == OPEN_LDAP)
  306. m_sysuser_dn.append("cn=").append(m_sysuser_commonname.str()).append(",").append(m_sysuser_basedn.str());
  307. }
  308. m_maxConnections = cfg->getPropInt(".//@maxConnections", DEFAULT_LDAP_POOL_SIZE);
  309. if(m_maxConnections <= 0)
  310. m_maxConnections = DEFAULT_LDAP_POOL_SIZE;
  311. if(m_serverType == ACTIVE_DIRECTORY)
  312. m_sdfieldname.append("ntSecurityDescriptor");
  313. else if(m_serverType == IPLANET)
  314. m_sdfieldname.append("aci");
  315. else if(m_serverType == OPEN_LDAP)
  316. m_sdfieldname.append("OpenLDAPaci");
  317. }
  318. virtual LdapServerType getServerType()
  319. {
  320. return m_serverType;
  321. }
  322. virtual const char* getSdFieldName()
  323. {
  324. return m_sdfieldname.str();
  325. }
  326. virtual StringBuffer& getLdapHost(StringBuffer& hostbuf)
  327. {
  328. hostbuf.clear();
  329. try
  330. {
  331. hostbuf.append(m_ldaphosts->next());
  332. }
  333. catch(IException* e)
  334. {
  335. StringBuffer emsg;
  336. e->errorMessage(emsg);
  337. DBGLOG("getLdapHost exception - %s", emsg.str());
  338. e->Release();
  339. }
  340. catch(...)
  341. {
  342. DBGLOG("getLdapHost unknown exception");
  343. }
  344. return hostbuf;
  345. }
  346. virtual void markDown(const char* ldaphost)
  347. {
  348. //SocketEndpoint ep(ldaphost, 0);
  349. //m_ldaphosts->setStatus(ep, false);
  350. }
  351. virtual int getLdapPort()
  352. {
  353. return m_ldapport;
  354. }
  355. virtual int getLdapSecurePort()
  356. {
  357. return m_ldap_secure_port;
  358. }
  359. virtual const char* getProtocol()
  360. {
  361. return m_protocol.str();
  362. }
  363. virtual const char* getBasedn()
  364. {
  365. return m_basedn.str();
  366. }
  367. virtual const char* getDomain()
  368. {
  369. return m_domain.str();
  370. }
  371. virtual const char* getAuthMethod()
  372. {
  373. return m_authmethod.str();
  374. }
  375. virtual const char* getUserBasedn()
  376. {
  377. return m_user_basedn.str();
  378. }
  379. virtual const char* getGroupBasedn()
  380. {
  381. return m_group_basedn.str();
  382. }
  383. virtual const char* getResourceBasedn(SecResourceType rtype)
  384. {
  385. if(rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE)
  386. return m_resource_basedn.str();
  387. else if(rtype == RT_FILE_SCOPE)
  388. return m_filescope_basedn.str();
  389. else if(rtype == RT_WORKUNIT_SCOPE)
  390. return m_workunitscope_basedn.str();
  391. else if(rtype == RT_SUDOERS)
  392. return m_sudoers_basedn.str();
  393. else
  394. return m_resource_basedn.str();
  395. }
  396. virtual const char* getTemplateName()
  397. {
  398. return m_template_name.str();
  399. }
  400. virtual const char* getSysUser()
  401. {
  402. return m_sysuser.str();
  403. }
  404. virtual const char* getSysUserDn()
  405. {
  406. return m_sysuser_dn.str();
  407. }
  408. virtual const char* getSysUserCommonName()
  409. {
  410. return m_sysuser_commonname.str();
  411. }
  412. virtual const char* getSysUserPassword()
  413. {
  414. return m_sysuser_password.str();
  415. }
  416. virtual const char* getSysUserBasedn()
  417. {
  418. return m_sysuser_basedn.str();
  419. }
  420. virtual bool sysuserSpecified()
  421. {
  422. return m_sysuser_specified;
  423. }
  424. virtual int getMaxConnections()
  425. {
  426. return m_maxConnections;
  427. }
  428. // For now, only sets default resourcebasedn, since it's only used by ESP services
  429. virtual void setResourceBasedn(const char* rbasedn, SecResourceType rtype)
  430. {
  431. if(rbasedn == NULL || rbasedn[0] == '\0')
  432. return;
  433. if(rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE)
  434. {
  435. LdapUtils::normalizeDn(rbasedn, m_basedn.str(), m_resource_basedn);
  436. }
  437. else if(rtype == RT_FILE_SCOPE)
  438. {
  439. LdapUtils::normalizeDn(rbasedn, m_basedn.str(), m_filescope_basedn);
  440. }
  441. else if(rtype == RT_WORKUNIT_SCOPE)
  442. {
  443. LdapUtils::normalizeDn(rbasedn, m_basedn.str(), m_workunitscope_basedn);
  444. }
  445. else
  446. {
  447. LdapUtils::normalizeDn(rbasedn, m_basedn.str(), m_resource_basedn);
  448. }
  449. }
  450. virtual void getDefaultSysUserBasedn(StringBuffer& sysuser_basedn)
  451. {
  452. if(m_serverType == ACTIVE_DIRECTORY)
  453. LdapUtils::normalizeDn( "cn=Users", m_basedn.str(), sysuser_basedn);
  454. else if(m_serverType == IPLANET)
  455. sysuser_basedn.append("ou=administrators,ou=topologymanagement,o=netscaperoot");
  456. }
  457. };
  458. class CLdapConnection : public CInterface, implements ILdapConnection
  459. {
  460. private:
  461. LDAP *m_ld;
  462. Owned<CLdapConfig> m_ldapconfig;
  463. time_t m_lastaccesstime;
  464. bool m_connected;
  465. public:
  466. IMPLEMENT_IINTERFACE
  467. CLdapConnection(CLdapConfig* ldapconfig)
  468. {
  469. m_ldapconfig.setown(LINK(ldapconfig));
  470. m_ld = NULL;
  471. m_connected = false;
  472. m_lastaccesstime = 0;
  473. }
  474. ~CLdapConnection()
  475. {
  476. if(m_ld != NULL)
  477. {
  478. ldap_unbind(m_ld);
  479. }
  480. }
  481. virtual int connect(const char* ldapserver, const char* protocol)
  482. {
  483. if(!ldapserver || *ldapserver == '\0')
  484. return -1;
  485. m_ld = LdapUtils::LdapInit(protocol, ldapserver, m_ldapconfig->getLdapPort(), m_ldapconfig->getLdapSecurePort());
  486. int rc = LDAP_SUCCESS;
  487. if(m_ldapconfig->sysuserSpecified())
  488. rc = LdapUtils::LdapBind(m_ld, m_ldapconfig->getDomain(), m_ldapconfig->getSysUser(), m_ldapconfig->getSysUserPassword(), m_ldapconfig->getSysUserDn(), m_ldapconfig->getServerType(), m_ldapconfig->getAuthMethod());
  489. else
  490. rc = LdapUtils::LdapBind(m_ld, m_ldapconfig->getDomain(), NULL, NULL, NULL, m_ldapconfig->getServerType(), m_ldapconfig->getAuthMethod());
  491. if(rc == LDAP_SUCCESS)
  492. {
  493. time(&m_lastaccesstime);
  494. m_connected = true;
  495. DBGLOG("Connected to LdapServer %s using protocol %s", ldapserver, protocol);
  496. }
  497. else
  498. {
  499. DBGLOG("LDAP: sysuser bind failed - %s", ldap_err2string(rc));
  500. ldap_unbind(m_ld);
  501. m_ld = NULL;
  502. }
  503. return rc;
  504. }
  505. virtual bool connect(bool force_ssl = false)
  506. {
  507. StringBuffer hostbuf;
  508. m_ldapconfig->getLdapHost(hostbuf);
  509. int rc = LDAP_SERVER_DOWN;
  510. const char* proto;
  511. if(force_ssl)
  512. proto = "ldaps";
  513. else
  514. proto = m_ldapconfig->getProtocol();
  515. for(int retries = 0; retries <= LDAPSEC_MAX_RETRIES; retries++)
  516. {
  517. rc = connect(hostbuf.str(), proto);
  518. if(!LdapServerDown(rc) || retries > LDAPSEC_MAX_RETRIES)
  519. break;
  520. sleep(LDAPSEC_RETRY_WAIT);
  521. if(retries < LDAPSEC_MAX_RETRIES)
  522. DBGLOG("Server temporarily unreachable, retrying ...");
  523. // Retrying next ldap sever, might be the same server
  524. hostbuf.clear();
  525. m_ldapconfig->getLdapHost(hostbuf);
  526. }
  527. if(rc == LDAP_SERVER_DOWN)
  528. {
  529. StringBuffer dc;
  530. LdapUtils::getDcName(m_ldapconfig->getDomain(), dc);
  531. if(dc.length() > 0)
  532. {
  533. WARNLOG("Using automatically obtained LDAP Server %s", dc.str());
  534. rc = connect(dc.str(), proto);
  535. }
  536. }
  537. if(rc == LDAP_SUCCESS)
  538. return true;
  539. else
  540. return false;
  541. }
  542. virtual LDAP* getLd()
  543. {
  544. return m_ld;
  545. }
  546. virtual bool validate()
  547. {
  548. time_t now;
  549. time(&now);
  550. if(!m_connected)
  551. return connect();
  552. else if(now - m_lastaccesstime <= 300)
  553. return true;
  554. else
  555. {
  556. bool ok = false;
  557. LDAPMessage* msg = NULL;
  558. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  559. int err = ldap_search_ext_s(m_ld, NULL, LDAP_SCOPE_BASE, "objectClass=*", NULL, 0, NULL, NULL, &timeOut, 1, &msg);
  560. if(err == LDAP_SUCCESS)
  561. {
  562. ok = true;
  563. }
  564. if(msg != NULL)
  565. ldap_msgfree(msg);
  566. if(!ok)
  567. {
  568. if(m_ld != NULL)
  569. {
  570. ldap_unbind(m_ld);
  571. m_ld = NULL;
  572. m_connected = false;
  573. }
  574. DBGLOG("cached connection invalid, creating a new connection");
  575. return connect();
  576. }
  577. else
  578. {
  579. time(&m_lastaccesstime);
  580. }
  581. }
  582. return true;
  583. }
  584. };
  585. class CLdapConnectionPool : public CInterface, implements ILdapConnectionPool
  586. {
  587. private:
  588. int m_maxsize;
  589. int m_currentsize;
  590. IArrayOf<ILdapConnection> m_connections;
  591. Monitor m_monitor;
  592. Owned<CLdapConfig> m_ldapconfig;
  593. public:
  594. IMPLEMENT_IINTERFACE
  595. CLdapConnectionPool(CLdapConfig* ldapconfig)
  596. {
  597. m_ldapconfig.setown(LINK(ldapconfig));
  598. m_maxsize = m_ldapconfig->getMaxConnections();
  599. m_currentsize = 0;
  600. // Set LDAP version to 3
  601. int version = LDAP_VERSION3;
  602. ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
  603. }
  604. virtual ILdapConnection* getConnection()
  605. {
  606. synchronized block(m_monitor);
  607. ForEachItemIn(x, m_connections)
  608. {
  609. CLdapConnection* curcon = (CLdapConnection*)&(m_connections.item(x));
  610. if(curcon != NULL && !curcon->IsShared())
  611. {
  612. //PrintLog("Reusing an LDAP connection");
  613. if(curcon->validate())
  614. return LINK(curcon);
  615. else
  616. throw MakeStringException(-1, "Connecting/authenticating to ldap server in re-validation failed");
  617. }
  618. }
  619. //PrintLog("Creating new connection");
  620. CLdapConnection* newcon = new CLdapConnection(m_ldapconfig.get());
  621. if(newcon != NULL)
  622. {
  623. if(!newcon->connect())
  624. {
  625. throw MakeStringException(-1, "Connecting/authenticating to ldap server failed");
  626. }
  627. if(m_currentsize <= m_maxsize)
  628. {
  629. m_connections.append(*newcon);
  630. m_currentsize++;
  631. return LINK(newcon);
  632. }
  633. else
  634. {
  635. return newcon;
  636. }
  637. }
  638. else
  639. {
  640. throw MakeStringException(-1, "Failed to create new ldap connection");
  641. }
  642. }
  643. virtual ILdapConnection* getSSLConnection()
  644. {
  645. CLdapConnection* newcon = new CLdapConnection(m_ldapconfig.get());
  646. if(newcon != NULL)
  647. {
  648. if(!newcon->connect(true))
  649. {
  650. throw MakeStringException(-1, "Connecting/authenticating to ldap server via ldaps failed");
  651. }
  652. return newcon;
  653. }
  654. else
  655. {
  656. throw MakeStringException(-1, "Failed to create new ldap connection");
  657. }
  658. }
  659. };
  660. #define LDAP_CONNECTION_TIMEOUT INFINITE
  661. //------------ New Connection Pool Implementation ------------//
  662. class CLdapConnectionManager : public CInterface, implements IResourceFactory<CLdapConnection>
  663. {
  664. Owned<CLdapConfig> m_ldapconfig;
  665. public:
  666. IMPLEMENT_IINTERFACE;
  667. CLdapConnectionManager(CLdapConfig* ldapconfig)
  668. {
  669. m_ldapconfig.setown(LINK(ldapconfig));
  670. }
  671. CLdapConnection* createResource()
  672. {
  673. CLdapConnection* newcon = new CLdapConnection(m_ldapconfig.get());
  674. if(newcon != NULL)
  675. {
  676. if(!newcon->connect())
  677. {
  678. throw MakeStringException(-1, "Connecting/authenticating to ldap server failed");
  679. }
  680. return newcon;
  681. }
  682. else
  683. {
  684. throw MakeStringException(-1, "Failed to create new ldap connection");
  685. }
  686. }
  687. };
  688. class CLdapConnectionPool2 : public CInterface, implements ILdapConnectionPool
  689. {
  690. private:
  691. int m_maxsize;
  692. Owned<CLdapConfig> m_ldapconfig;
  693. Owned<CResourcePool<CLdapConnection> > m_connections;
  694. public:
  695. IMPLEMENT_IINTERFACE
  696. CLdapConnectionPool2(CLdapConfig* ldapconfig)
  697. {
  698. m_ldapconfig.setown(LINK(ldapconfig));
  699. m_maxsize = m_ldapconfig->getMaxConnections();
  700. // Set LDAP version to 3
  701. int version = LDAP_VERSION3;
  702. ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
  703. m_connections.setown(new CResourcePool<CLdapConnection>);
  704. Owned<CLdapConnectionManager> poolMgr = new CLdapConnectionManager(ldapconfig);
  705. m_connections->init(m_maxsize, poolMgr.get());
  706. }
  707. virtual ILdapConnection* getConnection()
  708. {
  709. Owned<CLdapConnection> con;
  710. try
  711. {
  712. con.setown(m_connections->get(LDAP_CONNECTION_TIMEOUT));
  713. }
  714. catch(IException* e)
  715. {
  716. StringBuffer emsg;
  717. e->errorMessage(emsg);
  718. DBGLOG("getConnection exception - %s", emsg.str());
  719. e->Release();
  720. }
  721. catch(...)
  722. {
  723. DBGLOG("getConnection unknown exception");
  724. }
  725. if(con.get())
  726. {
  727. if(con->validate())
  728. return con.getLink();
  729. else
  730. throw MakeStringException(-1, "Connecting/authenticating to ldap server in re-validation failed");
  731. }
  732. else
  733. throw MakeStringException(-1, "Failed to get an LDAP Connection.");
  734. }
  735. virtual ILdapConnection* getSSLConnection()
  736. {
  737. CLdapConnection* newcon = new CLdapConnection(m_ldapconfig.get());
  738. if(newcon != NULL)
  739. {
  740. if(!newcon->connect(true))
  741. {
  742. throw MakeStringException(-1, "Connecting/authenticating to ldap server via ldaps failed");
  743. }
  744. return newcon;
  745. }
  746. else
  747. {
  748. throw MakeStringException(-1, "Failed to create new ldap connection");
  749. }
  750. }
  751. };
  752. struct ltstr
  753. {
  754. bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
  755. };
  756. class CLdapClient : public CInterface, implements ILdapClient
  757. {
  758. private:
  759. Owned<ILdapConnectionPool> m_connections;
  760. IPermissionProcessor* m_pp;
  761. //int m_defaultFileScopePermission;
  762. //int m_defaultWorkunitScopePermission;
  763. Owned<CLdapConfig> m_ldapconfig;
  764. StringBuffer m_pwscheme;
  765. public:
  766. IMPLEMENT_IINTERFACE
  767. CLdapClient(IPropertyTree* cfg)
  768. {
  769. m_ldapconfig.setown(new CLdapConfig(cfg));
  770. if(cfg && cfg->getPropBool("@useRealConnectionPool", false))
  771. m_connections.setown(new CLdapConnectionPool2(m_ldapconfig.get()));
  772. else
  773. m_connections.setown(new CLdapConnectionPool(m_ldapconfig.get()));
  774. m_pp = NULL;
  775. //m_defaultFileScopePermission = -2;
  776. //m_defaultWorkunitScopePermission = -2;
  777. }
  778. virtual void init(IPermissionProcessor* pp)
  779. {
  780. m_pp = pp;
  781. if(m_ldapconfig->getServerType() == OPEN_LDAP)
  782. {
  783. try
  784. {
  785. addDC(m_ldapconfig->getBasedn());
  786. }
  787. catch(...)
  788. {
  789. }
  790. try
  791. {
  792. addGroup("Directory Administrators", m_ldapconfig->getBasedn());
  793. }
  794. catch(...)
  795. {
  796. }
  797. }
  798. createLdapBasedn(NULL, m_ldapconfig->getResourceBasedn(RT_DEFAULT), PT_DEFAULT);
  799. createLdapBasedn(NULL, m_ldapconfig->getResourceBasedn(RT_FILE_SCOPE), PT_DEFAULT);
  800. createLdapBasedn(NULL, m_ldapconfig->getResourceBasedn(RT_WORKUNIT_SCOPE), PT_DEFAULT);
  801. createLdapBasedn(NULL, m_ldapconfig->getResourceBasedn(RT_SUDOERS), PT_DEFAULT);
  802. createLdapBasedn(NULL, m_ldapconfig->getUserBasedn(), PT_DEFAULT);
  803. createLdapBasedn(NULL, m_ldapconfig->getGroupBasedn(), PT_DEFAULT);
  804. }
  805. virtual LdapServerType getServerType()
  806. {
  807. return m_ldapconfig->getServerType();
  808. }
  809. virtual ILdapConfig* getLdapConfig()
  810. {
  811. return m_ldapconfig.get();
  812. }
  813. virtual void setResourceBasedn(const char* rbasedn, SecResourceType rtype)
  814. {
  815. m_ldapconfig->setResourceBasedn(rbasedn, rtype);
  816. createLdapBasedn(NULL, m_ldapconfig->getResourceBasedn(rtype), PT_DEFAULT);
  817. }
  818. virtual bool authenticate(ISecUser& user)
  819. {
  820. {
  821. char *attribute, **values;
  822. BerElement *ber;
  823. const char* username = user.getName();
  824. const char* password = user.credentials().getPassword();
  825. if(!username || !*username || !password || !*password)
  826. return false;
  827. const char* sysuser = m_ldapconfig->getSysUser();
  828. if(sysuser && *sysuser && (strcmp(username, sysuser) == 0))
  829. {
  830. if(strcmp(password, m_ldapconfig->getSysUserPassword()) == 0)
  831. {
  832. user.setFullName(m_ldapconfig->getSysUserCommonName());
  833. user.setAuthenticated(true);
  834. return true;
  835. }
  836. else
  837. {
  838. return false;
  839. }
  840. }
  841. StringBuffer filter;
  842. // Retrieve user's dn with system connection
  843. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  844. filter.append("sAMAccountName=");
  845. else
  846. filter.append("uid=");
  847. filter.append(username);
  848. LDAPMessage *res;
  849. char* attrs[] = {"cn", NULL};
  850. Owned<ILdapConnection> lconn = m_connections->getConnection();
  851. LDAP* sys_ld = ((CLdapConnection*)lconn.get())->getLd();
  852. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  853. int result = ldap_search_ext_s(sys_ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &res);
  854. if(result != LDAP_SUCCESS)
  855. {
  856. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( result ), filter.str(), m_ldapconfig->getUserBasedn());
  857. return false;
  858. }
  859. unsigned entries = ldap_count_entries(sys_ld, res);
  860. if(entries == 0)
  861. {
  862. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  863. result = ldap_search_ext_s(sys_ld, (char*)m_ldapconfig->getSysUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &res);
  864. if(result != LDAP_SUCCESS)
  865. {
  866. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( result ), filter.str(), m_ldapconfig->getSysUserBasedn());
  867. return false;
  868. }
  869. entries = ldap_count_entries(sys_ld, res);
  870. if(entries == 0)
  871. {
  872. DBGLOG("LDAP: User %s not found", username);
  873. return false;
  874. }
  875. }
  876. LDAPMessage *entry = LdapFirstEntry(sys_ld, res);
  877. if(entry == NULL)
  878. {
  879. DBGLOG("LDAP: Can't find entry for user %s", username);
  880. return false;
  881. }
  882. for ( attribute = ldap_first_attribute(sys_ld, res, &ber ); attribute != NULL; attribute = ldap_next_attribute(sys_ld, res, ber))
  883. {
  884. if((stricmp(attribute, "cn") == 0) && (values = ldap_get_values(sys_ld, entry, attribute)) != NULL )
  885. {
  886. //set the FullName
  887. if(values[0] != NULL)
  888. user.setFullName(values[0]);
  889. ldap_value_free( values );
  890. break;
  891. }
  892. }
  893. ber_free(ber, 0);
  894. char *userdn = ldap_get_dn(sys_ld, entry);
  895. if(userdn == NULL || strlen(userdn) == 0)
  896. {
  897. DBGLOG("LDAP: dn not found for user %s", username);
  898. ldap_msgfree(entry);
  899. return false;
  900. }
  901. StringBuffer userdnbuf;
  902. userdnbuf.append(userdn);
  903. ldap_msgfree(entry);
  904. ldap_memfree(userdn);
  905. StringBuffer hostbuf;
  906. m_ldapconfig->getLdapHost(hostbuf);
  907. int rc = LDAP_SERVER_DOWN;
  908. for(int retries = 0; retries <= LDAPSEC_MAX_RETRIES; retries++)
  909. {
  910. DBGLOG("LdapBind for user %s (retries=%d).", username, retries);
  911. {
  912. LDAP* user_ld = LdapUtils::LdapInit(m_ldapconfig->getProtocol(), hostbuf.str(), m_ldapconfig->getLdapPort(), m_ldapconfig->getLdapSecurePort());
  913. rc = LdapUtils::LdapBind(user_ld, m_ldapconfig->getDomain(), username, password, userdnbuf.str(), m_ldapconfig->getServerType(), m_ldapconfig->getAuthMethod());
  914. ldap_unbind(user_ld);
  915. }
  916. DBGLOG("finished LdapBind for user %s", username);
  917. if(!LdapServerDown(rc) || retries > LDAPSEC_MAX_RETRIES)
  918. break;
  919. sleep(LDAPSEC_RETRY_WAIT);
  920. if(retries < LDAPSEC_MAX_RETRIES)
  921. DBGLOG("Server temporarily unreachable, retrying ...");
  922. // Retrying next ldap sever, might be the same server
  923. hostbuf.clear();
  924. m_ldapconfig->getLdapHost(hostbuf);
  925. }
  926. if(rc == LDAP_SERVER_DOWN)
  927. {
  928. StringBuffer dc;
  929. LdapUtils::getDcName(NULL, dc);
  930. if(dc.length() > 0)
  931. {
  932. WARNLOG("Using automatically obtained LDAP Server %s", dc.str());
  933. LDAP* user_ld = LdapUtils::LdapInit(m_ldapconfig->getProtocol(), dc.str(), m_ldapconfig->getLdapPort(), m_ldapconfig->getLdapSecurePort());
  934. rc = LdapUtils::LdapBind(user_ld, m_ldapconfig->getDomain(), username, password, userdnbuf.str(), m_ldapconfig->getServerType(), m_ldapconfig->getAuthMethod());
  935. ldap_unbind(user_ld);
  936. }
  937. }
  938. if(rc != LDAP_SUCCESS)
  939. {
  940. DBGLOG("LDAP: Authentication for user %s failed - %s", username, ldap_err2string(rc));
  941. return false;
  942. }
  943. user.setAuthenticated(true);
  944. }
  945. //Always retrieve user info(SID, UID, fullname, etc) for Active Directory, when the user first logs in.
  946. if((m_ldapconfig->getServerType() == ACTIVE_DIRECTORY) && (m_pp != NULL))
  947. m_pp->retrieveUserInfo(user);
  948. return true;
  949. };
  950. virtual bool authorize(SecResourceType rtype, ISecUser& user, IArrayOf<ISecResource>& resources)
  951. {
  952. bool ok = false;
  953. const char* basedn = m_ldapconfig->getResourceBasedn(rtype);
  954. if(basedn == NULL || *basedn == '\0')
  955. {
  956. DBGLOG("corresponding basedn is not defined for authorize");
  957. return false;
  958. }
  959. const char* username = user.getName();
  960. if(!username || !*username)
  961. return false;
  962. const char* sysuser = m_ldapconfig->getSysUser();
  963. if(sysuser && *sysuser && (strcmp(username, sysuser) == 0))
  964. {
  965. ForEachItemIn(x, resources)
  966. {
  967. ISecResource* res = &resources.item(x);
  968. if(!res)
  969. continue;
  970. if(rtype == RT_MODULE)
  971. {
  972. StringBuffer filter;
  973. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  974. filter.append("name=");
  975. else
  976. filter.append("ou=");
  977. filter.append(res->getName());
  978. int count = countEntries(m_ldapconfig->getResourceBasedn(rtype), (char*)filter.str(), 10);
  979. if(count != 0)
  980. res->setAccessFlags(SecAccess_Full);
  981. else
  982. res->setAccessFlags(-1);
  983. }
  984. else
  985. res->setAccessFlags(SecAccess_Full);
  986. }
  987. return true;
  988. }
  989. if(rtype == RT_FILE_SCOPE)
  990. {
  991. int defaultFileScopePermission = -2;
  992. //if(m_defaultFileScopePermission == -2)
  993. {
  994. const char* basebasedn = strchr(basedn, ',') + 1;
  995. StringBuffer baseresource;
  996. baseresource.append(basebasedn-basedn-4, basedn+3);
  997. IArrayOf<ISecResource> base_resources;
  998. base_resources.append(*(new CLdapSecResource(baseresource.str())));
  999. bool baseok = authorizeScope(user, base_resources, basebasedn);
  1000. if(baseok)
  1001. {
  1002. //m_defaultFileScopePermission = base_resources.item(0).getAccessFlags();
  1003. defaultFileScopePermission = base_resources.item(0).getAccessFlags();
  1004. }
  1005. }
  1006. IArrayOf<ISecResource> non_emptylist;
  1007. ForEachItemIn(x, resources)
  1008. {
  1009. ISecResource& res = resources.item(x);
  1010. const char* res_name = res.getName();
  1011. if(res_name == NULL || *res_name == '\0')
  1012. res.setAccessFlags(defaultFileScopePermission); //res.setAccessFlags(m_defaultFileScopePermission);
  1013. else
  1014. non_emptylist.append(*LINK(&res));
  1015. }
  1016. ok = authorizeScope(user, non_emptylist, basedn);
  1017. //if(ok && m_defaultFileScopePermission != -2)
  1018. if(ok && defaultFileScopePermission != -2)
  1019. {
  1020. ForEachItemIn(x, non_emptylist)
  1021. {
  1022. ISecResource& res = non_emptylist.item(x);
  1023. if(res.getAccessFlags() == -1)
  1024. res.setAccessFlags(defaultFileScopePermission); //res.setAccessFlags(m_defaultFileScopePermission);
  1025. }
  1026. }
  1027. return ok;
  1028. }
  1029. else if(rtype == RT_WORKUNIT_SCOPE)
  1030. {
  1031. int defaultWorkunitScopePermission = -2;
  1032. //if(m_defaultWorkunitScopePermission == -2)
  1033. {
  1034. const char* basebasedn = strchr(basedn, ',') + 1;
  1035. StringBuffer baseresource;
  1036. baseresource.append(basebasedn-basedn-4, basedn+3);
  1037. IArrayOf<ISecResource> base_resources;
  1038. base_resources.append(*(new CLdapSecResource(baseresource.str())));
  1039. bool baseok = authorizeScope(user, base_resources, basebasedn);
  1040. if(baseok)
  1041. {
  1042. defaultWorkunitScopePermission = base_resources.item(0).getAccessFlags();
  1043. }
  1044. }
  1045. IArrayOf<ISecResource> non_emptylist;
  1046. ForEachItemIn(x, resources)
  1047. {
  1048. ISecResource& res = resources.item(x);
  1049. const char* res_name = res.getName();
  1050. if(res_name == NULL || *res_name == '\0')
  1051. res.setAccessFlags(defaultWorkunitScopePermission);
  1052. else
  1053. non_emptylist.append(*LINK(&res));
  1054. }
  1055. ok = authorizeScope(user, non_emptylist, basedn);
  1056. if(ok && defaultWorkunitScopePermission != -2)
  1057. {
  1058. ForEachItemIn(x, non_emptylist)
  1059. {
  1060. ISecResource& res = non_emptylist.item(x);
  1061. if(res.getAccessFlags() == -1)
  1062. res.setAccessFlags(defaultWorkunitScopePermission);
  1063. }
  1064. }
  1065. return ok;
  1066. }
  1067. else
  1068. {
  1069. IArrayOf<CSecurityDescriptor> sdlist;
  1070. ForEachItemIn(x, resources)
  1071. {
  1072. ISecResource& res = resources.item(x);
  1073. const char* resourcename = res.getName();
  1074. CSecurityDescriptor* sd = new CSecurityDescriptor(resourcename);
  1075. sdlist.append(*sd);
  1076. }
  1077. getSecurityDescriptors(rtype, sdlist);
  1078. if(m_pp != NULL)
  1079. ok = m_pp->getPermissions(user, sdlist, resources);
  1080. return ok;
  1081. }
  1082. }
  1083. // Returns true if all resources are correctly added, otherwise returns false.
  1084. virtual bool addResources(SecResourceType rtype, ISecUser& user, IArrayOf<ISecResource>& resources, SecPermissionType ptype, const char* basedn)
  1085. {
  1086. bool ret = true;
  1087. for(unsigned i = 0; i < resources.length(); i++)
  1088. {
  1089. ISecResource* resource = &resources.item(i);
  1090. if(resource != NULL)
  1091. {
  1092. bool oneret = addResource(rtype, user, resource, ptype, basedn);
  1093. ret = ret && oneret;
  1094. }
  1095. }
  1096. return ret;
  1097. }
  1098. virtual bool getUserInfo(ISecUser& user, const char* infotype)
  1099. {
  1100. char *attribute, **values;
  1101. BerElement *ber;
  1102. LDAPMessage *searchResult, *message;
  1103. const char* username = user.getName();
  1104. if(username == NULL || strlen(username) == 0)
  1105. {
  1106. DBGLOG("LDAP: getUserInfo : username is empty");
  1107. return false;
  1108. }
  1109. if(infotype && stricmp(infotype, "sudoers") == 0)
  1110. {
  1111. CLdapSecUser* ldapuser = dynamic_cast<CLdapSecUser*>(&user);
  1112. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1113. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1114. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1115. StringBuffer filter("sudoUser=");
  1116. filter.append(username);
  1117. char *attrs[] = {"sudoHost", "sudoCommand", "sudoOption", NULL};
  1118. const char* basedn = m_ldapconfig->getResourceBasedn(RT_SUDOERS);
  1119. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult);
  1120. if ( rc != LDAP_SUCCESS )
  1121. {
  1122. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basedn);
  1123. ldapuser->setSudoersEnabled(false);
  1124. ldapuser->setInSudoers(false);
  1125. return false;
  1126. }
  1127. ldapuser->setSudoersEnabled(true);
  1128. unsigned entries = ldap_count_entries(ld, searchResult);
  1129. if(entries == 0)
  1130. {
  1131. ldapuser->setInSudoers(false);
  1132. return true;
  1133. }
  1134. message = LdapFirstEntry(ld, searchResult);
  1135. if(message == NULL)
  1136. {
  1137. ldapuser->setInSudoers(false);
  1138. return true;
  1139. }
  1140. ldapuser->setInSudoers(true);
  1141. for ( attribute = ldap_first_attribute( ld,searchResult,&ber ); attribute != NULL; attribute = ldap_next_attribute(ld, searchResult,ber))
  1142. {
  1143. if(stricmp(attribute, "sudoHost") == 0)
  1144. {
  1145. if (( values = ldap_get_values(ld, message, attribute)) != NULL )
  1146. {
  1147. if(values[0] != NULL)
  1148. ldapuser->setSudoHost(values[0]);
  1149. ldap_value_free( values );
  1150. }
  1151. }
  1152. else if(stricmp(attribute, "sudoCommand") == 0)
  1153. {
  1154. if (( values = ldap_get_values(ld, message, attribute)) != NULL )
  1155. {
  1156. if(values[0] != NULL)
  1157. ldapuser->setSudoCommand(values[0]);
  1158. ldap_value_free(values);
  1159. }
  1160. }
  1161. else if(stricmp(attribute, "sudoOption") == 0)
  1162. {
  1163. if (( values = ldap_get_values(ld, message, attribute)) != NULL )
  1164. {
  1165. if(values[0] != NULL)
  1166. ldapuser->setSudoOption(values[0]);
  1167. ldap_value_free(values);
  1168. }
  1169. }
  1170. }
  1171. ber_free(ber, 0);
  1172. ldap_msgfree(searchResult);
  1173. return true;
  1174. }
  1175. else
  1176. {
  1177. StringBuffer filter;
  1178. const char* basedn = m_ldapconfig->getUserBasedn();
  1179. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1180. {
  1181. filter.append("sAMAccountName=");
  1182. }
  1183. else
  1184. {
  1185. filter.append("uid=");
  1186. if(stricmp(username, m_ldapconfig->getSysUser()) == 0)
  1187. basedn = m_ldapconfig->getSysUserBasedn();
  1188. }
  1189. filter.append(user.getName());
  1190. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1191. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1192. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1193. char *attrs[] = {"cn", "givenName", "sn", "gidnumber", "uidnumber", "homedirectory", "loginshell", "objectClass", NULL};
  1194. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1195. if ( rc != LDAP_SUCCESS )
  1196. {
  1197. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basedn);
  1198. return false;
  1199. }
  1200. ((CLdapSecUser*)&user)->setPosixenabled(false);
  1201. // Go through the search results by checking message types
  1202. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  1203. {
  1204. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  1205. attribute != NULL;
  1206. attribute = ldap_next_attribute( ld, searchResult,ber))
  1207. {
  1208. if(stricmp(attribute, "cn") == 0)
  1209. {
  1210. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1211. {
  1212. //set the FullName
  1213. if(values[0] != NULL)
  1214. user.setFullName(values[0]);
  1215. ldap_value_free( values );
  1216. }
  1217. }
  1218. else if(stricmp(attribute, "givenName") == 0)
  1219. {
  1220. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1221. {
  1222. //set the firstname
  1223. if(values[0] != NULL)
  1224. user.setFirstName(values[0]);
  1225. ldap_value_free( values );
  1226. }
  1227. }
  1228. else if(stricmp(attribute, "sn") == 0)
  1229. {
  1230. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1231. {
  1232. //set lastname
  1233. if(values[0] != NULL)
  1234. user.setLastName(values[0]);
  1235. ldap_value_free( values );
  1236. }
  1237. }
  1238. else if(stricmp(attribute, "gidnumber") == 0)
  1239. {
  1240. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1241. {
  1242. if(values[0] != NULL)
  1243. ((CLdapSecUser*)&user)->setGidnumber(values[0]);
  1244. ldap_value_free( values );
  1245. }
  1246. }
  1247. else if(stricmp(attribute, "uidnumber") == 0)
  1248. {
  1249. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1250. {
  1251. if(values[0] != NULL)
  1252. ((CLdapSecUser*)&user)->setUidnumber(values[0]);
  1253. ldap_value_free( values );
  1254. }
  1255. }
  1256. else if(stricmp(attribute, "homedirectory") == 0)
  1257. {
  1258. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1259. {
  1260. if(values[0] != NULL)
  1261. ((CLdapSecUser*)&user)->setHomedirectory(values[0]);
  1262. ldap_value_free( values );
  1263. }
  1264. }
  1265. else if(stricmp(attribute, "loginshell") == 0)
  1266. {
  1267. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1268. {
  1269. if(values[0] != NULL)
  1270. ((CLdapSecUser*)&user)->setLoginshell(values[0]);
  1271. ldap_value_free( values );
  1272. }
  1273. }
  1274. else if(stricmp(attribute, "objectClass") == 0)
  1275. {
  1276. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  1277. {
  1278. int valind = 0;
  1279. while(values[valind])
  1280. {
  1281. if(values[valind] && stricmp(values[valind], "posixAccount") == 0)
  1282. {
  1283. ((CLdapSecUser*)&user)->setPosixenabled(true);
  1284. break;
  1285. }
  1286. valind++;
  1287. }
  1288. ldap_value_free( values );
  1289. }
  1290. }
  1291. }
  1292. ber_free(ber, 0);
  1293. }
  1294. ldap_msgfree( searchResult );
  1295. return true;
  1296. }
  1297. }
  1298. ISecUser* lookupUser(unsigned uid)
  1299. {
  1300. StringBuffer sysuser;
  1301. sysuser.append(m_ldapconfig->getSysUser());
  1302. if(sysuser.length() == 0)
  1303. {
  1304. #ifdef _WIN32
  1305. char uname[128];
  1306. unsigned long len = 128;
  1307. int rc = GetUserName(uname, &len);
  1308. if(rc != 0)
  1309. sysuser.append(len, uname);
  1310. else
  1311. throw MakeStringException(-1, "Error getting current user's username, error code = %d", rc);
  1312. #else
  1313. throw MakeStringException(-1, "systemUser not found in config");
  1314. #endif
  1315. }
  1316. MemoryBuffer usersidbuf;
  1317. StringBuffer usersidstr;
  1318. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1319. {
  1320. if(m_pp != NULL)
  1321. m_pp->lookupSid(sysuser.str(), usersidbuf);
  1322. if(usersidbuf.length() == 0)
  1323. {
  1324. throw MakeStringException(-1, "system user %s's SID not found", sysuser.str());
  1325. }
  1326. int sidlen = usersidbuf.length();
  1327. char* uidbuf = (char*)&uid;
  1328. for(int i = 0; i < 4; i++)
  1329. {
  1330. usersidbuf.writeDirect(sidlen -4 + i, 1, (uidbuf + 3 - i));
  1331. }
  1332. LdapUtils::bin2str(usersidbuf, usersidstr);
  1333. }
  1334. else
  1335. {
  1336. usersidbuf.append(uid);
  1337. }
  1338. char *attribute, **values;
  1339. BerElement *ber;
  1340. LDAPMessage *searchResult, *message;
  1341. StringBuffer filter;
  1342. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1343. {
  1344. filter.append("objectSid=").append(usersidstr.str());
  1345. }
  1346. else
  1347. {
  1348. filter.appendf("entryid=%d", uid);
  1349. }
  1350. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1351. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1352. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1353. char* act_fieldname;
  1354. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1355. {
  1356. act_fieldname = "sAMAccountName";
  1357. }
  1358. else
  1359. {
  1360. act_fieldname = "uid";
  1361. }
  1362. char *attrs[] = {"cn", act_fieldname, NULL};
  1363. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1364. if ( rc != LDAP_SUCCESS )
  1365. {
  1366. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  1367. return NULL;
  1368. }
  1369. if(ldap_count_entries(ld, searchResult) < 1)
  1370. {
  1371. DBGLOG("No entries are found for user with uid %0X", uid);
  1372. return NULL;
  1373. }
  1374. CLdapSecUser* ldapuser = new CLdapSecUser("", "");
  1375. // Go through the search results by checking message types
  1376. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  1377. {
  1378. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  1379. attribute != NULL;
  1380. attribute = ldap_next_attribute( ld, searchResult,ber))
  1381. {
  1382. if (( values = ldap_get_values( ld, message, attribute))
  1383. != NULL )
  1384. {
  1385. if(values[0] != NULL)
  1386. {
  1387. if(stricmp(attribute, "cn") == 0)
  1388. ldapuser->setFullName(values[0]);
  1389. else if(stricmp(attribute, act_fieldname) == 0)
  1390. ldapuser->setName(values[0]);
  1391. }
  1392. ldap_value_free( values );
  1393. }
  1394. }
  1395. ber_free(ber, 0);
  1396. }
  1397. ldap_msgfree( searchResult );
  1398. ldapuser->setUserID(uid);
  1399. ldapuser->setUserSid(usersidbuf.length(), usersidbuf.toByteArray());
  1400. // Since we've got the SID for the user, cache it for later uses.
  1401. MemoryBuffer mb;
  1402. if(m_pp != NULL)
  1403. m_pp->getCachedSid(ldapuser->getName(), mb);
  1404. if(mb.length() == 0)
  1405. {
  1406. m_pp->cacheSid(ldapuser->getName(), usersidbuf.length(), usersidbuf.toByteArray());
  1407. }
  1408. return ldapuser;
  1409. }
  1410. bool lookupAccount(MemoryBuffer& sidbuf, StringBuffer& account_name, ACT_TYPE& act_type)
  1411. {
  1412. char *attribute, **values;
  1413. BerElement *ber;
  1414. LDAPMessage *searchResult, *message;
  1415. char* act_fieldname;
  1416. StringBuffer filter;
  1417. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1418. {
  1419. act_fieldname = "sAMAccountName";
  1420. StringBuffer usersidstr;
  1421. LdapUtils::bin2str(sidbuf, usersidstr);
  1422. filter.append("objectSid=").append(usersidstr.str());
  1423. }
  1424. else
  1425. {
  1426. unsigned* uid = (unsigned*)sidbuf.toByteArray();
  1427. filter.appendf("entryid=%d", *uid);
  1428. act_fieldname = "uid";
  1429. }
  1430. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1431. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1432. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1433. char *attrs[] = {"cn", act_fieldname, "objectClass", NULL};
  1434. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1435. if ( rc != LDAP_SUCCESS )
  1436. {
  1437. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  1438. return false;
  1439. }
  1440. if(ldap_count_entries(ld, searchResult) < 1)
  1441. {
  1442. rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getGroupBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1443. if(ldap_count_entries(ld, searchResult) < 1)
  1444. {
  1445. rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getSysUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1446. //DBGLOG("No entries are found");
  1447. return false;
  1448. }
  1449. }
  1450. StringBuffer act_name;
  1451. StringBuffer cnbuf;
  1452. // Go through the search results by checking message types
  1453. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  1454. {
  1455. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  1456. attribute != NULL;
  1457. attribute = ldap_next_attribute( ld, searchResult,ber))
  1458. {
  1459. if (( values = ldap_get_values( ld, message, attribute))
  1460. != NULL )
  1461. {
  1462. if(stricmp(attribute, act_fieldname) == 0)
  1463. {
  1464. if(values[0] != NULL)
  1465. {
  1466. act_name.clear().append(values[0]);
  1467. }
  1468. }
  1469. else if(stricmp(attribute, "cn") == 0)
  1470. {
  1471. if(values[0] != NULL)
  1472. {
  1473. cnbuf.clear().append(values[0]);
  1474. }
  1475. }
  1476. else if(stricmp(attribute, "objectClass") == 0)
  1477. {
  1478. int i = 0;
  1479. while(values[i] != NULL)
  1480. {
  1481. if(stricmp(values[i], "person") == 0)
  1482. act_type = USER_ACT;
  1483. if(stricmp(values[i], "group") == 0)
  1484. act_type = GROUP_ACT;
  1485. i++;
  1486. }
  1487. }
  1488. ldap_value_free( values );
  1489. }
  1490. }
  1491. ber_free(ber, 0);
  1492. }
  1493. if(act_type == USER_ACT)
  1494. account_name.append(act_name.str());
  1495. else
  1496. account_name.append(cnbuf.str());
  1497. ldap_msgfree( searchResult );
  1498. return true;
  1499. }
  1500. virtual void lookupSid(const char* basedn, const char* filter, MemoryBuffer& act_sid)
  1501. {
  1502. char *attribute;
  1503. struct berval** bvalues = NULL;
  1504. BerElement *ber;
  1505. LDAPMessage *searchResult, *message;
  1506. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1507. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1508. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1509. char* fieldname;
  1510. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1511. fieldname = "objectSid";
  1512. else
  1513. fieldname = "entryid";
  1514. char *attrs[] = {fieldname, NULL};
  1515. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter, attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1516. if ( rc != LDAP_SUCCESS )
  1517. {
  1518. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter, basedn);
  1519. return;
  1520. }
  1521. message = LdapFirstEntry( ld, searchResult);
  1522. if(searchResult != NULL)
  1523. {
  1524. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  1525. attribute != NULL;
  1526. attribute = ldap_next_attribute( ld, searchResult,ber))
  1527. {
  1528. if(stricmp(attribute, fieldname) != 0)
  1529. continue;
  1530. if (( bvalues = ldap_get_values_len( ld, message, attribute)) != NULL )
  1531. {
  1532. struct berval* val = bvalues[0];
  1533. if(val != NULL)
  1534. {
  1535. int len = val->bv_len;
  1536. act_sid.append(val->bv_len, val->bv_val);
  1537. }
  1538. ldap_value_free_len(bvalues);
  1539. break;
  1540. }
  1541. }
  1542. ber_free(ber, 0);
  1543. ldap_msgfree( searchResult );
  1544. }
  1545. }
  1546. virtual void lookupSid(const char* act_name, MemoryBuffer& act_sid, ACT_TYPE act_type)
  1547. {
  1548. StringBuffer filter;
  1549. const char* basedn;
  1550. if(act_type == USER_ACT)
  1551. {
  1552. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1553. filter.append("sAMAccountName=").append(act_name);
  1554. else
  1555. filter.append("uid=").append(act_name);
  1556. basedn = m_ldapconfig->getUserBasedn();
  1557. lookupSid(basedn, filter.str(), act_sid);
  1558. if(act_sid.length() == 0)
  1559. {
  1560. StringBuffer basebuf;
  1561. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1562. basebuf.append("cn=Users,").append(m_ldapconfig->getBasedn());
  1563. else if(stricmp(act_name, m_ldapconfig->getSysUser()) == 0)
  1564. basebuf.append(m_ldapconfig->getSysUserBasedn());
  1565. else
  1566. basebuf.append("ou=People,").append(m_ldapconfig->getBasedn());
  1567. lookupSid(basebuf.str(), filter.str(), act_sid);
  1568. }
  1569. }
  1570. else
  1571. {
  1572. filter.append("cn=").append(act_name);
  1573. basedn = m_ldapconfig->getGroupBasedn();
  1574. lookupSid(basedn, filter.str(), act_sid);
  1575. if(act_sid.length() == 0)
  1576. {
  1577. StringBuffer basebuf;
  1578. basebuf.append("cn=Users,").append(m_ldapconfig->getBasedn());
  1579. lookupSid(basebuf.str(), filter.str(), act_sid);
  1580. if(act_sid.length() == 0)
  1581. {
  1582. basebuf.clear();
  1583. basebuf.append("cn=Builtin,").append(m_ldapconfig->getBasedn());
  1584. lookupSid(basebuf.str(), filter.str(), act_sid);
  1585. }
  1586. }
  1587. }
  1588. }
  1589. virtual void setPermissionProcessor(IPermissionProcessor* pp)
  1590. {
  1591. m_pp = pp;
  1592. }
  1593. virtual bool retrieveUsers(IUserArray& users)
  1594. {
  1595. return retrieveUsers("", users);
  1596. }
  1597. virtual bool retrieveUsers(const char* searchstr, IUserArray& users)
  1598. {
  1599. char *attribute, **values;
  1600. struct berval** bvalues = NULL;
  1601. BerElement *ber;
  1602. LDAPMessage *searchResult, *message;
  1603. StringBuffer filter;
  1604. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1605. filter.append("objectClass=User");
  1606. else
  1607. filter.append("objectClass=inetorgperson");
  1608. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  1609. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1610. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1611. char* act_fieldname;
  1612. char* sid_fieldname;
  1613. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1614. {
  1615. act_fieldname = "sAMAccountName";
  1616. sid_fieldname = "objectSid";
  1617. }
  1618. else
  1619. {
  1620. act_fieldname = "uid";
  1621. sid_fieldname = "entryid";
  1622. }
  1623. if(searchstr && *searchstr && strcmp(searchstr, "*") != 0)
  1624. {
  1625. filter.insert(0, "(&(");
  1626. filter.appendf(")(|(%s=*%s*)(%s=*%s*)(%s=*%s*)))", act_fieldname, searchstr, "givenName", searchstr, "sn", searchstr);
  1627. }
  1628. char *attrs[] = {act_fieldname, sid_fieldname, "cn", NULL};
  1629. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  1630. if ( rc != LDAP_SUCCESS )
  1631. {
  1632. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  1633. return false;
  1634. }
  1635. // Go through the search results by checking message types
  1636. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  1637. {
  1638. Owned<ISecUser> user = new CLdapSecUser("", "");
  1639. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  1640. attribute != NULL;
  1641. attribute = ldap_next_attribute( ld, searchResult,ber))
  1642. {
  1643. if(stricmp(attribute, "cn") == 0)
  1644. {
  1645. if (( values = ldap_get_values( ld, message, attribute))
  1646. != NULL )
  1647. {
  1648. //set the FullName
  1649. if(values[0] != NULL)
  1650. user->setFullName(values[0]);
  1651. ldap_value_free( values );
  1652. }
  1653. }
  1654. else if(stricmp(attribute, act_fieldname) == 0)
  1655. {
  1656. if (( values = ldap_get_values( ld, message, attribute))
  1657. != NULL )
  1658. {
  1659. //set the FullName
  1660. if(values[0] != NULL)
  1661. user->setName(values[0]);
  1662. ldap_value_free( values );
  1663. }
  1664. }
  1665. else if(stricmp(attribute, sid_fieldname) == 0)
  1666. {
  1667. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1668. {
  1669. if (( bvalues = ldap_get_values_len( ld, message, attribute)) != NULL )
  1670. {
  1671. struct berval* val = bvalues[0];
  1672. if(val != NULL)
  1673. {
  1674. unsigned uid = val->bv_val[val->bv_len - 4];
  1675. int i;
  1676. for(i = 3; i > 0; i--)
  1677. {
  1678. uid = (uid << 8) + val->bv_val[val->bv_len - i];
  1679. }
  1680. ((CLdapSecUser*)user.get())->setUserID(uid);
  1681. }
  1682. ldap_value_free_len(bvalues);
  1683. }
  1684. }
  1685. else
  1686. {
  1687. if (( values = ldap_get_values( ld, message, attribute))
  1688. != NULL )
  1689. {
  1690. //set the FullName
  1691. if(values[0] != NULL)
  1692. ((CLdapSecUser*)user.get())->setUserID(atoi(values[0]));
  1693. ldap_value_free( values );
  1694. }
  1695. }
  1696. }
  1697. }
  1698. ber_free(ber, 0);
  1699. users.append(*LINK(user.get()));
  1700. }
  1701. ldap_msgfree( searchResult );
  1702. return true;
  1703. }
  1704. virtual bool userInGroup(const char* userdn, const char* groupdn)
  1705. {
  1706. const char* fldname;
  1707. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1708. fldname = "member";
  1709. else
  1710. fldname = "uniquemember";
  1711. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1712. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1713. int rc = ldap_compare_s(ld, (char*)groupdn, (char*)fldname, (char*)userdn);
  1714. if(rc == LDAP_COMPARE_TRUE)
  1715. return true;
  1716. else
  1717. return false;
  1718. }
  1719. // Update user's firstname, lastname (plus displayname for active directory).
  1720. virtual bool updateUser(const char* type, ISecUser& user)
  1721. {
  1722. const char* username = user.getName();
  1723. if(!username || !*username)
  1724. return false;
  1725. StringBuffer userdn;
  1726. getUserDN(username, userdn);
  1727. int rc = LDAP_SUCCESS;
  1728. if(!type || !*type || stricmp(type, "names") == 0)
  1729. {
  1730. StringBuffer cnbuf;
  1731. const char* fname = user.getFirstName();
  1732. const char* lname = user.getLastName();
  1733. if(fname && *fname && lname && *lname)
  1734. {
  1735. cnbuf.append(fname).append(" ").append(lname);
  1736. }
  1737. else
  1738. throw MakeStringException(-1, "Please specify both firstname and lastname");
  1739. char *gn_values[] = { (char*)fname, NULL };
  1740. LDAPMod gn_attr = {
  1741. LDAP_MOD_REPLACE,
  1742. "givenName",
  1743. gn_values
  1744. };
  1745. char *sn_values[] = { (char*)lname, NULL };
  1746. LDAPMod sn_attr = {
  1747. LDAP_MOD_REPLACE,
  1748. "sn",
  1749. sn_values
  1750. };
  1751. char *cn_values[] = {(char*)cnbuf.str(), NULL };
  1752. LDAPMod cn_attr =
  1753. {
  1754. LDAP_MOD_REPLACE,
  1755. "cn",
  1756. cn_values
  1757. };
  1758. char *dispname_values[] = {(char*)cnbuf.str(), NULL };
  1759. LDAPMod dispname_attr =
  1760. {
  1761. LDAP_MOD_REPLACE,
  1762. "displayName",
  1763. dispname_values
  1764. };
  1765. LDAPMod *attrs[4];
  1766. int ind = 0;
  1767. attrs[ind++] = &gn_attr;
  1768. attrs[ind++] = &sn_attr;
  1769. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1770. {
  1771. attrs[ind++] = &dispname_attr;
  1772. }
  1773. else
  1774. {
  1775. attrs[ind++] = &cn_attr;
  1776. }
  1777. attrs[ind] = NULL;
  1778. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1779. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1780. rc = ldap_modify_s(ld, (char*)userdn.str(), attrs);
  1781. if (rc == LDAP_SUCCESS && m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1782. {
  1783. StringBuffer newrdn("cn=");
  1784. newrdn.append(cnbuf.str());
  1785. rc = LdapRename(ld, (char*)userdn.str(), (char*)newrdn.str(), NULL, true, NULL, NULL);
  1786. }
  1787. }
  1788. else if(stricmp(type, "posixenable") == 0)
  1789. {
  1790. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1791. throw MakeStringException(-1, "posixAccount isn't applicable to Active Directory");
  1792. CLdapSecUser* ldapuser = dynamic_cast<CLdapSecUser*>(&user);
  1793. char* oc_values[] = {"posixAccount", NULL};
  1794. LDAPMod oc_attr = {
  1795. LDAP_MOD_ADD,
  1796. "objectclass",
  1797. oc_values
  1798. };
  1799. char* oc1_values[] = {"shadowAccount", NULL};
  1800. LDAPMod oc1_attr = {
  1801. LDAP_MOD_ADD,
  1802. "objectclass",
  1803. oc1_values
  1804. };
  1805. char *gidnum_values[] = { (char*)ldapuser->getGidnumber(), NULL };
  1806. LDAPMod gidnum_attr = {
  1807. LDAP_MOD_REPLACE,
  1808. "gidnumber",
  1809. gidnum_values
  1810. };
  1811. char *uidnum_values[] = { (char*)ldapuser->getUidnumber(), NULL };
  1812. LDAPMod uidnum_attr = {
  1813. LDAP_MOD_REPLACE,
  1814. "uidnumber",
  1815. uidnum_values
  1816. };
  1817. char *homedir_values[] = {(char*)ldapuser->getHomedirectory(), NULL };
  1818. LDAPMod homedir_attr =
  1819. {
  1820. LDAP_MOD_REPLACE,
  1821. "homedirectory",
  1822. homedir_values
  1823. };
  1824. char *loginshell_values[] = {(char*)ldapuser->getLoginshell(), NULL };
  1825. LDAPMod loginshell_attr =
  1826. {
  1827. LDAP_MOD_REPLACE,
  1828. "loginshell",
  1829. loginshell_values
  1830. };
  1831. LDAPMod *attrs[7];
  1832. int ind = 0;
  1833. attrs[ind++] = &gidnum_attr;
  1834. attrs[ind++] = &uidnum_attr;
  1835. attrs[ind++] = &homedir_attr;
  1836. attrs[ind++] = &loginshell_attr;
  1837. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1838. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1839. int compresult = ldap_compare_s(ld, (char*)userdn.str(), (char*)"objectclass", (char*)"posixAccount");
  1840. if(compresult != LDAP_COMPARE_TRUE)
  1841. attrs[ind++] = &oc_attr;
  1842. compresult = ldap_compare_s(ld, (char*)userdn.str(), (char*)"objectclass", (char*)"shadowAccount");
  1843. if(compresult != LDAP_COMPARE_TRUE)
  1844. attrs[ind++] = &oc1_attr;
  1845. attrs[ind] = NULL;
  1846. rc = ldap_modify_s(ld, (char*)userdn.str(), attrs);
  1847. }
  1848. else if(stricmp(type, "posixdisable") == 0)
  1849. {
  1850. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  1851. throw MakeStringException(-1, "posixAccount isn't applicable to Active Directory");
  1852. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1853. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1854. int compresult = ldap_compare_s(ld, (char*)userdn.str(), (char*)"objectclass", (char*)"posixAccount");
  1855. if(compresult != LDAP_COMPARE_TRUE)
  1856. {
  1857. rc = LDAP_SUCCESS;
  1858. }
  1859. else
  1860. {
  1861. CLdapSecUser* ldapuser = dynamic_cast<CLdapSecUser*>(&user);
  1862. char* oc_values[] = {"posixAccount", NULL};
  1863. LDAPMod oc_attr = {
  1864. LDAP_MOD_DELETE,
  1865. "objectclass",
  1866. oc_values
  1867. };
  1868. char* oc1_values[] = {"shadowAccount", NULL};
  1869. LDAPMod oc1_attr = {
  1870. LDAP_MOD_DELETE,
  1871. "objectclass",
  1872. oc1_values
  1873. };
  1874. char *gidnum_values[] = { NULL };
  1875. LDAPMod gidnum_attr = {
  1876. LDAP_MOD_DELETE,
  1877. "gidnumber",
  1878. gidnum_values
  1879. };
  1880. char *uidnum_values[] = {NULL };
  1881. LDAPMod uidnum_attr = {
  1882. LDAP_MOD_DELETE,
  1883. "uidnumber",
  1884. uidnum_values
  1885. };
  1886. char *homedir_values[] = { NULL };
  1887. LDAPMod homedir_attr =
  1888. {
  1889. LDAP_MOD_DELETE,
  1890. "homedirectory",
  1891. homedir_values
  1892. };
  1893. char *loginshell_values[] = { NULL };
  1894. LDAPMod loginshell_attr =
  1895. {
  1896. LDAP_MOD_DELETE,
  1897. "loginshell",
  1898. loginshell_values
  1899. };
  1900. LDAPMod *attrs[7];
  1901. int ind = 0;
  1902. attrs[ind++] = &gidnum_attr;
  1903. attrs[ind++] = &uidnum_attr;
  1904. attrs[ind++] = &homedir_attr;
  1905. attrs[ind++] = &loginshell_attr;
  1906. attrs[ind++] = &oc_attr;
  1907. attrs[ind++] = &oc1_attr;
  1908. attrs[ind] = NULL;
  1909. rc = ldap_modify_s(ld, (char*)userdn.str(), attrs);
  1910. }
  1911. }
  1912. else if(stricmp(type, "sudoersadd") == 0)
  1913. {
  1914. CLdapSecUser* ldapuser = dynamic_cast<CLdapSecUser*>(&user);
  1915. char *cn_values[] = {(char*)username, NULL };
  1916. LDAPMod cn_attr =
  1917. {
  1918. LDAP_MOD_ADD,
  1919. "cn",
  1920. cn_values
  1921. };
  1922. char *oc_values[] = {"sudoRole", NULL };
  1923. LDAPMod oc_attr =
  1924. {
  1925. LDAP_MOD_ADD,
  1926. "objectClass",
  1927. oc_values
  1928. };
  1929. char *user_values[] = {(char*)username, NULL };
  1930. LDAPMod user_attr =
  1931. {
  1932. LDAP_MOD_ADD,
  1933. "sudoUser",
  1934. user_values
  1935. };
  1936. char* sudoHost = (char*)ldapuser->getSudoHost();
  1937. char* sudoCommand = (char*)ldapuser->getSudoCommand();
  1938. char* sudoOption = (char*)ldapuser->getSudoOption();
  1939. char *host_values[] = {sudoHost, NULL };
  1940. LDAPMod host_attr =
  1941. {
  1942. LDAP_MOD_ADD,
  1943. "sudoHost",
  1944. host_values
  1945. };
  1946. char *cmd_values[] = {sudoCommand, NULL };
  1947. LDAPMod cmd_attr =
  1948. {
  1949. LDAP_MOD_ADD,
  1950. "sudoCommand",
  1951. cmd_values
  1952. };
  1953. char *option_values[] = {sudoOption, NULL };
  1954. LDAPMod option_attr =
  1955. {
  1956. LDAP_MOD_ADD,
  1957. "sudoOption",
  1958. option_values
  1959. };
  1960. LDAPMod *attrs[8];
  1961. int ind = 0;
  1962. attrs[ind++] = &cn_attr;
  1963. attrs[ind++] = &oc_attr;
  1964. attrs[ind++] = &user_attr;
  1965. if(sudoHost && *sudoHost)
  1966. attrs[ind++] = &host_attr;
  1967. if(sudoCommand && *sudoCommand)
  1968. attrs[ind++] = &cmd_attr;
  1969. if(sudoOption && *sudoOption)
  1970. attrs[ind++] = &option_attr;
  1971. attrs[ind] = NULL;
  1972. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1973. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1974. StringBuffer dn;
  1975. dn.append("cn=").append(username).append(",").append(m_ldapconfig->getResourceBasedn(RT_SUDOERS));
  1976. int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  1977. if ( rc != LDAP_SUCCESS )
  1978. {
  1979. if(rc == LDAP_ALREADY_EXISTS)
  1980. {
  1981. throw MakeStringException(-1, "can't add %s to sudoers, already exists", username);
  1982. }
  1983. else
  1984. {
  1985. DBGLOG("error adding %s to sudoers: %s", username, ldap_err2string( rc ));
  1986. throw MakeStringException(-1, "error adding %s to sudoers: %s", username, ldap_err2string( rc ));
  1987. }
  1988. }
  1989. }
  1990. else if(stricmp(type, "sudoersdelete") == 0)
  1991. {
  1992. StringBuffer dn;
  1993. dn.append("cn=").append(username).append(",").append(m_ldapconfig->getResourceBasedn(RT_SUDOERS));
  1994. Owned<ILdapConnection> lconn = m_connections->getConnection();
  1995. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  1996. int rc = ldap_delete_s(ld, (char*)dn.str());
  1997. if ( rc != LDAP_SUCCESS )
  1998. {
  1999. throw MakeStringException(-1, "Error deleting user %s from sudoers: %s", username, ldap_err2string(rc));
  2000. }
  2001. }
  2002. else if(stricmp(type, "sudoersupdate") == 0)
  2003. {
  2004. CLdapSecUser* ldapuser = dynamic_cast<CLdapSecUser*>(&user);
  2005. char* sudoHost = (char*)ldapuser->getSudoHost();
  2006. char* sudoCommand = (char*)ldapuser->getSudoCommand();
  2007. char* sudoOption = (char*)ldapuser->getSudoOption();
  2008. char *host_values[] = {(sudoHost&&*sudoHost)?sudoHost:NULL, NULL };
  2009. LDAPMod host_attr =
  2010. {
  2011. LDAP_MOD_REPLACE,
  2012. "sudoHost",
  2013. host_values
  2014. };
  2015. char *cmd_values[] = {(sudoCommand&&*sudoCommand)?sudoCommand:NULL, NULL };
  2016. LDAPMod cmd_attr =
  2017. {
  2018. LDAP_MOD_REPLACE,
  2019. "sudoCommand",
  2020. cmd_values
  2021. };
  2022. char *option_values[] = {(sudoOption&&*sudoOption)?sudoOption:NULL, NULL };
  2023. LDAPMod option_attr =
  2024. {
  2025. LDAP_MOD_REPLACE,
  2026. "sudoOption",
  2027. option_values
  2028. };
  2029. LDAPMod *attrs[4];
  2030. int ind = 0;
  2031. attrs[ind++] = &host_attr;
  2032. attrs[ind++] = &cmd_attr;
  2033. attrs[ind++] = &option_attr;
  2034. attrs[ind] = NULL;
  2035. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2036. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2037. StringBuffer dn;
  2038. dn.append("cn=").append(username).append(",").append(m_ldapconfig->getResourceBasedn(RT_SUDOERS));
  2039. int rc = ldap_modify_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  2040. if ( rc != LDAP_SUCCESS )
  2041. {
  2042. DBGLOG("error modifying sudoers for user %s: %s", username, ldap_err2string( rc ));
  2043. throw MakeStringException(-1, "error modifying sudoers for user %s: %s", username, ldap_err2string( rc ));
  2044. }
  2045. }
  2046. if (rc == LDAP_SUCCESS )
  2047. DBGLOG("User %s successfully updated", username);
  2048. else
  2049. throw MakeStringException(-1, "Error updating user %s - %s", username, ldap_err2string( rc ));
  2050. return true;
  2051. }
  2052. virtual bool changePasswordSSL(const char* username, const char* newPassword)
  2053. {
  2054. Owned<ILdapConnection> lconn;
  2055. try
  2056. {
  2057. lconn.setown(m_connections->getSSLConnection());
  2058. }
  2059. catch(IException*)
  2060. {
  2061. throw MakeStringException(-1, "Failed to set user %s's password because of not being able to create an SSL conenction to the ldap server. To set an Active Directory user's password from Linux, you need to enable SSL on the Active Directory ldap server", username);
  2062. }
  2063. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2064. char *attribute, **values = NULL;
  2065. BerElement *ber;
  2066. LDAPMessage *searchResult, *message;
  2067. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2068. StringBuffer filter;
  2069. filter.append("sAMAccountName=").append(username);
  2070. char *attrs[] = {"cn", NULL};
  2071. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2072. if ( rc != LDAP_SUCCESS )
  2073. {
  2074. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  2075. return false;
  2076. }
  2077. StringBuffer userdn;
  2078. message = LdapFirstEntry( ld, searchResult);
  2079. if(searchResult != NULL)
  2080. {
  2081. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2082. attribute != NULL;
  2083. attribute = ldap_next_attribute( ld, searchResult,ber))
  2084. {
  2085. if(stricmp(attribute, "cn") != 0)
  2086. continue;
  2087. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  2088. {
  2089. char* val = values[0];
  2090. userdn.append("cn=").append(val).append(",").append(m_ldapconfig->getUserBasedn());
  2091. ldap_value_free( values );
  2092. break;
  2093. }
  2094. }
  2095. ber_free(ber, 0);
  2096. ldap_msgfree( searchResult );
  2097. }
  2098. if(userdn.length() == 0)
  2099. {
  2100. throw MakeStringException(-1, "can't find dn for user %s", username);
  2101. }
  2102. LDAPMod modPassword;
  2103. LDAPMod *modEntry[2];
  2104. struct berval pwdBerVal;
  2105. struct berval *pwd_attr[2];
  2106. unsigned short pszPasswordWithQuotes[1024];
  2107. modEntry[0] = &modPassword;
  2108. modEntry[1] = NULL;
  2109. modPassword.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  2110. modPassword.mod_type = "unicodePwd";
  2111. modPassword.mod_vals.modv_bvals = pwd_attr;
  2112. pwd_attr[0] = &pwdBerVal;
  2113. pwd_attr[1]= NULL;
  2114. StringBuffer quotedPasswd("\"");
  2115. quotedPasswd.append(newPassword).append("\"");
  2116. ConvertCToW(pszPasswordWithQuotes, quotedPasswd);
  2117. pwdBerVal.bv_len = quotedPasswd.length() * sizeof(unsigned short);
  2118. pwdBerVal.bv_val = (char*)pszPasswordWithQuotes;
  2119. rc = ldap_modify_s(ld, (char*)userdn.str(), modEntry);
  2120. if (rc == LDAP_SUCCESS )
  2121. DBGLOG("User %s's password has been changed successfully", username);
  2122. else
  2123. {
  2124. StringBuffer errmsg;
  2125. errmsg.appendf("Error setting password for %s - (%d) %s.", username, rc, ldap_err2string( rc ));
  2126. if(rc == LDAP_UNWILLING_TO_PERFORM)
  2127. errmsg.append(" The ldap server refused to execute the password change action, one of the reasons might be that the new password you entered doesn't satisfy the policy requirement.");
  2128. throw MakeStringException(-1, "%s", errmsg.str());
  2129. }
  2130. return true;
  2131. }
  2132. virtual bool updateUser(ISecUser& user, const char* newPassword)
  2133. {
  2134. const char* username = user.getName();
  2135. if(!username || !*username)
  2136. return false;
  2137. return updateUser(username, newPassword);
  2138. }
  2139. virtual bool updateUser(const char* username, const char* newPassword)
  2140. {
  2141. if(!username || !*username)
  2142. return false;
  2143. const char* sysuser = m_ldapconfig->getSysUser();
  2144. if(sysuser && *sysuser && strcmp(username, sysuser) == 0)
  2145. throw MakeStringException(-1, "You can't change password of the system user.");
  2146. LdapServerType servertype = m_ldapconfig->getServerType();
  2147. bool ret = true;
  2148. if(servertype == ACTIVE_DIRECTORY)
  2149. {
  2150. #ifdef _WIN32
  2151. DWORD nStatus = 0;
  2152. // The application has to run on the same domain as ldap host, and under an administrative user.
  2153. USER_INFO_1003 usriSetPassword;
  2154. StringBuffer fullserver("\\\\");
  2155. StringBuffer server;
  2156. m_ldapconfig->getLdapHost(server);
  2157. fullserver.append(server.str());
  2158. LPWSTR whost = (LPWSTR)alloca((fullserver.length() +1) * sizeof(WCHAR));
  2159. ConvertCToW(whost, fullserver.str());
  2160. LPWSTR wusername = (LPWSTR)alloca((strlen(username) + 1) * sizeof(WCHAR));
  2161. ConvertCToW(wusername, username);
  2162. LPWSTR wnewpasswd = (LPWSTR)alloca((strlen(newPassword) + 1) * sizeof(WCHAR));
  2163. ConvertCToW(wnewpasswd, newPassword);
  2164. usriSetPassword.usri1003_password = wnewpasswd;
  2165. nStatus = NetUserSetInfo(whost, wusername, 1003, (LPBYTE)&usriSetPassword, NULL);
  2166. if (nStatus == NERR_Success)
  2167. {
  2168. DBGLOG("User %s's password has been changed successfully", username);
  2169. return true;
  2170. }
  2171. else
  2172. {
  2173. StringBuffer errcode, errmsg;
  2174. if(nStatus == ERROR_ACCESS_DENIED)
  2175. {
  2176. errcode.append("ERROR_ACCESS_DENIED");
  2177. errmsg.append("The user does not have access to the requested information.");
  2178. }
  2179. else if(nStatus == ERROR_INVALID_PASSWORD)
  2180. {
  2181. errcode.append("ERROR_INVALID_PASSWORD");
  2182. errmsg.append("The user has entered an invalid password.");
  2183. }
  2184. else if(nStatus == NERR_InvalidComputer)
  2185. {
  2186. errcode.append("NERR_InvalidComputer");
  2187. errmsg.append("The computer name is invalid.");
  2188. }
  2189. else if(nStatus == NERR_NotPrimary)
  2190. {
  2191. errcode.append("NERR_NotPrimary");
  2192. errmsg.append("The operation is allowed only on the primary domain controller of the domain.");
  2193. }
  2194. else if(nStatus == NERR_UserNotFound)
  2195. {
  2196. errcode.append("NERR_UserNotFound");
  2197. errmsg.append("The user name could not be found.");
  2198. }
  2199. else if(nStatus == NERR_PasswordTooShort)
  2200. {
  2201. errcode.append("NERR_PasswordTooShort");
  2202. errmsg.append("The password is shorter than required. ");
  2203. }
  2204. else if(nStatus == ERROR_LOGON_FAILURE)
  2205. {
  2206. errcode.append("ERROR_LOGON_FAILURE");
  2207. errmsg.append("To be able to reset password this way, esp has to run under an administrative user on the same domain as the active directory. ");
  2208. }
  2209. else
  2210. {
  2211. errcode.appendf("%d", nStatus);
  2212. errmsg.append("");
  2213. }
  2214. // For certain errors just return, other errors try changePasswordSSL.
  2215. if(nStatus == ERROR_INVALID_PASSWORD || nStatus == NERR_UserNotFound || nStatus == NERR_PasswordTooShort)
  2216. throw MakeStringException(-1, "An error has occurred while setting password with NetUserSetInfo for %s: %s - %s\n", username, errcode.str(), errmsg.str());
  2217. else
  2218. DBGLOG("An error has occurred while setting password with NetUserSetInfo for %s: %s - %s\n", username, errcode.str(), errmsg.str());
  2219. }
  2220. DBGLOG("Trying changePasswordSSL to change password over regular SSL connection.");
  2221. #endif
  2222. changePasswordSSL(username, newPassword);
  2223. }
  2224. else
  2225. {
  2226. StringBuffer filter;
  2227. filter.append("uid=").append(username);
  2228. char **values = NULL;
  2229. LDAPMessage *searchResult, *message;
  2230. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2231. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2232. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2233. char *attrs[] = {LDAP_NO_ATTRS, NULL};
  2234. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2235. if ( rc != LDAP_SUCCESS )
  2236. {
  2237. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  2238. return false;
  2239. }
  2240. StringBuffer userdn;
  2241. message = LdapFirstEntry( ld, searchResult);
  2242. if(message != NULL)
  2243. userdn.append(ldap_get_dn(ld, message));
  2244. ldap_msgfree( searchResult );
  2245. char* passwdvalue[] = { (char*)newPassword, NULL };
  2246. LDAPMod pmod =
  2247. {
  2248. LDAP_MOD_REPLACE,
  2249. "userpassword",
  2250. passwdvalue
  2251. };
  2252. LDAPMod* pmods[] = {&pmod, NULL};
  2253. rc = ldap_modify_s(ld, (char*)userdn.str(), pmods);
  2254. if (rc == LDAP_SUCCESS )
  2255. DBGLOG("User %s's password has been changed successfully", username);
  2256. else
  2257. {
  2258. StringBuffer errmsg;
  2259. errmsg.appendf("Error changing password for %s - (%d) %s.", username, rc, ldap_err2string( rc ));
  2260. if(rc == LDAP_UNWILLING_TO_PERFORM)
  2261. errmsg.append(" The ldap server refused to execute the password change action, one of the reasons might be that the new password you entered doesn't satisfy the policy requirement.");
  2262. throw MakeStringException(-1, "%s", errmsg.str());
  2263. }
  2264. }
  2265. return true;
  2266. }
  2267. virtual bool getResources(SecResourceType rtype, const char * basedn, const char* prefix, IArrayOf<ISecResource>& resources)
  2268. {
  2269. char *attribute, **values;
  2270. struct berval** bvalues = NULL;
  2271. BerElement *ber;
  2272. LDAPMessage *searchResult, *message;
  2273. StringBuffer basednbuf;
  2274. LdapUtils::normalizeDn(basedn, m_ldapconfig->getBasedn(), basednbuf);
  2275. StringBuffer filter("objectClass=*");
  2276. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2277. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2278. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2279. const char* fldname;
  2280. LdapServerType servertype = m_ldapconfig->getServerType();
  2281. if(servertype == ACTIVE_DIRECTORY && (rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE))
  2282. fldname = "name";
  2283. else
  2284. fldname = "ou";
  2285. char *attrs[] = {(char*)fldname, "description", NULL};
  2286. int rc = ldap_search_ext_s(ld, (char*)basednbuf.str(), LDAP_SCOPE_ONELEVEL, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2287. if ( rc != LDAP_SUCCESS )
  2288. {
  2289. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basednbuf.str());
  2290. return false;
  2291. }
  2292. // Go through the search results by checking message types
  2293. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  2294. {
  2295. StringBuffer descbuf;
  2296. StringBuffer curname;
  2297. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2298. attribute != NULL;
  2299. attribute = ldap_next_attribute( ld, searchResult,ber))
  2300. {
  2301. if (( values = ldap_get_values( ld, message, attribute))
  2302. != NULL )
  2303. {
  2304. char* val = values[0];
  2305. if(val != NULL)
  2306. {
  2307. if(stricmp(attribute, fldname) == 0)
  2308. {
  2309. curname.append(val);
  2310. }
  2311. else if(stricmp(attribute, "description") == 0)
  2312. {
  2313. descbuf.append(val);
  2314. }
  2315. }
  2316. ldap_value_free( values );
  2317. }
  2318. }
  2319. if(curname.length() == 0)
  2320. continue;
  2321. StringBuffer resourcename;
  2322. if(prefix != NULL && *prefix != '\0')
  2323. resourcename.append(prefix);
  2324. resourcename.append(curname.str());
  2325. CLdapSecResource* resource = new CLdapSecResource(resourcename.str());
  2326. resource->setDescription(descbuf.str());
  2327. resources.append(*resource);
  2328. if(rtype == RT_FILE_SCOPE || rtype == RT_WORKUNIT_SCOPE)
  2329. {
  2330. StringBuffer nextbasedn;
  2331. nextbasedn.append("ou=").append(curname.str()).append(",").append(basedn);
  2332. StringBuffer nextprefix;
  2333. if(prefix != NULL && *prefix != '\0')
  2334. nextprefix.append(prefix);
  2335. nextprefix.append(curname.str()).append("::");
  2336. getResources(rtype, nextbasedn.str(), nextprefix.str(), resources);
  2337. }
  2338. ber_free(ber, 0);
  2339. }
  2340. ldap_msgfree( searchResult );
  2341. return true;
  2342. }
  2343. virtual bool getResourcesEx(SecResourceType rtype, const char * basedn, const char* prefix, const char* searchstr, IArrayOf<ISecResource>& resources)
  2344. {
  2345. char *attribute, **values;
  2346. struct berval** bvalues = NULL;
  2347. BerElement *ber;
  2348. LDAPMessage *searchResult, *message;
  2349. StringBuffer basednbuf;
  2350. LdapUtils::normalizeDn(basedn, m_ldapconfig->getBasedn(), basednbuf);
  2351. StringBuffer filter("objectClass=*");
  2352. if(searchstr && *searchstr && strcmp(searchstr, "*") != 0)
  2353. {
  2354. filter.insert(0, "(&(");
  2355. filter.appendf(")(|(%s=*%s*)))", "uNCName", searchstr);
  2356. }
  2357. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2358. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2359. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2360. const char* fldname;
  2361. LdapServerType servertype = m_ldapconfig->getServerType();
  2362. if(servertype == ACTIVE_DIRECTORY && (rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE))
  2363. fldname = "name";
  2364. else
  2365. fldname = "ou";
  2366. char *attrs[] = {(char*)fldname, "description", NULL};
  2367. int rc = ldap_search_ext_s(ld, (char*)basednbuf.str(), LDAP_SCOPE_ONELEVEL, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2368. if ( rc != LDAP_SUCCESS )
  2369. {
  2370. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basednbuf.str());
  2371. return false;
  2372. }
  2373. // Go through the search results by checking message types
  2374. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  2375. {
  2376. StringBuffer descbuf;
  2377. StringBuffer curname;
  2378. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2379. attribute != NULL;
  2380. attribute = ldap_next_attribute( ld, searchResult,ber))
  2381. {
  2382. if (( values = ldap_get_values( ld, message, attribute))
  2383. != NULL )
  2384. {
  2385. char* val = values[0];
  2386. if(val != NULL)
  2387. {
  2388. if(stricmp(attribute, fldname) == 0)
  2389. {
  2390. curname.append(val);
  2391. }
  2392. else if(stricmp(attribute, "description") == 0)
  2393. {
  2394. descbuf.append(val);
  2395. }
  2396. }
  2397. ldap_value_free( values );
  2398. }
  2399. }
  2400. if(curname.length() == 0)
  2401. continue;
  2402. StringBuffer resourcename;
  2403. if(prefix != NULL && *prefix != '\0')
  2404. resourcename.append(prefix);
  2405. resourcename.append(curname.str());
  2406. CLdapSecResource* resource = new CLdapSecResource(resourcename.str());
  2407. resource->setDescription(descbuf.str());
  2408. resources.append(*resource);
  2409. if(rtype == RT_FILE_SCOPE || rtype == RT_WORKUNIT_SCOPE)
  2410. {
  2411. StringBuffer nextbasedn;
  2412. nextbasedn.append("ou=").append(curname.str()).append(",").append(basedn);
  2413. StringBuffer nextprefix;
  2414. if(prefix != NULL && *prefix != '\0')
  2415. nextprefix.append(prefix);
  2416. nextprefix.append(curname.str()).append("::");
  2417. getResources(rtype, nextbasedn.str(), nextprefix.str(), resources);
  2418. }
  2419. ber_free(ber, 0);
  2420. }
  2421. ldap_msgfree( searchResult );
  2422. return true;
  2423. }
  2424. virtual bool getPermissionsArray(const char* basedn, SecResourceType rtype, const char* name, IArrayOf<CPermission>& permissions)
  2425. {
  2426. StringBuffer basednbuf;
  2427. LdapUtils::normalizeDn(basedn, m_ldapconfig->getBasedn(), basednbuf);
  2428. Owned<CSecurityDescriptor> sd = new CSecurityDescriptor(name);
  2429. IArrayOf<CSecurityDescriptor> sdlist;
  2430. sdlist.append(*LINK(sd));
  2431. if(rtype == RT_FILE_SCOPE || rtype == RT_WORKUNIT_SCOPE)
  2432. getSecurityDescriptorsScope(sdlist, basednbuf.str());
  2433. else
  2434. getSecurityDescriptors(sdlist, basednbuf.str());
  2435. m_pp->getPermissionsArray(sd.get(), permissions);
  2436. return true;
  2437. }
  2438. virtual void getAllGroups(StringArray & groups)
  2439. {
  2440. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2441. {
  2442. groups.append("Authenticated Users");
  2443. groups.append("Administrators");
  2444. }
  2445. else
  2446. {
  2447. groups.append("Directory Administrators");
  2448. }
  2449. char *attribute, **values;
  2450. struct berval** bvalues = NULL;
  2451. BerElement *ber;
  2452. LDAPMessage *searchResult, *message;
  2453. StringBuffer filter;
  2454. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2455. filter.append("objectClass=group");
  2456. else
  2457. filter.append("objectClass=groupofuniquenames");
  2458. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2459. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2460. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2461. char *attrs[] = {"cn", NULL};
  2462. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getGroupBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2463. if ( rc != LDAP_SUCCESS )
  2464. {
  2465. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getGroupBasedn());
  2466. return;
  2467. }
  2468. // Go through the search results by checking message types
  2469. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  2470. {
  2471. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2472. attribute != NULL;
  2473. attribute = ldap_next_attribute( ld, searchResult,ber))
  2474. {
  2475. if(stricmp(attribute, "cn") == 0)
  2476. {
  2477. if (( values = ldap_get_values( ld, message, attribute))
  2478. != NULL )
  2479. {
  2480. //set the FullName
  2481. if(values[0] != NULL)
  2482. groups.append(values[0]);
  2483. ldap_value_free( values );
  2484. }
  2485. }
  2486. }
  2487. }
  2488. ldap_msgfree( searchResult );
  2489. }
  2490. virtual bool changePermission(CPermissionAction& action)
  2491. {
  2492. StringBuffer basednbuf;
  2493. LdapUtils::normalizeDn(action.m_basedn.str(), m_ldapconfig->getBasedn(), basednbuf);
  2494. Owned<CSecurityDescriptor> sd = new CSecurityDescriptor(action.m_rname.str());
  2495. IArrayOf<CSecurityDescriptor> sdlist;
  2496. sdlist.append(*LINK(sd));
  2497. if(action.m_rtype == RT_FILE_SCOPE || action.m_rtype == RT_WORKUNIT_SCOPE)
  2498. getSecurityDescriptorsScope(sdlist, basednbuf.str());
  2499. else
  2500. getSecurityDescriptors(sdlist, basednbuf.str());
  2501. if(m_ldapconfig->getServerType() != ACTIVE_DIRECTORY)
  2502. {
  2503. StringBuffer act_dn;
  2504. if(action.m_account_type == GROUP_ACT)
  2505. getGroupDN(action.m_account_name.str(), act_dn);
  2506. else
  2507. getUserDN(action.m_account_name.str(), act_dn);
  2508. action.m_account_name.clear().append(act_dn.str());
  2509. }
  2510. Owned<CSecurityDescriptor> newsd = m_pp->changePermission(sd.get(), action);
  2511. StringBuffer normdnbuf;
  2512. LdapServerType servertype = m_ldapconfig->getServerType();
  2513. name2dn(action.m_rtype, action.m_rname.str(), action.m_basedn.str(), normdnbuf);
  2514. char *empty_values[] = { NULL };
  2515. int numberOfSegs = m_pp->sdSegments(newsd.get());
  2516. LDAPMod *attrs[2];
  2517. LDAPMod sd_attr;
  2518. if(newsd->getDescriptor().length() > 0)
  2519. {
  2520. struct berval** sd_values = (struct berval**)alloca(sizeof(struct berval*)*(numberOfSegs+1));
  2521. MemoryBuffer& sdbuf = newsd->getDescriptor();
  2522. // Active Directory acutally has only one segment.
  2523. if(servertype == ACTIVE_DIRECTORY)
  2524. {
  2525. struct berval* sd_val = (struct berval*)alloca(sizeof(struct berval));
  2526. sd_val->bv_len = sdbuf.length();
  2527. sd_val->bv_val = (char*)sdbuf.toByteArray();
  2528. sd_values[0] = sd_val;
  2529. sd_values[1] = NULL;
  2530. sd_attr.mod_type = "nTSecurityDescriptor";
  2531. }
  2532. else
  2533. {
  2534. const char* bbptr = sdbuf.toByteArray();
  2535. const char* bptr = sdbuf.toByteArray();
  2536. int sdbuflen = sdbuf.length();
  2537. int segind;
  2538. for(segind = 0; segind < numberOfSegs; segind++)
  2539. {
  2540. if(bptr - bbptr >= sdbuflen)
  2541. break;
  2542. while(*bptr == '\0' && (bptr - bbptr) < sdbuflen)
  2543. bptr++;
  2544. const char* eptr = bptr;
  2545. while(*eptr != '\0' && (eptr - bbptr) < sdbuflen)
  2546. eptr++;
  2547. struct berval* sd_val = (struct berval*)alloca(sizeof(struct berval));
  2548. sd_val->bv_len = eptr - bptr;
  2549. sd_val->bv_val = (char*)bptr;
  2550. sd_values[segind] = sd_val;
  2551. bptr = eptr + 1;
  2552. }
  2553. sd_values[segind] = NULL;
  2554. sd_attr.mod_type = (char*)m_ldapconfig->getSdFieldName();
  2555. }
  2556. sd_attr.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  2557. sd_attr.mod_vals.modv_bvals = sd_values;
  2558. attrs[0] = &sd_attr;
  2559. }
  2560. else
  2561. {
  2562. if(m_ldapconfig->getServerType() == OPEN_LDAP)
  2563. throw MakeStringException(-1, "removing all permissions for openldap is currently not supported");
  2564. sd_attr.mod_op = LDAP_MOD_DELETE;
  2565. sd_attr.mod_type = (char*)m_ldapconfig->getSdFieldName();
  2566. sd_attr.mod_vals.modv_strvals = empty_values;
  2567. attrs[0] = &sd_attr;
  2568. }
  2569. attrs[1] = NULL;
  2570. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2571. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2572. int rc = ldap_modify_s(ld, (char*)normdnbuf.str(), attrs);
  2573. if ( rc != LDAP_SUCCESS )
  2574. {
  2575. throw MakeStringException(-1, "ldap_modify_s error: %d %s", rc, ldap_err2string( rc ));
  2576. }
  2577. return true;
  2578. }
  2579. virtual void getGroups(const char *user, StringArray& groups)
  2580. {
  2581. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2582. {
  2583. char *attribute, **values;
  2584. BerElement *ber;
  2585. LDAPMessage *searchResult, *message;
  2586. if(user == NULL || strlen(user) == 0)
  2587. return;
  2588. StringBuffer filter("sAMAccountName=");
  2589. filter.append(user);
  2590. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2591. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2592. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2593. char *attrs[] = {"memberOf", NULL};
  2594. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2595. if ( rc != LDAP_SUCCESS )
  2596. {
  2597. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  2598. return;
  2599. }
  2600. unsigned entries = ldap_count_entries(ld, searchResult);
  2601. if(entries == 0)
  2602. {
  2603. rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getSysUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2604. if ( rc != LDAP_SUCCESS )
  2605. {
  2606. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getSysUserBasedn());
  2607. return;
  2608. }
  2609. }
  2610. // Go through the search results by checking message types
  2611. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  2612. {
  2613. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2614. attribute != NULL;
  2615. attribute = ldap_next_attribute( ld, searchResult,ber))
  2616. {
  2617. if(stricmp(attribute, "memberOf") != 0)
  2618. continue;
  2619. if (( values = ldap_get_values( ld, message, attribute))
  2620. != NULL )
  2621. {
  2622. for (int i = 0; values[ i ] != NULL; i++ )
  2623. {
  2624. char* val = values[i];
  2625. char* comma = strchr(val, ',');
  2626. StringBuffer groupname;
  2627. groupname.append(comma - val -3, val+3);
  2628. groups.append(groupname.str());
  2629. }
  2630. ldap_value_free( values );
  2631. }
  2632. }
  2633. ber_free(ber, 0);
  2634. }
  2635. ldap_msgfree( searchResult );
  2636. }
  2637. else
  2638. {
  2639. StringArray allgroups;
  2640. getAllGroups(allgroups);
  2641. for(unsigned i = 0; i < allgroups.length(); i++)
  2642. {
  2643. const char* grp = allgroups.item(i);
  2644. StringBuffer grpdn, usrdn;
  2645. getUserDN(user, usrdn);
  2646. getGroupDN(grp, grpdn);
  2647. if(userInGroup(usrdn.str(), grpdn.str()))
  2648. {
  2649. groups.append(grp);
  2650. }
  2651. }
  2652. }
  2653. }
  2654. virtual void changeUserGroup(const char* action, const char* username, const char* groupname)
  2655. {
  2656. StringBuffer userdn, groupdn;
  2657. getUserDN(username, userdn);
  2658. getGroupDN(groupname, groupdn);
  2659. // Not needed for Active Directory
  2660. // changeUserMemberOf(action, userdn.str(), groupdn.str());
  2661. changeGroupMember(action, groupdn.str(), userdn.str());
  2662. }
  2663. virtual bool deleteUser(ISecUser* user)
  2664. {
  2665. if(user == NULL)
  2666. return false;
  2667. const char* username = user->getName();
  2668. if(username == NULL || *username == '\0')
  2669. return false;
  2670. StringBuffer userdn;
  2671. getUserDN(username, userdn);
  2672. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2673. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2674. int rc = ldap_delete_s(ld, (char*)userdn.str());
  2675. if ( rc != LDAP_SUCCESS )
  2676. {
  2677. throw MakeStringException(-1, "error deleting user %s: %s", username, ldap_err2string(rc));
  2678. }
  2679. StringArray grps;
  2680. getGroups(username, grps);
  2681. ForEachItemIn(x, grps)
  2682. {
  2683. const char* grp = grps.item(x);
  2684. if(!grp || !*grp)
  2685. continue;
  2686. changeUserGroup("delete", username, grp);
  2687. }
  2688. return true;
  2689. }
  2690. virtual void addGroup(const char* groupname)
  2691. {
  2692. if(groupname == NULL || *groupname == '\0')
  2693. throw MakeStringException(-1, "Can't add group, groupname is empty");
  2694. addGroup(groupname, m_ldapconfig->getGroupBasedn());
  2695. }
  2696. virtual void addGroup(const char* groupname, const char* basedn)
  2697. {
  2698. if(groupname == NULL || *groupname == '\0')
  2699. return;
  2700. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2701. {
  2702. if(stricmp(groupname, "Administrators") == 0)
  2703. throw MakeStringException(-1, "Can't add group %s, it's reserved by the system.", groupname);
  2704. }
  2705. else
  2706. {
  2707. if(stricmp(groupname, "Directory Administrators") == 0)
  2708. throw MakeStringException(-1, "Can't add group %s, it's reserved by the system.", groupname);
  2709. }
  2710. StringBuffer dn;
  2711. dn.append("cn=").append(groupname).append(",").append(basedn);
  2712. char* oc_name;
  2713. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2714. {
  2715. oc_name = "group";
  2716. }
  2717. else
  2718. {
  2719. oc_name = "groupofuniquenames";
  2720. }
  2721. char *cn_values[] = {(char*)groupname, NULL };
  2722. LDAPMod cn_attr =
  2723. {
  2724. LDAP_MOD_ADD,
  2725. "cn",
  2726. cn_values
  2727. };
  2728. char *oc_values[] = {oc_name, NULL };
  2729. LDAPMod oc_attr =
  2730. {
  2731. LDAP_MOD_ADD,
  2732. "objectClass",
  2733. oc_values
  2734. };
  2735. char *act_values[] = {(char*)groupname, NULL};
  2736. LDAPMod act_attr =
  2737. {
  2738. LDAP_MOD_ADD,
  2739. "sAMAccountName",
  2740. act_values
  2741. };
  2742. char *member_values[] = {"", NULL};
  2743. LDAPMod member_attr =
  2744. {
  2745. LDAP_MOD_ADD,
  2746. "uniqueMember",
  2747. member_values
  2748. };
  2749. LDAPMod *attrs[5];
  2750. int ind = 0;
  2751. attrs[ind++] = &cn_attr;
  2752. attrs[ind++] = &oc_attr;
  2753. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2754. {
  2755. attrs[ind++] = &act_attr;
  2756. }
  2757. if(m_ldapconfig->getServerType() == OPEN_LDAP)
  2758. {
  2759. attrs[ind++] = &member_attr;
  2760. }
  2761. attrs[ind] = NULL;
  2762. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2763. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2764. int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  2765. if ( rc != LDAP_SUCCESS )
  2766. {
  2767. if(rc == LDAP_ALREADY_EXISTS)
  2768. {
  2769. throw MakeStringException(-1, "can't add group %s, already exists", groupname);
  2770. }
  2771. else
  2772. {
  2773. DBGLOG("error addGroup %s, ldap_add_ext_s error: %s", groupname, ldap_err2string( rc ));
  2774. throw MakeStringException(-1, "error addGroup %s, ldap_add_ext_s error: %s", groupname, ldap_err2string( rc ));
  2775. }
  2776. }
  2777. }
  2778. virtual void deleteGroup(const char* groupname)
  2779. {
  2780. if(groupname == NULL || *groupname == '\0')
  2781. throw MakeStringException(-1, "group name can't be empty");
  2782. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2783. {
  2784. if(stricmp(groupname, "Administrators") == 0 || stricmp(groupname, "Authenticated Users") == 0)
  2785. throw MakeStringException(-1, "you can't delete Authenticated Users or Administrators group");
  2786. }
  2787. else
  2788. {
  2789. if(stricmp(groupname, "Directory Administrators") == 0)
  2790. throw MakeStringException(-1, "you can't delete Directory Administrators group");
  2791. }
  2792. StringBuffer dn;
  2793. getGroupDN(groupname, dn);
  2794. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2795. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2796. int rc = ldap_delete_s(ld, (char*)dn.str());
  2797. if ( rc != LDAP_SUCCESS )
  2798. {
  2799. throw MakeStringException(-1, "error deleting group %s: %s", groupname, ldap_err2string(rc));
  2800. }
  2801. }
  2802. virtual void getGroupMembers(const char* groupname, StringArray & users)
  2803. {
  2804. char *attribute, **values;
  2805. BerElement *ber;
  2806. LDAPMessage *searchResult, *message;
  2807. if(groupname == NULL || strlen(groupname) == 0)
  2808. throw MakeStringException(-1, "group name can't be empty");
  2809. StringBuffer grpdn;
  2810. getGroupDN(groupname, grpdn);
  2811. StringBuffer filter;
  2812. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2813. {
  2814. filter.append("distinguishedName=").append(grpdn.str());
  2815. }
  2816. else if(m_ldapconfig->getServerType() == IPLANET)
  2817. {
  2818. filter.append("entrydn=").append(grpdn.str());
  2819. }
  2820. else if(m_ldapconfig->getServerType() == OPEN_LDAP)
  2821. {
  2822. filter.append("cn=").append(groupname);
  2823. }
  2824. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  2825. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2826. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2827. const char* memfieldname;
  2828. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2829. {
  2830. memfieldname = "member";
  2831. }
  2832. else
  2833. {
  2834. memfieldname = "uniquemember";
  2835. }
  2836. char *attrs[] = {(char*)memfieldname, NULL};
  2837. StringBuffer groupbasedn;
  2838. getGroupBaseDN(groupname, groupbasedn);
  2839. int rc = ldap_search_ext_s(ld, (char*)groupbasedn.str(),LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  2840. if ( rc != LDAP_SUCCESS )
  2841. {
  2842. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getBasedn());
  2843. return;
  2844. }
  2845. unsigned entries = ldap_count_entries(ld, searchResult);
  2846. if(entries == 0)
  2847. {
  2848. throw MakeStringException(-1, "group %s not found", groupname);
  2849. }
  2850. // Go through the search results by checking message types
  2851. for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  2852. {
  2853. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  2854. attribute != NULL;
  2855. attribute = ldap_next_attribute( ld, searchResult,ber))
  2856. {
  2857. if (( values = ldap_get_values( ld, message, attribute))
  2858. != NULL )
  2859. {
  2860. for (int i = 0; values[ i ] != NULL; i++ )
  2861. {
  2862. char* val = values[i];
  2863. StringBuffer uid;
  2864. getUidFromDN(val, uid);
  2865. if(uid.length() > 0)
  2866. users.append(uid.str());
  2867. }
  2868. ldap_value_free( values );
  2869. }
  2870. }
  2871. ber_free(ber, 0);
  2872. }
  2873. ldap_msgfree( searchResult );
  2874. }
  2875. virtual void deleteResource(SecResourceType rtype, const char* name, const char* basedn)
  2876. {
  2877. if(basedn == NULL || *basedn == '\0')
  2878. basedn = m_ldapconfig->getResourceBasedn(rtype);
  2879. StringBuffer dn;
  2880. name2dn(rtype, name, basedn, dn);
  2881. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2882. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2883. int rc = ldap_delete_s(ld, (char*)dn.str());
  2884. if ( rc != LDAP_SUCCESS )
  2885. {
  2886. DBGLOG("error deleting %s: %s", dn.str(), ldap_err2string(rc));
  2887. //throw MakeStringException(-1, "error deleting %s: %s", dn.str(), ldap_err2string(rc));
  2888. }
  2889. }
  2890. virtual void renameResource(SecResourceType rtype, const char* oldname, const char* newname, const char* basedn)
  2891. {
  2892. if(oldname == NULL || *oldname == '\0' || newname == NULL || *newname == '\0')
  2893. throw MakeStringException(-1, "please specfiy old and new names");
  2894. if(basedn == NULL || *basedn == '\0')
  2895. basedn = m_ldapconfig->getResourceBasedn(rtype);
  2896. StringBuffer olddn, newrdn;
  2897. name2dn(rtype, oldname, basedn, olddn);
  2898. name2rdn(rtype, newname, newrdn);
  2899. Owned<ILdapConnection> lconn = m_connections->getConnection();
  2900. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  2901. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY && (rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE))
  2902. {
  2903. char* uncname_values[] = {(char*)newname, NULL};
  2904. LDAPMod uncname_attr =
  2905. {
  2906. LDAP_MOD_REPLACE,
  2907. "uNCName",
  2908. uncname_values
  2909. };
  2910. LDAPMod *attrs[2];
  2911. attrs[0] = &uncname_attr;
  2912. attrs[1] = NULL;
  2913. int rc = ldap_modify_s(ld, (char*)olddn.str(), attrs);
  2914. if (rc != LDAP_SUCCESS )
  2915. {
  2916. DBGLOG("Error changing unc %s to %s - %s", oldname, newname, ldap_err2string( rc ));
  2917. //throw MakeStringException(-1, "Error changing unc %s to %s - %s", oldname, newname, ldap_err2string( rc ));
  2918. }
  2919. }
  2920. #ifdef _WIN32
  2921. int rc = ldap_rename_ext_s(ld, (char*)olddn.str(), (char*)newrdn.str(), NULL, true, NULL, NULL);
  2922. #else
  2923. int rc = ldap_rename_s(ld, (char*)olddn.str(), (char*)newrdn.str(), NULL, true, NULL, NULL);
  2924. #endif
  2925. if (rc != LDAP_SUCCESS )
  2926. {
  2927. DBGLOG("Error renaming %s to %s - %s", oldname, newname, ldap_err2string( rc ));
  2928. //throw MakeStringException(-1, "Error renaming %s to %s - %s", oldname, newname, ldap_err2string( rc ));
  2929. }
  2930. }
  2931. virtual void copyResource(SecResourceType rtype, const char* oldname, const char* newname, const char* basedn)
  2932. {
  2933. if(oldname == NULL || *oldname == '\0' || newname == NULL || *newname == '\0')
  2934. throw MakeStringException(-1, "please specfiy old and new names");
  2935. if(basedn == NULL || *basedn == '\0')
  2936. basedn = m_ldapconfig->getResourceBasedn(rtype);
  2937. Owned<CSecurityDescriptor> sd = new CSecurityDescriptor(oldname);
  2938. IArrayOf<CSecurityDescriptor> sdlist;
  2939. sdlist.append(*LINK(sd));
  2940. if(rtype == RT_FILE_SCOPE || rtype == RT_WORKUNIT_SCOPE)
  2941. getSecurityDescriptorsScope(sdlist, basedn);
  2942. else
  2943. getSecurityDescriptors(sdlist, basedn);
  2944. if(sd->getDescriptor().length() == 0)
  2945. throw MakeStringException(-1, "error copying %s to %s, %s doesn't exist", oldname, newname, oldname);
  2946. ISecUser* user = NULL;
  2947. CLdapSecResource resource(newname);
  2948. addResource(rtype, *user, &resource, PT_DEFAULT, basedn, sd.get(), false);
  2949. }
  2950. void normalizeDn(const char* dn, StringBuffer& ndn)
  2951. {
  2952. LdapUtils::normalizeDn(dn, m_ldapconfig->getBasedn(), ndn);
  2953. }
  2954. virtual bool isSuperUser(ISecUser* user)
  2955. {
  2956. if(user == NULL || user->getName() == NULL)
  2957. return false;
  2958. const char* username = user->getName();
  2959. const char* sysuser = m_ldapconfig->getSysUser();
  2960. if(sysuser != NULL && stricmp(sysuser, username) == 0)
  2961. return true;
  2962. StringBuffer userdn, admingrpdn;
  2963. getUserDN(username, userdn);
  2964. getAdminGroupDN(admingrpdn);
  2965. return userInGroup(userdn.str(), admingrpdn.str());
  2966. }
  2967. virtual ILdapConfig* queryConfig()
  2968. {
  2969. return m_ldapconfig.get();
  2970. }
  2971. virtual int countUsers(const char* searchstr, int limit)
  2972. {
  2973. StringBuffer filter;
  2974. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  2975. filter.append("objectClass=User");
  2976. else
  2977. filter.append("objectClass=inetorgperson");
  2978. if(searchstr && *searchstr && strcmp(searchstr, "*") != 0)
  2979. {
  2980. filter.insert(0, "(&(");
  2981. filter.appendf(")(|(%s=*%s*)(%s=*%s*)(%s=*%s*)))", (m_ldapconfig->getServerType()==ACTIVE_DIRECTORY)?"sAMAcccountName":"uid", searchstr, "givenName", searchstr, "sn", searchstr);
  2982. }
  2983. return countEntries(m_ldapconfig->getUserBasedn(), filter.str(), limit);
  2984. }
  2985. virtual int countResources(const char* basedn, const char* searchstr, int limit)
  2986. {
  2987. StringBuffer filter;
  2988. filter.append("objectClass=*");
  2989. if(searchstr && *searchstr && strcmp(searchstr, "*") != 0)
  2990. {
  2991. filter.insert(0, "(&(");
  2992. filter.appendf(")(|(%s=*%s*)))", "uNCName", searchstr);
  2993. }
  2994. return countEntries(basedn, filter.str(), limit);
  2995. }
  2996. virtual int countEntries(const char* basedn, const char* filter, int limit)
  2997. {
  2998. struct berval** bvalues = NULL;
  2999. LDAPMessage *searchResult;
  3000. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  3001. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3002. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3003. char *attrs[] = { LDAP_NO_ATTRS, NULL };
  3004. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter, attrs, 0, NULL, NULL, &timeOut, limit, &searchResult );
  3005. if ( rc != LDAP_SUCCESS )
  3006. {
  3007. if(rc == LDAP_SIZELIMIT_EXCEEDED)
  3008. return -1;
  3009. else
  3010. throw MakeStringException(-1, "ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter, basedn);
  3011. }
  3012. int entries = ldap_count_entries(ld, searchResult);
  3013. ldap_msgfree( searchResult );
  3014. return entries;
  3015. }
  3016. virtual const char* getPasswordStorageScheme()
  3017. {
  3018. if(m_pwscheme.length() == 0)
  3019. {
  3020. if(m_ldapconfig->getServerType() == IPLANET)
  3021. {
  3022. LDAPMessage *msg;
  3023. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3024. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3025. char* pw_attrs[] = {"nsslapd-rootpwstoragescheme", NULL};
  3026. int err = ldap_search_s(ld, "cn=config", LDAP_SCOPE_BASE, "objectClass=*", pw_attrs, false, &msg);
  3027. if(err != LDAP_SUCCESS)
  3028. {
  3029. DBGLOG("ldap_search_s error: %s", ldap_err2string( err ));
  3030. return NULL;
  3031. }
  3032. LDAPMessage* entry = LdapFirstEntry(ld, msg);
  3033. if(entry != NULL)
  3034. {
  3035. char** vals = ldap_get_values(ld, entry, "nsslapd-rootpwstoragescheme");
  3036. if(vals != NULL)
  3037. {
  3038. if(vals[0] != NULL)
  3039. m_pwscheme.append(vals[0]);
  3040. ldap_value_free(vals);
  3041. }
  3042. }
  3043. ldap_msgfree(msg);
  3044. }
  3045. }
  3046. if(m_pwscheme.length() == 0)
  3047. return NULL;
  3048. else
  3049. return m_pwscheme.str();
  3050. }
  3051. private:
  3052. virtual void addDC(const char* dc)
  3053. {
  3054. if(dc == NULL || *dc == '\0')
  3055. return;
  3056. StringBuffer dcname;
  3057. LdapUtils::getName(dc, dcname);
  3058. char *dc_values[] = {(char*)dcname.str(), NULL };
  3059. LDAPMod dc_attr =
  3060. {
  3061. LDAP_MOD_ADD,
  3062. "dc",
  3063. dc_values
  3064. };
  3065. char *o_values[] = {(char*)dcname.str(), NULL };
  3066. LDAPMod o_attr =
  3067. {
  3068. LDAP_MOD_ADD,
  3069. "o",
  3070. o_values
  3071. };
  3072. char *oc_values[] = {"organization", "dcObject", NULL };
  3073. LDAPMod oc_attr =
  3074. {
  3075. LDAP_MOD_ADD,
  3076. "objectClass",
  3077. oc_values
  3078. };
  3079. LDAPMod *attrs[4];
  3080. attrs[0] = &oc_attr;
  3081. attrs[1] = &o_attr;
  3082. attrs[2] = &dc_attr;
  3083. attrs[3] = NULL;
  3084. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3085. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3086. int rc = ldap_add_ext_s(ld, (char*)dc, attrs, NULL, NULL);
  3087. if ( rc != LDAP_SUCCESS )
  3088. {
  3089. if(rc == LDAP_ALREADY_EXISTS)
  3090. {
  3091. throw MakeStringException(-1, "can't add dc %s, already exists", dc);
  3092. }
  3093. else
  3094. {
  3095. DBGLOG("error addDC %s, ldap_add_ext_s error: 0x%0x %s", dc, rc, ldap_err2string( rc ));
  3096. throw MakeStringException(-1, "error addDC %s, ldap_add_ext_s error: %s", dc, ldap_err2string( rc ));
  3097. }
  3098. }
  3099. }
  3100. virtual void getUserDN(const char* username, StringBuffer& userdn)
  3101. {
  3102. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3103. {
  3104. StringBuffer filter;
  3105. filter.append("sAMAccountName=");
  3106. filter.append(username);
  3107. char *attribute, **values = NULL;
  3108. BerElement *ber;
  3109. LDAPMessage *searchResult, *message;
  3110. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  3111. char *dn_fieldname;
  3112. dn_fieldname = "distinguishedName";
  3113. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3114. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3115. char *attrs[] = {dn_fieldname, NULL};
  3116. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  3117. if ( rc != LDAP_SUCCESS )
  3118. {
  3119. throw MakeStringException(-1, "ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  3120. }
  3121. unsigned entries = ldap_count_entries(ld, searchResult);
  3122. if(entries == 0)
  3123. {
  3124. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getSysUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  3125. if ( rc != LDAP_SUCCESS )
  3126. {
  3127. throw MakeStringException(-1, "ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getSysUserBasedn());
  3128. }
  3129. }
  3130. message = LdapFirstEntry( ld, searchResult);
  3131. if(searchResult != NULL)
  3132. {
  3133. attribute = ldap_first_attribute( ld,searchResult,&ber );
  3134. if(attribute != NULL)
  3135. {
  3136. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  3137. {
  3138. char* val = values[0];
  3139. userdn.append(val);
  3140. ldap_value_free( values );
  3141. }
  3142. }
  3143. ber_free(ber, 0);
  3144. ldap_msgfree( searchResult );
  3145. }
  3146. if(userdn.length() == 0)
  3147. throw MakeStringException(-1, "user %s can't be found", username);
  3148. }
  3149. else
  3150. {
  3151. if(stricmp(username, "anyone") == 0)
  3152. userdn.append(username);
  3153. else
  3154. userdn.append("uid=").append(username).append(",").append(m_ldapconfig->getUserBasedn());
  3155. }
  3156. }
  3157. virtual void getUidFromDN(const char* dn, StringBuffer& uid)
  3158. {
  3159. if(dn == NULL || *dn == '\0')
  3160. return;
  3161. if(m_ldapconfig->getServerType() != ACTIVE_DIRECTORY)
  3162. {
  3163. const char* comma = strchr(dn, ',');
  3164. // DN is in the format of "uid=uuu,ou=ooo,dc=dd"
  3165. uid.append(comma - dn - 4, dn + 4);
  3166. return;
  3167. }
  3168. StringBuffer filter;
  3169. filter.append("distinguishedName=").append(dn);
  3170. char *attribute, **values = NULL;
  3171. BerElement *ber;
  3172. LDAPMessage *searchResult, *message;
  3173. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  3174. char *uid_fieldname = "sAMAccountName";
  3175. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3176. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3177. char *attrs[] = {uid_fieldname, NULL};
  3178. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  3179. if ( rc != LDAP_SUCCESS )
  3180. {
  3181. throw MakeStringException(-1, "ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  3182. }
  3183. message = LdapFirstEntry( ld, searchResult);
  3184. if(searchResult != NULL)
  3185. {
  3186. attribute = ldap_first_attribute( ld,searchResult,&ber );
  3187. if(attribute != NULL)
  3188. {
  3189. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  3190. {
  3191. char* val = values[0];
  3192. uid.append(val);
  3193. ldap_value_free( values );
  3194. }
  3195. }
  3196. ber_free(ber, 0);
  3197. ldap_msgfree( searchResult );
  3198. }
  3199. }
  3200. virtual void getGroupDN(const char* groupname, StringBuffer& groupdn)
  3201. {
  3202. if(groupname == NULL)
  3203. return;
  3204. LdapServerType stype = m_ldapconfig->getServerType();
  3205. groupdn.append("cn=").append(groupname).append(",");
  3206. if(stype == ACTIVE_DIRECTORY && stricmp(groupname, "Administrators") == 0)
  3207. {
  3208. groupdn.append("cn=Builtin,").append(m_ldapconfig->getBasedn());
  3209. }
  3210. else if((stype == IPLANET || stype == OPEN_LDAP) && stricmp(groupname, "Directory Administrators") == 0)
  3211. {
  3212. groupdn.append(m_ldapconfig->getBasedn());
  3213. }
  3214. else
  3215. {
  3216. groupdn.append(m_ldapconfig->getGroupBasedn());
  3217. }
  3218. }
  3219. virtual void getGroupBaseDN(const char* groupname, StringBuffer& groupbasedn)
  3220. {
  3221. if(groupname == NULL)
  3222. return;
  3223. LdapServerType stype = m_ldapconfig->getServerType();
  3224. if(stype == ACTIVE_DIRECTORY && stricmp(groupname, "Administrators") == 0)
  3225. {
  3226. groupbasedn.append("cn=Builtin,").append(m_ldapconfig->getBasedn());
  3227. }
  3228. else if((stype == IPLANET || stype == OPEN_LDAP) && stricmp(groupname, "Directory Administrators") == 0)
  3229. {
  3230. groupbasedn.append(m_ldapconfig->getBasedn());
  3231. }
  3232. else
  3233. {
  3234. groupbasedn.append(m_ldapconfig->getGroupBasedn());
  3235. }
  3236. }
  3237. virtual void getAdminGroupDN(StringBuffer& groupdn)
  3238. {
  3239. LdapServerType stype = m_ldapconfig->getServerType();
  3240. if(stype == ACTIVE_DIRECTORY)
  3241. {
  3242. groupdn.append("cn=Administrators,cn=Builtin,").append(m_ldapconfig->getBasedn());
  3243. }
  3244. else if(stype == IPLANET)
  3245. {
  3246. groupdn.append("cn=Directory Administrators,").append(m_ldapconfig->getBasedn());
  3247. }
  3248. else if(stype == OPEN_LDAP)
  3249. {
  3250. groupdn.append("cn=Directory Administrators,").append(m_ldapconfig->getBasedn());
  3251. }
  3252. }
  3253. virtual void changeUserMemberOf(const char* action, const char* userdn, const char* groupdn)
  3254. {
  3255. char *grp_values[] = {(char*)groupdn, NULL};
  3256. LDAPMod grp_attr = {
  3257. (action != NULL && stricmp(action, "delete") == 0)?LDAP_MOD_DELETE:LDAP_MOD_ADD,
  3258. "memberOf",
  3259. grp_values
  3260. };
  3261. LDAPMod *grp_attrs[2];
  3262. grp_attrs[0] = &grp_attr;
  3263. grp_attrs[1] = NULL;
  3264. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3265. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3266. int rc = ldap_modify_ext_s(ld, (char*)userdn, grp_attrs, NULL, NULL);
  3267. if ( rc != LDAP_SUCCESS )
  3268. {
  3269. throw MakeStringException(-1, "error changing group for user %s, ldap_modify_ext_s error: %s", userdn, ldap_err2string( rc ));
  3270. }
  3271. }
  3272. virtual void changeGroupMember(const char* action, const char* groupdn, const char* userdn)
  3273. {
  3274. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3275. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3276. const char* memberfieldname;
  3277. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3278. {
  3279. memberfieldname = "member";
  3280. }
  3281. else
  3282. {
  3283. memberfieldname = "uniquemember";
  3284. }
  3285. char *member_values[] = {(char*)userdn, NULL};
  3286. LDAPMod member_attr = {
  3287. (action != NULL && stricmp(action, "delete") == 0)?LDAP_MOD_DELETE:LDAP_MOD_ADD,
  3288. (char*)memberfieldname,
  3289. member_values
  3290. };
  3291. LDAPMod *member_attrs[2];
  3292. member_attrs[0] = &member_attr;
  3293. member_attrs[1] = NULL;
  3294. int rc = ldap_modify_ext_s(ld, (char*)groupdn, member_attrs, NULL, NULL);
  3295. if ( rc != LDAP_SUCCESS )
  3296. {
  3297. if (action != NULL && stricmp(action, "delete") == 0)
  3298. throw MakeStringException(-1, "Failed in deleting member from group: ldap_modify_ext_s error: %s; userdn: %s; groupdn: %s", ldap_err2string( rc ), userdn, groupdn);
  3299. else
  3300. throw MakeStringException(-1, "Failed in adding member to group, ldap_modify_ext_s error: %s; userdn: %s; groupdn: %s", ldap_err2string( rc ), userdn, groupdn);
  3301. }
  3302. }
  3303. void ConvertCToW(unsigned short* pszDest, const CHAR* pszSrc)
  3304. {
  3305. unsigned i = 0;
  3306. for(i = 0; i < strlen(pszSrc); i++)
  3307. pszDest[i] = (unsigned short) pszSrc[i];
  3308. pszDest[i] = (unsigned short)'\0';
  3309. }
  3310. virtual bool authorizeScope(ISecUser& user, IArrayOf<ISecResource>& resources, const char* basedn)
  3311. {
  3312. IArrayOf<CSecurityDescriptor> sdlist;
  3313. std::set<const char*, ltstr> scopeset;
  3314. ForEachItemIn(x, resources)
  3315. {
  3316. ISecResource& res = resources.item(x);
  3317. const char* resourcename = res.getName();
  3318. if(resourcename == NULL || *resourcename == '\0')
  3319. continue;
  3320. // Add one extra Volume type SecurityDescriptor for each resource for ActiveDirectory.
  3321. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3322. {
  3323. CSecurityDescriptor* sd = new CSecurityDescriptor(resourcename);
  3324. sd->setObjectClass("Volume");
  3325. sdlist.append(*sd);
  3326. }
  3327. scopeset.insert(resourcename);
  3328. int len = strlen(resourcename);
  3329. const char* curptr = resourcename + len - 1;
  3330. while(curptr > resourcename)
  3331. {
  3332. while(curptr > resourcename && *curptr != ':')
  3333. curptr--;
  3334. bool foundcolon=false;
  3335. while(curptr >resourcename && *curptr == ':')
  3336. {
  3337. curptr--;
  3338. foundcolon = true;
  3339. }
  3340. if(curptr > resourcename || foundcolon)
  3341. {
  3342. int curlen = curptr - resourcename + 1;
  3343. char* curscope = (char*)alloca(curlen + 1);
  3344. strncpy(curscope, resourcename, curlen);
  3345. curscope[curlen] = 0;
  3346. scopeset.insert(curscope);
  3347. }
  3348. }
  3349. }
  3350. if(scopeset.size() == 0)
  3351. return true;
  3352. std::set<const char*, ltstr>::iterator iter;
  3353. for(iter = scopeset.begin(); iter != scopeset.end(); iter++)
  3354. {
  3355. const char* curscope = *iter;
  3356. CSecurityDescriptor* sd = new CSecurityDescriptor(*iter);
  3357. sd->setObjectClass("organizationalUnit");
  3358. sdlist.append(*sd);
  3359. }
  3360. getSecurityDescriptorsScope(sdlist, basedn);
  3361. IArrayOf<CSecurityDescriptor> matched_sdlist;
  3362. ForEachItemIn(y, resources)
  3363. {
  3364. ISecResource& res = resources.item(y);
  3365. const char* rname = res.getName();
  3366. if(rname == NULL || *rname == '\0')
  3367. throw MakeStringException(-1, "resource name can't be empty inside authorizeScope");
  3368. CSecurityDescriptor* matchedsd = NULL;
  3369. ForEachItemIn(z, sdlist)
  3370. {
  3371. CSecurityDescriptor& sd = sdlist.item(z);
  3372. const char* sdname = sd.getName();
  3373. if(sdname == NULL || *sdname == '\0')
  3374. continue;
  3375. if(strncmp(sdname, rname, strlen(sdname)) == 0
  3376. && (matchedsd == NULL
  3377. || ((matchedsd->getDescriptor().length() == 0 && sd.getDescriptor().length() > 0)
  3378. || (sd.getDescriptor().length() > 0 && strlen(sdname) > strlen(matchedsd->getName())))))
  3379. matchedsd = &sd;
  3380. }
  3381. if(matchedsd != NULL)
  3382. matched_sdlist.append(*LINK(matchedsd));
  3383. else
  3384. matched_sdlist.append(*(new CSecurityDescriptor(rname)));
  3385. }
  3386. bool ok = false;
  3387. if(m_pp != NULL)
  3388. ok = m_pp->getPermissions(user, matched_sdlist, resources);
  3389. return ok;
  3390. }
  3391. virtual void getSecurityDescriptors(SecResourceType rtype, IArrayOf<CSecurityDescriptor>& sdlist)
  3392. {
  3393. int len = sdlist.length();
  3394. if(len == 0)
  3395. return;
  3396. const char* rbasedn = m_ldapconfig->getResourceBasedn(rtype);
  3397. if(rbasedn == NULL || *rbasedn == '\0')
  3398. {
  3399. DBGLOG("corresponding resource basedn is not defined");
  3400. return;
  3401. }
  3402. std::map<std::string, IArrayOf<CSecurityDescriptor>*> sdmap;
  3403. for(int i = 0; i < len; i++)
  3404. {
  3405. CSecurityDescriptor& sd = sdlist.item(i);
  3406. const char* relativeBasedn = sd.getRelativeBasedn();
  3407. StringBuffer basedn;
  3408. if(relativeBasedn != NULL)
  3409. basedn.append(relativeBasedn).append(",");
  3410. basedn.append(rbasedn);
  3411. std::map<std::string, IArrayOf<CSecurityDescriptor>*>::iterator sdit = sdmap.find(basedn.str());
  3412. if(sdit == sdmap.end())
  3413. {
  3414. IArrayOf<CSecurityDescriptor>* newlist = new IArrayOf<CSecurityDescriptor>;
  3415. newlist->append(*LINK(&sd));
  3416. sdmap[basedn.str()] = newlist;
  3417. }
  3418. else
  3419. {
  3420. (*sdit).second->append(*LINK(&sd));
  3421. }
  3422. }
  3423. for(std::map<std::string, IArrayOf<CSecurityDescriptor>*>::iterator cur = sdmap.begin(); cur != sdmap.end(); cur++)
  3424. {
  3425. getSecurityDescriptors(*((*cur).second), (*cur).first.c_str());
  3426. delete (*cur).second;
  3427. }
  3428. }
  3429. virtual void getSecurityDescriptors(IArrayOf<CSecurityDescriptor>& sdlist, const char* basedn)
  3430. {
  3431. char *attribute, **values;
  3432. BerElement *ber;
  3433. struct berval** bvalues = NULL;
  3434. LDAPMessage *searchResult, *message;
  3435. int i;
  3436. const char *id_fieldname;
  3437. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3438. {
  3439. id_fieldname = "name";
  3440. }
  3441. else
  3442. {
  3443. id_fieldname = "ou";
  3444. }
  3445. const char *des_fieldname = m_ldapconfig->getSdFieldName();
  3446. int len = sdlist.length();
  3447. if(len == 0)
  3448. return;
  3449. StringBuffer filter;
  3450. filter.append("(|");
  3451. for(i = 0; i < len; i++)
  3452. {
  3453. CSecurityDescriptor& sd = sdlist.item(i);
  3454. StringBuffer namebuf;
  3455. namebuf.append(sd.getName());
  3456. namebuf.trim();
  3457. if(namebuf.length() > 0)
  3458. {
  3459. filter.append("(").append(id_fieldname).append("=").append(namebuf.str()).append(")");;
  3460. }
  3461. }
  3462. filter.append(")");
  3463. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  3464. char* attrs[] = {(char*)id_fieldname, (char*)des_fieldname, NULL};
  3465. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3466. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3467. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult ); /* returned results */
  3468. if ( rc != LDAP_SUCCESS )
  3469. {
  3470. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basedn);
  3471. return;
  3472. }
  3473. // Go through the search results by checking message types
  3474. for(message = LdapFirstEntry(ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  3475. {
  3476. StringBuffer resourcename;
  3477. for ( attribute = ldap_first_attribute( ld,searchResult,&ber ); attribute != NULL;
  3478. attribute = ldap_next_attribute( ld, searchResult,ber))
  3479. {
  3480. if(stricmp(attribute, id_fieldname) == 0)
  3481. {
  3482. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  3483. {
  3484. char* val = values[0];
  3485. resourcename.append(val);
  3486. }
  3487. ldap_value_free( values );
  3488. }
  3489. else if(stricmp(attribute, des_fieldname) == 0)
  3490. {
  3491. bvalues = ldap_get_values_len( ld, message, attribute);
  3492. }
  3493. ldap_memfree( attribute );
  3494. }
  3495. for(i = 0; i < len; i++)
  3496. {
  3497. CSecurityDescriptor& sd = sdlist.item(i);
  3498. if(resourcename.length() > 0 && stricmp(resourcename.str(), sd.getName()) == 0)
  3499. {
  3500. if(bvalues != NULL)
  3501. {
  3502. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3503. {
  3504. struct berval* val = bvalues[0];
  3505. if(val != NULL)
  3506. {
  3507. CSecurityDescriptor& sd = sdlist.item(i);
  3508. sd.setDescriptor(val->bv_len, val->bv_val);
  3509. }
  3510. }
  3511. else
  3512. {
  3513. MemoryBuffer allvals;
  3514. int valseq = 0;
  3515. struct berval* val = bvalues[valseq++];
  3516. while(val != NULL)
  3517. {
  3518. if(val->bv_len > 0)
  3519. {
  3520. allvals.append(val->bv_len, val->bv_val);
  3521. allvals.append('\0'); // my separator between ACIs
  3522. }
  3523. val = bvalues[valseq++];
  3524. }
  3525. if(allvals.length() > 0)
  3526. {
  3527. CSecurityDescriptor& sd = sdlist.item(i);
  3528. sd.setDescriptor(allvals.length(), (void*)allvals.toByteArray());
  3529. }
  3530. }
  3531. }
  3532. break;
  3533. }
  3534. }
  3535. if(bvalues != NULL)
  3536. {
  3537. ldap_value_free_len( bvalues );
  3538. bvalues = NULL;
  3539. }
  3540. ber_free(ber, 0);
  3541. }
  3542. ldap_msgfree( searchResult );
  3543. }
  3544. virtual void getSecurityDescriptorsScope(IArrayOf<CSecurityDescriptor>& sdlist, const char* basedn)
  3545. {
  3546. char *attribute;
  3547. BerElement *ber;
  3548. struct berval** bvalues = NULL;
  3549. LDAPMessage *searchResult, *message;
  3550. int i;
  3551. int len = sdlist.length();
  3552. if(len == 0)
  3553. return;
  3554. LdapServerType servertype = m_ldapconfig->getServerType();
  3555. char *sd_fieldname = (char*)m_ldapconfig->getSdFieldName();
  3556. StringBuffer filter;
  3557. filter.append("(|");
  3558. for(i = 0; i < len; i++)
  3559. {
  3560. CSecurityDescriptor& sd = sdlist.item(i);
  3561. StringBuffer namebuf;
  3562. namebuf.append(sd.getName());
  3563. namebuf.trim();
  3564. if(namebuf.length() > 0)
  3565. {
  3566. const char* resourcename = namebuf.str();
  3567. int len = namebuf.length();
  3568. const char* curptr = resourcename + len - 1;
  3569. StringBuffer dn, cn;
  3570. bool isleaf = true;
  3571. while(curptr > resourcename)
  3572. {
  3573. const char* lastptr = curptr;
  3574. while(curptr > resourcename && *curptr != ':')
  3575. curptr--;
  3576. int curlen;
  3577. const char* curscope;
  3578. if(*curptr == ':')
  3579. {
  3580. curlen = lastptr - curptr;
  3581. curscope = curptr + 1;
  3582. }
  3583. else
  3584. {
  3585. curlen = lastptr - curptr + 1;
  3586. curscope = curptr;
  3587. }
  3588. if(isleaf && (sd.getObjectClass() != NULL) && (stricmp(sd.getObjectClass(), "Volume") == 0))
  3589. {
  3590. cn.append(curlen, curscope);
  3591. dn.append("cn=").append(curlen, curscope).append(",");
  3592. }
  3593. else
  3594. {
  3595. cn.append(curlen, curscope);
  3596. dn.append("ou=").append(curlen, curscope).append(",");
  3597. }
  3598. isleaf = false;
  3599. if (curptr == resourcename) //handle a single char as the top scope, such as x::abc
  3600. break;
  3601. while(curptr >resourcename && *curptr == ':')
  3602. curptr--;
  3603. if (curptr == resourcename && *curptr != ':') //handle a single char as the top scope, such as x::abc
  3604. {
  3605. dn.append("ou=").append(1, curptr).append(",");
  3606. }
  3607. }
  3608. dn.append(basedn);
  3609. if(servertype == ACTIVE_DIRECTORY)
  3610. {
  3611. filter.append("(distinguishedName=").append(dn.str()).append(")");
  3612. }
  3613. else if(servertype == IPLANET)
  3614. {
  3615. filter.append("(entrydn=").append(dn.str()).append(")");
  3616. }
  3617. else if(servertype == OPEN_LDAP)
  3618. {
  3619. filter.append("(ou=").append(cn.str()).append(")");
  3620. }
  3621. sd.setDn(dn.str());
  3622. }
  3623. }
  3624. filter.append(")");
  3625. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  3626. char* attrs[] = {sd_fieldname, NULL};
  3627. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3628. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3629. int rc = ldap_search_ext_s(ld, (char*)basedn, LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult ); /* returned results */
  3630. if ( rc != LDAP_SUCCESS )
  3631. {
  3632. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), basedn);
  3633. return;
  3634. }
  3635. // Go through the search results by checking message types
  3636. for(message = LdapFirstEntry(ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
  3637. {
  3638. StringBuffer dn;
  3639. dn.append(ldap_get_dn(ld, message));
  3640. for ( attribute = ldap_first_attribute( ld,searchResult,&ber ); attribute != NULL;
  3641. attribute = ldap_next_attribute( ld, searchResult,ber))
  3642. {
  3643. if(stricmp(attribute, sd_fieldname) == 0)
  3644. {
  3645. bvalues = ldap_get_values_len( ld, message, attribute);
  3646. }
  3647. ldap_memfree( attribute );
  3648. }
  3649. for(i = 0; i < len; i++)
  3650. {
  3651. CSecurityDescriptor& sd = sdlist.item(i);
  3652. if(dn.length() > 0 && stricmp(dn.str(), sd.getDn()) == 0)
  3653. {
  3654. if(bvalues != NULL)
  3655. {
  3656. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3657. {
  3658. struct berval* val = bvalues[0];
  3659. if(val != NULL)
  3660. {
  3661. CSecurityDescriptor& sd = sdlist.item(i);
  3662. sd.setDescriptor(val->bv_len, val->bv_val);
  3663. }
  3664. }
  3665. else
  3666. {
  3667. MemoryBuffer allvals;
  3668. int valseq = 0;
  3669. struct berval* val = bvalues[valseq++];
  3670. while(val != NULL)
  3671. {
  3672. if(val->bv_len > 0)
  3673. {
  3674. allvals.append(val->bv_len, val->bv_val);
  3675. allvals.append('\0'); // my separator between ACIs
  3676. }
  3677. val = bvalues[valseq++];
  3678. }
  3679. if(allvals.length() > 0)
  3680. {
  3681. CSecurityDescriptor& sd = sdlist.item(i);
  3682. sd.setDescriptor(allvals.length(), (void*)allvals.toByteArray());
  3683. }
  3684. }
  3685. }
  3686. break;
  3687. }
  3688. }
  3689. if(bvalues != NULL)
  3690. {
  3691. ldap_value_free_len( bvalues );
  3692. bvalues = NULL;
  3693. }
  3694. ber_free(ber, 0);
  3695. }
  3696. ldap_msgfree( searchResult );
  3697. }
  3698. virtual void createLdapBasedn(ISecUser* user, const char* basedn, SecPermissionType ptype)
  3699. {
  3700. if(basedn == NULL || basedn[0] == '\0')
  3701. return;
  3702. const char* ptr = strstr(basedn, "ou=");
  3703. if(ptr == NULL)
  3704. return;
  3705. ptr += 3;
  3706. StringBuffer oubuf;
  3707. const char* comma = strchr(ptr, ',');
  3708. if(comma == NULL)
  3709. {
  3710. oubuf.append(ptr);
  3711. ptr = NULL;
  3712. }
  3713. else
  3714. {
  3715. oubuf.append(comma - ptr, ptr);
  3716. ptr = comma + 1;
  3717. }
  3718. if(ptr != NULL)
  3719. createLdapBasedn(user, ptr, ptype);
  3720. addOrganizationalUnit(user, oubuf.str(), ptr, ptype);
  3721. }
  3722. virtual bool addOrganizationalUnit(ISecUser* user, const char* name, const char* basedn, SecPermissionType ptype)
  3723. {
  3724. if(name == NULL || basedn == NULL)
  3725. return false;
  3726. if(strchr(name, '/') != NULL || strchr(name, '=') != NULL)
  3727. return false;
  3728. StringBuffer dn;
  3729. dn.append("ou=").append(name).append(",").append(basedn);
  3730. char *ou_values[] = {(char*)name, NULL };
  3731. LDAPMod ou_attr =
  3732. {
  3733. LDAP_MOD_ADD,
  3734. "ou",
  3735. ou_values
  3736. };
  3737. char *name_values[] = {(char*)name, NULL };
  3738. LDAPMod name_attr =
  3739. {
  3740. LDAP_MOD_ADD,
  3741. "name",
  3742. name_values
  3743. };
  3744. char *oc_values[] = {"OrganizationalUnit", NULL };
  3745. LDAPMod oc_attr =
  3746. {
  3747. LDAP_MOD_ADD,
  3748. "objectClass",
  3749. oc_values
  3750. };
  3751. MemoryBuffer sdbuf;
  3752. Owned<CSecurityDescriptor> default_sd = NULL;
  3753. if(m_pp != NULL)
  3754. default_sd.setown(m_pp->createDefaultSD(*user, name, ptype));
  3755. if(default_sd != NULL)
  3756. sdbuf.append(default_sd->getDescriptor());
  3757. LDAPMod *attrs[6];
  3758. int ind = 0;
  3759. attrs[ind++] = &ou_attr;
  3760. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  3761. {
  3762. attrs[ind++] = &name_attr;
  3763. }
  3764. attrs[ind++] = &oc_attr;
  3765. LDAPMod sd_attr;
  3766. struct berval sd_val;
  3767. sd_val.bv_len = sdbuf.length();
  3768. sd_val.bv_val = (char*)sdbuf.toByteArray();
  3769. struct berval* sd_values[] = {&sd_val, NULL};
  3770. sd_attr.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
  3771. sd_attr.mod_type = (char*)m_ldapconfig->getSdFieldName();
  3772. sd_attr.mod_vals.modv_bvals = sd_values;
  3773. if(sdbuf.length() > 0)
  3774. attrs[ind++] = &sd_attr;
  3775. attrs[ind] = NULL;
  3776. Owned<ILdapConnection> lconn = m_connections->getConnection();
  3777. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  3778. int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  3779. if ( rc != LDAP_SUCCESS )
  3780. {
  3781. if(rc == LDAP_ALREADY_EXISTS)
  3782. {
  3783. //WARNLOG("Can't insert ou=%s,%s to Ldap Server, already exists", name, basedn);
  3784. return false;
  3785. }
  3786. else
  3787. {
  3788. throw MakeStringException(-1, "ldap_add_ext_s error for ou=%s,%s: %d %s", name, basedn, rc, ldap_err2string( rc ));
  3789. }
  3790. }
  3791. return true;
  3792. }
  3793. virtual void name2dn(SecResourceType rtype, const char* resourcename, const char* basedn, StringBuffer& ldapname)
  3794. {
  3795. StringBuffer namebuf;
  3796. const char* bptr = resourcename;
  3797. const char* sep = strstr(resourcename, "::");
  3798. while(sep != NULL)
  3799. {
  3800. if(sep > bptr)
  3801. {
  3802. StringBuffer onebuf;
  3803. onebuf.append("ou=").append(sep-bptr, bptr).append(",");
  3804. namebuf.insert(0, onebuf.str());
  3805. }
  3806. bptr = sep + 2;
  3807. sep = strstr(bptr, "::");
  3808. }
  3809. if(*bptr != '\0')
  3810. {
  3811. StringBuffer onebuf;
  3812. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY && (rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE))
  3813. onebuf.append("cn");
  3814. else
  3815. onebuf.append("ou");
  3816. onebuf.append("=").append(bptr).append(",");
  3817. namebuf.insert(0, onebuf.str());
  3818. }
  3819. namebuf.append(basedn);
  3820. LdapUtils::normalizeDn(namebuf.str(), m_ldapconfig->getBasedn(), ldapname);
  3821. }
  3822. virtual void name2rdn(SecResourceType rtype, const char* resourcename, StringBuffer& ldapname)
  3823. {
  3824. if(resourcename == NULL || *resourcename == '\0')
  3825. return;
  3826. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY && (rtype == RT_DEFAULT || rtype == RT_MODULE || rtype == RT_SERVICE))
  3827. ldapname.append("cn=");
  3828. else
  3829. ldapname.append("ou=");
  3830. const char* prevptr = resourcename;
  3831. const char* nextptr = strstr(resourcename, "::");
  3832. while(nextptr != NULL)
  3833. {
  3834. prevptr = nextptr + 2;
  3835. nextptr = strstr(prevptr, "::");
  3836. }
  3837. if(prevptr != NULL && *prevptr != '\0')
  3838. ldapname.append(prevptr);
  3839. }
  3840. virtual bool addResource(SecResourceType rtype, ISecUser& user, ISecResource* resource, SecPermissionType ptype, const char* basedn)
  3841. {
  3842. Owned<CSecurityDescriptor> template_sd = NULL;
  3843. const char* templatename = m_ldapconfig->getTemplateName();
  3844. if(templatename != NULL && *templatename != '\0')
  3845. {
  3846. IArrayOf<CSecurityDescriptor> sdlist;
  3847. template_sd.setown(new CSecurityDescriptor(templatename));
  3848. sdlist.append(*LINK(template_sd));
  3849. if(basedn && *basedn)
  3850. getSecurityDescriptors(sdlist, basedn);
  3851. else
  3852. getSecurityDescriptors(rtype, sdlist);
  3853. }
  3854. Owned<CSecurityDescriptor> default_sd = NULL;
  3855. if(template_sd != NULL && template_sd->getDescriptor().length() > 0)
  3856. {
  3857. MemoryBuffer template_sd_buf;
  3858. template_sd_buf.append(template_sd->getDescriptor());
  3859. if(m_pp != NULL)
  3860. default_sd.setown(m_pp->createDefaultSD(user, resource, template_sd_buf));
  3861. }
  3862. else
  3863. {
  3864. if(m_pp != NULL)
  3865. default_sd.setown(m_pp->createDefaultSD(user, resource, ptype));
  3866. }
  3867. return addResource(rtype, user, resource, ptype, basedn, default_sd.get());
  3868. }
  3869. virtual bool addResource(SecResourceType rtype, ISecUser& user, ISecResource* resource, SecPermissionType ptype, const char* basedn, CSecurityDescriptor* default_sd, bool lessException=true)
  3870. {
  3871. if(resource == NULL)
  3872. return true;
  3873. char* resourcename = (char*)resource->getName();
  3874. if(resourcename == NULL)
  3875. {
  3876. DBGLOG("can't add resource, empty resource name");
  3877. return false;
  3878. }
  3879. const char* rbasedn;
  3880. StringBuffer rbasednbuf;
  3881. if(basedn == NULL)
  3882. rbasedn = m_ldapconfig->getResourceBasedn(rtype);
  3883. else
  3884. {
  3885. LdapUtils::normalizeDn(basedn, m_ldapconfig->getBasedn(), rbasednbuf);
  3886. rbasedn = rbasednbuf.str();
  3887. }
  3888. if(rbasedn == NULL || *rbasedn == '\0')
  3889. {
  3890. DBGLOG("Can't add resource, corresponding resource basedn is not defined");
  3891. return false;
  3892. }
  3893. if(strchr(resourcename, '/') != NULL || strchr(resourcename, '=') != NULL)
  3894. return false;
  3895. if(rtype == RT_FILE_SCOPE || rtype == RT_WORKUNIT_SCOPE)
  3896. {
  3897. StringBuffer extbuf;
  3898. name2dn(rtype, resourcename, rbasedn, extbuf);
  3899. createLdapBasedn(&user, extbuf.str(), ptype);
  3900. return true;
  3901. }
  3902. LdapServerType servertype = m_ldapconfig->getServerType();
  3903. char* description = (char*)((CLdapSecResource*)resource)->getDescription();
  3904. StringBuffer dn;
  3905. char *fieldname, *oc_name;
  3906. if(servertype == ACTIVE_DIRECTORY)
  3907. {
  3908. fieldname = "cn";
  3909. oc_name = "Volume";
  3910. }
  3911. else
  3912. {
  3913. fieldname = "ou";
  3914. oc_name = "OrganizationalUnit";
  3915. }
  3916. dn.append(fieldname).append("=").append(resourcename).append(",");
  3917. dn.append(rbasedn);
  3918. char *cn_values[] = {resourcename, NULL };
  3919. LDAPMod cn_attr =
  3920. {
  3921. LDAP_MOD_ADD,
  3922. fieldname,
  3923. cn_values
  3924. };
  3925. char *oc_values[] = {oc_name, NULL };
  3926. LDAPMod oc_attr =
  3927. {
  3928. LDAP_MOD_ADD,
  3929. "objectClass",
  3930. oc_values
  3931. };
  3932. char* uncname_values[] = {resourcename, NULL};
  3933. LDAPMod uncname_attr =
  3934. {
  3935. LDAP_MOD_ADD,
  3936. "uNCName",
  3937. uncname_values
  3938. };
  3939. StringBuffer descriptionbuf;
  3940. if(description && *description)
  3941. descriptionbuf.append(description);
  3942. else
  3943. descriptionbuf.appendf("Access to %s", resourcename);
  3944. char* description_values[] = {(char*)descriptionbuf.str(), NULL};
  3945. LDAPMod description_attr =
  3946. {
  3947. LDAP_MOD_ADD,
  3948. "description",
  3949. description_values
  3950. };
  3951. Owned<CSecurityDescriptor> template_sd = NULL;
  3952. const char* templatename = m_ldapconfig->getTemplateName();
  3953. if(templatename != NULL && *templatename != '\0')
  3954. {
  3955. IArrayOf<CSecurityDescriptor> sdlist;
  3956. template_sd.setown(new CSecurityDescriptor(templatename));
  3957. sdlist.append(*LINK(template_sd));
  3958. getSecurityDescriptors(rtype, sdlist);
  3959. }
  3960. int numberOfSegs = 0;
  3961. if(default_sd != NULL)
  3962. {
  3963. numberOfSegs = m_pp->sdSegments(default_sd);
  3964. }
  3965. LDAPMod **attrs = (LDAPMod**)(alloca((5+numberOfSegs)*sizeof(LDAPMod*)));
  3966. int ind = 0;
  3967. attrs[ind++] = &cn_attr;
  3968. attrs[ind++] = &oc_attr;
  3969. attrs[ind++] = &description_attr;
  3970. if(servertype == ACTIVE_DIRECTORY)
  3971. {
  3972. attrs[ind++] = &uncname_attr;
  3973. }
  3974. LDAPMod sd_attr;
  3975. if(default_sd != NULL)
  3976. {
  3977. struct berval** sd_values = (struct berval**)alloca(sizeof(struct berval*)*(numberOfSegs+1));
  3978. MemoryBuffer& sdbuf = default_sd->getDescriptor();
  3979. // Active Directory acutally has only one segment.
  3980. if(servertype == ACTIVE_DIRECTORY)
  3981. {
  3982. struct berval* sd_val = (struct berval*)alloca(sizeof(struct berval));
  3983. sd_val->bv_len = sdbuf.length();
  3984. sd_val->bv_val = (char*)sdbuf.toByteArray();
  3985. sd_values[0] = sd_val;
  3986. sd_values[1] = NULL;
  3987. sd_attr.mod_type = "ntSecurityDescriptor";
  3988. }
  3989. else
  3990. {
  3991. const char* bbptr = sdbuf.toByteArray();
  3992. const char* bptr = sdbuf.toByteArray();
  3993. int sdbuflen = sdbuf.length();
  3994. int segind;
  3995. for(segind = 0; segind < numberOfSegs; segind++)
  3996. {
  3997. if(bptr - bbptr >= sdbuflen)
  3998. break;
  3999. while(*bptr == '\0' && (bptr - bbptr) < sdbuflen)
  4000. bptr++;
  4001. const char* eptr = bptr;
  4002. while(*eptr != '\0' && (eptr - bbptr) < sdbuflen)
  4003. eptr++;
  4004. struct berval* sd_val = (struct berval*)alloca(sizeof(struct berval));
  4005. sd_val->bv_len = eptr - bptr;
  4006. sd_val->bv_val = (char*)bptr;
  4007. sd_values[segind] = sd_val;
  4008. bptr = eptr + 1;
  4009. }
  4010. sd_values[segind] = NULL;
  4011. sd_attr.mod_type = (char*)m_ldapconfig->getSdFieldName();
  4012. }
  4013. sd_attr.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
  4014. sd_attr.mod_vals.modv_bvals = sd_values;
  4015. attrs[ind++] = &sd_attr;
  4016. }
  4017. attrs[ind] = NULL;
  4018. Owned<ILdapConnection> lconn = m_connections->getConnection();
  4019. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  4020. int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  4021. if ( rc != LDAP_SUCCESS )
  4022. {
  4023. if(rc == LDAP_ALREADY_EXISTS)
  4024. {
  4025. //WARNLOG("Can't insert %s to Ldap Server, already exists", resourcename);
  4026. if(lessException)
  4027. return false;
  4028. else
  4029. throw MakeStringException(-1, "Can't insert %s, already exists", resourcename);
  4030. }
  4031. else
  4032. {
  4033. throw MakeStringException(-1, "ldap_add_ext_s error for %s: %d %s", resourcename, rc, ldap_err2string( rc ));
  4034. }
  4035. }
  4036. return true;
  4037. }
  4038. virtual bool enableUser(ISecUser* user, const char* dn, LDAP* ld)
  4039. {
  4040. const char* username = user->getName();
  4041. StringBuffer filter;
  4042. filter.append("sAMAccountName=").append(username);
  4043. char *attribute, **values = NULL;
  4044. BerElement *ber;
  4045. LDAPMessage *searchResult, *message;
  4046. TIMEVAL timeOut = {LDAPTIMEOUT,0};
  4047. char *attrs[] = {"userAccountControl", NULL};
  4048. int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT, &searchResult );
  4049. if ( rc != LDAP_SUCCESS )
  4050. {
  4051. DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
  4052. return false;
  4053. }
  4054. StringBuffer act_ctrl;
  4055. message = LdapFirstEntry( ld, searchResult);
  4056. if(searchResult != NULL)
  4057. {
  4058. for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
  4059. attribute != NULL;
  4060. attribute = ldap_next_attribute( ld, searchResult,ber))
  4061. {
  4062. if(stricmp(attribute, "userAccountControl") != 0)
  4063. continue;
  4064. if (( values = ldap_get_values( ld, message, attribute)) != NULL )
  4065. {
  4066. char* val = values[0];
  4067. act_ctrl.append(val);
  4068. ldap_value_free( values );
  4069. break;
  4070. }
  4071. }
  4072. ber_free(ber, 0);
  4073. ldap_msgfree( searchResult );
  4074. }
  4075. if(act_ctrl.length() == 0)
  4076. {
  4077. DBGLOG("enableUser: userAccountControl doesn't exist");
  4078. return false;
  4079. }
  4080. unsigned act_ctrl_val = atoi(act_ctrl.str());
  4081. // UF_ACCOUNTDISABLE 0x0002
  4082. act_ctrl_val &= 0xFFFFFFFD;
  4083. // UF_DONT_EXPIRE_PASSWD 0x10000
  4084. act_ctrl_val |= 0x10000;
  4085. StringBuffer new_act_ctrl;
  4086. new_act_ctrl.append(act_ctrl_val);
  4087. char *ctrl_values[] = {(char*)new_act_ctrl.str(), NULL};
  4088. LDAPMod ctrl_attr = {
  4089. LDAP_MOD_REPLACE,
  4090. "userAccountControl",
  4091. ctrl_values
  4092. };
  4093. LDAPMod *cattrs[2];
  4094. cattrs[0] = &ctrl_attr;
  4095. cattrs[1] = NULL;
  4096. rc = ldap_modify_ext_s(ld, (char*)dn, cattrs, NULL, NULL);
  4097. if ( rc != LDAP_SUCCESS )
  4098. {
  4099. throw MakeStringException(-1, "error enableUser %s, ldap_modify_ext_s error: %s", username, ldap_err2string( rc ));
  4100. }
  4101. // set the password.
  4102. Owned<ISecUser> tmpuser = new CLdapSecUser(user->getName(), "");
  4103. const char* passwd = user->credentials().getPassword();
  4104. if(passwd == NULL || *passwd == '\0')
  4105. passwd = "password";
  4106. updateUser(*tmpuser, passwd);
  4107. return true;
  4108. }
  4109. virtual bool addUser(ISecUser& user)
  4110. {
  4111. const char* username = user.getName();
  4112. if(username == NULL || *username == '\0')
  4113. {
  4114. DBGLOG("Can't add user, username not set");
  4115. return false;
  4116. }
  4117. const char* fname = user.getFirstName();
  4118. const char* lname = user.getLastName();
  4119. if((lname == NULL || *lname == '\0') && (fname == NULL || *fname == '\0' || m_ldapconfig->getServerType() == IPLANET))
  4120. lname = username;
  4121. const char* fullname = user.getFullName();
  4122. StringBuffer fullname_buf;
  4123. if(fullname == NULL || *fullname == '\0')
  4124. {
  4125. if(fname != NULL && *fname != '\0')
  4126. {
  4127. fullname_buf.append(fname);
  4128. if(lname != NULL && *lname != '\0')
  4129. fullname_buf.append(" ");
  4130. }
  4131. if(lname != NULL && *lname != '\0')
  4132. fullname_buf.append(lname);
  4133. if(fullname_buf.length() == 0)
  4134. {
  4135. fullname_buf.append(username);
  4136. }
  4137. fullname = fullname_buf.str();
  4138. }
  4139. StringBuffer dn;
  4140. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  4141. {
  4142. dn.append("cn=").append(fullname).append(",");
  4143. }
  4144. else
  4145. {
  4146. dn.append("uid=").append(user.getName()).append(",");
  4147. }
  4148. dn.append(m_ldapconfig->getUserBasedn());
  4149. char* oc_name;
  4150. char* act_fieldname;
  4151. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  4152. {
  4153. oc_name = "User";
  4154. act_fieldname = "sAMAccountName";
  4155. }
  4156. else
  4157. {
  4158. oc_name = "inetorgperson";
  4159. act_fieldname = "uid";
  4160. }
  4161. char *cn_values[] = {(char*)fullname, NULL };
  4162. LDAPMod cn_attr =
  4163. {
  4164. LDAP_MOD_ADD,
  4165. "cn",
  4166. cn_values
  4167. };
  4168. char *oc_values[] = {oc_name, NULL};
  4169. LDAPMod oc_attr =
  4170. {
  4171. LDAP_MOD_ADD,
  4172. "objectClass",
  4173. oc_values
  4174. };
  4175. char *gn_values[] = { (char*)fname, NULL };
  4176. LDAPMod gn_attr = {
  4177. LDAP_MOD_ADD,
  4178. "givenName",
  4179. gn_values
  4180. };
  4181. char *sn_values[] = { (char*)lname, NULL };
  4182. LDAPMod sn_attr = {
  4183. LDAP_MOD_ADD,
  4184. "sn",
  4185. sn_values
  4186. };
  4187. char* actname_values[] = {(char*)username, NULL};
  4188. LDAPMod actname_attr =
  4189. {
  4190. LDAP_MOD_ADD,
  4191. act_fieldname,
  4192. actname_values
  4193. };
  4194. const char* passwd = user.credentials().getPassword();
  4195. if(passwd == NULL || *passwd == '\0')
  4196. passwd = "password";
  4197. char* passwd_values[] = {(char*)passwd, NULL};
  4198. LDAPMod passwd_attr =
  4199. {
  4200. LDAP_MOD_ADD,
  4201. "userpassword",
  4202. passwd_values
  4203. };
  4204. char *dispname_values[] = {(char*)fullname, NULL };
  4205. LDAPMod dispname_attr =
  4206. {
  4207. LDAP_MOD_ADD,
  4208. "displayName",
  4209. dispname_values
  4210. };
  4211. char* username_values[] = {(char*)username, NULL};
  4212. LDAPMod username_attr =
  4213. {
  4214. LDAP_MOD_ADD,
  4215. "userPrincipalName",
  4216. username_values
  4217. };
  4218. LDAPMod *attrs[8];
  4219. int ind = 0;
  4220. attrs[ind++] = &cn_attr;
  4221. attrs[ind++] = &oc_attr;
  4222. if(fname != NULL && *fname != '\0')
  4223. attrs[ind++] = &gn_attr;
  4224. if(lname != NULL && *lname != '\0')
  4225. attrs[ind++] = &sn_attr;
  4226. attrs[ind++] = &actname_attr;
  4227. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  4228. {
  4229. attrs[ind++] = &username_attr;
  4230. attrs[ind++] = &dispname_attr;
  4231. }
  4232. else
  4233. {
  4234. attrs[ind++] = &passwd_attr;
  4235. }
  4236. attrs[ind] = NULL;
  4237. Owned<ILdapConnection> lconn = m_connections->getConnection();
  4238. LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
  4239. int rc = ldap_add_ext_s(ld, (char*)dn.str(), attrs, NULL, NULL);
  4240. if ( rc != LDAP_SUCCESS )
  4241. {
  4242. if(rc == LDAP_ALREADY_EXISTS)
  4243. {
  4244. DBGLOG("can't add user %s, already exists", username);
  4245. throw MakeStringException(-1, "can't add user %s, already exists", username);
  4246. }
  4247. else
  4248. {
  4249. DBGLOG("error addUser %s, ldap_add_ext_s error: %s", username, ldap_err2string( rc ));
  4250. throw MakeStringException(-1, "error addUser %s, ldap_add_ext_s error: %s", username, ldap_err2string( rc ));
  4251. }
  4252. }
  4253. if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
  4254. {
  4255. try
  4256. {
  4257. return enableUser(&user, dn.str(), ld);
  4258. }
  4259. catch(...)
  4260. {
  4261. deleteUser(&user);
  4262. throw;
  4263. }
  4264. }
  4265. return true;
  4266. }
  4267. };
  4268. int LdapUtils::getServerInfo(const char* ldapserver, int ldapport, StringBuffer& domainDN, LdapServerType& stype, const char* domainname)
  4269. {
  4270. stype = LDAPSERVER_UNKNOWN;
  4271. LDAP* ld = LdapInit("ldap", ldapserver, ldapport, 636);
  4272. if(ld == NULL)
  4273. {
  4274. ERRLOG("ldap init error");
  4275. return false;
  4276. }
  4277. int err = LdapSimpleBind(ld, NULL, NULL);
  4278. if(err != LDAP_SUCCESS)
  4279. {
  4280. DBGLOG("ldap anonymous bind error (%d) - %s", err, ldap_err2string(err));
  4281. // for new versions of openldap, version 2.2.*
  4282. if(err == LDAP_PROTOCOL_ERROR)
  4283. DBGLOG("If you're trying to connect to an OpenLdap server, make sure you have \"allow bind_v2\" enabled in slapd.conf");
  4284. return err;
  4285. }
  4286. LDAPMessage* msg = NULL;
  4287. char* attrs[] = {"namingContexts", NULL};
  4288. err = ldap_search_s(ld, NULL, LDAP_SCOPE_BASE, "objectClass=*", attrs, false, &msg);
  4289. if(err != LDAP_SUCCESS)
  4290. {
  4291. DBGLOG("ldap_search_s error: %s", ldap_err2string( err ));
  4292. return err;
  4293. }
  4294. LDAPMessage* entry = LdapFirstEntry(ld, msg);
  4295. if(entry != NULL)
  4296. {
  4297. char** domains = ldap_get_values(ld, entry, "namingContexts");
  4298. if(domains != NULL)
  4299. {
  4300. int i = 0;
  4301. char* curdn;
  4302. StringBuffer onedn;
  4303. while((curdn = domains[i]) != NULL)
  4304. {
  4305. if(*curdn != '\0' && (strncmp(curdn, "dc=", 3) == 0 || strncmp(curdn, "DC=", 3) == 0))
  4306. {
  4307. if(domainDN.length() == 0)
  4308. {
  4309. StringBuffer curdomain;
  4310. LdapUtils::getName(curdn, curdomain);
  4311. if(onedn.length() == 0)
  4312. onedn.append(curdomain.str());
  4313. if(!domainname || !*domainname || stricmp(curdomain.str(), domainname) == 0)
  4314. domainDN.append(curdn);
  4315. }
  4316. }
  4317. else if(*curdn != '\0' && strcmp(curdn, "o=NetscapeRoot") == 0)
  4318. stype = IPLANET;
  4319. i++;
  4320. }
  4321. if(domainDN.length() == 0)
  4322. domainDN.append(onedn.str());
  4323. ldap_value_free(domains);
  4324. if(stype == LDAPSERVER_UNKNOWN)
  4325. {
  4326. if(i <= 1)
  4327. stype = OPEN_LDAP;
  4328. else
  4329. stype = ACTIVE_DIRECTORY;
  4330. }
  4331. }
  4332. }
  4333. ldap_msgfree(msg);
  4334. ldap_unbind(ld);
  4335. return err;
  4336. }
  4337. #ifdef _WIN32
  4338. bool verifyServerCert(LDAP* ld, PCCERT_CONTEXT pServerCert)
  4339. {
  4340. return true;
  4341. }
  4342. #endif
  4343. ILdapClient* createLdapClient(IPropertyTree* cfg)
  4344. {
  4345. return new CLdapClient(cfg);
  4346. }