dasess.cpp 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066
  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 DECL_EXPORT
  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 "seclib.hpp"
  30. #include "dasess.hpp"
  31. #ifdef _MSC_VER
  32. #pragma warning (disable : 4355)
  33. #endif
  34. const char *queryRoleName(DaliClientRole role)
  35. {
  36. switch (role) {
  37. case DCR_Private: return "Private";
  38. case DCR_Diagnostic: return "Diagnostic";
  39. case DCR_ThorSlave: return "ThorSlave";
  40. case DCR_ThorMaster: return "ThorMaster";
  41. case DCR_EclServer: return "EclServer";
  42. case DCR_EclScheduler: return "EclScheduler";
  43. case DCR_EclAgent: return "EclAgent";
  44. case DCR_AgentExec: return "AgentExec";
  45. case DCR_DaliServer:return "DaliServer";
  46. case DCR_SashaServer: return "SashaServer";
  47. case DCR_Util: return "Util";
  48. case DCR_Dfu: return "Dfu";
  49. case DCR_DfuServer: return "DfuServer";
  50. case DCR_EspServer: return "EspServer";
  51. case DCR_WuClient: return "WuClient";
  52. case DCR_Config: return "Config";
  53. case DCR_Scheduler: return "Scheduler";
  54. case DCR_RoxyMaster: return "RoxieMaster";
  55. case DCR_RoxySlave: return "RoxieSlave";
  56. case DCR_BackupGen: return "BackupGen";
  57. case DCR_Other: return "Other";
  58. }
  59. return "Unknown";
  60. }
  61. interface ISessionManagerServer: implements IConnectionMonitor
  62. {
  63. virtual SessionId registerSession(SecurityToken tok,SessionId parentid) = 0;
  64. virtual SessionId registerClientProcess(INode *node,IGroup *&grp, DaliClientRole role) = 0;
  65. virtual void addProcessSession(SessionId id, INode *node, DaliClientRole role) = 0;
  66. virtual void addSession(SessionId id) = 0;
  67. virtual SessionId lookupProcessSession(INode *node) = 0;
  68. virtual INode *getProcessSessionNode(SessionId id) =0;
  69. virtual SecAccessFlags getPermissionsLDAP(const char *key,const char *obj,IUserDescriptor *udesc,unsigned flags, int *err)=0;
  70. virtual bool clearPermissionsCache(IUserDescriptor *udesc) = 0;
  71. virtual void stopSession(SessionId sessid,bool failed) = 0;
  72. virtual void setClientAuth(IDaliClientAuthConnection *authconn) = 0;
  73. virtual void setLDAPconnection(IDaliLdapConnection *_ldapconn) = 0;
  74. virtual bool authorizeConnection(int role,bool revoke) = 0;
  75. virtual void start() = 0;
  76. virtual void ready() = 0;
  77. virtual void stop() = 0;
  78. virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg) = 0;
  79. virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg) = 0;
  80. };
  81. static SessionId mySessionId=0;
  82. static ISessionManager *SessionManager=NULL;
  83. static ISessionManagerServer *SessionManagerServer=NULL;
  84. static CriticalSection sessionCrit;
  85. #define SESSIONREPLYTIMEOUT (3*60*1000)
  86. #define CLDAPE_getpermtimeout (-1)
  87. #define CLDAPE_ldapfailure (-2)
  88. class DECL_EXCEPTION CDaliLDAP_Exception: implements IException, public CInterface
  89. {
  90. int errcode;
  91. public:
  92. CDaliLDAP_Exception(int _errcode)
  93. {
  94. errcode = _errcode;
  95. }
  96. int errorCode() const { return errcode; }
  97. StringBuffer & errorMessage(StringBuffer &str) const
  98. {
  99. if (errcode==0)
  100. return str;
  101. str.appendf("LDAP Exception(%d): ",errcode);
  102. if (errcode==CLDAPE_getpermtimeout)
  103. return str.append("getPermissionsLDAP - timeout to LDAP server");
  104. if (errcode==CLDAPE_ldapfailure)
  105. return str.append("getPermissionsLDAP - LDAP server failure");
  106. return str.append("Unknown Exception");
  107. }
  108. MessageAudience errorAudience() const { return MSGAUD_user; }
  109. IMPLEMENT_IINTERFACE;
  110. };
  111. class CdelayedTerminate: public Thread // slightly obfuscated stop code
  112. {
  113. byte err;
  114. int run()
  115. {
  116. while (getRandom()%711!=0) getRandom(); // look busy
  117. ERRLOG("Server fault %d",(int)err);
  118. while (getRandom()%7!=0) Sleep(1);
  119. exit(0);
  120. }
  121. public:
  122. CdelayedTerminate(byte _err)
  123. {
  124. err = _err;
  125. start();
  126. Release();
  127. Sleep(100);
  128. }
  129. };
  130. class CSessionState: public CInterface
  131. {
  132. protected: friend class CSessionStateTable;
  133. SessionId id;
  134. public:
  135. CSessionState(SessionId _id)
  136. {
  137. id = _id;
  138. }
  139. SessionId getId() const
  140. {
  141. return id;
  142. }
  143. };
  144. class CSessionStateTable: private SuperHashTableOf<CSessionState,SessionId>
  145. {
  146. CheckedCriticalSection sessstatesect;
  147. void onAdd(void *) {}
  148. void onRemove(void *e)
  149. {
  150. CSessionState &elem=*(CSessionState *)e;
  151. elem.Release();
  152. }
  153. unsigned getHashFromElement(const void *e) const
  154. {
  155. const CSessionState &elem=*(const CSessionState *)e;
  156. SessionId id=elem.id;
  157. return low(id)^(unsigned)high(id);
  158. }
  159. unsigned getHashFromFindParam(const void *fp) const
  160. {
  161. SessionId id = *(const SessionId *)fp;
  162. return low(id)^(unsigned)high(id);
  163. }
  164. const void * getFindParam(const void *p) const
  165. {
  166. const CSessionState &elem=*(const CSessionState *)p;
  167. return (void *)&elem.id;
  168. }
  169. bool matchesFindParam(const void * et, const void *fp, unsigned) const
  170. {
  171. return ((CSessionState *)et)->id==*(SessionId *)fp;
  172. }
  173. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(CSessionState,SessionId);
  174. public:
  175. CSessionStateTable()
  176. {
  177. }
  178. ~CSessionStateTable() {
  179. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  180. _releaseAll();
  181. }
  182. bool add(CSessionState *e) // takes ownership
  183. {
  184. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  185. if (SuperHashTableOf<CSessionState,SessionId>::find(&e->id))
  186. return false;
  187. SuperHashTableOf<CSessionState,SessionId>::add(*e);
  188. return true;
  189. }
  190. CSessionState *query(SessionId id)
  191. {
  192. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  193. return SuperHashTableOf<CSessionState,SessionId>::find(&id);
  194. }
  195. void remove(SessionId id)
  196. {
  197. CHECKEDCRITICALBLOCK(sessstatesect,60000);
  198. SuperHashTableOf<CSessionState,SessionId>::remove(&id);
  199. }
  200. };
  201. class CProcessSessionState: public CSessionState
  202. {
  203. INode *node;
  204. DaliClientRole role;
  205. UInt64Array previousSessionIds;
  206. public:
  207. CProcessSessionState(SessionId id,INode *_node,DaliClientRole _role)
  208. : CSessionState(id)
  209. {
  210. node = _node;
  211. node->Link();
  212. role = _role;
  213. }
  214. ~CProcessSessionState()
  215. {
  216. node->Release();
  217. }
  218. INode &queryNode() const
  219. {
  220. return *node;
  221. }
  222. DaliClientRole queryRole() const
  223. {
  224. return role;
  225. }
  226. StringBuffer &getDetails(StringBuffer &buf)
  227. {
  228. StringBuffer ep;
  229. return buf.appendf("%16" I64F "X: %s, role=%s",CSessionState::id,node->endpoint().getUrlStr(ep).str(),queryRoleName(role));
  230. }
  231. void addSessionIds(CProcessSessionState &other, bool prevOnly)
  232. {
  233. loop
  234. {
  235. SessionId id = other.dequeuePreviousSessionId();
  236. if (!id)
  237. break;
  238. previousSessionIds.append(id);
  239. }
  240. if (!prevOnly)
  241. previousSessionIds.append(other.getId());
  242. }
  243. SessionId dequeuePreviousSessionId()
  244. {
  245. if (!previousSessionIds.ordinality())
  246. return 0;
  247. return previousSessionIds.popGet();
  248. }
  249. unsigned previousSessionIdCount() const
  250. {
  251. return previousSessionIds.ordinality();
  252. }
  253. void removeOldSessionId(SessionId id)
  254. {
  255. if (previousSessionIds.zap(id))
  256. PROGLOG("Removed old sessionId (%" I64F "x) from current process state", id);
  257. }
  258. };
  259. class CMapProcessToSession: private SuperHashTableOf<CProcessSessionState,INode>
  260. {
  261. CheckedCriticalSection mapprocesssect;
  262. void onAdd(void *) {}
  263. void onRemove(void *e) {} // do nothing
  264. unsigned getHashFromElement(const void *e) const
  265. {
  266. const CProcessSessionState &elem=*(const CProcessSessionState *)e;
  267. return elem.queryNode().getHash();
  268. }
  269. unsigned getHashFromFindParam(const void *fp) const
  270. {
  271. return ((INode *)fp)->getHash();
  272. }
  273. const void * getFindParam(const void *p) const
  274. {
  275. const CProcessSessionState &elem=*(const CProcessSessionState *)p;
  276. return (void *)&elem.queryNode();
  277. }
  278. bool matchesFindParam(const void * et, const void *fp, unsigned) const
  279. {
  280. return ((CProcessSessionState *)et)->queryNode().equals((INode *)fp);
  281. }
  282. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(CProcessSessionState,INode);
  283. public:
  284. CMapProcessToSession()
  285. {
  286. }
  287. ~CMapProcessToSession()
  288. {
  289. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  290. _releaseAll();
  291. }
  292. bool add(CProcessSessionState *e)
  293. {
  294. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  295. if (SuperHashTableOf<CProcessSessionState,INode>::find(&e->queryNode()))
  296. return false;
  297. SuperHashTableOf<CProcessSessionState,INode>::add(*e);
  298. return true;
  299. }
  300. void replace(CProcessSessionState *e)
  301. {
  302. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  303. SuperHashTableOf<CProcessSessionState,INode>::replace(*e);
  304. }
  305. CProcessSessionState *query(INode *n)
  306. {
  307. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  308. return SuperHashTableOf<CProcessSessionState,INode>::find(n);
  309. }
  310. bool remove(const CProcessSessionState *state, ISessionManagerServer *manager)
  311. {
  312. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  313. if (SuperHashTableOf<CProcessSessionState,INode>::removeExact((CProcessSessionState *)state))
  314. {
  315. if (manager)
  316. manager->authorizeConnection(state->queryRole(), true);
  317. return true;
  318. }
  319. return false;
  320. }
  321. unsigned count()
  322. {
  323. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  324. return SuperHashTableOf<CProcessSessionState,INode>::count();
  325. }
  326. CProcessSessionState *next(const CProcessSessionState *s)
  327. {
  328. CHECKEDCRITICALBLOCK(mapprocesssect,60000);
  329. return (CProcessSessionState *)SuperHashTableOf<CProcessSessionState,INode>::next(s);
  330. }
  331. };
  332. enum MSessionRequestKind {
  333. MSR_REGISTER_PROCESS_SESSION,
  334. MSR_SECONDARY_REGISTER_PROCESS_SESSION,
  335. MSR_REGISTER_SESSION,
  336. MSR_SECONDARY_REGISTER_SESSION,
  337. MSR_LOOKUP_PROCESS_SESSION,
  338. MSR_STOP_SESSION,
  339. MSR_IMPORT_CAPABILITIES,
  340. MSR_LOOKUP_LDAP_PERMISSIONS,
  341. MSR_CLEAR_PERMISSIONS_CACHE,
  342. MSR_EXIT, // TBD
  343. MSR_QUERY_SCOPE_SCANS_ENABLED,
  344. MSR_ENABLE_SCOPE_SCANS
  345. };
  346. class CQueryScopeScansEnabledReq : implements IMessageWrapper
  347. {
  348. public:
  349. bool enabled;
  350. Linked<IUserDescriptor> udesc;
  351. CQueryScopeScansEnabledReq(IUserDescriptor *_udesc) : udesc(_udesc) {}
  352. CQueryScopeScansEnabledReq() {}
  353. void serializeReq(CMessageBuffer &mb)
  354. {
  355. mb.append(MSR_QUERY_SCOPE_SCANS_ENABLED);
  356. udesc->serialize(mb);
  357. }
  358. void deserializeReq(CMessageBuffer &mb)
  359. {
  360. udesc.setown(createUserDescriptor(mb));
  361. }
  362. };
  363. class CEnableScopeScansReq : implements IMessageWrapper
  364. {
  365. public:
  366. bool doEnable;
  367. Linked<IUserDescriptor> udesc;
  368. CEnableScopeScansReq(IUserDescriptor *_udesc, bool _doEnable) : udesc(_udesc), doEnable(_doEnable) {}
  369. CEnableScopeScansReq() {}
  370. void serializeReq(CMessageBuffer &mb)
  371. {
  372. mb.append(MSR_ENABLE_SCOPE_SCANS);
  373. udesc->serialize(mb);
  374. mb.append(doEnable);
  375. }
  376. void deserializeReq(CMessageBuffer &mb)
  377. {
  378. udesc.setown(createUserDescriptor(mb));
  379. mb.read(doEnable);
  380. }
  381. };
  382. class CSessionRequestServer: public Thread
  383. {
  384. bool stopped;
  385. ISessionManagerServer &manager;
  386. Semaphore acceptConnections;
  387. public:
  388. CSessionRequestServer(ISessionManagerServer &_manager)
  389. : Thread("Session Manager, CSessionRequestServer"), manager(_manager)
  390. {
  391. stopped = true;
  392. }
  393. int run()
  394. {
  395. ICoven &coven=queryCoven();
  396. CMessageHandler<CSessionRequestServer> handler("CSessionRequestServer",this,&CSessionRequestServer::processMessage);
  397. stopped = false;
  398. CMessageBuffer mb;
  399. while (!stopped) {
  400. try {
  401. mb.clear();
  402. if (coven.recv(mb,RANK_ALL,MPTAG_DALI_SESSION_REQUEST,NULL))
  403. handler.handleMessage(mb);
  404. else
  405. stopped = true;
  406. }
  407. catch (IException *e)
  408. {
  409. EXCLOG(e, "CDaliPublisherServer");
  410. e->Release();
  411. }
  412. }
  413. return 0;
  414. }
  415. void processMessage(CMessageBuffer &mb)
  416. {
  417. ICoven &coven=queryCoven();
  418. SessionId id;
  419. int fn;
  420. mb.read(fn);
  421. switch (fn) {
  422. case MSR_REGISTER_PROCESS_SESSION: {
  423. acceptConnections.wait();
  424. acceptConnections.signal();
  425. Owned<INode> node(deserializeINode(mb));
  426. Owned<INode> servernode(deserializeINode(mb)); // hopefully me, but not if forwarded
  427. int role=0;
  428. if (mb.length()-mb.getPos()>=sizeof(role)) { // a capability block present
  429. mb.read(role);
  430. if (!manager.authorizeConnection(role,false)) {
  431. SocketEndpoint sender = mb.getSender();
  432. mb.clear();
  433. coven.reply(mb);
  434. MilliSleep(100+getRandom()%1000); // Causes client to 'work' for a short time.
  435. Owned<INode> node = createINode(sender);
  436. coven.disconnect(node);
  437. break;
  438. }
  439. #ifdef _DEBUG
  440. StringBuffer eps;
  441. PROGLOG("Connection to %s authorized",mb.getSender().getUrlStr(eps).str());
  442. #endif
  443. }
  444. IGroup *covengrp;
  445. id = manager.registerClientProcess(node.get(),covengrp,(DaliClientRole)role);
  446. mb.clear().append(id);
  447. if (covengrp->rank(servernode)==RANK_NULL) { // must have been redirected
  448. covengrp->Release(); // no good, so just use one we know about (may use something more sophisticated later)
  449. INode *na = servernode.get();
  450. covengrp = createIGroup(1, &na);
  451. }
  452. covengrp->serialize(mb);
  453. covengrp->Release();
  454. coven.reply(mb);
  455. }
  456. break;
  457. case MSR_SECONDARY_REGISTER_PROCESS_SESSION: {
  458. mb.read(id);
  459. Owned<INode> node (deserializeINode(mb));
  460. int role;
  461. mb.read(role);
  462. manager.addProcessSession(id,node.get(),(DaliClientRole)role);
  463. mb.clear();
  464. coven.reply(mb);
  465. }
  466. break;
  467. case MSR_REGISTER_SESSION: {
  468. SecurityToken tok;
  469. SessionId parentid;
  470. mb.read(tok).read(parentid);
  471. SessionId id = manager.registerSession(tok,parentid);
  472. mb.clear().append(id);
  473. coven.reply(mb);
  474. }
  475. break;
  476. case MSR_SECONDARY_REGISTER_SESSION: {
  477. mb.read(id);
  478. manager.addSession(id);
  479. mb.clear();
  480. coven.reply(mb);
  481. }
  482. break;
  483. case MSR_LOOKUP_PROCESS_SESSION: {
  484. // looks up from node or from id
  485. Owned<INode> node (deserializeINode(mb));
  486. if (node->endpoint().isNull()&&(mb.length()-mb.getPos()>=sizeof(id))) {
  487. mb.read(id);
  488. INode *n = manager.getProcessSessionNode(id);
  489. if (n)
  490. node.setown(n);
  491. node->serialize(mb.clear());
  492. }
  493. else {
  494. id = manager.lookupProcessSession(node.get());
  495. mb.clear().append(id);
  496. }
  497. coven.reply(mb);
  498. }
  499. break;
  500. case MSR_STOP_SESSION: {
  501. SessionId sessid;
  502. bool failed;
  503. mb.read(sessid).read(failed);
  504. manager.stopSession(sessid,failed);
  505. mb.clear();
  506. coven.reply(mb);
  507. }
  508. break;
  509. case MSR_LOOKUP_LDAP_PERMISSIONS: {
  510. StringAttr key;
  511. StringAttr obj;
  512. Owned<IUserDescriptor> udesc=createUserDescriptor();
  513. StringAttr username;
  514. StringAttr passwordenc;
  515. mb.read(key).read(obj);
  516. udesc->deserialize(mb);
  517. #ifdef NULL_DALIUSER_STACKTRACE
  518. //following debug code to be removed
  519. StringBuffer sb;
  520. udesc->getUserName(sb);
  521. if (0==sb.length())
  522. {
  523. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp CSessionRequestServer::processMessage() line %d", __LINE__);
  524. }
  525. #endif
  526. unsigned auditflags = 0;
  527. if (mb.length()-mb.getPos()>=sizeof(auditflags))
  528. mb.read(auditflags);
  529. int err = 0;
  530. SecAccessFlags perms = manager.getPermissionsLDAP(key,obj,udesc,auditflags,&err);
  531. mb.clear().append((int)perms);
  532. if (err)
  533. mb.append(err);
  534. coven.reply(mb);
  535. }
  536. break;
  537. case MSR_CLEAR_PERMISSIONS_CACHE: {
  538. Owned<IUserDescriptor> udesc=createUserDescriptor();
  539. udesc->deserialize(mb);
  540. bool ok = manager.clearPermissionsCache(udesc);
  541. mb.append(ok);
  542. coven.reply(mb);
  543. }
  544. break;
  545. case MSR_QUERY_SCOPE_SCANS_ENABLED:{
  546. CQueryScopeScansEnabledReq req;
  547. req.deserializeReq(mb);
  548. int err;
  549. StringBuffer retMsg;
  550. bool enabled = manager.queryScopeScansEnabled(req.udesc, &err, retMsg);
  551. mb.clear().append(err);
  552. mb.append(enabled);
  553. mb.append(retMsg.str());
  554. if (err != 0 || retMsg.length())
  555. {
  556. StringBuffer user;
  557. req.udesc->getUserName(user);
  558. DBGLOG("Error %d querying scope scan status for %s : %s", err, user.str(), retMsg.str());
  559. }
  560. coven.reply(mb);
  561. }
  562. break;
  563. case MSR_ENABLE_SCOPE_SCANS:{
  564. CEnableScopeScansReq req;
  565. req.deserializeReq(mb);
  566. int err;
  567. StringBuffer retMsg;
  568. bool ok = manager.enableScopeScans(req.udesc, req.doEnable, &err, retMsg);
  569. mb.clear().append(err);
  570. mb.append(retMsg.str());
  571. if (err != 0 || retMsg.length())
  572. {
  573. StringBuffer user;
  574. req.udesc->getUserName(user);
  575. DBGLOG("Error %d %sing Scope Scan Status for %s: %s", err, req.doEnable?"Enabl":"Disabl", user.str(), retMsg.str());
  576. }
  577. coven.reply(mb);
  578. }
  579. break;
  580. }
  581. }
  582. void ready()
  583. {
  584. acceptConnections.signal();
  585. }
  586. void stop()
  587. {
  588. if (!stopped) {
  589. stopped = true;
  590. queryCoven().cancel(RANK_ALL, MPTAG_DALI_SESSION_REQUEST);
  591. }
  592. join();
  593. }
  594. };
  595. class CSessionManagerBase: implements ISessionManager, public CInterface
  596. {
  597. protected:
  598. CheckedCriticalSection sessmanagersect;
  599. public:
  600. IMPLEMENT_IINTERFACE;
  601. CSessionManagerBase()
  602. {
  603. servernotifys.kill();
  604. }
  605. virtual ~CSessionManagerBase()
  606. {
  607. }
  608. class CSessionSubscriptionProxy: implements ISubscription, public CInterface
  609. {
  610. ISessionNotify *sub;
  611. SubscriptionId id;
  612. MemoryAttr ma;
  613. SessionId sessid;
  614. public:
  615. IMPLEMENT_IINTERFACE;
  616. CSessionSubscriptionProxy(ISessionNotify *_sub,SessionId _sessid)
  617. {
  618. sub = LINK(_sub);
  619. sessid = _sessid;
  620. MemoryBuffer mb;
  621. mb.append(sessid);
  622. ma.set(mb.length(),mb.toByteArray());
  623. id = queryCoven().getUniqueId();
  624. }
  625. ~CSessionSubscriptionProxy()
  626. {
  627. sub->Release();
  628. }
  629. ISessionNotify *queryNotify()
  630. {
  631. return sub;
  632. }
  633. const MemoryAttr &queryData()
  634. {
  635. return ma;
  636. }
  637. SubscriptionId getId()
  638. {
  639. return id;
  640. }
  641. void doNotify(bool aborted)
  642. {
  643. if (aborted)
  644. sub->aborted(sessid);
  645. else
  646. sub->closed(sessid);
  647. }
  648. void notify(MemoryBuffer &mb)
  649. {
  650. bool aborted;
  651. mb.read(aborted);
  652. doNotify(aborted);
  653. }
  654. void abort()
  655. {
  656. //NH: TBD
  657. }
  658. bool aborted()
  659. {
  660. return false;
  661. }
  662. };
  663. CIArrayOf<CSessionSubscriptionProxy>servernotifys;
  664. SubscriptionId subscribeSession(SessionId sessid, ISessionNotify *inotify)
  665. {
  666. CSessionSubscriptionProxy *proxy;
  667. SubscriptionId id;
  668. {
  669. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  670. proxy = new CSessionSubscriptionProxy(inotify,sessid);
  671. id = proxy->getId();
  672. if (sessid==SESSID_DALI_SERVER) {
  673. servernotifys.append(*proxy);
  674. return id;
  675. }
  676. }
  677. querySubscriptionManager(SESSION_PUBLISHER)->add(proxy,id);
  678. return id;
  679. }
  680. void unsubscribeSession(SubscriptionId id)
  681. {
  682. {
  683. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  684. // check not a server subscription
  685. ForEachItemIn(i,servernotifys) {
  686. if (servernotifys.item(i).getId()==id) {
  687. servernotifys.remove(i);
  688. return;
  689. }
  690. }
  691. }
  692. querySubscriptionManager(SESSION_PUBLISHER)->remove(id);
  693. }
  694. class cNotify: implements ISessionNotify, public CInterface
  695. {
  696. public:
  697. IMPLEMENT_IINTERFACE;
  698. Semaphore sem;
  699. void closed(SessionId id)
  700. {
  701. //PROGLOG("Session closed %" I64F "x",id);
  702. sem.signal();
  703. }
  704. void aborted(SessionId id)
  705. {
  706. //PROGLOG("Session aborted %" I64F "x",id);
  707. sem.signal();
  708. }
  709. };
  710. bool sessionStopped(SessionId id, unsigned timeout)
  711. {
  712. Owned<INode> node = getProcessSessionNode(id);
  713. if (node.get()==NULL)
  714. return true;
  715. if (timeout==0)
  716. return false;
  717. Owned<cNotify> cnotify = new cNotify;
  718. querySessionManager().subscribeSession(id,cnotify);
  719. if (cnotify->sem.wait(timeout))
  720. return false;
  721. node.setown(getProcessSessionNode(id));
  722. return node.get()==NULL;
  723. }
  724. void notifyServerStopped(bool aborted)
  725. {
  726. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  727. // check not a server subscription
  728. ForEachItemIn(i,servernotifys) {
  729. servernotifys.item(i).doNotify(aborted);
  730. }
  731. }
  732. };
  733. class CClientSessionManager: public CSessionManagerBase, implements IConnectionMonitor
  734. {
  735. bool securitydisabled;
  736. public:
  737. IMPLEMENT_IINTERFACE;
  738. CClientSessionManager()
  739. {
  740. securitydisabled = false;
  741. }
  742. virtual ~CClientSessionManager()
  743. {
  744. stop();
  745. }
  746. SessionId lookupProcessSession(INode *node)
  747. {
  748. if (!node)
  749. return mySessionId;
  750. CMessageBuffer mb;
  751. mb.append((int)MSR_LOOKUP_PROCESS_SESSION);
  752. node->serialize(mb);
  753. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  754. return 0;
  755. SessionId ret;
  756. mb.read(ret);
  757. return ret;
  758. }
  759. virtual INode *getProcessSessionNode(SessionId id)
  760. {
  761. if (!id)
  762. return NULL;
  763. CMessageBuffer mb;
  764. mb.append((int)MSR_LOOKUP_PROCESS_SESSION);
  765. queryNullNode()->serialize(mb);
  766. mb.append(id);
  767. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  768. return NULL;
  769. Owned<INode> node = deserializeINode(mb);
  770. if (node->endpoint().isNull())
  771. return NULL;
  772. return node.getClear();
  773. }
  774. SecAccessFlags getPermissionsLDAP(const char *key,const char *obj,IUserDescriptor *udesc,unsigned auditflags,int *err)
  775. {
  776. if (err)
  777. *err = 0;
  778. if (securitydisabled)
  779. return SecAccess_Unavailable;
  780. if (queryDaliServerVersion().compare("1.8") < 0) {
  781. securitydisabled = true;
  782. return SecAccess_Unavailable;
  783. }
  784. CMessageBuffer mb;
  785. mb.append((int)MSR_LOOKUP_LDAP_PERMISSIONS);
  786. mb.append(key).append(obj);
  787. #ifdef NULL_DALIUSER_STACKTRACE
  788. //following debug code to be removed
  789. StringBuffer sb;
  790. if (udesc)
  791. udesc->getUserName(sb);
  792. if (0==sb.length())
  793. {
  794. DBGLOG("UNEXPECTED USER (NULL) in dasess.cpp getPermissionsLDAP() line %d",__LINE__);
  795. PrintStackReport();
  796. }
  797. #endif
  798. udesc->serialize(mb);
  799. mb.append(auditflags);
  800. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  801. return SecAccess_None;
  802. SecAccessFlags perms = SecAccess_Unavailable;
  803. if (mb.remaining()>=sizeof(perms)) {
  804. mb.read((int &)perms);
  805. if (mb.remaining()>=sizeof(int)) {
  806. int e = 0;
  807. mb.read(e);
  808. if (err)
  809. *err = e;
  810. else if (e)
  811. throw new CDaliLDAP_Exception(e);
  812. }
  813. }
  814. if (perms == SecAccess_Unavailable)
  815. securitydisabled = true;
  816. return perms;
  817. }
  818. bool clearPermissionsCache(IUserDescriptor *udesc)
  819. {
  820. if (securitydisabled)
  821. return true;
  822. if (queryDaliServerVersion().compare("1.8") < 0) {
  823. securitydisabled = true;
  824. return true;
  825. }
  826. CMessageBuffer mb;
  827. mb.append((int)MSR_CLEAR_PERMISSIONS_CACHE);
  828. udesc->serialize(mb);
  829. return queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  830. }
  831. bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)
  832. {
  833. if (queryDaliServerVersion().compare("3.10") < 0)
  834. {
  835. *err = -1;
  836. StringBuffer ver;
  837. queryDaliServerVersion().toString(ver);
  838. retMsg.appendf("Scope Scan status feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
  839. return false;
  840. }
  841. if (securitydisabled)
  842. {
  843. *err = -1;
  844. retMsg.append("Security not enabled");
  845. return false;
  846. }
  847. if (queryDaliServerVersion().compare("1.8") < 0) {
  848. *err = -1;
  849. retMsg.append("Security not enabled");
  850. securitydisabled = true;
  851. return false;
  852. }
  853. CMessageBuffer mb;
  854. CQueryScopeScansEnabledReq req(udesc);
  855. req.serializeReq(mb);
  856. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  857. {
  858. *err = -1;
  859. retMsg.append("DALI Send/Recv error");
  860. return false;
  861. }
  862. int rc;
  863. bool enabled;
  864. mb.read(rc).read(enabled).read(retMsg);
  865. *err = rc;
  866. return enabled;
  867. }
  868. bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)
  869. {
  870. if (queryDaliServerVersion().compare("3.10") < 0)
  871. {
  872. *err = -1;
  873. StringBuffer ver;
  874. queryDaliServerVersion().toString(ver);
  875. retMsg.appendf("Scope Scan enable/disable feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
  876. return false;
  877. }
  878. if (securitydisabled)
  879. {
  880. *err = -1;
  881. retMsg.append("Security not enabled");
  882. return false;
  883. }
  884. if (queryDaliServerVersion().compare("1.8") < 0) {
  885. *err = -1;
  886. retMsg.append("Security not enabled");
  887. securitydisabled = true;
  888. return false;
  889. }
  890. CMessageBuffer mb;
  891. CEnableScopeScansReq req(udesc,enable);
  892. req.serializeReq(mb);
  893. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  894. {
  895. *err = -1;
  896. retMsg.append("DALI Send/Recv error");
  897. return false;
  898. }
  899. int rc;
  900. mb.read(rc).read(retMsg);
  901. *err = rc;
  902. if (rc == 0)
  903. {
  904. StringBuffer user;
  905. udesc->getUserName(user);
  906. DBGLOG("Scope Scans %sabled by %s",enable ? "En" : "Dis", user.str());
  907. }
  908. return rc == 0;
  909. }
  910. bool checkScopeScansLDAP()
  911. {
  912. assertex(!"checkScopeScansLDAP called on client");
  913. return true; // actually only used server size
  914. }
  915. unsigned getLDAPflags()
  916. {
  917. assertex(!"getLdapFlags called on client");
  918. return 0;
  919. }
  920. void setLDAPflags(unsigned)
  921. {
  922. assertex(!"setLdapFlags called on client");
  923. }
  924. bool authorizeConnection(DaliClientRole,bool)
  925. {
  926. return true;
  927. }
  928. SessionId startSession(SecurityToken tok, SessionId parentid)
  929. {
  930. CMessageBuffer mb;
  931. mb.append((int)MSR_REGISTER_SESSION).append(tok).append(parentid);
  932. if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
  933. return 0;
  934. SessionId ret;
  935. mb.read(ret);
  936. return ret;
  937. }
  938. void stopSession(SessionId sessid, bool failed)
  939. {
  940. if (sessid==SESSID_DALI_SERVER) {
  941. notifyServerStopped(failed);
  942. return;
  943. }
  944. CMessageBuffer mb;
  945. mb.append((int)MSR_STOP_SESSION).append(sessid).append(failed);
  946. queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  947. }
  948. void onClose(SocketEndpoint &ep)
  949. {
  950. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  951. Owned<INode> node = createINode(ep);
  952. if (queryCoven().inCoven(node)) {
  953. StringBuffer str;
  954. PROGLOG("Coven Session Stopping (%s)",ep.getUrlStr(str).str());
  955. if (queryCoven().size()==1)
  956. notifyServerStopped(true);
  957. }
  958. }
  959. void start()
  960. {
  961. addMPConnectionMonitor(this);
  962. }
  963. void stop()
  964. {
  965. }
  966. void ready()
  967. {
  968. removeMPConnectionMonitor(this);
  969. }
  970. StringBuffer &getClientProcessList(StringBuffer &buf)
  971. {
  972. // dummy
  973. return buf;
  974. }
  975. StringBuffer &getClientProcessEndpoint(SessionId,StringBuffer &buf)
  976. {
  977. // dummy
  978. return buf;
  979. }
  980. unsigned queryClientCount()
  981. {
  982. // dummy
  983. return 0;
  984. }
  985. void importCapabilities(MemoryBuffer &mb)
  986. {
  987. CMessageBuffer msg;
  988. msg.append((int)MSR_IMPORT_CAPABILITIES);
  989. msg.append(mb.length(), mb.toByteArray());
  990. queryCoven().sendRecv(msg,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
  991. }
  992. };
  993. class CLdapWorkItem : public Thread
  994. {
  995. StringAttr key;
  996. StringAttr obj;
  997. Linked<IUserDescriptor> udesc;
  998. Linked<IDaliLdapConnection> ldapconn;
  999. unsigned flags;
  1000. bool running;
  1001. Semaphore contsem;
  1002. Semaphore ready;
  1003. Semaphore &threaddone;
  1004. int ret;
  1005. public:
  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 SecAccessFlags 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 SecAccess_Unavailable;
  1249. #ifdef _NO_LDAP
  1250. return SecAccess_Unavailable;
  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. SecAccessFlags ret;
  1277. if (ldapworker->wait(1000*20,(int&)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 SecAccess_None;
  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 SecAccess_None;
  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 SecAccess_None;
  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 && 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. CSessionSubscriptionStub(ISubscription *_subs,SubscriptionId _id) // takes ownership
  1423. {
  1424. subs = _subs;
  1425. id = _id;
  1426. const MemoryAttr &ma = subs->queryData();
  1427. MemoryBuffer mb(ma.length(),ma.get());
  1428. mb.read(sessid);
  1429. }
  1430. ~CSessionSubscriptionStub()
  1431. {
  1432. subs->Release();
  1433. }
  1434. SubscriptionId getId() { return id; }
  1435. SessionId getSessionId() { return sessid; }
  1436. void notify(bool abort)
  1437. {
  1438. MemoryBuffer mb;
  1439. mb.append(abort);
  1440. subs->notify(mb);
  1441. }
  1442. const void *queryFindParam() const { return &id; }
  1443. };
  1444. OwningSimpleHashTableOf<CSessionSubscriptionStub, SubscriptionId> stubTable;
  1445. void add(ISubscription *subs,SubscriptionId id)
  1446. {
  1447. CSessionSubscriptionStub *nstub;
  1448. {
  1449. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1450. nstub = new CSessionSubscriptionStub(subs,id);
  1451. if (sessionstates.query(nstub->getSessionId())||(nstub->getSessionId()==mySessionId))
  1452. {
  1453. stubTable.replace(*nstub);
  1454. return;
  1455. }
  1456. }
  1457. // see if session known
  1458. MemoryBuffer mb;
  1459. bool abort=true;
  1460. mb.append(abort);
  1461. ERRLOG("Session Manager - adding unknown session ID %" I64F "x", nstub->getSessionId());
  1462. subs->notify(mb);
  1463. delete nstub;
  1464. return;
  1465. }
  1466. void remove(SubscriptionId id)
  1467. {
  1468. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1469. stubTable.remove(&id);
  1470. }
  1471. void stopSession(SessionId id, bool abort)
  1472. {
  1473. PROGLOG("Session stopping %" I64F "x %s",id,abort?"aborted":"ok");
  1474. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1475. // do in multiple stages as may remove one or more sub sessions
  1476. loop
  1477. {
  1478. CIArrayOf<CSessionSubscriptionStub> tonotify;
  1479. SuperHashIteratorOf<CSessionSubscriptionStub> iter(stubTable);
  1480. ForEach(iter)
  1481. {
  1482. CSessionSubscriptionStub &stub = iter.query();
  1483. if (stub.getSessionId()==id)
  1484. tonotify.append(*LINK(&stub));
  1485. }
  1486. if (tonotify.ordinality()==0)
  1487. break;
  1488. ForEachItemIn(j,tonotify)
  1489. {
  1490. CSessionSubscriptionStub &stub = tonotify.item(j);
  1491. stubTable.removeExact(&stub);
  1492. }
  1493. CHECKEDCRITICALUNBLOCK(sessmanagersect,60000);
  1494. ForEachItemIn(j2,tonotify)
  1495. {
  1496. CSessionSubscriptionStub &stub = tonotify.item(j2);
  1497. try { stub.notify(abort); }
  1498. catch (IException *e) { e->Release(); } // subscriber session may abort during stopSession
  1499. }
  1500. tonotify.kill(); // clear whilst sessmanagersect unblocked, as subs may query session manager.
  1501. }
  1502. const CSessionState *state = sessionstates.query(id);
  1503. if (state)
  1504. {
  1505. const CProcessSessionState *pState = QUERYINTERFACE(state, const CProcessSessionState);
  1506. if (pState)
  1507. {
  1508. CProcessSessionState *cState = processlookup.query(&pState->queryNode()); // get current
  1509. if (pState == cState) // so is current one.
  1510. {
  1511. /* This is reinstating a previous CProcessSessionState for this node (if there is one),
  1512. * that has not yet stopped, and adding any other pending process states to the CProcessSessionState
  1513. * being reinstated.
  1514. */
  1515. SessionId prevId = cState->dequeuePreviousSessionId();
  1516. if (prevId)
  1517. {
  1518. PROGLOG("Session (%" I64F "x) in stopSession, detected %d pending previous states, reinstating session (%" I64F "x) as current", id, cState->previousSessionIdCount(), prevId);
  1519. CSessionState *prevSessionState = sessionstates.query(prevId);
  1520. dbgassertex(prevSessionState); // must be there
  1521. CProcessSessionState *prevProcessState = QUERYINTERFACE(prevSessionState, CProcessSessionState);
  1522. dbgassertex(prevProcessState);
  1523. /* NB: prevProcessState's have 0 entries in their previousSessionIds, since they were merged at replacement time
  1524. * in addProcessSession()
  1525. */
  1526. /* add in any remaining to-be-stopped process sessions from current that's stopping into this previous state
  1527. * that's being reinstated, so will be picked up on next onClose()/stopSession()
  1528. */
  1529. prevProcessState->addSessionIds(*cState, true);
  1530. processlookup.replace(prevProcessState);
  1531. }
  1532. else
  1533. processlookup.remove(pState, this);
  1534. }
  1535. else // Here because in stopSession for an previous process state, that has been replaced (in addProcessSession)
  1536. {
  1537. if (processlookup.remove(pState, this))
  1538. {
  1539. // Don't think possible to be here, if not current must have replaced afaics
  1540. PROGLOG("Session (%" I64F "x) in stopSession, old process session removed", id);
  1541. }
  1542. else
  1543. PROGLOG("Session (%" I64F "x) in stopSession, old process session was already removed", id); // because replaced
  1544. if (cState)
  1545. {
  1546. PROGLOG("Session (%" I64F "x) was replaced, ensuring removed from new process state", id);
  1547. cState->removeOldSessionId(id); // If already replaced, then must ensure no longer tracked by new
  1548. }
  1549. }
  1550. }
  1551. sessionstates.remove(id);
  1552. }
  1553. }
  1554. void onClose(SocketEndpoint &ep)
  1555. {
  1556. StringBuffer clientStr;
  1557. PROGLOG("Client closed (%s)", ep.getUrlStr(clientStr).str());
  1558. SessionId idtostop;
  1559. {
  1560. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1561. Owned<INode> node = createINode(ep);
  1562. if (queryCoven().inCoven(node))
  1563. {
  1564. PROGLOG("Coven Session Stopping (%s)", clientStr.str());
  1565. // more TBD here
  1566. return;
  1567. }
  1568. CProcessSessionState *s = processlookup.query(node);
  1569. if (!s)
  1570. return;
  1571. idtostop = s->dequeuePreviousSessionId();
  1572. if (idtostop)
  1573. {
  1574. PROGLOG("Previous sessionId (%" I64F "x) for %s was replaced by (%" I64F "x), stopping old session now", idtostop, clientStr.str(), s->getId());
  1575. unsigned c = s->previousSessionIdCount();
  1576. if (c) // very unlikely, but could be >1, trace for info.
  1577. PROGLOG("%d old sessions pending closure", c);
  1578. }
  1579. else
  1580. idtostop = s->getId();
  1581. }
  1582. stopSession(idtostop,true);
  1583. }
  1584. StringBuffer &getClientProcessList(StringBuffer &buf)
  1585. {
  1586. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1587. unsigned n = processlookup.count();
  1588. CProcessSessionState *s=NULL;
  1589. for (unsigned i=0;i<n;i++) {
  1590. s=processlookup.next(s);
  1591. if (!s)
  1592. break;
  1593. s->getDetails(buf).append('\n');
  1594. }
  1595. return buf;
  1596. }
  1597. StringBuffer &getClientProcessEndpoint(SessionId id,StringBuffer &buf)
  1598. {
  1599. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1600. const CSessionState *state = sessionstates.query(id);
  1601. if (state) {
  1602. const CProcessSessionState *pstate = QUERYINTERFACE(state,const CProcessSessionState);
  1603. if (pstate)
  1604. return pstate->queryNode().endpoint().getUrlStr(buf);
  1605. }
  1606. return buf;
  1607. }
  1608. unsigned queryClientCount()
  1609. {
  1610. CHECKEDCRITICALBLOCK(sessmanagersect,60000);
  1611. return processlookup.count();
  1612. }
  1613. };
  1614. ISessionManager &querySessionManager()
  1615. {
  1616. CriticalBlock block(sessionCrit);
  1617. if (!SessionManager) {
  1618. assertex(!isCovenActive()||!queryCoven().inCoven()); // Check not Coven server (if occurs - not initialized correctly;
  1619. // If !coven someone is checking for dali so allow
  1620. SessionManager = new CClientSessionManager();
  1621. }
  1622. return *SessionManager;
  1623. }
  1624. class CDaliSessionServer: public IDaliServer, public CInterface
  1625. {
  1626. public:
  1627. IMPLEMENT_IINTERFACE;
  1628. CDaliSessionServer()
  1629. {
  1630. }
  1631. void start()
  1632. {
  1633. CriticalBlock block(sessionCrit);
  1634. assertex(queryCoven().inCoven()); // must be member of coven
  1635. CCovenSessionManager *serv = new CCovenSessionManager();
  1636. SessionManagerServer = serv;
  1637. SessionManager = serv;
  1638. SessionManagerServer->start();
  1639. }
  1640. void suspend()
  1641. {
  1642. }
  1643. void stop()
  1644. {
  1645. CriticalBlock block(sessionCrit);
  1646. SessionManagerServer->stop();
  1647. SessionManagerServer->Release();
  1648. SessionManagerServer = NULL;
  1649. SessionManager = NULL;
  1650. }
  1651. void ready()
  1652. {
  1653. SessionManagerServer->ready();
  1654. }
  1655. void nodeDown(rank_t rank)
  1656. {
  1657. assertex(!"TBD");
  1658. }
  1659. };
  1660. IDaliServer *createDaliSessionServer()
  1661. {
  1662. return new CDaliSessionServer();
  1663. }
  1664. void setLDAPconnection(IDaliLdapConnection *ldapconn)
  1665. {
  1666. if (SessionManagerServer)
  1667. SessionManagerServer->setLDAPconnection(ldapconn);
  1668. }
  1669. void setClientAuth(IDaliClientAuthConnection *authconn)
  1670. {
  1671. if (SessionManagerServer)
  1672. SessionManagerServer->setClientAuth(authconn);
  1673. }
  1674. #define REG_SLEEP 5000
  1675. bool registerClientProcess(ICommunicator *comm, IGroup *& retcoven,unsigned timeout,DaliClientRole role)
  1676. {
  1677. // NB doesn't use coven as not yet set up
  1678. if (comm->queryGroup().ordinality()==0)
  1679. return false;
  1680. CTimeMon tm(timeout);
  1681. retcoven = NULL;
  1682. unsigned nextLog = 0, lastNextLog = 0;
  1683. unsigned t=REG_SLEEP;
  1684. unsigned remaining;
  1685. rank_t r;
  1686. while (!tm.timedout(&remaining)) {
  1687. if (remaining>t)
  1688. remaining = t;
  1689. r = getRandom()%comm->queryGroup().ordinality();
  1690. bool ok = false;
  1691. if (remaining>10000) // MP protocol has a minimum time of 10s so if remaining < 10s use a detachable thread
  1692. ok = comm->verifyConnection(r,remaining);
  1693. else {
  1694. struct cThread: public Thread
  1695. {
  1696. Semaphore sem;
  1697. Linked<ICommunicator> comm;
  1698. bool ok;
  1699. Owned<IException> exc;
  1700. unsigned remaining;
  1701. rank_t r;
  1702. cThread(ICommunicator *_comm,rank_t _r,unsigned _remaining)
  1703. : Thread ("dasess.registerClientProcess"), comm(_comm)
  1704. {
  1705. r = _r;
  1706. remaining = _remaining;
  1707. ok = false;
  1708. }
  1709. int run()
  1710. {
  1711. try {
  1712. if (comm->verifyConnection(r,remaining))
  1713. ok = true;
  1714. }
  1715. catch (IException *e)
  1716. {
  1717. exc.setown(e);
  1718. }
  1719. sem.signal();
  1720. return 0;
  1721. }
  1722. } *t = new cThread(comm,r,remaining);
  1723. t->start();
  1724. t->sem.wait(remaining);
  1725. ok = t->ok;
  1726. if (t->exc.get()) {
  1727. IException *e = t->exc.getClear();
  1728. t->Release();
  1729. throw e;
  1730. }
  1731. t->Release();
  1732. }
  1733. if (ok) {
  1734. CMessageBuffer mb;
  1735. mb.append((int)MSR_REGISTER_PROCESS_SESSION);
  1736. queryMyNode()->serialize(mb);
  1737. comm->queryGroup().queryNode(r).serialize(mb);
  1738. mb.append((int)role);
  1739. if (comm->sendRecv(mb,r,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT)) {
  1740. if (!mb.length())
  1741. {
  1742. // failed system capability match,
  1743. retcoven = comm->getGroup(); // continue as if - will fail later more obscurely.
  1744. return true;
  1745. }
  1746. mb.read(mySessionId);
  1747. retcoven = deserializeIGroup(mb);
  1748. return true;
  1749. }
  1750. }
  1751. StringBuffer str;
  1752. PROGLOG("Failed to connect to Dali Server %s.", comm->queryGroup().queryNode(r).endpoint().getUrlStr(str).str());
  1753. if (tm.timedout())
  1754. {
  1755. PROGLOG("%s", str.append(" Timed out.").str());
  1756. break;
  1757. }
  1758. else if (0 == nextLog)
  1759. {
  1760. PROGLOG("%s", str.append(" Retrying...").str());
  1761. if ((lastNextLog * REG_SLEEP) >= 60000) // limit to a minute between logging
  1762. nextLog = 60000 / REG_SLEEP;
  1763. else
  1764. nextLog = lastNextLog + 2; // wait +2 REG_SLEEP pauses before next logging
  1765. lastNextLog = nextLog;
  1766. }
  1767. else
  1768. --nextLog;
  1769. Sleep(REG_SLEEP);
  1770. }
  1771. return false;
  1772. }
  1773. extern void stopClientProcess()
  1774. {
  1775. CriticalBlock block(sessionCrit);
  1776. if (mySessionId&&SessionManager) {
  1777. try {
  1778. querySessionManager().stopSession(mySessionId,false);
  1779. }
  1780. catch (IDaliClient_Exception *e) {
  1781. if (e->errorCode()!=DCERR_server_closed)
  1782. throw;
  1783. e->Release();
  1784. }
  1785. mySessionId = 0;
  1786. }
  1787. }
  1788. class CProcessSessionWatchdog
  1789. {
  1790. };
  1791. class CUserDescriptor: implements IUserDescriptor, public CInterface
  1792. {
  1793. StringAttr username;
  1794. StringAttr passwordenc;
  1795. public:
  1796. IMPLEMENT_IINTERFACE;
  1797. StringBuffer &getUserName(StringBuffer &buf)
  1798. {
  1799. return buf.append(username);
  1800. }
  1801. StringBuffer &getPassword(StringBuffer &buf)
  1802. {
  1803. decrypt(buf,passwordenc);
  1804. return buf;
  1805. }
  1806. virtual void set(const char *name,const char *password)
  1807. {
  1808. username.set(name);
  1809. StringBuffer buf;
  1810. encrypt(buf,password);
  1811. passwordenc.set(buf.str());
  1812. }
  1813. virtual void clear()
  1814. {
  1815. username.clear();
  1816. passwordenc.clear();
  1817. }
  1818. void serialize(MemoryBuffer &mb)
  1819. {
  1820. mb.append(username).append(passwordenc);
  1821. }
  1822. void deserialize(MemoryBuffer &mb)
  1823. {
  1824. mb.read(username).read(passwordenc);
  1825. }
  1826. };
  1827. IUserDescriptor *createUserDescriptor()
  1828. {
  1829. return new CUserDescriptor;
  1830. }
  1831. IUserDescriptor *createUserDescriptor(MemoryBuffer &mb)
  1832. {
  1833. IUserDescriptor * udesc = createUserDescriptor();
  1834. udesc->deserialize(mb);
  1835. return udesc;
  1836. }
  1837. MODULE_INIT(INIT_PRIORITY_DALI_DASESS)
  1838. {
  1839. return true;
  1840. }
  1841. MODULE_EXIT()
  1842. {
  1843. ::Release(SessionManager);
  1844. SessionManager = NULL;
  1845. }