ldap.c 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Amitay Isaacs <amitay@w-o-i.com> |
  14. | Eric Warnke <ericw@albany.edu> |
  15. | Rasmus Lerdorf <rasmus@php.net> |
  16. | Gerrit Thomson <334647@swin.edu.au> |
  17. | Jani Taskinen <sniper@iki.fi> |
  18. | Stig Venaas <venaas@uninett.no> |
  19. | Doug Goldstein <cardoe@cardoe.com> |
  20. | Côme Chilliet <mcmic@php.net> |
  21. | PHP 4.0 updates: Zeev Suraski <zeev@php.net> |
  22. +----------------------------------------------------------------------+
  23. */
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27. #include "php.h"
  28. #include "php_ini.h"
  29. #include <stddef.h>
  30. #include "ext/standard/dl.h"
  31. #include "php_ldap.h"
  32. #include "ldap_arginfo.h"
  33. #ifdef PHP_WIN32
  34. #include <string.h>
  35. #include "config.w32.h"
  36. #undef WINDOWS
  37. #undef strcasecmp
  38. #undef strncasecmp
  39. #define WINSOCK 1
  40. #define __STDC__ 1
  41. #endif
  42. #include "ext/standard/info.h"
  43. #ifdef HAVE_LDAP_SASL
  44. #include <sasl/sasl.h>
  45. #endif
  46. #define PHP_LDAP_ESCAPE_FILTER 0x01
  47. #define PHP_LDAP_ESCAPE_DN 0x02
  48. #if defined(LDAP_CONTROL_PAGEDRESULTS) && !defined(HAVE_LDAP_CONTROL_FIND)
  49. LDAPControl *ldap_control_find( const char *oid, LDAPControl **ctrls, LDAPControl ***nextctrlp)
  50. {
  51. assert(nextctrlp == NULL);
  52. return ldap_find_control(oid, ctrls);
  53. }
  54. #endif
  55. #if !defined(LDAP_API_FEATURE_X_OPENLDAP)
  56. void ldap_memvfree(void **v)
  57. {
  58. ldap_value_free((char **)v);
  59. }
  60. #endif
  61. typedef struct {
  62. LDAP *link;
  63. #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
  64. zval rebindproc;
  65. #endif
  66. zend_object std;
  67. } ldap_linkdata;
  68. typedef struct {
  69. LDAPMessage *result;
  70. zend_object std;
  71. } ldap_resultdata;
  72. typedef struct {
  73. LDAPMessage *data;
  74. BerElement *ber;
  75. zval res;
  76. zend_object std;
  77. } ldap_result_entry;
  78. ZEND_DECLARE_MODULE_GLOBALS(ldap)
  79. static PHP_GINIT_FUNCTION(ldap);
  80. static zend_class_entry *ldap_link_ce, *ldap_result_ce, *ldap_result_entry_ce;
  81. static zend_object_handlers ldap_link_object_handlers, ldap_result_object_handlers, ldap_result_entry_object_handlers;
  82. #ifdef COMPILE_DL_LDAP
  83. #ifdef ZTS
  84. ZEND_TSRMLS_CACHE_DEFINE()
  85. #endif
  86. ZEND_GET_MODULE(ldap)
  87. #endif
  88. static inline ldap_linkdata *ldap_link_from_obj(zend_object *obj) {
  89. return (ldap_linkdata *)((char *)(obj) - XtOffsetOf(ldap_linkdata, std));
  90. }
  91. #define Z_LDAP_LINK_P(zv) ldap_link_from_obj(Z_OBJ_P(zv))
  92. static zend_object *ldap_link_create_object(zend_class_entry *class_type) {
  93. ldap_linkdata *intern = zend_object_alloc(sizeof(ldap_linkdata), class_type);
  94. zend_object_std_init(&intern->std, class_type);
  95. object_properties_init(&intern->std, class_type);
  96. intern->std.handlers = &ldap_link_object_handlers;
  97. return &intern->std;
  98. }
  99. static zend_function *ldap_link_get_constructor(zend_object *object) {
  100. zend_throw_error(NULL, "Cannot directly construct LDAP\\Connection, use ldap_create() instead");
  101. return NULL;
  102. }
  103. static void ldap_link_free(ldap_linkdata *ld)
  104. {
  105. /* We use ldap_destroy rather than ldap_unbind here, because ldap_unbind
  106. * will skip the destructor entirely if a critical client control is set. */
  107. ldap_destroy(ld->link);
  108. ld->link = NULL;
  109. #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
  110. zval_ptr_dtor(&ld->rebindproc);
  111. #endif
  112. LDAPG(num_links)--;
  113. }
  114. static void ldap_link_free_obj(zend_object *obj)
  115. {
  116. ldap_linkdata *ld = ldap_link_from_obj(obj);
  117. if (ld->link) {
  118. ldap_link_free(ld);
  119. }
  120. zend_object_std_dtor(&ld->std);
  121. }
  122. static inline ldap_resultdata *ldap_result_from_obj(zend_object *obj) {
  123. return (ldap_resultdata *)((char *)(obj) - XtOffsetOf(ldap_resultdata, std));
  124. }
  125. #define Z_LDAP_RESULT_P(zv) ldap_result_from_obj(Z_OBJ_P(zv))
  126. static zend_object *ldap_result_create_object(zend_class_entry *class_type) {
  127. ldap_resultdata *intern = zend_object_alloc(sizeof(ldap_resultdata), class_type);
  128. zend_object_std_init(&intern->std, class_type);
  129. object_properties_init(&intern->std, class_type);
  130. intern->std.handlers = &ldap_result_object_handlers;
  131. return &intern->std;
  132. }
  133. static zend_function *ldap_result_get_constructor(zend_object *object) {
  134. zend_throw_error(NULL, "Cannot directly construct LDAP\\Result, use the dedicated functions instead");
  135. return NULL;
  136. }
  137. static void ldap_result_free(ldap_resultdata *result)
  138. {
  139. ldap_msgfree(result->result);
  140. result->result = NULL;
  141. }
  142. static void ldap_result_free_obj(zend_object *obj)
  143. {
  144. ldap_resultdata *result = ldap_result_from_obj(obj);
  145. if (result->result) {
  146. ldap_result_free(result);
  147. }
  148. zend_object_std_dtor(&result->std);
  149. }
  150. static inline ldap_result_entry *ldap_result_entry_from_obj(zend_object *obj) {
  151. return (ldap_result_entry *)((char *)(obj) - XtOffsetOf(ldap_result_entry, std));
  152. }
  153. #define Z_LDAP_RESULT_ENTRY_P(zv) ldap_result_entry_from_obj(Z_OBJ_P(zv))
  154. static zend_object *ldap_result_entry_create_object(zend_class_entry *class_type) {
  155. ldap_result_entry *intern = zend_object_alloc(sizeof(ldap_result_entry), class_type);
  156. zend_object_std_init(&intern->std, class_type);
  157. object_properties_init(&intern->std, class_type);
  158. intern->std.handlers = &ldap_result_entry_object_handlers;
  159. return &intern->std;
  160. }
  161. static zend_function *ldap_result_entry_get_constructor(zend_object *obj) {
  162. zend_throw_error(NULL, "Cannot directly construct LDAP\\ResultEntry, use the dedicated functions instead");
  163. return NULL;
  164. }
  165. static void ldap_result_entry_free_obj(zend_object *obj)
  166. {
  167. ldap_result_entry *entry = ldap_result_entry_from_obj(obj);
  168. if (entry->ber != NULL) {
  169. ber_free(entry->ber, 0);
  170. entry->ber = NULL;
  171. }
  172. zval_ptr_dtor(&entry->res);
  173. zend_object_std_dtor(&entry->std);
  174. }
  175. #define VERIFY_LDAP_LINK_CONNECTED(ld) \
  176. { \
  177. if (!ld->link) { \
  178. zend_throw_error(NULL, "LDAP connection has already been closed"); \
  179. RETURN_THROWS(); \
  180. } \
  181. }
  182. #define VERIFY_LDAP_RESULT_OPEN(lr) \
  183. { \
  184. if (!lr->result) { \
  185. zend_throw_error(NULL, "LDAP result has already been closed"); \
  186. RETURN_THROWS(); \
  187. } \
  188. }
  189. /* {{{ Parse controls from and to arrays */
  190. static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request)
  191. {
  192. array_init(array);
  193. add_assoc_string(array, "oid", ctrl->ldctl_oid);
  194. if (request) {
  195. /* iscritical field only makes sense in request controls (which may be obtained by ldap_get_option) */
  196. add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0));
  197. }
  198. /* If it is a known oid, parse to values */
  199. if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
  200. int expire = 0, grace = 0, rc;
  201. LDAPPasswordPolicyError pperr;
  202. zval value;
  203. rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr);
  204. if ( rc == LDAP_SUCCESS ) {
  205. array_init(&value);
  206. add_assoc_long(&value, "expire", expire);
  207. add_assoc_long(&value, "grace", grace);
  208. if ( pperr != PP_noError ) {
  209. add_assoc_long(&value, "error", pperr);
  210. }
  211. add_assoc_zval(array, "value", &value);
  212. } else {
  213. add_assoc_null(array, "value");
  214. }
  215. } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
  216. int lestimated, rc;
  217. struct berval lcookie = { 0L, NULL };
  218. zval value;
  219. if (ctrl->ldctl_value.bv_len) {
  220. /* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
  221. rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
  222. } else {
  223. /* ldap_parse_pageresponse_control will crash if value is empty */
  224. rc = -1;
  225. }
  226. if ( rc == LDAP_SUCCESS ) {
  227. array_init(&value);
  228. add_assoc_long(&value, "size", lestimated);
  229. add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len);
  230. add_assoc_zval(array, "value", &value);
  231. } else {
  232. add_assoc_null(array, "value");
  233. }
  234. if (lcookie.bv_val) {
  235. ldap_memfree(lcookie.bv_val);
  236. }
  237. } else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
  238. BerElement *ber;
  239. struct berval bv;
  240. ber = ber_init(&ctrl->ldctl_value);
  241. if (ber == NULL) {
  242. add_assoc_null(array, "value");
  243. } else if (ber_scanf(ber, "{m{" /*}}*/, &bv) == LBER_ERROR) {
  244. add_assoc_null(array, "value");
  245. } else {
  246. zval value;
  247. array_init(&value);
  248. add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len);
  249. while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) {
  250. int i;
  251. BerVarray vals = NULL;
  252. zval tmp;
  253. if (ber_scanf(ber, "[W]", &vals) == LBER_ERROR || vals == NULL)
  254. {
  255. break;
  256. }
  257. array_init(&tmp);
  258. for (i = 0; vals[i].bv_val != NULL; i++) {
  259. add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len);
  260. }
  261. add_assoc_zval(&value, bv.bv_val, &tmp);
  262. ber_bvarray_free(vals);
  263. }
  264. add_assoc_zval(array, "value", &value);
  265. }
  266. if (ber != NULL) {
  267. ber_free(ber, 1);
  268. }
  269. } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) {
  270. zval value;
  271. int errcode, rc;
  272. char* attribute;
  273. if (ctrl->ldctl_value.bv_len) {
  274. rc = ldap_parse_sortresponse_control(ld, ctrl, &errcode, &attribute);
  275. } else {
  276. rc = -1;
  277. }
  278. if ( rc == LDAP_SUCCESS ) {
  279. array_init(&value);
  280. add_assoc_long(&value, "errcode", errcode);
  281. if (attribute) {
  282. add_assoc_string(&value, "attribute", attribute);
  283. ldap_memfree(attribute);
  284. }
  285. add_assoc_zval(array, "value", &value);
  286. } else {
  287. add_assoc_null(array, "value");
  288. }
  289. } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) {
  290. int target, count, errcode, rc;
  291. struct berval *context;
  292. zval value;
  293. if (ctrl->ldctl_value.bv_len) {
  294. rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode);
  295. } else {
  296. rc = -1;
  297. }
  298. if ( rc == LDAP_SUCCESS ) {
  299. array_init(&value);
  300. add_assoc_long(&value, "target", target);
  301. add_assoc_long(&value, "count", count);
  302. add_assoc_long(&value, "errcode", errcode);
  303. if (context) {
  304. add_assoc_stringl(&value, "context", context->bv_val, context->bv_len);
  305. }
  306. add_assoc_zval(array, "value", &value);
  307. ber_bvfree(context);
  308. } else {
  309. add_assoc_null(array, "value");
  310. }
  311. } else {
  312. if (ctrl->ldctl_value.bv_len) {
  313. add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len);
  314. } else {
  315. add_assoc_null(array, "value");
  316. }
  317. }
  318. }
  319. static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array)
  320. {
  321. zval* val;
  322. zend_string *control_oid;
  323. int control_iscritical = 0, rc = LDAP_SUCCESS;
  324. char** ldap_attrs = NULL;
  325. LDAPSortKey** sort_keys = NULL;
  326. zend_string *tmpstring = NULL, **tmpstrings1 = NULL, **tmpstrings2 = NULL;
  327. size_t num_tmpstrings1 = 0, num_tmpstrings2 = 0;
  328. if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) {
  329. zend_value_error("%s(): Control must have an \"oid\" key", get_active_function_name());
  330. return -1;
  331. }
  332. control_oid = zval_get_string(val);
  333. if (EG(exception)) {
  334. return -1;
  335. }
  336. if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) {
  337. control_iscritical = zend_is_true(val);
  338. } else {
  339. control_iscritical = 0;
  340. }
  341. BerElement *ber = NULL;
  342. struct berval control_value = { 0L, NULL };
  343. int control_value_alloc = 0;
  344. if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) {
  345. if (Z_TYPE_P(val) != IS_ARRAY) {
  346. tmpstring = zval_get_string(val);
  347. if (EG(exception)) {
  348. rc = -1;
  349. goto failure;
  350. }
  351. control_value.bv_val = ZSTR_VAL(tmpstring);
  352. control_value.bv_len = ZSTR_LEN(tmpstring);
  353. } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
  354. zval* tmp;
  355. int pagesize = 1;
  356. struct berval cookie = { 0L, NULL };
  357. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
  358. pagesize = zval_get_long(tmp);
  359. }
  360. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) {
  361. tmpstring = zval_get_string(tmp);
  362. if (EG(exception)) {
  363. rc = -1;
  364. goto failure;
  365. }
  366. cookie.bv_val = ZSTR_VAL(tmpstring);
  367. cookie.bv_len = ZSTR_LEN(tmpstring);
  368. }
  369. /* ldap_create_page_control_value() allocates memory for control_value.bv_val */
  370. control_value_alloc = 1;
  371. rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
  372. if (rc != LDAP_SUCCESS) {
  373. php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
  374. }
  375. } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
  376. zval* tmp;
  377. zend_string* assert;
  378. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
  379. rc = -1;
  380. zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name());
  381. } else {
  382. assert = zval_get_string(tmp);
  383. if (EG(exception)) {
  384. rc = -1;
  385. goto failure;
  386. }
  387. /* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
  388. See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
  389. int success = LDAP_SUCCESS;
  390. ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
  391. /* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
  392. control_value_alloc = 1;
  393. rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
  394. if (rc != LDAP_SUCCESS) {
  395. php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
  396. }
  397. zend_string_release(assert);
  398. }
  399. } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VALUESRETURNFILTER) == 0) {
  400. zval* tmp;
  401. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
  402. rc = -1;
  403. zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name());
  404. } else {
  405. ber = ber_alloc_t(LBER_USE_DER);
  406. if (ber == NULL) {
  407. rc = -1;
  408. php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
  409. } else {
  410. tmpstring = zval_get_string(tmp);
  411. if (EG(exception)) {
  412. rc = -1;
  413. goto failure;
  414. }
  415. if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
  416. rc = -1;
  417. php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
  418. } else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
  419. rc = -1;
  420. }
  421. }
  422. }
  423. } else if ((strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_POST_READ) == 0)) {
  424. zval* tmp;
  425. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrs", sizeof("attrs") - 1)) == NULL) {
  426. rc = -1;
  427. zend_value_error("%s(): Control must have an \"attrs\" key", get_active_function_name());
  428. } else {
  429. ber = ber_alloc_t(LBER_USE_DER);
  430. if (ber == NULL) {
  431. rc = -1;
  432. php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
  433. } else {
  434. int num_attribs, i;
  435. zval* attr;
  436. num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp));
  437. ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
  438. tmpstrings1 = safe_emalloc(num_attribs, sizeof(zend_string*), 0);
  439. num_tmpstrings1 = 0;
  440. for (i = 0; i<num_attribs; i++) {
  441. if ((attr = zend_hash_index_find(Z_ARRVAL_P(tmp), i)) == NULL) {
  442. rc = -1;
  443. php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
  444. goto failure;
  445. }
  446. tmpstrings1[num_tmpstrings1] = zval_get_string(attr);
  447. if (EG(exception)) {
  448. rc = -1;
  449. goto failure;
  450. }
  451. ldap_attrs[i] = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
  452. ++num_tmpstrings1;
  453. }
  454. ldap_attrs[num_attribs] = NULL;
  455. ber_init2( ber, NULL, LBER_USE_DER );
  456. if (ber_printf(ber, "{v}", ldap_attrs) == -1) {
  457. rc = -1;
  458. php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
  459. } else {
  460. int err;
  461. err = ber_flatten2(ber, &control_value, control_value_alloc);
  462. if (err < 0) {
  463. rc = -1;
  464. php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
  465. }
  466. }
  467. }
  468. }
  469. } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_SORTREQUEST) == 0) {
  470. int num_keys, i;
  471. zval *sortkey, *tmp;
  472. num_keys = zend_hash_num_elements(Z_ARRVAL_P(val));
  473. sort_keys = safe_emalloc((num_keys+1), sizeof(LDAPSortKey*), 0);
  474. tmpstrings1 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
  475. tmpstrings2 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
  476. num_tmpstrings1 = 0;
  477. num_tmpstrings2 = 0;
  478. for (i = 0; i<num_keys; i++) {
  479. if ((sortkey = zend_hash_index_find(Z_ARRVAL_P(val), i)) == NULL) {
  480. rc = -1;
  481. php_error_docref(NULL, E_WARNING, "Failed to encode sort keys list");
  482. goto failure;
  483. }
  484. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "attr", sizeof("attr") - 1)) == NULL) {
  485. rc = -1;
  486. zend_value_error("%s(): Sort key list must have an \"attr\" key", get_active_function_name());
  487. goto failure;
  488. }
  489. sort_keys[i] = emalloc(sizeof(LDAPSortKey));
  490. tmpstrings1[num_tmpstrings1] = zval_get_string(tmp);
  491. if (EG(exception)) {
  492. rc = -1;
  493. goto failure;
  494. }
  495. sort_keys[i]->attributeType = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
  496. ++num_tmpstrings1;
  497. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) {
  498. tmpstrings2[num_tmpstrings2] = zval_get_string(tmp);
  499. if (EG(exception)) {
  500. rc = -1;
  501. goto failure;
  502. }
  503. sort_keys[i]->orderingRule = ZSTR_VAL(tmpstrings2[num_tmpstrings2]);
  504. ++num_tmpstrings2;
  505. } else {
  506. sort_keys[i]->orderingRule = NULL;
  507. }
  508. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) {
  509. sort_keys[i]->reverseOrder = zend_is_true(tmp);
  510. } else {
  511. sort_keys[i]->reverseOrder = 0;
  512. }
  513. }
  514. sort_keys[num_keys] = NULL;
  515. /* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
  516. control_value_alloc = 1;
  517. rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
  518. if (rc != LDAP_SUCCESS) {
  519. php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
  520. }
  521. } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
  522. zval* tmp;
  523. LDAPVLVInfo vlvInfo;
  524. struct berval attrValue;
  525. struct berval context;
  526. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "before", sizeof("before") - 1)) != NULL) {
  527. vlvInfo.ldvlv_before_count = zval_get_long(tmp);
  528. } else {
  529. rc = -1;
  530. zend_value_error("%s(): Array value for VLV control must have a \"before\" key", get_active_function_name());
  531. goto failure;
  532. }
  533. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "after", sizeof("after") - 1)) != NULL) {
  534. vlvInfo.ldvlv_after_count = zval_get_long(tmp);
  535. } else {
  536. rc = -1;
  537. zend_value_error("%s(): Array value for VLV control must have an \"after\" key", get_active_function_name());
  538. goto failure;
  539. }
  540. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) {
  541. tmpstring = zval_get_string(tmp);
  542. if (EG(exception)) {
  543. rc = -1;
  544. goto failure;
  545. }
  546. attrValue.bv_val = ZSTR_VAL(tmpstring);
  547. attrValue.bv_len = ZSTR_LEN(tmpstring);
  548. vlvInfo.ldvlv_attrvalue = &attrValue;
  549. } else if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "offset", sizeof("offset") - 1)) != NULL) {
  550. vlvInfo.ldvlv_attrvalue = NULL;
  551. vlvInfo.ldvlv_offset = zval_get_long(tmp);
  552. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "count", sizeof("count") - 1)) != NULL) {
  553. vlvInfo.ldvlv_count = zval_get_long(tmp);
  554. } else {
  555. rc = -1;
  556. zend_value_error("%s(): Array value for VLV control must have a \"count\" key", get_active_function_name());
  557. goto failure;
  558. }
  559. } else {
  560. rc = -1;
  561. zend_value_error("%s(): Array value for VLV control must have either an \"attrvalue\" or an \"offset\" key", get_active_function_name());
  562. goto failure;
  563. }
  564. if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) {
  565. tmpstring = zval_get_string(tmp);
  566. if (EG(exception)) {
  567. rc = -1;
  568. goto failure;
  569. }
  570. context.bv_val = ZSTR_VAL(tmpstring);
  571. context.bv_len = ZSTR_LEN(tmpstring);
  572. vlvInfo.ldvlv_context = &context;
  573. } else {
  574. vlvInfo.ldvlv_context = NULL;
  575. }
  576. /* ldap_create_vlv_control_value() allocates memory for control_value.bv_val */
  577. control_value_alloc = 1;
  578. rc = ldap_create_vlv_control_value(ld, &vlvInfo, &control_value);
  579. if (rc != LDAP_SUCCESS) {
  580. php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
  581. }
  582. } else {
  583. zend_type_error("%s(): Control OID %s cannot be of type array", get_active_function_name(), ZSTR_VAL(control_oid));
  584. rc = -1;
  585. }
  586. }
  587. if (rc == LDAP_SUCCESS) {
  588. rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
  589. }
  590. failure:
  591. zend_string_release(control_oid);
  592. if (tmpstring != NULL) {
  593. zend_string_release(tmpstring);
  594. }
  595. if (tmpstrings1 != NULL) {
  596. int i;
  597. for (i = 0; i < num_tmpstrings1; ++i) {
  598. zend_string_release(tmpstrings1[i]);
  599. }
  600. efree(tmpstrings1);
  601. }
  602. if (tmpstrings2 != NULL) {
  603. int i;
  604. for (i = 0; i < num_tmpstrings2; ++i) {
  605. zend_string_release(tmpstrings2[i]);
  606. }
  607. efree(tmpstrings2);
  608. }
  609. if (control_value.bv_val != NULL && control_value_alloc != 0) {
  610. ber_memfree(control_value.bv_val);
  611. }
  612. if (ber != NULL) {
  613. ber_free(ber, 1);
  614. }
  615. if (ldap_attrs != NULL) {
  616. efree(ldap_attrs);
  617. }
  618. if (sort_keys != NULL) {
  619. LDAPSortKey** sortp = sort_keys;
  620. while (*sortp) {
  621. efree(*sortp);
  622. sortp++;
  623. }
  624. efree(sort_keys);
  625. sort_keys = NULL;
  626. }
  627. if (rc == LDAP_SUCCESS) {
  628. return LDAP_SUCCESS;
  629. }
  630. /* Failed */
  631. *ctrl = NULL;
  632. return -1;
  633. }
  634. static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array, int request)
  635. {
  636. zval tmp1;
  637. LDAPControl **ctrlp;
  638. array = zend_try_array_init(array);
  639. if (!array) {
  640. return;
  641. }
  642. if (ctrls == NULL) {
  643. return;
  644. }
  645. ctrlp = ctrls;
  646. while (*ctrlp != NULL) {
  647. _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request);
  648. add_assoc_zval(array, (*ctrlp)->ldctl_oid, &tmp1);
  649. ctrlp++;
  650. }
  651. ldap_controls_free(ctrls);
  652. }
  653. static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array, uint32_t arg_num)
  654. {
  655. int ncontrols;
  656. LDAPControl** ctrlp, **ctrls = NULL;
  657. zval* ctrlarray;
  658. int error = 0;
  659. ncontrols = zend_hash_num_elements(Z_ARRVAL_P(array));
  660. ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
  661. *ctrls = NULL;
  662. ctrlp = ctrls;
  663. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), ctrlarray) {
  664. if (Z_TYPE_P(ctrlarray) != IS_ARRAY) {
  665. zend_argument_type_error(arg_num, "must contain only arrays, where each array is a control");
  666. error = 1;
  667. break;
  668. }
  669. if (_php_ldap_control_from_array(ld, ctrlp, ctrlarray) == LDAP_SUCCESS) {
  670. ++ctrlp;
  671. } else {
  672. error = 1;
  673. break;
  674. }
  675. *ctrlp = NULL;
  676. } ZEND_HASH_FOREACH_END();
  677. if (error) {
  678. ctrlp = ctrls;
  679. while (*ctrlp) {
  680. ldap_control_free(*ctrlp);
  681. ctrlp++;
  682. }
  683. efree(ctrls);
  684. ctrls = NULL;
  685. }
  686. return ctrls;
  687. }
  688. static void _php_ldap_controls_free (LDAPControl*** ctrls)
  689. {
  690. LDAPControl **ctrlp;
  691. if (*ctrls) {
  692. ctrlp = *ctrls;
  693. while (*ctrlp) {
  694. ldap_control_free(*ctrlp);
  695. ctrlp++;
  696. }
  697. efree(*ctrls);
  698. *ctrls = NULL;
  699. }
  700. }
  701. /* }}} */
  702. /* {{{ PHP_INI_BEGIN */
  703. PHP_INI_BEGIN()
  704. STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
  705. PHP_INI_END()
  706. /* }}} */
  707. /* {{{ PHP_GINIT_FUNCTION */
  708. static PHP_GINIT_FUNCTION(ldap)
  709. {
  710. #if defined(COMPILE_DL_LDAP) && defined(ZTS)
  711. ZEND_TSRMLS_CACHE_UPDATE();
  712. #endif
  713. ldap_globals->num_links = 0;
  714. }
  715. /* }}} */
  716. /* {{{ PHP_MINIT_FUNCTION */
  717. PHP_MINIT_FUNCTION(ldap)
  718. {
  719. REGISTER_INI_ENTRIES();
  720. ldap_link_ce = register_class_LDAP_Connection();
  721. ldap_link_ce->create_object = ldap_link_create_object;
  722. memcpy(&ldap_link_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  723. ldap_link_object_handlers.offset = XtOffsetOf(ldap_linkdata, std);
  724. ldap_link_object_handlers.free_obj = ldap_link_free_obj;
  725. ldap_link_object_handlers.get_constructor = ldap_link_get_constructor;
  726. ldap_link_object_handlers.clone_obj = NULL;
  727. ldap_link_object_handlers.compare = zend_objects_not_comparable;
  728. ldap_result_ce = register_class_LDAP_Result();
  729. ldap_result_ce->create_object = ldap_result_create_object;
  730. memcpy(&ldap_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  731. ldap_result_object_handlers.offset = XtOffsetOf(ldap_resultdata, std);
  732. ldap_result_object_handlers.free_obj = ldap_result_free_obj;
  733. ldap_result_object_handlers.get_constructor = ldap_result_get_constructor;
  734. ldap_result_object_handlers.clone_obj = NULL;
  735. ldap_result_object_handlers.compare = zend_objects_not_comparable;
  736. ldap_result_entry_ce = register_class_LDAP_ResultEntry();
  737. ldap_result_entry_ce->create_object = ldap_result_entry_create_object;
  738. memcpy(&ldap_result_entry_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  739. ldap_result_entry_object_handlers.offset = XtOffsetOf(ldap_result_entry, std);
  740. ldap_result_entry_object_handlers.free_obj = ldap_result_entry_free_obj;
  741. ldap_result_entry_object_handlers.get_constructor = ldap_result_entry_get_constructor;
  742. ldap_result_entry_object_handlers.clone_obj = NULL;
  743. ldap_result_entry_object_handlers.compare = zend_objects_not_comparable;
  744. /* Constants to be used with deref-parameter in php_ldap_do_search() */
  745. REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS);
  746. REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS);
  747. REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
  748. REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
  749. /* Constants to be used with ldap_modify_batch() */
  750. REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_ADD", LDAP_MODIFY_BATCH_ADD, CONST_PERSISTENT | CONST_CS);
  751. REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE", LDAP_MODIFY_BATCH_REMOVE, CONST_PERSISTENT | CONST_CS);
  752. REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE_ALL", LDAP_MODIFY_BATCH_REMOVE_ALL, CONST_PERSISTENT | CONST_CS);
  753. REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REPLACE", LDAP_MODIFY_BATCH_REPLACE, CONST_PERSISTENT | CONST_CS);
  754. REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_ATTRIB", LDAP_MODIFY_BATCH_ATTRIB, CONST_PERSISTENT | CONST_CS);
  755. REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_MODTYPE", LDAP_MODIFY_BATCH_MODTYPE, CONST_PERSISTENT | CONST_CS);
  756. REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_VALUES", LDAP_MODIFY_BATCH_VALUES, CONST_PERSISTENT | CONST_CS);
  757. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
  758. /* LDAP options */
  759. REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
  760. REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS);
  761. REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS);
  762. #ifdef LDAP_OPT_NETWORK_TIMEOUT
  763. REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_OPT_NETWORK_TIMEOUT, CONST_PERSISTENT | CONST_CS);
  764. #elif defined (LDAP_X_OPT_CONNECT_TIMEOUT)
  765. REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_X_OPT_CONNECT_TIMEOUT, CONST_PERSISTENT | CONST_CS);
  766. #endif
  767. #ifdef LDAP_OPT_TIMEOUT
  768. REGISTER_LONG_CONSTANT("LDAP_OPT_TIMEOUT", LDAP_OPT_TIMEOUT, CONST_PERSISTENT | CONST_CS);
  769. #endif
  770. REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS);
  771. REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS);
  772. REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);
  773. #ifdef LDAP_OPT_RESTART
  774. REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);
  775. #endif
  776. #ifdef LDAP_OPT_HOST_NAME
  777. REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);
  778. #endif
  779. REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);
  780. #ifdef LDAP_OPT_MATCHED_DN
  781. REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);
  782. #endif
  783. REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS);
  784. REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);
  785. #endif
  786. #ifdef LDAP_OPT_DEBUG_LEVEL
  787. REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);
  788. #endif
  789. #ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
  790. REGISTER_LONG_CONSTANT("LDAP_OPT_DIAGNOSTIC_MESSAGE", LDAP_OPT_DIAGNOSTIC_MESSAGE, CONST_PERSISTENT | CONST_CS);
  791. #endif
  792. #ifdef HAVE_LDAP_SASL
  793. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS);
  794. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS);
  795. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS);
  796. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS);
  797. #endif
  798. #ifdef LDAP_OPT_X_SASL_NOCANON
  799. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_NOCANON", LDAP_OPT_X_SASL_NOCANON, CONST_PERSISTENT | CONST_CS);
  800. #endif
  801. #ifdef LDAP_OPT_X_SASL_USERNAME
  802. REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_USERNAME", LDAP_OPT_X_SASL_USERNAME, CONST_PERSISTENT | CONST_CS);
  803. #endif
  804. #ifdef ORALDAP
  805. REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS);
  806. REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
  807. REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
  808. #endif
  809. #if (LDAP_API_VERSION > 2000)
  810. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_REQUIRE_CERT", LDAP_OPT_X_TLS_REQUIRE_CERT, CONST_PERSISTENT | CONST_CS);
  811. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_NEVER", LDAP_OPT_X_TLS_NEVER, CONST_PERSISTENT | CONST_CS);
  812. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_HARD", LDAP_OPT_X_TLS_HARD, CONST_PERSISTENT | CONST_CS);
  813. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_DEMAND", LDAP_OPT_X_TLS_DEMAND, CONST_PERSISTENT | CONST_CS);
  814. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_ALLOW", LDAP_OPT_X_TLS_ALLOW, CONST_PERSISTENT | CONST_CS);
  815. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_TRY", LDAP_OPT_X_TLS_TRY, CONST_PERSISTENT | CONST_CS);
  816. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CACERTDIR", LDAP_OPT_X_TLS_CACERTDIR, CONST_PERSISTENT | CONST_CS);
  817. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CACERTFILE", LDAP_OPT_X_TLS_CACERTFILE, CONST_PERSISTENT | CONST_CS);
  818. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CERTFILE", LDAP_OPT_X_TLS_CERTFILE, CONST_PERSISTENT | CONST_CS);
  819. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CIPHER_SUITE", LDAP_OPT_X_TLS_CIPHER_SUITE, CONST_PERSISTENT | CONST_CS);
  820. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_KEYFILE", LDAP_OPT_X_TLS_KEYFILE, CONST_PERSISTENT | CONST_CS);
  821. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_RANDOM_FILE", LDAP_OPT_X_TLS_RANDOM_FILE, CONST_PERSISTENT | CONST_CS);
  822. #endif
  823. #ifdef LDAP_OPT_X_TLS_CRLCHECK
  824. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRLCHECK", LDAP_OPT_X_TLS_CRLCHECK, CONST_PERSISTENT | CONST_CS);
  825. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_NONE", LDAP_OPT_X_TLS_CRL_NONE, CONST_PERSISTENT | CONST_CS);
  826. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_PEER", LDAP_OPT_X_TLS_CRL_PEER, CONST_PERSISTENT | CONST_CS);
  827. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_ALL", LDAP_OPT_X_TLS_CRL_ALL, CONST_PERSISTENT | CONST_CS);
  828. #endif
  829. #ifdef LDAP_OPT_X_TLS_DHFILE
  830. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_DHFILE", LDAP_OPT_X_TLS_DHFILE, CONST_PERSISTENT | CONST_CS);
  831. #endif
  832. #ifdef LDAP_OPT_X_TLS_CRLFILE
  833. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRLFILE", LDAP_OPT_X_TLS_CRLFILE, CONST_PERSISTENT | CONST_CS);
  834. #endif
  835. #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
  836. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_MIN", LDAP_OPT_X_TLS_PROTOCOL_MIN, CONST_PERSISTENT | CONST_CS);
  837. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_SSL2", LDAP_OPT_X_TLS_PROTOCOL_SSL2, CONST_PERSISTENT | CONST_CS);
  838. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_SSL3", LDAP_OPT_X_TLS_PROTOCOL_SSL3, CONST_PERSISTENT | CONST_CS);
  839. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_0", LDAP_OPT_X_TLS_PROTOCOL_TLS1_0, CONST_PERSISTENT | CONST_CS);
  840. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_1", LDAP_OPT_X_TLS_PROTOCOL_TLS1_1, CONST_PERSISTENT | CONST_CS);
  841. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_2", LDAP_OPT_X_TLS_PROTOCOL_TLS1_2, CONST_PERSISTENT | CONST_CS);
  842. #endif
  843. #ifdef LDAP_OPT_X_TLS_PACKAGE
  844. REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PACKAGE", LDAP_OPT_X_TLS_PACKAGE, CONST_PERSISTENT | CONST_CS);
  845. #endif
  846. #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
  847. REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_IDLE", LDAP_OPT_X_KEEPALIVE_IDLE, CONST_PERSISTENT | CONST_CS);
  848. REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_PROBES", LDAP_OPT_X_KEEPALIVE_PROBES, CONST_PERSISTENT | CONST_CS);
  849. REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_INTERVAL", LDAP_OPT_X_KEEPALIVE_INTERVAL, CONST_PERSISTENT | CONST_CS);
  850. #endif
  851. REGISTER_LONG_CONSTANT("LDAP_ESCAPE_FILTER", PHP_LDAP_ESCAPE_FILTER, CONST_PERSISTENT | CONST_CS);
  852. REGISTER_LONG_CONSTANT("LDAP_ESCAPE_DN", PHP_LDAP_ESCAPE_DN, CONST_PERSISTENT | CONST_CS);
  853. #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
  854. REGISTER_STRING_CONSTANT("LDAP_EXOP_START_TLS", LDAP_EXOP_START_TLS, CONST_PERSISTENT | CONST_CS);
  855. REGISTER_STRING_CONSTANT("LDAP_EXOP_MODIFY_PASSWD", LDAP_EXOP_MODIFY_PASSWD, CONST_PERSISTENT | CONST_CS);
  856. REGISTER_STRING_CONSTANT("LDAP_EXOP_REFRESH", LDAP_EXOP_REFRESH, CONST_PERSISTENT | CONST_CS);
  857. REGISTER_STRING_CONSTANT("LDAP_EXOP_WHO_AM_I", LDAP_EXOP_WHO_AM_I, CONST_PERSISTENT | CONST_CS);
  858. REGISTER_STRING_CONSTANT("LDAP_EXOP_TURN", LDAP_EXOP_TURN, CONST_PERSISTENT | CONST_CS);
  859. #endif
  860. /* LDAP Controls */
  861. /* standard track controls */
  862. #ifdef LDAP_CONTROL_MANAGEDSAIT
  863. /* RFC 3296 */
  864. REGISTER_STRING_CONSTANT("LDAP_CONTROL_MANAGEDSAIT", LDAP_CONTROL_MANAGEDSAIT, CONST_PERSISTENT | CONST_CS);
  865. #endif
  866. #ifdef LDAP_CONTROL_PROXY_AUTHZ
  867. /* RFC 4370 */
  868. REGISTER_STRING_CONSTANT("LDAP_CONTROL_PROXY_AUTHZ", LDAP_CONTROL_PROXY_AUTHZ, CONST_PERSISTENT | CONST_CS);
  869. #endif
  870. #ifdef LDAP_CONTROL_SUBENTRIES
  871. /* RFC 3672 */
  872. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SUBENTRIES", LDAP_CONTROL_SUBENTRIES, CONST_PERSISTENT | CONST_CS);
  873. #endif
  874. #ifdef LDAP_CONTROL_VALUESRETURNFILTER
  875. /* RFC 3876 */
  876. REGISTER_STRING_CONSTANT("LDAP_CONTROL_VALUESRETURNFILTER", LDAP_CONTROL_VALUESRETURNFILTER, CONST_PERSISTENT | CONST_CS);
  877. #endif
  878. #ifdef LDAP_CONTROL_ASSERT
  879. /* RFC 4528 */
  880. REGISTER_STRING_CONSTANT("LDAP_CONTROL_ASSERT", LDAP_CONTROL_ASSERT, CONST_PERSISTENT | CONST_CS);
  881. /* RFC 4527 */
  882. REGISTER_STRING_CONSTANT("LDAP_CONTROL_PRE_READ", LDAP_CONTROL_PRE_READ, CONST_PERSISTENT | CONST_CS);
  883. REGISTER_STRING_CONSTANT("LDAP_CONTROL_POST_READ", LDAP_CONTROL_POST_READ, CONST_PERSISTENT | CONST_CS);
  884. #endif
  885. #ifdef LDAP_CONTROL_SORTREQUEST
  886. /* RFC 2891 */
  887. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTREQUEST", LDAP_CONTROL_SORTREQUEST, CONST_PERSISTENT | CONST_CS);
  888. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTRESPONSE", LDAP_CONTROL_SORTRESPONSE, CONST_PERSISTENT | CONST_CS);
  889. #endif
  890. /* non-standard track controls */
  891. #ifdef LDAP_CONTROL_PAGEDRESULTS
  892. /* RFC 2696 */
  893. REGISTER_STRING_CONSTANT("LDAP_CONTROL_PAGEDRESULTS", LDAP_CONTROL_PAGEDRESULTS, CONST_PERSISTENT | CONST_CS);
  894. #endif
  895. #ifdef LDAP_CONTROL_AUTHZID_REQUEST
  896. /* RFC 3829 */
  897. REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_REQUEST", LDAP_CONTROL_AUTHZID_REQUEST, CONST_PERSISTENT | CONST_CS);
  898. REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_RESPONSE", LDAP_CONTROL_AUTHZID_RESPONSE, CONST_PERSISTENT | CONST_CS);
  899. #endif
  900. #ifdef LDAP_CONTROL_SYNC
  901. /* LDAP Content Synchronization Operation -- RFC 4533 */
  902. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC", LDAP_CONTROL_SYNC, CONST_PERSISTENT | CONST_CS);
  903. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_STATE", LDAP_CONTROL_SYNC_STATE, CONST_PERSISTENT | CONST_CS);
  904. REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_DONE", LDAP_CONTROL_SYNC_DONE, CONST_PERSISTENT | CONST_CS);
  905. #endif
  906. #ifdef LDAP_CONTROL_DONTUSECOPY
  907. /* LDAP Don't Use Copy Control (RFC 6171) */
  908. REGISTER_STRING_CONSTANT("LDAP_CONTROL_DONTUSECOPY", LDAP_CONTROL_DONTUSECOPY, CONST_PERSISTENT | CONST_CS);
  909. #endif
  910. #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
  911. /* Password policy Controls */
  912. REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYREQUEST", LDAP_CONTROL_PASSWORDPOLICYREQUEST, CONST_PERSISTENT | CONST_CS);
  913. REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYRESPONSE", LDAP_CONTROL_PASSWORDPOLICYRESPONSE, CONST_PERSISTENT | CONST_CS);
  914. #endif
  915. #ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES
  916. /* MS Active Directory controls */
  917. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_INCREMENTAL_VALUES", LDAP_CONTROL_X_INCREMENTAL_VALUES, CONST_PERSISTENT | CONST_CS);
  918. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_DOMAIN_SCOPE", LDAP_CONTROL_X_DOMAIN_SCOPE, CONST_PERSISTENT | CONST_CS);
  919. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_PERMISSIVE_MODIFY", LDAP_CONTROL_X_PERMISSIVE_MODIFY, CONST_PERSISTENT | CONST_CS);
  920. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_SEARCH_OPTIONS", LDAP_CONTROL_X_SEARCH_OPTIONS, CONST_PERSISTENT | CONST_CS);
  921. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_TREE_DELETE", LDAP_CONTROL_X_TREE_DELETE, CONST_PERSISTENT | CONST_CS);
  922. REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_EXTENDED_DN", LDAP_CONTROL_X_EXTENDED_DN, CONST_PERSISTENT | CONST_CS);
  923. #endif
  924. #ifdef LDAP_CONTROL_VLVREQUEST
  925. /* LDAP VLV */
  926. REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVREQUEST", LDAP_CONTROL_VLVREQUEST, CONST_PERSISTENT | CONST_CS);
  927. REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVRESPONSE", LDAP_CONTROL_VLVRESPONSE, CONST_PERSISTENT | CONST_CS);
  928. #endif
  929. ldap_module_entry.type = type;
  930. return SUCCESS;
  931. }
  932. /* }}} */
  933. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  934. PHP_MSHUTDOWN_FUNCTION(ldap)
  935. {
  936. UNREGISTER_INI_ENTRIES();
  937. return SUCCESS;
  938. }
  939. /* }}} */
  940. /* {{{ PHP_MINFO_FUNCTION */
  941. PHP_MINFO_FUNCTION(ldap)
  942. {
  943. char tmp[32];
  944. php_info_print_table_start();
  945. php_info_print_table_row(2, "LDAP Support", "enabled");
  946. if (LDAPG(max_links) == -1) {
  947. snprintf(tmp, 31, ZEND_LONG_FMT "/unlimited", LDAPG(num_links));
  948. } else {
  949. snprintf(tmp, 31, ZEND_LONG_FMT "/" ZEND_LONG_FMT, LDAPG(num_links), LDAPG(max_links));
  950. }
  951. php_info_print_table_row(2, "Total Links", tmp);
  952. #ifdef LDAP_API_VERSION
  953. snprintf(tmp, 31, "%d", LDAP_API_VERSION);
  954. php_info_print_table_row(2, "API Version", tmp);
  955. #endif
  956. #ifdef LDAP_VENDOR_NAME
  957. php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
  958. #endif
  959. #ifdef LDAP_VENDOR_VERSION
  960. snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
  961. php_info_print_table_row(2, "Vendor Version", tmp);
  962. #endif
  963. #ifdef HAVE_LDAP_SASL
  964. php_info_print_table_row(2, "SASL Support", "Enabled");
  965. #endif
  966. php_info_print_table_end();
  967. DISPLAY_INI_ENTRIES();
  968. }
  969. /* }}} */
  970. /* {{{ Connect to an LDAP server */
  971. PHP_FUNCTION(ldap_connect)
  972. {
  973. char *host = NULL;
  974. size_t hostlen = 0;
  975. zend_long port = LDAP_PORT;
  976. #ifdef HAVE_ORALDAP
  977. char *wallet = NULL, *walletpasswd = NULL;
  978. size_t walletlen = 0, walletpasswdlen = 0;
  979. zend_long authmode = GSLC_SSL_NO_AUTH;
  980. int ssl=0;
  981. #endif
  982. ldap_linkdata *ld;
  983. LDAP *ldap = NULL;
  984. #ifdef HAVE_ORALDAP
  985. if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
  986. WRONG_PARAM_COUNT;
  987. }
  988. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!lssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS) {
  989. RETURN_THROWS();
  990. }
  991. if (ZEND_NUM_ARGS() == 5) {
  992. ssl = 1;
  993. }
  994. #else
  995. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &host, &hostlen, &port) != SUCCESS) {
  996. RETURN_THROWS();
  997. }
  998. #endif
  999. if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
  1000. php_error_docref(NULL, E_WARNING, "Too many open links (" ZEND_LONG_FMT ")", LDAPG(num_links));
  1001. RETURN_FALSE;
  1002. }
  1003. object_init_ex(return_value, ldap_link_ce);
  1004. ld = Z_LDAP_LINK_P(return_value);
  1005. {
  1006. int rc = LDAP_SUCCESS;
  1007. char *url = host;
  1008. if (url && !ldap_is_ldap_url(url)) {
  1009. size_t urllen = hostlen + sizeof( "ldap://:65535" );
  1010. if (port <= 0 || port > 65535) {
  1011. zend_argument_value_error(2, "must be between 1 and 65535");
  1012. RETURN_THROWS();
  1013. }
  1014. url = emalloc(urllen);
  1015. snprintf( url, urllen, "ldap://%s:" ZEND_LONG_FMT, host, port );
  1016. }
  1017. #ifdef LDAP_API_FEATURE_X_OPENLDAP
  1018. /* ldap_init() is deprecated, use ldap_initialize() instead.
  1019. */
  1020. rc = ldap_initialize(&ldap, url);
  1021. #else /* ! LDAP_API_FEATURE_X_OPENLDAP */
  1022. /* ldap_init does not support URLs.
  1023. * We must try the original host and port information.
  1024. */
  1025. ldap = ldap_init(host, port);
  1026. if (ldap == NULL) {
  1027. zval_ptr_dtor(return_value);
  1028. php_error_docref(NULL, E_WARNING, "Could not create session handle");
  1029. RETURN_FALSE;
  1030. }
  1031. #endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
  1032. if (url != host) {
  1033. efree(url);
  1034. }
  1035. if (rc != LDAP_SUCCESS) {
  1036. zval_ptr_dtor(return_value);
  1037. php_error_docref(NULL, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
  1038. RETURN_FALSE;
  1039. }
  1040. }
  1041. if (ldap == NULL) {
  1042. zval_ptr_dtor(return_value);
  1043. RETURN_FALSE;
  1044. } else {
  1045. #ifdef HAVE_ORALDAP
  1046. if (ssl) {
  1047. if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
  1048. zval_ptr_dtor(return_value);
  1049. php_error_docref(NULL, E_WARNING, "SSL init failed");
  1050. RETURN_FALSE;
  1051. }
  1052. }
  1053. #endif
  1054. LDAPG(num_links)++;
  1055. ld->link = ldap;
  1056. }
  1057. }
  1058. /* }}} */
  1059. /* {{{ _get_lderrno */
  1060. static int _get_lderrno(LDAP *ldap)
  1061. {
  1062. #if LDAP_API_VERSION > 2000 || defined(HAVE_ORALDAP)
  1063. int lderr;
  1064. /* New versions of OpenLDAP do it this way */
  1065. ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
  1066. return lderr;
  1067. #else
  1068. return ldap->ld_errno;
  1069. #endif
  1070. }
  1071. /* }}} */
  1072. /* {{{ _set_lderrno */
  1073. static void _set_lderrno(LDAP *ldap, int lderr)
  1074. {
  1075. #if LDAP_API_VERSION > 2000 || defined(HAVE_ORALDAP)
  1076. /* New versions of OpenLDAP do it this way */
  1077. ldap_set_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
  1078. #else
  1079. ldap->ld_errno = lderr;
  1080. #endif
  1081. }
  1082. /* }}} */
  1083. /* {{{ Bind to LDAP directory */
  1084. PHP_FUNCTION(ldap_bind)
  1085. {
  1086. zval *link;
  1087. char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
  1088. size_t ldap_bind_dnlen, ldap_bind_pwlen;
  1089. ldap_linkdata *ld;
  1090. int rc;
  1091. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!", &link, ldap_link_ce, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) != SUCCESS) {
  1092. RETURN_THROWS();
  1093. }
  1094. ld = Z_LDAP_LINK_P(link);
  1095. VERIFY_LDAP_LINK_CONNECTED(ld);
  1096. if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
  1097. _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
  1098. zend_argument_type_error(2, "must not contain null bytes");
  1099. RETURN_THROWS();
  1100. }
  1101. if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
  1102. _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
  1103. zend_argument_type_error(3, "must not contain null bytes");
  1104. RETURN_THROWS();
  1105. }
  1106. {
  1107. #ifdef LDAP_API_FEATURE_X_OPENLDAP
  1108. /* ldap_simple_bind_s() is deprecated, use ldap_sasl_bind_s() instead.
  1109. */
  1110. struct berval cred;
  1111. cred.bv_val = ldap_bind_pw;
  1112. cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
  1113. rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
  1114. NULL, NULL, /* no controls right now */
  1115. NULL); /* we don't care about the server's credentials */
  1116. #else /* ! LDAP_API_FEATURE_X_OPENLDAP */
  1117. rc = ldap_simple_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw);
  1118. #endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
  1119. }
  1120. if ( rc != LDAP_SUCCESS) {
  1121. php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
  1122. RETURN_FALSE;
  1123. } else {
  1124. RETURN_TRUE;
  1125. }
  1126. }
  1127. /* }}} */
  1128. /* {{{ Bind to LDAP directory */
  1129. PHP_FUNCTION(ldap_bind_ext)
  1130. {
  1131. zval *serverctrls = NULL;
  1132. zval *link;
  1133. char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
  1134. size_t ldap_bind_dnlen, ldap_bind_pwlen;
  1135. ldap_linkdata *ld;
  1136. LDAPControl **lserverctrls = NULL;
  1137. ldap_resultdata *result;
  1138. LDAPMessage *ldap_res;
  1139. int rc;
  1140. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!a!", &link, ldap_link_ce, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &serverctrls) != SUCCESS) {
  1141. RETURN_THROWS();
  1142. }
  1143. ld = Z_LDAP_LINK_P(link);
  1144. VERIFY_LDAP_LINK_CONNECTED(ld);
  1145. if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
  1146. _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
  1147. zend_argument_type_error(2, "must not contain null bytes");
  1148. RETURN_THROWS();
  1149. }
  1150. if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
  1151. _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
  1152. zend_argument_type_error(3, "must not contain null bytes");
  1153. RETURN_THROWS();
  1154. }
  1155. if (serverctrls) {
  1156. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
  1157. if (lserverctrls == NULL) {
  1158. RETVAL_FALSE;
  1159. goto cleanup;
  1160. }
  1161. }
  1162. {
  1163. /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */
  1164. struct berval cred;
  1165. int msgid;
  1166. cred.bv_val = ldap_bind_pw;
  1167. cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
  1168. /* asynchronous call */
  1169. rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
  1170. lserverctrls, NULL, &msgid);
  1171. if (rc != LDAP_SUCCESS ) {
  1172. php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s (%d)", ldap_err2string(rc), rc);
  1173. RETVAL_FALSE;
  1174. goto cleanup;
  1175. }
  1176. rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  1177. if (rc == -1) {
  1178. php_error_docref(NULL, E_WARNING, "Bind operation failed");
  1179. RETVAL_FALSE;
  1180. goto cleanup;
  1181. }
  1182. /* return a PHP control object */
  1183. object_init_ex(return_value, ldap_result_ce);
  1184. result = Z_LDAP_RESULT_P(return_value);
  1185. result->result = ldap_res;
  1186. }
  1187. cleanup:
  1188. if (lserverctrls) {
  1189. _php_ldap_controls_free(&lserverctrls);
  1190. }
  1191. return;
  1192. }
  1193. /* }}} */
  1194. #ifdef HAVE_LDAP_SASL
  1195. typedef struct {
  1196. char *mech;
  1197. char *realm;
  1198. char *authcid;
  1199. char *passwd;
  1200. char *authzid;
  1201. } php_ldap_bictx;
  1202. /* {{{ _php_sasl_setdefs */
  1203. static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
  1204. {
  1205. php_ldap_bictx *ctx;
  1206. ctx = ber_memalloc(sizeof(php_ldap_bictx));
  1207. ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
  1208. ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
  1209. ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
  1210. ctx->passwd = (passwd) ? ber_strdup(passwd) : NULL;
  1211. ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
  1212. if (ctx->mech == NULL) {
  1213. ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
  1214. }
  1215. if (ctx->realm == NULL) {
  1216. ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
  1217. }
  1218. if (ctx->authcid == NULL) {
  1219. ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
  1220. }
  1221. if (ctx->authzid == NULL) {
  1222. ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
  1223. }
  1224. return ctx;
  1225. }
  1226. /* }}} */
  1227. /* {{{ _php_sasl_freedefs */
  1228. static void _php_sasl_freedefs(php_ldap_bictx *ctx)
  1229. {
  1230. if (ctx->mech) ber_memfree(ctx->mech);
  1231. if (ctx->realm) ber_memfree(ctx->realm);
  1232. if (ctx->authcid) ber_memfree(ctx->authcid);
  1233. if (ctx->passwd) ber_memfree(ctx->passwd);
  1234. if (ctx->authzid) ber_memfree(ctx->authzid);
  1235. ber_memfree(ctx);
  1236. }
  1237. /* }}} */
  1238. /* {{{ _php_sasl_interact
  1239. Internal interact function for SASL */
  1240. static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
  1241. {
  1242. sasl_interact_t *interact = in;
  1243. const char *p;
  1244. php_ldap_bictx *ctx = defaults;
  1245. for (;interact->id != SASL_CB_LIST_END;interact++) {
  1246. p = NULL;
  1247. switch(interact->id) {
  1248. case SASL_CB_GETREALM:
  1249. p = ctx->realm;
  1250. break;
  1251. case SASL_CB_AUTHNAME:
  1252. p = ctx->authcid;
  1253. break;
  1254. case SASL_CB_USER:
  1255. p = ctx->authzid;
  1256. break;
  1257. case SASL_CB_PASS:
  1258. p = ctx->passwd;
  1259. break;
  1260. }
  1261. if (p) {
  1262. interact->result = p;
  1263. interact->len = strlen(interact->result);
  1264. }
  1265. }
  1266. return LDAP_SUCCESS;
  1267. }
  1268. /* }}} */
  1269. /* {{{ Bind to LDAP directory using SASL */
  1270. PHP_FUNCTION(ldap_sasl_bind)
  1271. {
  1272. zval *link;
  1273. ldap_linkdata *ld;
  1274. char *binddn = NULL;
  1275. char *passwd = NULL;
  1276. char *sasl_mech = NULL;
  1277. char *sasl_realm = NULL;
  1278. char *sasl_authz_id = NULL;
  1279. char *sasl_authc_id = NULL;
  1280. char *props = NULL;
  1281. size_t rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
  1282. php_ldap_bictx *ctx;
  1283. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!s!s!s!", &link, ldap_link_ce, &binddn, &dn_len, &passwd, &passwd_len, &sasl_mech, &mech_len, &sasl_realm, &realm_len, &sasl_authc_id, &authc_id_len, &sasl_authz_id, &authz_id_len, &props, &props_len) != SUCCESS) {
  1284. RETURN_THROWS();
  1285. }
  1286. ld = Z_LDAP_LINK_P(link);
  1287. VERIFY_LDAP_LINK_CONNECTED(ld);
  1288. ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
  1289. if (props) {
  1290. ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
  1291. }
  1292. rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
  1293. if (rc != LDAP_SUCCESS) {
  1294. php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
  1295. RETVAL_FALSE;
  1296. } else {
  1297. RETVAL_TRUE;
  1298. }
  1299. _php_sasl_freedefs(ctx);
  1300. }
  1301. /* }}} */
  1302. #endif /* HAVE_LDAP_SASL */
  1303. /* {{{ Unbind from LDAP directory */
  1304. PHP_FUNCTION(ldap_unbind)
  1305. {
  1306. zval *link;
  1307. ldap_linkdata *ld;
  1308. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
  1309. RETURN_THROWS();
  1310. }
  1311. ld = Z_LDAP_LINK_P(link);
  1312. VERIFY_LDAP_LINK_CONNECTED(ld);
  1313. ldap_link_free(ld);
  1314. RETURN_TRUE;
  1315. }
  1316. /* }}} */
  1317. /* {{{ php_set_opts */
  1318. static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
  1319. {
  1320. /* sizelimit */
  1321. if (sizelimit > -1) {
  1322. #if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
  1323. ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
  1324. ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
  1325. #else
  1326. *old_sizelimit = ldap->ld_sizelimit;
  1327. ldap->ld_sizelimit = sizelimit;
  1328. #endif
  1329. }
  1330. /* timelimit */
  1331. if (timelimit > -1) {
  1332. #if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
  1333. ldap_get_option(ldap, LDAP_OPT_TIMELIMIT, old_timelimit);
  1334. ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
  1335. #else
  1336. *old_timelimit = ldap->ld_timelimit;
  1337. ldap->ld_timelimit = timelimit;
  1338. #endif
  1339. }
  1340. /* deref */
  1341. if (deref > -1) {
  1342. #if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
  1343. ldap_get_option(ldap, LDAP_OPT_DEREF, old_deref);
  1344. ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
  1345. #else
  1346. *old_deref = ldap->ld_deref;
  1347. ldap->ld_deref = deref;
  1348. #endif
  1349. }
  1350. }
  1351. /* }}} */
  1352. /* {{{ php_ldap_do_search */
  1353. static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
  1354. {
  1355. zval *link, *attrs = NULL, *attr, *serverctrls = NULL;
  1356. zend_string *base_dn_str, *filter_str;
  1357. HashTable *base_dn_ht, *filter_ht;
  1358. zend_long attrsonly, sizelimit, timelimit, deref;
  1359. zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
  1360. char **ldap_attrs = NULL;
  1361. ldap_linkdata *ld = NULL;
  1362. ldap_resultdata *result;
  1363. LDAPMessage *ldap_res = NULL;
  1364. LDAPControl **lserverctrls = NULL;
  1365. int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
  1366. int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
  1367. int num_attribs = 0, ret = 1, i, ldap_errno, argcount = ZEND_NUM_ARGS();
  1368. ZEND_PARSE_PARAMETERS_START(3, 9)
  1369. Z_PARAM_ZVAL(link)
  1370. Z_PARAM_ARRAY_HT_OR_STR(base_dn_ht, base_dn_str)
  1371. Z_PARAM_ARRAY_HT_OR_STR(filter_ht, filter_str)
  1372. Z_PARAM_OPTIONAL
  1373. Z_PARAM_ARRAY_EX(attrs, 0, 1)
  1374. Z_PARAM_LONG(attrsonly)
  1375. Z_PARAM_LONG(sizelimit)
  1376. Z_PARAM_LONG(timelimit)
  1377. Z_PARAM_LONG(deref)
  1378. Z_PARAM_ARRAY_EX(serverctrls, 1, 1)
  1379. ZEND_PARSE_PARAMETERS_END();
  1380. /* Reverse -> fall through */
  1381. switch (argcount) {
  1382. case 9:
  1383. case 8:
  1384. ldap_deref = deref;
  1385. ZEND_FALLTHROUGH;
  1386. case 7:
  1387. ldap_timelimit = timelimit;
  1388. ZEND_FALLTHROUGH;
  1389. case 6:
  1390. ldap_sizelimit = sizelimit;
  1391. ZEND_FALLTHROUGH;
  1392. case 5:
  1393. ldap_attrsonly = attrsonly;
  1394. ZEND_FALLTHROUGH;
  1395. case 4:
  1396. num_attribs = zend_hash_num_elements(Z_ARRVAL_P(attrs));
  1397. ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
  1398. for (i = 0; i<num_attribs; i++) {
  1399. if ((attr = zend_hash_index_find(Z_ARRVAL_P(attrs), i)) == NULL) {
  1400. php_error_docref(NULL, E_WARNING, "Array initialization wrong");
  1401. ret = 0;
  1402. goto cleanup;
  1403. }
  1404. convert_to_string(attr);
  1405. if (EG(exception)) {
  1406. ret = 0;
  1407. goto cleanup;
  1408. }
  1409. ldap_attrs[i] = Z_STRVAL_P(attr);
  1410. }
  1411. ldap_attrs[num_attribs] = NULL;
  1412. ZEND_FALLTHROUGH;
  1413. default:
  1414. break;
  1415. }
  1416. /* parallel search? */
  1417. if (Z_TYPE_P(link) == IS_ARRAY) {
  1418. int i, nlinks, nbases, nfilters, *rcs;
  1419. ldap_linkdata **lds;
  1420. zval *entry, object;
  1421. nlinks = zend_hash_num_elements(Z_ARRVAL_P(link));
  1422. if (nlinks == 0) {
  1423. zend_argument_value_error(1, "cannot be empty");
  1424. ret = 0;
  1425. goto cleanup;
  1426. }
  1427. if (base_dn_ht) {
  1428. nbases = zend_hash_num_elements(base_dn_ht);
  1429. if (nbases != nlinks) {
  1430. zend_argument_value_error(2, "must have the same number of elements as the links array");
  1431. ret = 0;
  1432. goto cleanup;
  1433. }
  1434. zend_hash_internal_pointer_reset(base_dn_ht);
  1435. } else {
  1436. nbases = 0; /* this means string, not array */
  1437. ldap_base_dn = zend_string_copy(base_dn_str);
  1438. if (EG(exception)) {
  1439. ret = 0;
  1440. goto cleanup;
  1441. }
  1442. }
  1443. if (filter_ht) {
  1444. nfilters = zend_hash_num_elements(filter_ht);
  1445. if (nfilters != nlinks) {
  1446. zend_argument_value_error(3, "must have the same number of elements as the links array");
  1447. ret = 0;
  1448. goto cleanup;
  1449. }
  1450. zend_hash_internal_pointer_reset(filter_ht);
  1451. } else {
  1452. nfilters = 0; /* this means string, not array */
  1453. ldap_filter = zend_string_copy(filter_str);
  1454. }
  1455. lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
  1456. rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
  1457. zend_hash_internal_pointer_reset(Z_ARRVAL_P(link));
  1458. for (i=0; i<nlinks; i++) {
  1459. entry = zend_hash_get_current_data(Z_ARRVAL_P(link));
  1460. if (Z_TYPE_P(entry) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(entry), ldap_link_ce)) {
  1461. zend_argument_value_error(1, "must only contain objects of type LDAP");
  1462. ret = 0;
  1463. goto cleanup_parallel;
  1464. }
  1465. ld = Z_LDAP_LINK_P(entry);
  1466. if (!ld->link) {
  1467. zend_throw_error(NULL, "LDAP connection has already been closed");
  1468. ret = 0;
  1469. goto cleanup_parallel;
  1470. }
  1471. if (nbases != 0) { /* base_dn an array? */
  1472. entry = zend_hash_get_current_data(base_dn_ht);
  1473. zend_hash_move_forward(base_dn_ht);
  1474. ldap_base_dn = zval_get_string(entry);
  1475. if (EG(exception)) {
  1476. ret = 0;
  1477. goto cleanup_parallel;
  1478. }
  1479. }
  1480. if (nfilters != 0) { /* filter an array? */
  1481. entry = zend_hash_get_current_data(filter_ht);
  1482. zend_hash_move_forward(filter_ht);
  1483. ldap_filter = zval_get_string(entry);
  1484. if (EG(exception)) {
  1485. ret = 0;
  1486. goto cleanup_parallel;
  1487. }
  1488. }
  1489. if (serverctrls) {
  1490. /* We have to parse controls again for each link as they use it */
  1491. _php_ldap_controls_free(&lserverctrls);
  1492. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 9);
  1493. if (lserverctrls == NULL) {
  1494. rcs[i] = -1;
  1495. continue;
  1496. }
  1497. }
  1498. php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
  1499. /* Run the actual search */
  1500. ldap_search_ext(ld->link, ZSTR_VAL(ldap_base_dn), scope, ZSTR_VAL(ldap_filter), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &rcs[i]);
  1501. lds[i] = ld;
  1502. zend_hash_move_forward(Z_ARRVAL_P(link));
  1503. }
  1504. array_init(return_value);
  1505. /* Collect results from the searches */
  1506. for (i=0; i<nlinks; i++) {
  1507. if (rcs[i] != -1) {
  1508. rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  1509. }
  1510. if (rcs[i] != -1) {
  1511. object_init_ex(&object, ldap_result_ce);
  1512. result = Z_LDAP_RESULT_P(&object);
  1513. result->result = ldap_res;
  1514. add_next_index_zval(return_value, &object);
  1515. } else {
  1516. add_next_index_bool(return_value, 0);
  1517. }
  1518. }
  1519. cleanup_parallel:
  1520. efree(lds);
  1521. efree(rcs);
  1522. } else if (Z_TYPE_P(link) == IS_OBJECT && instanceof_function(Z_OBJCE_P(link), ldap_link_ce)) {
  1523. ld = Z_LDAP_LINK_P(link);
  1524. if (!ld->link) {
  1525. zend_throw_error(NULL, "LDAP connection has already been closed");
  1526. ret = 0;
  1527. goto cleanup;
  1528. }
  1529. if (!base_dn_str) {
  1530. zend_argument_type_error(2, "must be of type string when argument #1 ($ldap) is an LDAP instance");
  1531. ret = 0;
  1532. goto cleanup;
  1533. }
  1534. ldap_base_dn = zend_string_copy(base_dn_str);
  1535. if (!filter_str) {
  1536. zend_argument_type_error(3, "must be of type string when argument #1 ($ldap) is an LDAP instance");
  1537. ret = 0;
  1538. goto cleanup;
  1539. }
  1540. ldap_filter = zend_string_copy(filter_str);
  1541. if (serverctrls) {
  1542. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 9);
  1543. if (lserverctrls == NULL) {
  1544. ret = 0;
  1545. goto cleanup;
  1546. }
  1547. }
  1548. php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
  1549. /* Run the actual search */
  1550. ldap_errno = ldap_search_ext_s(ld->link, ZSTR_VAL(ldap_base_dn), scope, ZSTR_VAL(ldap_filter), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res);
  1551. if (ldap_errno != LDAP_SUCCESS
  1552. && ldap_errno != LDAP_SIZELIMIT_EXCEEDED
  1553. #ifdef LDAP_ADMINLIMIT_EXCEEDED
  1554. && ldap_errno != LDAP_ADMINLIMIT_EXCEEDED
  1555. #endif
  1556. #ifdef LDAP_REFERRAL
  1557. && ldap_errno != LDAP_REFERRAL
  1558. #endif
  1559. ) {
  1560. /* ldap_res should be freed regardless of return value of ldap_search_ext_s()
  1561. * see: https://linux.die.net/man/3/ldap_search_ext_s */
  1562. if (ldap_res != NULL) {
  1563. ldap_msgfree(ldap_res);
  1564. }
  1565. php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(ldap_errno));
  1566. ret = 0;
  1567. } else {
  1568. if (ldap_errno == LDAP_SIZELIMIT_EXCEEDED) {
  1569. php_error_docref(NULL, E_WARNING, "Partial search results returned: Sizelimit exceeded");
  1570. }
  1571. #ifdef LDAP_ADMINLIMIT_EXCEEDED
  1572. else if (ldap_errno == LDAP_ADMINLIMIT_EXCEEDED) {
  1573. php_error_docref(NULL, E_WARNING, "Partial search results returned: Adminlimit exceeded");
  1574. }
  1575. #endif
  1576. object_init_ex(return_value, ldap_result_ce);
  1577. result = Z_LDAP_RESULT_P(return_value);
  1578. result->result = ldap_res;
  1579. }
  1580. } else {
  1581. zend_argument_type_error(1, "must be of type LDAP|array, %s given", zend_zval_type_name(link));
  1582. }
  1583. cleanup:
  1584. if (ld) {
  1585. /* Restoring previous options */
  1586. php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
  1587. }
  1588. if (ldap_filter) {
  1589. zend_string_release(ldap_filter);
  1590. }
  1591. if (ldap_base_dn) {
  1592. zend_string_release(ldap_base_dn);
  1593. }
  1594. if (ldap_attrs != NULL) {
  1595. efree(ldap_attrs);
  1596. }
  1597. if (!ret) {
  1598. RETVAL_BOOL(ret);
  1599. }
  1600. if (lserverctrls) {
  1601. _php_ldap_controls_free(&lserverctrls);
  1602. }
  1603. }
  1604. /* }}} */
  1605. /* {{{ Read an entry */
  1606. PHP_FUNCTION(ldap_read)
  1607. {
  1608. php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
  1609. }
  1610. /* }}} */
  1611. /* {{{ Single-level search */
  1612. PHP_FUNCTION(ldap_list)
  1613. {
  1614. php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
  1615. }
  1616. /* }}} */
  1617. /* {{{ Search LDAP tree under base_dn */
  1618. PHP_FUNCTION(ldap_search)
  1619. {
  1620. php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
  1621. }
  1622. /* }}} */
  1623. /* {{{ Free result memory */
  1624. PHP_FUNCTION(ldap_free_result)
  1625. {
  1626. zval *result;
  1627. ldap_resultdata *ldap_result;
  1628. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &result, ldap_result_ce) != SUCCESS) {
  1629. RETURN_THROWS();
  1630. }
  1631. ldap_result = Z_LDAP_RESULT_P(result);
  1632. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  1633. ldap_result_free(ldap_result);
  1634. RETVAL_TRUE;
  1635. }
  1636. /* }}} */
  1637. /* {{{ Count the number of entries in a search result */
  1638. PHP_FUNCTION(ldap_count_entries)
  1639. {
  1640. zval *link, *result;
  1641. ldap_linkdata *ld;
  1642. ldap_resultdata *ldap_result;
  1643. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
  1644. RETURN_THROWS();
  1645. }
  1646. ld = Z_LDAP_LINK_P(link);
  1647. VERIFY_LDAP_LINK_CONNECTED(ld);
  1648. ldap_result = Z_LDAP_RESULT_P(result);
  1649. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  1650. RETURN_LONG(ldap_count_entries(ld->link, ldap_result->result));
  1651. }
  1652. /* }}} */
  1653. /* {{{ Return first result id */
  1654. PHP_FUNCTION(ldap_first_entry)
  1655. {
  1656. zval *link, *result;
  1657. ldap_linkdata *ld;
  1658. ldap_result_entry *resultentry;
  1659. ldap_resultdata *ldap_result;
  1660. LDAPMessage *entry;
  1661. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
  1662. RETURN_THROWS();
  1663. }
  1664. ld = Z_LDAP_LINK_P(link);
  1665. VERIFY_LDAP_LINK_CONNECTED(ld);
  1666. ldap_result = Z_LDAP_RESULT_P(result);
  1667. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  1668. if ((entry = ldap_first_entry(ld->link, ldap_result->result)) == NULL) {
  1669. RETVAL_FALSE;
  1670. } else {
  1671. object_init_ex(return_value, ldap_result_entry_ce);
  1672. resultentry = Z_LDAP_RESULT_ENTRY_P(return_value);
  1673. ZVAL_COPY(&resultentry->res, result);
  1674. resultentry->data = entry;
  1675. resultentry->ber = NULL;
  1676. }
  1677. }
  1678. /* }}} */
  1679. /* {{{ Get next result entry */
  1680. PHP_FUNCTION(ldap_next_entry)
  1681. {
  1682. zval *link, *result_entry;
  1683. ldap_linkdata *ld;
  1684. ldap_result_entry *resultentry, *resultentry_next;
  1685. LDAPMessage *entry_next;
  1686. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  1687. RETURN_THROWS();
  1688. }
  1689. ld = Z_LDAP_LINK_P(link);
  1690. VERIFY_LDAP_LINK_CONNECTED(ld);
  1691. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1692. if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
  1693. RETVAL_FALSE;
  1694. } else {
  1695. object_init_ex(return_value, ldap_result_entry_ce);
  1696. resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value);
  1697. ZVAL_COPY(&resultentry_next->res, &resultentry->res);
  1698. resultentry_next->data = entry_next;
  1699. resultentry_next->ber = NULL;
  1700. }
  1701. }
  1702. /* }}} */
  1703. /* {{{ Get all result entries */
  1704. PHP_FUNCTION(ldap_get_entries)
  1705. {
  1706. zval *link, *result;
  1707. ldap_resultdata *ldap_result;
  1708. LDAPMessage *ldap_result_entry;
  1709. zval tmp1, tmp2;
  1710. ldap_linkdata *ld;
  1711. LDAP *ldap;
  1712. int num_entries, num_attrib, num_values, i;
  1713. BerElement *ber;
  1714. char *attribute;
  1715. size_t attr_len;
  1716. struct berval **ldap_value;
  1717. char *dn;
  1718. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
  1719. RETURN_THROWS();
  1720. }
  1721. ld = Z_LDAP_LINK_P(link);
  1722. VERIFY_LDAP_LINK_CONNECTED(ld);
  1723. ldap_result = Z_LDAP_RESULT_P(result);
  1724. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  1725. ldap = ld->link;
  1726. num_entries = ldap_count_entries(ldap, ldap_result->result);
  1727. array_init(return_value);
  1728. add_assoc_long(return_value, "count", num_entries);
  1729. if (num_entries == 0) {
  1730. return;
  1731. }
  1732. ldap_result_entry = ldap_first_entry(ldap, ldap_result->result);
  1733. if (ldap_result_entry == NULL) {
  1734. zend_array_destroy(Z_ARR_P(return_value));
  1735. RETURN_FALSE;
  1736. }
  1737. num_entries = 0;
  1738. while (ldap_result_entry != NULL) {
  1739. array_init(&tmp1);
  1740. num_attrib = 0;
  1741. attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
  1742. while (attribute != NULL) {
  1743. ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
  1744. num_values = ldap_count_values_len(ldap_value);
  1745. array_init(&tmp2);
  1746. add_assoc_long(&tmp2, "count", num_values);
  1747. for (i = 0; i < num_values; i++) {
  1748. add_index_stringl(&tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
  1749. }
  1750. ldap_value_free_len(ldap_value);
  1751. attr_len = strlen(attribute);
  1752. zend_str_tolower(attribute, attr_len);
  1753. zend_hash_str_update(Z_ARRVAL(tmp1), attribute, attr_len, &tmp2);
  1754. add_index_string(&tmp1, num_attrib, attribute);
  1755. num_attrib++;
  1756. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1757. ldap_memfree(attribute);
  1758. #endif
  1759. attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
  1760. }
  1761. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1762. if (ber != NULL) {
  1763. ber_free(ber, 0);
  1764. }
  1765. #endif
  1766. add_assoc_long(&tmp1, "count", num_attrib);
  1767. dn = ldap_get_dn(ldap, ldap_result_entry);
  1768. if (dn) {
  1769. add_assoc_string(&tmp1, "dn", dn);
  1770. } else {
  1771. add_assoc_null(&tmp1, "dn");
  1772. }
  1773. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1774. ldap_memfree(dn);
  1775. #else
  1776. free(dn);
  1777. #endif
  1778. zend_hash_index_update(Z_ARRVAL_P(return_value), num_entries, &tmp1);
  1779. num_entries++;
  1780. ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry);
  1781. }
  1782. add_assoc_long(return_value, "count", num_entries);
  1783. }
  1784. /* }}} */
  1785. /* {{{ Return first attribute */
  1786. PHP_FUNCTION(ldap_first_attribute)
  1787. {
  1788. zval *link, *result_entry;
  1789. ldap_linkdata *ld;
  1790. ldap_result_entry *resultentry;
  1791. char *attribute;
  1792. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  1793. RETURN_THROWS();
  1794. }
  1795. ld = Z_LDAP_LINK_P(link);
  1796. VERIFY_LDAP_LINK_CONNECTED(ld);
  1797. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1798. if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
  1799. RETURN_FALSE;
  1800. } else {
  1801. RETVAL_STRING(attribute);
  1802. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1803. ldap_memfree(attribute);
  1804. #endif
  1805. }
  1806. }
  1807. /* }}} */
  1808. /* {{{ Get the next attribute in result */
  1809. PHP_FUNCTION(ldap_next_attribute)
  1810. {
  1811. zval *link, *result_entry;
  1812. ldap_linkdata *ld;
  1813. ldap_result_entry *resultentry;
  1814. char *attribute;
  1815. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  1816. RETURN_THROWS();
  1817. }
  1818. ld = Z_LDAP_LINK_P(link);
  1819. VERIFY_LDAP_LINK_CONNECTED(ld);
  1820. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1821. if (resultentry->ber == NULL) {
  1822. php_error_docref(NULL, E_WARNING, "Called before calling ldap_first_attribute() or no attributes found in result entry");
  1823. RETURN_FALSE;
  1824. }
  1825. if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
  1826. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1827. if (resultentry->ber != NULL) {
  1828. ber_free(resultentry->ber, 0);
  1829. resultentry->ber = NULL;
  1830. }
  1831. #endif
  1832. RETURN_FALSE;
  1833. } else {
  1834. RETVAL_STRING(attribute);
  1835. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1836. ldap_memfree(attribute);
  1837. #endif
  1838. }
  1839. }
  1840. /* }}} */
  1841. /* {{{ Get attributes from a search result entry */
  1842. PHP_FUNCTION(ldap_get_attributes)
  1843. {
  1844. zval *link, *result_entry;
  1845. zval tmp;
  1846. ldap_linkdata *ld;
  1847. ldap_result_entry *resultentry;
  1848. char *attribute;
  1849. struct berval **ldap_value;
  1850. int i, num_values, num_attrib;
  1851. BerElement *ber;
  1852. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  1853. RETURN_THROWS();
  1854. }
  1855. ld = Z_LDAP_LINK_P(link);
  1856. VERIFY_LDAP_LINK_CONNECTED(ld);
  1857. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1858. array_init(return_value);
  1859. num_attrib = 0;
  1860. attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
  1861. while (attribute != NULL) {
  1862. ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
  1863. num_values = ldap_count_values_len(ldap_value);
  1864. array_init(&tmp);
  1865. add_assoc_long(&tmp, "count", num_values);
  1866. for (i = 0; i < num_values; i++) {
  1867. add_index_stringl(&tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
  1868. }
  1869. ldap_value_free_len(ldap_value);
  1870. zend_hash_str_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute), &tmp);
  1871. add_index_string(return_value, num_attrib, attribute);
  1872. num_attrib++;
  1873. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1874. ldap_memfree(attribute);
  1875. #endif
  1876. attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
  1877. }
  1878. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1879. if (ber != NULL) {
  1880. ber_free(ber, 0);
  1881. }
  1882. #endif
  1883. add_assoc_long(return_value, "count", num_attrib);
  1884. }
  1885. /* }}} */
  1886. /* {{{ Get all values with lengths from a result entry */
  1887. PHP_FUNCTION(ldap_get_values_len)
  1888. {
  1889. zval *link, *result_entry;
  1890. ldap_linkdata *ld;
  1891. ldap_result_entry *resultentry;
  1892. char *attr;
  1893. struct berval **ldap_value_len;
  1894. int i, num_values;
  1895. size_t attr_len;
  1896. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOs", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &attr, &attr_len) != SUCCESS) {
  1897. RETURN_THROWS();
  1898. }
  1899. ld = Z_LDAP_LINK_P(link);
  1900. VERIFY_LDAP_LINK_CONNECTED(ld);
  1901. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1902. if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attr)) == NULL) {
  1903. php_error_docref(NULL, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
  1904. RETURN_FALSE;
  1905. }
  1906. num_values = ldap_count_values_len(ldap_value_len);
  1907. array_init(return_value);
  1908. for (i=0; i<num_values; i++) {
  1909. add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len);
  1910. }
  1911. add_assoc_long(return_value, "count", num_values);
  1912. ldap_value_free_len(ldap_value_len);
  1913. }
  1914. /* }}} */
  1915. /* {{{ Get the DN of a result entry */
  1916. PHP_FUNCTION(ldap_get_dn)
  1917. {
  1918. zval *link, *result_entry;
  1919. ldap_linkdata *ld;
  1920. ldap_result_entry *resultentry;
  1921. char *text;
  1922. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  1923. RETURN_THROWS();
  1924. }
  1925. ld = Z_LDAP_LINK_P(link);
  1926. VERIFY_LDAP_LINK_CONNECTED(ld);
  1927. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  1928. text = ldap_get_dn(ld->link, resultentry->data);
  1929. if (text != NULL) {
  1930. RETVAL_STRING(text);
  1931. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1932. ldap_memfree(text);
  1933. #else
  1934. free(text);
  1935. #endif
  1936. } else {
  1937. RETURN_FALSE;
  1938. }
  1939. }
  1940. /* }}} */
  1941. /* {{{ Splits DN into its component parts */
  1942. PHP_FUNCTION(ldap_explode_dn)
  1943. {
  1944. zend_long with_attrib;
  1945. char *dn, **ldap_value;
  1946. int i, count;
  1947. size_t dn_len;
  1948. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &dn, &dn_len, &with_attrib) != SUCCESS) {
  1949. RETURN_THROWS();
  1950. }
  1951. if (!(ldap_value = ldap_explode_dn(dn, with_attrib))) {
  1952. /* Invalid parameters were passed to ldap_explode_dn */
  1953. RETURN_FALSE;
  1954. }
  1955. i=0;
  1956. while (ldap_value[i] != NULL) i++;
  1957. count = i;
  1958. array_init(return_value);
  1959. add_assoc_long(return_value, "count", count);
  1960. for (i = 0; i<count; i++) {
  1961. add_index_string(return_value, i, ldap_value[i]);
  1962. }
  1963. ldap_memvfree((void **)ldap_value);
  1964. }
  1965. /* }}} */
  1966. /* {{{ Convert DN to User Friendly Naming format */
  1967. PHP_FUNCTION(ldap_dn2ufn)
  1968. {
  1969. char *dn, *ufn;
  1970. size_t dn_len;
  1971. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &dn, &dn_len) != SUCCESS) {
  1972. RETURN_THROWS();
  1973. }
  1974. ufn = ldap_dn2ufn(dn);
  1975. if (ufn != NULL) {
  1976. RETVAL_STRING(ufn);
  1977. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) || WINDOWS
  1978. ldap_memfree(ufn);
  1979. #endif
  1980. } else {
  1981. RETURN_FALSE;
  1982. }
  1983. }
  1984. /* }}} */
  1985. /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
  1986. #define PHP_LD_FULL_ADD 0xff
  1987. /* {{{ php_ldap_do_modify */
  1988. static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
  1989. {
  1990. zval *serverctrls = NULL;
  1991. zval *link, *entry, *value, *ivalue;
  1992. ldap_linkdata *ld;
  1993. char *dn;
  1994. LDAPMod **ldap_mods;
  1995. LDAPControl **lserverctrls = NULL;
  1996. ldap_resultdata *result;
  1997. LDAPMessage *ldap_res;
  1998. int i, j, num_attribs, num_values, msgid;
  1999. size_t dn_len;
  2000. int *num_berval;
  2001. zend_string *attribute;
  2002. zend_ulong index;
  2003. int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
  2004. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osa/|a!", &link, ldap_link_ce, &dn, &dn_len, &entry, &serverctrls) != SUCCESS) {
  2005. RETURN_THROWS();
  2006. }
  2007. ld = Z_LDAP_LINK_P(link);
  2008. VERIFY_LDAP_LINK_CONNECTED(ld);
  2009. num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry));
  2010. ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
  2011. num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
  2012. zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry));
  2013. /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
  2014. if (oper == PHP_LD_FULL_ADD) {
  2015. oper = LDAP_MOD_ADD;
  2016. is_full_add = 1;
  2017. }
  2018. /* end additional , gerrit thomson */
  2019. for (i = 0; i < num_attribs; i++) {
  2020. ldap_mods[i] = emalloc(sizeof(LDAPMod));
  2021. ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
  2022. ldap_mods[i]->mod_type = NULL;
  2023. if (zend_hash_get_current_key(Z_ARRVAL_P(entry), &attribute, &index) == HASH_KEY_IS_STRING) {
  2024. ldap_mods[i]->mod_type = estrndup(ZSTR_VAL(attribute), ZSTR_LEN(attribute));
  2025. } else {
  2026. php_error_docref(NULL, E_WARNING, "Unknown attribute in the data");
  2027. /* Free allocated memory */
  2028. while (i >= 0) {
  2029. if (ldap_mods[i]->mod_type) {
  2030. efree(ldap_mods[i]->mod_type);
  2031. }
  2032. efree(ldap_mods[i]);
  2033. i--;
  2034. }
  2035. efree(num_berval);
  2036. efree(ldap_mods);
  2037. RETURN_FALSE;
  2038. }
  2039. value = zend_hash_get_current_data(Z_ARRVAL_P(entry));
  2040. ZVAL_DEREF(value);
  2041. if (Z_TYPE_P(value) != IS_ARRAY) {
  2042. num_values = 1;
  2043. } else {
  2044. SEPARATE_ARRAY(value);
  2045. num_values = zend_hash_num_elements(Z_ARRVAL_P(value));
  2046. }
  2047. num_berval[i] = num_values;
  2048. ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
  2049. /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
  2050. if ((num_values == 1) && (Z_TYPE_P(value) != IS_ARRAY)) {
  2051. convert_to_string(value);
  2052. if (EG(exception)) {
  2053. RETVAL_FALSE;
  2054. goto cleanup;
  2055. }
  2056. ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
  2057. ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_P(value);
  2058. ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_P(value);
  2059. } else {
  2060. for (j = 0; j < num_values; j++) {
  2061. if ((ivalue = zend_hash_index_find(Z_ARRVAL_P(value), j)) == NULL) {
  2062. zend_argument_value_error(3, "must contain arrays with consecutive integer indices starting from 0");
  2063. num_berval[i] = j;
  2064. num_attribs = i + 1;
  2065. RETVAL_FALSE;
  2066. goto cleanup;
  2067. }
  2068. convert_to_string(ivalue);
  2069. if (EG(exception)) {
  2070. RETVAL_FALSE;
  2071. goto cleanup;
  2072. }
  2073. ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
  2074. ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_P(ivalue);
  2075. ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(ivalue);
  2076. }
  2077. }
  2078. ldap_mods[i]->mod_bvalues[num_values] = NULL;
  2079. zend_hash_move_forward(Z_ARRVAL_P(entry));
  2080. }
  2081. ldap_mods[num_attribs] = NULL;
  2082. if (serverctrls) {
  2083. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
  2084. if (lserverctrls == NULL) {
  2085. RETVAL_FALSE;
  2086. goto cleanup;
  2087. }
  2088. }
  2089. /* check flag to see if do_mod was called to perform full add , gerrit thomson */
  2090. if (is_full_add == 1) {
  2091. if (ext) {
  2092. i = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
  2093. } else {
  2094. i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
  2095. }
  2096. if (i != LDAP_SUCCESS) {
  2097. php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i));
  2098. RETVAL_FALSE;
  2099. } else if (ext) {
  2100. i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  2101. if (i == -1) {
  2102. php_error_docref(NULL, E_WARNING, "Add operation failed");
  2103. RETVAL_FALSE;
  2104. goto cleanup;
  2105. }
  2106. /* return a PHP control object */
  2107. object_init_ex(return_value, ldap_result_ce);
  2108. result = Z_LDAP_RESULT_P(return_value);
  2109. result->result = ldap_res;
  2110. } else RETVAL_TRUE;
  2111. } else {
  2112. if (ext) {
  2113. i = ldap_modify_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
  2114. } else {
  2115. i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
  2116. }
  2117. if (i != LDAP_SUCCESS) {
  2118. php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i));
  2119. RETVAL_FALSE;
  2120. } else if (ext) {
  2121. i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  2122. if (i == -1) {
  2123. php_error_docref(NULL, E_WARNING, "Modify operation failed");
  2124. RETVAL_FALSE;
  2125. goto cleanup;
  2126. }
  2127. /* return a PHP control object */
  2128. object_init_ex(return_value, ldap_result_ce);
  2129. result = Z_LDAP_RESULT_P(return_value);
  2130. result->result = ldap_res;
  2131. } else RETVAL_TRUE;
  2132. }
  2133. cleanup:
  2134. for (i = 0; i < num_attribs; i++) {
  2135. efree(ldap_mods[i]->mod_type);
  2136. for (j = 0; j < num_berval[i]; j++) {
  2137. efree(ldap_mods[i]->mod_bvalues[j]);
  2138. }
  2139. efree(ldap_mods[i]->mod_bvalues);
  2140. efree(ldap_mods[i]);
  2141. }
  2142. efree(num_berval);
  2143. efree(ldap_mods);
  2144. if (lserverctrls) {
  2145. _php_ldap_controls_free(&lserverctrls);
  2146. }
  2147. return;
  2148. }
  2149. /* }}} */
  2150. /* {{{ Add entries to LDAP directory */
  2151. PHP_FUNCTION(ldap_add)
  2152. {
  2153. /* use a newly define parameter into the do_modify so ldap_mod_add can be used the way it is supposed to be used , Gerrit THomson */
  2154. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0);
  2155. }
  2156. /* }}} */
  2157. /* {{{ Add entries to LDAP directory */
  2158. PHP_FUNCTION(ldap_add_ext)
  2159. {
  2160. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1);
  2161. }
  2162. /* }}} */
  2163. /* three functions for attribute base modifications, gerrit Thomson */
  2164. /* {{{ Replace attribute values with new ones */
  2165. PHP_FUNCTION(ldap_mod_replace)
  2166. {
  2167. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0);
  2168. }
  2169. /* }}} */
  2170. /* {{{ Replace attribute values with new ones */
  2171. PHP_FUNCTION(ldap_mod_replace_ext)
  2172. {
  2173. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1);
  2174. }
  2175. /* }}} */
  2176. /* {{{ Add attribute values to current */
  2177. PHP_FUNCTION(ldap_mod_add)
  2178. {
  2179. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0);
  2180. }
  2181. /* }}} */
  2182. /* {{{ Add attribute values to current */
  2183. PHP_FUNCTION(ldap_mod_add_ext)
  2184. {
  2185. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1);
  2186. }
  2187. /* }}} */
  2188. /* {{{ Delete attribute values */
  2189. PHP_FUNCTION(ldap_mod_del)
  2190. {
  2191. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0);
  2192. }
  2193. /* }}} */
  2194. /* {{{ Delete attribute values */
  2195. PHP_FUNCTION(ldap_mod_del_ext)
  2196. {
  2197. php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1);
  2198. }
  2199. /* }}} */
  2200. /* {{{ php_ldap_do_delete */
  2201. static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext)
  2202. {
  2203. zval *serverctrls = NULL;
  2204. zval *link;
  2205. ldap_linkdata *ld;
  2206. LDAPControl **lserverctrls = NULL;
  2207. ldap_resultdata *result;
  2208. LDAPMessage *ldap_res;
  2209. char *dn;
  2210. int rc, msgid;
  2211. size_t dn_len;
  2212. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|a!", &link, ldap_link_ce, &dn, &dn_len, &serverctrls) != SUCCESS) {
  2213. RETURN_THROWS();
  2214. }
  2215. ld = Z_LDAP_LINK_P(link);
  2216. VERIFY_LDAP_LINK_CONNECTED(ld);
  2217. if (serverctrls) {
  2218. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 3);
  2219. if (lserverctrls == NULL) {
  2220. RETVAL_FALSE;
  2221. goto cleanup;
  2222. }
  2223. }
  2224. if (ext) {
  2225. rc = ldap_delete_ext(ld->link, dn, lserverctrls, NULL, &msgid);
  2226. } else {
  2227. rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL);
  2228. }
  2229. if (rc != LDAP_SUCCESS) {
  2230. php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc));
  2231. RETVAL_FALSE;
  2232. goto cleanup;
  2233. } else if (ext) {
  2234. rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  2235. if (rc == -1) {
  2236. php_error_docref(NULL, E_WARNING, "Delete operation failed");
  2237. RETVAL_FALSE;
  2238. goto cleanup;
  2239. }
  2240. /* return a PHP control object */
  2241. object_init_ex(return_value, ldap_result_ce);
  2242. result = Z_LDAP_RESULT_P(return_value);
  2243. result->result = ldap_res;
  2244. } else {
  2245. RETVAL_TRUE;
  2246. }
  2247. cleanup:
  2248. if (lserverctrls) {
  2249. _php_ldap_controls_free(&lserverctrls);
  2250. }
  2251. return;
  2252. }
  2253. /* }}} */
  2254. /* {{{ Delete an entry from a directory */
  2255. PHP_FUNCTION(ldap_delete)
  2256. {
  2257. php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2258. }
  2259. /* }}} */
  2260. /* {{{ Delete an entry from a directory */
  2261. PHP_FUNCTION(ldap_delete_ext)
  2262. {
  2263. php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2264. }
  2265. /* }}} */
  2266. /* {{{ _ldap_str_equal_to_const */
  2267. static size_t _ldap_str_equal_to_const(const char *str, size_t str_len, const char *cstr)
  2268. {
  2269. size_t i;
  2270. if (strlen(cstr) != str_len)
  2271. return 0;
  2272. for (i = 0; i < str_len; ++i) {
  2273. if (str[i] != cstr[i]) {
  2274. return 0;
  2275. }
  2276. }
  2277. return 1;
  2278. }
  2279. /* }}} */
  2280. /* {{{ _ldap_strlen_max */
  2281. static size_t _ldap_strlen_max(const char *str, size_t max_len)
  2282. {
  2283. size_t i;
  2284. for (i = 0; i < max_len; ++i) {
  2285. if (str[i] == '\0') {
  2286. return i;
  2287. }
  2288. }
  2289. return max_len;
  2290. }
  2291. /* }}} */
  2292. /* {{{ _ldap_hash_fetch */
  2293. static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
  2294. {
  2295. *out = zend_hash_str_find(Z_ARRVAL_P(hashTbl), key, strlen(key));
  2296. }
  2297. /* }}} */
  2298. /* {{{ Perform multiple modifications as part of one operation */
  2299. PHP_FUNCTION(ldap_modify_batch)
  2300. {
  2301. zval *serverctrls = NULL;
  2302. ldap_linkdata *ld;
  2303. zval *link, *mods, *mod, *modinfo;
  2304. zend_string *modval;
  2305. zval *attrib, *modtype, *vals;
  2306. zval *fetched;
  2307. char *dn;
  2308. size_t dn_len;
  2309. int i, j, k;
  2310. int num_mods, num_modprops, num_modvals;
  2311. LDAPMod **ldap_mods;
  2312. LDAPControl **lserverctrls = NULL;
  2313. uint32_t oper;
  2314. /*
  2315. $mods = array(
  2316. array(
  2317. "attrib" => "unicodePwd",
  2318. "modtype" => LDAP_MODIFY_BATCH_REMOVE,
  2319. "values" => array($oldpw)
  2320. ),
  2321. array(
  2322. "attrib" => "unicodePwd",
  2323. "modtype" => LDAP_MODIFY_BATCH_ADD,
  2324. "values" => array($newpw)
  2325. ),
  2326. array(
  2327. "attrib" => "userPrincipalName",
  2328. "modtype" => LDAP_MODIFY_BATCH_REPLACE,
  2329. "values" => array("janitor@corp.contoso.com")
  2330. ),
  2331. array(
  2332. "attrib" => "userCert",
  2333. "modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
  2334. )
  2335. );
  2336. */
  2337. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osa/|a!", &link, ldap_link_ce, &dn, &dn_len, &mods, &serverctrls) != SUCCESS) {
  2338. RETURN_THROWS();
  2339. }
  2340. ld = Z_LDAP_LINK_P(link);
  2341. VERIFY_LDAP_LINK_CONNECTED(ld);
  2342. /* perform validation */
  2343. {
  2344. zend_string *modkey;
  2345. zend_long modtype;
  2346. /* to store the wrongly-typed keys */
  2347. zend_ulong tmpUlong;
  2348. /* make sure the DN contains no NUL bytes */
  2349. if (_ldap_strlen_max(dn, dn_len) != dn_len) {
  2350. zend_argument_type_error(2, "must not contain null bytes");
  2351. RETURN_THROWS();
  2352. }
  2353. /* make sure the top level is a normal array */
  2354. zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
  2355. if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
  2356. zend_argument_type_error(3, "must be integer-indexed");
  2357. RETURN_THROWS();
  2358. }
  2359. num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
  2360. for (i = 0; i < num_mods; i++) {
  2361. /* is the numbering consecutive? */
  2362. if ((fetched = zend_hash_index_find(Z_ARRVAL_P(mods), i)) == NULL) {
  2363. zend_argument_value_error(3, "must have consecutive integer indices starting from 0");
  2364. RETURN_THROWS();
  2365. }
  2366. mod = fetched;
  2367. /* is it an array? */
  2368. if (Z_TYPE_P(mod) != IS_ARRAY) {
  2369. zend_argument_value_error(3, "must only contain arrays");
  2370. RETURN_THROWS();
  2371. }
  2372. SEPARATE_ARRAY(mod);
  2373. /* for the modification hashtable... */
  2374. zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
  2375. num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
  2376. for (j = 0; j < num_modprops; j++) {
  2377. /* are the keys strings? */
  2378. if (zend_hash_get_current_key(Z_ARRVAL_P(mod), &modkey, &tmpUlong) != HASH_KEY_IS_STRING) {
  2379. zend_argument_type_error(3, "must only contain string-indexed arrays");
  2380. RETURN_THROWS();
  2381. }
  2382. /* is this a valid entry? */
  2383. if (
  2384. !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB) &&
  2385. !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE) &&
  2386. !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)
  2387. ) {
  2388. zend_argument_value_error(3, "must contain arrays only containing the \"" LDAP_MODIFY_BATCH_ATTRIB "\", \"" LDAP_MODIFY_BATCH_MODTYPE "\" and \"" LDAP_MODIFY_BATCH_VALUES "\" keys");
  2389. RETURN_THROWS();
  2390. }
  2391. fetched = zend_hash_get_current_data(Z_ARRVAL_P(mod));
  2392. modinfo = fetched;
  2393. /* does the value type match the key? */
  2394. if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB)) {
  2395. if (Z_TYPE_P(modinfo) != IS_STRING) {
  2396. zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" must be of type string, %s given", get_active_function_name(), zend_zval_type_name(modinfo));
  2397. RETURN_THROWS();
  2398. }
  2399. if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
  2400. zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" cannot contain null-bytes", get_active_function_name());
  2401. RETURN_THROWS();
  2402. }
  2403. }
  2404. else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE)) {
  2405. if (Z_TYPE_P(modinfo) != IS_LONG) {
  2406. zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be of type int, %s given", get_active_function_name(), zend_zval_type_name(modinfo));
  2407. RETURN_THROWS();
  2408. }
  2409. /* is the value in range? */
  2410. modtype = Z_LVAL_P(modinfo);
  2411. if (
  2412. modtype != LDAP_MODIFY_BATCH_ADD &&
  2413. modtype != LDAP_MODIFY_BATCH_REMOVE &&
  2414. modtype != LDAP_MODIFY_BATCH_REPLACE &&
  2415. modtype != LDAP_MODIFY_BATCH_REMOVE_ALL
  2416. ) {
  2417. zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be one of the LDAP_MODIFY_BATCH_* constants", get_active_function_name());
  2418. RETURN_THROWS();
  2419. }
  2420. /* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
  2421. if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
  2422. if (zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
  2423. zend_value_error("%s(): If option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is LDAP_MODIFY_BATCH_REMOVE_ALL, option \"" LDAP_MODIFY_BATCH_VALUES "\" cannot be provided", get_active_function_name());
  2424. RETURN_THROWS();
  2425. }
  2426. }
  2427. else {
  2428. if (!zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
  2429. zend_value_error("%s(): If option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is not LDAP_MODIFY_BATCH_REMOVE_ALL, option \"" LDAP_MODIFY_BATCH_VALUES "\" must be provided", get_active_function_name());
  2430. RETURN_THROWS();
  2431. }
  2432. }
  2433. }
  2434. else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)) {
  2435. if (Z_TYPE_P(modinfo) != IS_ARRAY) {
  2436. zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must be of type array, %s given", get_active_function_name(), zend_zval_type_name(modinfo));
  2437. RETURN_THROWS();
  2438. }
  2439. SEPARATE_ARRAY(modinfo);
  2440. /* is the array not empty? */
  2441. zend_hash_internal_pointer_reset(Z_ARRVAL_P(modinfo));
  2442. num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
  2443. if (num_modvals == 0) {
  2444. zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" cannot be empty", get_active_function_name());
  2445. RETURN_THROWS();
  2446. }
  2447. /* are its keys integers? */
  2448. if (zend_hash_get_current_key_type(Z_ARRVAL_P(modinfo)) != HASH_KEY_IS_LONG) {
  2449. zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must be integer-indexed", get_active_function_name());
  2450. RETURN_THROWS();
  2451. }
  2452. /* are the keys consecutive? */
  2453. for (k = 0; k < num_modvals; k++) {
  2454. if ((fetched = zend_hash_index_find(Z_ARRVAL_P(modinfo), k)) == NULL) {
  2455. zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must have consecutive integer indices starting from 0", get_active_function_name());
  2456. RETURN_THROWS();
  2457. }
  2458. }
  2459. }
  2460. zend_hash_move_forward(Z_ARRVAL_P(mod));
  2461. }
  2462. }
  2463. }
  2464. /* validation was successful */
  2465. /* allocate array of modifications */
  2466. ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
  2467. /* for each modification */
  2468. for (i = 0; i < num_mods; i++) {
  2469. /* allocate the modification struct */
  2470. ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0);
  2471. /* fetch the relevant data */
  2472. fetched = zend_hash_index_find(Z_ARRVAL_P(mods), i);
  2473. mod = fetched;
  2474. _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
  2475. _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
  2476. _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
  2477. /* map the modification type */
  2478. switch (Z_LVAL_P(modtype)) {
  2479. case LDAP_MODIFY_BATCH_ADD:
  2480. oper = LDAP_MOD_ADD;
  2481. break;
  2482. case LDAP_MODIFY_BATCH_REMOVE:
  2483. case LDAP_MODIFY_BATCH_REMOVE_ALL:
  2484. oper = LDAP_MOD_DELETE;
  2485. break;
  2486. case LDAP_MODIFY_BATCH_REPLACE:
  2487. oper = LDAP_MOD_REPLACE;
  2488. break;
  2489. default:
  2490. zend_throw_error(NULL, "Unknown and uncaught modification type.");
  2491. RETVAL_FALSE;
  2492. efree(ldap_mods[i]);
  2493. num_mods = i;
  2494. goto cleanup;
  2495. }
  2496. /* fill in the basic info */
  2497. ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
  2498. ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
  2499. if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
  2500. /* no values */
  2501. ldap_mods[i]->mod_bvalues = NULL;
  2502. }
  2503. else {
  2504. /* allocate space for the values as part of this modification */
  2505. num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
  2506. ldap_mods[i]->mod_bvalues = safe_emalloc((num_modvals+1), sizeof(struct berval *), 0);
  2507. /* for each value */
  2508. for (j = 0; j < num_modvals; j++) {
  2509. /* fetch it */
  2510. fetched = zend_hash_index_find(Z_ARRVAL_P(vals), j);
  2511. modval = zval_get_string(fetched);
  2512. if (EG(exception)) {
  2513. RETVAL_FALSE;
  2514. ldap_mods[i]->mod_bvalues[j] = NULL;
  2515. num_mods = i + 1;
  2516. goto cleanup;
  2517. }
  2518. /* allocate the data struct */
  2519. ldap_mods[i]->mod_bvalues[j] = safe_emalloc(1, sizeof(struct berval), 0);
  2520. /* fill it */
  2521. ldap_mods[i]->mod_bvalues[j]->bv_len = ZSTR_LEN(modval);
  2522. ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(ZSTR_VAL(modval), ZSTR_LEN(modval));
  2523. zend_string_release(modval);
  2524. }
  2525. /* NULL-terminate values */
  2526. ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
  2527. }
  2528. }
  2529. /* NULL-terminate modifications */
  2530. ldap_mods[num_mods] = NULL;
  2531. if (serverctrls) {
  2532. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
  2533. if (lserverctrls == NULL) {
  2534. RETVAL_FALSE;
  2535. goto cleanup;
  2536. }
  2537. }
  2538. /* perform (finally) */
  2539. if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) {
  2540. php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
  2541. RETVAL_FALSE;
  2542. } else RETVAL_TRUE;
  2543. /* clean up */
  2544. cleanup: {
  2545. for (i = 0; i < num_mods; i++) {
  2546. /* attribute */
  2547. efree(ldap_mods[i]->mod_type);
  2548. if (ldap_mods[i]->mod_bvalues != NULL) {
  2549. /* each BER value */
  2550. for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
  2551. /* free the data bytes */
  2552. efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
  2553. /* free the bvalue struct */
  2554. efree(ldap_mods[i]->mod_bvalues[j]);
  2555. }
  2556. /* the BER value array */
  2557. efree(ldap_mods[i]->mod_bvalues);
  2558. }
  2559. /* the modification */
  2560. efree(ldap_mods[i]);
  2561. }
  2562. /* the modifications array */
  2563. efree(ldap_mods);
  2564. if (lserverctrls) {
  2565. _php_ldap_controls_free(&lserverctrls);
  2566. }
  2567. }
  2568. }
  2569. /* }}} */
  2570. /* {{{ Get the current ldap error number */
  2571. PHP_FUNCTION(ldap_errno)
  2572. {
  2573. zval *link;
  2574. ldap_linkdata *ld;
  2575. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
  2576. RETURN_THROWS();
  2577. }
  2578. ld = Z_LDAP_LINK_P(link);
  2579. VERIFY_LDAP_LINK_CONNECTED(ld);
  2580. RETURN_LONG(_get_lderrno(ld->link));
  2581. }
  2582. /* }}} */
  2583. /* {{{ Convert error number to error string */
  2584. PHP_FUNCTION(ldap_err2str)
  2585. {
  2586. zend_long perrno;
  2587. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perrno) != SUCCESS) {
  2588. RETURN_THROWS();
  2589. }
  2590. RETURN_STRING(ldap_err2string(perrno));
  2591. }
  2592. /* }}} */
  2593. /* {{{ Get the current ldap error string */
  2594. PHP_FUNCTION(ldap_error)
  2595. {
  2596. zval *link;
  2597. ldap_linkdata *ld;
  2598. int ld_errno;
  2599. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
  2600. RETURN_THROWS();
  2601. }
  2602. ld = Z_LDAP_LINK_P(link);
  2603. VERIFY_LDAP_LINK_CONNECTED(ld);
  2604. ld_errno = _get_lderrno(ld->link);
  2605. RETURN_STRING(ldap_err2string(ld_errno));
  2606. }
  2607. /* }}} */
  2608. /* {{{ Determine if an entry has a specific value for one of its attributes */
  2609. PHP_FUNCTION(ldap_compare)
  2610. {
  2611. zval *serverctrls = NULL;
  2612. zval *link;
  2613. char *dn, *attr, *value;
  2614. size_t dn_len, attr_len, value_len;
  2615. ldap_linkdata *ld;
  2616. LDAPControl **lserverctrls = NULL;
  2617. int ldap_errno;
  2618. struct berval lvalue;
  2619. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osss|a!", &link, ldap_link_ce, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls) != SUCCESS) {
  2620. RETURN_THROWS();
  2621. }
  2622. ld = Z_LDAP_LINK_P(link);
  2623. VERIFY_LDAP_LINK_CONNECTED(ld);
  2624. if (serverctrls) {
  2625. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 5);
  2626. if (lserverctrls == NULL) {
  2627. RETVAL_FALSE;
  2628. goto cleanup;
  2629. }
  2630. }
  2631. lvalue.bv_val = value;
  2632. lvalue.bv_len = value_len;
  2633. ldap_errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, NULL);
  2634. switch (ldap_errno) {
  2635. case LDAP_COMPARE_TRUE:
  2636. RETVAL_TRUE;
  2637. break;
  2638. case LDAP_COMPARE_FALSE:
  2639. RETVAL_FALSE;
  2640. break;
  2641. default:
  2642. php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(ldap_errno));
  2643. RETVAL_LONG(-1);
  2644. }
  2645. cleanup:
  2646. if (lserverctrls) {
  2647. _php_ldap_controls_free(&lserverctrls);
  2648. }
  2649. return;
  2650. }
  2651. /* }}} */
  2652. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
  2653. /* {{{ Get the current value of various session-wide parameters */
  2654. PHP_FUNCTION(ldap_get_option)
  2655. {
  2656. zval *link, *retval;
  2657. ldap_linkdata *ld;
  2658. zend_long option;
  2659. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz", &link, ldap_link_ce, &option, &retval) != SUCCESS) {
  2660. RETURN_THROWS();
  2661. }
  2662. ld = Z_LDAP_LINK_P(link);
  2663. VERIFY_LDAP_LINK_CONNECTED(ld);
  2664. switch (option) {
  2665. /* options with int value */
  2666. case LDAP_OPT_DEREF:
  2667. case LDAP_OPT_SIZELIMIT:
  2668. case LDAP_OPT_TIMELIMIT:
  2669. case LDAP_OPT_PROTOCOL_VERSION:
  2670. case LDAP_OPT_ERROR_NUMBER:
  2671. case LDAP_OPT_REFERRALS:
  2672. #ifdef LDAP_OPT_RESTART
  2673. case LDAP_OPT_RESTART:
  2674. #endif
  2675. #ifdef LDAP_OPT_X_SASL_NOCANON
  2676. case LDAP_OPT_X_SASL_NOCANON:
  2677. #endif
  2678. #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
  2679. case LDAP_OPT_X_TLS_REQUIRE_CERT:
  2680. #endif
  2681. #ifdef LDAP_OPT_X_TLS_CRLCHECK
  2682. case LDAP_OPT_X_TLS_CRLCHECK:
  2683. #endif
  2684. #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
  2685. case LDAP_OPT_X_TLS_PROTOCOL_MIN:
  2686. #endif
  2687. #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
  2688. case LDAP_OPT_X_KEEPALIVE_IDLE:
  2689. case LDAP_OPT_X_KEEPALIVE_PROBES:
  2690. case LDAP_OPT_X_KEEPALIVE_INTERVAL:
  2691. #endif
  2692. {
  2693. int val;
  2694. if (ldap_get_option(ld->link, option, &val)) {
  2695. RETURN_FALSE;
  2696. }
  2697. ZEND_TRY_ASSIGN_REF_LONG(retval, val);
  2698. } break;
  2699. #ifdef LDAP_OPT_NETWORK_TIMEOUT
  2700. case LDAP_OPT_NETWORK_TIMEOUT:
  2701. {
  2702. struct timeval *timeout = NULL;
  2703. if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
  2704. if (timeout) {
  2705. ldap_memfree(timeout);
  2706. }
  2707. RETURN_FALSE;
  2708. }
  2709. if (!timeout) {
  2710. RETURN_FALSE;
  2711. }
  2712. ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
  2713. ldap_memfree(timeout);
  2714. } break;
  2715. #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
  2716. case LDAP_X_OPT_CONNECT_TIMEOUT:
  2717. {
  2718. int timeout;
  2719. if (ldap_get_option(ld->link, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
  2720. RETURN_FALSE;
  2721. }
  2722. ZEND_TRY_ASSIGN_REF_LONG(retval, (timeout / 1000));
  2723. } break;
  2724. #endif
  2725. #ifdef LDAP_OPT_TIMEOUT
  2726. case LDAP_OPT_TIMEOUT:
  2727. {
  2728. struct timeval *timeout = NULL;
  2729. if (ldap_get_option(ld->link, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
  2730. if (timeout) {
  2731. ldap_memfree(timeout);
  2732. }
  2733. RETURN_FALSE;
  2734. }
  2735. if (!timeout) {
  2736. RETURN_FALSE;
  2737. }
  2738. ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
  2739. ldap_memfree(timeout);
  2740. } break;
  2741. #endif
  2742. /* options with string value */
  2743. case LDAP_OPT_ERROR_STRING:
  2744. #ifdef LDAP_OPT_HOST_NAME
  2745. case LDAP_OPT_HOST_NAME:
  2746. #endif
  2747. #ifdef HAVE_LDAP_SASL
  2748. case LDAP_OPT_X_SASL_MECH:
  2749. case LDAP_OPT_X_SASL_REALM:
  2750. case LDAP_OPT_X_SASL_AUTHCID:
  2751. case LDAP_OPT_X_SASL_AUTHZID:
  2752. #endif
  2753. #ifdef LDAP_OPT_X_SASL_USERNAME
  2754. case LDAP_OPT_X_SASL_USERNAME:
  2755. #endif
  2756. #if (LDAP_API_VERSION > 2000)
  2757. case LDAP_OPT_X_TLS_CACERTDIR:
  2758. case LDAP_OPT_X_TLS_CACERTFILE:
  2759. case LDAP_OPT_X_TLS_CERTFILE:
  2760. case LDAP_OPT_X_TLS_CIPHER_SUITE:
  2761. case LDAP_OPT_X_TLS_KEYFILE:
  2762. case LDAP_OPT_X_TLS_RANDOM_FILE:
  2763. #endif
  2764. #ifdef LDAP_OPT_X_TLS_PACKAGE
  2765. case LDAP_OPT_X_TLS_PACKAGE:
  2766. #endif
  2767. #ifdef LDAP_OPT_X_TLS_CRLFILE
  2768. case LDAP_OPT_X_TLS_CRLFILE:
  2769. #endif
  2770. #ifdef LDAP_OPT_X_TLS_DHFILE
  2771. case LDAP_OPT_X_TLS_DHFILE:
  2772. #endif
  2773. #ifdef LDAP_OPT_MATCHED_DN
  2774. case LDAP_OPT_MATCHED_DN:
  2775. #endif
  2776. {
  2777. char *val = NULL;
  2778. if (ldap_get_option(ld->link, option, &val) || val == NULL || *val == '\0') {
  2779. if (val) {
  2780. ldap_memfree(val);
  2781. }
  2782. RETURN_FALSE;
  2783. }
  2784. ZEND_TRY_ASSIGN_REF_STRING(retval, val);
  2785. ldap_memfree(val);
  2786. } break;
  2787. case LDAP_OPT_SERVER_CONTROLS:
  2788. case LDAP_OPT_CLIENT_CONTROLS:
  2789. {
  2790. LDAPControl **ctrls = NULL;
  2791. if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) {
  2792. if (ctrls) {
  2793. ldap_memfree(ctrls);
  2794. }
  2795. RETURN_FALSE;
  2796. }
  2797. _php_ldap_controls_to_array(ld->link, ctrls, retval, 1);
  2798. } break;
  2799. /* options not implemented
  2800. case LDAP_OPT_API_INFO:
  2801. case LDAP_OPT_API_FEATURE_INFO:
  2802. */
  2803. default:
  2804. RETURN_FALSE;
  2805. }
  2806. RETURN_TRUE;
  2807. }
  2808. /* }}} */
  2809. /* {{{ Set the value of various session-wide parameters */
  2810. PHP_FUNCTION(ldap_set_option)
  2811. {
  2812. zval *link = NULL, *newval;
  2813. ldap_linkdata *ld;
  2814. LDAP *ldap;
  2815. zend_long option;
  2816. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O!lz", &link, ldap_link_ce, &option, &newval) != SUCCESS) {
  2817. RETURN_THROWS();
  2818. }
  2819. if (!link) {
  2820. ldap = NULL;
  2821. } else {
  2822. ld = Z_LDAP_LINK_P(link);
  2823. VERIFY_LDAP_LINK_CONNECTED(ld);
  2824. ldap = ld->link;
  2825. }
  2826. switch (option) {
  2827. /* options with int value */
  2828. case LDAP_OPT_DEREF:
  2829. case LDAP_OPT_SIZELIMIT:
  2830. case LDAP_OPT_TIMELIMIT:
  2831. case LDAP_OPT_PROTOCOL_VERSION:
  2832. case LDAP_OPT_ERROR_NUMBER:
  2833. #ifdef LDAP_OPT_DEBUG_LEVEL
  2834. case LDAP_OPT_DEBUG_LEVEL:
  2835. #endif
  2836. #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
  2837. case LDAP_OPT_X_TLS_REQUIRE_CERT:
  2838. #endif
  2839. #ifdef LDAP_OPT_X_TLS_CRLCHECK
  2840. case LDAP_OPT_X_TLS_CRLCHECK:
  2841. #endif
  2842. #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
  2843. case LDAP_OPT_X_TLS_PROTOCOL_MIN:
  2844. #endif
  2845. #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
  2846. case LDAP_OPT_X_KEEPALIVE_IDLE:
  2847. case LDAP_OPT_X_KEEPALIVE_PROBES:
  2848. case LDAP_OPT_X_KEEPALIVE_INTERVAL:
  2849. #endif
  2850. {
  2851. int val;
  2852. convert_to_long(newval);
  2853. if (ZEND_LONG_EXCEEDS_INT(Z_LVAL_P(newval))) {
  2854. zend_argument_value_error(3, "is too large");
  2855. RETURN_THROWS();
  2856. }
  2857. val = (int)Z_LVAL_P(newval);
  2858. if (ldap_set_option(ldap, option, &val)) {
  2859. RETURN_FALSE;
  2860. }
  2861. } break;
  2862. #ifdef LDAP_OPT_NETWORK_TIMEOUT
  2863. case LDAP_OPT_NETWORK_TIMEOUT:
  2864. {
  2865. struct timeval timeout;
  2866. convert_to_long(newval);
  2867. timeout.tv_sec = Z_LVAL_P(newval);
  2868. timeout.tv_usec = 0;
  2869. if (ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
  2870. RETURN_FALSE;
  2871. }
  2872. } break;
  2873. #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
  2874. case LDAP_X_OPT_CONNECT_TIMEOUT:
  2875. {
  2876. int timeout;
  2877. convert_to_long(newval);
  2878. timeout = 1000 * Z_LVAL_P(newval); /* Convert to milliseconds */
  2879. if (ldap_set_option(ldap, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
  2880. RETURN_FALSE;
  2881. }
  2882. } break;
  2883. #endif
  2884. #ifdef LDAP_OPT_TIMEOUT
  2885. case LDAP_OPT_TIMEOUT:
  2886. {
  2887. struct timeval timeout;
  2888. convert_to_long(newval);
  2889. timeout.tv_sec = Z_LVAL_P(newval);
  2890. timeout.tv_usec = 0;
  2891. if (ldap_set_option(ldap, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
  2892. RETURN_FALSE;
  2893. }
  2894. } break;
  2895. #endif
  2896. /* options with string value */
  2897. case LDAP_OPT_ERROR_STRING:
  2898. #ifdef LDAP_OPT_HOST_NAME
  2899. case LDAP_OPT_HOST_NAME:
  2900. #endif
  2901. #ifdef HAVE_LDAP_SASL
  2902. case LDAP_OPT_X_SASL_MECH:
  2903. case LDAP_OPT_X_SASL_REALM:
  2904. case LDAP_OPT_X_SASL_AUTHCID:
  2905. case LDAP_OPT_X_SASL_AUTHZID:
  2906. #endif
  2907. #if (LDAP_API_VERSION > 2000)
  2908. case LDAP_OPT_X_TLS_CACERTDIR:
  2909. case LDAP_OPT_X_TLS_CACERTFILE:
  2910. case LDAP_OPT_X_TLS_CERTFILE:
  2911. case LDAP_OPT_X_TLS_CIPHER_SUITE:
  2912. case LDAP_OPT_X_TLS_KEYFILE:
  2913. case LDAP_OPT_X_TLS_RANDOM_FILE:
  2914. #endif
  2915. #ifdef LDAP_OPT_X_TLS_CRLFILE
  2916. case LDAP_OPT_X_TLS_CRLFILE:
  2917. #endif
  2918. #ifdef LDAP_OPT_X_TLS_DHFILE
  2919. case LDAP_OPT_X_TLS_DHFILE:
  2920. #endif
  2921. #ifdef LDAP_OPT_MATCHED_DN
  2922. case LDAP_OPT_MATCHED_DN:
  2923. #endif
  2924. {
  2925. zend_string *val;
  2926. val = zval_get_string(newval);
  2927. if (EG(exception)) {
  2928. RETURN_THROWS();
  2929. }
  2930. if (ldap_set_option(ldap, option, ZSTR_VAL(val))) {
  2931. zend_string_release(val);
  2932. RETURN_FALSE;
  2933. }
  2934. zend_string_release(val);
  2935. } break;
  2936. /* options with boolean value */
  2937. case LDAP_OPT_REFERRALS:
  2938. #ifdef LDAP_OPT_RESTART
  2939. case LDAP_OPT_RESTART:
  2940. #endif
  2941. #ifdef LDAP_OPT_X_SASL_NOCANON
  2942. case LDAP_OPT_X_SASL_NOCANON:
  2943. #endif
  2944. {
  2945. void *val;
  2946. val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF;
  2947. if (ldap_set_option(ldap, option, val)) {
  2948. RETURN_FALSE;
  2949. }
  2950. } break;
  2951. /* options with control list value */
  2952. case LDAP_OPT_SERVER_CONTROLS:
  2953. case LDAP_OPT_CLIENT_CONTROLS:
  2954. {
  2955. LDAPControl **ctrls;
  2956. int rc;
  2957. if (Z_TYPE_P(newval) != IS_ARRAY) {
  2958. zend_argument_type_error(3, "must be of type array for the LDAP_OPT_CLIENT_CONTROLS option, %s given", zend_zval_type_name(newval));
  2959. RETURN_THROWS();
  2960. }
  2961. ctrls = _php_ldap_controls_from_array(ldap, newval, 3);
  2962. if (ctrls == NULL) {
  2963. RETURN_FALSE;
  2964. } else {
  2965. rc = ldap_set_option(ldap, option, ctrls);
  2966. _php_ldap_controls_free(&ctrls);
  2967. if (rc != LDAP_SUCCESS) {
  2968. RETURN_FALSE;
  2969. }
  2970. }
  2971. } break;
  2972. default:
  2973. RETURN_FALSE;
  2974. }
  2975. RETURN_TRUE;
  2976. }
  2977. /* }}} */
  2978. #ifdef HAVE_LDAP_PARSE_RESULT
  2979. /* {{{ Extract information from result */
  2980. PHP_FUNCTION(ldap_parse_result)
  2981. {
  2982. zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls;
  2983. ldap_linkdata *ld;
  2984. ldap_resultdata *ldap_result;
  2985. LDAPControl **lserverctrls = NULL;
  2986. char **lreferrals, **refp;
  2987. char *lmatcheddn, *lerrmsg;
  2988. int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
  2989. if (zend_parse_parameters(myargcount, "OOz|zzzz", &link, ldap_link_ce, &result, ldap_result_ce, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
  2990. RETURN_THROWS();
  2991. }
  2992. ld = Z_LDAP_LINK_P(link);
  2993. VERIFY_LDAP_LINK_CONNECTED(ld);
  2994. ldap_result = Z_LDAP_RESULT_P(result);
  2995. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  2996. rc = ldap_parse_result(ld->link, ldap_result->result, &lerrcode,
  2997. myargcount > 3 ? &lmatcheddn : NULL,
  2998. myargcount > 4 ? &lerrmsg : NULL,
  2999. myargcount > 5 ? &lreferrals : NULL,
  3000. myargcount > 6 ? &lserverctrls : NULL,
  3001. 0);
  3002. if (rc != LDAP_SUCCESS) {
  3003. php_error_docref(NULL, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
  3004. RETURN_FALSE;
  3005. }
  3006. ZEND_TRY_ASSIGN_REF_LONG(errcode, lerrcode);
  3007. /* Reverse -> fall through */
  3008. switch (myargcount) {
  3009. case 7:
  3010. _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
  3011. ZEND_FALLTHROUGH;
  3012. case 6:
  3013. referrals = zend_try_array_init(referrals);
  3014. if (!referrals) {
  3015. RETURN_THROWS();
  3016. }
  3017. if (lreferrals != NULL) {
  3018. refp = lreferrals;
  3019. while (*refp) {
  3020. add_next_index_string(referrals, *refp);
  3021. refp++;
  3022. }
  3023. ldap_memvfree((void**)lreferrals);
  3024. }
  3025. ZEND_FALLTHROUGH;
  3026. case 5:
  3027. if (lerrmsg == NULL) {
  3028. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(errmsg);
  3029. } else {
  3030. ZEND_TRY_ASSIGN_REF_STRING(errmsg, lerrmsg);
  3031. ldap_memfree(lerrmsg);
  3032. }
  3033. ZEND_FALLTHROUGH;
  3034. case 4:
  3035. if (lmatcheddn == NULL) {
  3036. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(matcheddn);
  3037. } else {
  3038. ZEND_TRY_ASSIGN_REF_STRING(matcheddn, lmatcheddn);
  3039. ldap_memfree(lmatcheddn);
  3040. }
  3041. }
  3042. RETURN_TRUE;
  3043. }
  3044. /* }}} */
  3045. #endif
  3046. /* {{{ Extended operation response parsing, Pierangelo Masarati */
  3047. #ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
  3048. /* {{{ Extract information from extended operation result */
  3049. PHP_FUNCTION(ldap_parse_exop)
  3050. {
  3051. zval *link, *result, *retdata, *retoid;
  3052. ldap_linkdata *ld;
  3053. ldap_resultdata *ldap_result;
  3054. char *lretoid;
  3055. struct berval *lretdata;
  3056. int rc, myargcount = ZEND_NUM_ARGS();
  3057. if (zend_parse_parameters(myargcount, "OO|zz", &link, ldap_link_ce, &result, ldap_result_ce, &retdata, &retoid) != SUCCESS) {
  3058. RETURN_THROWS();
  3059. }
  3060. ld = Z_LDAP_LINK_P(link);
  3061. VERIFY_LDAP_LINK_CONNECTED(ld);
  3062. ldap_result = Z_LDAP_RESULT_P(result);
  3063. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  3064. rc = ldap_parse_extended_result(ld->link, ldap_result->result,
  3065. myargcount > 3 ? &lretoid: NULL,
  3066. myargcount > 2 ? &lretdata: NULL,
  3067. 0);
  3068. if (rc != LDAP_SUCCESS) {
  3069. php_error_docref(NULL, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
  3070. RETURN_FALSE;
  3071. }
  3072. /* Reverse -> fall through */
  3073. switch (myargcount) {
  3074. case 4:
  3075. if (lretoid == NULL) {
  3076. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
  3077. } else {
  3078. ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
  3079. ldap_memfree(lretoid);
  3080. }
  3081. ZEND_FALLTHROUGH;
  3082. case 3:
  3083. /* use arg #3 as the data returned by the server */
  3084. if (lretdata == NULL) {
  3085. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
  3086. } else {
  3087. ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
  3088. ldap_memfree(lretdata->bv_val);
  3089. ldap_memfree(lretdata);
  3090. }
  3091. }
  3092. RETURN_TRUE;
  3093. }
  3094. /* }}} */
  3095. #endif
  3096. /* }}} */
  3097. /* {{{ Count the number of references in a search result */
  3098. PHP_FUNCTION(ldap_count_references)
  3099. {
  3100. zval *link, *result;
  3101. ldap_linkdata *ld;
  3102. ldap_resultdata *ldap_result;
  3103. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
  3104. RETURN_THROWS();
  3105. }
  3106. ld = Z_LDAP_LINK_P(link);
  3107. VERIFY_LDAP_LINK_CONNECTED(ld);
  3108. ldap_result = Z_LDAP_RESULT_P(result);
  3109. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  3110. RETURN_LONG(ldap_count_references(ld->link, ldap_result->result));
  3111. }
  3112. /* }}} */
  3113. /* {{{ Return first reference */
  3114. PHP_FUNCTION(ldap_first_reference)
  3115. {
  3116. zval *link, *result;
  3117. ldap_linkdata *ld;
  3118. ldap_result_entry *resultentry;
  3119. ldap_resultdata *ldap_result;
  3120. LDAPMessage *entry;
  3121. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
  3122. RETURN_THROWS();
  3123. }
  3124. ld = Z_LDAP_LINK_P(link);
  3125. VERIFY_LDAP_LINK_CONNECTED(ld);
  3126. ldap_result = Z_LDAP_RESULT_P(result);
  3127. VERIFY_LDAP_RESULT_OPEN(ldap_result);
  3128. if ((entry = ldap_first_reference(ld->link, ldap_result->result)) == NULL) {
  3129. RETVAL_FALSE;
  3130. } else {
  3131. object_init_ex(return_value, ldap_result_entry_ce);
  3132. resultentry = Z_LDAP_RESULT_ENTRY_P(return_value);
  3133. ZVAL_COPY(&resultentry->res, result);
  3134. resultentry->data = entry;
  3135. resultentry->ber = NULL;
  3136. }
  3137. }
  3138. /* }}} */
  3139. /* {{{ Get next reference */
  3140. PHP_FUNCTION(ldap_next_reference)
  3141. {
  3142. zval *link, *result_entry;
  3143. ldap_linkdata *ld;
  3144. ldap_result_entry *resultentry, *resultentry_next;
  3145. LDAPMessage *entry_next;
  3146. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
  3147. RETURN_THROWS();
  3148. }
  3149. ld = Z_LDAP_LINK_P(link);
  3150. VERIFY_LDAP_LINK_CONNECTED(ld);
  3151. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  3152. if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
  3153. RETVAL_FALSE;
  3154. } else {
  3155. object_init_ex(return_value, ldap_result_entry_ce);
  3156. resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value);
  3157. ZVAL_COPY(&resultentry_next->res, &resultentry->res);
  3158. resultentry_next->data = entry_next;
  3159. resultentry_next->ber = NULL;
  3160. }
  3161. }
  3162. /* }}} */
  3163. #ifdef HAVE_LDAP_PARSE_REFERENCE
  3164. /* {{{ Extract information from reference entry */
  3165. PHP_FUNCTION(ldap_parse_reference)
  3166. {
  3167. zval *link, *result_entry, *referrals;
  3168. ldap_linkdata *ld;
  3169. ldap_result_entry *resultentry;
  3170. char **lreferrals, **refp;
  3171. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOz", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &referrals) != SUCCESS) {
  3172. RETURN_THROWS();
  3173. }
  3174. ld = Z_LDAP_LINK_P(link);
  3175. VERIFY_LDAP_LINK_CONNECTED(ld);
  3176. resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
  3177. if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
  3178. RETURN_FALSE;
  3179. }
  3180. referrals = zend_try_array_init(referrals);
  3181. if (!referrals) {
  3182. RETURN_THROWS();
  3183. }
  3184. if (lreferrals != NULL) {
  3185. refp = lreferrals;
  3186. while (*refp) {
  3187. add_next_index_string(referrals, *refp);
  3188. refp++;
  3189. }
  3190. ldap_memvfree((void**)lreferrals);
  3191. }
  3192. RETURN_TRUE;
  3193. }
  3194. /* }}} */
  3195. #endif
  3196. /* {{{ php_ldap_do_rename */
  3197. static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext)
  3198. {
  3199. zval *serverctrls = NULL;
  3200. zval *link;
  3201. ldap_linkdata *ld;
  3202. LDAPControl **lserverctrls = NULL;
  3203. ldap_resultdata *result;
  3204. LDAPMessage *ldap_res;
  3205. int rc, msgid;
  3206. char *dn, *newrdn, *newparent;
  3207. size_t dn_len, newrdn_len, newparent_len;
  3208. bool deleteoldrdn;
  3209. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osssb|a!", &link, ldap_link_ce, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls) != SUCCESS) {
  3210. RETURN_THROWS();
  3211. }
  3212. ld = Z_LDAP_LINK_P(link);
  3213. VERIFY_LDAP_LINK_CONNECTED(ld);
  3214. if (newparent_len == 0) {
  3215. newparent = NULL;
  3216. }
  3217. #if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
  3218. if (serverctrls) {
  3219. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 6);
  3220. if (lserverctrls == NULL) {
  3221. RETVAL_FALSE;
  3222. goto cleanup;
  3223. }
  3224. }
  3225. if (ext) {
  3226. rc = ldap_rename(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL, &msgid);
  3227. } else {
  3228. rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL);
  3229. }
  3230. #else
  3231. if (newparent_len != 0) {
  3232. php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
  3233. RETURN_FALSE;
  3234. }
  3235. if (serverctrls) {
  3236. php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported");
  3237. RETURN_FALSE;
  3238. }
  3239. if (ext) {
  3240. php_error_docref(NULL, E_WARNING, "You are using old LDAP API, ldap_rename_ext is not supported");
  3241. RETURN_FALSE;
  3242. }
  3243. /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
  3244. rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn);
  3245. #endif
  3246. if (rc != LDAP_SUCCESS) {
  3247. RETVAL_FALSE;
  3248. } else if (ext) {
  3249. rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  3250. if (rc == -1) {
  3251. php_error_docref(NULL, E_WARNING, "Rename operation failed");
  3252. RETVAL_FALSE;
  3253. goto cleanup;
  3254. }
  3255. /* return a PHP control object */
  3256. object_init_ex(return_value, ldap_result_ce);
  3257. result = Z_LDAP_RESULT_P(return_value);
  3258. result->result = ldap_res;
  3259. } else {
  3260. RETVAL_TRUE;
  3261. }
  3262. cleanup:
  3263. if (lserverctrls) {
  3264. _php_ldap_controls_free(&lserverctrls);
  3265. }
  3266. return;
  3267. }
  3268. /* }}} */
  3269. /* {{{ Modify the name of an entry */
  3270. PHP_FUNCTION(ldap_rename)
  3271. {
  3272. php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  3273. }
  3274. /* }}} */
  3275. /* {{{ Modify the name of an entry */
  3276. PHP_FUNCTION(ldap_rename_ext)
  3277. {
  3278. php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  3279. }
  3280. /* }}} */
  3281. #ifdef HAVE_LDAP_START_TLS_S
  3282. /* {{{ Start TLS */
  3283. PHP_FUNCTION(ldap_start_tls)
  3284. {
  3285. zval *link;
  3286. ldap_linkdata *ld;
  3287. int rc, protocol = LDAP_VERSION3;
  3288. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
  3289. RETURN_THROWS();
  3290. }
  3291. ld = Z_LDAP_LINK_P(link);
  3292. VERIFY_LDAP_LINK_CONNECTED(ld);
  3293. if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
  3294. ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
  3295. ) {
  3296. php_error_docref(NULL, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
  3297. RETURN_FALSE;
  3298. } else {
  3299. RETURN_TRUE;
  3300. }
  3301. }
  3302. /* }}} */
  3303. #endif
  3304. #endif /* (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) */
  3305. #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
  3306. /* {{{ _ldap_rebind_proc() */
  3307. int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
  3308. {
  3309. ldap_linkdata *ld = NULL;
  3310. int retval;
  3311. zval cb_args[2];
  3312. zval cb_retval;
  3313. zval *cb_link = (zval *) params;
  3314. ld = Z_LDAP_LINK_P(cb_link);
  3315. if (!ld->link) {
  3316. zend_throw_error(NULL, "LDAP connection has already been closed");
  3317. return LDAP_OTHER;
  3318. }
  3319. /* link exists and callback set? */
  3320. if (Z_ISUNDEF(ld->rebindproc)) {
  3321. php_error_docref(NULL, E_WARNING, "No callback set");
  3322. return LDAP_OTHER;
  3323. }
  3324. /* callback */
  3325. ZVAL_COPY_VALUE(&cb_args[0], cb_link);
  3326. ZVAL_STRING(&cb_args[1], url);
  3327. if (call_user_function(EG(function_table), NULL, &ld->rebindproc, &cb_retval, 2, cb_args) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
  3328. retval = zval_get_long(&cb_retval);
  3329. zval_ptr_dtor(&cb_retval);
  3330. } else {
  3331. php_error_docref(NULL, E_WARNING, "rebind_proc PHP callback failed");
  3332. retval = LDAP_OTHER;
  3333. }
  3334. zval_ptr_dtor(&cb_args[1]);
  3335. return retval;
  3336. }
  3337. /* }}} */
  3338. /* {{{ Set a callback function to do re-binds on referral chasing. */
  3339. PHP_FUNCTION(ldap_set_rebind_proc)
  3340. {
  3341. zval *link;
  3342. zend_fcall_info fci;
  3343. zend_fcall_info_cache fcc;
  3344. ldap_linkdata *ld;
  3345. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Of!", &link, ldap_link_ce, &fci, &fcc) == FAILURE) {
  3346. RETURN_THROWS();
  3347. }
  3348. ld = Z_LDAP_LINK_P(link);
  3349. VERIFY_LDAP_LINK_CONNECTED(ld);
  3350. if (!ZEND_FCI_INITIALIZED(fci)) {
  3351. /* unregister rebind procedure */
  3352. if (!Z_ISUNDEF(ld->rebindproc)) {
  3353. zval_ptr_dtor(&ld->rebindproc);
  3354. ZVAL_UNDEF(&ld->rebindproc);
  3355. ldap_set_rebind_proc(ld->link, NULL, NULL);
  3356. }
  3357. RETURN_TRUE;
  3358. }
  3359. /* register rebind procedure */
  3360. if (Z_ISUNDEF(ld->rebindproc)) {
  3361. ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
  3362. } else {
  3363. zval_ptr_dtor(&ld->rebindproc);
  3364. }
  3365. ZVAL_COPY(&ld->rebindproc, &fci.function_name);
  3366. RETURN_TRUE;
  3367. }
  3368. /* }}} */
  3369. #endif
  3370. static zend_string* php_ldap_do_escape(const bool *map, const char *value, size_t valuelen, zend_long flags)
  3371. {
  3372. char hex[] = "0123456789abcdef";
  3373. size_t i, p = 0;
  3374. size_t len = 0;
  3375. zend_string *ret;
  3376. for (i = 0; i < valuelen; i++) {
  3377. len += (map[(unsigned char) value[i]]) ? 3 : 1;
  3378. }
  3379. /* Per RFC 4514, a leading and trailing space must be escaped */
  3380. if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) {
  3381. len += 2;
  3382. }
  3383. if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) {
  3384. len += 2;
  3385. }
  3386. ret = zend_string_alloc(len, 0);
  3387. for (i = 0; i < valuelen; i++) {
  3388. unsigned char v = (unsigned char) value[i];
  3389. if (map[v] || ((flags & PHP_LDAP_ESCAPE_DN) && ((i == 0) || (i + 1 == valuelen)) && (v == ' '))) {
  3390. ZSTR_VAL(ret)[p++] = '\\';
  3391. ZSTR_VAL(ret)[p++] = hex[v >> 4];
  3392. ZSTR_VAL(ret)[p++] = hex[v & 0x0f];
  3393. } else {
  3394. ZSTR_VAL(ret)[p++] = v;
  3395. }
  3396. }
  3397. ZSTR_VAL(ret)[p] = '\0';
  3398. ZSTR_LEN(ret) = p;
  3399. return ret;
  3400. }
  3401. static void php_ldap_escape_map_set_chars(bool *map, const char *chars, const size_t charslen, char escape)
  3402. {
  3403. size_t i = 0;
  3404. while (i < charslen) {
  3405. map[(unsigned char) chars[i++]] = escape;
  3406. }
  3407. }
  3408. PHP_FUNCTION(ldap_escape)
  3409. {
  3410. char *value, *ignores;
  3411. size_t valuelen = 0, ignoreslen = 0;
  3412. int i;
  3413. zend_long flags = 0;
  3414. bool map[256] = {0}, havecharlist = 0;
  3415. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl", &value, &valuelen, &ignores, &ignoreslen, &flags) != SUCCESS) {
  3416. RETURN_THROWS();
  3417. }
  3418. if (!valuelen) {
  3419. RETURN_EMPTY_STRING();
  3420. }
  3421. if (flags & PHP_LDAP_ESCAPE_FILTER) {
  3422. havecharlist = 1;
  3423. php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1);
  3424. }
  3425. if (flags & PHP_LDAP_ESCAPE_DN) {
  3426. havecharlist = 1;
  3427. php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, 1);
  3428. }
  3429. if (!havecharlist) {
  3430. for (i = 0; i < 256; i++) {
  3431. map[i] = 1;
  3432. }
  3433. }
  3434. if (ignoreslen) {
  3435. php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0);
  3436. }
  3437. RETURN_NEW_STR(php_ldap_do_escape(map, value, valuelen, flags));
  3438. }
  3439. #ifdef STR_TRANSLATION
  3440. /* {{{ php_ldap_do_translate */
  3441. static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way)
  3442. {
  3443. char *value;
  3444. size_t value_len;
  3445. int result;
  3446. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) != SUCCESS) {
  3447. RETURN_THROWS();
  3448. }
  3449. if (value_len == 0) {
  3450. RETURN_FALSE;
  3451. }
  3452. if (way == 1) {
  3453. result = ldap_8859_to_t61(&value, &value_len, 0);
  3454. } else {
  3455. result = ldap_t61_to_8859(&value, &value_len, 0);
  3456. }
  3457. if (result == LDAP_SUCCESS) {
  3458. RETVAL_STRINGL(value, value_len);
  3459. free(value);
  3460. } else {
  3461. php_error_docref(NULL, E_WARNING, "Conversion from ISO-8859-1 to t61 failed: %s", ldap_err2string(result));
  3462. RETVAL_FALSE;
  3463. }
  3464. }
  3465. /* }}} */
  3466. /* {{{ Translate t61 characters to 8859 characters */
  3467. PHP_FUNCTION(ldap_t61_to_8859)
  3468. {
  3469. php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  3470. }
  3471. /* }}} */
  3472. /* {{{ Translate 8859 characters to t61 characters */
  3473. PHP_FUNCTION(ldap_8859_to_t61)
  3474. {
  3475. php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  3476. }
  3477. /* }}} */
  3478. #endif
  3479. /* {{{ Extended operations, Pierangelo Masarati */
  3480. #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
  3481. /* {{{ Extended operation */
  3482. PHP_FUNCTION(ldap_exop)
  3483. {
  3484. zval *serverctrls = NULL;
  3485. zval *link, *retdata = NULL, *retoid = NULL;
  3486. char *lretoid = NULL;
  3487. zend_string *reqoid, *reqdata = NULL;
  3488. struct berval lreqdata, *lretdata = NULL;
  3489. ldap_linkdata *ld;
  3490. ldap_resultdata *result;
  3491. LDAPMessage *ldap_res;
  3492. LDAPControl **lserverctrls = NULL;
  3493. int rc, msgid;
  3494. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|S!a!zz", &link, ldap_link_ce, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) {
  3495. RETURN_THROWS();
  3496. }
  3497. ld = Z_LDAP_LINK_P(link);
  3498. VERIFY_LDAP_LINK_CONNECTED(ld);
  3499. if (reqdata) {
  3500. lreqdata.bv_val = ZSTR_VAL(reqdata);
  3501. lreqdata.bv_len = ZSTR_LEN(reqdata);
  3502. } else {
  3503. lreqdata.bv_len = 0;
  3504. }
  3505. if (serverctrls) {
  3506. lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
  3507. if (lserverctrls == NULL) {
  3508. RETVAL_FALSE;
  3509. goto cleanup;
  3510. }
  3511. }
  3512. if (retdata) {
  3513. /* synchronous call */
  3514. rc = ldap_extended_operation_s(ld->link, ZSTR_VAL(reqoid),
  3515. lreqdata.bv_len > 0 ? &lreqdata: NULL,
  3516. lserverctrls,
  3517. NULL,
  3518. retoid ? &lretoid : NULL,
  3519. &lretdata );
  3520. if (rc != LDAP_SUCCESS ) {
  3521. php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
  3522. RETVAL_FALSE;
  3523. goto cleanup;
  3524. }
  3525. if (retoid) {
  3526. if (lretoid) {
  3527. ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
  3528. ldap_memfree(lretoid);
  3529. } else {
  3530. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
  3531. }
  3532. }
  3533. if (lretdata) {
  3534. ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
  3535. ldap_memfree(lretdata->bv_val);
  3536. ldap_memfree(lretdata);
  3537. } else {
  3538. ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
  3539. }
  3540. RETVAL_TRUE;
  3541. goto cleanup;
  3542. }
  3543. /* asynchronous call */
  3544. rc = ldap_extended_operation(ld->link, ZSTR_VAL(reqoid),
  3545. lreqdata.bv_len > 0 ? &lreqdata: NULL,
  3546. lserverctrls,
  3547. NULL,
  3548. &msgid);
  3549. if (rc != LDAP_SUCCESS ) {
  3550. php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
  3551. RETVAL_FALSE;
  3552. goto cleanup;
  3553. }
  3554. rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  3555. if (rc == -1) {
  3556. php_error_docref(NULL, E_WARNING, "Extended operation %s failed", ZSTR_VAL(reqoid));
  3557. RETVAL_FALSE;
  3558. goto cleanup;
  3559. }
  3560. /* return a PHP control object */
  3561. object_init_ex(return_value, ldap_result_ce);
  3562. result = Z_LDAP_RESULT_P(return_value);
  3563. result->result = ldap_res;
  3564. cleanup:
  3565. if (lserverctrls) {
  3566. _php_ldap_controls_free(&lserverctrls);
  3567. }
  3568. }
  3569. /* }}} */
  3570. #endif
  3571. #ifdef HAVE_LDAP_PASSWD
  3572. /* {{{ Passwd modify extended operation */
  3573. PHP_FUNCTION(ldap_exop_passwd)
  3574. {
  3575. zval *link, *serverctrls;
  3576. struct berval luser = { 0L, NULL };
  3577. struct berval loldpw = { 0L, NULL };
  3578. struct berval lnewpw = { 0L, NULL };
  3579. struct berval lgenpasswd = { 0L, NULL };
  3580. LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
  3581. LDAPMessage* ldap_res = NULL;
  3582. ldap_linkdata *ld;
  3583. int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
  3584. char* errmsg = NULL;
  3585. if (zend_parse_parameters(myargcount, "O|sssz/", &link, ldap_link_ce, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
  3586. RETURN_THROWS();
  3587. }
  3588. ld = Z_LDAP_LINK_P(link);
  3589. VERIFY_LDAP_LINK_CONNECTED(ld);
  3590. switch (myargcount) {
  3591. case 5:
  3592. /* ldap_create_passwordpolicy_control() allocates ctrl */
  3593. if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
  3594. requestctrls[0] = ctrl;
  3595. }
  3596. }
  3597. /* asynchronous call to get result and controls */
  3598. rc = ldap_passwd(ld->link, &luser,
  3599. loldpw.bv_len > 0 ? &loldpw : NULL,
  3600. lnewpw.bv_len > 0 ? &lnewpw : NULL,
  3601. requestctrls,
  3602. NULL, &msgid);
  3603. if (requestctrls[0] != NULL) {
  3604. ldap_control_free(requestctrls[0]);
  3605. }
  3606. if (rc != LDAP_SUCCESS ) {
  3607. php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3608. RETVAL_FALSE;
  3609. goto cleanup;
  3610. }
  3611. rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
  3612. if ((rc < 0) || !ldap_res) {
  3613. rc = _get_lderrno(ld->link);
  3614. php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3615. RETVAL_FALSE;
  3616. goto cleanup;
  3617. }
  3618. rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
  3619. if( rc != LDAP_SUCCESS ) {
  3620. php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3621. RETVAL_FALSE;
  3622. goto cleanup;
  3623. }
  3624. rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
  3625. if( rc != LDAP_SUCCESS ) {
  3626. php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3627. RETVAL_FALSE;
  3628. goto cleanup;
  3629. }
  3630. if (myargcount > 4) {
  3631. _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
  3632. }
  3633. /* return */
  3634. if (lnewpw.bv_len == 0) {
  3635. if (lgenpasswd.bv_len == 0) {
  3636. RETVAL_EMPTY_STRING();
  3637. } else {
  3638. RETVAL_STRINGL(lgenpasswd.bv_val, lgenpasswd.bv_len);
  3639. }
  3640. } else if (err == LDAP_SUCCESS) {
  3641. RETVAL_TRUE;
  3642. } else {
  3643. php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", (errmsg ? errmsg : ldap_err2string(err)), err);
  3644. RETVAL_FALSE;
  3645. }
  3646. cleanup:
  3647. if (lgenpasswd.bv_val != NULL) {
  3648. ldap_memfree(lgenpasswd.bv_val);
  3649. }
  3650. if (ldap_res != NULL) {
  3651. ldap_msgfree(ldap_res);
  3652. }
  3653. if (errmsg != NULL) {
  3654. ldap_memfree(errmsg);
  3655. }
  3656. }
  3657. /* }}} */
  3658. #endif
  3659. #ifdef HAVE_LDAP_WHOAMI_S
  3660. /* {{{ Whoami extended operation */
  3661. PHP_FUNCTION(ldap_exop_whoami)
  3662. {
  3663. zval *link;
  3664. struct berval *lauthzid;
  3665. ldap_linkdata *ld;
  3666. int rc;
  3667. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) == FAILURE) {
  3668. RETURN_THROWS();
  3669. }
  3670. ld = Z_LDAP_LINK_P(link);
  3671. VERIFY_LDAP_LINK_CONNECTED(ld);
  3672. /* synchronous call */
  3673. rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL);
  3674. if (rc != LDAP_SUCCESS ) {
  3675. php_error_docref(NULL, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3676. RETURN_FALSE;
  3677. }
  3678. if (lauthzid == NULL) {
  3679. RETVAL_EMPTY_STRING();
  3680. } else {
  3681. RETVAL_STRINGL(lauthzid->bv_val, lauthzid->bv_len);
  3682. ldap_memfree(lauthzid->bv_val);
  3683. ldap_memfree(lauthzid);
  3684. }
  3685. }
  3686. /* }}} */
  3687. #endif
  3688. #ifdef HAVE_LDAP_REFRESH_S
  3689. /* {{{ DDS refresh extended operation */
  3690. PHP_FUNCTION(ldap_exop_refresh)
  3691. {
  3692. zval *link;
  3693. zend_long ttl;
  3694. struct berval ldn;
  3695. ber_int_t lttl;
  3696. ber_int_t newttl;
  3697. ldap_linkdata *ld;
  3698. int rc;
  3699. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osl", &link, ldap_link_ce, &ldn.bv_val, &ldn.bv_len, &ttl) != SUCCESS) {
  3700. RETURN_THROWS();
  3701. }
  3702. ld = Z_LDAP_LINK_P(link);
  3703. VERIFY_LDAP_LINK_CONNECTED(ld);
  3704. lttl = (ber_int_t) ttl;
  3705. rc = ldap_refresh_s(ld->link, &ldn, lttl, &newttl, NULL, NULL);
  3706. if (rc != LDAP_SUCCESS ) {
  3707. php_error_docref(NULL, E_WARNING, "Refresh extended operation failed: %s (%d)", ldap_err2string(rc), rc);
  3708. RETURN_FALSE;
  3709. }
  3710. RETURN_LONG(newttl);
  3711. }
  3712. /* }}} */
  3713. #endif
  3714. zend_module_entry ldap_module_entry = { /* {{{ */
  3715. STANDARD_MODULE_HEADER,
  3716. "ldap",
  3717. ext_functions,
  3718. PHP_MINIT(ldap),
  3719. PHP_MSHUTDOWN(ldap),
  3720. NULL,
  3721. NULL,
  3722. PHP_MINFO(ldap),
  3723. PHP_LDAP_VERSION,
  3724. PHP_MODULE_GLOBALS(ldap),
  3725. PHP_GINIT(ldap),
  3726. NULL,
  3727. NULL,
  3728. STANDARD_MODULE_PROPERTIES_EX
  3729. };
  3730. /* }}} */