dasess.cpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #define da_decl __declspec(dllexport)
  14. #include "platform.h"
  15. #include "jlib.hpp"
  16. #include "jfile.hpp"
  17. #include "jsuperhash.hpp"
  18. #include "jmisc.hpp"
  19. #include "jencrypt.hpp"
  20. #include "dacoven.hpp"
  21. #include "mpbuff.hpp"
  22. #include "mpcomm.hpp"
  23. #include "mputil.hpp"
  24. #include "daserver.hpp"
  25. #include "dasubs.ipp"
  26. #include "dasds.hpp"
  27. #include "daclient.hpp"
  28. #include "daldap.hpp"
  29. #include "dasess.hpp"
  30. #ifdef _MSC_VER
  31. #pragma warning (disable : 4355)
  32. #endif
  33. const char *queryRoleName(DaliClientRole role)
  34. {
  35. switch (role) {
  36. case DCR_Private: return "Private";
  37. case DCR_Diagnostic: return "Diagnostic";
  38. case DCR_ThorSlave: return "ThorSlave";
  39. case DCR_ThorMaster: return "ThorMaster";
  40. case DCR_EclServer: return "EclServer";
  41. case DCR_EclScheduler: return "EclScheduler";
  42. case DCR_EclAgent: return "EclAgent";
  43. case DCR_AgentExec: return "AgentExec";
  44. case DCR_DaliServer:return "DaliServer";
  45. case DCR_SashaServer: return "SashaServer";
  46. case DCR_Util: return "Util";
  47. case DCR_Dfu: return "Dfu";
  48. case DCR_DfuServer: return "DfuServer";
  49. case DCR_EspServer: return "EspServer";
  50. case DCR_WuClient: return "WuClient";
  51. case DCR_Config: return "Config";
  52. case DCR_Scheduler: return "Scheduler";
  53. case DCR_RoxyMaster: return "RoxieMaster";
  54. case DCR_RoxySlave: return "RoxieSlave";
  55. case DCR_BackupGen: return "BackupGen";
  56. case DCR_Other: return "Other";
  57. }
  58. return "Unknown";
  59. }
  60. interface ISessionManagerServer: implements IConnectionMonitor
  61. {
  62. virtual SessionId registerSession(SecurityToken tok,SessionId parentid) = 0;
  63. virtual SessionId registerClientProcess(INode *node,IGroup *&grp, DaliClientRole role) = 0;
  64. virtual void addProcessSession(SessionId id, INode *node, DaliClientRole role) = 0;
  65. virtual void addSession(SessionId id) = 0;
  66. virtual SessionId lookupProcessSession(INode *node) = 0;
  67. virtual INode *getProcessSessionNode(SessionId id) =0;
  68. virtual int getPermissionsLDAP(const char *key,const char *obj,IUserDescriptor *udesc,unsigned flags, int *err)=0;
  69. virtual bool clearPermissionsCache(IUserDescriptor *udesc) = 0;
  70. virtual void stopSession(SessionId sessid,bool failed) = 0;
  71. virtual void setClientAuth(IDaliClientAuthConnection *authconn) = 0;
  72. virtual void setLDAPconnection(IDaliLdapConnection *_ldapconn) = 0;
  73. virtual bool authorizeConnection(int role,bool revoke) = 0;
  74. virtual void start() = 0;
  75. virtual void ready() = 0;
  76. virtual void stop() = 0;
  77. virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg) = 0;
  78. virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg) = 0;
  79. };
  80. static SessionId mySessionId=0;
  81. static ISessionManager *SessionManager=NULL;
  82. static ISessionManagerServer *SessionManagerServer=NULL;
  83. static CriticalSection sessionCrit;
  84. #define SESSIONREPLYTIMEOUT (3*60*1000)
  85. #define CLDAPE_getpermtimeout (-1)
  86. #define CLDAPE_ldapfailure (-2)
  87. class CDaliLDAP_Exception: public CInterface, implements IException
  88. {
  89. int errcode;
  90. public:
  91. CDaliLDAP_Exception(int _errcode)
  92. {
  93. errcode = _errcode;
  94. }
  95. int errorCode() const { return errcode; }
  96. StringBuffer & errorMessage(StringBuffer &str) const
  97. {
  98. if (errcode==0)
  99. return str;
  100. str.appendf("LDAP Exception(%d): ",errcode);
  101. if (errcode==CLDAPE_getpermtimeout)
  102. return str.append("getPermissionsLDAP - timeout to LDAP server");
  103. if (errcode==CLDAPE_ldapfailure)
  104. return str.append("getPermissionsLDAP - LDAP server failure");
  105. return str.append("Unknown Exception");
  106. }
  107. MessageAudience errorAudience() const { return MSGAUD_user; }
  108. IMPLEMENT_IINTERFACE;
  109. };
  110. class CdelayedTerminate: public Thread // slightly obfuscated stop code
  111. {
  112. byte err;
  113. int run()
  114. {
  115. while (getRandom()%711!=0) getRandom(); // look busy
  116. ERRLOG("Server fault %d",(int)err);
  117. while (getRandom()%7!=0) Sleep(1);
  118. exit(0);
  119. }
  120. public:
  121. CdelayedTerminate(byte _err)
  122. {
  123. err = _err;
  124. start();
  125. Release();
  126. Sleep(100);
  127. }
  128. };
  129. class CSessionState: public CInterface
  130. {
  131. protected: friend class CSessionStateTable;
  132. SessionId id;
  133. public:
  134. CSessionState(SessionId _id)
  135. {
  136. id = _id;
  137. }
  138. SessionId getId() const
  139. {
  140. return id;
  141. }
  142. };
  143. class CSessionStateTable: private SuperHashTableOf<CSessionState,SessionId>
  144. {
  145. CheckedCriticalSection sessstatesect;
  146. void onAdd(void *) {}
  147. void onRemove(void *e)
  148. {
  149. CSessionState &elem=*(CSessionState *)e;
  150. elem.Release();
  151. }
  152. unsigned getHashFromElement(const void *e) const
  153. {
  154. const CSessionState &elem=*(const CSessionState *)e;
  155. SessionId id=elem.id;
  156. return low(id)^(unsigned)high(id);
  157. }
  158. unsigned getHashFromFindParam(const void *fp) const
  159. {
  160. SessionId id = *(const SessionId *)fp;
  161. return low(id)^(unsigned)high(id);
  162. }
  163. const void * getFindParam(const void *p) const
  164. {
  165. const CSessionState &elem=*(const CSessionState *)p;
  166. return (void *)&elem.id;
  167. }
  168. bool matchesFindParam(const void * et, const void *fp, unsigned) const
  169. {
  170. return ((CSessionState *)et)->id==*(SessionId *)fp;
  171. }
  172. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(CSessionState,SessionId);
  173. public:
  174. CSessionStateTable()
  175. {
  176. }
  177. ~CSessionStateTable() {
  178. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  179. releaseAll();
  180. }
  181. bool add(CSessionState *e) // takes ownership
  182. {
  183. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  184. if (SuperHashTableOf<CSessionState,SessionId>::find(&e->id))
  185. return false;
  186. SuperHashTableOf<CSessionState,SessionId>::add(*e);
  187. return true;
  188. }
  189. CSessionState *query(SessionId id)
  190. {
  191. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  192. return SuperHashTableOf<CSessionState,SessionId>::find(&id);
  193. }
  194. void remove(SessionId id)
  195. {
  196. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  197. SuperHashTableOf<CSessionState,SessionId>::remove(&id);
  198. }
  199. };
  200. class CProcessSessionState: public CSessionState
  201. {
  202. INode *node;
  203. DaliClientRole role;
  204. UInt64Array previousSessionIds;
  205. public:
  206. CProcessSessionState(SessionId id,INode *_node,DaliClientRole _role)
  207. : CSessionState(id)
  208. {
  209. node = _node;
  210. node->Link();
  211. role = _role;
  212. }
  213. ~CProcessSessionState()
  214. {
  215. node->Release();
  216. }
  217. INode &queryNode() const
  218. {
  219. return *node;
  220. }
  221. DaliClientRole queryRole() const
  222. {
  223. return role;
  224. }
  225. StringBuffer &getDetails(StringBuffer &buf)
  226. {
  227. StringBuffer ep;
  228. return buf.appendf("%16"I64F"X: %s, role=%s",CSessionState::id,node->endpoint().getUrlStr(ep).str(),queryRoleName(role));
  229. }
  230. void addSessionIds(CProcessSessionState &other, bool prevOnly)
  231. {
  232. loop
  233. {
  234. SessionId id = other.dequeuePreviousSessionId();
  235. if (!id)
  236. break;
  237. previousSessionIds.append(id);
  238. }
  239. if (!prevOnly)
  240. previousSessionIds.append(other.getId());
  241. }
  242. SessionId dequeuePreviousSessionId()
  243. {
  244. if (!previousSessionIds.ordinality())
  245. return 0;
  246. return previousSessionIds.popGet();
  247. }
  248. unsigned previousSessionIdCount() const
  249. {
  250. return previousSessionIds.ordinality();
  251. }
  252. void removeOldSessionId(SessionId id)
  253. {
  254. if (previousSessionIds.zap(id))
  255. PROGLOG("Removed old sessionId (%"I64F"x) from current process state", id);
  256. }
  257. };
  258. class CMapProcessToSession: private SuperHashTableOf<CProcessSessionState,INode>
  259. {
  260. CheckedCriticalSection mapprocesssect;
  261. void onAdd(void *) {}
  262. void onRemove(void *e) {} // do nothing
  263. unsigned getHashFromElement(const void *e) const
  264. {
  265. const CProcessSessionState &elem=*(const CProcessSessionState *)e;
  266. return elem.queryNode().getHash();
  267. }
  268. unsigned getHashFromFindParam(const void *fp) const
  269. {
  270. return ((INode *)fp)->getHash();
  271. }
  272. const void * getFindParam(const void *p) const
  273. {
  274. const CProcessSessionState &elem=*(const CProcessSessionState *)p;
  275. return (void *)&elem.queryNode();
  276. }
  277. bool matchesFindParam(const void * et, const void *fp, unsigned) const
  278. {
  279. return ((CProcessSessionState *)et)->queryNode().equals((INode *)fp);
  280. }
  281. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(CProcessSessionState,INode);
  282. public:
  283. CMapProcessToSession()
  284. {
  285. }
  286. ~CMapProcessToSession()
  287. {
  288. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  289. releaseAll();
  290. }
  291. bool add(CProcessSessionState *e)
  292. {
  293. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  294. if (SuperHashTableOf<CProcessSessionState,INode>::find(&e->queryNode()))
  295. return false;
  296. SuperHashTableOf<CProcessSessionState,INode>::add(*e);
  297. return true;
  298. }
  299. void replace(CProcessSessionState *e)
  300. {
  301. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  302. SuperHashTableOf<CProcessSessionState,INode>::replace(*e);
  303. }
  304. CProcessSessionState *query(INode *n)
  305. {
  306. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  307. return SuperHashTableOf<CProcessSessionState,INode>::find(n);
  308. }
  309. bool remove(const CProcessSessionState *state, ISessionManagerServer *manager)
  310. {
  311. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  312. if (SuperHashTableOf<CProcessSessionState,INode>::removeExact((CProcessSessionState *)state))
  313. {
  314. if (manager)
  315. manager->authorizeConnection(state->queryRole(), true);
  316. return true;
  317. }
  318. return false;
  319. }
  320. unsigned count()
  321. {
  322. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  323. return SuperHashTableOf<CProcessSessionState,INode>::count();
  324. }
  325. CProcessSessionState *next(const CProcessSessionState *s)
  326. {
  327. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  328. return (CProcessSessionState *)SuperHashTableOf<CProcessSessionState,INode>::next(s);
  329. }
  330. };
  331. enum MSessionRequestKind {
  332. MSR_REGISTER_PROCESS_SESSION,
  333. MSR_SECONDARY_REGISTER_PROCESS_SESSION,
  334. MSR_REGISTER_SESSION,
  335. MSR_SECONDARY_REGISTER_SESSION,
  336. MSR_LOOKUP_PROCESS_SESSION,
  337. MSR_STOP_SESSION,
  338. MSR_IMPORT_CAPABILITIES,
  339. MSR_LOOKUP_LDAP_PERMISSIONS,
  340. MSR_CLEAR_PERMISSIONS_CACHE,
  341. MSR_EXIT, // TBD
  342. MSR_QUERY_SCOPE_SCANS_ENABLED,
  343. MSR_ENABLE_SCOPE_SCANS
  344. };
  345. class CQueryScopeScansEnabledReq : implements IMessageWrapper
  346. {
  347. public:
  348. bool enabled;
  349. Linked<IUserDescriptor> udesc;
  350. CQueryScopeScansEnabledReq(IUserDescriptor *_udesc) : udesc(_udesc) {}
  351. CQueryScopeScansEnabledReq() {}
  352. void serializeReq(CMessageBuffer &mb)
  353. {
  354. mb.append(MSR_QUERY_SCOPE_SCANS_ENABLED);
  355. udesc->serialize(mb);
  356. }
  357. void deserializeReq(CMessageBuffer &mb)
  358. {
  359. udesc.setown(createUserDescriptor(mb));
  360. }
  361. };
  362. class CEnableScopeScansReq : implements IMessageWrapper
  363. {
  364. public:
  365. bool doEnable;
  366. Linked<IUserDescriptor> udesc;
  367. CEnableScopeScansReq(IUserDescriptor *_udesc, bool _doEnable) : udesc(_udesc), doEnable(_doEnable) {}
  368. CEnableScopeScansReq() {}
  369. void serializeReq(CMessageBuffer &mb)
  370. {
  371. mb.append(MSR_ENABLE_SCOPE_SCANS);
  372. udesc->serialize(mb);
  373. mb.append(doEnable);
  374. }
  375. void deserializeReq(CMessageBuffer &mb)
  376. {
  377. udesc.setown(createUserDescriptor(mb));
  378. mb.read(doEnable);
  379. }
  380. };
  381. class CSessionRequestServer: public Thread
  382. {
  383. bool stopped;
  384. ISessionManagerServer &manager;
  385. Semaphore acceptConnections;
  386. public:
  387. CSessionRequestServer(ISessionManagerServer &_manager)
  388. : Thread("Session Manager, CSessionRequestServer"), manager(_manager)
  389. {
  390. stopped = true;
  391. }
  392. int run()
  393. {
  394. ICoven &coven=queryCoven();
  395. CMessageHandler<CSessionRequestServer> handler("CSessionRequestServer",this,&CSessionRequestServer::processMessage);
  396. stopped = false;
  397. CMessageBuffer mb;
  398. while (!stopped) {
  399. try {
  400. mb.clear();
  401. if (coven.recv(mb,RANK_ALL,MPTAG_DALI_SESSION_REQUEST,NULL))
  402. handler.handleMessage(mb);
  403. else
  404. stopped = true;
  405. }
  406. catch (IException *e)
  407. {
  408. EXCLOG(e, "CDaliPublisherServer");
  409. e->Release();
  410. }
  411. }
  412. return 0;
  413. }
  414. void processMessage(CMessageBuffer &mb)
  415. {
  416. ICoven &coven=queryCoven();
  417. SessionId id;
  418. int fn;
  419. mb.read(fn);
  420. switch (fn) {
  421. case MSR_REGISTER_PROCESS_SESSION: {
  422. acceptConnections.wait();
  423. acceptConnections.signal();
  424. Owned<INode> node(deserializeINode(mb));
  425. Owned<INode> servernode(deserializeINode(mb)); // hopefully me, but not if forwarded
  426. int role=0;
  427. if (mb.length()-mb.getPos()>=sizeof(role)) { // a capability block present
  428. mb.read(role);
  429. if (!manager.authorizeConnection(role,false)) {
  430. SocketEndpoint sender = mb.getSender();
  431. mb.clear();
  432. coven.reply(mb);
  433. MilliSleep(100+getRandom()%1000); // Causes client to 'work' for a short time.
  434. Owned<INode> node = createINode(sender);
  435. coven.disconnect(node);
  436. break;
  437. }
  438. #ifdef _DEBUG
  439. StringBuffer eps;
  440. PROGLOG("Connection to %s authorized",mb.getSender().getUrlStr(eps).str());
  441. #endif
  442. }
  443. IGroup *covengrp;
  444. id = manager.registerClientProcess(node.get(),covengrp,(DaliClientRole)role);
  445. mb.clear().append(id);
  446. if (covengrp->rank(servernode)==RANK_NULL) { // must have been redirected
  447. covengrp->Release(); // no good, so just use one we know about (may use something more sophisticated later)
  448. INode *na = servernode.get();
  449. covengrp = createIGroup(1, &na);
  450. }
  451. covengrp->serialize(mb);
  452. covengrp->Release();
  453. coven.reply(mb);
  454. }
  455. break;
  456. case MSR_SECONDARY_REGISTER_PROCESS_SESSION: {
  457. mb.read(id);
  458. Owned<INode> node (deserializeINode(mb));
  459. int role;
  460. mb.read(role);
  461. manager.addProcessSession(id,node.get(),(DaliClientRole)role);
  462. mb.clear();
  463. coven.reply(mb);
  464. }
  465. break;
  466. case MSR_REGISTER_SESSION: {
  467. SecurityToken tok;
  468. SessionId parentid;
  469. mb.read(tok).read(parentid);
  470. SessionId id = manager.registerSession(tok,parentid);
  471. mb.clear().append(id);
  472. coven.reply(mb);
  473. }
  474. break;
  475. case MSR_SECONDARY_REGISTER_SESSION: {
  476. mb.read(id);
  477. manager.addSession(id);
  478. mb.clear();
  479. coven.reply(mb);
  480. }
  481. break;
  482. case MSR_LOOKUP_PROCESS_SESSION: {
  483. // looks up from node or from id
  484. Owned<INode> node (deserializeINode(mb));
  485. if (node->endpoint().isNull()&&(mb.length()-mb.getPos()>=sizeof(id))) {
  486. mb.read(id);
  487. INode *n = manager.getProcessSessionNode(id);
  488. if (n)
  489. node.setown(n);
  490. node->serialize(mb.clear());
  491. }
  492. else {
  493. id = manager.lookupProcessSession(node.get());
  494. mb.clear().append(id);
  495. }
  496. coven.reply(mb);
  497. }
  498. break;
  499. case MSR_STOP_SESSION: {
  500. SessionId sessid;
  501. bool failed;
  502. mb.read(sessid).read(failed);
  503. manager.stopSession(sessid,failed);
  504. mb.clear();
  505. coven.reply(mb);
  506. }
  507. break;
  508. case MSR_LOOKUP_LDAP_PERMISSIONS: {
  509. StringAttr key;
  510. StringAttr obj;
  511. Owned<IUserDescriptor> udesc=createUserDescriptor();
  512. StringAttr username;
  513. StringAttr passwordenc;
  514. mb.read(key).read(obj);
  515. udesc->deserialize(mb);
  516. #ifdef NULL_DALIUSER_STACKTRACE
  517. //following debug code to be removed
  518. StringBuffer sb;
  519. udesc->getUserName(sb);
  520. if (0==sb.length())
  521. {
  522. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp CSessionRequestServer::processMessage() line %d", __LINE__);
  523. }
  524. #endif
  525. unsigned auditflags = 0;
  526. if (mb.length()-mb.getPos()>=sizeof(auditflags))
  527. mb.read(auditflags);
  528. int err = 0;
  529. int ret=manager.getPermissionsLDAP(key,obj,udesc,auditflags,&err);
  530. mb.clear().append(ret);
  531. if (err)
  532. mb.append(err);
  533. coven.reply(mb);
  534. }
  535. break;
  536. case MSR_CLEAR_PERMISSIONS_CACHE: {
  537. Owned<IUserDescriptor> udesc=createUserDescriptor();
  538. udesc->deserialize(mb);
  539. bool ok = manager.clearPermissionsCache(udesc);
  540. mb.append(ok);
  541. coven.reply(mb);
  542. }
  543. break;
  544. case MSR_QUERY_SCOPE_SCANS_ENABLED:{
  545. CQueryScopeScansEnabledReq req;
  546. req.deserializeReq(mb);
  547. int err;
  548. StringBuffer retMsg;
  549. bool enabled = manager.queryScopeScansEnabled(req.udesc, &err, retMsg);
  550. mb.clear().append(err);
  551. mb.append(enabled);
  552. mb.append(retMsg.str());
  553. if (err != 0 || retMsg.length())
  554. {
  555. StringBuffer user;
  556. req.udesc->getUserName(user);
  557. DBGLOG("Error %d querying scope scan status for %s : %s", err, user.str(), retMsg.str());
  558. }
  559. coven.reply(mb);
  560. }
  561. break;
  562. case MSR_ENABLE_SCOPE_SCANS:{
  563. CEnableScopeScansReq req;
  564. req.deserializeReq(mb);
  565. int err;
  566. StringBuffer retMsg;
  567. bool ok = manager.enableScopeScans(req.udesc, req.doEnable, &err, retMsg);
  568. mb.clear().append(err);
  569. mb.append(retMsg.str());
  570. if (err != 0 || retMsg.length())
  571. {
  572. StringBuffer user;
  573. req.udesc->getUserName(user);
  574. DBGLOG("Error %d %sing Scope Scan Status for %s: %s", err, req.doEnable?"Enabl":"Disabl", user.str(), retMsg.str());
  575. }
  576. coven.reply(mb);
  577. }
  578. break;
  579. }
  580. }
  581. void ready()
  582. {
  583. acceptConnections.signal();
  584. }
  585. void stop()
  586. {
  587. if (!stopped) {
  588. stopped = true;
  589. queryCoven().cancel(RANK_ALL, MPTAG_DALI_SESSION_REQUEST);
  590. }
  591. join();
  592. }
  593. };
  594. class CSessionManagerBase: public CInterface, implements ISessionManager
  595. {
  596. protected:
  597. CheckedCriticalSection sessmanagersect;
  598. public:
  599. IMPLEMENT_IINTERFACE;
  600. CSessionManagerBase()
  601. {
  602. servernotifys.kill();
  603. }
  604. virtual ~CSessionManagerBase()
  605. {
  606. }
  607. class CSessionSubscriptionProxy: public CInterface, implements ISubscription
  608. {
  609. ISessionNotify *sub;
  610. SubscriptionId id;
  611. MemoryAttr ma;
  612. SessionId sessid;
  613. public:
  614. IMPLEMENT_IINTERFACE;
  615. CSessionSubscriptionProxy(ISessionNotify *_sub,SessionId _sessid)
  616. {
  617. sub = LINK(_sub);
  618. sessid = _sessid;
  619. MemoryBuffer mb;
  620. mb.append(sessid);
  621. ma.set(mb.length(),mb.toByteArray());
  622. id = queryCoven().getUniqueId();
  623. }
  624. ~CSessionSubscriptionProxy()
  625. {
  626. sub->Release();
  627. }
  628. ISessionNotify *queryNotify()
  629. {
  630. return sub;
  631. }
  632. const MemoryAttr &queryData()
  633. {
  634. return ma;
  635. }
  636. SubscriptionId getId()
  637. {
  638. return id;
  639. }
  640. void doNotify(bool aborted)
  641. {
  642. if (aborted)
  643. sub->aborted(sessid);
  644. else
  645. sub->closed(sessid);
  646. }
  647. void notify(MemoryBuffer &mb)
  648. {
  649. bool aborted;
  650. mb.read(aborted);
  651. doNotify(aborted);
  652. }
  653. void abort()
  654. {
  655. //NH: TBD
  656. }
  657. bool aborted()
  658. {
  659. return false;
  660. }
  661. };
  662. CIArrayOf<CSessionSubscriptionProxy>servernotifys;
  663. SubscriptionId subscribeSession(SessionId sessid, ISessionNotify *inotify)
  664. {
  665. CSessionSubscriptionProxy *proxy;
  666. SubscriptionId id;
  667. {
  668. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  669. proxy = new CSessionSubscriptionProxy(inotify,sessid);
  670. id = proxy->getId();
  671. if (sessid==SESSID_DALI_SERVER) {
  672. servernotifys.append(*proxy);
  673. return id;
  674. }
  675. }
  676. querySubscriptionManager(SESSION_PUBLISHER)->add(proxy,id);
  677. return id;
  678. }
  679. void unsubscribeSession(SubscriptionId id)
  680. {
  681. {
  682. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  683. // check not a server subscription
  684. ForEachItemIn(i,servernotifys) {
  685. if (servernotifys.item(i).getId()==id) {
  686. servernotifys.remove(i);
  687. return;
  688. }
  689. }
  690. }
  691. querySubscriptionManager(SESSION_PUBLISHER)->remove(id);
  692. }
  693. class cNotify: public CInterface, implements ISessionNotify
  694. {
  695. public:
  696. IMPLEMENT_IINTERFACE;
  697. Semaphore sem;
  698. void closed(SessionId id)
  699. {
  700. //PROGLOG("Session closed %"I64F"x",id);
  701. sem.signal();
  702. }
  703. void aborted(SessionId id)
  704. {
  705. //PROGLOG("Session aborted %"I64F"x",id);
  706. sem.signal();
  707. }
  708. };
  709. bool sessionStopped(SessionId id, unsigned timeout)
  710. {
  711. Owned<INode> node = getProcessSessionNode(id);
  712. if (node.get()==NULL)
  713. return true;
  714. if (timeout==0)
  715. return false;
  716. Owned<cNotify> cnotify = new cNotify;
  717. querySessionManager().subscribeSession(id,cnotify);
  718. if (cnotify->sem.wait(timeout))
  719. return false;
  720. node.setown(getProcessSessionNode(id));
  721. return node.get()==NULL;
  722. }
  723. void notifyServerStopped(bool aborted)
  724. {
  725. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  726. // check not a server subscription
  727. ForEachItemIn(i,servernotifys) {
  728. servernotifys.item(i).doNotify(aborted);
  729. }
  730. }
  731. };
  732. class CClientSessionManager: public CSessionManagerBase, implements IConnectionMonitor
  733. {
  734. bool securitydisabled;
  735. public:
  736. IMPLEMENT_IINTERFACE;
  737. CClientSessionManager()
  738. {
  739. securitydisabled = false;
  740. }
  741. virtual ~CClientSessionManager()
  742. {
  743. stop();
  744. }
  745. SessionId lookupProcessSession(INode *node)
  746. {
  747. if (!node)
  748. return mySessionId;
  749. CMessageBuffer mb;
  750. mb.append((int)MSR_LOOKUP_PROCESS_SESSION);
  751. node->serialize(mb);
  752. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  753. return 0;
  754. SessionId ret;
  755. mb.read(ret);
  756. return ret;
  757. }
  758. virtual INode *getProcessSessionNode(SessionId id)
  759. {
  760. if (!id)
  761. return NULL;
  762. CMessageBuffer mb;
  763. mb.append((int)MSR_LOOKUP_PROCESS_SESSION);
  764. queryNullNode()->serialize(mb);
  765. mb.append(id);
  766. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  767. return NULL;
  768. Owned<INode> node = deserializeINode(mb);
  769. if (node->endpoint().isNull())
  770. return NULL;
  771. return node.getClear();
  772. }
  773. int getPermissionsLDAP(const char *key,const char *obj,IUserDescriptor *udesc,unsigned auditflags,int *err)
  774. {
  775. if (err)
  776. *err = 0;
  777. if (securitydisabled)
  778. return -1;
  779. if (queryDaliServerVersion().compare("1.8") < 0) {
  780. securitydisabled = true;
  781. return -1;
  782. }
  783. CMessageBuffer mb;
  784. mb.append((int)MSR_LOOKUP_LDAP_PERMISSIONS);
  785. mb.append(key).append(obj);
  786. #ifdef NULL_DALIUSER_STACKTRACE
  787. //following debug code to be removed
  788. StringBuffer sb;
  789. if (udesc)
  790. udesc->getUserName(sb);
  791. if (0==sb.length())
  792. {
  793. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp getPermissionsLDAP() line %d",__LINE__);
  794. PrintStackReport();
  795. }
  796. #endif
  797. udesc->serialize(mb);
  798. mb.append(auditflags);
  799. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  800. return 0;
  801. int ret=-1;
  802. if (mb.remaining()>=sizeof(ret)) {
  803. mb.read(ret);
  804. if (mb.remaining()>=sizeof(int)) {
  805. int e = 0;
  806. mb.read(e);
  807. if (err)
  808. *err = e;
  809. else if (e)
  810. throw new CDaliLDAP_Exception(e);
  811. }
  812. }
  813. if (ret==-1)
  814. securitydisabled = true;
  815. return ret;
  816. }
  817. bool clearPermissionsCache(IUserDescriptor *udesc)
  818. {
  819. if (securitydisabled)
  820. return true;
  821. if (queryDaliServerVersion().compare("1.8") < 0) {
  822. securitydisabled = true;
  823. return true;
  824. }
  825. CMessageBuffer mb;
  826. mb.append((int)MSR_CLEAR_PERMISSIONS_CACHE);
  827. udesc->serialize(mb);
  828. return queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  829. }
  830. bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)
  831. {
  832. if (queryDaliServerVersion().compare("3.10") < 0)
  833. {
  834. *err = -1;
  835. StringBuffer ver;
  836. queryDaliServerVersion().toString(ver);
  837. retMsg.appendf("Scope Scan status feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
  838. return false;
  839. }
  840. if (securitydisabled)
  841. {
  842. *err = -1;
  843. retMsg.append("Security not enabled");
  844. return false;
  845. }
  846. if (queryDaliServerVersion().compare("1.8") < 0) {
  847. *err = -1;
  848. retMsg.append("Security not enabled");
  849. securitydisabled = true;
  850. return false;
  851. }
  852. CMessageBuffer mb;
  853. CQueryScopeScansEnabledReq req(udesc);
  854. req.serializeReq(mb);
  855. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  856. {
  857. *err = -1;
  858. retMsg.append("DALI Send/Recv error");
  859. return false;
  860. }
  861. int rc;
  862. bool enabled;
  863. mb.read(rc).read(enabled).read(retMsg);
  864. *err = rc;
  865. return enabled;
  866. }
  867. bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)
  868. {
  869. if (queryDaliServerVersion().compare("3.10") < 0)
  870. {
  871. *err = -1;
  872. StringBuffer ver;
  873. queryDaliServerVersion().toString(ver);
  874. retMsg.appendf("Scope Scan enable/disable feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
  875. return false;
  876. }
  877. if (securitydisabled)
  878. {
  879. *err = -1;
  880. retMsg.append("Security not enabled");
  881. return false;
  882. }
  883. if (queryDaliServerVersion().compare("1.8") < 0) {
  884. *err = -1;
  885. retMsg.append("Security not enabled");
  886. securitydisabled = true;
  887. return false;
  888. }
  889. CMessageBuffer mb;
  890. CEnableScopeScansReq req(udesc,enable);
  891. req.serializeReq(mb);
  892. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  893. {
  894. *err = -1;
  895. retMsg.append("DALI Send/Recv error");
  896. return false;
  897. }
  898. int rc;
  899. mb.read(rc).read(retMsg);
  900. *err = rc;
  901. if (rc == 0)
  902. {
  903. StringBuffer user;
  904. udesc->getUserName(user);
  905. DBGLOG("Scope Scans %sabled by %s",enable ? "En" : "Dis", user.str());
  906. }
  907. return rc == 0;
  908. }
  909. bool checkScopeScansLDAP()
  910. {
  911. assertex(!"checkScopeScansLDAP called on client");
  912. return true; // actually only used server size
  913. }
  914. unsigned getLDAPflags()
  915. {
  916. assertex(!"getLdapFlags called on client");
  917. return 0;
  918. }
  919. void setLDAPflags(unsigned)
  920. {
  921. assertex(!"setLdapFlags called on client");
  922. }
  923. bool authorizeConnection(DaliClientRole,bool)
  924. {
  925. return true;
  926. }
  927. SessionId startSession(SecurityToken tok, SessionId parentid)
  928. {
  929. CMessageBuffer mb;
  930. mb.append((int)MSR_REGISTER_SESSION).append(tok).append(parentid);
  931. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  932. return 0;
  933. SessionId ret;
  934. mb.read(ret);
  935. return ret;
  936. }
  937. void stopSession(SessionId sessid, bool failed)
  938. {
  939. if (sessid==SESSID_DALI_SERVER) {
  940. notifyServerStopped(failed);
  941. return;
  942. }
  943. CMessageBuffer mb;
  944. mb.append((int)MSR_STOP_SESSION).append(sessid).append(failed);
  945. queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  946. }
  947. void onClose(SocketEndpoint &ep)
  948. {
  949. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  950. Owned<INode> node = createINode(ep);
  951. if (queryCoven().inCoven(node)) {
  952. StringBuffer str;
  953. PROGLOG("Coven Session Stopping (%s)",ep.getUrlStr(str).str());
  954. if (queryCoven().size()==1)
  955. notifyServerStopped(true);
  956. }
  957. }
  958. void start()
  959. {
  960. addMPConnectionMonitor(this);
  961. }
  962. void stop()
  963. {
  964. }
  965. void ready()
  966. {
  967. removeMPConnectionMonitor(this);
  968. }
  969. StringBuffer &getClientProcessList(StringBuffer &buf)
  970. {
  971. // dummy
  972. return buf;
  973. }
  974. StringBuffer &getClientProcessEndpoint(SessionId,StringBuffer &buf)
  975. {
  976. // dummy
  977. return buf;
  978. }
  979. unsigned queryClientCount()
  980. {
  981. // dummy
  982. return 0;
  983. }
  984. void importCapabilities(MemoryBuffer &mb)
  985. {
  986. CMessageBuffer msg;
  987. msg.append((int)MSR_IMPORT_CAPABILITIES);
  988. msg.append(mb.length(), mb.toByteArray());
  989. queryCoven().sendRecv(msg,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  990. }
  991. };
  992. class CLdapWorkItem : public Thread
  993. {
  994. StringAttr key;
  995. StringAttr obj;
  996. Linked<IUserDescriptor> udesc;
  997. Linked<IDaliLdapConnection> ldapconn;
  998. unsigned flags;
  999. bool running;
  1000. Semaphore contsem;
  1001. Semaphore ready;
  1002. Semaphore &threaddone;
  1003. int ret;
  1004. public:
  1005. IMPLEMENT_IINTERFACE;
  1006. CLdapWorkItem(IDaliLdapConnection *_ldapconn,Semaphore &_threaddone)
  1007. : ldapconn(_ldapconn), threaddone(_threaddone)
  1008. {
  1009. running = false;
  1010. }
  1011. void start(const char *_key,const char *_obj,IUserDescriptor *_udesc,unsigned _flags)
  1012. {
  1013. key.set(_key);
  1014. obj.set(_obj);
  1015. #ifdef NULL_DALIUSER_STACKTRACE
  1016. StringBuffer sb;
  1017. if (_udesc)
  1018. _udesc->getUserName(sb);
  1019. if (sb.length()==0)
  1020. {
  1021. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp CLdapWorkItem::start() line %d",__LINE__);
  1022. PrintStackReport();
  1023. }
  1024. #endif
  1025. udesc.set(_udesc);
  1026. flags = _flags;
  1027. ret = CLDAPE_ldapfailure;
  1028. if (!running) {
  1029. running = true;
  1030. Thread::start();
  1031. }
  1032. contsem.signal();
  1033. }
  1034. int run()
  1035. {
  1036. loop {
  1037. contsem.wait();
  1038. if (!running)
  1039. break;
  1040. try {
  1041. ret = ldapconn->getPermissions(key,obj,udesc,flags);
  1042. }
  1043. catch(IException *e) {
  1044. LOG(MCoperatorError, unknownJob, e, "CLdapWorkItem");
  1045. e->Release();
  1046. }
  1047. ready.signal();
  1048. }
  1049. threaddone.signal();
  1050. return 0;
  1051. }
  1052. bool wait(unsigned timeout, int &_ret)
  1053. {
  1054. if (ready.wait(timeout)) {
  1055. _ret = ret;
  1056. return true;
  1057. }
  1058. _ret = 0;
  1059. return false;
  1060. }
  1061. void stop()
  1062. {
  1063. running = false;
  1064. contsem.signal();
  1065. }
  1066. static CLdapWorkItem *get(IDaliLdapConnection *_ldapconn,Semaphore &_threaddone)
  1067. {
  1068. if (!_threaddone.wait(1000*60*5)) {
  1069. ERRLOG("Too many stalled LDAP threads");
  1070. return NULL;
  1071. }
  1072. return new CLdapWorkItem(_ldapconn,_threaddone);
  1073. }
  1074. };
  1075. class CCovenSessionManager: public CSessionManagerBase, implements ISessionManagerServer, implements ISubscriptionManager
  1076. {
  1077. CSessionRequestServer sessionrequestserver;
  1078. CSessionStateTable sessionstates;
  1079. CMapProcessToSession processlookup;
  1080. Owned<IDaliLdapConnection> ldapconn;
  1081. Owned<CLdapWorkItem> ldapworker;
  1082. Semaphore ldapsig;
  1083. atomic_t ldapwaiting;
  1084. Semaphore workthreadsem;
  1085. bool stopping;
  1086. void remoteAddProcessSession(rank_t dst,SessionId id,INode *node, DaliClientRole role)
  1087. {
  1088. CMessageBuffer mb;
  1089. mb.append((int)MSR_SECONDARY_REGISTER_PROCESS_SESSION).append(id);
  1090. node->serialize(mb);
  1091. int r = (int)role;
  1092. mb.append(role);
  1093. queryCoven().sendRecv(mb,dst,MPTAG_DALI_SESSION_REQUEST);
  1094. // no fail currently
  1095. }
  1096. void remoteAddSession(rank_t dst,SessionId id)
  1097. {
  1098. CMessageBuffer mb;
  1099. mb.append((int)MSR_SECONDARY_REGISTER_SESSION).append(id);
  1100. queryCoven().sendRecv(mb,dst,MPTAG_DALI_SESSION_REQUEST);
  1101. // no fail currently
  1102. }
  1103. public:
  1104. IMPLEMENT_IINTERFACE;
  1105. CCovenSessionManager()
  1106. : sessionrequestserver(*this)
  1107. {
  1108. mySessionId = queryCoven().getUniqueId(); // tell others in coven TBD
  1109. registerSubscriptionManager(SESSION_PUBLISHER,this);
  1110. atomic_set(&ldapwaiting,0);
  1111. workthreadsem.signal(10);
  1112. stopping = false;
  1113. ldapsig.signal();
  1114. }
  1115. ~CCovenSessionManager()
  1116. {
  1117. stubTable.kill();
  1118. }
  1119. void start()
  1120. {
  1121. sessionrequestserver.start();
  1122. }
  1123. void stop()
  1124. {
  1125. stopping = true;
  1126. if (!ldapsig.wait(60*1000))
  1127. WARNLOG("LDAP stalled(1)");
  1128. if (ldapworker) {
  1129. ldapworker->stop();
  1130. if (!ldapworker->join(1000))
  1131. WARNLOG("LDAP stalled(2)");
  1132. ldapworker.clear();
  1133. }
  1134. ldapconn.clear();
  1135. removeMPConnectionMonitor(this);
  1136. sessionrequestserver.stop();
  1137. }
  1138. void ready()
  1139. {
  1140. addMPConnectionMonitor(this);
  1141. sessionrequestserver.ready();
  1142. }
  1143. void setLDAPconnection(IDaliLdapConnection *_ldapconn)
  1144. {
  1145. if (_ldapconn&&(_ldapconn->getLDAPflags()&DLF_ENABLED))
  1146. ldapconn.setown(_ldapconn);
  1147. else {
  1148. ldapconn.clear();
  1149. ::Release(_ldapconn);
  1150. }
  1151. }
  1152. void setClientAuth(IDaliClientAuthConnection *_authconn)
  1153. {
  1154. }
  1155. void addProcessSession(SessionId id,INode *client,DaliClientRole role)
  1156. {
  1157. StringBuffer str;
  1158. PROGLOG("Session starting %"I64F"x (%s) : role=%s",id,client->endpoint().getUrlStr(str).str(),queryRoleName(role));
  1159. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1160. CProcessSessionState *s = new CProcessSessionState(id,client,role);
  1161. while (!sessionstates.add(s)) // takes ownership
  1162. {
  1163. WARNLOG("Dali session manager: session already registered");
  1164. sessionstates.remove(id);
  1165. }
  1166. while (!processlookup.add(s))
  1167. {
  1168. /* There's existing ip:port match (client) in process table..
  1169. * Old may be in process of closing or about to, but new has beaten the onClose() to it..
  1170. * Track old sessions in new CProcessSessionState instance, so that in-process or upcoming onClose()/stopSession() can find them
  1171. */
  1172. CProcessSessionState *previousState = processlookup.query(client);
  1173. dbgassertex(previousState); // Must be there, it's reason add() failed
  1174. SessionId oldSessionId = previousState->getId();
  1175. s->addSessionIds(*previousState, false); // merges sessions from previous process state into new one that replaces it
  1176. WARNLOG("Dali session manager: registerClient process session already registered, old (%"I64F"x) replaced", oldSessionId);
  1177. processlookup.remove(previousState, this);
  1178. }
  1179. }
  1180. void addSession(SessionId id)
  1181. {
  1182. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1183. CSessionState *s = new CSessionState(id);
  1184. while (!sessionstates.add(s)) { // takes ownership
  1185. WARNLOG("Dali session manager: session already registered (2)");
  1186. sessionstates.remove(id);
  1187. }
  1188. }
  1189. SessionId registerSession(SecurityToken, SessionId parent)
  1190. {
  1191. // this is where security token should be checked
  1192. // not in critical block (otherwise possibility of deadlock)
  1193. ICoven &coven=queryCoven();
  1194. SessionId id = coven.getUniqueId();
  1195. rank_t myrank = coven.getServerRank();
  1196. rank_t ownerrank = coven.chooseServer(id);
  1197. // first do local
  1198. if (myrank==ownerrank)
  1199. addSession(id);
  1200. else
  1201. remoteAddSession(ownerrank,id);
  1202. ForEachOtherNodeInGroup(r,coven.queryGroup()) {
  1203. if (r!=ownerrank)
  1204. remoteAddSession(r,id);
  1205. }
  1206. return id;
  1207. }
  1208. SessionId registerClientProcess(INode *client, IGroup *& retcoven, DaliClientRole role)
  1209. {
  1210. // not in critical block (otherwise possibility of deadlock)
  1211. retcoven = NULL;
  1212. ICoven &coven=queryCoven();
  1213. SessionId id = coven.getUniqueId();
  1214. rank_t myrank = coven.getServerRank();
  1215. rank_t ownerrank = coven.chooseServer(id);
  1216. // first do local
  1217. if (myrank==ownerrank)
  1218. addProcessSession(id,client,role);
  1219. else
  1220. remoteAddProcessSession(ownerrank,id,client,role);
  1221. ForEachOtherNodeInGroup(r,coven.queryGroup()) {
  1222. if (r!=ownerrank)
  1223. remoteAddProcessSession(r,id,client,role);
  1224. }
  1225. retcoven = coven.getGroup();
  1226. return id;
  1227. }
  1228. SessionId lookupProcessSession(INode *node)
  1229. {
  1230. if (!node)
  1231. return mySessionId;
  1232. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1233. CProcessSessionState *s= processlookup.query(node);
  1234. return s?s->getId():0;
  1235. }
  1236. INode *getProcessSessionNode(SessionId id)
  1237. {
  1238. StringBuffer eps;
  1239. if (SessionManager->getClientProcessEndpoint(id,eps).length()!=0)
  1240. return createINode(eps.str());
  1241. return NULL;
  1242. }
  1243. virtual int getPermissionsLDAP(const char *key,const char *obj,IUserDescriptor *udesc,unsigned flags, int *err)
  1244. {
  1245. if (err)
  1246. *err = 0;
  1247. if (!ldapconn)
  1248. return -1;
  1249. #ifdef _NO_LDAP
  1250. return -1;
  1251. #else
  1252. #ifdef NULL_DALIUSER_STACKTRACE
  1253. StringBuffer sb;
  1254. if (udesc)
  1255. udesc->getUserName(sb);
  1256. if (sb.length()==0)
  1257. {
  1258. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp CCovenSessionManager::getPermissionsLDAP() line %d",__LINE__);
  1259. PrintStackReport();
  1260. }
  1261. #endif
  1262. if ((ldapconn->getLDAPflags()&(DLF_SAFE|DLF_ENABLED))!=(DLF_SAFE|DLF_ENABLED))
  1263. return ldapconn->getPermissions(key,obj,udesc,flags);
  1264. atomic_inc(&ldapwaiting);
  1265. unsigned retries = 0;
  1266. while (!stopping) {
  1267. if (ldapsig.wait(1000)) {
  1268. atomic_dec(&ldapwaiting);
  1269. if (!ldapworker)
  1270. ldapworker.setown(CLdapWorkItem::get(ldapconn,workthreadsem));
  1271. if (ldapworker) {
  1272. ldapworker->start(key,obj,udesc,flags);
  1273. for (unsigned i=0;i<10;i++) {
  1274. if (i)
  1275. WARNLOG("LDAP stalled(%d) - retrying",i);
  1276. int ret;
  1277. if (ldapworker->wait(1000*20,ret)) {
  1278. if (ret==CLDAPE_ldapfailure) {
  1279. LOG(MCoperatorError, unknownJob, "LDAP - failure (returning no access for %s)",obj);
  1280. ldapsig.signal();
  1281. if (err)
  1282. *err = CLDAPE_ldapfailure;
  1283. return 0;
  1284. }
  1285. else {
  1286. ldapsig.signal();
  1287. return ret;
  1288. }
  1289. }
  1290. if (atomic_read(&ldapwaiting)>10) // give up quicker if piling up
  1291. break;
  1292. if (i==5) { // one retry
  1293. ldapworker->stop(); // abandon thread
  1294. ldapworker.clear();
  1295. ldapworker.setown(CLdapWorkItem::get(ldapconn,workthreadsem));
  1296. if (ldapworker)
  1297. ldapworker->start(key,obj,udesc,flags);
  1298. }
  1299. }
  1300. if (ldapworker)
  1301. ldapworker->stop();
  1302. ldapworker.clear(); // abandon thread
  1303. }
  1304. LOG(MCoperatorError, unknownJob, "LDAP stalled - aborting (returning no access for %s)",obj);
  1305. ldapsig.signal();
  1306. if (err)
  1307. *err = CLDAPE_getpermtimeout;
  1308. return 0;
  1309. }
  1310. else {
  1311. unsigned waiting = atomic_read(&ldapwaiting);
  1312. static unsigned last=0;
  1313. static unsigned lasttick=0;
  1314. static unsigned first50=0;
  1315. if ((waiting!=last)&&(msTick()-lasttick>1000)) {
  1316. WARNLOG("%d threads waiting for ldap",waiting);
  1317. last = waiting;
  1318. lasttick = msTick();
  1319. }
  1320. if (waiting>50) {
  1321. if (first50==0)
  1322. first50 = msTick();
  1323. else if (msTick()-first50>60*1000) {
  1324. LOG(MCoperatorError, unknownJob, "LDAP stalled - aborting (returning 0 for %s)", obj);
  1325. if (err)
  1326. *err = CLDAPE_getpermtimeout;
  1327. break;
  1328. }
  1329. }
  1330. else
  1331. first50 = 0;
  1332. }
  1333. }
  1334. atomic_dec(&ldapwaiting);
  1335. return 0;
  1336. #endif
  1337. }
  1338. virtual bool clearPermissionsCache(IUserDescriptor *udesc)
  1339. {
  1340. #ifdef _NO_LDAP
  1341. bool ok = true;
  1342. #else
  1343. bool ok = true;
  1344. if (ldapconn->getLDAPflags() & DLF_ENABLED)
  1345. ok = ldapconn->clearPermissionsCache(udesc);
  1346. #endif
  1347. return ok;
  1348. }
  1349. virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)
  1350. {
  1351. #ifdef _NO_LDAP
  1352. *err = -1;
  1353. retMsg.append("LDAP not enabled");
  1354. return false;
  1355. #else
  1356. *err = 0;
  1357. return checkScopeScansLDAP();
  1358. #endif
  1359. }
  1360. virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)
  1361. {
  1362. #ifdef _NO_LDAP
  1363. *err = -1;
  1364. retMsg.append("LDAP not supporteded");
  1365. return false;
  1366. #else
  1367. if (!ldapconn)
  1368. {
  1369. *err = -1;
  1370. retMsg.append("LDAP not connected");
  1371. return false;
  1372. }
  1373. return ldapconn->enableScopeScans(udesc, enable, err);
  1374. #endif
  1375. }
  1376. virtual bool checkScopeScansLDAP()
  1377. {
  1378. #ifdef _NO_LDAP
  1379. return false;
  1380. #else
  1381. return ldapconn?ldapconn->checkScopeScans():false;
  1382. #endif
  1383. }
  1384. virtual unsigned getLDAPflags()
  1385. {
  1386. #ifdef _NO_LDAP
  1387. return 0;
  1388. #else
  1389. return ldapconn?ldapconn->getLDAPflags():0;
  1390. #endif
  1391. }
  1392. void setLDAPflags(unsigned flags)
  1393. {
  1394. #ifndef _NO_LDAP
  1395. if (ldapconn)
  1396. ldapconn->setLDAPflags(flags);
  1397. #endif
  1398. }
  1399. bool authorizeConnection(int role,bool revoke)
  1400. {
  1401. return true;
  1402. }
  1403. SessionId startSession(SecurityToken tok, SessionId parentid)
  1404. {
  1405. return registerSession(tok,parentid);
  1406. }
  1407. void setSessionDependancy(SessionId id , SessionId dependsonid )
  1408. {
  1409. UNIMPLEMENTED; // TBD
  1410. }
  1411. void clearSessionDependancy(SessionId id , SessionId dependsonid )
  1412. {
  1413. UNIMPLEMENTED; // TBD
  1414. }
  1415. protected:
  1416. class CSessionSubscriptionStub: public CInterface
  1417. {
  1418. ISubscription *subs;
  1419. SubscriptionId id;
  1420. SessionId sessid;
  1421. public:
  1422. IMPLEMENT_IINTERFACE;
  1423. CSessionSubscriptionStub(ISubscription *_subs,SubscriptionId _id) // takes ownership
  1424. {
  1425. subs = _subs;
  1426. id = _id;
  1427. const MemoryAttr &ma = subs->queryData();
  1428. MemoryBuffer mb(ma.length(),ma.get());
  1429. mb.read(sessid);
  1430. }
  1431. ~CSessionSubscriptionStub()
  1432. {
  1433. subs->Release();
  1434. }
  1435. SubscriptionId getId() { return id; }
  1436. SessionId getSessionId() { return sessid; }
  1437. void notify(bool abort)
  1438. {
  1439. MemoryBuffer mb;
  1440. mb.append(abort);
  1441. subs->notify(mb);
  1442. }
  1443. const void *queryFindParam() const { return &id; }
  1444. };
  1445. OwningSimpleHashTableOf<CSessionSubscriptionStub, SubscriptionId> stubTable;
  1446. void add(ISubscription *subs,SubscriptionId id)
  1447. {
  1448. CSessionSubscriptionStub *nstub;
  1449. {
  1450. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1451. nstub = new CSessionSubscriptionStub(subs,id);
  1452. if (sessionstates.query(nstub->getSessionId())||(nstub->getSessionId()==mySessionId))
  1453. {
  1454. stubTable.replace(*nstub);
  1455. return;
  1456. }
  1457. }
  1458. // see if session known
  1459. MemoryBuffer mb;
  1460. bool abort=true;
  1461. mb.append(abort);
  1462. ERRLOG("Session Manager - adding unknown session ID %"I64F"x", nstub->getSessionId());
  1463. subs->notify(mb);
  1464. delete nstub;
  1465. return;
  1466. }
  1467. void remove(SubscriptionId id)
  1468. {
  1469. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1470. stubTable.remove(&id);
  1471. }
  1472. void stopSession(SessionId id, bool abort)
  1473. {
  1474. PROGLOG("Session stopping %"I64F"x %s",id,abort?"aborted":"ok");
  1475. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1476. // do in multiple stages as may remove one or more sub sessions
  1477. loop
  1478. {
  1479. CIArrayOf<CSessionSubscriptionStub> tonotify;
  1480. SuperHashIteratorOf<CSessionSubscriptionStub> iter(stubTable);
  1481. ForEach(iter)
  1482. {
  1483. CSessionSubscriptionStub &stub = iter.query();
  1484. if (stub.getSessionId()==id)
  1485. tonotify.append(*LINK(&stub));
  1486. }
  1487. if (tonotify.ordinality()==0)
  1488. break;
  1489. ForEachItemIn(j,tonotify)
  1490. {
  1491. CSessionSubscriptionStub &stub = tonotify.item(j);
  1492. stubTable.removeExact(&stub);
  1493. }
  1494. CHECKEDCRITICALUNBLOCK(sessmanagersect,60000);
  1495. ForEachItemIn(j2,tonotify)
  1496. {
  1497. CSessionSubscriptionStub &stub = tonotify.item(j2);
  1498. try { stub.notify(abort); }
  1499. catch (IException *e) { e->Release(); } // subscriber session may abort during stopSession
  1500. }
  1501. tonotify.kill(); // clear whilst sessmanagersect unblocked, as subs may query session manager.
  1502. }
  1503. const CSessionState *state = sessionstates.query(id);
  1504. if (state)
  1505. {
  1506. const CProcessSessionState *pState = QUERYINTERFACE(state, const CProcessSessionState);
  1507. if (pState)
  1508. {
  1509. CProcessSessionState *cState = processlookup.query(&pState->queryNode()); // get current
  1510. if (pState == cState) // so is current one.
  1511. {
  1512. /* This is reinstating a previous CProcessSessionState for this node (if there is one),
  1513. * that has not yet stopped, and adding any other pending process states to the CProcessSessionState
  1514. * being reinstated.
  1515. */
  1516. SessionId prevId = cState->dequeuePreviousSessionId();
  1517. if (prevId)
  1518. {
  1519. PROGLOG("Session (%"I64F"x) in stopSession, detected %d pending previous states, reinstating session (%"I64F"x) as current", id, cState->previousSessionIdCount(), prevId);
  1520. CSessionState *prevSessionState = sessionstates.query(prevId);
  1521. dbgassertex(prevSessionState); // must be there
  1522. CProcessSessionState *prevProcessState = QUERYINTERFACE(prevSessionState, CProcessSessionState);
  1523. dbgassertex(prevProcessState);
  1524. /* NB: prevProcessState's have 0 entries in their previousSessionIds, since they were merged at replacement time
  1525. * in addProcessSession()
  1526. */
  1527. /* add in any remaining to-be-stopped process sessions from current that's stopping into this previous state
  1528. * that's being reinstated, so will be picked up on next onClose()/stopSession()
  1529. */
  1530. prevProcessState->addSessionIds(*cState, true);
  1531. processlookup.replace(prevProcessState);
  1532. }
  1533. else
  1534. processlookup.remove(pState, this);
  1535. }
  1536. else // Here because in stopSession for an previous process state, that has been replaced (in addProcessSession)
  1537. {
  1538. if (processlookup.remove(pState, this))
  1539. {
  1540. // Don't think possible to be here, if not current must have replaced afaics
  1541. PROGLOG("Session (%"I64F"x) in stopSession, old process session removed", id);
  1542. }
  1543. else
  1544. PROGLOG("Session (%"I64F"x) in stopSession, old process session was already removed", id); // because replaced
  1545. if (cState)
  1546. {
  1547. PROGLOG("Session (%"I64F"x) was replaced, ensuring removed from new process state", id);
  1548. cState->removeOldSessionId(id); // If already replaced, then must ensure no longer tracked by new
  1549. }
  1550. }
  1551. }
  1552. sessionstates.remove(id);
  1553. }
  1554. }
  1555. void onClose(SocketEndpoint &ep)
  1556. {
  1557. StringBuffer clientStr;
  1558. PROGLOG("Client closed (%s)", ep.getUrlStr(clientStr).str());
  1559. SessionId idtostop;
  1560. {
  1561. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1562. Owned<INode> node = createINode(ep);
  1563. if (queryCoven().inCoven(node))
  1564. {
  1565. PROGLOG("Coven Session Stopping (%s)", clientStr.str());
  1566. // more TBD here
  1567. return;
  1568. }
  1569. CProcessSessionState *s = processlookup.query(node);
  1570. if (!s)
  1571. return;
  1572. idtostop = s->dequeuePreviousSessionId();
  1573. if (idtostop)
  1574. {
  1575. PROGLOG("Previous sessionId (%"I64F"x) for %s was replaced by (%"I64F"x), stopping old session now", idtostop, clientStr.str(), s->getId());
  1576. unsigned c = s->previousSessionIdCount();
  1577. if (c) // very unlikely, but could be >1, trace for info.
  1578. PROGLOG("%d old sessions pending closure", c);
  1579. }
  1580. else
  1581. idtostop = s->getId();
  1582. }
  1583. stopSession(idtostop,true);
  1584. }
  1585. StringBuffer &getClientProcessList(StringBuffer &buf)
  1586. {
  1587. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1588. unsigned n = processlookup.count();
  1589. CProcessSessionState *s=NULL;
  1590. for (unsigned i=0;i<n;i++) {
  1591. s=processlookup.next(s);
  1592. if (!s)
  1593. break;
  1594. s->getDetails(buf).append('\n');
  1595. }
  1596. return buf;
  1597. }
  1598. StringBuffer &getClientProcessEndpoint(SessionId id,StringBuffer &buf)
  1599. {
  1600. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1601. const CSessionState *state = sessionstates.query(id);
  1602. if (state) {
  1603. const CProcessSessionState *pstate = QUERYINTERFACE(state,const CProcessSessionState);
  1604. if (pstate)
  1605. return pstate->queryNode().endpoint().getUrlStr(buf);
  1606. }
  1607. return buf;
  1608. }
  1609. unsigned queryClientCount()
  1610. {
  1611. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1612. return processlookup.count();
  1613. }
  1614. };
  1615. ISessionManager &querySessionManager()
  1616. {
  1617. CriticalBlock block(sessionCrit);
  1618. if (!SessionManager) {
  1619. assertex(!isCovenActive()||!queryCoven().inCoven()); // Check not Coven server (if occurs - not initialized correctly;
  1620. // If !coven someone is checking for dali so allow
  1621. SessionManager = new CClientSessionManager();
  1622. }
  1623. return *SessionManager;
  1624. }
  1625. class CDaliSessionServer: public CInterface, public IDaliServer
  1626. {
  1627. public:
  1628. IMPLEMENT_IINTERFACE;
  1629. CDaliSessionServer()
  1630. {
  1631. }
  1632. void start()
  1633. {
  1634. CriticalBlock block(sessionCrit);
  1635. assertex(queryCoven().inCoven()); // must be member of coven
  1636. CCovenSessionManager *serv = new CCovenSessionManager();
  1637. SessionManagerServer = serv;
  1638. SessionManager = serv;
  1639. SessionManagerServer->start();
  1640. }
  1641. void suspend()
  1642. {
  1643. }
  1644. void stop()
  1645. {
  1646. CriticalBlock block(sessionCrit);
  1647. SessionManagerServer->stop();
  1648. SessionManagerServer->Release();
  1649. SessionManagerServer = NULL;
  1650. SessionManager = NULL;
  1651. }
  1652. void ready()
  1653. {
  1654. SessionManagerServer->ready();
  1655. }
  1656. void nodeDown(rank_t rank)
  1657. {
  1658. assertex(!"TBD");
  1659. }
  1660. };
  1661. IDaliServer *createDaliSessionServer()
  1662. {
  1663. return new CDaliSessionServer();
  1664. }
  1665. void setLDAPconnection(IDaliLdapConnection *ldapconn)
  1666. {
  1667. if (SessionManagerServer)
  1668. SessionManagerServer->setLDAPconnection(ldapconn);
  1669. }
  1670. void setClientAuth(IDaliClientAuthConnection *authconn)
  1671. {
  1672. if (SessionManagerServer)
  1673. SessionManagerServer->setClientAuth(authconn);
  1674. }
  1675. #define REG_SLEEP 5000
  1676. bool registerClientProcess(ICommunicator *comm, IGroup *& retcoven,unsigned timeout,DaliClientRole role)
  1677. {
  1678. // NB doesn't use coven as not yet set up
  1679. if (comm->queryGroup().ordinality()==0)
  1680. return false;
  1681. CTimeMon tm(timeout);
  1682. retcoven = NULL;
  1683. unsigned nextLog = 0, lastNextLog = 0;
  1684. unsigned t=REG_SLEEP;
  1685. unsigned remaining;
  1686. rank_t r;
  1687. while (!tm.timedout(&remaining)) {
  1688. if (remaining>t)
  1689. remaining = t;
  1690. r = getRandom()%comm->queryGroup().ordinality();
  1691. bool ok = false;
  1692. if (remaining>10000) // MP protocol has a minimum time of 10s so if remaining < 10s use a detachable thread
  1693. ok = comm->verifyConnection(r,remaining);
  1694. else {
  1695. struct cThread: public Thread
  1696. {
  1697. IMPLEMENT_IINTERFACE;
  1698. Semaphore sem;
  1699. Linked<ICommunicator> comm;
  1700. bool ok;
  1701. Owned<IException> exc;
  1702. unsigned remaining;
  1703. rank_t r;
  1704. cThread(ICommunicator *_comm,rank_t _r,unsigned _remaining)
  1705. : Thread ("dasess.registerClientProcess"), comm(_comm)
  1706. {
  1707. r = _r;
  1708. remaining = _remaining;
  1709. ok = false;
  1710. }
  1711. int run()
  1712. {
  1713. try {
  1714. if (comm->verifyConnection(r,remaining))
  1715. ok = true;
  1716. }
  1717. catch (IException *e)
  1718. {
  1719. exc.setown(e);
  1720. }
  1721. sem.signal();
  1722. return 0;
  1723. }
  1724. } *t = new cThread(comm,r,remaining);
  1725. t->start();
  1726. t->sem.wait(remaining);
  1727. ok = t->ok;
  1728. if (t->exc.get()) {
  1729. IException *e = t->exc.getClear();
  1730. t->Release();
  1731. throw e;
  1732. }
  1733. t->Release();
  1734. }
  1735. if (ok) {
  1736. CMessageBuffer mb;
  1737. mb.append((int)MSR_REGISTER_PROCESS_SESSION);
  1738. queryMyNode()->serialize(mb);
  1739. comm->queryGroup().queryNode(r).serialize(mb);
  1740. mb.append((int)role);
  1741. if (comm->sendRecv(mb,r,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT)) {
  1742. if (!mb.length())
  1743. {
  1744. // failed system capability match,
  1745. retcoven = comm->getGroup(); // continue as if - will fail later more obscurely.
  1746. return true;
  1747. }
  1748. mb.read(mySessionId);
  1749. retcoven = deserializeIGroup(mb);
  1750. return true;
  1751. }
  1752. }
  1753. StringBuffer str;
  1754. PROGLOG("Failed to connect to Dali Server %s.", comm->queryGroup().queryNode(r).endpoint().getUrlStr(str).str());
  1755. if (tm.timedout())
  1756. {
  1757. PROGLOG("%s", str.append(" Timed out.").str());
  1758. break;
  1759. }
  1760. else if (0 == nextLog)
  1761. {
  1762. PROGLOG("%s", str.append(" Retrying...").str());
  1763. if ((lastNextLog * REG_SLEEP) >= 60000) // limit to a minute between logging
  1764. nextLog = 60000 / REG_SLEEP;
  1765. else
  1766. nextLog = lastNextLog + 2; // wait +2 REG_SLEEP pauses before next logging
  1767. lastNextLog = nextLog;
  1768. }
  1769. else
  1770. --nextLog;
  1771. Sleep(REG_SLEEP);
  1772. }
  1773. return false;
  1774. }
  1775. extern void stopClientProcess()
  1776. {
  1777. CriticalBlock block(sessionCrit);
  1778. if (mySessionId&&SessionManager) {
  1779. try {
  1780. querySessionManager().stopSession(mySessionId,false);
  1781. }
  1782. catch (IDaliClient_Exception *e) {
  1783. if (e->errorCode()!=DCERR_server_closed)
  1784. throw;
  1785. e->Release();
  1786. }
  1787. mySessionId = 0;
  1788. }
  1789. }
  1790. class CProcessSessionWatchdog
  1791. {
  1792. };
  1793. class CUserDescriptor: public CInterface, implements IUserDescriptor
  1794. {
  1795. StringAttr username;
  1796. StringAttr passwordenc;
  1797. public:
  1798. IMPLEMENT_IINTERFACE;
  1799. StringBuffer &getUserName(StringBuffer &buf)
  1800. {
  1801. return buf.append(username);
  1802. }
  1803. StringBuffer &getPassword(StringBuffer &buf)
  1804. {
  1805. decrypt(buf,passwordenc);
  1806. return buf;
  1807. }
  1808. virtual void set(const char *name,const char *password)
  1809. {
  1810. username.set(name);
  1811. StringBuffer buf;
  1812. encrypt(buf,password);
  1813. passwordenc.set(buf.str());
  1814. }
  1815. virtual void clear()
  1816. {
  1817. username.clear();
  1818. passwordenc.clear();
  1819. }
  1820. void serialize(MemoryBuffer &mb)
  1821. {
  1822. mb.append(username).append(passwordenc);
  1823. }
  1824. void deserialize(MemoryBuffer &mb)
  1825. {
  1826. mb.read(username).read(passwordenc);
  1827. }
  1828. };
  1829. IUserDescriptor *createUserDescriptor()
  1830. {
  1831. return new CUserDescriptor;
  1832. }
  1833. IUserDescriptor *createUserDescriptor(MemoryBuffer &mb)
  1834. {
  1835. IUserDescriptor * udesc = createUserDescriptor();
  1836. udesc->deserialize(mb);
  1837. return udesc;
  1838. }
  1839. MODULE_INIT(INIT_PRIORITY_DALI_DASESS)
  1840. {
  1841. return true;
  1842. }
  1843. MODULE_EXIT()
  1844. {
  1845. ::Release(SessionManager);
  1846. SessionManager = NULL;
  1847. }