caching.cpp 24 KB

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