caching.cpp 24 KB

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