caching.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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. #include "caching.hpp"
  14. #include "jtime.hpp"
  15. //define a container for multiple instances of a security manager cache
  16. typedef map<string, CPermissionsCache*> MapCache;
  17. static CriticalSection mapCacheCS;//guards modifications to the cache map
  18. static MapCache g_mapCache;
  19. /**********************************************************
  20. * CResPermissionsCache *
  21. * (used by CPermissionsCache defined below) *
  22. **********************************************************/
  23. time_t getThreadCreateTime()
  24. {
  25. time_t t;
  26. void* tslval = getThreadLocalVal();
  27. if(tslval == NULL)
  28. return 0;
  29. memcpy(&t, tslval, sizeof(t));
  30. return t;
  31. }
  32. CResPermissionsCache::~CResPermissionsCache()
  33. {
  34. MapResAccess::const_iterator i;
  35. MapResAccess::const_iterator iEnd = m_resAccessMap.end();
  36. for (i = m_resAccessMap.begin(); i != iEnd; i++)
  37. {
  38. ISecResource* ptr = ((*i).second).second;
  39. if(ptr)
  40. {
  41. ptr->Release();
  42. }
  43. }
  44. }
  45. int CResPermissionsCache::lookup( IArrayOf<ISecResource>& resources, bool* pFound )
  46. {
  47. time_t tstamp;
  48. time(&tstamp);
  49. int timeout = m_pParentCache->getCacheTimeout();
  50. if(timeout == 0 && m_pParentCache->isTransactionalEnabled())
  51. timeout = 10; //Transactional timeout is set to 10 seconds for long transactions that might take over 10 seconds.
  52. tstamp -= timeout;
  53. if (m_tLastCleanup < tstamp)
  54. removeStaleEntries(tstamp);
  55. int nresources = resources.ordinality();
  56. int nFound = 0;
  57. for (int i = 0; i < nresources; i++)
  58. {
  59. ISecResource& secResource = resources.item(i);
  60. const char* resource = secResource.getName();
  61. if(resource == NULL)
  62. {
  63. *pFound++ = false;
  64. continue;
  65. }
  66. #ifdef _DEBUG
  67. DBGLOG("CACHE: CResPermissionsCache Looking up resource(%d of %d) %s:%s", i, nresources, m_user.c_str(), resource);
  68. #endif
  69. MapResAccess::iterator it = m_resAccessMap.find(SecCacheKeyEntry(resource, secResource.getResourceType()));
  70. if (it != m_resAccessMap.end())//exists in cache
  71. {
  72. ResPermCacheEntry& resParamCacheEntry = (*it).second;
  73. const time_t timestamp = resParamCacheEntry.first;
  74. if (timestamp < tstamp)//entry was not stale during last cleanup but is stale now
  75. *pFound++ = false;
  76. else if(!m_pParentCache->isCacheEnabled() && m_pParentCache->isTransactionalEnabled())//m_pParentCache->getOriginalTimeout() == 0)
  77. {
  78. time_t tctime = getThreadCreateTime();
  79. if(tctime <= 0 || timestamp < tctime)
  80. {
  81. *pFound++ = false;
  82. }
  83. else
  84. {
  85. secResource.copy(resParamCacheEntry.second);
  86. #ifdef _DEBUG
  87. DBGLOG("CACHE: CResPermissionsCache FoundA %s:%s=>%d", m_user.c_str(), resource, ((ISecResource*)resParamCacheEntry.second)->getAccessFlags());
  88. #endif
  89. *pFound++ = true;
  90. nFound++;
  91. }
  92. }
  93. else
  94. {
  95. secResource.copy(resParamCacheEntry.second);
  96. #ifdef _DEBUG
  97. DBGLOG("CACHE: CResPermissionsCache FoundB %s:%s=>%d", m_user.c_str(), resource, ((ISecResource*)resParamCacheEntry.second)->getAccessFlags());
  98. #endif
  99. *pFound++ = true;
  100. nFound++;
  101. }
  102. }
  103. else
  104. *pFound++ = false;
  105. }
  106. return nFound;
  107. }
  108. void CResPermissionsCache::add( IArrayOf<ISecResource>& resources )
  109. {
  110. time_t tstamp;
  111. time(&tstamp);
  112. int nresources = resources.ordinality();
  113. for (int i = 0; i < nresources; i++)
  114. {
  115. ISecResource* secResource = &resources.item(i);
  116. if(!secResource)
  117. continue;
  118. const char* resource = secResource->getName();
  119. SecResourceType resourcetype = secResource->getResourceType();
  120. if(resource == NULL)
  121. continue;
  122. int permissions = secResource->getAccessFlags();
  123. if(permissions == -1)
  124. continue;
  125. MapResAccess::iterator it = m_resAccessMap.find(SecCacheKeyEntry(resource, resourcetype));
  126. if (it != m_resAccessMap.end())//already exists so overwrite it but first remove existing timestamp info
  127. {
  128. ResPermCacheEntry& resParamCacheEntry = (*it).second;
  129. time_t oldtstamp = resParamCacheEntry.first;
  130. //there may be multiple resources associated with the same timestamp
  131. //in the multimap so find this entry
  132. //
  133. MapTimeStamp::iterator itL = m_timestampMap.lower_bound( oldtstamp );
  134. MapTimeStamp::iterator itU = m_timestampMap.upper_bound( oldtstamp );
  135. MapTimeStamp::iterator its;
  136. for ( its = itL; its != itU; its++)
  137. {
  138. SecCacheKeyEntry& cachekey = (*its).second;
  139. if (cachekey.first == resource && cachekey.second == resourcetype)
  140. {
  141. m_timestampMap.erase(its);
  142. break;
  143. }
  144. }
  145. m_resAccessMap.erase(SecCacheKeyEntry(resource, resourcetype));
  146. }
  147. #ifdef _DEBUG
  148. DBGLOG("CACHE: CResPermissionsCache Adding %s:%s(%d)", m_user.c_str(), resource, permissions);
  149. #endif
  150. m_resAccessMap.insert( pair<SecCacheKeyEntry, ResPermCacheEntry>(SecCacheKeyEntry(resource, resourcetype), ResPermCacheEntry(tstamp, secResource->clone())));
  151. m_timestampMap.insert( pair<time_t, SecCacheKeyEntry>(tstamp, SecCacheKeyEntry(resource, resourcetype)));
  152. }
  153. }
  154. void CResPermissionsCache::removeStaleEntries(time_t tstamp)
  155. {
  156. MapTimeStamp::iterator i;
  157. MapTimeStamp::iterator itL = m_timestampMap.lower_bound(tstamp);
  158. MapTimeStamp::iterator iBegin = m_timestampMap.begin();
  159. for (i = iBegin; i != itL; i++)
  160. {
  161. SecCacheKeyEntry& cachekey = (*i).second;
  162. MapResAccess::iterator it = m_resAccessMap.find(cachekey);
  163. if (it != m_resAccessMap.end())//exists in cache
  164. {
  165. ResPermCacheEntry& entry = (*it).second;
  166. if(entry.second)
  167. entry.second->Release();
  168. }
  169. m_resAccessMap.erase(cachekey);
  170. }
  171. m_timestampMap.erase(iBegin, itL);
  172. m_tLastCleanup = tstamp;
  173. }
  174. void CResPermissionsCache::remove(SecResourceType rtype, const char* resourcename)
  175. {
  176. SecCacheKeyEntry key(resourcename, rtype);
  177. MapResAccess::iterator it = m_resAccessMap.find(key);
  178. if (it != m_resAccessMap.end())//exists in cache
  179. {
  180. ResPermCacheEntry& entry = (*it).second;
  181. if(entry.second)
  182. entry.second->Release();
  183. }
  184. m_resAccessMap.erase(key);
  185. }
  186. /**********************************************************
  187. * CPermissionsCache *
  188. **********************************************************/
  189. CPermissionsCache::~CPermissionsCache()
  190. {
  191. if (!m_secMgrClass.isEmpty())
  192. {
  193. CriticalBlock block(mapCacheCS);
  194. g_mapCache.erase(m_secMgrClass.str());
  195. }
  196. flush();
  197. }
  198. int CPermissionsCache::lookup( ISecUser& sec_user, IArrayOf<ISecResource>& resources,
  199. bool* pFound)
  200. {
  201. const char* userId = sec_user.getName();
  202. int nFound;
  203. ReadLockBlock readLock(m_resPermCacheRWLock);
  204. MapResPermissionsCache::const_iterator i = m_resPermissionsMap.find( userId );
  205. if (i != m_resPermissionsMap.end())
  206. {
  207. CResPermissionsCache* pResPermissionsCache = (*i).second;
  208. nFound = pResPermissionsCache->lookup( resources, pFound );
  209. }
  210. else
  211. {
  212. nFound = 0;
  213. memset(pFound, 0, sizeof(bool)*resources.ordinality());
  214. }
  215. #ifdef _DEBUG
  216. DBGLOG("CACHE: CPermissionsCache Looked up resources for %s:*, found %d of %d matches", userId, nFound, resources.ordinality());
  217. #endif
  218. return nFound;
  219. }
  220. void CPermissionsCache::add( ISecUser& sec_user, IArrayOf<ISecResource>& resources )
  221. {
  222. const char* user = sec_user.getName();
  223. WriteLockBlock writeLock(m_resPermCacheRWLock);
  224. MapResPermissionsCache::const_iterator i = m_resPermissionsMap.find( user );
  225. CResPermissionsCache* pResPermissionsCache;
  226. if (i == m_resPermissionsMap.end())
  227. {
  228. #ifdef _DEBUG
  229. DBGLOG("CACHE: CPermissionsCache Adding resources to cache for new user %s", user);
  230. #endif
  231. pResPermissionsCache = new CResPermissionsCache(this, user);
  232. m_resPermissionsMap.insert(pair<string, CResPermissionsCache*>(user, pResPermissionsCache));
  233. }
  234. else
  235. {
  236. #ifdef _DEBUG
  237. DBGLOG("CACHE: CPermissionsCache Adding resources to cache for existing user %s", user);
  238. #endif
  239. pResPermissionsCache = (*i).second;
  240. }
  241. pResPermissionsCache->add( resources );
  242. }
  243. void CPermissionsCache::removePermissions( ISecUser& sec_user)
  244. {
  245. const char* user = sec_user.getName();
  246. if(user != NULL && *user != '\0')
  247. {
  248. #ifdef _DEBUG
  249. DBGLOG("CACHE: CPermissionsCache Removing permissions for user %s", user);
  250. #endif
  251. WriteLockBlock writeLock(m_resPermCacheRWLock);
  252. m_resPermissionsMap.erase(user);
  253. }
  254. }
  255. void CPermissionsCache::remove(SecResourceType rtype, const char* resourcename)
  256. {
  257. MapResPermissionsCache::const_iterator i;
  258. WriteLockBlock writeLock(m_resPermCacheRWLock);
  259. MapResPermissionsCache::const_iterator iEnd = m_resPermissionsMap.end();
  260. for (i = m_resPermissionsMap.begin(); i != iEnd; i++)
  261. {
  262. i->second->remove(rtype, resourcename);
  263. }
  264. }
  265. bool CPermissionsCache::lookup(ISecUser& sec_user)
  266. {
  267. if(!isCacheEnabled())
  268. return false;
  269. const char* username = sec_user.getName();
  270. if(!username || !*username)
  271. return false;
  272. string key(username);
  273. ReadLockBlock readLock(m_userCacheRWLock );
  274. MapUserCache::iterator it = m_userCache.find(key);
  275. if (it == m_userCache.end())
  276. return false;
  277. CachedUser* user = (CachedUser*)(it->second);
  278. time_t now;
  279. time(&now);
  280. if(user->getTimestamp() < (now - m_cacheTimeout))
  281. {
  282. m_userCache.erase(username);
  283. delete user;
  284. return false;
  285. }
  286. const char* cachedpw = user->queryUser()->credentials().getPassword();
  287. StringBuffer pw(sec_user.credentials().getPassword());
  288. if(cachedpw && pw.length() > 0)
  289. {
  290. StringBuffer md5pbuf;
  291. md5_string(pw, md5pbuf);
  292. if(strcmp(cachedpw, md5pbuf.str()) == 0)
  293. {
  294. #ifdef _DEBUG
  295. DBGLOG("CACHE: CPermissionsCache Found validated user %s", username);
  296. #endif
  297. // Copy cached user to the sec_user structure, but still keep the original clear text password.
  298. user->queryUser()->copyTo(sec_user);
  299. sec_user.credentials().setPassword(pw.str());
  300. return true;
  301. }
  302. else
  303. {
  304. m_userCache.erase(username);
  305. delete user;
  306. return false;
  307. }
  308. }
  309. return false;
  310. }
  311. ISecUser* CPermissionsCache::getCachedUser( ISecUser& sec_user)
  312. {
  313. if(!isCacheEnabled())
  314. return NULL;
  315. const char* username = sec_user.getName();
  316. if(!username || !*username)
  317. return NULL;
  318. string key(username);
  319. ReadLockBlock readLock(m_userCacheRWLock );
  320. MapUserCache::iterator it = m_userCache.find(key);
  321. if (it == m_userCache.end())
  322. return NULL;
  323. CachedUser* user = (CachedUser*)(it->second);
  324. return LINK(user->queryUser());
  325. }
  326. void CPermissionsCache::add(ISecUser& sec_user)
  327. {
  328. if(!isCacheEnabled())
  329. return;
  330. const char* username = sec_user.getName();
  331. if(!username || !*username)
  332. return;
  333. string key(username);
  334. WriteLockBlock writeLock(m_userCacheRWLock );
  335. MapUserCache::iterator it = m_userCache.find(key);
  336. CachedUser* user = NULL;
  337. if (it != m_userCache.end())
  338. {
  339. user = (CachedUser*)(it->second);
  340. m_userCache.erase(username);
  341. delete user;
  342. }
  343. #ifdef _DEBUG
  344. DBGLOG("CACHE: CPermissionsCache Adding cached user %s", username);
  345. #endif
  346. m_userCache[username] = new CachedUser(sec_user.clone());
  347. }
  348. void CPermissionsCache::removeFromUserCache(ISecUser& sec_user)
  349. {
  350. const char* username = sec_user.getName();
  351. if(username && *username)
  352. {
  353. string key(username);
  354. WriteLockBlock writeLock(m_userCacheRWLock );
  355. MapUserCache::iterator it = m_userCache.find(key);
  356. if (it != m_userCache.end())
  357. {
  358. CachedUser* user = (CachedUser*)(it->second);
  359. m_userCache.erase(username);
  360. delete user;
  361. #ifdef _DEBUG
  362. DBGLOG("CACHE: CPermissionsCache Removing cached user %s", username);
  363. #endif
  364. }
  365. }
  366. }
  367. bool CPermissionsCache::addManagedFileScopes(IArrayOf<ISecResource>& scopes)
  368. {
  369. WriteLockBlock writeLock(m_scopesRWLock);
  370. ForEachItemIn(x, scopes)
  371. {
  372. ISecResource* scope = &scopes.item(x);
  373. if(!scope)
  374. continue;
  375. const char* cachekey = scope->getName();
  376. if(cachekey == NULL)
  377. continue;
  378. map<string, ISecResource*>::iterator it = m_managedFileScopesMap.find(cachekey);
  379. if (it != m_managedFileScopesMap.end())
  380. {
  381. ISecResource *res = (*it).second;
  382. res->Release();
  383. m_managedFileScopesMap.erase(it);
  384. }
  385. #ifdef _DEBUG
  386. DBGLOG("Caching Managed File Scope %s",cachekey);
  387. #endif
  388. m_managedFileScopesMap.insert( pair<string, ISecResource*>(cachekey, LINK(scope)));
  389. }
  390. return true;
  391. }
  392. inline void CPermissionsCache::removeManagedFileScopes(IArrayOf<ISecResource>& scopes)
  393. {
  394. WriteLockBlock writeLock(m_scopesRWLock);
  395. ForEachItemIn(x, scopes)
  396. {
  397. ISecResource* scope = &scopes.item(x);
  398. if(!scope)
  399. continue;
  400. const char* cachekey = scope->getName();
  401. if(cachekey == NULL)
  402. continue;
  403. map<string, ISecResource*>::iterator it = m_managedFileScopesMap.find(cachekey);
  404. if (it != m_managedFileScopesMap.end())
  405. {
  406. ISecResource *res = (*it).second;
  407. res->Release();
  408. m_managedFileScopesMap.erase(it);
  409. }
  410. }
  411. }
  412. inline void CPermissionsCache::removeAllManagedFileScopes()
  413. {
  414. WriteLockBlock writeLock(m_scopesRWLock);
  415. map<string, ISecResource*>::const_iterator cit;
  416. map<string, ISecResource*>::const_iterator iEnd = m_managedFileScopesMap.end();
  417. for (cit = m_managedFileScopesMap.begin(); cit != iEnd; cit++)
  418. {
  419. ISecResource *res = (*cit).second;
  420. res->Release();
  421. }
  422. m_managedFileScopesMap.clear();
  423. }
  424. /*
  425. if perms set on 'scopeA::scopeB' only and lookup of 'scopeA::scopeB::scopeC::scopeD'
  426. need to lookup:
  427. 'scopeA'
  428. no match=>continue
  429. match=>continue if read permissions (if no read, implies can't "see" child scopes)
  430. 'scopeA::scopeB'
  431. no match=>continue
  432. match=>continue if read permissions (if no read, implies can't "see" child scopes)
  433. etc. Until full scope path checked, or no read permissions hit on ancestor scope.
  434. */
  435. bool CPermissionsCache::queryPermsManagedFileScope(ISecUser& sec_user, const char * fullScope, StringBuffer& managedScope, int * accessFlags)
  436. {
  437. if (!fullScope || !*fullScope)
  438. {
  439. *accessFlags = queryDefaultPermission(sec_user);
  440. return true;
  441. }
  442. time_t now;
  443. time(&now);
  444. if (m_secMgr && (0 == m_lastManagedFileScopesRefresh || m_lastManagedFileScopesRefresh < (now - m_cacheTimeout)))
  445. {
  446. removeAllManagedFileScopes();
  447. IArrayOf<ISecResource> scopes;
  448. aindex_t count = m_secMgr->getManagedFileScopes(scopes);
  449. if (count)
  450. addManagedFileScopes(scopes);
  451. m_defaultPermission = SecAccess_Unknown;//trigger refresh
  452. m_lastManagedFileScopesRefresh = now;
  453. }
  454. if (m_managedFileScopesMap.empty())
  455. {
  456. *accessFlags = queryDefaultPermission(sec_user);
  457. return true;
  458. }
  459. StringArray scopes;
  460. {
  461. StringBuffer scope;
  462. const char * p = fullScope;
  463. while (*p)
  464. {
  465. if (*p == ':')
  466. {
  467. if (*(p+1) != ':')
  468. return false;//Malformed scope string, let LDAP figure it out
  469. scopes.append(scope.str());
  470. scope.append(*(p++));
  471. }
  472. scope.append(*(p++));
  473. }
  474. scopes.append(scope.str());
  475. }
  476. ISecResource *matchedRes = NULL;
  477. ISecResource *res = NULL;
  478. bool isManaged = false;
  479. ReadLockBlock readLock(m_scopesRWLock);
  480. for(unsigned i = 0; i < scopes.length(); i++)
  481. {
  482. const char* scope = scopes.item(i);
  483. map<string, ISecResource*>::const_iterator it = m_managedFileScopesMap.find(scope);
  484. if (it != m_managedFileScopesMap.end())
  485. {
  486. isManaged = true;
  487. res = (*it).second;
  488. res->setResourceType(RT_FILE_SCOPE);
  489. LINK(res);
  490. IArrayOf<ISecResource> secResArr;
  491. secResArr.append(*res);
  492. bool found;
  493. int nFound = lookup(sec_user, secResArr, &found);
  494. if (nFound && found)
  495. {
  496. if (0 == (res->getAccessFlags() & SecAccess_Read))
  497. {
  498. *accessFlags = res->getAccessFlags();
  499. managedScope.append(const_cast<char *>(res->getName()));
  500. #ifdef _DEBUG
  501. DBGLOG("FileScope %s for %s(%s) access denied %d",fullScope, sec_user.getName(), res->getName(), *accessFlags);
  502. #endif
  503. return true;
  504. }
  505. else
  506. matchedRes = res;//allowed at this scope, but must also look at child scopes
  507. }
  508. }
  509. }
  510. bool rc;
  511. if (isManaged)
  512. {
  513. if (matchedRes)
  514. {
  515. *accessFlags = matchedRes->getAccessFlags();
  516. managedScope.append(const_cast<char *>(matchedRes->getName()));
  517. #ifdef _DEBUG
  518. DBGLOG("FileScope %s for %s(%s) access granted %d", fullScope, sec_user.getName(), matchedRes->getName(), *accessFlags);
  519. #endif
  520. rc = true;
  521. }
  522. else
  523. {
  524. managedScope.append(const_cast<char *>(res->getName()));
  525. #ifdef _DEBUG
  526. DBGLOG("FileScope %s for %s(%s) managed but not cached", fullScope, sec_user.getName(), res->getName());
  527. #endif
  528. rc = false;//need to go to LDAP to check
  529. }
  530. }
  531. else
  532. {
  533. *accessFlags = queryDefaultPermission(sec_user);
  534. #ifdef _DEBUG
  535. DBGLOG("FileScope %s for %s not managed, using default %d", fullScope, sec_user.getName(),*accessFlags);
  536. #endif
  537. rc = true;
  538. }
  539. return rc;
  540. }
  541. int CPermissionsCache::queryDefaultPermission(ISecUser& user)
  542. {
  543. if (m_defaultPermission == SecAccess_Unknown)
  544. {
  545. if (m_secMgr)
  546. m_defaultPermission = m_secMgr->queryDefaultPermission(user);
  547. else
  548. m_defaultPermission = SecAccess_None;
  549. }
  550. return m_defaultPermission;
  551. }
  552. void CPermissionsCache::flush()
  553. {
  554. {
  555. WriteLockBlock writeLock(m_resPermCacheRWLock);
  556. MapResPermissionsCache::const_iterator i;
  557. MapResPermissionsCache::const_iterator iEnd = m_resPermissionsMap.end();
  558. for (i = m_resPermissionsMap.begin(); i != iEnd; i++)
  559. delete (*i).second;
  560. m_resPermissionsMap.clear();
  561. }
  562. {
  563. WriteLockBlock writeLock(m_userCacheRWLock );
  564. MapUserCache::const_iterator ui;
  565. MapUserCache::const_iterator uiEnd = m_userCache.end();
  566. for (ui = m_userCache.begin(); ui != uiEnd; ui++)
  567. delete (*ui).second;
  568. m_userCache.clear();
  569. }
  570. m_lastManagedFileScopesRefresh = 0;
  571. m_defaultPermission = SecAccess_Unknown;//trigger refresh
  572. }
  573. CPermissionsCache* CPermissionsCache::getInstance(const char * _secMgrClass)
  574. {
  575. const char * secMgrClass = (_secMgrClass != nullptr && *_secMgrClass) ? _secMgrClass : "genericSecMgrClass";
  576. CriticalBlock block(mapCacheCS);
  577. MapCache::iterator it = g_mapCache.find(secMgrClass);
  578. if (it != g_mapCache.end())//exists in cache
  579. {
  580. LINK((*it).second);
  581. return (*it).second;
  582. }
  583. else
  584. {
  585. CPermissionsCache * instance = new CPermissionsCache(_secMgrClass);
  586. g_mapCache.insert(pair<string, CPermissionsCache*>(secMgrClass, instance));
  587. return instance;
  588. }
  589. }